/** Free the allocated memory back to the memory pool. @param Pool The memory pool of the host controller. @param Mem The memory to free. @param Size The size of the memory to free. **/ VOID UsbHcFreeMem ( IN USBHC_MEM_POOL *Pool, IN VOID *Mem, IN UINTN Size ) { USBHC_MEM_BLOCK *Head; USBHC_MEM_BLOCK *Block; UINT8 *ToFree; UINTN AllocSize; UINTN Byte; UINTN Bit; UINTN Count; Head = Pool->Head; AllocSize = USBHC_MEM_ROUND (Size); ToFree = (UINT8 *) Mem; for (Block = Head; Block != NULL; Block = Block->Next) { // // scan the memory block list for the memory block that // completely contains the memory to free. // if ((Block->BufHost <= ToFree) && ((ToFree + AllocSize) <= (Block->BufHost + Block->BufLen))) { // // compute the start byte and bit in the bit array // Byte = ((ToFree - Block->BufHost) / USBHC_MEM_UNIT) / 8; Bit = ((ToFree - Block->BufHost) / USBHC_MEM_UNIT) % 8; // // reset associated bits in bit array // for (Count = 0; Count < (AllocSize / USBHC_MEM_UNIT); Count++) { ASSERT (USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit)); Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] ^ USB_HC_BIT (Bit)); NEXT_BIT (Byte, Bit); } break; } } // // If Block == NULL, it means that the current memory isn't // in the host controller's pool. This is critical because // the caller has passed in a wrong memory pointer // ASSERT (Block != NULL); // // Release the current memory block if it is empty and not the head // if ((Block != Head) && UsbHcIsMemBlockEmpty (Block)) { //UsbHcUnlinkMemBlock (Head, Block); UsbHcFreeMemBlock (Pool, Block); } }
/** Calculate the corresponding host address according to the pci address. @param Pool The memory pool of the host controller. @param Mem The pointer to pci memory. @param Size The size of the memory region. @return The host memory address **/ EFI_PHYSICAL_ADDRESS UsbHcGetHostAddrForPciAddr ( IN USBHC_MEM_POOL *Pool, IN VOID *Mem, IN UINTN Size ) { USBHC_MEM_BLOCK *Head; USBHC_MEM_BLOCK *Block; UINTN AllocSize; EFI_PHYSICAL_ADDRESS HostAddr; UINTN Offset; Head = Pool->Head; AllocSize = USBHC_MEM_ROUND (Size); if (Mem == NULL) { return 0; } for (Block = Head; Block != NULL; Block = Block->Next) { // // scan the memory block list for the memory block that // completely contains the allocated memory. // if ((Block->Buf <= (UINT8 *) Mem) && (((UINT8 *) Mem + AllocSize) <= (Block->Buf + Block->BufLen))) { break; } } ASSERT ((Block != NULL)); // // calculate the pci memory address for host memory address. // Offset = (UINT8 *)Mem - Block->Buf; HostAddr = (EFI_PHYSICAL_ADDRESS)(UINTN) (Block->BufHost + Offset); return HostAddr; }
/** Allocate some memory from the host controller's memory pool which can be used to communicate with host controller. @param Pool The host controller's memory pool. @param Size Size of the memory to allocate. @return The allocated memory or NULL. **/ VOID * UsbHcAllocateMem ( IN USBHC_MEM_POOL *Pool, IN UINTN Size ) { USBHC_MEM_BLOCK *Head; USBHC_MEM_BLOCK *Block; USBHC_MEM_BLOCK *NewBlock; VOID *Mem; UINTN AllocSize; UINTN Pages; Mem = NULL; AllocSize = USBHC_MEM_ROUND (Size); Head = Pool->Head; ASSERT (Head != NULL); // // First check whether current memory blocks can satisfy the allocation. // for (Block = Head; Block != NULL; Block = Block->Next) { Mem = UsbHcAllocMemFromBlock (Block, AllocSize / USBHC_MEM_UNIT); if (Mem != NULL) { ZeroMem (Mem, Size); break; } } if (Mem != NULL) { return Mem; } // // Create a new memory block if there is not enough memory // in the pool. If the allocation size is larger than the // default page number, just allocate a large enough memory // block. Otherwise allocate default pages. // if (AllocSize > EFI_PAGES_TO_SIZE (USBHC_MEM_DEFAULT_PAGES)) { Pages = EFI_SIZE_TO_PAGES (AllocSize) + 1; } else { Pages = USBHC_MEM_DEFAULT_PAGES; } NewBlock = UsbHcAllocMemBlock (Pool, Pages); if (NewBlock == NULL) { DEBUG ((EFI_D_ERROR, "UsbHcAllocateMem: failed to allocate block\n")); return NULL; } // // Add the new memory block to the pool, then allocate memory from it // UsbHcInsertMemBlockToPool (Head, NewBlock); Mem = UsbHcAllocMemFromBlock (NewBlock, AllocSize / USBHC_MEM_UNIT); if (Mem != NULL) { ZeroMem (Mem, Size); } return Mem; }