4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The routine procedure for uhci memory allocate/free.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncCopyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncThis program and the accompanying materials
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncare licensed and made available under the terms and conditions of the BSD License
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncwhich accompanies this distribution. The full text of the license may be found at
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynchttp://opensource.org/licenses/bsd-license.php
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include "Uhci.h"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Allocate a block of memory to be used by the buffer pool.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Pool The buffer pool to allocate memory for.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Pages How many pages to allocate.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return The allocated memory block or NULL if failed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUSBHC_MEM_BLOCK *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUsbHcAllocMemBlock (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN USBHC_MEM_POOL *Pool,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN Pages
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync USBHC_MEM_BLOCK *Block;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_PCI_IO_PROTOCOL *PciIo;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID *BufHost;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID *Mapping;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_PHYSICAL_ADDRESS MappedAddr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Bytes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PciIo = Pool->PciIo;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Block = AllocateZeroPool (sizeof (USBHC_MEM_BLOCK));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Block == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // each bit in the bit array represents USBHC_MEM_UNIT
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // bytes of memory in the memory block.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (USBHC_MEM_UNIT * 8 <= EFI_PAGE_SIZE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Block->BufLen = EFI_PAGES_TO_SIZE (Pages);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Block->BitsLen = Block->BufLen / (USBHC_MEM_UNIT * 8);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Block->Bits = AllocateZeroPool (Block->BitsLen);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Block->Bits == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->FreePool (Block);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Allocate the number of Pages of memory, then map it for
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // bus master read and write.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = PciIo->AllocateBuffer (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PciIo,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AllocateAnyPages,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EfiBootServicesData,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Pages,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &BufHost,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto FREE_BITARRAY;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Bytes = EFI_PAGES_TO_SIZE (Pages);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = PciIo->Map (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PciIo,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EfiPciIoOperationBusMasterCommonBuffer,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BufHost,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Bytes,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &MappedAddr,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Mapping
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (Pages))) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto FREE_BUFFER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check whether the data structure used by the host controller
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // should be restricted into the same 4G
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Pool->Check4G && (Pool->Which4G != USB_HC_HIGH_32BIT (MappedAddr))) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PciIo->Unmap (PciIo, Mapping);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto FREE_BUFFER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Block->BufHost = BufHost;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Block->Buf = (UINT8 *) ((UINTN) MappedAddr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Block->Mapping = Mapping;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Block;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncFREE_BUFFER:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PciIo->FreeBuffer (PciIo, Pages, BufHost);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncFREE_BITARRAY:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->FreePool (Block->Bits);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->FreePool (Block);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Free the memory block from the memory pool.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Pool The memory pool to free the block from.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Block The memory block to free.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUsbHcFreeMemBlock (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN USBHC_MEM_POOL *Pool,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN USBHC_MEM_BLOCK *Block
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_PCI_IO_PROTOCOL *PciIo;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT ((Pool != NULL) && (Block != NULL));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PciIo = Pool->PciIo;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Unmap the common buffer then free the structures
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PciIo->Unmap (PciIo, Block->Mapping);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PciIo->FreeBuffer (PciIo, EFI_SIZE_TO_PAGES (Block->BufLen), Block->BufHost);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->FreePool (Block->Bits);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->FreePool (Block);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Alloc some memory from the block.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Block The memory block to allocate memory from.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Units Number of memory units to allocate.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return EFI_SUCCESS The needed memory is allocated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return EFI_NOT_FOUND Can't find the free memory.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUsbHcAllocMemFromBlock (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN USBHC_MEM_BLOCK *Block,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN Units
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Byte;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 Bit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN StartByte;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 StartBit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Available;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Count;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT ((Block != 0) && (Units != 0));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync StartByte = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync StartBit = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Available = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Byte = 0, Bit = 0; Byte < Block->BitsLen;) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If current bit is zero, the corresponding memory unit is
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // available, otherwise we need to restart our searching.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Available counts the consective number of zero bit.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Available++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Available >= Units) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NEXT_BIT (Byte, Bit);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NEXT_BIT (Byte, Bit);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Available = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync StartByte = Byte;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync StartBit = Bit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Available < Units) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Mark the memory as allocated
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Byte = StartByte;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Bit = StartBit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Count = 0; Count < Units; Count++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] | (UINT8) USB_HC_BIT (Bit));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NEXT_BIT (Byte, Bit);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Block->Buf + (StartByte * 8 + StartBit) * USBHC_MEM_UNIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Calculate the corresponding pci bus address according to the Mem parameter.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Pool The memory pool of the host controller.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Mem The pointer to host memory.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Size The size of the memory region.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return the pci memory address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_PHYSICAL_ADDRESS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUsbHcGetPciAddressForHostMem (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN USBHC_MEM_POOL *Pool,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Mem,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN Size
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync USBHC_MEM_BLOCK *Head;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync USBHC_MEM_BLOCK *Block;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN AllocSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_PHYSICAL_ADDRESS PhyAddr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Offset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head = Pool->Head;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AllocSize = USBHC_MEM_ROUND (Size);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Mem == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Block = Head; Block != NULL; Block = Block->Next) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // scan the memory block list for the memory block that
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // completely contains the allocated memory.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Block->BufHost <= (UINT8 *) Mem) && (((UINT8 *) Mem + AllocSize) <= (Block->BufHost + Block->BufLen))) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT ((Block != NULL));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // calculate the pci memory address for host memory address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Offset = (UINT8 *)Mem - Block->BufHost;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PhyAddr = (EFI_PHYSICAL_ADDRESS)(UINTN) (Block->Buf + Offset);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return PhyAddr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Insert the memory block to the pool's list of the blocks.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Head The head of the memory pool's block list.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Block The memory block to insert.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUsbHcInsertMemBlockToPool (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN USBHC_MEM_BLOCK *Head,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN USBHC_MEM_BLOCK *Block
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT ((Head != NULL) && (Block != NULL));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Block->Next = Head->Next;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head->Next = Block;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Is the memory block empty?
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Block The memory block to check.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return TRUE The memory block is empty.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return FALSE The memory block isn't empty.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncBOOLEAN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUsbHcIsMemBlockEmpty (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN USBHC_MEM_BLOCK *Block
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Index;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; Index < Block->BitsLen; Index++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Block->Bits[Index] != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Unlink the memory block from the pool's list.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Head The block list head of the memory's pool.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param BlockToUnlink The memory block to unlink.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUsbHcUnlinkMemBlock (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN USBHC_MEM_BLOCK *Head,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN USBHC_MEM_BLOCK *BlockToUnlink
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync USBHC_MEM_BLOCK *Block;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT ((Head != NULL) && (BlockToUnlink != NULL));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Block = Head; Block != NULL; Block = Block->Next) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Block->Next == BlockToUnlink) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Block->Next = BlockToUnlink->Next;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BlockToUnlink->Next = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Initialize the memory management pool for the host controller.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param PciIo The PciIo that can be used to access the host controller.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Check4G Whether the host controller requires allocated memory
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync from one 4G address space.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Which4G The 4G memory area each memory allocated should be from.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return EFI_SUCCESS The memory pool is initialized.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return EFI_OUT_OF_RESOURCE Fail to init the memory pool.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUSBHC_MEM_POOL *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUsbHcInitMemPool (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_PCI_IO_PROTOCOL *PciIo,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN BOOLEAN Check4G,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 Which4G
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync USBHC_MEM_POOL *Pool;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Pool = AllocatePool (sizeof (USBHC_MEM_POOL));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Pool == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Pool;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Pool->PciIo = PciIo;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Pool->Check4G = Check4G;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Pool->Which4G = Which4G;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Pool->Head = UsbHcAllocMemBlock (Pool, USBHC_MEM_DEFAULT_PAGES);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Pool->Head == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->FreePool (Pool);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Pool = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Pool;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Release the memory management pool.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Pool The USB memory pool to free.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return EFI_SUCCESS The memory pool is freed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return EFI_DEVICE_ERROR Failed to free the memory pool.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUsbHcFreeMemPool (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN USBHC_MEM_POOL *Pool
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync USBHC_MEM_BLOCK *Block;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Pool->Head != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Unlink all the memory blocks from the pool, then free them.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // UsbHcUnlinkMemBlock can't be used to unlink and free the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // first block.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Block = Pool->Head->Next; Block != NULL; Block = Pool->Head->Next) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UsbHcUnlinkMemBlock (Pool->Head, Block);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UsbHcFreeMemBlock (Pool, Block);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UsbHcFreeMemBlock (Pool, Pool->Head);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->FreePool (Pool);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Allocate some memory from the host controller's memory pool
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync which can be used to communicate with host controller.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Pool The host controller's memory pool.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Size Size of the memory to allocate.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return The allocated memory or NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUsbHcAllocateMem (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN USBHC_MEM_POOL *Pool,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN Size
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync USBHC_MEM_BLOCK *Head;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync USBHC_MEM_BLOCK *Block;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync USBHC_MEM_BLOCK *NewBlock;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID *Mem;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN AllocSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Pages;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mem = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AllocSize = USBHC_MEM_ROUND (Size);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head = Pool->Head;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Head != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // First check whether current memory blocks can satisfy the allocation.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Block = Head; Block != NULL; Block = Block->Next) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mem = UsbHcAllocMemFromBlock (Block, AllocSize / USBHC_MEM_UNIT);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Mem != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ZeroMem (Mem, Size);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Mem != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Mem;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Create a new memory block if there is not enough memory
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // in the pool. If the allocation size is larger than the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // default page number, just allocate a large enough memory
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // block. Otherwise allocate default pages.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (AllocSize > EFI_PAGES_TO_SIZE (USBHC_MEM_DEFAULT_PAGES)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Pages = EFI_SIZE_TO_PAGES (AllocSize) + 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Pages = USBHC_MEM_DEFAULT_PAGES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewBlock = UsbHcAllocMemBlock (Pool, Pages);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NewBlock == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG ((EFI_D_INFO, "UsbHcAllocateMem: failed to allocate block\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Add the new memory block to the pool, then allocate memory from it
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UsbHcInsertMemBlockToPool (Head, NewBlock);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mem = UsbHcAllocMemFromBlock (NewBlock, AllocSize / USBHC_MEM_UNIT);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Mem != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ZeroMem (Mem, Size);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Mem;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Free the allocated memory back to the memory pool.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Pool The memory pool of the host controller.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Mem The memory to free.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Size The size of the memory to free.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUsbHcFreeMem (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN USBHC_MEM_POOL *Pool,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Mem,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN Size
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync USBHC_MEM_BLOCK *Head;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync USBHC_MEM_BLOCK *Block;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *ToFree;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN AllocSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Byte;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Bit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Count;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head = Pool->Head;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AllocSize = USBHC_MEM_ROUND (Size);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ToFree = (UINT8 *) Mem;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Block = Head; Block != NULL; Block = Block->Next) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // scan the memory block list for the memory block that
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // completely contains the memory to free.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Block->Buf <= ToFree) && ((ToFree + AllocSize) <= (Block->Buf + Block->BufLen))) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // compute the start byte and bit in the bit array
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Byte = ((ToFree - Block->Buf) / USBHC_MEM_UNIT) / 8;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Bit = ((ToFree - Block->Buf) / USBHC_MEM_UNIT) % 8;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // reset associated bits in bit arry
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Count = 0; Count < (AllocSize / USBHC_MEM_UNIT); Count++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] ^ USB_HC_BIT (Bit));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NEXT_BIT (Byte, Bit);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If Block == NULL, it means that the current memory isn't
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // in the host controller's pool. This is critical because
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // the caller has passed in a wrong memory point
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Block != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Release the current memory block if it is empty and not the head
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Block != Head) && UsbHcIsMemBlockEmpty (Block)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UsbHcUnlinkMemBlock (Head, Block);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UsbHcFreeMemBlock (Pool, Block);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}