* [PATCH v6 0/2] MdeModulePkg/NonDiscoverablePciDeviceDxe: non-coherent DMA support @ 2016-12-09 15:04 Ard Biesheuvel 2016-12-09 15:04 ` [PATCH v6 1/2] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA Ard Biesheuvel 2016-12-09 15:04 ` [PATCH v6 2/2] Omap35xxPkg/PciEmulation: port to new non-discoverable device infrastructure Ard Biesheuvel 0 siblings, 2 replies; 6+ messages in thread From: Ard Biesheuvel @ 2016-12-09 15:04 UTC (permalink / raw) To: edk2-devel, leif.lindholm, ruiyu.ni; +Cc: feng.tian, liming.gao, Ard Biesheuvel These are the two patches that remain from the series 'MdeModulePkg: add support for non-discoverable devices', whose v5 I have partially merged. What remains is: - a patch that enhances NonDiscoverablePciDeviceDxe to support non-coherent DMA masters, which are not uncommon on ARM platforms - a patch that replaces the existing BeagleBoard PciEmulation code with a slim driver that builds on top of NonDiscoverablePciDeviceDxe to drive the non-coherent non-PCI EHCI controller on the OMAP 3630. Changes since v5: - add missing EFIAPI modifiers to non-coherent PCI I/O protocol methods Ard Biesheuvel (2): MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA Omap35xxPkg/PciEmulation: port to new non-discoverable device infrastructure BeagleBoardPkg/BeagleBoardPkg.dsc | 2 + BeagleBoardPkg/BeagleBoardPkg.fdf | 1 + MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c | 14 +- MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf | 2 + MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c | 329 +++++++++++ MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h | 29 + Omap35xxPkg/Omap35xxPkg.dsc | 2 +- Omap35xxPkg/PciEmulation/PciEmulation.c | 578 +------------------- Omap35xxPkg/PciEmulation/PciEmulation.h | 292 ---------- Omap35xxPkg/PciEmulation/PciEmulation.inf | 16 +- Omap35xxPkg/PciEmulation/PciRootBridgeIo.c | 306 ----------- 11 files changed, 403 insertions(+), 1168 deletions(-) delete mode 100644 Omap35xxPkg/PciEmulation/PciEmulation.h delete mode 100644 Omap35xxPkg/PciEmulation/PciRootBridgeIo.c -- 2.7.4 ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v6 1/2] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA 2016-12-09 15:04 [PATCH v6 0/2] MdeModulePkg/NonDiscoverablePciDeviceDxe: non-coherent DMA support Ard Biesheuvel @ 2016-12-09 15:04 ` Ard Biesheuvel 2016-12-14 9:15 ` Ard Biesheuvel 2016-12-15 8:17 ` Ni, Ruiyu 2016-12-09 15:04 ` [PATCH v6 2/2] Omap35xxPkg/PciEmulation: port to new non-discoverable device infrastructure Ard Biesheuvel 1 sibling, 2 replies; 6+ messages in thread From: Ard Biesheuvel @ 2016-12-09 15:04 UTC (permalink / raw) To: edk2-devel, leif.lindholm, ruiyu.ni; +Cc: feng.tian, liming.gao, Ard Biesheuvel Add support for non-coherent DMA, either by performing explicit cache maintenance when DMA mappings are aligned to the CPU's DMA buffer alignment, or by bounce buffering via uncached mappings otherwise. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Tested-by: Marcin Wojtas <mw@semihalf.com> --- MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c | 14 +- MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf | 2 + MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c | 329 ++++++++++++++++++++ MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h | 29 ++ 4 files changed, 367 insertions(+), 7 deletions(-) diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c index ee765d7a5d9c..0fcf2b2ec1bf 100644 --- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c +++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c @@ -16,6 +16,8 @@ #include <Protocol/DriverBinding.h> +EFI_CPU_ARCH_PROTOCOL *mCpu; + // // We only support the following device types // @@ -69,14 +71,7 @@ NonDiscoverablePciDeviceSupported ( return Status; } - // - // Restricted to DMA coherent for now - // Status = EFI_UNSUPPORTED; - if (Device->DmaType != NonDiscoverableDeviceDmaTypeCoherent) { - goto CloseProtocol; - } - for (Idx = 0; Idx < ARRAY_SIZE (SupportedNonDiscoverableDevices); Idx++) { if (CompareGuid (Device->Type, SupportedNonDiscoverableDevices [Idx])) { Status = EFI_SUCCESS; @@ -224,6 +219,11 @@ NonDiscoverablePciDeviceDxeEntryPoint ( IN EFI_SYSTEM_TABLE *SystemTable ) { + EFI_STATUS Status; + + Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&mCpu); + ASSERT_EFI_ERROR(Status); + return EfiLibInstallDriverBindingComponentName2 ( ImageHandle, SystemTable, diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf index 996fe310e0e3..5faa8945134c 100644 --- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf +++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf @@ -32,6 +32,7 @@ [Packages] [LibraryClasses] BaseMemoryLib DebugLib + DxeServicesTableLib MemoryAllocationLib UefiBootServicesTableLib UefiDriverEntryPoint @@ -40,6 +41,7 @@ [LibraryClasses] [Protocols] gEfiPciIoProtocolGuid ## BY_START gEdkiiNonDiscoverableDeviceProtocolGuid ## TO_START + gEfiCpuArchProtocolGuid ## CONSUMES [Guids] gEdkiiNonDiscoverableAhciDeviceGuid diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c index 56482e3353c0..814f7643ae4c 100644 --- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c +++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c @@ -15,6 +15,8 @@ #include "NonDiscoverablePciDeviceIo.h" +#include <Library/DxeServicesTableLib.h> + #include <IndustryStandard/Acpi.h> #include <Protocol/PciRootBridgeIo.h> @@ -537,6 +539,324 @@ CoherentPciIoFreeBuffer ( return EFI_SUCCESS; } +STATIC +EFI_STATUS +EFIAPI +NonCoherentPciIoFreeBuffer ( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ) +{ + NON_DISCOVERABLE_PCI_DEVICE *Dev; + LIST_ENTRY *Entry; + EFI_STATUS Status; + NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *Alloc; + BOOLEAN Found; + + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This); + + Found = FALSE; + + // + // Find the uncached allocation list entry associated + // with this allocation + // + for (Entry = Dev->UncachedAllocationList.ForwardLink; + Entry != &Dev->UncachedAllocationList; + Entry = Entry->ForwardLink) { + + Alloc = BASE_CR (Entry, NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION, List); + if (Alloc->HostAddress == HostAddress && Alloc->NumPages == Pages) { + // + // We are freeing the exact allocation we were given + // before by AllocateBuffer() + // + Found = TRUE; + break; + } + } + + if (!Found) { + ASSERT_EFI_ERROR (EFI_NOT_FOUND); + return EFI_NOT_FOUND; + } + + RemoveEntryList (&Alloc->List); + + Status = gDS->SetMemorySpaceAttributes ( + (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, + EFI_PAGES_TO_SIZE (Pages), + Alloc->Attributes); + if (EFI_ERROR (Status)) { + goto FreeAlloc; + } + + // + // If we fail to restore the original attributes, it is better to leak the + // memory than to return it to the heap + // + FreePages (HostAddress, Pages); + +FreeAlloc: + FreePool (Alloc); + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +NonCoherentPciIoAllocateBuffer ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes + ) +{ + NON_DISCOVERABLE_PCI_DEVICE *Dev; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor; + EFI_STATUS Status; + UINT64 MemType; + NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *Alloc; + VOID *AllocAddress; + + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This); + + Status = CoherentPciIoAllocateBuffer (This, Type, MemoryType, Pages, + &AllocAddress, Attributes); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gDS->GetMemorySpaceDescriptor ( + (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress, + &GcdDescriptor); + if (EFI_ERROR (Status)) { + goto FreeBuffer; + } + + if ((GcdDescriptor.Capabilities & (EFI_MEMORY_WC | EFI_MEMORY_UC)) == 0) { + Status = EFI_UNSUPPORTED; + goto FreeBuffer; + } + + // + // Set the preferred memory attributes + // + if ((Attributes & EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE) != 0 || + (GcdDescriptor.Capabilities & EFI_MEMORY_UC) == 0) { + // + // Use write combining if it was requested, or if it is the only + // type supported by the region. + // + MemType = EFI_MEMORY_WC; + } else { + MemType = EFI_MEMORY_UC; + } + + Alloc = AllocatePool (sizeof *Alloc); + if (Alloc == NULL) { + goto FreeBuffer; + } + + Alloc->HostAddress = AllocAddress; + Alloc->NumPages = Pages; + Alloc->Attributes = GcdDescriptor.Attributes; + + // + // Record this allocation in the linked list, so we + // can restore the memory space attributes later + // + InsertHeadList (&Dev->UncachedAllocationList, &Alloc->List); + + Status = gDS->SetMemorySpaceAttributes ( + (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress, + EFI_PAGES_TO_SIZE (Pages), + MemType); + if (EFI_ERROR (Status)) { + goto RemoveList; + } + + Status = mCpu->FlushDataCache ( + mCpu, + (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress, + EFI_PAGES_TO_SIZE (Pages), + EfiCpuFlushTypeInvalidate); + if (EFI_ERROR (Status)) { + goto RemoveList; + } + + *HostAddress = AllocAddress; + + return EFI_SUCCESS; + +RemoveList: + RemoveEntryList (&Alloc->List); + FreePool (Alloc); + +FreeBuffer: + CoherentPciIoFreeBuffer (This, Pages, AllocAddress); + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +NonCoherentPciIoMap ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + NON_DISCOVERABLE_PCI_DEVICE *Dev; + EFI_STATUS Status; + NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo; + UINTN AlignMask; + VOID *AllocAddress; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor; + BOOLEAN Bounce; + + MapInfo = AllocatePool (sizeof *MapInfo); + if (MapInfo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + MapInfo->HostAddress = HostAddress; + MapInfo->Operation = Operation; + MapInfo->NumberOfBytes = *NumberOfBytes; + + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This); + + // + // If this device does not support 64-bit DMA addressing, we need to allocate + // a bounce buffer and copy over the data in case HostAddress >= 4 GB. + // + Bounce = ((Dev->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0 && + (UINTN)HostAddress + *NumberOfBytes > SIZE_4GB); + + if (!Bounce) { + switch (Operation) { + case EfiPciIoOperationBusMasterRead: + case EfiPciIoOperationBusMasterWrite: + // + // For streaming DMA, it is sufficient if the buffer is aligned to + // the CPUs DMA buffer alignment. + // + AlignMask = mCpu->DmaBufferAlignment - 1; + if ((((UINTN) HostAddress | *NumberOfBytes) & AlignMask) == 0) { + break; + } + // fall through + + case EfiPciIoOperationBusMasterCommonBuffer: + // + // Check whether the host address refers to an uncached mapping. + // + Status = gDS->GetMemorySpaceDescriptor ( + (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, + &GcdDescriptor); + if (EFI_ERROR (Status) || + (GcdDescriptor.Attributes & (EFI_MEMORY_WB|EFI_MEMORY_WT)) != 0) { + Bounce = TRUE; + } + break; + + default: + ASSERT (FALSE); + } + } + + if (Bounce) { + if (Operation == EfiPciIoOperationBusMasterCommonBuffer) { + Status = EFI_DEVICE_ERROR; + goto FreeMapInfo; + } + + Status = NonCoherentPciIoAllocateBuffer (This, AllocateAnyPages, + EfiBootServicesData, EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes), + &AllocAddress, EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE); + if (EFI_ERROR (Status)) { + goto FreeMapInfo; + } + MapInfo->AllocAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress; + if (Operation == EfiPciIoOperationBusMasterRead) { + gBS->CopyMem (AllocAddress, HostAddress, *NumberOfBytes); + } + *DeviceAddress = MapInfo->AllocAddress; + } else { + MapInfo->AllocAddress = 0; + *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress; + + // + // We are not using a bounce buffer: the mapping is sufficiently + // aligned to allow us to simply flush the caches. Note that cleaning + // the caches is necessary for both data directions: + // - for bus master read, we want the latest data to be present + // in main memory + // - for bus master write, we don't want any stale dirty cachelines that + // may be written back unexpectedly, and clobber the data written to + // main memory by the device. + // + mCpu->FlushDataCache (mCpu, (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, + *NumberOfBytes, EfiCpuFlushTypeWriteBack); + } + + *Mapping = MapInfo; + return EFI_SUCCESS; + +FreeMapInfo: + FreePool (MapInfo); + + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +NonCoherentPciIoUnmap ( + IN EFI_PCI_IO_PROTOCOL *This, + IN VOID *Mapping + ) +{ + NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo; + + if (Mapping == NULL) { + return EFI_DEVICE_ERROR; + } + + MapInfo = Mapping; + if (MapInfo->AllocAddress != 0) { + // + // We are using a bounce buffer: copy back the data if necessary, + // and free the buffer. + // + if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) { + gBS->CopyMem (MapInfo->HostAddress, (VOID *)(UINTN)MapInfo->AllocAddress, + MapInfo->NumberOfBytes); + } + NonCoherentPciIoFreeBuffer (This, + EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes), + (VOID *)(UINTN)MapInfo->AllocAddress); + } else { + // + // We are *not* using a bounce buffer: if this is a bus master write, + // we have to invalidate the caches so the CPU will see the uncached + // data written by the device. + // + if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) { + mCpu->FlushDataCache (mCpu, + (EFI_PHYSICAL_ADDRESS)(UINTN)MapInfo->HostAddress, + MapInfo->NumberOfBytes, EfiCpuFlushTypeInvalidate); + } + } + FreePool (MapInfo); + return EFI_SUCCESS; +} STATIC EFI_STATUS @@ -726,12 +1046,21 @@ InitializePciIoProtocol ( EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc; INTN Idx; + InitializeListHead (&Dev->UncachedAllocationList); + Dev->ConfigSpace.Hdr.VendorId = PCI_ID_VENDOR_UNKNOWN; Dev->ConfigSpace.Hdr.DeviceId = PCI_ID_DEVICE_DONTCARE; // Copy protocol structure CopyMem(&Dev->PciIo, &PciIoTemplate, sizeof PciIoTemplate); + if (Dev->Device->DmaType == NonDiscoverableDeviceDmaTypeNonCoherent) { + Dev->PciIo.AllocateBuffer = NonCoherentPciIoAllocateBuffer; + Dev->PciIo.FreeBuffer = NonCoherentPciIoFreeBuffer; + Dev->PciIo.Map = NonCoherentPciIoMap; + Dev->PciIo.Unmap = NonCoherentPciIoUnmap; + } + if (CompareGuid (Dev->Device->Type, &gEdkiiNonDiscoverableAhciDeviceGuid)) { Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_MASS_STORAGE_AHCI; Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_MASS_STORAGE_SATADPA; diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h index bc0a3d3258f9..449614862911 100644 --- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h +++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h @@ -15,6 +15,8 @@ #ifndef __NON_DISCOVERABLE_PCI_DEVICE_IO_H__ #define __NON_DISCOVERABLE_PCI_DEVICE_IO_H__ +#include <PiDxe.h> + #include <Library/BaseMemoryLib.h> #include <Library/DebugLib.h> #include <Library/MemoryAllocationLib.h> @@ -25,6 +27,7 @@ #include <Protocol/ComponentName.h> #include <Protocol/NonDiscoverableDevice.h> +#include <Protocol/Cpu.h> #include <Protocol/PciIo.h> #define NON_DISCOVERABLE_PCI_DEVICE_SIG SIGNATURE_32 ('P', 'P', 'I', 'D') @@ -38,6 +41,27 @@ #define PCI_MAX_BARS 6 +extern EFI_CPU_ARCH_PROTOCOL *mCpu; + +typedef struct { + // + // The linked-list next pointer + // + LIST_ENTRY List; + // + // The address of the uncached allocation + // + VOID *HostAddress; + // + // The number of pages in the allocation + // + UINTN NumPages; + // + // The attributes of the allocation + // + UINT64 Attributes; +} NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION; + typedef struct { UINT32 Signature; // @@ -71,6 +95,11 @@ typedef struct { // Whether this device has been enabled // BOOLEAN Enabled; + // + // Linked list to keep track of uncached allocations performed + // on behalf of this device + // + LIST_ENTRY UncachedAllocationList; } NON_DISCOVERABLE_PCI_DEVICE; VOID -- 2.7.4 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v6 1/2] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA 2016-12-09 15:04 ` [PATCH v6 1/2] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA Ard Biesheuvel @ 2016-12-14 9:15 ` Ard Biesheuvel 2016-12-15 8:17 ` Ni, Ruiyu 1 sibling, 0 replies; 6+ messages in thread From: Ard Biesheuvel @ 2016-12-14 9:15 UTC (permalink / raw) To: edk2-devel@lists.01.org, Leif Lindholm, Ruiyu Ni Cc: Tian, Feng, Gao, Liming, Ard Biesheuvel Ray, Do you have any comments on this version? Thanks, Ard. On 9 December 2016 at 15:04, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote: > Add support for non-coherent DMA, either by performing explicit cache > maintenance when DMA mappings are aligned to the CPU's DMA buffer alignment, > or by bounce buffering via uncached mappings otherwise. > > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> > Tested-by: Marcin Wojtas <mw@semihalf.com> > --- > MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c | 14 +- > MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf | 2 + > MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c | 329 ++++++++++++++++++++ > MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h | 29 ++ > 4 files changed, 367 insertions(+), 7 deletions(-) > > diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c > index ee765d7a5d9c..0fcf2b2ec1bf 100644 > --- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c > +++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c > @@ -16,6 +16,8 @@ > > #include <Protocol/DriverBinding.h> > > +EFI_CPU_ARCH_PROTOCOL *mCpu; > + > // > // We only support the following device types > // > @@ -69,14 +71,7 @@ NonDiscoverablePciDeviceSupported ( > return Status; > } > > - // > - // Restricted to DMA coherent for now > - // > Status = EFI_UNSUPPORTED; > - if (Device->DmaType != NonDiscoverableDeviceDmaTypeCoherent) { > - goto CloseProtocol; > - } > - > for (Idx = 0; Idx < ARRAY_SIZE (SupportedNonDiscoverableDevices); Idx++) { > if (CompareGuid (Device->Type, SupportedNonDiscoverableDevices [Idx])) { > Status = EFI_SUCCESS; > @@ -224,6 +219,11 @@ NonDiscoverablePciDeviceDxeEntryPoint ( > IN EFI_SYSTEM_TABLE *SystemTable > ) > { > + EFI_STATUS Status; > + > + Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&mCpu); > + ASSERT_EFI_ERROR(Status); > + > return EfiLibInstallDriverBindingComponentName2 ( > ImageHandle, > SystemTable, > diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf > index 996fe310e0e3..5faa8945134c 100644 > --- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf > +++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf > @@ -32,6 +32,7 @@ [Packages] > [LibraryClasses] > BaseMemoryLib > DebugLib > + DxeServicesTableLib > MemoryAllocationLib > UefiBootServicesTableLib > UefiDriverEntryPoint > @@ -40,6 +41,7 @@ [LibraryClasses] > [Protocols] > gEfiPciIoProtocolGuid ## BY_START > gEdkiiNonDiscoverableDeviceProtocolGuid ## TO_START > + gEfiCpuArchProtocolGuid ## CONSUMES > > [Guids] > gEdkiiNonDiscoverableAhciDeviceGuid > diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c > index 56482e3353c0..814f7643ae4c 100644 > --- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c > +++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c > @@ -15,6 +15,8 @@ > > #include "NonDiscoverablePciDeviceIo.h" > > +#include <Library/DxeServicesTableLib.h> > + > #include <IndustryStandard/Acpi.h> > > #include <Protocol/PciRootBridgeIo.h> > @@ -537,6 +539,324 @@ CoherentPciIoFreeBuffer ( > return EFI_SUCCESS; > } > > +STATIC > +EFI_STATUS > +EFIAPI > +NonCoherentPciIoFreeBuffer ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN UINTN Pages, > + IN VOID *HostAddress > + ) > +{ > + NON_DISCOVERABLE_PCI_DEVICE *Dev; > + LIST_ENTRY *Entry; > + EFI_STATUS Status; > + NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *Alloc; > + BOOLEAN Found; > + > + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This); > + > + Found = FALSE; > + > + // > + // Find the uncached allocation list entry associated > + // with this allocation > + // > + for (Entry = Dev->UncachedAllocationList.ForwardLink; > + Entry != &Dev->UncachedAllocationList; > + Entry = Entry->ForwardLink) { > + > + Alloc = BASE_CR (Entry, NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION, List); > + if (Alloc->HostAddress == HostAddress && Alloc->NumPages == Pages) { > + // > + // We are freeing the exact allocation we were given > + // before by AllocateBuffer() > + // > + Found = TRUE; > + break; > + } > + } > + > + if (!Found) { > + ASSERT_EFI_ERROR (EFI_NOT_FOUND); > + return EFI_NOT_FOUND; > + } > + > + RemoveEntryList (&Alloc->List); > + > + Status = gDS->SetMemorySpaceAttributes ( > + (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, > + EFI_PAGES_TO_SIZE (Pages), > + Alloc->Attributes); > + if (EFI_ERROR (Status)) { > + goto FreeAlloc; > + } > + > + // > + // If we fail to restore the original attributes, it is better to leak the > + // memory than to return it to the heap > + // > + FreePages (HostAddress, Pages); > + > +FreeAlloc: > + FreePool (Alloc); > + return Status; > +} > + > +STATIC > +EFI_STATUS > +EFIAPI > +NonCoherentPciIoAllocateBuffer ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN EFI_ALLOCATE_TYPE Type, > + IN EFI_MEMORY_TYPE MemoryType, > + IN UINTN Pages, > + OUT VOID **HostAddress, > + IN UINT64 Attributes > + ) > +{ > + NON_DISCOVERABLE_PCI_DEVICE *Dev; > + EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor; > + EFI_STATUS Status; > + UINT64 MemType; > + NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *Alloc; > + VOID *AllocAddress; > + > + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This); > + > + Status = CoherentPciIoAllocateBuffer (This, Type, MemoryType, Pages, > + &AllocAddress, Attributes); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status = gDS->GetMemorySpaceDescriptor ( > + (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress, > + &GcdDescriptor); > + if (EFI_ERROR (Status)) { > + goto FreeBuffer; > + } > + > + if ((GcdDescriptor.Capabilities & (EFI_MEMORY_WC | EFI_MEMORY_UC)) == 0) { > + Status = EFI_UNSUPPORTED; > + goto FreeBuffer; > + } > + > + // > + // Set the preferred memory attributes > + // > + if ((Attributes & EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE) != 0 || > + (GcdDescriptor.Capabilities & EFI_MEMORY_UC) == 0) { > + // > + // Use write combining if it was requested, or if it is the only > + // type supported by the region. > + // > + MemType = EFI_MEMORY_WC; > + } else { > + MemType = EFI_MEMORY_UC; > + } > + > + Alloc = AllocatePool (sizeof *Alloc); > + if (Alloc == NULL) { > + goto FreeBuffer; > + } > + > + Alloc->HostAddress = AllocAddress; > + Alloc->NumPages = Pages; > + Alloc->Attributes = GcdDescriptor.Attributes; > + > + // > + // Record this allocation in the linked list, so we > + // can restore the memory space attributes later > + // > + InsertHeadList (&Dev->UncachedAllocationList, &Alloc->List); > + > + Status = gDS->SetMemorySpaceAttributes ( > + (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress, > + EFI_PAGES_TO_SIZE (Pages), > + MemType); > + if (EFI_ERROR (Status)) { > + goto RemoveList; > + } > + > + Status = mCpu->FlushDataCache ( > + mCpu, > + (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress, > + EFI_PAGES_TO_SIZE (Pages), > + EfiCpuFlushTypeInvalidate); > + if (EFI_ERROR (Status)) { > + goto RemoveList; > + } > + > + *HostAddress = AllocAddress; > + > + return EFI_SUCCESS; > + > +RemoveList: > + RemoveEntryList (&Alloc->List); > + FreePool (Alloc); > + > +FreeBuffer: > + CoherentPciIoFreeBuffer (This, Pages, AllocAddress); > + return Status; > +} > + > +STATIC > +EFI_STATUS > +EFIAPI > +NonCoherentPciIoMap ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN EFI_PCI_IO_PROTOCOL_OPERATION Operation, > + IN VOID *HostAddress, > + IN OUT UINTN *NumberOfBytes, > + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, > + OUT VOID **Mapping > + ) > +{ > + NON_DISCOVERABLE_PCI_DEVICE *Dev; > + EFI_STATUS Status; > + NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo; > + UINTN AlignMask; > + VOID *AllocAddress; > + EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor; > + BOOLEAN Bounce; > + > + MapInfo = AllocatePool (sizeof *MapInfo); > + if (MapInfo == NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + MapInfo->HostAddress = HostAddress; > + MapInfo->Operation = Operation; > + MapInfo->NumberOfBytes = *NumberOfBytes; > + > + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This); > + > + // > + // If this device does not support 64-bit DMA addressing, we need to allocate > + // a bounce buffer and copy over the data in case HostAddress >= 4 GB. > + // > + Bounce = ((Dev->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0 && > + (UINTN)HostAddress + *NumberOfBytes > SIZE_4GB); > + > + if (!Bounce) { > + switch (Operation) { > + case EfiPciIoOperationBusMasterRead: > + case EfiPciIoOperationBusMasterWrite: > + // > + // For streaming DMA, it is sufficient if the buffer is aligned to > + // the CPUs DMA buffer alignment. > + // > + AlignMask = mCpu->DmaBufferAlignment - 1; > + if ((((UINTN) HostAddress | *NumberOfBytes) & AlignMask) == 0) { > + break; > + } > + // fall through > + > + case EfiPciIoOperationBusMasterCommonBuffer: > + // > + // Check whether the host address refers to an uncached mapping. > + // > + Status = gDS->GetMemorySpaceDescriptor ( > + (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, > + &GcdDescriptor); > + if (EFI_ERROR (Status) || > + (GcdDescriptor.Attributes & (EFI_MEMORY_WB|EFI_MEMORY_WT)) != 0) { > + Bounce = TRUE; > + } > + break; > + > + default: > + ASSERT (FALSE); > + } > + } > + > + if (Bounce) { > + if (Operation == EfiPciIoOperationBusMasterCommonBuffer) { > + Status = EFI_DEVICE_ERROR; > + goto FreeMapInfo; > + } > + > + Status = NonCoherentPciIoAllocateBuffer (This, AllocateAnyPages, > + EfiBootServicesData, EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes), > + &AllocAddress, EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE); > + if (EFI_ERROR (Status)) { > + goto FreeMapInfo; > + } > + MapInfo->AllocAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress; > + if (Operation == EfiPciIoOperationBusMasterRead) { > + gBS->CopyMem (AllocAddress, HostAddress, *NumberOfBytes); > + } > + *DeviceAddress = MapInfo->AllocAddress; > + } else { > + MapInfo->AllocAddress = 0; > + *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress; > + > + // > + // We are not using a bounce buffer: the mapping is sufficiently > + // aligned to allow us to simply flush the caches. Note that cleaning > + // the caches is necessary for both data directions: > + // - for bus master read, we want the latest data to be present > + // in main memory > + // - for bus master write, we don't want any stale dirty cachelines that > + // may be written back unexpectedly, and clobber the data written to > + // main memory by the device. > + // > + mCpu->FlushDataCache (mCpu, (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, > + *NumberOfBytes, EfiCpuFlushTypeWriteBack); > + } > + > + *Mapping = MapInfo; > + return EFI_SUCCESS; > + > +FreeMapInfo: > + FreePool (MapInfo); > + > + return Status; > +} > + > +STATIC > +EFI_STATUS > +EFIAPI > +NonCoherentPciIoUnmap ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN VOID *Mapping > + ) > +{ > + NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo; > + > + if (Mapping == NULL) { > + return EFI_DEVICE_ERROR; > + } > + > + MapInfo = Mapping; > + if (MapInfo->AllocAddress != 0) { > + // > + // We are using a bounce buffer: copy back the data if necessary, > + // and free the buffer. > + // > + if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) { > + gBS->CopyMem (MapInfo->HostAddress, (VOID *)(UINTN)MapInfo->AllocAddress, > + MapInfo->NumberOfBytes); > + } > + NonCoherentPciIoFreeBuffer (This, > + EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes), > + (VOID *)(UINTN)MapInfo->AllocAddress); > + } else { > + // > + // We are *not* using a bounce buffer: if this is a bus master write, > + // we have to invalidate the caches so the CPU will see the uncached > + // data written by the device. > + // > + if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) { > + mCpu->FlushDataCache (mCpu, > + (EFI_PHYSICAL_ADDRESS)(UINTN)MapInfo->HostAddress, > + MapInfo->NumberOfBytes, EfiCpuFlushTypeInvalidate); > + } > + } > + FreePool (MapInfo); > + return EFI_SUCCESS; > +} > > STATIC > EFI_STATUS > @@ -726,12 +1046,21 @@ InitializePciIoProtocol ( > EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc; > INTN Idx; > > + InitializeListHead (&Dev->UncachedAllocationList); > + > Dev->ConfigSpace.Hdr.VendorId = PCI_ID_VENDOR_UNKNOWN; > Dev->ConfigSpace.Hdr.DeviceId = PCI_ID_DEVICE_DONTCARE; > > // Copy protocol structure > CopyMem(&Dev->PciIo, &PciIoTemplate, sizeof PciIoTemplate); > > + if (Dev->Device->DmaType == NonDiscoverableDeviceDmaTypeNonCoherent) { > + Dev->PciIo.AllocateBuffer = NonCoherentPciIoAllocateBuffer; > + Dev->PciIo.FreeBuffer = NonCoherentPciIoFreeBuffer; > + Dev->PciIo.Map = NonCoherentPciIoMap; > + Dev->PciIo.Unmap = NonCoherentPciIoUnmap; > + } > + > if (CompareGuid (Dev->Device->Type, &gEdkiiNonDiscoverableAhciDeviceGuid)) { > Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_MASS_STORAGE_AHCI; > Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_MASS_STORAGE_SATADPA; > diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h > index bc0a3d3258f9..449614862911 100644 > --- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h > +++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h > @@ -15,6 +15,8 @@ > #ifndef __NON_DISCOVERABLE_PCI_DEVICE_IO_H__ > #define __NON_DISCOVERABLE_PCI_DEVICE_IO_H__ > > +#include <PiDxe.h> > + > #include <Library/BaseMemoryLib.h> > #include <Library/DebugLib.h> > #include <Library/MemoryAllocationLib.h> > @@ -25,6 +27,7 @@ > > #include <Protocol/ComponentName.h> > #include <Protocol/NonDiscoverableDevice.h> > +#include <Protocol/Cpu.h> > #include <Protocol/PciIo.h> > > #define NON_DISCOVERABLE_PCI_DEVICE_SIG SIGNATURE_32 ('P', 'P', 'I', 'D') > @@ -38,6 +41,27 @@ > > #define PCI_MAX_BARS 6 > > +extern EFI_CPU_ARCH_PROTOCOL *mCpu; > + > +typedef struct { > + // > + // The linked-list next pointer > + // > + LIST_ENTRY List; > + // > + // The address of the uncached allocation > + // > + VOID *HostAddress; > + // > + // The number of pages in the allocation > + // > + UINTN NumPages; > + // > + // The attributes of the allocation > + // > + UINT64 Attributes; > +} NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION; > + > typedef struct { > UINT32 Signature; > // > @@ -71,6 +95,11 @@ typedef struct { > // Whether this device has been enabled > // > BOOLEAN Enabled; > + // > + // Linked list to keep track of uncached allocations performed > + // on behalf of this device > + // > + LIST_ENTRY UncachedAllocationList; > } NON_DISCOVERABLE_PCI_DEVICE; > > VOID > -- > 2.7.4 > ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v6 1/2] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA 2016-12-09 15:04 ` [PATCH v6 1/2] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA Ard Biesheuvel 2016-12-14 9:15 ` Ard Biesheuvel @ 2016-12-15 8:17 ` Ni, Ruiyu 2016-12-15 8:22 ` Ard Biesheuvel 1 sibling, 1 reply; 6+ messages in thread From: Ni, Ruiyu @ 2016-12-15 8:17 UTC (permalink / raw) To: Ard Biesheuvel, edk2-devel@lists.01.org, leif.lindholm@linaro.org Cc: Tian, Feng, Gao, Liming Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com> > -----Original Message----- > From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of > Ard Biesheuvel > Sent: Friday, December 9, 2016 11:05 PM > To: edk2-devel@lists.01.org; leif.lindholm@linaro.org; Ni, Ruiyu > <ruiyu.ni@intel.com> > Cc: Tian, Feng <feng.tian@intel.com>; Gao, Liming <liming.gao@intel.com>; > Ard Biesheuvel <ard.biesheuvel@linaro.org> > Subject: [edk2] [PATCH v6 1/2] > MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non- > coherent DMA > > Add support for non-coherent DMA, either by performing explicit cache > maintenance when DMA mappings are aligned to the CPU's DMA buffer > alignment, > or by bounce buffering via uncached mappings otherwise. > > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> > Tested-by: Marcin Wojtas <mw@semihalf.com> > --- > > MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci > DeviceDxe.c | 14 +- > > MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci > DeviceDxe.inf | 2 + > > MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci > DeviceIo.c | 329 ++++++++++++++++++++ > > MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci > DeviceIo.h | 29 ++ > 4 files changed, 367 insertions(+), 7 deletions(-) > > diff --git > a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable > PciDeviceDxe.c > b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable > PciDeviceDxe.c > index ee765d7a5d9c..0fcf2b2ec1bf 100644 > --- > a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable > PciDeviceDxe.c > +++ > b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable > PciDeviceDxe.c > @@ -16,6 +16,8 @@ > > #include <Protocol/DriverBinding.h> > > +EFI_CPU_ARCH_PROTOCOL *mCpu; > + > // > // We only support the following device types > // > @@ -69,14 +71,7 @@ NonDiscoverablePciDeviceSupported ( > return Status; > } > > - // > - // Restricted to DMA coherent for now > - // > Status = EFI_UNSUPPORTED; > - if (Device->DmaType != NonDiscoverableDeviceDmaTypeCoherent) { > - goto CloseProtocol; > - } > - > for (Idx = 0; Idx < ARRAY_SIZE (SupportedNonDiscoverableDevices); Idx++) > { > if (CompareGuid (Device->Type, SupportedNonDiscoverableDevices [Idx])) > { > Status = EFI_SUCCESS; > @@ -224,6 +219,11 @@ NonDiscoverablePciDeviceDxeEntryPoint ( > IN EFI_SYSTEM_TABLE *SystemTable > ) > { > + EFI_STATUS Status; > + > + Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID > **)&mCpu); > + ASSERT_EFI_ERROR(Status); > + > return EfiLibInstallDriverBindingComponentName2 ( > ImageHandle, > SystemTable, > diff --git > a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable > PciDeviceDxe.inf > b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable > PciDeviceDxe.inf > index 996fe310e0e3..5faa8945134c 100644 > --- > a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable > PciDeviceDxe.inf > +++ > b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable > PciDeviceDxe.inf > @@ -32,6 +32,7 @@ [Packages] > [LibraryClasses] > BaseMemoryLib > DebugLib > + DxeServicesTableLib > MemoryAllocationLib > UefiBootServicesTableLib > UefiDriverEntryPoint > @@ -40,6 +41,7 @@ [LibraryClasses] > [Protocols] > gEfiPciIoProtocolGuid ## BY_START > gEdkiiNonDiscoverableDeviceProtocolGuid ## TO_START > + gEfiCpuArchProtocolGuid ## CONSUMES > > [Guids] > gEdkiiNonDiscoverableAhciDeviceGuid > diff --git > a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable > PciDeviceIo.c > b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable > PciDeviceIo.c > index 56482e3353c0..814f7643ae4c 100644 > --- > a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable > PciDeviceIo.c > +++ > b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable > PciDeviceIo.c > @@ -15,6 +15,8 @@ > > #include "NonDiscoverablePciDeviceIo.h" > > +#include <Library/DxeServicesTableLib.h> > + > #include <IndustryStandard/Acpi.h> > > #include <Protocol/PciRootBridgeIo.h> > @@ -537,6 +539,324 @@ CoherentPciIoFreeBuffer ( > return EFI_SUCCESS; > } > > +STATIC > +EFI_STATUS > +EFIAPI > +NonCoherentPciIoFreeBuffer ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN UINTN Pages, > + IN VOID *HostAddress > + ) > +{ > + NON_DISCOVERABLE_PCI_DEVICE *Dev; > + LIST_ENTRY *Entry; > + EFI_STATUS Status; > + NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *Alloc; > + BOOLEAN Found; > + > + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This); > + > + Found = FALSE; > + > + // > + // Find the uncached allocation list entry associated > + // with this allocation > + // > + for (Entry = Dev->UncachedAllocationList.ForwardLink; > + Entry != &Dev->UncachedAllocationList; > + Entry = Entry->ForwardLink) { > + > + Alloc = BASE_CR (Entry, > NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION, List); > + if (Alloc->HostAddress == HostAddress && Alloc->NumPages == Pages) { > + // > + // We are freeing the exact allocation we were given > + // before by AllocateBuffer() > + // > + Found = TRUE; > + break; > + } > + } > + > + if (!Found) { > + ASSERT_EFI_ERROR (EFI_NOT_FOUND); > + return EFI_NOT_FOUND; > + } > + > + RemoveEntryList (&Alloc->List); > + > + Status = gDS->SetMemorySpaceAttributes ( > + (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, > + EFI_PAGES_TO_SIZE (Pages), > + Alloc->Attributes); > + if (EFI_ERROR (Status)) { > + goto FreeAlloc; > + } > + > + // > + // If we fail to restore the original attributes, it is better to leak the > + // memory than to return it to the heap > + // > + FreePages (HostAddress, Pages); > + > +FreeAlloc: > + FreePool (Alloc); > + return Status; > +} > + > +STATIC > +EFI_STATUS > +EFIAPI > +NonCoherentPciIoAllocateBuffer ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN EFI_ALLOCATE_TYPE Type, > + IN EFI_MEMORY_TYPE MemoryType, > + IN UINTN Pages, > + OUT VOID **HostAddress, > + IN UINT64 Attributes > + ) > +{ > + NON_DISCOVERABLE_PCI_DEVICE *Dev; > + EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor; > + EFI_STATUS Status; > + UINT64 MemType; > + NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *Alloc; > + VOID *AllocAddress; > + > + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This); > + > + Status = CoherentPciIoAllocateBuffer (This, Type, MemoryType, Pages, > + &AllocAddress, Attributes); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status = gDS->GetMemorySpaceDescriptor ( > + (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress, > + &GcdDescriptor); > + if (EFI_ERROR (Status)) { > + goto FreeBuffer; > + } > + > + if ((GcdDescriptor.Capabilities & (EFI_MEMORY_WC | EFI_MEMORY_UC)) > == 0) { > + Status = EFI_UNSUPPORTED; > + goto FreeBuffer; > + } > + > + // > + // Set the preferred memory attributes > + // > + if ((Attributes & EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE) != 0 || > + (GcdDescriptor.Capabilities & EFI_MEMORY_UC) == 0) { > + // > + // Use write combining if it was requested, or if it is the only > + // type supported by the region. > + // > + MemType = EFI_MEMORY_WC; > + } else { > + MemType = EFI_MEMORY_UC; > + } > + > + Alloc = AllocatePool (sizeof *Alloc); > + if (Alloc == NULL) { > + goto FreeBuffer; > + } > + > + Alloc->HostAddress = AllocAddress; > + Alloc->NumPages = Pages; > + Alloc->Attributes = GcdDescriptor.Attributes; > + > + // > + // Record this allocation in the linked list, so we > + // can restore the memory space attributes later > + // > + InsertHeadList (&Dev->UncachedAllocationList, &Alloc->List); > + > + Status = gDS->SetMemorySpaceAttributes ( > + (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress, > + EFI_PAGES_TO_SIZE (Pages), > + MemType); > + if (EFI_ERROR (Status)) { > + goto RemoveList; > + } > + > + Status = mCpu->FlushDataCache ( > + mCpu, > + (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress, > + EFI_PAGES_TO_SIZE (Pages), > + EfiCpuFlushTypeInvalidate); > + if (EFI_ERROR (Status)) { > + goto RemoveList; > + } > + > + *HostAddress = AllocAddress; > + > + return EFI_SUCCESS; > + > +RemoveList: > + RemoveEntryList (&Alloc->List); > + FreePool (Alloc); > + > +FreeBuffer: > + CoherentPciIoFreeBuffer (This, Pages, AllocAddress); > + return Status; > +} > + > +STATIC > +EFI_STATUS > +EFIAPI > +NonCoherentPciIoMap ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN EFI_PCI_IO_PROTOCOL_OPERATION Operation, > + IN VOID *HostAddress, > + IN OUT UINTN *NumberOfBytes, > + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, > + OUT VOID **Mapping > + ) > +{ > + NON_DISCOVERABLE_PCI_DEVICE *Dev; > + EFI_STATUS Status; > + NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo; > + UINTN AlignMask; > + VOID *AllocAddress; > + EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor; > + BOOLEAN Bounce; > + > + MapInfo = AllocatePool (sizeof *MapInfo); > + if (MapInfo == NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + MapInfo->HostAddress = HostAddress; > + MapInfo->Operation = Operation; > + MapInfo->NumberOfBytes = *NumberOfBytes; > + > + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This); > + > + // > + // If this device does not support 64-bit DMA addressing, we need to > allocate > + // a bounce buffer and copy over the data in case HostAddress >= 4 GB. > + // > + Bounce = ((Dev->Attributes & > EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0 && > + (UINTN)HostAddress + *NumberOfBytes > SIZE_4GB); > + > + if (!Bounce) { > + switch (Operation) { > + case EfiPciIoOperationBusMasterRead: > + case EfiPciIoOperationBusMasterWrite: > + // > + // For streaming DMA, it is sufficient if the buffer is aligned to > + // the CPUs DMA buffer alignment. > + // > + AlignMask = mCpu->DmaBufferAlignment - 1; > + if ((((UINTN) HostAddress | *NumberOfBytes) & AlignMask) == 0) { > + break; > + } > + // fall through > + > + case EfiPciIoOperationBusMasterCommonBuffer: > + // > + // Check whether the host address refers to an uncached mapping. > + // > + Status = gDS->GetMemorySpaceDescriptor ( > + (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, > + &GcdDescriptor); > + if (EFI_ERROR (Status) || > + (GcdDescriptor.Attributes & > (EFI_MEMORY_WB|EFI_MEMORY_WT)) != 0) { > + Bounce = TRUE; > + } > + break; > + > + default: > + ASSERT (FALSE); > + } > + } > + > + if (Bounce) { > + if (Operation == EfiPciIoOperationBusMasterCommonBuffer) { > + Status = EFI_DEVICE_ERROR; > + goto FreeMapInfo; > + } > + > + Status = NonCoherentPciIoAllocateBuffer (This, AllocateAnyPages, > + EfiBootServicesData, EFI_SIZE_TO_PAGES (MapInfo- > >NumberOfBytes), > + &AllocAddress, EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE); > + if (EFI_ERROR (Status)) { > + goto FreeMapInfo; > + } > + MapInfo->AllocAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress; > + if (Operation == EfiPciIoOperationBusMasterRead) { > + gBS->CopyMem (AllocAddress, HostAddress, *NumberOfBytes); > + } > + *DeviceAddress = MapInfo->AllocAddress; > + } else { > + MapInfo->AllocAddress = 0; > + *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress; > + > + // > + // We are not using a bounce buffer: the mapping is sufficiently > + // aligned to allow us to simply flush the caches. Note that cleaning > + // the caches is necessary for both data directions: > + // - for bus master read, we want the latest data to be present > + // in main memory > + // - for bus master write, we don't want any stale dirty cachelines that > + // may be written back unexpectedly, and clobber the data written to > + // main memory by the device. > + // > + mCpu->FlushDataCache (mCpu, > (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, > + *NumberOfBytes, EfiCpuFlushTypeWriteBack); > + } > + > + *Mapping = MapInfo; > + return EFI_SUCCESS; > + > +FreeMapInfo: > + FreePool (MapInfo); > + > + return Status; > +} > + > +STATIC > +EFI_STATUS > +EFIAPI > +NonCoherentPciIoUnmap ( > + IN EFI_PCI_IO_PROTOCOL *This, > + IN VOID *Mapping > + ) > +{ > + NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo; > + > + if (Mapping == NULL) { > + return EFI_DEVICE_ERROR; > + } > + > + MapInfo = Mapping; > + if (MapInfo->AllocAddress != 0) { > + // > + // We are using a bounce buffer: copy back the data if necessary, > + // and free the buffer. > + // > + if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) { > + gBS->CopyMem (MapInfo->HostAddress, (VOID *)(UINTN)MapInfo- > >AllocAddress, > + MapInfo->NumberOfBytes); > + } > + NonCoherentPciIoFreeBuffer (This, > + EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes), > + (VOID *)(UINTN)MapInfo->AllocAddress); > + } else { > + // > + // We are *not* using a bounce buffer: if this is a bus master write, > + // we have to invalidate the caches so the CPU will see the uncached > + // data written by the device. > + // > + if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) { > + mCpu->FlushDataCache (mCpu, > + (EFI_PHYSICAL_ADDRESS)(UINTN)MapInfo->HostAddress, > + MapInfo->NumberOfBytes, EfiCpuFlushTypeInvalidate); > + } > + } > + FreePool (MapInfo); > + return EFI_SUCCESS; > +} > > STATIC > EFI_STATUS > @@ -726,12 +1046,21 @@ InitializePciIoProtocol ( > EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc; > INTN Idx; > > + InitializeListHead (&Dev->UncachedAllocationList); > + > Dev->ConfigSpace.Hdr.VendorId = PCI_ID_VENDOR_UNKNOWN; > Dev->ConfigSpace.Hdr.DeviceId = PCI_ID_DEVICE_DONTCARE; > > // Copy protocol structure > CopyMem(&Dev->PciIo, &PciIoTemplate, sizeof PciIoTemplate); > > + if (Dev->Device->DmaType == > NonDiscoverableDeviceDmaTypeNonCoherent) { > + Dev->PciIo.AllocateBuffer = NonCoherentPciIoAllocateBuffer; > + Dev->PciIo.FreeBuffer = NonCoherentPciIoFreeBuffer; > + Dev->PciIo.Map = NonCoherentPciIoMap; > + Dev->PciIo.Unmap = NonCoherentPciIoUnmap; > + } > + > if (CompareGuid (Dev->Device->Type, > &gEdkiiNonDiscoverableAhciDeviceGuid)) { > Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_MASS_STORAGE_AHCI; > Dev->ConfigSpace.Hdr.ClassCode[1] = > PCI_CLASS_MASS_STORAGE_SATADPA; > diff --git > a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable > PciDeviceIo.h > b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable > PciDeviceIo.h > index bc0a3d3258f9..449614862911 100644 > --- > a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable > PciDeviceIo.h > +++ > b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable > PciDeviceIo.h > @@ -15,6 +15,8 @@ > #ifndef __NON_DISCOVERABLE_PCI_DEVICE_IO_H__ > #define __NON_DISCOVERABLE_PCI_DEVICE_IO_H__ > > +#include <PiDxe.h> > + > #include <Library/BaseMemoryLib.h> > #include <Library/DebugLib.h> > #include <Library/MemoryAllocationLib.h> > @@ -25,6 +27,7 @@ > > #include <Protocol/ComponentName.h> > #include <Protocol/NonDiscoverableDevice.h> > +#include <Protocol/Cpu.h> > #include <Protocol/PciIo.h> > > #define NON_DISCOVERABLE_PCI_DEVICE_SIG SIGNATURE_32 ('P', 'P', 'I', > 'D') > @@ -38,6 +41,27 @@ > > #define PCI_MAX_BARS 6 > > +extern EFI_CPU_ARCH_PROTOCOL *mCpu; > + > +typedef struct { > + // > + // The linked-list next pointer > + // > + LIST_ENTRY List; > + // > + // The address of the uncached allocation > + // > + VOID *HostAddress; > + // > + // The number of pages in the allocation > + // > + UINTN NumPages; > + // > + // The attributes of the allocation > + // > + UINT64 Attributes; > +} NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION; > + > typedef struct { > UINT32 Signature; > // > @@ -71,6 +95,11 @@ typedef struct { > // Whether this device has been enabled > // > BOOLEAN Enabled; > + // > + // Linked list to keep track of uncached allocations performed > + // on behalf of this device > + // > + LIST_ENTRY UncachedAllocationList; > } NON_DISCOVERABLE_PCI_DEVICE; > > VOID > -- > 2.7.4 > > _______________________________________________ > edk2-devel mailing list > edk2-devel@lists.01.org > https://lists.01.org/mailman/listinfo/edk2-devel ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v6 1/2] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA 2016-12-15 8:17 ` Ni, Ruiyu @ 2016-12-15 8:22 ` Ard Biesheuvel 0 siblings, 0 replies; 6+ messages in thread From: Ard Biesheuvel @ 2016-12-15 8:22 UTC (permalink / raw) To: Ni, Ruiyu Cc: edk2-devel@lists.01.org, leif.lindholm@linaro.org, Tian, Feng, Gao, Liming On 15 December 2016 at 08:17, Ni, Ruiyu <ruiyu.ni@intel.com> wrote: > > > Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com> Pushed, thanks. >> -----Original Message----- >> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of >> Ard Biesheuvel >> Sent: Friday, December 9, 2016 11:05 PM >> To: edk2-devel@lists.01.org; leif.lindholm@linaro.org; Ni, Ruiyu >> <ruiyu.ni@intel.com> >> Cc: Tian, Feng <feng.tian@intel.com>; Gao, Liming <liming.gao@intel.com>; >> Ard Biesheuvel <ard.biesheuvel@linaro.org> >> Subject: [edk2] [PATCH v6 1/2] >> MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non- >> coherent DMA >> >> Add support for non-coherent DMA, either by performing explicit cache >> maintenance when DMA mappings are aligned to the CPU's DMA buffer >> alignment, >> or by bounce buffering via uncached mappings otherwise. >> >> Contributed-under: TianoCore Contribution Agreement 1.0 >> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> >> Tested-by: Marcin Wojtas <mw@semihalf.com> >> --- >> >> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci >> DeviceDxe.c | 14 +- >> >> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci >> DeviceDxe.inf | 2 + >> >> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci >> DeviceIo.c | 329 ++++++++++++++++++++ >> >> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci >> DeviceIo.h | 29 ++ >> 4 files changed, 367 insertions(+), 7 deletions(-) >> >> diff --git >> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable >> PciDeviceDxe.c >> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable >> PciDeviceDxe.c >> index ee765d7a5d9c..0fcf2b2ec1bf 100644 >> --- >> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable >> PciDeviceDxe.c >> +++ >> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable >> PciDeviceDxe.c >> @@ -16,6 +16,8 @@ >> >> #include <Protocol/DriverBinding.h> >> >> +EFI_CPU_ARCH_PROTOCOL *mCpu; >> + >> // >> // We only support the following device types >> // >> @@ -69,14 +71,7 @@ NonDiscoverablePciDeviceSupported ( >> return Status; >> } >> >> - // >> - // Restricted to DMA coherent for now >> - // >> Status = EFI_UNSUPPORTED; >> - if (Device->DmaType != NonDiscoverableDeviceDmaTypeCoherent) { >> - goto CloseProtocol; >> - } >> - >> for (Idx = 0; Idx < ARRAY_SIZE (SupportedNonDiscoverableDevices); Idx++) >> { >> if (CompareGuid (Device->Type, SupportedNonDiscoverableDevices [Idx])) >> { >> Status = EFI_SUCCESS; >> @@ -224,6 +219,11 @@ NonDiscoverablePciDeviceDxeEntryPoint ( >> IN EFI_SYSTEM_TABLE *SystemTable >> ) >> { >> + EFI_STATUS Status; >> + >> + Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID >> **)&mCpu); >> + ASSERT_EFI_ERROR(Status); >> + >> return EfiLibInstallDriverBindingComponentName2 ( >> ImageHandle, >> SystemTable, >> diff --git >> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable >> PciDeviceDxe.inf >> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable >> PciDeviceDxe.inf >> index 996fe310e0e3..5faa8945134c 100644 >> --- >> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable >> PciDeviceDxe.inf >> +++ >> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable >> PciDeviceDxe.inf >> @@ -32,6 +32,7 @@ [Packages] >> [LibraryClasses] >> BaseMemoryLib >> DebugLib >> + DxeServicesTableLib >> MemoryAllocationLib >> UefiBootServicesTableLib >> UefiDriverEntryPoint >> @@ -40,6 +41,7 @@ [LibraryClasses] >> [Protocols] >> gEfiPciIoProtocolGuid ## BY_START >> gEdkiiNonDiscoverableDeviceProtocolGuid ## TO_START >> + gEfiCpuArchProtocolGuid ## CONSUMES >> >> [Guids] >> gEdkiiNonDiscoverableAhciDeviceGuid >> diff --git >> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable >> PciDeviceIo.c >> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable >> PciDeviceIo.c >> index 56482e3353c0..814f7643ae4c 100644 >> --- >> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable >> PciDeviceIo.c >> +++ >> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable >> PciDeviceIo.c >> @@ -15,6 +15,8 @@ >> >> #include "NonDiscoverablePciDeviceIo.h" >> >> +#include <Library/DxeServicesTableLib.h> >> + >> #include <IndustryStandard/Acpi.h> >> >> #include <Protocol/PciRootBridgeIo.h> >> @@ -537,6 +539,324 @@ CoherentPciIoFreeBuffer ( >> return EFI_SUCCESS; >> } >> >> +STATIC >> +EFI_STATUS >> +EFIAPI >> +NonCoherentPciIoFreeBuffer ( >> + IN EFI_PCI_IO_PROTOCOL *This, >> + IN UINTN Pages, >> + IN VOID *HostAddress >> + ) >> +{ >> + NON_DISCOVERABLE_PCI_DEVICE *Dev; >> + LIST_ENTRY *Entry; >> + EFI_STATUS Status; >> + NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *Alloc; >> + BOOLEAN Found; >> + >> + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This); >> + >> + Found = FALSE; >> + >> + // >> + // Find the uncached allocation list entry associated >> + // with this allocation >> + // >> + for (Entry = Dev->UncachedAllocationList.ForwardLink; >> + Entry != &Dev->UncachedAllocationList; >> + Entry = Entry->ForwardLink) { >> + >> + Alloc = BASE_CR (Entry, >> NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION, List); >> + if (Alloc->HostAddress == HostAddress && Alloc->NumPages == Pages) { >> + // >> + // We are freeing the exact allocation we were given >> + // before by AllocateBuffer() >> + // >> + Found = TRUE; >> + break; >> + } >> + } >> + >> + if (!Found) { >> + ASSERT_EFI_ERROR (EFI_NOT_FOUND); >> + return EFI_NOT_FOUND; >> + } >> + >> + RemoveEntryList (&Alloc->List); >> + >> + Status = gDS->SetMemorySpaceAttributes ( >> + (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, >> + EFI_PAGES_TO_SIZE (Pages), >> + Alloc->Attributes); >> + if (EFI_ERROR (Status)) { >> + goto FreeAlloc; >> + } >> + >> + // >> + // If we fail to restore the original attributes, it is better to leak the >> + // memory than to return it to the heap >> + // >> + FreePages (HostAddress, Pages); >> + >> +FreeAlloc: >> + FreePool (Alloc); >> + return Status; >> +} >> + >> +STATIC >> +EFI_STATUS >> +EFIAPI >> +NonCoherentPciIoAllocateBuffer ( >> + IN EFI_PCI_IO_PROTOCOL *This, >> + IN EFI_ALLOCATE_TYPE Type, >> + IN EFI_MEMORY_TYPE MemoryType, >> + IN UINTN Pages, >> + OUT VOID **HostAddress, >> + IN UINT64 Attributes >> + ) >> +{ >> + NON_DISCOVERABLE_PCI_DEVICE *Dev; >> + EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor; >> + EFI_STATUS Status; >> + UINT64 MemType; >> + NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *Alloc; >> + VOID *AllocAddress; >> + >> + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This); >> + >> + Status = CoherentPciIoAllocateBuffer (This, Type, MemoryType, Pages, >> + &AllocAddress, Attributes); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + Status = gDS->GetMemorySpaceDescriptor ( >> + (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress, >> + &GcdDescriptor); >> + if (EFI_ERROR (Status)) { >> + goto FreeBuffer; >> + } >> + >> + if ((GcdDescriptor.Capabilities & (EFI_MEMORY_WC | EFI_MEMORY_UC)) >> == 0) { >> + Status = EFI_UNSUPPORTED; >> + goto FreeBuffer; >> + } >> + >> + // >> + // Set the preferred memory attributes >> + // >> + if ((Attributes & EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE) != 0 || >> + (GcdDescriptor.Capabilities & EFI_MEMORY_UC) == 0) { >> + // >> + // Use write combining if it was requested, or if it is the only >> + // type supported by the region. >> + // >> + MemType = EFI_MEMORY_WC; >> + } else { >> + MemType = EFI_MEMORY_UC; >> + } >> + >> + Alloc = AllocatePool (sizeof *Alloc); >> + if (Alloc == NULL) { >> + goto FreeBuffer; >> + } >> + >> + Alloc->HostAddress = AllocAddress; >> + Alloc->NumPages = Pages; >> + Alloc->Attributes = GcdDescriptor.Attributes; >> + >> + // >> + // Record this allocation in the linked list, so we >> + // can restore the memory space attributes later >> + // >> + InsertHeadList (&Dev->UncachedAllocationList, &Alloc->List); >> + >> + Status = gDS->SetMemorySpaceAttributes ( >> + (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress, >> + EFI_PAGES_TO_SIZE (Pages), >> + MemType); >> + if (EFI_ERROR (Status)) { >> + goto RemoveList; >> + } >> + >> + Status = mCpu->FlushDataCache ( >> + mCpu, >> + (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress, >> + EFI_PAGES_TO_SIZE (Pages), >> + EfiCpuFlushTypeInvalidate); >> + if (EFI_ERROR (Status)) { >> + goto RemoveList; >> + } >> + >> + *HostAddress = AllocAddress; >> + >> + return EFI_SUCCESS; >> + >> +RemoveList: >> + RemoveEntryList (&Alloc->List); >> + FreePool (Alloc); >> + >> +FreeBuffer: >> + CoherentPciIoFreeBuffer (This, Pages, AllocAddress); >> + return Status; >> +} >> + >> +STATIC >> +EFI_STATUS >> +EFIAPI >> +NonCoherentPciIoMap ( >> + IN EFI_PCI_IO_PROTOCOL *This, >> + IN EFI_PCI_IO_PROTOCOL_OPERATION Operation, >> + IN VOID *HostAddress, >> + IN OUT UINTN *NumberOfBytes, >> + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, >> + OUT VOID **Mapping >> + ) >> +{ >> + NON_DISCOVERABLE_PCI_DEVICE *Dev; >> + EFI_STATUS Status; >> + NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo; >> + UINTN AlignMask; >> + VOID *AllocAddress; >> + EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor; >> + BOOLEAN Bounce; >> + >> + MapInfo = AllocatePool (sizeof *MapInfo); >> + if (MapInfo == NULL) { >> + return EFI_OUT_OF_RESOURCES; >> + } >> + >> + MapInfo->HostAddress = HostAddress; >> + MapInfo->Operation = Operation; >> + MapInfo->NumberOfBytes = *NumberOfBytes; >> + >> + Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This); >> + >> + // >> + // If this device does not support 64-bit DMA addressing, we need to >> allocate >> + // a bounce buffer and copy over the data in case HostAddress >= 4 GB. >> + // >> + Bounce = ((Dev->Attributes & >> EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0 && >> + (UINTN)HostAddress + *NumberOfBytes > SIZE_4GB); >> + >> + if (!Bounce) { >> + switch (Operation) { >> + case EfiPciIoOperationBusMasterRead: >> + case EfiPciIoOperationBusMasterWrite: >> + // >> + // For streaming DMA, it is sufficient if the buffer is aligned to >> + // the CPUs DMA buffer alignment. >> + // >> + AlignMask = mCpu->DmaBufferAlignment - 1; >> + if ((((UINTN) HostAddress | *NumberOfBytes) & AlignMask) == 0) { >> + break; >> + } >> + // fall through >> + >> + case EfiPciIoOperationBusMasterCommonBuffer: >> + // >> + // Check whether the host address refers to an uncached mapping. >> + // >> + Status = gDS->GetMemorySpaceDescriptor ( >> + (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, >> + &GcdDescriptor); >> + if (EFI_ERROR (Status) || >> + (GcdDescriptor.Attributes & >> (EFI_MEMORY_WB|EFI_MEMORY_WT)) != 0) { >> + Bounce = TRUE; >> + } >> + break; >> + >> + default: >> + ASSERT (FALSE); >> + } >> + } >> + >> + if (Bounce) { >> + if (Operation == EfiPciIoOperationBusMasterCommonBuffer) { >> + Status = EFI_DEVICE_ERROR; >> + goto FreeMapInfo; >> + } >> + >> + Status = NonCoherentPciIoAllocateBuffer (This, AllocateAnyPages, >> + EfiBootServicesData, EFI_SIZE_TO_PAGES (MapInfo- >> >NumberOfBytes), >> + &AllocAddress, EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE); >> + if (EFI_ERROR (Status)) { >> + goto FreeMapInfo; >> + } >> + MapInfo->AllocAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress; >> + if (Operation == EfiPciIoOperationBusMasterRead) { >> + gBS->CopyMem (AllocAddress, HostAddress, *NumberOfBytes); >> + } >> + *DeviceAddress = MapInfo->AllocAddress; >> + } else { >> + MapInfo->AllocAddress = 0; >> + *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress; >> + >> + // >> + // We are not using a bounce buffer: the mapping is sufficiently >> + // aligned to allow us to simply flush the caches. Note that cleaning >> + // the caches is necessary for both data directions: >> + // - for bus master read, we want the latest data to be present >> + // in main memory >> + // - for bus master write, we don't want any stale dirty cachelines that >> + // may be written back unexpectedly, and clobber the data written to >> + // main memory by the device. >> + // >> + mCpu->FlushDataCache (mCpu, >> (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, >> + *NumberOfBytes, EfiCpuFlushTypeWriteBack); >> + } >> + >> + *Mapping = MapInfo; >> + return EFI_SUCCESS; >> + >> +FreeMapInfo: >> + FreePool (MapInfo); >> + >> + return Status; >> +} >> + >> +STATIC >> +EFI_STATUS >> +EFIAPI >> +NonCoherentPciIoUnmap ( >> + IN EFI_PCI_IO_PROTOCOL *This, >> + IN VOID *Mapping >> + ) >> +{ >> + NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO *MapInfo; >> + >> + if (Mapping == NULL) { >> + return EFI_DEVICE_ERROR; >> + } >> + >> + MapInfo = Mapping; >> + if (MapInfo->AllocAddress != 0) { >> + // >> + // We are using a bounce buffer: copy back the data if necessary, >> + // and free the buffer. >> + // >> + if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) { >> + gBS->CopyMem (MapInfo->HostAddress, (VOID *)(UINTN)MapInfo- >> >AllocAddress, >> + MapInfo->NumberOfBytes); >> + } >> + NonCoherentPciIoFreeBuffer (This, >> + EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes), >> + (VOID *)(UINTN)MapInfo->AllocAddress); >> + } else { >> + // >> + // We are *not* using a bounce buffer: if this is a bus master write, >> + // we have to invalidate the caches so the CPU will see the uncached >> + // data written by the device. >> + // >> + if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) { >> + mCpu->FlushDataCache (mCpu, >> + (EFI_PHYSICAL_ADDRESS)(UINTN)MapInfo->HostAddress, >> + MapInfo->NumberOfBytes, EfiCpuFlushTypeInvalidate); >> + } >> + } >> + FreePool (MapInfo); >> + return EFI_SUCCESS; >> +} >> >> STATIC >> EFI_STATUS >> @@ -726,12 +1046,21 @@ InitializePciIoProtocol ( >> EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc; >> INTN Idx; >> >> + InitializeListHead (&Dev->UncachedAllocationList); >> + >> Dev->ConfigSpace.Hdr.VendorId = PCI_ID_VENDOR_UNKNOWN; >> Dev->ConfigSpace.Hdr.DeviceId = PCI_ID_DEVICE_DONTCARE; >> >> // Copy protocol structure >> CopyMem(&Dev->PciIo, &PciIoTemplate, sizeof PciIoTemplate); >> >> + if (Dev->Device->DmaType == >> NonDiscoverableDeviceDmaTypeNonCoherent) { >> + Dev->PciIo.AllocateBuffer = NonCoherentPciIoAllocateBuffer; >> + Dev->PciIo.FreeBuffer = NonCoherentPciIoFreeBuffer; >> + Dev->PciIo.Map = NonCoherentPciIoMap; >> + Dev->PciIo.Unmap = NonCoherentPciIoUnmap; >> + } >> + >> if (CompareGuid (Dev->Device->Type, >> &gEdkiiNonDiscoverableAhciDeviceGuid)) { >> Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_MASS_STORAGE_AHCI; >> Dev->ConfigSpace.Hdr.ClassCode[1] = >> PCI_CLASS_MASS_STORAGE_SATADPA; >> diff --git >> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable >> PciDeviceIo.h >> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable >> PciDeviceIo.h >> index bc0a3d3258f9..449614862911 100644 >> --- >> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable >> PciDeviceIo.h >> +++ >> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable >> PciDeviceIo.h >> @@ -15,6 +15,8 @@ >> #ifndef __NON_DISCOVERABLE_PCI_DEVICE_IO_H__ >> #define __NON_DISCOVERABLE_PCI_DEVICE_IO_H__ >> >> +#include <PiDxe.h> >> + >> #include <Library/BaseMemoryLib.h> >> #include <Library/DebugLib.h> >> #include <Library/MemoryAllocationLib.h> >> @@ -25,6 +27,7 @@ >> >> #include <Protocol/ComponentName.h> >> #include <Protocol/NonDiscoverableDevice.h> >> +#include <Protocol/Cpu.h> >> #include <Protocol/PciIo.h> >> >> #define NON_DISCOVERABLE_PCI_DEVICE_SIG SIGNATURE_32 ('P', 'P', 'I', >> 'D') >> @@ -38,6 +41,27 @@ >> >> #define PCI_MAX_BARS 6 >> >> +extern EFI_CPU_ARCH_PROTOCOL *mCpu; >> + >> +typedef struct { >> + // >> + // The linked-list next pointer >> + // >> + LIST_ENTRY List; >> + // >> + // The address of the uncached allocation >> + // >> + VOID *HostAddress; >> + // >> + // The number of pages in the allocation >> + // >> + UINTN NumPages; >> + // >> + // The attributes of the allocation >> + // >> + UINT64 Attributes; >> +} NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION; >> + >> typedef struct { >> UINT32 Signature; >> // >> @@ -71,6 +95,11 @@ typedef struct { >> // Whether this device has been enabled >> // >> BOOLEAN Enabled; >> + // >> + // Linked list to keep track of uncached allocations performed >> + // on behalf of this device >> + // >> + LIST_ENTRY UncachedAllocationList; >> } NON_DISCOVERABLE_PCI_DEVICE; >> >> VOID >> -- >> 2.7.4 >> >> _______________________________________________ >> edk2-devel mailing list >> edk2-devel@lists.01.org >> https://lists.01.org/mailman/listinfo/edk2-devel ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v6 2/2] Omap35xxPkg/PciEmulation: port to new non-discoverable device infrastructure 2016-12-09 15:04 [PATCH v6 0/2] MdeModulePkg/NonDiscoverablePciDeviceDxe: non-coherent DMA support Ard Biesheuvel 2016-12-09 15:04 ` [PATCH v6 1/2] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA Ard Biesheuvel @ 2016-12-09 15:04 ` Ard Biesheuvel 1 sibling, 0 replies; 6+ messages in thread From: Ard Biesheuvel @ 2016-12-09 15:04 UTC (permalink / raw) To: edk2-devel, leif.lindholm, ruiyu.ni; +Cc: feng.tian, liming.gao, Ard Biesheuvel Move to the new non-discoverable device protocols for wiring the PCI based EHCI controller driver to the non-discoverable EHCI controller found on the OMAP 3530. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> --- BeagleBoardPkg/BeagleBoardPkg.dsc | 2 + BeagleBoardPkg/BeagleBoardPkg.fdf | 1 + Omap35xxPkg/Omap35xxPkg.dsc | 2 +- Omap35xxPkg/PciEmulation/PciEmulation.c | 578 +------------------- Omap35xxPkg/PciEmulation/PciEmulation.h | 292 ---------- Omap35xxPkg/PciEmulation/PciEmulation.inf | 16 +- Omap35xxPkg/PciEmulation/PciRootBridgeIo.c | 306 ----------- 7 files changed, 36 insertions(+), 1161 deletions(-) diff --git a/BeagleBoardPkg/BeagleBoardPkg.dsc b/BeagleBoardPkg/BeagleBoardPkg.dsc index 69d3c5f1841b..b24db6cbfb04 100644 --- a/BeagleBoardPkg/BeagleBoardPkg.dsc +++ b/BeagleBoardPkg/BeagleBoardPkg.dsc @@ -185,6 +185,7 @@ [LibraryClasses.common.DXE_DRIVER] DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf + NonDiscoverableDeviceRegistrationLib|MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf [LibraryClasses.common.UEFI_APPLICATION] ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf @@ -447,6 +448,7 @@ [Components.common] # USB # Omap35xxPkg/PciEmulation/PciEmulation.inf + MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf { <PcdsFixedAtBuild> diff --git a/BeagleBoardPkg/BeagleBoardPkg.fdf b/BeagleBoardPkg/BeagleBoardPkg.fdf index 42e097f64118..3d00355fff84 100644 --- a/BeagleBoardPkg/BeagleBoardPkg.fdf +++ b/BeagleBoardPkg/BeagleBoardPkg.fdf @@ -167,6 +167,7 @@ [FV.FvMain] # INF Omap35xxPkg/PciEmulation/PciEmulation.inf + INF MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf INF MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf diff --git a/Omap35xxPkg/Omap35xxPkg.dsc b/Omap35xxPkg/Omap35xxPkg.dsc index 436c10bb7f2f..9395570ccaa3 100644 --- a/Omap35xxPkg/Omap35xxPkg.dsc +++ b/Omap35xxPkg/Omap35xxPkg.dsc @@ -80,7 +80,7 @@ [LibraryClasses.common] [LibraryClasses.common.DXE_DRIVER] DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf - + NonDiscoverableDeviceRegistrationLib|MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf [LibraryClasses.ARM] NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf diff --git a/Omap35xxPkg/PciEmulation/PciEmulation.c b/Omap35xxPkg/PciEmulation/PciEmulation.c index 17ea03ccf486..d17646a9ed58 100644 --- a/Omap35xxPkg/PciEmulation/PciEmulation.c +++ b/Omap35xxPkg/PciEmulation/PciEmulation.c @@ -1,6 +1,7 @@ /** @file Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR> + Copyright (c) 2016, Linaro, Ltd. All rights reserved.<BR> This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -12,49 +13,27 @@ **/ -#include "PciEmulation.h" +#include <PiDxe.h> -EMBEDDED_EXTERNAL_DEVICE *gTPS65950; - -#define HOST_CONTROLLER_OPERATION_REG_SIZE 0x44 +#include <Library/BaseLib.h> +#include <Library/DebugLib.h> +#include <Library/IoLib.h> +#include <Library/NonDiscoverableDeviceRegistrationLib.h> +#include <Library/UefiBootServicesTableLib.h> -typedef struct { - ACPI_HID_DEVICE_PATH AcpiDevicePath; - PCI_DEVICE_PATH PciDevicePath; - EFI_DEVICE_PATH_PROTOCOL EndDevicePath; -} EFI_PCI_IO_DEVICE_PATH; +#include <Protocol/EmbeddedExternalDevice.h> -typedef struct { - UINT32 Signature; - EFI_PCI_IO_DEVICE_PATH DevicePath; - EFI_PCI_IO_PROTOCOL PciIoProtocol; - PCI_TYPE00 *ConfigSpace; - PCI_ROOT_BRIDGE RootBridge; - UINTN Segment; -} EFI_PCI_IO_PRIVATE_DATA; +#include <TPS65950.h> +#include <Omap3530/Omap3530.h> -#define EFI_PCI_IO_PRIVATE_DATA_SIGNATURE SIGNATURE_32('p', 'c', 'i', 'o') -#define EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(a) CR(a, EFI_PCI_IO_PRIVATE_DATA, PciIoProtocol, EFI_PCI_IO_PRIVATE_DATA_SIGNATURE) +EMBEDDED_EXTERNAL_DEVICE *gTPS65950; -EFI_PCI_IO_DEVICE_PATH PciIoDevicePathTemplate = -{ - { - { ACPI_DEVICE_PATH, ACPI_DP, { sizeof (ACPI_HID_DEVICE_PATH), 0 } }, - EISA_PNP_ID(0x0A03), // HID - 0 // UID - }, - { - { HARDWARE_DEVICE_PATH, HW_PCI_DP, { sizeof (PCI_DEVICE_PATH), 0 } }, - 0, - 0 - }, - { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0} } -}; +#define HOST_CONTROLLER_OPERATION_REG_SIZE 0x44 STATIC -VOID +EFI_STATUS ConfigureUSBHost ( - VOID + NON_DISCOVERABLE_DEVICE *Device ) { EFI_STATUS Status; @@ -103,454 +82,10 @@ ConfigureUSBHost ( Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID3, LEDEN), 1, &Data); ASSERT_EFI_ERROR (Status); -} - - -EFI_STATUS -PciIoPollMem ( - IN EFI_PCI_IO_PROTOCOL *This, - IN EFI_PCI_IO_PROTOCOL_WIDTH Width, - IN UINT8 BarIndex, - IN UINT64 Offset, - IN UINT64 Mask, - IN UINT64 Value, - IN UINT64 Delay, - OUT UINT64 *Result - ) -{ - ASSERT (FALSE); - return EFI_UNSUPPORTED; -} - -EFI_STATUS -PciIoPollIo ( - IN EFI_PCI_IO_PROTOCOL *This, - IN EFI_PCI_IO_PROTOCOL_WIDTH Width, - IN UINT8 BarIndex, - IN UINT64 Offset, - IN UINT64 Mask, - IN UINT64 Value, - IN UINT64 Delay, - OUT UINT64 *Result - ) -{ - ASSERT (FALSE); - return EFI_UNSUPPORTED; -} - -EFI_STATUS -PciIoMemRead ( - IN EFI_PCI_IO_PROTOCOL *This, - IN EFI_PCI_IO_PROTOCOL_WIDTH Width, - IN UINT8 BarIndex, - IN UINT64 Offset, - IN UINTN Count, - IN OUT VOID *Buffer - ) -{ - EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This); - - return PciRootBridgeIoMemRead (&Private->RootBridge.Io, - (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, - Private->ConfigSpace->Device.Bar[BarIndex] + Offset, - Count, - Buffer - ); -} - -EFI_STATUS -PciIoMemWrite ( - IN EFI_PCI_IO_PROTOCOL *This, - IN EFI_PCI_IO_PROTOCOL_WIDTH Width, - IN UINT8 BarIndex, - IN UINT64 Offset, - IN UINTN Count, - IN OUT VOID *Buffer - ) -{ - EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This); - - return PciRootBridgeIoMemWrite (&Private->RootBridge.Io, - (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, - Private->ConfigSpace->Device.Bar[BarIndex] + Offset, - Count, - Buffer - ); -} - -EFI_STATUS -PciIoIoRead ( - IN EFI_PCI_IO_PROTOCOL *This, - IN EFI_PCI_IO_PROTOCOL_WIDTH Width, - IN UINT8 BarIndex, - IN UINT64 Offset, - IN UINTN Count, - IN OUT VOID *Buffer - ) -{ - ASSERT (FALSE); - return EFI_UNSUPPORTED; -} - -EFI_STATUS -PciIoIoWrite ( - IN EFI_PCI_IO_PROTOCOL *This, - IN EFI_PCI_IO_PROTOCOL_WIDTH Width, - IN UINT8 BarIndex, - IN UINT64 Offset, - IN UINTN Count, - IN OUT VOID *Buffer - ) -{ - ASSERT (FALSE); - return EFI_UNSUPPORTED; -} - -/** - Enable a PCI driver to read PCI controller registers in PCI configuration space. - - @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance. - @param[in] Width Signifies the width of the memory operations. - @param[in] Offset The offset within the PCI configuration space for - the PCI controller. - @param[in] Count The number of PCI configuration operations to - perform. Bytes moved is Width size * Count, - starting at Offset. - - @param[in out] Buffer The destination buffer to store the results. - - @retval EFI_SUCCESS The data was read from the PCI controller. - @retval EFI_INVALID_PARAMETER "Width" is invalid. - @retval EFI_INVALID_PARAMETER "Buffer" is NULL. - -**/ -EFI_STATUS -PciIoPciRead ( - IN EFI_PCI_IO_PROTOCOL *This, - IN EFI_PCI_IO_PROTOCOL_WIDTH Width, - IN UINT32 Offset, - IN UINTN Count, - IN OUT VOID *Buffer - ) -{ - EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This); - EFI_STATUS Status; - - if ((Width < 0) || (Width >= EfiPciIoWidthMaximum) || (Buffer == NULL)) { - return EFI_INVALID_PARAMETER; - } - - Status = PciRootBridgeIoMemRW ( - (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)Width, - Count, - TRUE, - (PTR)(UINTN)Buffer, - TRUE, - (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset) //Fix me ConfigSpace - ); - - return Status; -} - -/** - Enable a PCI driver to write PCI controller registers in PCI configuration space. - - @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance. - @param[in] Width Signifies the width of the memory operations. - @param[in] Offset The offset within the PCI configuration space for - the PCI controller. - @param[in] Count The number of PCI configuration operations to - perform. Bytes moved is Width size * Count, - starting at Offset. - - @param[in out] Buffer The source buffer to write data from. - - @retval EFI_SUCCESS The data was read from the PCI controller. - @retval EFI_INVALID_PARAMETER "Width" is invalid. - @retval EFI_INVALID_PARAMETER "Buffer" is NULL. - -**/ -EFI_STATUS -PciIoPciWrite ( - IN EFI_PCI_IO_PROTOCOL *This, - IN EFI_PCI_IO_PROTOCOL_WIDTH Width, - IN UINT32 Offset, - IN UINTN Count, - IN OUT VOID *Buffer - ) -{ - EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This); - - if ((Width < 0) || (Width >= EfiPciIoWidthMaximum) || (Buffer == NULL)) { - return EFI_INVALID_PARAMETER; - } - - return PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, - Count, - TRUE, - (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset), - TRUE, - (PTR)(UINTN)Buffer - ); -} - -EFI_STATUS -PciIoCopyMem ( - IN EFI_PCI_IO_PROTOCOL *This, - IN EFI_PCI_IO_PROTOCOL_WIDTH Width, - IN UINT8 DestBarIndex, - IN UINT64 DestOffset, - IN UINT8 SrcBarIndex, - IN UINT64 SrcOffset, - IN UINTN Count - ) -{ - ASSERT (FALSE); - return EFI_UNSUPPORTED; -} - -EFI_STATUS -PciIoMap ( - IN EFI_PCI_IO_PROTOCOL *This, - IN EFI_PCI_IO_PROTOCOL_OPERATION Operation, - IN VOID *HostAddress, - IN OUT UINTN *NumberOfBytes, - OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, - OUT VOID **Mapping - ) -{ - DMA_MAP_OPERATION DmaOperation; - - if (Operation == EfiPciIoOperationBusMasterRead) { - DmaOperation = MapOperationBusMasterRead; - } else if (Operation == EfiPciIoOperationBusMasterWrite) { - DmaOperation = MapOperationBusMasterWrite; - } else if (Operation == EfiPciIoOperationBusMasterCommonBuffer) { - DmaOperation = MapOperationBusMasterCommonBuffer; - } else { - return EFI_INVALID_PARAMETER; - } - return DmaMap (DmaOperation, HostAddress, NumberOfBytes, DeviceAddress, Mapping); -} -EFI_STATUS -PciIoUnmap ( - IN EFI_PCI_IO_PROTOCOL *This, - IN VOID *Mapping - ) -{ - return DmaUnmap (Mapping); -} - -/** - Allocate pages that are suitable for an EfiPciIoOperationBusMasterCommonBuffer - mapping. - - @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance. - @param[in] Type This parameter is not used and must be ignored. - @param[in] MemoryType The type of memory to allocate, EfiBootServicesData or - EfiRuntimeServicesData. - @param[in] Pages The number of pages to allocate. - @param[out] HostAddress A pointer to store the base system memory address of - the allocated range. - @param[in] Attributes The requested bit mask of attributes for the allocated - range. Only the attributes, - EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE and - EFI_PCI_ATTRIBUTE_MEMORY_CACHED may be used with this - function. If any other bits are set, then EFI_UNSUPPORTED - is returned. This function ignores this bit mask. - - @retval EFI_SUCCESS The requested memory pages were allocated. - @retval EFI_INVALID_PARAMETER HostAddress is NULL. - @retval EFI_INVALID_PARAMETER MemoryType is invalid. - @retval EFI_UNSUPPORTED Attributes is unsupported. - @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. - -**/ -EFI_STATUS -PciIoAllocateBuffer ( - IN EFI_PCI_IO_PROTOCOL *This, - IN EFI_ALLOCATE_TYPE Type, - IN EFI_MEMORY_TYPE MemoryType, - IN UINTN Pages, - OUT VOID **HostAddress, - IN UINT64 Attributes - ) -{ - if (Attributes & - (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | - EFI_PCI_ATTRIBUTE_MEMORY_CACHED ))) { - return EFI_UNSUPPORTED; - } - - return DmaAllocateBuffer (MemoryType, Pages, HostAddress); -} - - -EFI_STATUS -PciIoFreeBuffer ( - IN EFI_PCI_IO_PROTOCOL *This, - IN UINTN Pages, - IN VOID *HostAddress - ) -{ - return DmaFreeBuffer (Pages, HostAddress); -} - - -EFI_STATUS -PciIoFlush ( - IN EFI_PCI_IO_PROTOCOL *This - ) -{ return EFI_SUCCESS; } -/** - Retrieves this PCI controller's current PCI bus number, device number, and function number. - - @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance. - @param[out] SegmentNumber The PCI controller's current PCI segment number. - @param[out] BusNumber The PCI controller's current PCI bus number. - @param[out] DeviceNumber The PCI controller's current PCI device number. - @param[out] FunctionNumber The PCI controller's current PCI function number. - - @retval EFI_SUCCESS The PCI controller location was returned. - @retval EFI_INVALID_PARAMETER At least one out of the four output parameters is - a NULL pointer. -**/ -EFI_STATUS -PciIoGetLocation ( - IN EFI_PCI_IO_PROTOCOL *This, - OUT UINTN *SegmentNumber, - OUT UINTN *BusNumber, - OUT UINTN *DeviceNumber, - OUT UINTN *FunctionNumber - ) -{ - EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This); - - if ((SegmentNumber == NULL) || (BusNumber == NULL) || - (DeviceNumber == NULL) || (FunctionNumber == NULL) ) { - return EFI_INVALID_PARAMETER; - } - - *SegmentNumber = Private->Segment; - *BusNumber = 0xff; - *DeviceNumber = 0; - *FunctionNumber = 0; - - return EFI_SUCCESS; -} - -/** - Performs an operation on the attributes that this PCI controller supports. - - The operations include getting the set of supported attributes, retrieving - the current attributes, setting the current attributes, enabling attributes, - and disabling attributes. - - @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance. - @param[in] Operation The operation to perform on the attributes for this - PCI controller. - @param[in] Attributes The mask of attributes that are used for Set, - Enable and Disable operations. - @param[out] Result A pointer to the result mask of attributes that are - returned for the Get and Supported operations. This - is an optional parameter that may be NULL for the - Set, Enable, and Disable operations. - - @retval EFI_SUCCESS The operation on the PCI controller's - attributes was completed. If the operation - was Get or Supported, then the attribute mask - is returned in Result. - @retval EFI_INVALID_PARAMETER Operation is greater than or equal to - EfiPciIoAttributeOperationMaximum. - @retval EFI_INVALID_PARAMETER Operation is Get and Result is NULL. - @retval EFI_INVALID_PARAMETER Operation is Supported and Result is NULL. - -**/ -EFI_STATUS -PciIoAttributes ( - IN EFI_PCI_IO_PROTOCOL *This, - IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation, - IN UINT64 Attributes, - OUT UINT64 *Result OPTIONAL - ) -{ - switch (Operation) { - case EfiPciIoAttributeOperationGet: - case EfiPciIoAttributeOperationSupported: - if (Result == NULL) { - return EFI_INVALID_PARAMETER; - } - // - // We are not a real PCI device so just say things we kind of do - // - *Result = EFI_PCI_DEVICE_ENABLE; - break; - - case EfiPciIoAttributeOperationSet: - case EfiPciIoAttributeOperationEnable: - case EfiPciIoAttributeOperationDisable: - if (Attributes & (~EFI_PCI_DEVICE_ENABLE)) { - return EFI_UNSUPPORTED; - } - // Since we are not a real PCI device no enable/set or disable operations exist. - return EFI_SUCCESS; - - default: - return EFI_INVALID_PARAMETER; - }; - return EFI_SUCCESS; -} - -EFI_STATUS -PciIoGetBarAttributes ( - IN EFI_PCI_IO_PROTOCOL *This, - IN UINT8 BarIndex, - OUT UINT64 *Supports, OPTIONAL - OUT VOID **Resources OPTIONAL - ) -{ - ASSERT (FALSE); - return EFI_UNSUPPORTED; -} - -EFI_STATUS -PciIoSetBarAttributes ( - IN EFI_PCI_IO_PROTOCOL *This, - IN UINT64 Attributes, - IN UINT8 BarIndex, - IN OUT UINT64 *Offset, - IN OUT UINT64 *Length - ) -{ - ASSERT (FALSE); - return EFI_UNSUPPORTED; -} - -EFI_PCI_IO_PROTOCOL PciIoTemplate = -{ - PciIoPollMem, - PciIoPollIo, - { PciIoMemRead, PciIoMemWrite }, - { PciIoIoRead, PciIoIoWrite }, - { PciIoPciRead, PciIoPciWrite }, - PciIoCopyMem, - PciIoMap, - PciIoUnmap, - PciIoAllocateBuffer, - PciIoFreeBuffer, - PciIoFlush, - PciIoGetLocation, - PciIoAttributes, - PciIoGetBarAttributes, - PciIoSetBarAttributes, - 0, - 0 -}; - EFI_STATUS EFIAPI PciEmulationEntryPoint ( @@ -558,76 +93,21 @@ PciEmulationEntryPoint ( IN EFI_SYSTEM_TABLE *SystemTable ) { - EFI_STATUS Status; - EFI_HANDLE Handle; - EFI_PCI_IO_PRIVATE_DATA *Private; UINT8 CapabilityLength; UINT8 PhysicalPorts; - UINTN Count; - - - //Configure USB host for OMAP3530. - ConfigureUSBHost(); - - // Create a private structure - Private = AllocatePool(sizeof(EFI_PCI_IO_PRIVATE_DATA)); - if (Private == NULL) { - Status = EFI_OUT_OF_RESOURCES; - return Status; - } - - Private->Signature = EFI_PCI_IO_PRIVATE_DATA_SIGNATURE; // Fill in signature - Private->RootBridge.Signature = PCI_ROOT_BRIDGE_SIGNATURE; // Fake Root Bridge structure needs a signature too - Private->RootBridge.MemoryStart = USB_EHCI_HCCAPBASE; // Get the USB capability register base - Private->Segment = 0; // Default to segment zero - - // Find out the capability register length and number of physical ports. - CapabilityLength = MmioRead8(Private->RootBridge.MemoryStart); - PhysicalPorts = (MmioRead32 (Private->RootBridge.MemoryStart + 0x4)) & 0x0000000F; - - // Calculate the total size of the USB registers. - Private->RootBridge.MemorySize = CapabilityLength + (HOST_CONTROLLER_OPERATION_REG_SIZE + ((4 * PhysicalPorts) - 1)); - - // Enable Port Power bit in Port status and control registers in EHCI register space. - // Port Power Control (PPC) bit in the HCSPARAMS register is already set which indicates - // host controller implementation includes port power control. - for (Count = 0; Count < PhysicalPorts; Count++) { - MmioOr32 ((Private->RootBridge.MemoryStart + CapabilityLength + HOST_CONTROLLER_OPERATION_REG_SIZE + 4*Count), 0x00001000); - } - - // Create fake PCI config space. - Private->ConfigSpace = AllocateZeroPool(sizeof(PCI_TYPE00)); - if (Private->ConfigSpace == NULL) { - Status = EFI_OUT_OF_RESOURCES; - FreePool(Private); - return Status; - } - - // Configure PCI config space - Private->ConfigSpace->Hdr.VendorId = 0xFFFF; // Invalid vendor Id as it is not an actual device. - Private->ConfigSpace->Hdr.DeviceId = 0x0000; // Not relevant as the vendor id is not valid. - Private->ConfigSpace->Hdr.ClassCode[0] = 0x20; - Private->ConfigSpace->Hdr.ClassCode[1] = 0x03; - Private->ConfigSpace->Hdr.ClassCode[2] = 0x0C; - Private->ConfigSpace->Device.Bar[0] = Private->RootBridge.MemoryStart; - - Handle = NULL; - - // Unique device path. - CopyMem(&Private->DevicePath, &PciIoDevicePathTemplate, sizeof(PciIoDevicePathTemplate)); - Private->DevicePath.AcpiDevicePath.UID = 0; - - // Copy protocol structure - CopyMem(&Private->PciIoProtocol, &PciIoTemplate, sizeof(PciIoTemplate)); - - Status = gBS->InstallMultipleProtocolInterfaces(&Handle, - &gEfiPciIoProtocolGuid, &Private->PciIoProtocol, - &gEfiDevicePathProtocolGuid, &Private->DevicePath, - NULL); - if (EFI_ERROR(Status)) { - DEBUG((EFI_D_ERROR, "PciEmulationEntryPoint InstallMultipleProtocolInterfaces() failed.\n")); - } - - return Status; + UINTN MemorySize; + + CapabilityLength = MmioRead8 (USB_EHCI_HCCAPBASE); + PhysicalPorts = MmioRead32 (USB_EHCI_HCCAPBASE + 0x4) & 0x0000000F; + MemorySize = CapabilityLength + HOST_CONTROLLER_OPERATION_REG_SIZE + + 4 * PhysicalPorts - 1; + + return RegisterNonDiscoverableMmioDevice ( + NonDiscoverableDeviceTypeEhci, + NonDiscoverableDeviceDmaTypeNonCoherent, + ConfigureUSBHost, + NULL, + 1, + USB_EHCI_HCCAPBASE, MemorySize + ); } - diff --git a/Omap35xxPkg/PciEmulation/PciEmulation.h b/Omap35xxPkg/PciEmulation/PciEmulation.h deleted file mode 100644 index d5ee04318939..000000000000 --- a/Omap35xxPkg/PciEmulation/PciEmulation.h +++ /dev/null @@ -1,292 +0,0 @@ -/** @file - - Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR> - - This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#ifndef _PCI_ROOT_BRIDGE_H_ -#define _PCI_ROOT_BRIDGE_H_ - -#include <PiDxe.h> - -#include <TPS65950.h> - -#include <Library/BaseLib.h> -#include <Library/BaseMemoryLib.h> -#include <Library/DebugLib.h> -#include <Library/DxeServicesTableLib.h> -#include <Library/IoLib.h> -#include <Library/MemoryAllocationLib.h> -#include <Library/PciLib.h> -#include <Library/UefiLib.h> -#include <Library/UefiBootServicesTableLib.h> -#include <Library/OmapDmaLib.h> -#include <Library/DmaLib.h> - -#include <Protocol/EmbeddedExternalDevice.h> -#include <Protocol/DevicePath.h> -#include <Protocol/PciIo.h> -#include <Protocol/PciRootBridgeIo.h> -#include <Protocol/PciHostBridgeResourceAllocation.h> - -#include <IndustryStandard/Pci22.h> -#include <IndustryStandard/Acpi.h> - -#include <Omap3530/Omap3530.h> - - - -#define EFI_RESOURCE_NONEXISTENT 0xFFFFFFFFFFFFFFFFULL -#define EFI_RESOURCE_LESS 0xFFFFFFFFFFFFFFFEULL -#define EFI_RESOURCE_SATISFIED 0x0000000000000000ULL - - -typedef struct { - ACPI_HID_DEVICE_PATH AcpiDevicePath; - EFI_DEVICE_PATH_PROTOCOL EndDevicePath; -} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH; - - -#define ACPI_CONFIG_IO 0 -#define ACPI_CONFIG_MMIO 1 -#define ACPI_CONFIG_BUS 2 - -typedef struct { - EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR Desc[3]; - EFI_ACPI_END_TAG_DESCRIPTOR EndDesc; -} ACPI_CONFIG_INFO; - - -#define PCI_ROOT_BRIDGE_SIGNATURE SIGNATURE_32 ('P', 'c', 'i', 'F') - -typedef struct { - UINT32 Signature; - EFI_HANDLE Handle; - EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Io; - EFI_PCI_ROOT_BRIDGE_DEVICE_PATH DevicePath; - - UINT8 StartBus; - UINT8 EndBus; - UINT16 Type; - UINT32 MemoryStart; - UINT32 MemorySize; - UINTN IoOffset; - UINT32 IoStart; - UINT32 IoSize; - UINT64 PciAttributes; - - ACPI_CONFIG_INFO *Config; - -} PCI_ROOT_BRIDGE; - - -#define INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(a) CR (a, PCI_ROOT_BRIDGE, Io, PCI_ROOT_BRIDGE_SIGNATURE) - - -typedef union { - UINT8 volatile *buf; - UINT8 volatile *ui8; - UINT16 volatile *ui16; - UINT32 volatile *ui32; - UINT64 volatile *ui64; - UINTN volatile ui; -} PTR; - - - -EFI_STATUS -EFIAPI -PciRootBridgeIoPollMem ( - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, - IN UINT64 Address, - IN UINT64 Mask, - IN UINT64 Value, - IN UINT64 Delay, - OUT UINT64 *Result - ); - -EFI_STATUS -EFIAPI -PciRootBridgeIoPollIo ( - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, - IN UINT64 Address, - IN UINT64 Mask, - IN UINT64 Value, - IN UINT64 Delay, - OUT UINT64 *Result - ); - -EFI_STATUS -EFIAPI -PciRootBridgeIoMemRead ( - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, - IN UINT64 Address, - IN UINTN Count, - IN OUT VOID *Buffer - ); - -EFI_STATUS -EFIAPI -PciRootBridgeIoMemWrite ( - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, - IN UINT64 Address, - IN UINTN Count, - IN OUT VOID *Buffer - ); - -EFI_STATUS -EFIAPI -PciRootBridgeIoIoRead ( - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, - IN UINT64 UserAddress, - IN UINTN Count, - IN OUT VOID *UserBuffer - ); - -EFI_STATUS -EFIAPI -PciRootBridgeIoIoWrite ( - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, - IN UINT64 UserAddress, - IN UINTN Count, - IN OUT VOID *UserBuffer - ); - -EFI_STATUS -EFIAPI -PciRootBridgeIoCopyMem ( - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, - IN UINT64 DestAddress, - IN UINT64 SrcAddress, - IN UINTN Count - ); - -EFI_STATUS -EFIAPI -PciRootBridgeIoPciRead ( - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, - IN UINT64 Address, - IN UINTN Count, - IN OUT VOID *Buffer - ); - -EFI_STATUS -EFIAPI -PciRootBridgeIoPciWrite ( - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, - IN UINT64 Address, - IN UINTN Count, - IN OUT VOID *Buffer - ); - -EFI_STATUS -EFIAPI -PciRootBridgeIoMap ( - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation, - IN VOID *HostAddress, - IN OUT UINTN *NumberOfBytes, - OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, - OUT VOID **Mapping - ); - -EFI_STATUS -EFIAPI -PciRootBridgeIoUnmap ( - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, - IN VOID *Mapping - ); - -EFI_STATUS -EFIAPI -PciRootBridgeIoAllocateBuffer ( - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, - IN EFI_ALLOCATE_TYPE Type, - IN EFI_MEMORY_TYPE MemoryType, - IN UINTN Pages, - OUT VOID **HostAddress, - IN UINT64 Attributes - ); - -EFI_STATUS -EFIAPI -PciRootBridgeIoFreeBuffer ( - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, - IN UINTN Pages, - OUT VOID *HostAddress - ); - -EFI_STATUS -EFIAPI -PciRootBridgeIoFlush ( - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This - ); - -EFI_STATUS -EFIAPI -PciRootBridgeIoGetAttributes ( - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, - OUT UINT64 *Supported, - OUT UINT64 *Attributes - ); - -EFI_STATUS -EFIAPI -PciRootBridgeIoSetAttributes ( - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, - IN UINT64 Attributes, - IN OUT UINT64 *ResourceBase, - IN OUT UINT64 *ResourceLength - ); - -EFI_STATUS -EFIAPI -PciRootBridgeIoConfiguration ( - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, - OUT VOID **Resources - ); - -// -// Private Function Prototypes -// -EFI_STATUS -EFIAPI -PciRootBridgeIoMemRW ( - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, - IN UINTN Count, - IN BOOLEAN InStrideFlag, - IN PTR In, - IN BOOLEAN OutStrideFlag, - OUT PTR Out - ); - -BOOLEAN -PciIoMemAddressValid ( - IN EFI_PCI_IO_PROTOCOL *This, - IN UINT64 Address - ); - -EFI_STATUS -EmulatePciIoForEhci ( - INTN MvPciIfMaxIf - ); - -#endif - diff --git a/Omap35xxPkg/PciEmulation/PciEmulation.inf b/Omap35xxPkg/PciEmulation/PciEmulation.inf index 2180bb49898d..4df9c505e8cd 100644 --- a/Omap35xxPkg/PciEmulation/PciEmulation.inf +++ b/Omap35xxPkg/PciEmulation/PciEmulation.inf @@ -22,33 +22,23 @@ [Defines] ENTRY_POINT = PciEmulationEntryPoint [Sources.common] - PciRootBridgeIo.c PciEmulation.c [Packages] MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - ArmPkg/ArmPkg.dec EmbeddedPkg/EmbeddedPkg.dec Omap35xxPkg/Omap35xxPkg.dec [LibraryClasses] BaseLib - DxeServicesTableLib - UefiLib + DebugLib + IoLib + NonDiscoverableDeviceRegistrationLib UefiBootServicesTableLib UefiDriverEntryPoint - UefiRuntimeServicesTableLib - IoLib - OmapDmaLib - DmaLib [Protocols] - gEfiPciRootBridgeIoProtocolGuid - gEfiDevicePathProtocolGuid - gEfiPciHostBridgeResourceAllocationProtocolGuid - gEfiPciIoProtocolGuid gEmbeddedExternalDeviceProtocolGuid [Depex] diff --git a/Omap35xxPkg/PciEmulation/PciRootBridgeIo.c b/Omap35xxPkg/PciEmulation/PciRootBridgeIo.c deleted file mode 100644 index e8635ed88d91..000000000000 --- a/Omap35xxPkg/PciEmulation/PciRootBridgeIo.c +++ /dev/null @@ -1,306 +0,0 @@ -/** @file - - Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR> - - This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include "PciEmulation.h" - -BOOLEAN -PciRootBridgeMemAddressValid ( - IN PCI_ROOT_BRIDGE *Private, - IN UINT64 Address - ) -{ - if ((Address >= Private->MemoryStart) && (Address < (Private->MemoryStart + Private->MemorySize))) { - return TRUE; - } - - return FALSE; -} - - -EFI_STATUS -PciRootBridgeIoMemRW ( - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, - IN UINTN Count, - IN BOOLEAN InStrideFlag, - IN PTR In, - IN BOOLEAN OutStrideFlag, - OUT PTR Out - ) -{ - UINTN Stride; - UINTN InStride; - UINTN OutStride; - - - Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03); - Stride = (UINTN)1 << Width; - InStride = InStrideFlag ? Stride : 0; - OutStride = OutStrideFlag ? Stride : 0; - - // - // Loop for each iteration and move the data - // - switch (Width) { - case EfiPciWidthUint8: - for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) { - *In.ui8 = *Out.ui8; - } - break; - case EfiPciWidthUint16: - for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) { - *In.ui16 = *Out.ui16; - } - break; - case EfiPciWidthUint32: - for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) { - *In.ui32 = *Out.ui32; - } - break; - default: - return EFI_INVALID_PARAMETER; - } - - return EFI_SUCCESS; -} - -EFI_STATUS -PciRootBridgeIoPciRW ( - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, - IN BOOLEAN Write, - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, - IN UINT64 UserAddress, - IN UINTN Count, - IN OUT VOID *UserBuffer - ) -{ - return EFI_SUCCESS; -} - -/** - Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space. - - @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. - @param Width Signifies the width of the memory operations. - @param Address The base address of the memory operations. - @param Count The number of memory operations to perform. - @param Buffer For read operations, the destination buffer to store the results. For write - operations, the source buffer to write data from. - - @retval EFI_SUCCESS The data was read from or written to the PCI root bridge. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. - @retval EFI_INVALID_PARAMETER One or more parameters are invalid. - -**/ -EFI_STATUS -EFIAPI -PciRootBridgeIoMemRead ( - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, - IN UINT64 Address, - IN UINTN Count, - IN OUT VOID *Buffer - ) -{ - PCI_ROOT_BRIDGE *Private; - UINTN AlignMask; - PTR In; - PTR Out; - - if ( Buffer == NULL ) { - return EFI_INVALID_PARAMETER; - } - - Private = INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This); - - if (!PciRootBridgeMemAddressValid (Private, Address)) { - return EFI_INVALID_PARAMETER; - } - - AlignMask = (1 << (Width & 0x03)) - 1; - if (Address & AlignMask) { - return EFI_INVALID_PARAMETER; - } - - In.buf = Buffer; - Out.buf = (VOID *)(UINTN) Address; - - switch (Width) { - case EfiPciWidthUint8: - case EfiPciWidthUint16: - case EfiPciWidthUint32: - case EfiPciWidthUint64: - return PciRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out); - - case EfiPciWidthFifoUint8: - case EfiPciWidthFifoUint16: - case EfiPciWidthFifoUint32: - case EfiPciWidthFifoUint64: - return PciRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out); - - case EfiPciWidthFillUint8: - case EfiPciWidthFillUint16: - case EfiPciWidthFillUint32: - case EfiPciWidthFillUint64: - return PciRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out); - - default: - break; - } - - return EFI_INVALID_PARAMETER; -} - - - -/** - Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space. - - @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. - @param Width Signifies the width of the memory operations. - @param Address The base address of the memory operations. - @param Count The number of memory operations to perform. - @param Buffer For read operations, the destination buffer to store the results. For write - operations, the source buffer to write data from. - - @retval EFI_SUCCESS The data was read from or written to the PCI root bridge. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. - @retval EFI_INVALID_PARAMETER One or more parameters are invalid. - -**/ -EFI_STATUS -EFIAPI -PciRootBridgeIoMemWrite ( - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, - IN UINT64 Address, - IN UINTN Count, - IN OUT VOID *Buffer - ) -{ - PCI_ROOT_BRIDGE *Private; - UINTN AlignMask; - PTR In; - PTR Out; - - if ( Buffer == NULL ) { - return EFI_INVALID_PARAMETER; - } - - Private = INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This); - - if (!PciRootBridgeMemAddressValid (Private, Address)) { - return EFI_INVALID_PARAMETER; - } - - AlignMask = (1 << (Width & 0x03)) - 1; - if (Address & AlignMask) { - return EFI_INVALID_PARAMETER; - } - - In.buf = (VOID *)(UINTN) Address; - Out.buf = Buffer; - - switch (Width) { - case EfiPciWidthUint8: - case EfiPciWidthUint16: - case EfiPciWidthUint32: - case EfiPciWidthUint64: - return PciRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out); - - case EfiPciWidthFifoUint8: - case EfiPciWidthFifoUint16: - case EfiPciWidthFifoUint32: - case EfiPciWidthFifoUint64: - return PciRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out); - - case EfiPciWidthFillUint8: - case EfiPciWidthFillUint16: - case EfiPciWidthFillUint32: - case EfiPciWidthFillUint64: - return PciRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out); - - default: - break; - } - - return EFI_INVALID_PARAMETER; -} - -/** - Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space. - - @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. - @param Width Signifies the width of the memory operations. - @param Address The base address of the memory operations. - @param Count The number of memory operations to perform. - @param Buffer For read operations, the destination buffer to store the results. For write - operations, the source buffer to write data from. - - @retval EFI_SUCCESS The data was read from or written to the PCI root bridge. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. - @retval EFI_INVALID_PARAMETER One or more parameters are invalid. - -**/ -EFI_STATUS -EFIAPI -PciRootBridgeIoPciRead ( - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, - IN UINT64 Address, - IN UINTN Count, - IN OUT VOID *Buffer - ) -{ - if (Buffer == NULL) { - return EFI_INVALID_PARAMETER; - } - - return PciRootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer); -} - - - -/** - Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space. - - @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. - @param Width Signifies the width of the memory operations. - @param Address The base address of the memory operations. - @param Count The number of memory operations to perform. - @param Buffer For read operations, the destination buffer to store the results. For write - operations, the source buffer to write data from. - - @retval EFI_SUCCESS The data was read from or written to the PCI root bridge. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. - @retval EFI_INVALID_PARAMETER One or more parameters are invalid. - -**/ -EFI_STATUS -EFIAPI -PciRootBridgeIoPciWrite ( - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, - IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, - IN UINT64 Address, - IN UINTN Count, - IN OUT VOID *Buffer - ) -{ - if (Buffer == NULL) { - return EFI_INVALID_PARAMETER; - } - - return PciRootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer); -} - - -- 2.7.4 ^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2016-12-15 8:22 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2016-12-09 15:04 [PATCH v6 0/2] MdeModulePkg/NonDiscoverablePciDeviceDxe: non-coherent DMA support Ard Biesheuvel 2016-12-09 15:04 ` [PATCH v6 1/2] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA Ard Biesheuvel 2016-12-14 9:15 ` Ard Biesheuvel 2016-12-15 8:17 ` Ni, Ruiyu 2016-12-15 8:22 ` Ard Biesheuvel 2016-12-09 15:04 ` [PATCH v6 2/2] Omap35xxPkg/PciEmulation: port to new non-discoverable device infrastructure Ard Biesheuvel
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox