\r
PCI Root Bridge Io Protocol code.\r
\r
-Copyright (c) 1999 - 2016, 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) 1999 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
\r
#define NO_MAPPING (VOID *) (UINTN) -1\r
\r
+#define RESOURCE_VALID(Resource) ((Resource)->Base <= (Resource)->Limit)\r
+\r
//\r
// Lookup table for increment values based on transfer widths\r
//\r
-UINT8 mInStride[] = {\r
+UINT8 mInStride[] = {\r
1, // EfiPciWidthUint8\r
2, // EfiPciWidthUint16\r
4, // EfiPciWidthUint32\r
//\r
// Lookup table for increment values based on transfer widths\r
//\r
-UINT8 mOutStride[] = {\r
+UINT8 mOutStride[] = {\r
1, // EfiPciWidthUint8\r
2, // EfiPciWidthUint16\r
4, // EfiPciWidthUint32\r
Construct the Pci Root Bridge instance.\r
\r
@param Bridge The root bridge instance.\r
- @param HostBridgeHandle Handle to the HostBridge.\r
\r
@return The pointer to PCI_ROOT_BRIDGE_INSTANCE just created\r
or NULL if creation fails.\r
**/\r
PCI_ROOT_BRIDGE_INSTANCE *\r
CreateRootBridge (\r
- IN PCI_ROOT_BRIDGE *Bridge,\r
- IN EFI_HANDLE HostBridgeHandle\r
+ IN PCI_ROOT_BRIDGE *Bridge\r
)\r
{\r
- PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
- PCI_RESOURCE_TYPE Index;\r
- CHAR16 *DevicePathStr;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ PCI_RESOURCE_TYPE Index;\r
+ CHAR16 *DevicePathStr;\r
+ PCI_ROOT_BRIDGE_APERTURE *Aperture;\r
\r
DevicePathStr = NULL;\r
\r
- DEBUG ((EFI_D_INFO, "RootBridge: "));\r
- DEBUG ((EFI_D_INFO, "%s\n", DevicePathStr = ConvertDevicePathToText (Bridge->DevicePath, FALSE, FALSE)));\r
- DEBUG ((EFI_D_INFO, " Support/Attr: %lx / %lx\n", Bridge->Supports, Bridge->Attributes));\r
- DEBUG ((EFI_D_INFO, " DmaAbove4G: %s\n", Bridge->DmaAbove4G ? L"Yes" : L"No"));\r
- DEBUG ((EFI_D_INFO, " AllocAttr: %lx (%s%s)\n", Bridge->AllocationAttributes,\r
- (Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0 ? L"CombineMemPMem " : L"",\r
- (Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) != 0 ? L"Mem64Decode" : L""\r
- ));\r
- DEBUG ((EFI_D_INFO, " Bus: %lx - %lx\n", Bridge->Bus.Base, Bridge->Bus.Limit));\r
- DEBUG ((EFI_D_INFO, " Io: %lx - %lx\n", Bridge->Io.Base, Bridge->Io.Limit));\r
- DEBUG ((EFI_D_INFO, " Mem: %lx - %lx\n", Bridge->Mem.Base, Bridge->Mem.Limit));\r
- DEBUG ((EFI_D_INFO, " MemAbove4G: %lx - %lx\n", Bridge->MemAbove4G.Base, Bridge->MemAbove4G.Limit));\r
- DEBUG ((EFI_D_INFO, " PMem: %lx - %lx\n", Bridge->PMem.Base, Bridge->PMem.Limit));\r
- DEBUG ((EFI_D_INFO, " PMemAbove4G: %lx - %lx\n", Bridge->PMemAbove4G.Base, Bridge->PMemAbove4G.Limit));\r
+ DEBUG ((DEBUG_INFO, "RootBridge: "));\r
+ DEBUG ((DEBUG_INFO, "%s\n", DevicePathStr = ConvertDevicePathToText (Bridge->DevicePath, FALSE, FALSE)));\r
+ DEBUG ((DEBUG_INFO, " Support/Attr: %lx / %lx\n", Bridge->Supports, Bridge->Attributes));\r
+ DEBUG ((DEBUG_INFO, " DmaAbove4G: %s\n", Bridge->DmaAbove4G ? L"Yes" : L"No"));\r
+ DEBUG ((DEBUG_INFO, "NoExtConfSpace: %s\n", Bridge->NoExtendedConfigSpace ? L"Yes" : L"No"));\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ " AllocAttr: %lx (%s%s)\n",\r
+ Bridge->AllocationAttributes,\r
+ (Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0 ? L"CombineMemPMem " : L"",\r
+ (Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) != 0 ? L"Mem64Decode" : L""\r
+ ));\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ " Bus: %lx - %lx Translation=%lx\n",\r
+ Bridge->Bus.Base,\r
+ Bridge->Bus.Limit,\r
+ Bridge->Bus.Translation\r
+ ));\r
+ //\r
+ // Translation for bus is not supported.\r
+ //\r
+ ASSERT (Bridge->Bus.Translation == 0);\r
+ if (Bridge->Bus.Translation != 0) {\r
+ return NULL;\r
+ }\r
+\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ " Io: %lx - %lx Translation=%lx\n",\r
+ Bridge->Io.Base,\r
+ Bridge->Io.Limit,\r
+ Bridge->Io.Translation\r
+ ));\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ " Mem: %lx - %lx Translation=%lx\n",\r
+ Bridge->Mem.Base,\r
+ Bridge->Mem.Limit,\r
+ Bridge->Mem.Translation\r
+ ));\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ " MemAbove4G: %lx - %lx Translation=%lx\n",\r
+ Bridge->MemAbove4G.Base,\r
+ Bridge->MemAbove4G.Limit,\r
+ Bridge->MemAbove4G.Translation\r
+ ));\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ " PMem: %lx - %lx Translation=%lx\n",\r
+ Bridge->PMem.Base,\r
+ Bridge->PMem.Limit,\r
+ Bridge->PMem.Translation\r
+ ));\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ " PMemAbove4G: %lx - %lx Translation=%lx\n",\r
+ Bridge->PMemAbove4G.Base,\r
+ Bridge->PMemAbove4G.Limit,\r
+ Bridge->PMemAbove4G.Translation\r
+ ));\r
\r
//\r
// Make sure Mem and MemAbove4G apertures are valid\r
//\r
- if (Bridge->Mem.Base < Bridge->Mem.Limit) {\r
+ if (RESOURCE_VALID (&Bridge->Mem)) {\r
ASSERT (Bridge->Mem.Limit < SIZE_4GB);\r
if (Bridge->Mem.Limit >= SIZE_4GB) {\r
return NULL;\r
}\r
}\r
- if (Bridge->MemAbove4G.Base < Bridge->MemAbove4G.Limit) {\r
+\r
+ if (RESOURCE_VALID (&Bridge->MemAbove4G)) {\r
ASSERT (Bridge->MemAbove4G.Base >= SIZE_4GB);\r
if (Bridge->MemAbove4G.Base < SIZE_4GB) {\r
return NULL;\r
}\r
}\r
- if (Bridge->PMem.Base < Bridge->PMem.Limit) {\r
+\r
+ if (RESOURCE_VALID (&Bridge->PMem)) {\r
ASSERT (Bridge->PMem.Limit < SIZE_4GB);\r
if (Bridge->PMem.Limit >= SIZE_4GB) {\r
return NULL;\r
}\r
}\r
- if (Bridge->PMemAbove4G.Base < Bridge->PMemAbove4G.Limit) {\r
+\r
+ if (RESOURCE_VALID (&Bridge->PMemAbove4G)) {\r
ASSERT (Bridge->PMemAbove4G.Base >= SIZE_4GB);\r
if (Bridge->PMemAbove4G.Base < SIZE_4GB) {\r
return NULL;\r
}\r
}\r
\r
- if ((Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) {\r
- //\r
- // If this bit is set, then the PCI Root Bridge does not\r
- // support separate windows for Non-prefetchable and Prefetchable\r
- // memory.\r
- //\r
- ASSERT (Bridge->PMem.Base >= Bridge->PMem.Limit);\r
- ASSERT (Bridge->PMemAbove4G.Base >= Bridge->PMemAbove4G.Limit);\r
- if ((Bridge->PMem.Base < Bridge->PMem.Limit) ||\r
- (Bridge->PMemAbove4G.Base < Bridge->PMemAbove4G.Limit)\r
- ) {\r
- return NULL;\r
+ //\r
+ // Ignore AllocationAttributes when resources were already assigned.\r
+ //\r
+ if (!Bridge->ResourceAssigned) {\r
+ if ((Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) {\r
+ //\r
+ // If this bit is set, then the PCI Root Bridge does not\r
+ // support separate windows for Non-prefetchable and Prefetchable\r
+ // memory.\r
+ //\r
+ ASSERT (!RESOURCE_VALID (&Bridge->PMem));\r
+ ASSERT (!RESOURCE_VALID (&Bridge->PMemAbove4G));\r
+ if (RESOURCE_VALID (&Bridge->PMem) || RESOURCE_VALID (&Bridge->PMemAbove4G)) {\r
+ return NULL;\r
+ }\r
}\r
- }\r
\r
- if ((Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) == 0) {\r
- //\r
- // If this bit is not set, then the PCI Root Bridge does not support\r
- // 64 bit memory windows.\r
- //\r
- ASSERT (Bridge->MemAbove4G.Base >= Bridge->MemAbove4G.Limit);\r
- ASSERT (Bridge->PMemAbove4G.Base >= Bridge->PMemAbove4G.Limit);\r
- if ((Bridge->MemAbove4G.Base < Bridge->MemAbove4G.Limit) ||\r
- (Bridge->PMemAbove4G.Base < Bridge->PMemAbove4G.Limit)\r
- ) {\r
- return NULL;\r
+ if ((Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) == 0) {\r
+ //\r
+ // If this bit is not set, then the PCI Root Bridge does not support\r
+ // 64 bit memory windows.\r
+ //\r
+ ASSERT (!RESOURCE_VALID (&Bridge->MemAbove4G));\r
+ ASSERT (!RESOURCE_VALID (&Bridge->PMemAbove4G));\r
+ if (RESOURCE_VALID (&Bridge->MemAbove4G) || RESOURCE_VALID (&Bridge->PMemAbove4G)) {\r
+ return NULL;\r
+ }\r
}\r
}\r
\r
RootBridge = AllocateZeroPool (sizeof (PCI_ROOT_BRIDGE_INSTANCE));\r
ASSERT (RootBridge != NULL);\r
\r
- RootBridge->Signature = PCI_ROOT_BRIDGE_SIGNATURE;\r
- RootBridge->Supports = Bridge->Supports;\r
- RootBridge->Attributes = Bridge->Attributes;\r
- RootBridge->DmaAbove4G = Bridge->DmaAbove4G;\r
- RootBridge->AllocationAttributes = Bridge->AllocationAttributes;\r
- RootBridge->DevicePath = DuplicateDevicePath (Bridge->DevicePath);\r
- RootBridge->DevicePathStr = DevicePathStr;\r
- RootBridge->ConfigBuffer = AllocatePool (\r
- TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)\r
- );\r
+ RootBridge->Signature = PCI_ROOT_BRIDGE_SIGNATURE;\r
+ RootBridge->Supports = Bridge->Supports;\r
+ RootBridge->Attributes = Bridge->Attributes;\r
+ RootBridge->DmaAbove4G = Bridge->DmaAbove4G;\r
+ RootBridge->NoExtendedConfigSpace = Bridge->NoExtendedConfigSpace;\r
+ RootBridge->AllocationAttributes = Bridge->AllocationAttributes;\r
+ RootBridge->DevicePath = DuplicateDevicePath (Bridge->DevicePath);\r
+ RootBridge->DevicePathStr = DevicePathStr;\r
+ RootBridge->ConfigBuffer = AllocatePool (\r
+ TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)\r
+ );\r
ASSERT (RootBridge->ConfigBuffer != NULL);\r
InitializeListHead (&RootBridge->Maps);\r
\r
CopyMem (&RootBridge->Io, &Bridge->Io, sizeof (PCI_ROOT_BRIDGE_APERTURE));\r
CopyMem (&RootBridge->Mem, &Bridge->Mem, sizeof (PCI_ROOT_BRIDGE_APERTURE));\r
CopyMem (&RootBridge->MemAbove4G, &Bridge->MemAbove4G, sizeof (PCI_ROOT_BRIDGE_APERTURE));\r
-\r
+ CopyMem (&RootBridge->PMem, &Bridge->PMem, sizeof (PCI_ROOT_BRIDGE_APERTURE));\r
+ CopyMem (&RootBridge->PMemAbove4G, &Bridge->PMemAbove4G, sizeof (PCI_ROOT_BRIDGE_APERTURE));\r
\r
for (Index = TypeIo; Index < TypeMax; Index++) {\r
- RootBridge->ResAllocNode[Index].Type = Index;\r
- RootBridge->ResAllocNode[Index].Base = 0;\r
- RootBridge->ResAllocNode[Index].Length = 0;\r
- RootBridge->ResAllocNode[Index].Status = ResNone;\r
+ switch (Index) {\r
+ case TypeBus:\r
+ Aperture = &RootBridge->Bus;\r
+ break;\r
+ case TypeIo:\r
+ Aperture = &RootBridge->Io;\r
+ break;\r
+ case TypeMem32:\r
+ Aperture = &RootBridge->Mem;\r
+ break;\r
+ case TypeMem64:\r
+ Aperture = &RootBridge->MemAbove4G;\r
+ break;\r
+ case TypePMem32:\r
+ Aperture = &RootBridge->PMem;\r
+ break;\r
+ case TypePMem64:\r
+ Aperture = &RootBridge->PMemAbove4G;\r
+ break;\r
+ default:\r
+ ASSERT (FALSE);\r
+ Aperture = NULL;\r
+ break;\r
+ }\r
+\r
+ RootBridge->ResAllocNode[Index].Type = Index;\r
+ if (Bridge->ResourceAssigned && (Aperture->Limit >= Aperture->Base)) {\r
+ //\r
+ // Base in ResAllocNode is a host address, while Base in Aperture is a\r
+ // device address.\r
+ //\r
+ RootBridge->ResAllocNode[Index].Base = TO_HOST_ADDRESS (\r
+ Aperture->Base,\r
+ Aperture->Translation\r
+ );\r
+ RootBridge->ResAllocNode[Index].Length = Aperture->Limit - Aperture->Base + 1;\r
+ RootBridge->ResAllocNode[Index].Status = ResAllocated;\r
+ } else {\r
+ RootBridge->ResAllocNode[Index].Base = 0;\r
+ RootBridge->ResAllocNode[Index].Length = 0;\r
+ RootBridge->ResAllocNode[Index].Status = ResNone;\r
+ }\r
}\r
\r
RootBridge->RootBridgeIo.SegmentNumber = Bridge->Segment;\r
- RootBridge->RootBridgeIo.ParentHandle = HostBridgeHandle;\r
RootBridge->RootBridgeIo.PollMem = RootBridgeIoPollMem;\r
RootBridge->RootBridgeIo.PollIo = RootBridgeIoPollIo;\r
RootBridge->RootBridgeIo.Mem.Read = RootBridgeIoMemRead;\r
\r
@retval EFI_INVALID_PARAMETER Buffer is NULL.\r
\r
+ @retval EFI_INVALID_PARAMETER Address or Count is invalid.\r
+\r
@retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.\r
\r
@retval EFI_UNSUPPORTED The address range specified by Address, Width,\r
UINT64 Base;\r
UINT64 Limit;\r
UINT32 Size;\r
+ UINT64 Length;\r
\r
//\r
// Check to see if Buffer is NULL\r
//\r
// Check to see if Width is in the valid range\r
//\r
- if ((UINT32) Width >= EfiPciWidthMaximum) {\r
+ if ((UINT32)Width >= EfiPciWidthMaximum) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
//\r
- // For FIFO type, the target address won't increase during the access,\r
+ // For FIFO type, the device address won't increase during the access,\r
// so treat Count as 1\r
//\r
- if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {\r
+ if ((Width >= EfiPciWidthFifoUint8) && (Width <= EfiPciWidthFifoUint64)) {\r
Count = 1;\r
}\r
\r
- Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
+ Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)(Width & 0x03);\r
Size = 1 << Width;\r
\r
+ //\r
+ // Make sure (Count * Size) doesn't exceed MAX_UINT64\r
+ //\r
+ if (Count > DivU64x32 (MAX_UINT64, Size)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
//\r
// Check to see if Address is aligned\r
//\r
return EFI_UNSUPPORTED;\r
}\r
\r
+ //\r
+ // Make sure (Address + Count * Size) doesn't exceed MAX_UINT64\r
+ //\r
+ Length = MultU64x32 (Count, Size);\r
+ if (Address > MAX_UINT64 - Length) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
\r
//\r
//\r
// Allow Legacy IO access\r
//\r
- if (Address + MultU64x32 (Count, Size) <= 0x1000) {\r
+ if (Address + Length <= 0x1000) {\r
if ((RootBridge->Attributes & (\r
- EFI_PCI_ATTRIBUTE_ISA_IO | EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO | EFI_PCI_ATTRIBUTE_VGA_IO |\r
- EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO |\r
- EFI_PCI_ATTRIBUTE_ISA_IO_16 | EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 | EFI_PCI_ATTRIBUTE_VGA_IO_16)) != 0) {\r
+ EFI_PCI_ATTRIBUTE_ISA_IO | EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO | EFI_PCI_ATTRIBUTE_VGA_IO |\r
+ EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO |\r
+ EFI_PCI_ATTRIBUTE_ISA_IO_16 | EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 | EFI_PCI_ATTRIBUTE_VGA_IO_16)) != 0)\r
+ {\r
return EFI_SUCCESS;\r
}\r
}\r
- Base = RootBridge->Io.Base;\r
+\r
+ Base = RootBridge->Io.Base;\r
Limit = RootBridge->Io.Limit;\r
} else if (OperationType == MemOperation) {\r
//\r
// Allow Legacy MMIO access\r
//\r
- if ((Address >= 0xA0000) && (Address + MultU64x32 (Count, Size)) <= 0xC0000) {\r
+ if ((Address >= 0xA0000) && ((Address + Length) <= 0xC0000)) {\r
if ((RootBridge->Attributes & EFI_PCI_ATTRIBUTE_VGA_MEMORY) != 0) {\r
return EFI_SUCCESS;\r
}\r
}\r
+\r
//\r
// By comparing the Address against Limit we know which range to be used\r
// for checking\r
//\r
- if (Address + MultU64x32 (Count, Size) <= RootBridge->Mem.Limit + 1) {\r
- Base = RootBridge->Mem.Base;\r
+ if ((Address >= RootBridge->Mem.Base) && (Address + Length <= RootBridge->Mem.Limit + 1)) {\r
+ Base = RootBridge->Mem.Base;\r
Limit = RootBridge->Mem.Limit;\r
- } else {\r
- Base = RootBridge->MemAbove4G.Base;\r
+ } else if ((Address >= RootBridge->PMem.Base) && (Address + Length <= RootBridge->PMem.Limit + 1)) {\r
+ Base = RootBridge->PMem.Base;\r
+ Limit = RootBridge->PMem.Limit;\r
+ } else if ((Address >= RootBridge->MemAbove4G.Base) && (Address + Length <= RootBridge->MemAbove4G.Limit + 1)) {\r
+ Base = RootBridge->MemAbove4G.Base;\r
Limit = RootBridge->MemAbove4G.Limit;\r
+ } else {\r
+ Base = RootBridge->PMemAbove4G.Base;\r
+ Limit = RootBridge->PMemAbove4G.Limit;\r
}\r
} else {\r
- PciRbAddr = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &Address;\r
- if (PciRbAddr->Bus < RootBridge->Bus.Base ||\r
- PciRbAddr->Bus > RootBridge->Bus.Limit) {\r
+ PciRbAddr = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *)&Address;\r
+ if ((PciRbAddr->Bus < RootBridge->Bus.Base) ||\r
+ (PciRbAddr->Bus > RootBridge->Bus.Limit))\r
+ {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- if (PciRbAddr->Device > PCI_MAX_DEVICE ||\r
- PciRbAddr->Function > PCI_MAX_FUNC) {\r
+ if ((PciRbAddr->Device > PCI_MAX_DEVICE) ||\r
+ (PciRbAddr->Function > PCI_MAX_FUNC))\r
+ {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
} else {\r
Address = PciRbAddr->Register;\r
}\r
- Base = 0;\r
- Limit = 0xFFF;\r
+\r
+ Base = 0;\r
+ Limit = RootBridge->NoExtendedConfigSpace ? 0xFF : 0xFFF;\r
}\r
\r
if (Address < Base) {\r
- return EFI_INVALID_PARAMETER;\r
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
- if (Address + MultU64x32 (Count, Size) > Limit + 1) {\r
+ if (Address + Length > Limit + 1) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Use address to match apertures of memory type and then get the corresponding\r
+ translation.\r
+\r
+ @param RootBridge The root bridge instance.\r
+ @param Address The address used to match aperture.\r
+ @param Translation Pointer containing the output translation.\r
+\r
+ @return EFI_SUCCESS Get translation successfully.\r
+ @return EFI_INVALID_PARAMETER No matched memory aperture; the input Address\r
+ must be invalid.\r
+**/\r
+EFI_STATUS\r
+RootBridgeIoGetMemTranslationByAddress (\r
+ IN PCI_ROOT_BRIDGE_INSTANCE *RootBridge,\r
+ IN UINT64 Address,\r
+ IN OUT UINT64 *Translation\r
+ )\r
+{\r
+ if ((Address >= RootBridge->Mem.Base) && (Address <= RootBridge->Mem.Limit)) {\r
+ *Translation = RootBridge->Mem.Translation;\r
+ } else if ((Address >= RootBridge->PMem.Base) && (Address <= RootBridge->PMem.Limit)) {\r
+ *Translation = RootBridge->PMem.Translation;\r
+ } else if ((Address >= RootBridge->MemAbove4G.Base) && (Address <= RootBridge->MemAbove4G.Limit)) {\r
+ *Translation = RootBridge->MemAbove4G.Translation;\r
+ } else if ((Address >= RootBridge->PMemAbove4G.Base) && (Address <= RootBridge->PMemAbove4G.Limit)) {\r
+ *Translation = RootBridge->PMemAbove4G.Translation;\r
+ } else {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Return the result of (Multiplicand * Multiplier / Divisor).\r
+\r
+ @param Multiplicand A 64-bit unsigned value.\r
+ @param Multiplier A 64-bit unsigned value.\r
+ @param Divisor A 32-bit unsigned value.\r
+ @param Remainder A pointer to a 32-bit unsigned value. This parameter is\r
+ optional and may be NULL.\r
+\r
+ @return Multiplicand * Multiplier / Divisor.\r
+**/\r
+UINT64\r
+MultThenDivU64x64x32 (\r
+ IN UINT64 Multiplicand,\r
+ IN UINT64 Multiplier,\r
+ IN UINT32 Divisor,\r
+ OUT UINT32 *Remainder OPTIONAL\r
+ )\r
+{\r
+ UINT64 Uint64;\r
+ UINT32 LocalRemainder;\r
+ UINT32 Uint32;\r
+\r
+ if (Multiplicand > DivU64x64Remainder (MAX_UINT64, Multiplier, NULL)) {\r
+ //\r
+ // Make sure Multiplicand is the bigger one.\r
+ //\r
+ if (Multiplicand < Multiplier) {\r
+ Uint64 = Multiplicand;\r
+ Multiplicand = Multiplier;\r
+ Multiplier = Uint64;\r
+ }\r
+\r
+ //\r
+ // Because Multiplicand * Multiplier overflows,\r
+ // Multiplicand * Multiplier / Divisor\r
+ // = (2 * Multiplicand' + 1) * Multiplier / Divisor\r
+ // = 2 * (Multiplicand' * Multiplier / Divisor) + Multiplier / Divisor\r
+ //\r
+ Uint64 = MultThenDivU64x64x32 (RShiftU64 (Multiplicand, 1), Multiplier, Divisor, &LocalRemainder);\r
+ Uint64 = LShiftU64 (Uint64, 1);\r
+ Uint32 = 0;\r
+ if ((Multiplicand & 0x1) == 1) {\r
+ Uint64 += DivU64x32Remainder (Multiplier, Divisor, &Uint32);\r
+ }\r
+\r
+ return Uint64 + DivU64x32Remainder (Uint32 + LShiftU64 (LocalRemainder, 1), Divisor, Remainder);\r
+ } else {\r
+ return DivU64x32Remainder (MultU64x64 (Multiplicand, Multiplier), Divisor, Remainder);\r
+ }\r
+}\r
+\r
+/**\r
+ Return the elapsed tick count from CurrentTick.\r
+\r
+ @param CurrentTick On input, the previous tick count.\r
+ On output, the current tick count.\r
+ @param StartTick The value the performance counter starts with when it\r
+ rolls over.\r
+ @param EndTick The value that the performance counter ends with before\r
+ it rolls over.\r
+\r
+ @return The elapsed tick count from CurrentTick.\r
+**/\r
+UINT64\r
+GetElapsedTick (\r
+ UINT64 *CurrentTick,\r
+ UINT64 StartTick,\r
+ UINT64 EndTick\r
+ )\r
+{\r
+ UINT64 PreviousTick;\r
+\r
+ PreviousTick = *CurrentTick;\r
+ *CurrentTick = GetPerformanceCounter ();\r
+ if (StartTick < EndTick) {\r
+ return *CurrentTick - PreviousTick;\r
+ } else {\r
+ return PreviousTick - *CurrentTick;\r
+ }\r
+}\r
+\r
/**\r
Polls an address in memory mapped I/O space until an exit condition is met,\r
or a timeout occurs.\r
EFI_STATUS Status;\r
UINT64 NumberOfTicks;\r
UINT32 Remainder;\r
+ UINT64 StartTick;\r
+ UINT64 EndTick;\r
+ UINT64 CurrentTick;\r
+ UINT64 ElapsedTick;\r
+ UINT64 Frequency;\r
\r
if (Result == NULL) {\r
return EFI_INVALID_PARAMETER;\r
\r
if (Delay == 0) {\r
return EFI_SUCCESS;\r
-\r
} else {\r
-\r
- //\r
- // Determine the proper # of metronome ticks to wait for polling the\r
- // location. The nuber of ticks is Roundup (Delay /\r
- // mMetronome->TickPeriod)+1\r
- // The "+1" to account for the possibility of the first tick being short\r
- // because we started in the middle of a tick.\r
//\r
- // BugBug: overriding mMetronome->TickPeriod with UINT32 until Metronome\r
- // protocol definition is updated.\r
+ // NumberOfTicks = Frenquency * Delay / EFI_TIMER_PERIOD_SECONDS(1)\r
//\r
- NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) mMetronome->TickPeriod,\r
- &Remainder);\r
- if (Remainder != 0) {\r
- NumberOfTicks += 1;\r
+ Frequency = GetPerformanceCounterProperties (&StartTick, &EndTick);\r
+ NumberOfTicks = MultThenDivU64x64x32 (Frequency, Delay, (UINT32)EFI_TIMER_PERIOD_SECONDS (1), &Remainder);\r
+ if (Remainder >= (UINTN)EFI_TIMER_PERIOD_SECONDS (1) / 2) {\r
+ NumberOfTicks++;\r
}\r
- NumberOfTicks += 1;\r
-\r
- while (NumberOfTicks != 0) {\r
-\r
- mMetronome->WaitForTick (mMetronome, 1);\r
\r
+ for ( ElapsedTick = 0, CurrentTick = GetPerformanceCounter ()\r
+ ; ElapsedTick <= NumberOfTicks\r
+ ; ElapsedTick += GetElapsedTick (&CurrentTick, StartTick, EndTick)\r
+ )\r
+ {\r
Status = This->Mem.Read (This, Width, Address, 1, Result);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
if ((*Result & Mask) == Value) {\r
return EFI_SUCCESS;\r
}\r
-\r
- NumberOfTicks -= 1;\r
}\r
}\r
+\r
return EFI_TIMEOUT;\r
}\r
\r
EFI_STATUS Status;\r
UINT64 NumberOfTicks;\r
UINT32 Remainder;\r
+ UINT64 StartTick;\r
+ UINT64 EndTick;\r
+ UINT64 CurrentTick;\r
+ UINT64 ElapsedTick;\r
+ UINT64 Frequency;\r
\r
//\r
// No matter what, always do a single poll.\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
+\r
if ((*Result & Mask) == Value) {\r
return EFI_SUCCESS;\r
}\r
\r
if (Delay == 0) {\r
return EFI_SUCCESS;\r
-\r
} else {\r
-\r
//\r
- // Determine the proper # of metronome ticks to wait for polling the\r
- // location. The number of ticks is Roundup (Delay /\r
- // mMetronome->TickPeriod)+1\r
- // The "+1" to account for the possibility of the first tick being short\r
- // because we started in the middle of a tick.\r
+ // NumberOfTicks = Frenquency * Delay / EFI_TIMER_PERIOD_SECONDS(1)\r
//\r
- NumberOfTicks = DivU64x32Remainder (Delay, (UINT32)mMetronome->TickPeriod,\r
- &Remainder);\r
- if (Remainder != 0) {\r
- NumberOfTicks += 1;\r
+ Frequency = GetPerformanceCounterProperties (&StartTick, &EndTick);\r
+ NumberOfTicks = MultThenDivU64x64x32 (Frequency, Delay, (UINT32)EFI_TIMER_PERIOD_SECONDS (1), &Remainder);\r
+ if (Remainder >= (UINTN)EFI_TIMER_PERIOD_SECONDS (1) / 2) {\r
+ NumberOfTicks++;\r
}\r
- NumberOfTicks += 1;\r
-\r
- while (NumberOfTicks != 0) {\r
-\r
- mMetronome->WaitForTick (mMetronome, 1);\r
\r
+ for ( ElapsedTick = 0, CurrentTick = GetPerformanceCounter ()\r
+ ; ElapsedTick <= NumberOfTicks\r
+ ; ElapsedTick += GetElapsedTick (&CurrentTick, StartTick, EndTick)\r
+ )\r
+ {\r
Status = This->Io.Read (This, Width, Address, 1, Result);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
if ((*Result & Mask) == Value) {\r
return EFI_SUCCESS;\r
}\r
-\r
- NumberOfTicks -= 1;\r
}\r
}\r
+\r
return EFI_TIMEOUT;\r
}\r
\r
OUT VOID *Buffer\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ UINT64 Translation;\r
\r
- Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address,\r
- Count, Buffer);\r
+ Status = RootBridgeIoCheckParameter (\r
+ This,\r
+ MemOperation,\r
+ Width,\r
+ Address,\r
+ Count,\r
+ Buffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
+ Status = RootBridgeIoGetMemTranslationByAddress (RootBridge, Address, &Translation);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
- return mCpuIo->Mem.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);\r
+\r
+ // Address passed to CpuIo->Mem.Read needs to be a host address instead of\r
+ // device address.\r
+ return mCpuIo->Mem.Read (\r
+ mCpuIo,\r
+ (EFI_CPU_IO_PROTOCOL_WIDTH)Width,\r
+ TO_HOST_ADDRESS (Address, Translation),\r
+ Count,\r
+ Buffer\r
+ );\r
}\r
\r
/**\r
IN VOID *Buffer\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ UINT64 Translation;\r
\r
- Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address,\r
- Count, Buffer);\r
+ Status = RootBridgeIoCheckParameter (\r
+ This,\r
+ MemOperation,\r
+ Width,\r
+ Address,\r
+ Count,\r
+ Buffer\r
+ );\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
- return mCpuIo->Mem.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);\r
+\r
+ RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
+ Status = RootBridgeIoGetMemTranslationByAddress (RootBridge, Address, &Translation);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ // Address passed to CpuIo->Mem.Write needs to be a host address instead of\r
+ // device address.\r
+ return mCpuIo->Mem.Write (\r
+ mCpuIo,\r
+ (EFI_CPU_IO_PROTOCOL_WIDTH)Width,\r
+ TO_HOST_ADDRESS (Address, Translation),\r
+ Count,\r
+ Buffer\r
+ );\r
}\r
\r
/**\r
OUT VOID *Buffer\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+\r
Status = RootBridgeIoCheckParameter (\r
- This, IoOperation, Width,\r
- Address, Count, Buffer\r
+ This,\r
+ IoOperation,\r
+ Width,\r
+ Address,\r
+ Count,\r
+ Buffer\r
);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
- return mCpuIo->Io.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);\r
+\r
+ RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
+\r
+ // Address passed to CpuIo->Io.Read needs to be a host address instead of\r
+ // device address.\r
+ return mCpuIo->Io.Read (\r
+ mCpuIo,\r
+ (EFI_CPU_IO_PROTOCOL_WIDTH)Width,\r
+ TO_HOST_ADDRESS (Address, RootBridge->Io.Translation),\r
+ Count,\r
+ Buffer\r
+ );\r
}\r
\r
/**\r
EFI_STATUS\r
EFIAPI\r
RootBridgeIoIoWrite (\r
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
- IN UINT64 Address,\r
- IN UINTN Count,\r
- IN VOID *Buffer\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN VOID *Buffer\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+\r
Status = RootBridgeIoCheckParameter (\r
- This, IoOperation, Width,\r
- Address, Count, Buffer\r
+ This,\r
+ IoOperation,\r
+ Width,\r
+ Address,\r
+ Count,\r
+ Buffer\r
);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
- return mCpuIo->Io.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);\r
+\r
+ RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
+\r
+ // Address passed to CpuIo->Io.Write needs to be a host address instead of\r
+ // device address.\r
+ return mCpuIo->Io.Write (\r
+ mCpuIo,\r
+ (EFI_CPU_IO_PROTOCOL_WIDTH)Width,\r
+ TO_HOST_ADDRESS (Address, RootBridge->Io.Translation),\r
+ Count,\r
+ Buffer\r
+ );\r
}\r
\r
/**\r
EFI_STATUS\r
EFIAPI\r
RootBridgeIoCopyMem (\r
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
- IN UINT64 DestAddress,\r
- IN UINT64 SrcAddress,\r
- IN UINTN Count\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 DestAddress,\r
+ IN UINT64 SrcAddress,\r
+ IN UINTN Count\r
)\r
{\r
EFI_STATUS Status;\r
UINTN Index;\r
UINT64 Result;\r
\r
- if ((UINT32) Width > EfiPciWidthUint64) {\r
+ if ((UINT32)Width > EfiPciWidthUint64) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
return EFI_SUCCESS;\r
}\r
\r
- Stride = (UINTN) (1 << Width);\r
+ Stride = (UINTN)(1 << Width);\r
\r
Forward = TRUE;\r
if ((DestAddress > SrcAddress) &&\r
- (DestAddress < (SrcAddress + Count * Stride))) {\r
- Forward = FALSE;\r
- SrcAddress = SrcAddress + (Count - 1) * Stride;\r
+ (DestAddress < (SrcAddress + Count * Stride)))\r
+ {\r
+ Forward = FALSE;\r
+ SrcAddress = SrcAddress + (Count - 1) * Stride;\r
DestAddress = DestAddress + (Count - 1) * Stride;\r
}\r
\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
+\r
Status = RootBridgeIoMemWrite (\r
This,\r
Width,\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
+\r
if (Forward) {\r
- SrcAddress += Stride;\r
+ SrcAddress += Stride;\r
DestAddress += Stride;\r
} else {\r
- SrcAddress -= Stride;\r
+ SrcAddress -= Stride;\r
DestAddress -= Stride;\r
}\r
}\r
+\r
return EFI_SUCCESS;\r
}\r
\r
-\r
/**\r
PCI configuration space access.\r
\r
EFI_STATUS\r
EFIAPI\r
RootBridgeIoPciAccess (\r
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
- IN BOOLEAN Read,\r
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
- IN UINT64 Address,\r
- IN UINTN Count,\r
- IN OUT VOID *Buffer\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN BOOLEAN Read,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
)\r
{\r
EFI_STATUS Status;\r
//\r
InStride = mInStride[Width];\r
OutStride = mOutStride[Width];\r
- Size = (UINTN) (1 << (Width & 0x03));\r
+ Size = (UINTN)(1 << (Width & 0x03));\r
for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {\r
if (Read) {\r
PciSegmentReadBuffer (Address, Size, Uint8Buffer);\r
PciSegmentWriteBuffer (Address, Size, Uint8Buffer);\r
}\r
}\r
+\r
return EFI_SUCCESS;\r
}\r
\r
EFI_STATUS\r
EFIAPI\r
RootBridgeIoPciRead (\r
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
- IN UINT64 Address,\r
- IN UINTN Count,\r
- IN OUT VOID *Buffer\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
)\r
{\r
return RootBridgeIoPciAccess (This, TRUE, Width, Address, Count, Buffer);\r
EFI_STATUS\r
EFIAPI\r
RootBridgeIoPciWrite (\r
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
- IN UINT64 Address,\r
- IN UINTN Count,\r
- IN OUT VOID *Buffer\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
)\r
{\r
return RootBridgeIoPciAccess (This, FALSE, Width, Address, Count, Buffer);\r
OUT VOID **Mapping\r
)\r
{\r
- EFI_STATUS Status;\r
- PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
- EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
- MAP_INFO *MapInfo;\r
+ EFI_STATUS Status;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
+ MAP_INFO *MapInfo;\r
\r
- if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL ||\r
- Mapping == NULL) {\r
+ if ((HostAddress == NULL) || (NumberOfBytes == NULL) || (DeviceAddress == NULL) ||\r
+ (Mapping == NULL))\r
+ {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
//\r
// Make sure that Operation is valid\r
//\r
- if ((UINT32) Operation >= EfiPciOperationMaximum) {\r
+ if ((UINT32)Operation >= EfiPciOperationMaximum) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
\r
- PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;\r
- if (!RootBridge->DmaAbove4G && ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB)) {\r
+ if (mIoMmu != NULL) {\r
+ if (!RootBridge->DmaAbove4G) {\r
+ //\r
+ // Clear 64bit support\r
+ //\r
+ if (Operation > EfiPciOperationBusMasterCommonBuffer) {\r
+ Operation = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION)(Operation - EfiPciOperationBusMasterRead64);\r
+ }\r
+ }\r
+\r
+ Status = mIoMmu->Map (\r
+ mIoMmu,\r
+ (EDKII_IOMMU_OPERATION)Operation,\r
+ HostAddress,\r
+ NumberOfBytes,\r
+ DeviceAddress,\r
+ Mapping\r
+ );\r
+ return Status;\r
+ }\r
+\r
+ PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;\r
+ if ((!RootBridge->DmaAbove4G ||\r
+ ((Operation != EfiPciOperationBusMasterRead64) &&\r
+ (Operation != EfiPciOperationBusMasterWrite64) &&\r
+ (Operation != EfiPciOperationBusMasterCommonBuffer64))) &&\r
+ ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB))\r
+ {\r
//\r
- // If the root bridge can not handle performing DMA above 4GB but\r
- // any part of the DMA transfer being mapped is above 4GB, then\r
+ // If the root bridge or the device cannot handle performing DMA above\r
+ // 4GB but any part of the DMA transfer being mapped is above 4GB, then\r
// map the DMA transfer to a buffer below 4GB.\r
//\r
\r
- if (Operation == EfiPciOperationBusMasterCommonBuffer ||\r
- Operation == EfiPciOperationBusMasterCommonBuffer64) {\r
+ if ((Operation == EfiPciOperationBusMasterCommonBuffer) ||\r
+ (Operation == EfiPciOperationBusMasterCommonBuffer64))\r
+ {\r
//\r
// Common Buffer operations can not be remapped. If the common buffer\r
// if above 4GB, then it is not possible to generate a mapping, so return\r
// then copy the contents of the real buffer into the mapped buffer\r
// so the Bus Master can read the contents of the real buffer.\r
//\r
- if (Operation == EfiPciOperationBusMasterRead ||\r
- Operation == EfiPciOperationBusMasterRead64) {\r
+ if ((Operation == EfiPciOperationBusMasterRead) ||\r
+ (Operation == EfiPciOperationBusMasterRead64))\r
+ {\r
CopyMem (\r
- (VOID *) (UINTN) MapInfo->MappedHostAddress,\r
- (VOID *) (UINTN) MapInfo->HostAddress,\r
+ (VOID *)(UINTN)MapInfo->MappedHostAddress,\r
+ (VOID *)(UINTN)MapInfo->HostAddress,\r
MapInfo->NumberOfBytes\r
);\r
}\r
//\r
// Return a pointer to the MAP_INFO structure in Mapping\r
//\r
- *Mapping = MapInfo;\r
+ *Mapping = MapInfo;\r
} else {\r
//\r
// If the root bridge CAN handle performing DMA above 4GB or\r
IN VOID *Mapping\r
)\r
{\r
- MAP_INFO *MapInfo;\r
- LIST_ENTRY *Link;\r
- PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ MAP_INFO *MapInfo;\r
+ LIST_ENTRY *Link;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ EFI_STATUS Status;\r
+\r
+ if (mIoMmu != NULL) {\r
+ Status = mIoMmu->Unmap (\r
+ mIoMmu,\r
+ Mapping\r
+ );\r
+ return Status;\r
+ }\r
\r
RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
+\r
//\r
// See if the Map() operation associated with this Unmap() required a mapping\r
// buffer. If a mapping buffer was not required, then this function simply\r
for (Link = GetFirstNode (&RootBridge->Maps)\r
; !IsNull (&RootBridge->Maps, Link)\r
; Link = GetNextNode (&RootBridge->Maps, Link)\r
- ) {\r
+ )\r
+ {\r
MapInfo = MAP_INFO_FROM_LINK (Link);\r
if (MapInfo == Mapping) {\r
break;\r
}\r
}\r
+\r
//\r
// Mapping is not a valid value returned by Map()\r
//\r
if (MapInfo != Mapping) {\r
return EFI_INVALID_PARAMETER;\r
}\r
+\r
RemoveEntryList (&MapInfo->Link);\r
\r
//\r
// then copy the contents of the mapped buffer into the real buffer\r
// so the processor can read the contents of the real buffer.\r
//\r
- if (MapInfo->Operation == EfiPciOperationBusMasterWrite ||\r
- MapInfo->Operation == EfiPciOperationBusMasterWrite64) {\r
+ if ((MapInfo->Operation == EfiPciOperationBusMasterWrite) ||\r
+ (MapInfo->Operation == EfiPciOperationBusMasterWrite64))\r
+ {\r
CopyMem (\r
- (VOID *) (UINTN) MapInfo->HostAddress,\r
- (VOID *) (UINTN) MapInfo->MappedHostAddress,\r
+ (VOID *)(UINTN)MapInfo->HostAddress,\r
+ (VOID *)(UINTN)MapInfo->MappedHostAddress,\r
MapInfo->NumberOfBytes\r
);\r
}\r
// The only valid memory types are EfiBootServicesData and\r
// EfiRuntimeServicesData\r
//\r
- if (MemoryType != EfiBootServicesData &&\r
- MemoryType != EfiRuntimeServicesData) {\r
+ if ((MemoryType != EfiBootServicesData) &&\r
+ (MemoryType != EfiRuntimeServicesData))\r
+ {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
\r
+ if (mIoMmu != NULL) {\r
+ if (!RootBridge->DmaAbove4G) {\r
+ //\r
+ // Clear DUAL_ADDRESS_CYCLE\r
+ //\r
+ Attributes &= ~((UINT64)EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE);\r
+ }\r
+\r
+ Status = mIoMmu->AllocateBuffer (\r
+ mIoMmu,\r
+ Type,\r
+ MemoryType,\r
+ Pages,\r
+ HostAddress,\r
+ Attributes\r
+ );\r
+ return Status;\r
+ }\r
+\r
AllocateType = AllocateAnyPages;\r
- if (!RootBridge->DmaAbove4G) {\r
+ if (!RootBridge->DmaAbove4G ||\r
+ ((Attributes & EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0))\r
+ {\r
//\r
// Limit allocations to memory below 4GB\r
//\r
AllocateType = AllocateMaxAddress;\r
- PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1);\r
+ PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(SIZE_4GB - 1);\r
}\r
+\r
Status = gBS->AllocatePages (\r
AllocateType,\r
MemoryType,\r
&PhysicalAddress\r
);\r
if (!EFI_ERROR (Status)) {\r
- *HostAddress = (VOID *) (UINTN) PhysicalAddress;\r
+ *HostAddress = (VOID *)(UINTN)PhysicalAddress;\r
}\r
\r
return Status;\r
OUT VOID *HostAddress\r
)\r
{\r
- return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);\r
+ EFI_STATUS Status;\r
+\r
+ if (mIoMmu != NULL) {\r
+ Status = mIoMmu->FreeBuffer (\r
+ mIoMmu,\r
+ Pages,\r
+ HostAddress\r
+ );\r
+ return Status;\r
+ }\r
+\r
+ return gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, Pages);\r
}\r
\r
/**\r
EFI_STATUS\r
EFIAPI\r
RootBridgeIoFlush (\r
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This\r
)\r
{\r
return EFI_SUCCESS;\r
OUT UINT64 *Attributes\r
)\r
{\r
- PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
\r
- if (Attributes == NULL && Supported == NULL) {\r
+ if ((Attributes == NULL) && (Supported == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
// Set the return value for Supported and Attributes\r
//\r
if (Supported != NULL) {\r
- *Supported = RootBridge->Supports;\r
+ *Supported = RootBridge->Supports;\r
}\r
\r
if (Attributes != NULL) {\r
IN OUT UINT64 *ResourceLength\r
)\r
{\r
- PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
\r
RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
\r
\r
/**\r
Retrieves the current resource settings of this PCI root bridge in the form\r
- of a set of ACPI 2.0 resource descriptors.\r
+ of a set of ACPI resource descriptors.\r
\r
There are only two resource descriptor types from the ACPI Specification that\r
may be used to describe the current resources allocated to a PCI root bridge.\r
- These are the QWORD Address Space Descriptor (ACPI 2.0 Section 6.4.3.5.1),\r
- and the End Tag (ACPI 2.0 Section 6.4.2.8). The QWORD Address Space\r
- Descriptor can describe memory, I/O, and bus number ranges for dynamic or\r
- fixed resources. The configuration of a PCI root bridge is described with one\r
- or more QWORD Address Space Descriptors followed by an End Tag.\r
+ These are the QWORD Address Space Descriptor, and the End Tag. The QWORD\r
+ Address Space Descriptor can describe memory, I/O, and bus number ranges for\r
+ dynamic or fixed resources. The configuration of a PCI root bridge is described\r
+ with one or more QWORD Address Space Descriptors followed by an End Tag.\r
\r
@param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
- @param[out] Resources A pointer to the ACPI 2.0 resource descriptors that\r
+ @param[out] Resources A pointer to the resource descriptors that\r
describe the current configuration of this PCI root\r
- bridge. The storage for the ACPI 2.0 resource\r
+ bridge. The storage for the resource\r
descriptors is allocated by this function. The\r
caller must treat the return buffer as read-only\r
data, and the buffer must not be freed by the\r
EFI_STATUS\r
EFIAPI\r
RootBridgeIoConfiguration (\r
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
- OUT VOID **Resources\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ OUT VOID **Resources\r
)\r
{\r
- PCI_RESOURCE_TYPE Index;\r
- PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
- PCI_RES_NODE *ResAllocNode;\r
- EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
- EFI_ACPI_END_TAG_DESCRIPTOR *End;\r
+ PCI_RESOURCE_TYPE Index;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ PCI_RES_NODE *ResAllocNode;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
+ EFI_ACPI_END_TAG_DESCRIPTOR *End;\r
\r
//\r
// Get this instance of the Root Bridge.\r
);\r
Descriptor = RootBridge->ConfigBuffer;\r
for (Index = TypeIo; Index < TypeMax; Index++) {\r
-\r
ResAllocNode = &RootBridge->ResAllocNode[Index];\r
\r
if (ResAllocNode->Status != ResAllocated) {\r
\r
Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
- Descriptor->AddrRangeMin = ResAllocNode->Base;\r
- Descriptor->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1;\r
- Descriptor->AddrLen = ResAllocNode->Length;\r
- switch (ResAllocNode->Type) {\r
-\r
- case TypeIo:\r
- Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
- break;\r
+ // According to UEFI 2.7, RootBridgeIo->Configuration should return address\r
+ // range in CPU view (host address), and ResAllocNode->Base is already a CPU\r
+ // view address (host address).\r
+ Descriptor->AddrRangeMin = ResAllocNode->Base;\r
+ Descriptor->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1;\r
+ Descriptor->AddrLen = ResAllocNode->Length;\r
+ Descriptor->AddrTranslationOffset = GetTranslationByResourceType (\r
+ RootBridge,\r
+ ResAllocNode->Type\r
+ );\r
\r
- case TypePMem32:\r
- Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
- case TypeMem32:\r
- Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
- Descriptor->AddrSpaceGranularity = 32;\r
- break;\r
-\r
- case TypePMem64:\r
- Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
- case TypeMem64:\r
- Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
- Descriptor->AddrSpaceGranularity = 64;\r
- break;\r
-\r
- case TypeBus:\r
- Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;\r
- break;\r
-\r
- default:\r
- break;\r
+ switch (ResAllocNode->Type) {\r
+ case TypeIo:\r
+ Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
+ break;\r
+\r
+ case TypePMem32:\r
+ Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
+ case TypeMem32:\r
+ Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ Descriptor->AddrSpaceGranularity = 32;\r
+ break;\r
+\r
+ case TypePMem64:\r
+ Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
+ case TypeMem64:\r
+ Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ Descriptor->AddrSpaceGranularity = 64;\r
+ break;\r
+\r
+ case TypeBus:\r
+ Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;\r
+ break;\r
+\r
+ default:\r
+ break;\r
}\r
\r
Descriptor++;\r
}\r
+\r
//\r
// Terminate the entries.\r
//\r
- End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;\r
+ End = (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor;\r
End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
End->Checksum = 0x0;\r
\r