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
13 Allocate a block of memory to be used by the buffer pool.
15 @param Pool The buffer pool to allocate memory for.
16 @param Pages How many pages to allocate.
18 @return The allocated memory block or NULL if failed.
23 IN USBHC_MEM_POOL
*Pool
,
27 USBHC_MEM_BLOCK
*Block
;
28 EFI_PCI_IO_PROTOCOL
*PciIo
;
31 EFI_PHYSICAL_ADDRESS MappedAddr
;
37 Block
= AllocateZeroPool (sizeof (USBHC_MEM_BLOCK
));
43 // each bit in the bit array represents USBHC_MEM_UNIT
44 // bytes of memory in the memory block.
46 ASSERT (USBHC_MEM_UNIT
* 8 <= EFI_PAGE_SIZE
);
48 Block
->BufLen
= EFI_PAGES_TO_SIZE (Pages
);
49 Block
->BitsLen
= Block
->BufLen
/ (USBHC_MEM_UNIT
* 8);
50 Block
->Bits
= AllocateZeroPool (Block
->BitsLen
);
52 if (Block
->Bits
== NULL
) {
53 gBS
->FreePool (Block
);
58 // Allocate the number of Pages of memory, then map it for
59 // bus master read and write.
61 Status
= PciIo
->AllocateBuffer (
70 if (EFI_ERROR (Status
)) {
74 Bytes
= EFI_PAGES_TO_SIZE (Pages
);
77 EfiPciIoOperationBusMasterCommonBuffer
,
84 if (EFI_ERROR (Status
) || (Bytes
!= EFI_PAGES_TO_SIZE (Pages
))) {
88 Block
->BufHost
= BufHost
;
89 Block
->Buf
= (UINT8
*)((UINTN
)MappedAddr
);
90 Block
->Mapping
= Mapping
;
95 PciIo
->FreeBuffer (PciIo
, Pages
, BufHost
);
98 gBS
->FreePool (Block
->Bits
);
99 gBS
->FreePool (Block
);
104 Free the memory block from the memory pool.
106 @param Pool The memory pool to free the block from.
107 @param Block The memory block to free.
112 IN USBHC_MEM_POOL
*Pool
,
113 IN USBHC_MEM_BLOCK
*Block
116 EFI_PCI_IO_PROTOCOL
*PciIo
;
118 ASSERT ((Pool
!= NULL
) && (Block
!= NULL
));
123 // Unmap the common buffer then free the structures
125 PciIo
->Unmap (PciIo
, Block
->Mapping
);
126 PciIo
->FreeBuffer (PciIo
, EFI_SIZE_TO_PAGES (Block
->BufLen
), Block
->BufHost
);
128 gBS
->FreePool (Block
->Bits
);
129 gBS
->FreePool (Block
);
133 Alloc some memory from the block.
135 @param Block The memory block to allocate memory from.
136 @param Units Number of memory units to allocate.
138 @return The pointer to the allocated memory. If couldn't allocate the needed memory,
139 the return value is NULL.
143 UsbHcAllocMemFromBlock (
144 IN USBHC_MEM_BLOCK
*Block
,
155 ASSERT ((Block
!= 0) && (Units
!= 0));
161 for (Byte
= 0, Bit
= 0; Byte
< Block
->BitsLen
;) {
163 // If current bit is zero, the corresponding memory unit is
164 // available, otherwise we need to restart our searching.
165 // Available counts the consective number of zero bit.
167 if (!USB_HC_BIT_IS_SET (Block
->Bits
[Byte
], Bit
)) {
170 if (Available
>= Units
) {
174 NEXT_BIT (Byte
, Bit
);
176 NEXT_BIT (Byte
, Bit
);
184 if (Available
< Units
) {
189 // Mark the memory as allocated
194 for (Count
= 0; Count
< Units
; Count
++) {
195 ASSERT (!USB_HC_BIT_IS_SET (Block
->Bits
[Byte
], Bit
));
197 Block
->Bits
[Byte
] = (UINT8
)(Block
->Bits
[Byte
] | USB_HC_BIT (Bit
));
198 NEXT_BIT (Byte
, Bit
);
201 return Block
->BufHost
+ (StartByte
* 8 + StartBit
) * USBHC_MEM_UNIT
;
205 Calculate the corresponding pci bus address according to the Mem parameter.
207 @param Pool The memory pool of the host controller.
208 @param Mem The pointer to host memory.
209 @param Size The size of the memory region.
211 @return The pci memory address
215 UsbHcGetPciAddrForHostAddr (
216 IN USBHC_MEM_POOL
*Pool
,
221 USBHC_MEM_BLOCK
*Head
;
222 USBHC_MEM_BLOCK
*Block
;
224 EFI_PHYSICAL_ADDRESS PhyAddr
;
228 AllocSize
= USBHC_MEM_ROUND (Size
);
234 for (Block
= Head
; Block
!= NULL
; Block
= Block
->Next
) {
236 // scan the memory block list for the memory block that
237 // completely contains the allocated memory.
239 if ((Block
->BufHost
<= (UINT8
*)Mem
) && (((UINT8
*)Mem
+ AllocSize
) <= (Block
->BufHost
+ Block
->BufLen
))) {
244 ASSERT ((Block
!= NULL
));
246 // calculate the pci memory address for host memory address.
248 Offset
= (UINT8
*)Mem
- Block
->BufHost
;
249 PhyAddr
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)(Block
->Buf
+ Offset
);
254 Calculate the corresponding host address according to the pci address.
256 @param Pool The memory pool of the host controller.
257 @param Mem The pointer to pci memory.
258 @param Size The size of the memory region.
260 @return The host memory address
264 UsbHcGetHostAddrForPciAddr (
265 IN USBHC_MEM_POOL
*Pool
,
270 USBHC_MEM_BLOCK
*Head
;
271 USBHC_MEM_BLOCK
*Block
;
273 EFI_PHYSICAL_ADDRESS HostAddr
;
277 AllocSize
= USBHC_MEM_ROUND (Size
);
283 for (Block
= Head
; Block
!= NULL
; Block
= Block
->Next
) {
285 // scan the memory block list for the memory block that
286 // completely contains the allocated memory.
288 if ((Block
->Buf
<= (UINT8
*)Mem
) && (((UINT8
*)Mem
+ AllocSize
) <= (Block
->Buf
+ Block
->BufLen
))) {
293 ASSERT ((Block
!= NULL
));
295 // calculate the pci memory address for host memory address.
297 Offset
= (UINT8
*)Mem
- Block
->Buf
;
298 HostAddr
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)(Block
->BufHost
+ Offset
);
303 Insert the memory block to the pool's list of the blocks.
305 @param Head The head of the memory pool's block list.
306 @param Block The memory block to insert.
310 UsbHcInsertMemBlockToPool (
311 IN USBHC_MEM_BLOCK
*Head
,
312 IN USBHC_MEM_BLOCK
*Block
315 ASSERT ((Head
!= NULL
) && (Block
!= NULL
));
316 Block
->Next
= Head
->Next
;
321 Is the memory block empty?
323 @param Block The memory block to check.
325 @retval TRUE The memory block is empty.
326 @retval FALSE The memory block isn't empty.
330 UsbHcIsMemBlockEmpty (
331 IN USBHC_MEM_BLOCK
*Block
336 for (Index
= 0; Index
< Block
->BitsLen
; Index
++) {
337 if (Block
->Bits
[Index
] != 0) {
346 Unlink the memory block from the pool's list.
348 @param Head The block list head of the memory's pool.
349 @param BlockToUnlink The memory block to unlink.
353 UsbHcUnlinkMemBlock (
354 IN USBHC_MEM_BLOCK
*Head
,
355 IN USBHC_MEM_BLOCK
*BlockToUnlink
358 USBHC_MEM_BLOCK
*Block
;
360 ASSERT ((Head
!= NULL
) && (BlockToUnlink
!= NULL
));
362 for (Block
= Head
; Block
!= NULL
; Block
= Block
->Next
) {
363 if (Block
->Next
== BlockToUnlink
) {
364 Block
->Next
= BlockToUnlink
->Next
;
365 BlockToUnlink
->Next
= NULL
;
372 Initialize the memory management pool for the host controller.
374 @param PciIo The PciIo that can be used to access the host controller.
376 @retval EFI_SUCCESS The memory pool is initialized.
377 @retval EFI_OUT_OF_RESOURCE Fail to init the memory pool.
382 IN EFI_PCI_IO_PROTOCOL
*PciIo
385 USBHC_MEM_POOL
*Pool
;
387 Pool
= AllocatePool (sizeof (USBHC_MEM_POOL
));
394 Pool
->Head
= UsbHcAllocMemBlock (Pool
, USBHC_MEM_DEFAULT_PAGES
);
396 if (Pool
->Head
== NULL
) {
397 gBS
->FreePool (Pool
);
405 Release the memory management pool.
407 @param Pool The USB memory pool to free.
409 @retval EFI_SUCCESS The memory pool is freed.
410 @retval EFI_DEVICE_ERROR Failed to free the memory pool.
415 IN USBHC_MEM_POOL
*Pool
418 USBHC_MEM_BLOCK
*Block
;
420 ASSERT (Pool
->Head
!= NULL
);
423 // Unlink all the memory blocks from the pool, then free them.
424 // UsbHcUnlinkMemBlock can't be used to unlink and free the
427 for (Block
= Pool
->Head
->Next
; Block
!= NULL
; Block
= Pool
->Head
->Next
) {
428 UsbHcUnlinkMemBlock (Pool
->Head
, Block
);
429 UsbHcFreeMemBlock (Pool
, Block
);
432 UsbHcFreeMemBlock (Pool
, Pool
->Head
);
433 gBS
->FreePool (Pool
);
438 Allocate some memory from the host controller's memory pool
439 which can be used to communicate with host controller.
441 @param Pool The host controller's memory pool.
442 @param Size Size of the memory to allocate.
444 @return The allocated memory or NULL.
449 IN USBHC_MEM_POOL
*Pool
,
453 USBHC_MEM_BLOCK
*Head
;
454 USBHC_MEM_BLOCK
*Block
;
455 USBHC_MEM_BLOCK
*NewBlock
;
461 AllocSize
= USBHC_MEM_ROUND (Size
);
463 ASSERT (Head
!= NULL
);
466 // First check whether current memory blocks can satisfy the allocation.
468 for (Block
= Head
; Block
!= NULL
; Block
= Block
->Next
) {
469 Mem
= UsbHcAllocMemFromBlock (Block
, AllocSize
/ USBHC_MEM_UNIT
);
482 // Create a new memory block if there is not enough memory
483 // in the pool. If the allocation size is larger than the
484 // default page number, just allocate a large enough memory
485 // block. Otherwise allocate default pages.
487 if (AllocSize
> EFI_PAGES_TO_SIZE (USBHC_MEM_DEFAULT_PAGES
)) {
488 Pages
= EFI_SIZE_TO_PAGES (AllocSize
) + 1;
490 Pages
= USBHC_MEM_DEFAULT_PAGES
;
493 NewBlock
= UsbHcAllocMemBlock (Pool
, Pages
);
495 if (NewBlock
== NULL
) {
496 DEBUG ((DEBUG_ERROR
, "UsbHcAllocateMem: failed to allocate block\n"));
501 // Add the new memory block to the pool, then allocate memory from it
503 UsbHcInsertMemBlockToPool (Head
, NewBlock
);
504 Mem
= UsbHcAllocMemFromBlock (NewBlock
, AllocSize
/ USBHC_MEM_UNIT
);
514 Free the allocated memory back to the memory pool.
516 @param Pool The memory pool of the host controller.
517 @param Mem The memory to free.
518 @param Size The size of the memory to free.
523 IN USBHC_MEM_POOL
*Pool
,
528 USBHC_MEM_BLOCK
*Head
;
529 USBHC_MEM_BLOCK
*Block
;
537 AllocSize
= USBHC_MEM_ROUND (Size
);
538 ToFree
= (UINT8
*)Mem
;
540 for (Block
= Head
; Block
!= NULL
; Block
= Block
->Next
) {
542 // scan the memory block list for the memory block that
543 // completely contains the memory to free.
545 if ((Block
->BufHost
<= ToFree
) && ((ToFree
+ AllocSize
) <= (Block
->BufHost
+ Block
->BufLen
))) {
547 // compute the start byte and bit in the bit array
549 Byte
= ((ToFree
- Block
->BufHost
) / USBHC_MEM_UNIT
) / 8;
550 Bit
= ((ToFree
- Block
->BufHost
) / USBHC_MEM_UNIT
) % 8;
553 // reset associated bits in bit array
555 for (Count
= 0; Count
< (AllocSize
/ USBHC_MEM_UNIT
); Count
++) {
556 ASSERT (USB_HC_BIT_IS_SET (Block
->Bits
[Byte
], Bit
));
558 Block
->Bits
[Byte
] = (UINT8
)(Block
->Bits
[Byte
] ^ USB_HC_BIT (Bit
));
559 NEXT_BIT (Byte
, Bit
);
567 // If Block == NULL, it means that the current memory isn't
568 // in the host controller's pool. This is critical because
569 // the caller has passed in a wrong memory point
571 ASSERT (Block
!= NULL
);
574 // Release the current memory block if it is empty and not the head
576 if ((Block
!= Head
) && UsbHcIsMemBlockEmpty (Block
)) {
577 UsbHcUnlinkMemBlock (Head
, Block
);
578 UsbHcFreeMemBlock (Pool
, Block
);
585 Allocates pages at a specified alignment that are suitable for an EfiPciIoOperationBusMasterCommonBuffer mapping.
587 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
589 @param PciIo The PciIo that can be used to access the host controller.
590 @param Pages The number of pages to allocate.
591 @param Alignment The requested alignment of the allocation. Must be a power of two.
592 @param HostAddress The system memory address to map to the PCI controller.
593 @param DeviceAddress The resulting map address for the bus master PCI controller to
594 use to access the hosts HostAddress.
595 @param Mapping A resulting value to pass to Unmap().
597 @retval EFI_SUCCESS Success to allocate aligned pages.
598 @retval EFI_INVALID_PARAMETER Pages or Alignment is not valid.
599 @retval EFI_OUT_OF_RESOURCES Do not have enough resources to allocate memory.
604 UsbHcAllocateAlignedPages (
605 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
608 OUT VOID
**HostAddress
,
609 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
617 UINTN UnalignedPages
;
622 // Alignment must be a power of two or zero.
624 ASSERT ((Alignment
& (Alignment
- 1)) == 0);
626 if ((Alignment
& (Alignment
- 1)) != 0) {
627 return EFI_INVALID_PARAMETER
;
631 return EFI_INVALID_PARAMETER
;
634 if (Alignment
> EFI_PAGE_SIZE
) {
636 // Calculate the total number of pages since alignment is larger than page size.
638 AlignmentMask
= Alignment
- 1;
639 RealPages
= Pages
+ EFI_SIZE_TO_PAGES (Alignment
);
641 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
643 ASSERT (RealPages
> Pages
);
645 Status
= PciIo
->AllocateBuffer (
653 if (EFI_ERROR (Status
)) {
654 return EFI_OUT_OF_RESOURCES
;
657 AlignedMemory
= ((UINTN
)Memory
+ AlignmentMask
) & ~AlignmentMask
;
658 UnalignedPages
= EFI_SIZE_TO_PAGES (AlignedMemory
- (UINTN
)Memory
);
659 if (UnalignedPages
> 0) {
661 // Free first unaligned page(s).
663 Status
= PciIo
->FreeBuffer (PciIo
, UnalignedPages
, Memory
);
664 ASSERT_EFI_ERROR (Status
);
667 Memory
= (VOID
*)(UINTN
)(AlignedMemory
+ EFI_PAGES_TO_SIZE (Pages
));
668 UnalignedPages
= RealPages
- Pages
- UnalignedPages
;
669 if (UnalignedPages
> 0) {
671 // Free last unaligned page(s).
673 Status
= PciIo
->FreeBuffer (PciIo
, UnalignedPages
, Memory
);
674 ASSERT_EFI_ERROR (Status
);
678 // Do not over-allocate pages in this case.
680 Status
= PciIo
->AllocateBuffer (
688 if (EFI_ERROR (Status
)) {
689 return EFI_OUT_OF_RESOURCES
;
692 AlignedMemory
= (UINTN
)Memory
;
695 Bytes
= EFI_PAGES_TO_SIZE (Pages
);
696 Status
= PciIo
->Map (
698 EfiPciIoOperationBusMasterCommonBuffer
,
699 (VOID
*)AlignedMemory
,
705 if (EFI_ERROR (Status
) || (Bytes
!= EFI_PAGES_TO_SIZE (Pages
))) {
706 Status
= PciIo
->FreeBuffer (PciIo
, Pages
, (VOID
*)AlignedMemory
);
707 return EFI_OUT_OF_RESOURCES
;
710 *HostAddress
= (VOID
*)AlignedMemory
;
716 Frees memory that was allocated with UsbHcAllocateAlignedPages().
718 @param PciIo The PciIo that can be used to access the host controller.
719 @param HostAddress The system memory address to map to the PCI controller.
720 @param Pages The number of 4 KB pages to free.
721 @param Mapping The mapping value returned from Map().
725 UsbHcFreeAlignedPages (
726 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
727 IN VOID
*HostAddress
,
736 Status
= PciIo
->Unmap (PciIo
, Mapping
);
737 ASSERT_EFI_ERROR (Status
);
739 Status
= PciIo
->FreeBuffer (
744 ASSERT_EFI_ERROR (Status
);