/** 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); } }
/** Alloc some memory from the block. @param Block The memory block to allocate memory from. @param Units Number of memory units to allocate. @return The pointer to the allocated memory. If couldn't allocate the needed memory, the return value is NULL. **/ VOID * UsbHcAllocMemFromBlock ( IN USBHC_MEM_BLOCK *Block, IN UINTN Units ) { UINTN Byte; UINT8 Bit; UINTN StartByte; UINT8 StartBit; UINTN Available; UINTN Count; ASSERT ((Block != 0) && (Units != 0)); StartByte = 0; StartBit = 0; Available = 0; for (Byte = 0, Bit = 0; Byte < Block->BitsLen;) { // // If current bit is zero, the corresponding memory unit is // available, otherwise we need to restart our searching. // Available counts the consective number of zero bit. // if (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit)) { Available++; if (Available >= Units) { break; } NEXT_BIT (Byte, Bit); } else { NEXT_BIT (Byte, Bit); Available = 0; StartByte = Byte; StartBit = Bit; } } if (Available < Units) { return NULL; } // // Mark the memory as allocated // Byte = StartByte; Bit = StartBit; for (Count = 0; Count < Units; 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); } return Block->BufHost + (StartByte * 8 + StartBit) * USBHC_MEM_UNIT; }