#include "PciRootBridge.h"\r
#include "PciHostResource.h"\r
\r
+extern EDKII_IOMMU_PROTOCOL *mIoMmuProtocol;\r
+\r
#define NO_MAPPING (VOID *) (UINTN) -1\r
\r
//\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_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
+ 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, "NoExtConfSpace: %s\n", Bridge->NoExtendedConfigSpace ? 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 ((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
\r
//\r
// Make sure Mem and MemAbove4G apertures are valid\r
//\r
- if (Bridge->Mem.Base < Bridge->Mem.Limit) {\r
+ if (Bridge->Mem.Base <= Bridge->Mem.Limit) {\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
+ if (Bridge->MemAbove4G.Base <= Bridge->MemAbove4G.Limit) {\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
+ if (Bridge->PMem.Base <= Bridge->PMem.Limit) {\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
+ if (Bridge->PMemAbove4G.Base <= Bridge->PMemAbove4G.Limit) {\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 (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
}\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 (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
+ }\r
}\r
}\r
\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
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
+ RootBridge->ResAllocNode[Index].Type = Index;\r
+ if (Bridge->ResourceAssigned && (Aperture->Limit >= Aperture->Base)) {\r
+ RootBridge->ResAllocNode[Index].Base = Aperture->Base;\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
Address = PciRbAddr->Register;\r
}\r
Base = 0;\r
- Limit = 0xFFF;\r
+ Limit = RootBridge->NoExtendedConfigSpace ? 0xFF : 0xFFF;\r
}\r
\r
if (Address < Base) {\r
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a\r
lack of resources.\r
**/\r
-\r
EFI_STATUS\r
EFIAPI\r
RootBridgeIoPollMem (\r
}\r
\r
/**\r
-\r
Provides the PCI controller-specific address needed to access\r
system memory for DMA.\r
\r
@retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.\r
@retval EFI_DEVICE_ERROR The System hardware could not map the requested address.\r
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of resources.\r
-\r
**/\r
EFI_STATUS\r
EFIAPI\r
\r
RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
\r
+ if (mIoMmuProtocol != 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
+ Status = mIoMmuProtocol->Map (\r
+ mIoMmuProtocol,\r
+ 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 && ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB)) {\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
MAP_INFO *MapInfo;\r
LIST_ENTRY *Link;\r
PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ EFI_STATUS Status;\r
+\r
+ if (mIoMmuProtocol != NULL) {\r
+ Status = mIoMmuProtocol->Unmap (\r
+ mIoMmuProtocol,\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
\r
RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
\r
+ if (mIoMmuProtocol != NULL) {\r
+ if (!RootBridge->DmaAbove4G) {\r
+ //\r
+ // Clear DUAL_ADDRESS_CYCLE\r
+ //\r
+ Attributes &= ~EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE;\r
+ }\r
+ Status = mIoMmuProtocol->AllocateBuffer (\r
+ mIoMmuProtocol,\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
// Limit allocations to memory below 4GB\r
//\r
OUT VOID *HostAddress\r
)\r
{\r
+ EFI_STATUS Status;\r
+\r
+ if (mIoMmuProtocol != NULL) {\r
+ Status = mIoMmuProtocol->FreeBuffer (\r
+ mIoMmuProtocol,\r
+ Pages,\r
+ HostAddress\r
+ );\r
+ return Status;\r
+ }\r
+\r
return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);\r
}\r
\r