+++ /dev/null
-/*++\r
-\r
-Copyright (c) 2005 - 2012, 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
-\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
-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
-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
- UINT32 Remainder;\r
-\r
- if (Result == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
-\r
- if ((UINT32)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
- return EFI_SUCCESS;\r
- } else {\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
- UINT32 Remainder;\r
-\r
- if (Result == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if ((UINT32)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
- return EFI_SUCCESS;\r
- } else {\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 ((UINT32)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 ((UINT32)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 ((UINT32)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 ((UINT32)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) > 0x100000000ULL) {\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
- (VOID **)&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
- (VOID **)&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
-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 = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_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