3 Routine procedures for memory allocate/free.
5 Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
15 Allocate a block of memory to be used by the buffer pool.
17 @param Pool The buffer pool to allocate memory for.
18 @param Pages How many pages to allocate.
20 @return The allocated memory block or NULL if failed.
25 IN USBHC_MEM_POOL
*Pool
,
29 USBHC_MEM_BLOCK
*Block
;
30 EFI_PCI_IO_PROTOCOL
*PciIo
;
33 EFI_PHYSICAL_ADDRESS MappedAddr
;
39 Block
= AllocateZeroPool (sizeof (USBHC_MEM_BLOCK
));
45 // each bit in the bit array represents USBHC_MEM_UNIT
46 // bytes of memory in the memory block.
48 ASSERT (USBHC_MEM_UNIT
* 8 <= EFI_PAGE_SIZE
);
50 Block
->BufLen
= EFI_PAGES_TO_SIZE (Pages
);
51 Block
->BitsLen
= Block
->BufLen
/ (USBHC_MEM_UNIT
* 8);
52 Block
->Bits
= AllocateZeroPool (Block
->BitsLen
);
54 if (Block
->Bits
== NULL
) {
55 gBS
->FreePool (Block
);
60 // Allocate the number of Pages of memory, then map it for
61 // bus master read and write.
63 Status
= PciIo
->AllocateBuffer (
72 if (EFI_ERROR (Status
)) {
76 Bytes
= EFI_PAGES_TO_SIZE (Pages
);
79 EfiPciIoOperationBusMasterCommonBuffer
,
86 if (EFI_ERROR (Status
) || (Bytes
!= EFI_PAGES_TO_SIZE (Pages
))) {
90 Block
->BufHost
= BufHost
;
91 Block
->Buf
= (UINT8
*) ((UINTN
) MappedAddr
);
92 Block
->Mapping
= Mapping
;
97 PciIo
->FreeBuffer (PciIo
, Pages
, BufHost
);
100 gBS
->FreePool (Block
->Bits
);
101 gBS
->FreePool (Block
);
107 Free the memory block from the memory pool.
109 @param Pool The memory pool to free the block from.
110 @param Block The memory block to free.
115 IN USBHC_MEM_POOL
*Pool
,
116 IN USBHC_MEM_BLOCK
*Block
119 EFI_PCI_IO_PROTOCOL
*PciIo
;
121 ASSERT ((Pool
!= NULL
) && (Block
!= NULL
));
126 // Unmap the common buffer then free the structures
128 PciIo
->Unmap (PciIo
, Block
->Mapping
);
129 PciIo
->FreeBuffer (PciIo
, EFI_SIZE_TO_PAGES (Block
->BufLen
), Block
->BufHost
);
131 gBS
->FreePool (Block
->Bits
);
132 gBS
->FreePool (Block
);
137 Alloc some memory from the block.
139 @param Block The memory block to allocate memory from.
140 @param Units Number of memory units to allocate.
142 @return The pointer to the allocated memory. If couldn't allocate the needed memory,
143 the return value is NULL.
147 UsbHcAllocMemFromBlock (
148 IN USBHC_MEM_BLOCK
*Block
,
159 ASSERT ((Block
!= 0) && (Units
!= 0));
165 for (Byte
= 0, Bit
= 0; Byte
< Block
->BitsLen
;) {
167 // If current bit is zero, the corresponding memory unit is
168 // available, otherwise we need to restart our searching.
169 // Available counts the consective number of zero bit.
171 if (!USB_HC_BIT_IS_SET (Block
->Bits
[Byte
], Bit
)) {
174 if (Available
>= Units
) {
178 NEXT_BIT (Byte
, Bit
);
181 NEXT_BIT (Byte
, Bit
);
189 if (Available
< Units
) {
194 // Mark the memory as allocated
199 for (Count
= 0; Count
< Units
; Count
++) {
200 ASSERT (!USB_HC_BIT_IS_SET (Block
->Bits
[Byte
], Bit
));
202 Block
->Bits
[Byte
] = (UINT8
) (Block
->Bits
[Byte
] | USB_HC_BIT (Bit
));
203 NEXT_BIT (Byte
, Bit
);
206 return Block
->BufHost
+ (StartByte
* 8 + StartBit
) * USBHC_MEM_UNIT
;
210 Calculate the corresponding pci bus address according to the Mem parameter.
212 @param Pool The memory pool of the host controller.
213 @param Mem The pointer to host memory.
214 @param Size The size of the memory region.
216 @return The pci memory address
220 UsbHcGetPciAddrForHostAddr (
221 IN USBHC_MEM_POOL
*Pool
,
226 USBHC_MEM_BLOCK
*Head
;
227 USBHC_MEM_BLOCK
*Block
;
229 EFI_PHYSICAL_ADDRESS PhyAddr
;
233 AllocSize
= USBHC_MEM_ROUND (Size
);
239 for (Block
= Head
; Block
!= NULL
; Block
= Block
->Next
) {
241 // scan the memory block list for the memory block that
242 // completely contains the allocated memory.
244 if ((Block
->BufHost
<= (UINT8
*) Mem
) && (((UINT8
*) Mem
+ AllocSize
) <= (Block
->BufHost
+ Block
->BufLen
))) {
249 ASSERT ((Block
!= NULL
));
251 // calculate the pci memory address for host memory address.
253 Offset
= (UINT8
*)Mem
- Block
->BufHost
;
254 PhyAddr
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) (Block
->Buf
+ Offset
);
259 Calculate the corresponding host address according to the pci address.
261 @param Pool The memory pool of the host controller.
262 @param Mem The pointer to pci memory.
263 @param Size The size of the memory region.
265 @return The host memory address
269 UsbHcGetHostAddrForPciAddr (
270 IN USBHC_MEM_POOL
*Pool
,
275 USBHC_MEM_BLOCK
*Head
;
276 USBHC_MEM_BLOCK
*Block
;
278 EFI_PHYSICAL_ADDRESS HostAddr
;
282 AllocSize
= USBHC_MEM_ROUND (Size
);
288 for (Block
= Head
; Block
!= NULL
; Block
= Block
->Next
) {
290 // scan the memory block list for the memory block that
291 // completely contains the allocated memory.
293 if ((Block
->Buf
<= (UINT8
*) Mem
) && (((UINT8
*) Mem
+ AllocSize
) <= (Block
->Buf
+ Block
->BufLen
))) {
298 ASSERT ((Block
!= NULL
));
300 // calculate the pci memory address for host memory address.
302 Offset
= (UINT8
*)Mem
- Block
->Buf
;
303 HostAddr
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) (Block
->BufHost
+ Offset
);
308 Insert the memory block to the pool's list of the blocks.
310 @param Head The head of the memory pool's block list.
311 @param Block The memory block to insert.
315 UsbHcInsertMemBlockToPool (
316 IN USBHC_MEM_BLOCK
*Head
,
317 IN USBHC_MEM_BLOCK
*Block
320 ASSERT ((Head
!= NULL
) && (Block
!= NULL
));
321 Block
->Next
= Head
->Next
;
327 Is the memory block empty?
329 @param Block The memory block to check.
331 @retval TRUE The memory block is empty.
332 @retval FALSE The memory block isn't empty.
336 UsbHcIsMemBlockEmpty (
337 IN USBHC_MEM_BLOCK
*Block
342 for (Index
= 0; Index
< Block
->BitsLen
; Index
++) {
343 if (Block
->Bits
[Index
] != 0) {
353 Unlink the memory block from the pool's list.
355 @param Head The block list head of the memory's pool.
356 @param BlockToUnlink The memory block to unlink.
360 UsbHcUnlinkMemBlock (
361 IN USBHC_MEM_BLOCK
*Head
,
362 IN USBHC_MEM_BLOCK
*BlockToUnlink
365 USBHC_MEM_BLOCK
*Block
;
367 ASSERT ((Head
!= NULL
) && (BlockToUnlink
!= NULL
));
369 for (Block
= Head
; Block
!= NULL
; Block
= Block
->Next
) {
370 if (Block
->Next
== BlockToUnlink
) {
371 Block
->Next
= BlockToUnlink
->Next
;
372 BlockToUnlink
->Next
= NULL
;
380 Initialize the memory management pool for the host controller.
382 @param PciIo The PciIo that can be used to access the host controller.
384 @retval EFI_SUCCESS The memory pool is initialized.
385 @retval EFI_OUT_OF_RESOURCE Fail to init the memory pool.
390 IN EFI_PCI_IO_PROTOCOL
*PciIo
393 USBHC_MEM_POOL
*Pool
;
395 Pool
= AllocatePool (sizeof (USBHC_MEM_POOL
));
402 Pool
->Head
= UsbHcAllocMemBlock (Pool
, USBHC_MEM_DEFAULT_PAGES
);
404 if (Pool
->Head
== NULL
) {
405 gBS
->FreePool (Pool
);
414 Release the memory management pool.
416 @param Pool The USB memory pool to free.
418 @retval EFI_SUCCESS The memory pool is freed.
419 @retval EFI_DEVICE_ERROR Failed to free the memory pool.
424 IN USBHC_MEM_POOL
*Pool
427 USBHC_MEM_BLOCK
*Block
;
429 ASSERT (Pool
->Head
!= NULL
);
432 // Unlink all the memory blocks from the pool, then free them.
433 // UsbHcUnlinkMemBlock can't be used to unlink and free the
436 for (Block
= Pool
->Head
->Next
; Block
!= NULL
; Block
= Pool
->Head
->Next
) {
437 UsbHcUnlinkMemBlock (Pool
->Head
, Block
);
438 UsbHcFreeMemBlock (Pool
, Block
);
441 UsbHcFreeMemBlock (Pool
, Pool
->Head
);
442 gBS
->FreePool (Pool
);
448 Allocate some memory from the host controller's memory pool
449 which can be used to communicate with host controller.
451 @param Pool The host controller's memory pool.
452 @param Size Size of the memory to allocate.
454 @return The allocated memory or NULL.
459 IN USBHC_MEM_POOL
*Pool
,
463 USBHC_MEM_BLOCK
*Head
;
464 USBHC_MEM_BLOCK
*Block
;
465 USBHC_MEM_BLOCK
*NewBlock
;
471 AllocSize
= USBHC_MEM_ROUND (Size
);
473 ASSERT (Head
!= NULL
);
476 // First check whether current memory blocks can satisfy the allocation.
478 for (Block
= Head
; Block
!= NULL
; Block
= Block
->Next
) {
479 Mem
= UsbHcAllocMemFromBlock (Block
, AllocSize
/ USBHC_MEM_UNIT
);
492 // Create a new memory block if there is not enough memory
493 // in the pool. If the allocation size is larger than the
494 // default page number, just allocate a large enough memory
495 // block. Otherwise allocate default pages.
497 if (AllocSize
> EFI_PAGES_TO_SIZE (USBHC_MEM_DEFAULT_PAGES
)) {
498 Pages
= EFI_SIZE_TO_PAGES (AllocSize
) + 1;
500 Pages
= USBHC_MEM_DEFAULT_PAGES
;
503 NewBlock
= UsbHcAllocMemBlock (Pool
, Pages
);
505 if (NewBlock
== NULL
) {
506 DEBUG ((EFI_D_ERROR
, "UsbHcAllocateMem: failed to allocate block\n"));
511 // Add the new memory block to the pool, then allocate memory from it
513 UsbHcInsertMemBlockToPool (Head
, NewBlock
);
514 Mem
= UsbHcAllocMemFromBlock (NewBlock
, AllocSize
/ USBHC_MEM_UNIT
);
525 Free the allocated memory back to the memory pool.
527 @param Pool The memory pool of the host controller.
528 @param Mem The memory to free.
529 @param Size The size of the memory to free.
534 IN USBHC_MEM_POOL
*Pool
,
539 USBHC_MEM_BLOCK
*Head
;
540 USBHC_MEM_BLOCK
*Block
;
548 AllocSize
= USBHC_MEM_ROUND (Size
);
549 ToFree
= (UINT8
*) Mem
;
551 for (Block
= Head
; Block
!= NULL
; Block
= Block
->Next
) {
553 // scan the memory block list for the memory block that
554 // completely contains the memory to free.
556 if ((Block
->BufHost
<= ToFree
) && ((ToFree
+ AllocSize
) <= (Block
->BufHost
+ Block
->BufLen
))) {
558 // compute the start byte and bit in the bit array
560 Byte
= ((ToFree
- Block
->BufHost
) / USBHC_MEM_UNIT
) / 8;
561 Bit
= ((ToFree
- Block
->BufHost
) / USBHC_MEM_UNIT
) % 8;
564 // reset associated bits in bit array
566 for (Count
= 0; Count
< (AllocSize
/ USBHC_MEM_UNIT
); Count
++) {
567 ASSERT (USB_HC_BIT_IS_SET (Block
->Bits
[Byte
], Bit
));
569 Block
->Bits
[Byte
] = (UINT8
) (Block
->Bits
[Byte
] ^ USB_HC_BIT (Bit
));
570 NEXT_BIT (Byte
, Bit
);
578 // If Block == NULL, it means that the current memory isn't
579 // in the host controller's pool. This is critical because
580 // the caller has passed in a wrong memory point
582 ASSERT (Block
!= NULL
);
585 // Release the current memory block if it is empty and not the head
587 if ((Block
!= Head
) && UsbHcIsMemBlockEmpty (Block
)) {
588 UsbHcUnlinkMemBlock (Head
, Block
);
589 UsbHcFreeMemBlock (Pool
, Block
);
596 Allocates pages at a specified alignment that are suitable for an EfiPciIoOperationBusMasterCommonBuffer mapping.
598 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
600 @param PciIo The PciIo that can be used to access the host controller.
601 @param Pages The number of pages to allocate.
602 @param Alignment The requested alignment of the allocation. Must be a power of two.
603 @param HostAddress The system memory address to map to the PCI controller.
604 @param DeviceAddress The resulting map address for the bus master PCI controller to
605 use to access the hosts HostAddress.
606 @param Mapping A resulting value to pass to Unmap().
608 @retval EFI_SUCCESS Success to allocate aligned pages.
609 @retval EFI_INVALID_PARAMETER Pages or Alignment is not valid.
610 @retval EFI_OUT_OF_RESOURCES Do not have enough resources to allocate memory.
615 UsbHcAllocateAlignedPages (
616 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
619 OUT VOID
**HostAddress
,
620 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
628 UINTN UnalignedPages
;
633 // Alignment must be a power of two or zero.
635 ASSERT ((Alignment
& (Alignment
- 1)) == 0);
637 if ((Alignment
& (Alignment
- 1)) != 0) {
638 return EFI_INVALID_PARAMETER
;
642 return EFI_INVALID_PARAMETER
;
644 if (Alignment
> EFI_PAGE_SIZE
) {
646 // Calculate the total number of pages since alignment is larger than page size.
648 AlignmentMask
= Alignment
- 1;
649 RealPages
= Pages
+ EFI_SIZE_TO_PAGES (Alignment
);
651 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
653 ASSERT (RealPages
> Pages
);
655 Status
= PciIo
->AllocateBuffer (
663 if (EFI_ERROR (Status
)) {
664 return EFI_OUT_OF_RESOURCES
;
666 AlignedMemory
= ((UINTN
) Memory
+ AlignmentMask
) & ~AlignmentMask
;
667 UnalignedPages
= EFI_SIZE_TO_PAGES (AlignedMemory
- (UINTN
) Memory
);
668 if (UnalignedPages
> 0) {
670 // Free first unaligned page(s).
672 Status
= PciIo
->FreeBuffer (PciIo
, UnalignedPages
, Memory
);
673 ASSERT_EFI_ERROR (Status
);
675 Memory
= (VOID
*)(UINTN
)(AlignedMemory
+ EFI_PAGES_TO_SIZE (Pages
));
676 UnalignedPages
= RealPages
- Pages
- UnalignedPages
;
677 if (UnalignedPages
> 0) {
679 // Free last unaligned page(s).
681 Status
= PciIo
->FreeBuffer (PciIo
, UnalignedPages
, Memory
);
682 ASSERT_EFI_ERROR (Status
);
686 // Do not over-allocate pages in this case.
688 Status
= PciIo
->AllocateBuffer (
696 if (EFI_ERROR (Status
)) {
697 return EFI_OUT_OF_RESOURCES
;
699 AlignedMemory
= (UINTN
) Memory
;
702 Bytes
= EFI_PAGES_TO_SIZE (Pages
);
703 Status
= PciIo
->Map (
705 EfiPciIoOperationBusMasterCommonBuffer
,
706 (VOID
*) AlignedMemory
,
712 if (EFI_ERROR (Status
) || (Bytes
!= EFI_PAGES_TO_SIZE (Pages
))) {
713 Status
= PciIo
->FreeBuffer (PciIo
, Pages
, (VOID
*) AlignedMemory
);
714 return EFI_OUT_OF_RESOURCES
;
717 *HostAddress
= (VOID
*) AlignedMemory
;
723 Frees memory that was allocated with UsbHcAllocateAlignedPages().
725 @param PciIo The PciIo that can be used to access the host controller.
726 @param HostAddress The system memory address to map to the PCI controller.
727 @param Pages The number of 4 KB pages to free.
728 @param Mapping The mapping value returned from Map().
732 UsbHcFreeAlignedPages (
733 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
734 IN VOID
*HostAddress
,
743 Status
= PciIo
->Unmap (PciIo
, Mapping
);
744 ASSERT_EFI_ERROR (Status
);
746 Status
= PciIo
->FreeBuffer (
751 ASSERT_EFI_ERROR (Status
);