ehcimem.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 775 行 · 第 1/2 页
C
775 行
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. 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.
Module Name:
EhciMem.c
Abstract:
Revision History
--*/
#include "Tiano.h"
#include "EfiDriverLib.h"
#include "Ehci.h"
EFI_STATUS
CreateMemoryBlock (
IN USB2_HC_DEV *HcDev,
OUT MEMORY_MANAGE_HEADER **MemoryHeader,
IN UINTN MemoryBlockSizeInPages
)
/*++
Routine Description:
Use PciIo->AllocateBuffer to allocate common buffer for the memory block,
and use PciIo->Map to map the common buffer for Bus Master Read/Write.
Arguments:
HcDev - USB2_HC_DEV
MemoryHeader - MEMORY_MANAGE_HEADER to output
MemoryBlockSizeInPages - MemoryBlockSizeInPages
Returns:
EFI_SUCCESS Success
EFI_OUT_OF_RESOURCES Fail for no resources
EFI_UNSUPPORTED Unsupported currently
--*/
{
EFI_STATUS Status;
VOID *CommonBuffer;
EFI_PHYSICAL_ADDRESS MappedAddress;
UINTN MemoryBlockSizeInBytes;
VOID *Mapping;
//
// Allocate memory for MemoryHeader
//
*MemoryHeader = EfiLibAllocateZeroPool (sizeof (MEMORY_MANAGE_HEADER));
if (*MemoryHeader == NULL) {
return EFI_OUT_OF_RESOURCES;
}
(*MemoryHeader)->Next = NULL;
//
// set Memory block size
//
(*MemoryHeader)->MemoryBlockSizeInBytes = EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages);
//
// each bit in Bit Array will manage 32 bytes memory in memory block
//
(*MemoryHeader)->BitArraySizeInBytes = ((*MemoryHeader)->MemoryBlockSizeInBytes / MEM_UNIT_SIZE) / 8;
//
// Allocate memory for BitArray
//
(*MemoryHeader)->BitArrayPtr = EfiLibAllocateZeroPool ((*MemoryHeader)->BitArraySizeInBytes);
if ((*MemoryHeader)->BitArrayPtr == NULL) {
gBS->FreePool (*MemoryHeader);
return EFI_OUT_OF_RESOURCES;
}
//
// Memory Block uses MemoryBlockSizeInPages pages,
// and it is allocated as common buffer use.
//
Status = HcDev->PciIo->AllocateBuffer (
HcDev->PciIo,
AllocateAnyPages,
EfiBootServicesData,
MemoryBlockSizeInPages,
&CommonBuffer,
0
);
if (EFI_ERROR (Status)) {
gBS->FreePool ((*MemoryHeader)->BitArrayPtr);
gBS->FreePool (*MemoryHeader);
return EFI_OUT_OF_RESOURCES;
}
MemoryBlockSizeInBytes = EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages);
Status = HcDev->PciIo->Map (
HcDev->PciIo,
EfiPciIoOperationBusMasterCommonBuffer,
CommonBuffer,
&MemoryBlockSizeInBytes,
&MappedAddress,
&Mapping
);
//
// If returned Mapped size is less than the size
// we request,do not support.
//
if (EFI_ERROR (Status) || (MemoryBlockSizeInBytes != EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages))) {
HcDev->PciIo->FreeBuffer (HcDev->PciIo, MemoryBlockSizeInPages, CommonBuffer);
gBS->FreePool ((*MemoryHeader)->BitArrayPtr);
gBS->FreePool (*MemoryHeader);
return EFI_UNSUPPORTED;
}
//
// Data structure involved by host controller
// should be restricted into the same 4G
//
if (HcDev->Is64BitCapable != 0) {
if (HcDev->High32BitAddr != GET_32B_TO_63B (MappedAddress)) {
HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
HcDev->PciIo->FreeBuffer (HcDev->PciIo, MemoryBlockSizeInPages, CommonBuffer);
gBS->FreePool ((*MemoryHeader)->BitArrayPtr);
gBS->FreePool (*MemoryHeader);
return EFI_UNSUPPORTED;
}
}
//
// Set Memory block initial address
//
(*MemoryHeader)->MemoryBlockPtr = (UINT8 *) ((UINTN) MappedAddress);
(*MemoryHeader)->Mapping = Mapping;
EfiZeroMem (
(*MemoryHeader)->MemoryBlockPtr,
EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages)
);
return EFI_SUCCESS;
}
EFI_STATUS
FreeMemoryHeader (
IN USB2_HC_DEV *HcDev,
IN MEMORY_MANAGE_HEADER *MemoryHeader
)
/*++
Routine Description:
Free Memory Header
Arguments:
HcDev - USB2_HC_DEV
MemoryHeader - MemoryHeader to be freed
Returns:
EFI_SUCCESS Success
EFI_INVALID_PARAMETER Parameter is error
--*/
{
if ((MemoryHeader == NULL) || (HcDev == NULL)) {
return EFI_INVALID_PARAMETER;
}
//
// unmap the common buffer used by the memory block
//
HcDev->PciIo->Unmap (HcDev->PciIo, MemoryHeader->Mapping);
//
// free common buffer
//
HcDev->PciIo->FreeBuffer (
HcDev->PciIo,
EFI_SIZE_TO_PAGES (MemoryHeader->MemoryBlockSizeInBytes),
MemoryHeader->MemoryBlockPtr
);
//
// free bit array
//
gBS->FreePool (MemoryHeader->BitArrayPtr);
//
// free memory header
//
gBS->FreePool (MemoryHeader);
return EFI_SUCCESS;
}
EFI_STATUS
EhciAllocatePool (
IN USB2_HC_DEV *HcDev,
OUT UINT8 **Pool,
IN UINTN AllocSize
)
/*++
Routine Description:
Ehci Allocate Pool
Arguments:
HcDev - USB2_HC_DEV
Pool - Place to store pointer to the memory buffer
AllocSize - Alloc Size
Returns:
EFI_SUCCESS Success
EFI_DEVICE_ERROR Fail
--*/
{
MEMORY_MANAGE_HEADER *MemoryHeader;
MEMORY_MANAGE_HEADER *TempHeaderPtr;
MEMORY_MANAGE_HEADER *NewMemoryHeader;
UINTN RealAllocSize;
UINTN MemoryBlockSizeInPages;
EFI_STATUS Status;
EFI_TPL OldTpl;
*Pool = NULL;
MemoryHeader = HcDev->MemoryHeader;
ASSERT (MemoryHeader != NULL);
OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY + 1);
//
// allocate unit is 32 bytes (align on 32 byte)
//
if (AllocSize & (MEM_UNIT_SIZE - 1)) {
RealAllocSize = (AllocSize / MEM_UNIT_SIZE + 1) * MEM_UNIT_SIZE;
} else {
RealAllocSize = AllocSize;
}
//
// There may be linked MemoryHeaders.
// To allocate a free pool in Memory blocks,
// must search in the MemoryHeader link list
// until enough free pool is found.
//
Status = EFI_NOT_FOUND;
for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL; TempHeaderPtr = TempHeaderPtr->Next) {
Status = AllocMemInMemoryBlock (
TempHeaderPtr,
Pool,
RealAllocSize / MEM_UNIT_SIZE
);
if (!EFI_ERROR (Status)) {
break;
}
}
gBS->RestoreTPL (OldTpl);
if (!EFI_ERROR (Status)) {
EfiZeroMem (*Pool, AllocSize);
return EFI_SUCCESS;
}
//
// There is no enough memory,
// Create a new Memory Block
//
//
// if pool size is larger than NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES,
// just allocate a large enough memory block.
//
if (RealAllocSize > EFI_PAGES_TO_SIZE (NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES)) {
MemoryBlockSizeInPages = EFI_SIZE_TO_PAGES (RealAllocSize) + 1;
} else {
MemoryBlockSizeInPages = NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES;
}
Status = CreateMemoryBlock (HcDev, &NewMemoryHeader, MemoryBlockSizeInPages);
if (EFI_ERROR (Status)) {
return Status;
}
OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY + 1);
//
// Link the new Memory Block to the Memory Header list
//
InsertMemoryHeaderToList (MemoryHeader, NewMemoryHeader);
Status = AllocMemInMemoryBlock (
NewMemoryHeader,
Pool,
RealAllocSize / MEM_UNIT_SIZE
);
gBS->RestoreTPL (OldTpl);
if (!EFI_ERROR (Status)) {
EfiZeroMem (*Pool, AllocSize);
}
return Status;
}
VOID
EhciFreePool (
IN USB2_HC_DEV *HcDev,
IN UINT8 *Pool,
IN UINTN AllocSize
)
/*++
Routine Description:
Uhci Free Pool
Arguments:
HcDev - USB_HC_DEV
Pool - Pool to free
AllocSize - Pool size
Returns:
VOID
--*/
{
MEMORY_MANAGE_HEADER *MemoryHeader;
MEMORY_MANAGE_HEADER *TempHeaderPtr;
UINTN StartBytePos;
UINTN Index;
UINT8 StartBitPos;
UINT8 Index2;
UINTN Count;
UINTN RealAllocSize;
EFI_TPL OldTpl;
OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY + 1);
MemoryHeader = HcDev->MemoryHeader;
//
// allocate unit is 32 byte (align on 32 byte)
//
if (AllocSize & (MEM_UNIT_SIZE - 1)) {
RealAllocSize = (AllocSize / MEM_UNIT_SIZE + 1) * MEM_UNIT_SIZE;
} else {
RealAllocSize = AllocSize;
}
//
// scan the memory header linked list for
// the asigned memory to free.
//
for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL; TempHeaderPtr = TempHeaderPtr->Next) {
if ((Pool >= TempHeaderPtr->MemoryBlockPtr) &&
((Pool + RealAllocSize) <= (TempHeaderPtr->MemoryBlockPtr + TempHeaderPtr->MemoryBlockSizeInBytes))
) {
//
// Pool is in the Memory Block area,
// find the start byte and bit in the bit array
//
StartBytePos = ((Pool - TempHeaderPtr->MemoryBlockPtr) / MEM_UNIT_SIZE) / 8;
StartBitPos = (UINT8) (((Pool - TempHeaderPtr->MemoryBlockPtr) / MEM_UNIT_SIZE) & 0x7);
//
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?