3 Routine procedures for memory allocate/free.
5 Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 Allocate a block of memory to be used by the buffer pool.
23 @param Pool The buffer pool to allocate memory for.
24 @param Pages How many pages to allocate.
26 @return The allocated memory block or NULL if failed.
31 IN USBHC_MEM_POOL
*Pool
,
35 USBHC_MEM_BLOCK
*Block
;
36 EFI_PCI_IO_PROTOCOL
*PciIo
;
39 EFI_PHYSICAL_ADDRESS MappedAddr
;
45 Block
= AllocateZeroPool (sizeof (USBHC_MEM_BLOCK
));
51 // each bit in the bit array represents USBHC_MEM_UNIT
52 // bytes of memory in the memory block.
54 ASSERT (USBHC_MEM_UNIT
* 8 <= EFI_PAGE_SIZE
);
56 Block
->BufLen
= EFI_PAGES_TO_SIZE (Pages
);
57 Block
->BitsLen
= Block
->BufLen
/ (USBHC_MEM_UNIT
* 8);
58 Block
->Bits
= AllocateZeroPool (Block
->BitsLen
);
60 if (Block
->Bits
== NULL
) {
61 gBS
->FreePool (Block
);
66 // Allocate the number of Pages of memory, then map it for
67 // bus master read and write.
69 Status
= PciIo
->AllocateBuffer (
78 if (EFI_ERROR (Status
)) {
82 Bytes
= EFI_PAGES_TO_SIZE (Pages
);
85 EfiPciIoOperationBusMasterCommonBuffer
,
92 if (EFI_ERROR (Status
) || (Bytes
!= EFI_PAGES_TO_SIZE (Pages
))) {
96 Block
->BufHost
= BufHost
;
97 Block
->Buf
= (UINT8
*) ((UINTN
) MappedAddr
);
98 Block
->Mapping
= Mapping
;
103 PciIo
->FreeBuffer (PciIo
, Pages
, BufHost
);
106 gBS
->FreePool (Block
->Bits
);
107 gBS
->FreePool (Block
);
113 Free the memory block from the memory pool.
115 @param Pool The memory pool to free the block from.
116 @param Block The memory block to free.
121 IN USBHC_MEM_POOL
*Pool
,
122 IN USBHC_MEM_BLOCK
*Block
125 EFI_PCI_IO_PROTOCOL
*PciIo
;
127 ASSERT ((Pool
!= NULL
) && (Block
!= NULL
));
132 // Unmap the common buffer then free the structures
134 PciIo
->Unmap (PciIo
, Block
->Mapping
);
135 PciIo
->FreeBuffer (PciIo
, EFI_SIZE_TO_PAGES (Block
->BufLen
), Block
->BufHost
);
137 gBS
->FreePool (Block
->Bits
);
138 gBS
->FreePool (Block
);
143 Alloc some memory from the block.
145 @param Block The memory block to allocate memory from.
146 @param Units Number of memory units to allocate.
148 @return The pointer to the allocated memory. If couldn't allocate the needed memory,
149 the return value is NULL.
153 UsbHcAllocMemFromBlock (
154 IN USBHC_MEM_BLOCK
*Block
,
165 ASSERT ((Block
!= 0) && (Units
!= 0));
171 for (Byte
= 0, Bit
= 0; Byte
< Block
->BitsLen
;) {
173 // If current bit is zero, the corresponding memory unit is
174 // available, otherwise we need to restart our searching.
175 // Available counts the consective number of zero bit.
177 if (!USB_HC_BIT_IS_SET (Block
->Bits
[Byte
], Bit
)) {
180 if (Available
>= Units
) {
184 NEXT_BIT (Byte
, Bit
);
187 NEXT_BIT (Byte
, Bit
);
195 if (Available
< Units
) {
200 // Mark the memory as allocated
205 for (Count
= 0; Count
< Units
; Count
++) {
206 ASSERT (!USB_HC_BIT_IS_SET (Block
->Bits
[Byte
], Bit
));
208 Block
->Bits
[Byte
] = (UINT8
) (Block
->Bits
[Byte
] | USB_HC_BIT (Bit
));
209 NEXT_BIT (Byte
, Bit
);
212 return Block
->BufHost
+ (StartByte
* 8 + StartBit
) * USBHC_MEM_UNIT
;
216 Calculate the corresponding pci bus address according to the Mem parameter.
218 @param Pool The memory pool of the host controller.
219 @param Mem The pointer to host memory.
220 @param Size The size of the memory region.
222 @return The pci memory address
226 UsbHcGetPciAddrForHostAddr (
227 IN USBHC_MEM_POOL
*Pool
,
232 USBHC_MEM_BLOCK
*Head
;
233 USBHC_MEM_BLOCK
*Block
;
235 EFI_PHYSICAL_ADDRESS PhyAddr
;
239 AllocSize
= USBHC_MEM_ROUND (Size
);
245 for (Block
= Head
; Block
!= NULL
; Block
= Block
->Next
) {
247 // scan the memory block list for the memory block that
248 // completely contains the allocated memory.
250 if ((Block
->BufHost
<= (UINT8
*) Mem
) && (((UINT8
*) Mem
+ AllocSize
) <= (Block
->BufHost
+ Block
->BufLen
))) {
255 ASSERT ((Block
!= NULL
));
257 // calculate the pci memory address for host memory address.
259 Offset
= (UINT8
*)Mem
- Block
->BufHost
;
260 PhyAddr
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) (Block
->Buf
+ Offset
);
265 Calculate the corresponding host address according to the pci address.
267 @param Pool The memory pool of the host controller.
268 @param Mem The pointer to pci memory.
269 @param Size The size of the memory region.
271 @return The host memory address
275 UsbHcGetHostAddrForPciAddr (
276 IN USBHC_MEM_POOL
*Pool
,
281 USBHC_MEM_BLOCK
*Head
;
282 USBHC_MEM_BLOCK
*Block
;
284 EFI_PHYSICAL_ADDRESS HostAddr
;
288 AllocSize
= USBHC_MEM_ROUND (Size
);
294 for (Block
= Head
; Block
!= NULL
; Block
= Block
->Next
) {
296 // scan the memory block list for the memory block that
297 // completely contains the allocated memory.
299 if ((Block
->Buf
<= (UINT8
*) Mem
) && (((UINT8
*) Mem
+ AllocSize
) <= (Block
->Buf
+ Block
->BufLen
))) {
304 ASSERT ((Block
!= NULL
));
306 // calculate the pci memory address for host memory address.
308 Offset
= (UINT8
*)Mem
- Block
->Buf
;
309 HostAddr
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) (Block
->BufHost
+ Offset
);
314 Insert the memory block to the pool's list of the blocks.
316 @param Head The head of the memory pool's block list.
317 @param Block The memory block to insert.
321 UsbHcInsertMemBlockToPool (
322 IN USBHC_MEM_BLOCK
*Head
,
323 IN USBHC_MEM_BLOCK
*Block
326 ASSERT ((Head
!= NULL
) && (Block
!= NULL
));
327 Block
->Next
= Head
->Next
;
333 Is the memory block empty?
335 @param Block The memory block to check.
337 @retval TRUE The memory block is empty.
338 @retval FALSE The memory block isn't empty.
342 UsbHcIsMemBlockEmpty (
343 IN USBHC_MEM_BLOCK
*Block
348 for (Index
= 0; Index
< Block
->BitsLen
; Index
++) {
349 if (Block
->Bits
[Index
] != 0) {
359 Unlink the memory block from the pool's list.
361 @param Head The block list head of the memory's pool.
362 @param BlockToUnlink The memory block to unlink.
366 UsbHcUnlinkMemBlock (
367 IN USBHC_MEM_BLOCK
*Head
,
368 IN USBHC_MEM_BLOCK
*BlockToUnlink
371 USBHC_MEM_BLOCK
*Block
;
373 ASSERT ((Head
!= NULL
) && (BlockToUnlink
!= NULL
));
375 for (Block
= Head
; Block
!= NULL
; Block
= Block
->Next
) {
376 if (Block
->Next
== BlockToUnlink
) {
377 Block
->Next
= BlockToUnlink
->Next
;
378 BlockToUnlink
->Next
= NULL
;
386 Initialize the memory management pool for the host controller.
388 @param PciIo The PciIo that can be used to access the host controller.
390 @retval EFI_SUCCESS The memory pool is initialized.
391 @retval EFI_OUT_OF_RESOURCE Fail to init the memory pool.
396 IN EFI_PCI_IO_PROTOCOL
*PciIo
399 USBHC_MEM_POOL
*Pool
;
401 Pool
= AllocatePool (sizeof (USBHC_MEM_POOL
));
408 Pool
->Head
= UsbHcAllocMemBlock (Pool
, USBHC_MEM_DEFAULT_PAGES
);
410 if (Pool
->Head
== NULL
) {
411 gBS
->FreePool (Pool
);
420 Release the memory management pool.
422 @param Pool The USB memory pool to free.
424 @retval EFI_SUCCESS The memory pool is freed.
425 @retval EFI_DEVICE_ERROR Failed to free the memory pool.
430 IN USBHC_MEM_POOL
*Pool
433 USBHC_MEM_BLOCK
*Block
;
435 ASSERT (Pool
->Head
!= NULL
);
438 // Unlink all the memory blocks from the pool, then free them.
439 // UsbHcUnlinkMemBlock can't be used to unlink and free the
442 for (Block
= Pool
->Head
->Next
; Block
!= NULL
; Block
= Pool
->Head
->Next
) {
443 UsbHcUnlinkMemBlock (Pool
->Head
, Block
);
444 UsbHcFreeMemBlock (Pool
, Block
);
447 UsbHcFreeMemBlock (Pool
, Pool
->Head
);
448 gBS
->FreePool (Pool
);
454 Allocate some memory from the host controller's memory pool
455 which can be used to communicate with host controller.
457 @param Pool The host controller's memory pool.
458 @param Size Size of the memory to allocate.
460 @return The allocated memory or NULL.
465 IN USBHC_MEM_POOL
*Pool
,
469 USBHC_MEM_BLOCK
*Head
;
470 USBHC_MEM_BLOCK
*Block
;
471 USBHC_MEM_BLOCK
*NewBlock
;
477 AllocSize
= USBHC_MEM_ROUND (Size
);
479 ASSERT (Head
!= NULL
);
482 // First check whether current memory blocks can satisfy the allocation.
484 for (Block
= Head
; Block
!= NULL
; Block
= Block
->Next
) {
485 Mem
= UsbHcAllocMemFromBlock (Block
, AllocSize
/ USBHC_MEM_UNIT
);
498 // Create a new memory block if there is not enough memory
499 // in the pool. If the allocation size is larger than the
500 // default page number, just allocate a large enough memory
501 // block. Otherwise allocate default pages.
503 if (AllocSize
> EFI_PAGES_TO_SIZE (USBHC_MEM_DEFAULT_PAGES
)) {
504 Pages
= EFI_SIZE_TO_PAGES (AllocSize
) + 1;
506 Pages
= USBHC_MEM_DEFAULT_PAGES
;
509 NewBlock
= UsbHcAllocMemBlock (Pool
, Pages
);
511 if (NewBlock
== NULL
) {
512 DEBUG ((EFI_D_ERROR
, "UsbHcAllocateMem: failed to allocate block\n"));
517 // Add the new memory block to the pool, then allocate memory from it
519 UsbHcInsertMemBlockToPool (Head
, NewBlock
);
520 Mem
= UsbHcAllocMemFromBlock (NewBlock
, AllocSize
/ USBHC_MEM_UNIT
);
531 Free the allocated memory back to the memory pool.
533 @param Pool The memory pool of the host controller.
534 @param Mem The memory to free.
535 @param Size The size of the memory to free.
540 IN USBHC_MEM_POOL
*Pool
,
545 USBHC_MEM_BLOCK
*Head
;
546 USBHC_MEM_BLOCK
*Block
;
554 AllocSize
= USBHC_MEM_ROUND (Size
);
555 ToFree
= (UINT8
*) Mem
;
557 for (Block
= Head
; Block
!= NULL
; Block
= Block
->Next
) {
559 // scan the memory block list for the memory block that
560 // completely contains the memory to free.
562 if ((Block
->BufHost
<= ToFree
) && ((ToFree
+ AllocSize
) <= (Block
->BufHost
+ Block
->BufLen
))) {
564 // compute the start byte and bit in the bit array
566 Byte
= ((ToFree
- Block
->BufHost
) / USBHC_MEM_UNIT
) / 8;
567 Bit
= ((ToFree
- Block
->BufHost
) / USBHC_MEM_UNIT
) % 8;
570 // reset associated bits in bit arry
572 for (Count
= 0; Count
< (AllocSize
/ USBHC_MEM_UNIT
); Count
++) {
573 ASSERT (USB_HC_BIT_IS_SET (Block
->Bits
[Byte
], Bit
));
575 Block
->Bits
[Byte
] = (UINT8
) (Block
->Bits
[Byte
] ^ USB_HC_BIT (Bit
));
576 NEXT_BIT (Byte
, Bit
);
584 // If Block == NULL, it means that the current memory isn't
585 // in the host controller's pool. This is critical because
586 // the caller has passed in a wrong memory point
588 ASSERT (Block
!= NULL
);
591 // Release the current memory block if it is empty and not the head
593 if ((Block
!= Head
) && UsbHcIsMemBlockEmpty (Block
)) {
594 UsbHcUnlinkMemBlock (Head
, Block
);
595 UsbHcFreeMemBlock (Pool
, Block
);
602 Allocates pages at a specified alignment that are suitable for an EfiPciIoOperationBusMasterCommonBuffer mapping.
604 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
606 @param PciIo The PciIo that can be used to access the host controller.
607 @param Pages The number of pages to allocate.
608 @param Alignment The requested alignment of the allocation. Must be a power of two.
609 @param HostAddress The system memory address to map to the PCI controller.
610 @param DeviceAddress The resulting map address for the bus master PCI controller to
611 use to access the hosts HostAddress.
612 @param Mapping A resulting value to pass to Unmap().
614 @retval EFI_SUCCESS Success to allocate aligned pages.
615 @retval EFI_INVALID_PARAMETER Pages or Alignment is not valid.
616 @retval EFI_OUT_OF_RESOURCES Do not have enough resources to allocate memory.
621 UsbHcAllocateAlignedPages (
622 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
625 OUT VOID
**HostAddress
,
626 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
634 UINTN UnalignedPages
;
639 // Alignment must be a power of two or zero.
641 ASSERT ((Alignment
& (Alignment
- 1)) == 0);
643 if ((Alignment
& (Alignment
- 1)) != 0) {
644 return EFI_INVALID_PARAMETER
;
648 return EFI_INVALID_PARAMETER
;
650 if (Alignment
> EFI_PAGE_SIZE
) {
652 // Calculate the total number of pages since alignment is larger than page size.
654 AlignmentMask
= Alignment
- 1;
655 RealPages
= Pages
+ EFI_SIZE_TO_PAGES (Alignment
);
657 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
659 ASSERT (RealPages
> Pages
);
661 Status
= PciIo
->AllocateBuffer (
669 if (EFI_ERROR (Status
)) {
670 return EFI_OUT_OF_RESOURCES
;
672 AlignedMemory
= ((UINTN
) Memory
+ AlignmentMask
) & ~AlignmentMask
;
673 UnalignedPages
= EFI_SIZE_TO_PAGES (AlignedMemory
- (UINTN
) Memory
);
674 if (UnalignedPages
> 0) {
676 // Free first unaligned page(s).
678 Status
= PciIo
->FreeBuffer (PciIo
, UnalignedPages
, Memory
);
679 ASSERT_EFI_ERROR (Status
);
681 Memory
= (VOID
*)(UINTN
)(AlignedMemory
+ EFI_PAGES_TO_SIZE (Pages
));
682 UnalignedPages
= RealPages
- Pages
- UnalignedPages
;
683 if (UnalignedPages
> 0) {
685 // Free last unaligned page(s).
687 Status
= PciIo
->FreeBuffer (PciIo
, UnalignedPages
, Memory
);
688 ASSERT_EFI_ERROR (Status
);
692 // Do not over-allocate pages in this case.
694 Status
= PciIo
->AllocateBuffer (
702 if (EFI_ERROR (Status
)) {
703 return EFI_OUT_OF_RESOURCES
;
705 AlignedMemory
= (UINTN
) Memory
;
708 Bytes
= EFI_PAGES_TO_SIZE (Pages
);
709 Status
= PciIo
->Map (
711 EfiPciIoOperationBusMasterCommonBuffer
,
712 (VOID
*) AlignedMemory
,
718 if (EFI_ERROR (Status
) || (Bytes
!= EFI_PAGES_TO_SIZE (Pages
))) {
719 Status
= PciIo
->FreeBuffer (PciIo
, Pages
, (VOID
*) AlignedMemory
);
720 return EFI_OUT_OF_RESOURCES
;
723 *HostAddress
= (VOID
*) AlignedMemory
;
729 Frees memory that was allocated with UsbHcAllocateAlignedPages().
731 @param PciIo The PciIo that can be used to access the host controller.
732 @param HostAddress The system memory address to map to the PCI controller.
733 @param Pages The number of 4 KB pages to free.
734 @param Mapping The mapping value returned from Map().
738 UsbHcFreeAlignedPages (
739 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
740 IN VOID
*HostAddress
,
749 Status
= PciIo
->Unmap (PciIo
, Mapping
);
750 ASSERT_EFI_ERROR (Status
);
752 Status
= PciIo
->FreeBuffer (
757 ASSERT_EFI_ERROR (Status
);