mirror of https://github.com/acidanthera/audk.git
ArmPkg/ArmDmaLib: Fix coherency issues in DmaLib
Some coherencies issues were existing in the former version of DmaLib. These issues could have for consequences to not make the MdeModulePkg/Bus/Usb software stack not work. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12137 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
9201b04422
commit
e6d572ba03
|
@ -13,9 +13,10 @@
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#include <Base.h>
|
#include <PiDxe.h>
|
||||||
#include <Library/DebugLib.h>
|
#include <Library/DebugLib.h>
|
||||||
#include <Library/DmaLib.h>
|
#include <Library/DmaLib.h>
|
||||||
|
#include <Library/DxeServicesTableLib.h>
|
||||||
#include <Library/MemoryAllocationLib.h>
|
#include <Library/MemoryAllocationLib.h>
|
||||||
#include <Library/UefiBootServicesTableLib.h>
|
#include <Library/UefiBootServicesTableLib.h>
|
||||||
#include <Library/UncachedMemoryAllocationLib.h>
|
#include <Library/UncachedMemoryAllocationLib.h>
|
||||||
|
@ -38,9 +39,6 @@ typedef struct {
|
||||||
EFI_CPU_ARCH_PROTOCOL *gCpu;
|
EFI_CPU_ARCH_PROTOCOL *gCpu;
|
||||||
UINTN gCacheAlignment = 0;
|
UINTN gCacheAlignment = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Provides the DMA controller-specific addresses needed to access system memory.
|
Provides the DMA controller-specific addresses needed to access system memory.
|
||||||
|
|
||||||
|
@ -71,16 +69,15 @@ DmaMap (
|
||||||
OUT VOID **Mapping
|
OUT VOID **Mapping
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
MAP_INFO_INSTANCE *Map;
|
MAP_INFO_INSTANCE *Map;
|
||||||
VOID *Buffer;
|
VOID *Buffer;
|
||||||
|
EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;
|
||||||
|
|
||||||
if ( HostAddress == NULL || NumberOfBytes == NULL ||
|
if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL ) {
|
||||||
DeviceAddress == NULL || Mapping == NULL ) {
|
|
||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (Operation >= MapOperationMaximum) {
|
if (Operation >= MapOperationMaximum) {
|
||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
@ -97,20 +94,44 @@ DmaMap (
|
||||||
|
|
||||||
if ((((UINTN)HostAddress & (gCacheAlignment - 1)) != 0) ||
|
if ((((UINTN)HostAddress & (gCacheAlignment - 1)) != 0) ||
|
||||||
((*NumberOfBytes % gCacheAlignment) != 0)) {
|
((*NumberOfBytes % gCacheAlignment) != 0)) {
|
||||||
//
|
|
||||||
// If the buffer does not fill entire cache lines we must double buffer into
|
// Get the cacheability of the region
|
||||||
// uncached memory. Device (PCI) address becomes uncached page.
|
Status = gDS->GetMemorySpaceDescriptor (HostAddress, &GcdDescriptor);
|
||||||
//
|
if (EFI_ERROR(Status)) {
|
||||||
Map->DoubleBuffer = TRUE;
|
|
||||||
Status = DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (*NumberOfBytes), &Buffer);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
*DeviceAddress = (PHYSICAL_ADDRESS)(UINTN)Buffer;
|
// If the mapped buffer is not an uncached buffer
|
||||||
|
if (GcdDescriptor.Attributes != EFI_MEMORY_UC) {
|
||||||
|
//
|
||||||
|
// If the buffer does not fill entire cache lines we must double buffer into
|
||||||
|
// uncached memory. Device (PCI) address becomes uncached page.
|
||||||
|
//
|
||||||
|
Map->DoubleBuffer = TRUE;
|
||||||
|
Status = DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (*NumberOfBytes), &Buffer);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((Operation == MapOperationBusMasterRead) || (Operation == MapOperationBusMasterCommonBuffer)) {
|
||||||
|
CopyMem (Buffer, HostAddress, *NumberOfBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
*DeviceAddress = (PHYSICAL_ADDRESS)(UINTN)Buffer;
|
||||||
|
} else {
|
||||||
|
Map->DoubleBuffer = FALSE;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Map->DoubleBuffer = FALSE;
|
Map->DoubleBuffer = FALSE;
|
||||||
|
|
||||||
|
// Flush the Data Cache (should not have any effect if the memory region is uncached)
|
||||||
|
gCpu->FlushDataCache (gCpu, *DeviceAddress, *NumberOfBytes, EfiCpuFlushTypeWriteBackInvalidate);
|
||||||
|
|
||||||
|
if ((Operation == MapOperationBusMasterRead) || (Operation == MapOperationBusMasterCommonBuffer)) {
|
||||||
|
// In case the buffer is used for instance to send command to a PCI controller, we must ensure the memory is uncached
|
||||||
|
Status = gDS->SetMemorySpaceAttributes (ALIGN_VALUE(*DeviceAddress - BASE_4KB - 1,BASE_4KB), ALIGN_VALUE(*NumberOfBytes,BASE_4KB), EFI_MEMORY_UC);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Map->HostAddress = (UINTN)HostAddress;
|
Map->HostAddress = (UINTN)HostAddress;
|
||||||
|
@ -118,17 +139,6 @@ DmaMap (
|
||||||
Map->NumberOfBytes = *NumberOfBytes;
|
Map->NumberOfBytes = *NumberOfBytes;
|
||||||
Map->Operation = Operation;
|
Map->Operation = Operation;
|
||||||
|
|
||||||
if (Map->DoubleBuffer) {
|
|
||||||
if (Map->Operation == MapOperationBusMasterWrite) {
|
|
||||||
CopyMem ((VOID *)(UINTN)Map->DeviceAddress, (VOID *)(UINTN)Map->HostAddress, Map->NumberOfBytes);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// EfiCpuFlushTypeWriteBack, EfiCpuFlushTypeInvalidate
|
|
||||||
if (Map->Operation == MapOperationBusMasterWrite || Map->Operation == MapOperationBusMasterRead) {
|
|
||||||
gCpu->FlushDataCache (gCpu, (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, Map->NumberOfBytes, EfiCpuFlushTypeWriteBackInvalidate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +169,7 @@ DmaUnmap (
|
||||||
Map = (MAP_INFO_INSTANCE *)Mapping;
|
Map = (MAP_INFO_INSTANCE *)Mapping;
|
||||||
|
|
||||||
if (Map->DoubleBuffer) {
|
if (Map->DoubleBuffer) {
|
||||||
if (Map->Operation == MapOperationBusMasterRead) {
|
if ((Map->Operation == MapOperationBusMasterWrite) || (Map->Operation == MapOperationBusMasterCommonBuffer)) {
|
||||||
CopyMem ((VOID *)(UINTN)Map->HostAddress, (VOID *)(UINTN)Map->DeviceAddress, Map->NumberOfBytes);
|
CopyMem ((VOID *)(UINTN)Map->HostAddress, (VOID *)(UINTN)Map->DeviceAddress, Map->NumberOfBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue