--- /dev/null
+/*++\r
+\r
+Copyright (c) 2005 - 2007, Intel Corporation \r
+All rights reserved. This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php \r
+ \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+\r
+Module Name:\r
+ PcatPciRootBridgeIo.c\r
+ \r
+Abstract:\r
+\r
+ EFI PC AT PCI Root Bridge Io Protocol\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "PcatPciRootBridge.h"\r
+\r
+//\r
+// Protocol Member Function Prototypes\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoPollMem ( \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 UINT64 Mask,\r
+ IN UINT64 Value,\r
+ IN UINT64 Delay,\r
+ OUT UINT64 *Result\r
+ );\r
+ \r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoPollIo ( \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 UINT64 Mask,\r
+ IN UINT64 Value,\r
+ IN UINT64 Delay,\r
+ OUT UINT64 *Result\r
+ );\r
+ \r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoMemRead (\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
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoMemWrite (\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
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoIoRead (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 UserAddress,\r
+ IN UINTN Count,\r
+ IN OUT VOID *UserBuffer\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoIoWrite (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 UserAddress,\r
+ IN UINTN Count,\r
+ IN OUT VOID *UserBuffer\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoCopyMem (\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\r
+EFIAPI\r
+PcatRootBridgeIoPciRead (\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
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoPciWrite (\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
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoMap (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,\r
+ IN VOID *HostAddress,\r
+ IN OUT UINTN *NumberOfBytes,\r
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
+ OUT VOID **Mapping\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoUnmap (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN VOID *Mapping\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoAllocateBuffer (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_ALLOCATE_TYPE Type,\r
+ IN EFI_MEMORY_TYPE MemoryType,\r
+ IN UINTN Pages,\r
+ OUT VOID **HostAddress,\r
+ IN UINT64 Attributes\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoFreeBuffer (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN UINTN Pages,\r
+ OUT VOID *HostAddress\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoFlush (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoGetAttributes (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ OUT UINT64 *Supported,\r
+ OUT UINT64 *Attributes\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoSetAttributes (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN UINT64 Attributes,\r
+ IN OUT UINT64 *ResourceBase,\r
+ IN OUT UINT64 *ResourceLength \r
+ ); \r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoConfiguration (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ OUT VOID **Resources\r
+ );\r
+\r
+//\r
+// Private Function Prototypes\r
+//\r
+STATIC \r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoMemRW (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINTN Count,\r
+ IN BOOLEAN InStrideFlag,\r
+ IN PTR In,\r
+ IN BOOLEAN OutStrideFlag,\r
+ OUT PTR Out\r
+ );\r
+\r
+EFI_STATUS\r
+PcatRootBridgeIoConstructor (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol,\r
+ IN UINTN SegmentNumber\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Contruct the Pci Root Bridge Io protocol\r
+\r
+Arguments:\r
+\r
+ Protocol - protocol to initialize\r
+ \r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ Protocol->ParentHandle = NULL;\r
+\r
+ Protocol->PollMem = PcatRootBridgeIoPollMem;\r
+ Protocol->PollIo = PcatRootBridgeIoPollIo;\r
+\r
+ Protocol->Mem.Read = PcatRootBridgeIoMemRead;\r
+ Protocol->Mem.Write = PcatRootBridgeIoMemWrite;\r
+\r
+ Protocol->Io.Read = PcatRootBridgeIoIoRead;\r
+ Protocol->Io.Write = PcatRootBridgeIoIoWrite;\r
+\r
+ Protocol->CopyMem = PcatRootBridgeIoCopyMem;\r
+\r
+ Protocol->Pci.Read = PcatRootBridgeIoPciRead;\r
+ Protocol->Pci.Write = PcatRootBridgeIoPciWrite;\r
+\r
+ Protocol->Map = PcatRootBridgeIoMap;\r
+ Protocol->Unmap = PcatRootBridgeIoUnmap;\r
+\r
+ Protocol->AllocateBuffer = PcatRootBridgeIoAllocateBuffer;\r
+ Protocol->FreeBuffer = PcatRootBridgeIoFreeBuffer;\r
+\r
+ Protocol->Flush = PcatRootBridgeIoFlush;\r
+\r
+ Protocol->GetAttributes = PcatRootBridgeIoGetAttributes;\r
+ Protocol->SetAttributes = PcatRootBridgeIoSetAttributes;\r
+\r
+ Protocol->Configuration = PcatRootBridgeIoConfiguration;\r
+\r
+ Protocol->SegmentNumber = (UINT32)SegmentNumber;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoPollMem ( \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 UINT64 Mask,\r
+ IN UINT64 Value,\r
+ IN UINT64 Delay,\r
+ OUT UINT64 *Result\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT64 NumberOfTicks;\r
+ UINTN Remainder;\r
+\r
+ if (Result == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+\r
+ if (Width < 0 || Width > EfiPciWidthUint64) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // No matter what, always do a single poll.\r
+ //\r
+ Status = This->Mem.Read (This, Width, Address, 1, Result);\r
+ if ( EFI_ERROR(Status) ) {\r
+ return Status;\r
+ } \r
+ if ( (*Result & Mask) == Value ) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if ( Delay != 0 ) {\r
+\r
+ NumberOfTicks = DivU64x32Remainder (Delay, 100, &Remainder);\r
+ if ( Remainder !=0 ) {\r
+ NumberOfTicks += 1;\r
+ }\r
+ NumberOfTicks += 1;\r
+ \r
+ while ( NumberOfTicks ) {\r
+\r
+ gBS->Stall (10);\r
+\r
+ Status = This->Mem.Read (This, Width, Address, 1, Result);\r
+ if ( EFI_ERROR(Status) ) {\r
+ return Status;\r
+ }\r
+ \r
+ if ( (*Result & Mask) == Value ) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ NumberOfTicks -= 1;\r
+ }\r
+ }\r
+ return EFI_TIMEOUT;\r
+}\r
+ \r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoPollIo ( \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 UINT64 Mask,\r
+ IN UINT64 Value,\r
+ IN UINT64 Delay,\r
+ OUT UINT64 *Result\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT64 NumberOfTicks;\r
+ UINTN Remainder;\r
+\r
+ if (Result == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Width < 0 || Width > EfiPciWidthUint64) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // No matter what, always do a single poll.\r
+ //\r
+ Status = This->Io.Read (This, Width, Address, 1, Result);\r
+ if ( EFI_ERROR(Status) ) {\r
+ return Status;\r
+ } \r
+ if ( (*Result & Mask) == Value ) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (Delay != 0) {\r
+\r
+ NumberOfTicks = DivU64x32Remainder (Delay, 100, &Remainder);\r
+ if ( Remainder !=0 ) {\r
+ NumberOfTicks += 1;\r
+ }\r
+ NumberOfTicks += 1;\r
+ \r
+ while ( NumberOfTicks ) {\r
+\r
+ gBS->Stall(10);\r
+ \r
+ Status = This->Io.Read (This, Width, Address, 1, Result);\r
+ if ( EFI_ERROR(Status) ) {\r
+ return Status;\r
+ }\r
+ \r
+ if ( (*Result & Mask) == Value ) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ NumberOfTicks -= 1;\r
+ }\r
+ }\r
+ return EFI_TIMEOUT;\r
+}\r
+\r
+BOOLEAN\r
+PcatRootBridgeMemAddressValid (\r
+ IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData,\r
+ IN UINT64 Address\r
+ )\r
+{\r
+ if ((Address >= PrivateData->PciExpressBaseAddress) && (Address < PrivateData->PciExpressBaseAddress + 0x10000000)) {\r
+ return TRUE;\r
+ }\r
+ if ((Address >= PrivateData->MemBase) && (Address < PrivateData->MemLimit)) {\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoMemRead (\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
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
+ UINTN AlignMask;\r
+ PTR In;\r
+ PTR Out;\r
+\r
+ if ( Buffer == NULL ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
+\r
+ if (!PcatRootBridgeMemAddressValid (PrivateData, Address)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ AlignMask = (1 << (Width & 0x03)) - 1;\r
+ if (Address & AlignMask) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Address += PrivateData->PhysicalMemoryBase;\r
+\r
+ In.buf = Buffer;\r
+ Out.buf = (VOID *)(UINTN) Address;\r
+ if (Width >= EfiPciWidthUint8 && Width <= EfiPciWidthUint64) {\r
+ return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);\r
+ }\r
+ if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {\r
+ return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);\r
+ }\r
+ if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {\r
+ return PcatRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);\r
+ }\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoMemWrite (\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
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
+ UINTN AlignMask;\r
+ PTR In;\r
+ PTR Out;\r
+\r
+ if ( Buffer == NULL ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
+\r
+ if (!PcatRootBridgeMemAddressValid (PrivateData, Address)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ AlignMask = (1 << (Width & 0x03)) - 1;\r
+ if (Address & AlignMask) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Address += PrivateData->PhysicalMemoryBase;\r
+\r
+ In.buf = (VOID *)(UINTN) Address;\r
+ Out.buf = Buffer;\r
+ if (Width >= EfiPciWidthUint8 && Width <= EfiPciWidthUint64) {\r
+ return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);\r
+ }\r
+ if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {\r
+ return PcatRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);\r
+ }\r
+ if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {\r
+ return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);\r
+ }\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoCopyMem (\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
+{\r
+ EFI_STATUS Status;\r
+ BOOLEAN Direction;\r
+ UINTN Stride;\r
+ UINTN Index;\r
+ UINT64 Result;\r
+\r
+ if (Width < 0 || Width > EfiPciWidthUint64) {\r
+ return EFI_INVALID_PARAMETER;\r
+ } \r
+\r
+ if (DestAddress == SrcAddress) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Stride = (UINTN)1 << Width;\r
+\r
+ Direction = TRUE;\r
+ if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) {\r
+ Direction = FALSE;\r
+ SrcAddress = SrcAddress + (Count-1) * Stride;\r
+ DestAddress = DestAddress + (Count-1) * Stride;\r
+ }\r
+\r
+ for (Index = 0;Index < Count;Index++) {\r
+ Status = PcatRootBridgeIoMemRead (\r
+ This,\r
+ Width,\r
+ SrcAddress,\r
+ 1,\r
+ &Result\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = PcatRootBridgeIoMemWrite (\r
+ This,\r
+ Width,\r
+ DestAddress,\r
+ 1,\r
+ &Result\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ if (Direction) {\r
+ SrcAddress += Stride;\r
+ DestAddress += Stride;\r
+ } else {\r
+ SrcAddress -= Stride;\r
+ DestAddress -= Stride;\r
+ }\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoPciRead (\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
+ if (Buffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ return PcatRootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoPciWrite (\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
+ if (Buffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ return PcatRootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoMap (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,\r
+ IN VOID *HostAddress,\r
+ IN OUT UINTN *NumberOfBytes,\r
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
+ OUT VOID **Mapping\r
+ )\r
+\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
+ MAP_INFO *MapInfo;\r
+ MAP_INFO_INSTANCE *MapInstance;\r
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
+\r
+ if ( HostAddress == NULL || NumberOfBytes == NULL || \r
+ DeviceAddress == NULL || Mapping == NULL ) {\r
+ \r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Perform a fence operation to make sure all memory operations are flushed\r
+ //\r
+ MemoryFence();\r
+\r
+ //\r
+ // Initialize the return values to their defaults\r
+ //\r
+ *Mapping = NULL;\r
+\r
+ //\r
+ // Make sure that Operation is valid\r
+ //\r
+ if (Operation < 0 || Operation >= EfiPciOperationMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Most PCAT like chipsets can not handle performing DMA above 4GB.\r
+ // If any part of the DMA transfer being mapped is above 4GB, then\r
+ // map the DMA transfer to a buffer below 4GB.\r
+ //\r
+ PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;\r
+ if ((PhysicalAddress + *NumberOfBytes) > 0x100000000) {\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
+ // an error.\r
+ //\r
+ if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Allocate a MAP_INFO structure to remember the mapping when Unmap() is\r
+ // called later.\r
+ //\r
+ Status = gBS->AllocatePool (\r
+ EfiBootServicesData, \r
+ sizeof(MAP_INFO), \r
+ &MapInfo\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ *NumberOfBytes = 0;\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Return a pointer to the MAP_INFO structure in Mapping\r
+ //\r
+ *Mapping = MapInfo;\r
+\r
+ //\r
+ // Initialize the MAP_INFO structure\r
+ //\r
+ MapInfo->Operation = Operation;\r
+ MapInfo->NumberOfBytes = *NumberOfBytes;\r
+ MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES(*NumberOfBytes);\r
+ MapInfo->HostAddress = PhysicalAddress;\r
+ MapInfo->MappedHostAddress = 0x00000000ffffffff;\r
+\r
+ //\r
+ // Allocate a buffer below 4GB to map the transfer to.\r
+ //\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress, \r
+ EfiBootServicesData, \r
+ MapInfo->NumberOfPages,\r
+ &MapInfo->MappedHostAddress\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ gBS->FreePool (MapInfo);\r
+ *NumberOfBytes = 0;\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // If this is a read operation from the Bus Master's point of view,\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 || Operation == EfiPciOperationBusMasterRead64) {\r
+ CopyMem (\r
+ (VOID *)(UINTN)MapInfo->MappedHostAddress, \r
+ (VOID *)(UINTN)MapInfo->HostAddress,\r
+ MapInfo->NumberOfBytes\r
+ );\r
+ }\r
+\r
+\r
+ Status =gBS->AllocatePool (\r
+ EfiBootServicesData, \r
+ sizeof(MAP_INFO_INSTANCE), \r
+ &MapInstance\r
+ ); \r
+ if (EFI_ERROR(Status)) {\r
+ gBS->FreePages (MapInfo->MappedHostAddress,MapInfo->NumberOfPages);\r
+ gBS->FreePool (MapInfo);\r
+ *NumberOfBytes = 0;\r
+ return Status;\r
+ }\r
+\r
+ MapInstance->Map=MapInfo;\r
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
+ InsertTailList(&PrivateData->MapInfo,&MapInstance->Link);\r
+ \r
+ //\r
+ // The DeviceAddress is the address of the maped buffer below 4GB\r
+ //\r
+ *DeviceAddress = MapInfo->MappedHostAddress;\r
+ } else {\r
+ //\r
+ // The transfer is below 4GB, so the DeviceAddress is simply the HostAddress\r
+ //\r
+ *DeviceAddress = PhysicalAddress;\r
+ }\r
+\r
+ //\r
+ // Perform a fence operation to make sure all memory operations are flushed\r
+ //\r
+ MemoryFence();\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoUnmap (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN VOID *Mapping\r
+ )\r
+\r
+{\r
+ MAP_INFO *MapInfo;\r
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
+ LIST_ENTRY *Link;\r
+\r
+ //\r
+ // Perform a fence operation to make sure all memory operations are flushed\r
+ //\r
+ MemoryFence();\r
+\r
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
+ //\r
+ // See if the Map() operation associated with this Unmap() required a mapping buffer.\r
+ // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS.\r
+ //\r
+ if (Mapping != NULL) {\r
+ //\r
+ // Get the MAP_INFO structure from Mapping\r
+ //\r
+ MapInfo = (MAP_INFO *)Mapping;\r
+\r
+ for (Link = PrivateData->MapInfo.ForwardLink; Link != &PrivateData->MapInfo; Link = Link->ForwardLink) {\r
+ if (((MAP_INFO_INSTANCE*)Link)->Map == MapInfo)\r
+ break;\r
+ }\r
+\r
+ if (Link == &PrivateData->MapInfo) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ RemoveEntryList(Link);\r
+ ((MAP_INFO_INSTANCE*)Link)->Map = NULL;\r
+ gBS->FreePool((MAP_INFO_INSTANCE*)Link);\r
+\r
+ //\r
+ // If this is a write operation from the Bus Master's point of view,\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 || MapInfo->Operation == EfiPciOperationBusMasterWrite64) {\r
+ CopyMem (\r
+ (VOID *)(UINTN)MapInfo->HostAddress, \r
+ (VOID *)(UINTN)MapInfo->MappedHostAddress,\r
+ MapInfo->NumberOfBytes\r
+ );\r
+ }\r
+\r
+ //\r
+ // Free the mapped buffer and the MAP_INFO structure.\r
+ //\r
+ gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages);\r
+ gBS->FreePool (Mapping);\r
+ }\r
+\r
+ //\r
+ // Perform a fence operation to make sure all memory operations are flushed\r
+ //\r
+ MemoryFence();\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoAllocateBuffer (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_ALLOCATE_TYPE Type,\r
+ IN EFI_MEMORY_TYPE MemoryType,\r
+ IN UINTN Pages,\r
+ OUT VOID **HostAddress,\r
+ IN UINT64 Attributes\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
+\r
+ //\r
+ // Validate Attributes\r
+ //\r
+ if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Check for invalid inputs\r
+ //\r
+ if (HostAddress == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData\r
+ //\r
+ if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Limit allocations to memory below 4GB\r
+ //\r
+ PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(0xffffffff);\r
+\r
+ Status = gBS->AllocatePages (AllocateMaxAddress, MemoryType, Pages, &PhysicalAddress);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ *HostAddress = (VOID *)(UINTN)PhysicalAddress;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoFreeBuffer (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN UINTN Pages,\r
+ OUT VOID *HostAddress\r
+ )\r
+\r
+{\r
+\r
+ if( HostAddress == NULL ){\r
+ return EFI_INVALID_PARAMETER;\r
+ } \r
+ return gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, Pages);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoFlush (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This\r
+ )\r
+\r
+{\r
+ //\r
+ // Perform a fence operation to make sure all memory operations are flushed\r
+ //\r
+ MemoryFence();\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoGetAttributes (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ OUT UINT64 *Supported, OPTIONAL\r
+ OUT UINT64 *Attributes\r
+ )\r
+\r
+{\r
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
+\r
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
+\r
+ if (Attributes == NULL && Supported == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Supported is an OPTIONAL parameter. See if it is NULL\r
+ //\r
+ if (Supported) {\r
+ //\r
+ // This is a generic driver for a PC-AT class system. It does not have any\r
+ // chipset specific knowlegde, so none of the attributes can be set or \r
+ // cleared. Any attempt to set attribute that are already set will succeed, \r
+ // and any attempt to set an attribute that is not supported will fail.\r
+ //\r
+ *Supported = PrivateData->Attributes;\r
+ }\r
+\r
+ //\r
+ // Set Attrbutes to the attributes detected when the PCI Root Bridge was initialized\r
+ //\r
+ \r
+ if (Attributes) {\r
+ *Attributes = PrivateData->Attributes;\r
+ }\r
+ \r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoSetAttributes (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN UINT64 Attributes,\r
+ IN OUT UINT64 *ResourceBase,\r
+ IN OUT UINT64 *ResourceLength \r
+ )\r
+\r
+{\r
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
+ \r
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
+\r
+ //\r
+ // This is a generic driver for a PC-AT class system. It does not have any\r
+ // chipset specific knowlegde, so none of the attributes can be set or \r
+ // cleared. Any attempt to set attribute that are already set will succeed, \r
+ // and any attempt to set an attribute that is not supported will fail.\r
+ //\r
+ if (Attributes & (~PrivateData->Attributes)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoConfiguration (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ OUT VOID **Resources\r
+ )\r
+\r
+{\r
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
+ \r
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
+\r
+ *Resources = PrivateData->Configuration;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+//\r
+// Internal function\r
+//\r
+\r
+STATIC \r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoMemRW (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINTN Count,\r
+ IN BOOLEAN InStrideFlag,\r
+ IN PTR In,\r
+ IN BOOLEAN OutStrideFlag,\r
+ OUT PTR Out\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Private service to provide the memory read/write\r
+\r
+Arguments:\r
+\r
+ Width of the Memory Access\r
+ Count of the number of accesses to perform\r
+\r
+Returns:\r
+\r
+ Status\r
+\r
+ EFI_SUCCESS - Successful transaction\r
+ EFI_INVALID_PARAMETER - Unsupported width and address combination\r
+\r
+--*/\r
+{\r
+ UINTN Stride;\r
+ UINTN InStride;\r
+ UINTN OutStride;\r
+\r
+\r
+ Width = Width & 0x03;\r
+ Stride = (UINTN)1 << Width;\r
+ InStride = InStrideFlag ? Stride : 0;\r
+ OutStride = OutStrideFlag ? Stride : 0;\r
+\r
+ //\r
+ // Loop for each iteration and move the data\r
+ //\r
+ switch (Width) {\r
+ case EfiPciWidthUint8:\r
+ for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {\r
+ MemoryFence();\r
+ *In.ui8 = *Out.ui8;\r
+ MemoryFence();\r
+ }\r
+ break;\r
+ case EfiPciWidthUint16:\r
+ for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {\r
+ MemoryFence();\r
+ *In.ui16 = *Out.ui16;\r
+ MemoryFence();\r
+ }\r
+ break;\r
+ case EfiPciWidthUint32:\r
+ for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {\r
+ MemoryFence();\r
+ *In.ui32 = *Out.ui32;\r
+ MemoryFence();\r
+ }\r
+ break;\r
+ default:\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r