]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / XhciPei / UsbHcMem.c
CommitLineData
d987459f
SZ
1/** @file\r
2PEIM to produce gPeiUsb2HostControllerPpiGuid based on gPeiUsbControllerPpiGuid\r
3which is used to enable recovery function from USB Drivers.\r
4\r
2048c585 5Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>\r
47ab3970 6Copyright (C) 2022 Advanced Micro Devices, Inc. All rights reserved.<BR>\r
d987459f 7\r
9d510e61 8SPDX-License-Identifier: BSD-2-Clause-Patent\r
d987459f
SZ
9\r
10**/\r
11\r
12#include "XhcPeim.h"\r
13\r
14/**\r
15 Allocate a block of memory to be used by the buffer pool.\r
16\r
17 @param Pages How many pages to allocate.\r
18\r
19 @return Pointer to the allocated memory block or NULL if failed.\r
20\r
21**/\r
22USBHC_MEM_BLOCK *\r
23UsbHcAllocMemBlock (\r
1436aea4 24 IN UINTN Pages\r
d987459f
SZ
25 )\r
26{\r
27 USBHC_MEM_BLOCK *Block;\r
b575ca32
JY
28 VOID *BufHost;\r
29 VOID *Mapping;\r
30 EFI_PHYSICAL_ADDRESS MappedAddr;\r
d987459f
SZ
31 EFI_STATUS Status;\r
32 UINTN PageNumber;\r
33 EFI_PHYSICAL_ADDRESS TempPtr;\r
34\r
35 PageNumber = EFI_SIZE_TO_PAGES (sizeof (USBHC_MEM_BLOCK));\r
1436aea4
MK
36 Status = PeiServicesAllocatePages (\r
37 EfiBootServicesData,\r
38 PageNumber,\r
39 &TempPtr\r
40 );\r
d987459f
SZ
41\r
42 if (EFI_ERROR (Status)) {\r
43 return NULL;\r
44 }\r
1436aea4
MK
45\r
46 ZeroMem ((VOID *)(UINTN)TempPtr, EFI_PAGES_TO_SIZE (PageNumber));\r
d987459f
SZ
47\r
48 //\r
49 // each bit in the bit array represents USBHC_MEM_UNIT\r
50 // bytes of memory in the memory block.\r
51 //\r
52 ASSERT (USBHC_MEM_UNIT * 8 <= EFI_PAGE_SIZE);\r
53\r
1436aea4
MK
54 Block = (USBHC_MEM_BLOCK *)(UINTN)TempPtr;\r
55 Block->BufLen = EFI_PAGES_TO_SIZE (Pages);\r
d987459f
SZ
56 Block->BitsLen = Block->BufLen / (USBHC_MEM_UNIT * 8);\r
57\r
58 PageNumber = EFI_SIZE_TO_PAGES (Block->BitsLen);\r
1436aea4
MK
59 Status = PeiServicesAllocatePages (\r
60 EfiBootServicesData,\r
61 PageNumber,\r
62 &TempPtr\r
63 );\r
d987459f
SZ
64\r
65 if (EFI_ERROR (Status)) {\r
66 return NULL;\r
67 }\r
d987459f 68\r
1436aea4
MK
69 ZeroMem ((VOID *)(UINTN)TempPtr, EFI_PAGES_TO_SIZE (PageNumber));\r
70\r
71 Block->Bits = (UINT8 *)(UINTN)TempPtr;\r
d987459f 72\r
b575ca32 73 Status = IoMmuAllocateBuffer (\r
d987459f 74 Pages,\r
b575ca32
JY
75 &BufHost,\r
76 &MappedAddr,\r
77 &Mapping\r
d987459f
SZ
78 );\r
79 if (EFI_ERROR (Status)) {\r
80 return NULL;\r
81 }\r
d987459f 82\r
1436aea4
MK
83 ZeroMem ((VOID *)(UINTN)BufHost, EFI_PAGES_TO_SIZE (Pages));\r
84\r
85 Block->BufHost = (UINT8 *)(UINTN)BufHost;\r
86 Block->Buf = (UINT8 *)(UINTN)MappedAddr;\r
87 Block->Mapping = Mapping;\r
88 Block->Next = NULL;\r
d987459f
SZ
89\r
90 return Block;\r
91}\r
92\r
93/**\r
94 Free the memory block from the memory pool.\r
95\r
96 @param Pool The memory pool to free the block from.\r
97 @param Block The memory block to free.\r
98\r
99**/\r
100VOID\r
101UsbHcFreeMemBlock (\r
1436aea4
MK
102 IN USBHC_MEM_POOL *Pool,\r
103 IN USBHC_MEM_BLOCK *Block\r
d987459f
SZ
104 )\r
105{\r
106 ASSERT ((Pool != NULL) && (Block != NULL));\r
b575ca32
JY
107\r
108 IoMmuFreeBuffer (EFI_SIZE_TO_PAGES (Block->BufLen), Block->BufHost, Block->Mapping);\r
109\r
d987459f
SZ
110 //\r
111 // No free memory in PEI.\r
112 //\r
113}\r
114\r
115/**\r
116 Alloc some memory from the block.\r
117\r
118 @param Block The memory block to allocate memory from.\r
119 @param Units Number of memory units to allocate.\r
120\r
121 @return The pointer to the allocated memory.\r
122 If couldn't allocate the needed memory, the return value is NULL.\r
123\r
124**/\r
125VOID *\r
126UsbHcAllocMemFromBlock (\r
1436aea4
MK
127 IN USBHC_MEM_BLOCK *Block,\r
128 IN UINTN Units\r
d987459f
SZ
129 )\r
130{\r
1436aea4
MK
131 UINTN Byte;\r
132 UINT8 Bit;\r
133 UINTN StartByte;\r
134 UINT8 StartBit;\r
135 UINTN Available;\r
136 UINTN Count;\r
d987459f
SZ
137\r
138 ASSERT ((Block != 0) && (Units != 0));\r
139\r
1436aea4
MK
140 StartByte = 0;\r
141 StartBit = 0;\r
142 Available = 0;\r
d987459f
SZ
143\r
144 for (Byte = 0, Bit = 0; Byte < Block->BitsLen;) {\r
145 //\r
146 // If current bit is zero, the corresponding memory unit is\r
147 // available, otherwise we need to restart our searching.\r
148 // Available counts the consective number of zero bit.\r
149 //\r
150 if (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit)) {\r
151 Available++;\r
152\r
153 if (Available >= Units) {\r
154 break;\r
155 }\r
156\r
157 NEXT_BIT (Byte, Bit);\r
158 } else {\r
159 NEXT_BIT (Byte, Bit);\r
160\r
1436aea4
MK
161 Available = 0;\r
162 StartByte = Byte;\r
163 StartBit = Bit;\r
d987459f
SZ
164 }\r
165 }\r
166\r
167 if (Available < Units) {\r
168 return NULL;\r
169 }\r
170\r
171 //\r
172 // Mark the memory as allocated\r
173 //\r
1436aea4
MK
174 Byte = StartByte;\r
175 Bit = StartBit;\r
d987459f
SZ
176\r
177 for (Count = 0; Count < Units; Count++) {\r
178 ASSERT (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));\r
179\r
1436aea4 180 Block->Bits[Byte] = (UINT8)(Block->Bits[Byte] | (UINT8)USB_HC_BIT (Bit));\r
d987459f
SZ
181 NEXT_BIT (Byte, Bit);\r
182 }\r
183\r
184 return Block->BufHost + (StartByte * 8 + StartBit) * USBHC_MEM_UNIT;\r
185}\r
186\r
187/**\r
188 Calculate the corresponding pci bus address according to the Mem parameter.\r
189\r
190 @param Pool The memory pool of the host controller.\r
191 @param Mem The pointer to host memory.\r
192 @param Size The size of the memory region.\r
193\r
194 @return The pci memory address\r
195\r
196**/\r
197EFI_PHYSICAL_ADDRESS\r
198UsbHcGetPciAddrForHostAddr (\r
1436aea4
MK
199 IN USBHC_MEM_POOL *Pool,\r
200 IN VOID *Mem,\r
201 IN UINTN Size\r
d987459f
SZ
202 )\r
203{\r
204 USBHC_MEM_BLOCK *Head;\r
205 USBHC_MEM_BLOCK *Block;\r
206 UINTN AllocSize;\r
207 EFI_PHYSICAL_ADDRESS PhyAddr;\r
208 UINTN Offset;\r
209\r
210 Head = Pool->Head;\r
211 AllocSize = USBHC_MEM_ROUND (Size);\r
212\r
213 if (Mem == NULL) {\r
214 return 0;\r
215 }\r
216\r
217 for (Block = Head; Block != NULL; Block = Block->Next) {\r
218 //\r
219 // scan the memory block list for the memory block that\r
220 // completely contains the allocated memory.\r
221 //\r
1436aea4 222 if ((Block->BufHost <= (UINT8 *)Mem) && (((UINT8 *)Mem + AllocSize) <= (Block->BufHost + Block->BufLen))) {\r
d987459f
SZ
223 break;\r
224 }\r
225 }\r
226\r
227 ASSERT ((Block != NULL));\r
228 //\r
229 // calculate the pci memory address for host memory address.\r
230 //\r
1436aea4
MK
231 Offset = (UINT8 *)Mem - Block->BufHost;\r
232 PhyAddr = (EFI_PHYSICAL_ADDRESS)(UINTN)(Block->Buf + Offset);\r
d987459f
SZ
233 return PhyAddr;\r
234}\r
235\r
236/**\r
237 Calculate the corresponding host address according to the pci address.\r
238\r
239 @param Pool The memory pool of the host controller.\r
240 @param Mem The pointer to pci memory.\r
241 @param Size The size of the memory region.\r
242\r
243 @return The host memory address\r
244\r
245**/\r
246EFI_PHYSICAL_ADDRESS\r
247UsbHcGetHostAddrForPciAddr (\r
1436aea4
MK
248 IN USBHC_MEM_POOL *Pool,\r
249 IN VOID *Mem,\r
250 IN UINTN Size\r
d987459f
SZ
251 )\r
252{\r
253 USBHC_MEM_BLOCK *Head;\r
254 USBHC_MEM_BLOCK *Block;\r
255 UINTN AllocSize;\r
256 EFI_PHYSICAL_ADDRESS HostAddr;\r
257 UINTN Offset;\r
258\r
259 Head = Pool->Head;\r
260 AllocSize = USBHC_MEM_ROUND (Size);\r
261\r
262 if (Mem == NULL) {\r
263 return 0;\r
264 }\r
265\r
266 for (Block = Head; Block != NULL; Block = Block->Next) {\r
267 //\r
268 // scan the memory block list for the memory block that\r
269 // completely contains the allocated memory.\r
270 //\r
1436aea4 271 if ((Block->Buf <= (UINT8 *)Mem) && (((UINT8 *)Mem + AllocSize) <= (Block->Buf + Block->BufLen))) {\r
d987459f
SZ
272 break;\r
273 }\r
274 }\r
275\r
276 ASSERT ((Block != NULL));\r
277 //\r
278 // calculate the host memory address for pci memory address.\r
279 //\r
1436aea4
MK
280 Offset = (UINT8 *)Mem - Block->Buf;\r
281 HostAddr = (EFI_PHYSICAL_ADDRESS)(UINTN)(Block->BufHost + Offset);\r
d987459f
SZ
282 return HostAddr;\r
283}\r
284\r
285/**\r
286 Insert the memory block to the pool's list of the blocks.\r
287\r
288 @param Head The head of the memory pool's block list.\r
289 @param Block The memory block to insert.\r
290\r
291**/\r
292VOID\r
293UsbHcInsertMemBlockToPool (\r
1436aea4
MK
294 IN USBHC_MEM_BLOCK *Head,\r
295 IN USBHC_MEM_BLOCK *Block\r
d987459f
SZ
296 )\r
297{\r
298 ASSERT ((Head != NULL) && (Block != NULL));\r
299 Block->Next = Head->Next;\r
300 Head->Next = Block;\r
301}\r
302\r
303/**\r
304 Is the memory block empty?\r
305\r
306 @param Block The memory block to check.\r
307\r
308 @retval TRUE The memory block is empty.\r
309 @retval FALSE The memory block isn't empty.\r
310\r
311**/\r
312BOOLEAN\r
313UsbHcIsMemBlockEmpty (\r
1436aea4 314 IN USBHC_MEM_BLOCK *Block\r
d987459f
SZ
315 )\r
316{\r
1436aea4 317 UINTN Index;\r
d987459f
SZ
318\r
319 for (Index = 0; Index < Block->BitsLen; Index++) {\r
320 if (Block->Bits[Index] != 0) {\r
321 return FALSE;\r
322 }\r
323 }\r
324\r
325 return TRUE;\r
326}\r
327\r
d987459f
SZ
328/**\r
329 Initialize the memory management pool for the host controller.\r
330\r
331 @return Pointer to the allocated memory pool or NULL if failed.\r
332\r
333**/\r
334USBHC_MEM_POOL *\r
335UsbHcInitMemPool (\r
336 VOID\r
337 )\r
338{\r
339 USBHC_MEM_POOL *Pool;\r
340 UINTN PageNumber;\r
341 EFI_STATUS Status;\r
342 EFI_PHYSICAL_ADDRESS TempPtr;\r
343\r
344 PageNumber = EFI_SIZE_TO_PAGES (sizeof (USBHC_MEM_POOL));\r
1436aea4
MK
345 Status = PeiServicesAllocatePages (\r
346 EfiBootServicesData,\r
347 PageNumber,\r
348 &TempPtr\r
349 );\r
d987459f
SZ
350 if (EFI_ERROR (Status)) {\r
351 return NULL;\r
352 }\r
d987459f 353\r
1436aea4
MK
354 ZeroMem ((VOID *)(UINTN)TempPtr, EFI_PAGES_TO_SIZE (PageNumber));\r
355\r
356 Pool = (USBHC_MEM_POOL *)((UINTN)TempPtr);\r
d987459f
SZ
357 Pool->Head = UsbHcAllocMemBlock (USBHC_MEM_DEFAULT_PAGES);\r
358\r
359 if (Pool->Head == NULL) {\r
360 //\r
361 // No free memory in PEI.\r
362 //\r
363 Pool = NULL;\r
364 }\r
365\r
366 return Pool;\r
367}\r
368\r
47ab3970
AC
369/**\r
370 Unlink the memory block from the pool's list.\r
371\r
372 @param Head The block list head of the memory's pool.\r
373 @param BlockToUnlink The memory block to unlink.\r
374\r
375**/\r
376VOID\r
377UsbHcUnlinkMemBlock (\r
378 IN USBHC_MEM_BLOCK *Head,\r
379 IN USBHC_MEM_BLOCK *BlockToUnlink\r
380 )\r
381{\r
382 USBHC_MEM_BLOCK *Block;\r
383\r
384 ASSERT ((Head != NULL) && (BlockToUnlink != NULL));\r
385\r
386 for (Block = Head; Block != NULL; Block = Block->Next) {\r
387 if (Block->Next == BlockToUnlink) {\r
388 Block->Next = BlockToUnlink->Next;\r
389 BlockToUnlink->Next = NULL;\r
390 break;\r
391 }\r
392 }\r
393}\r
394\r
d987459f
SZ
395/**\r
396 Release the memory management pool.\r
397\r
398 @param Pool The USB memory pool to free.\r
399\r
400**/\r
401VOID\r
402UsbHcFreeMemPool (\r
1436aea4 403 IN USBHC_MEM_POOL *Pool\r
d987459f
SZ
404 )\r
405{\r
1436aea4 406 USBHC_MEM_BLOCK *Block;\r
d987459f
SZ
407\r
408 ASSERT (Pool->Head != NULL);\r
409\r
410 //\r
411 // Unlink all the memory blocks from the pool, then free them.\r
412 // UsbHcUnlinkMemBlock can't be used to unlink and free the\r
413 // first block.\r
414 //\r
415 for (Block = Pool->Head->Next; Block != NULL; Block = Pool->Head->Next) {\r
47ab3970 416 UsbHcUnlinkMemBlock (Pool->Head, Block);\r
d987459f
SZ
417 UsbHcFreeMemBlock (Pool, Block);\r
418 }\r
419\r
420 UsbHcFreeMemBlock (Pool, Pool->Head);\r
421}\r
422\r
423/**\r
424 Allocate some memory from the host controller's memory pool\r
425 which can be used to communicate with host controller.\r
426\r
427 @param Pool The host controller's memory pool.\r
428 @param Size Size of the memory to allocate.\r
429\r
430 @return The allocated memory or NULL.\r
431\r
432**/\r
433VOID *\r
434UsbHcAllocateMem (\r
1436aea4
MK
435 IN USBHC_MEM_POOL *Pool,\r
436 IN UINTN Size\r
d987459f
SZ
437 )\r
438{\r
1436aea4
MK
439 USBHC_MEM_BLOCK *Head;\r
440 USBHC_MEM_BLOCK *Block;\r
441 USBHC_MEM_BLOCK *NewBlock;\r
442 VOID *Mem;\r
443 UINTN AllocSize;\r
444 UINTN Pages;\r
d987459f
SZ
445\r
446 Mem = NULL;\r
447 AllocSize = USBHC_MEM_ROUND (Size);\r
448 Head = Pool->Head;\r
449 ASSERT (Head != NULL);\r
450\r
451 //\r
452 // First check whether current memory blocks can satisfy the allocation.\r
453 //\r
454 for (Block = Head; Block != NULL; Block = Block->Next) {\r
455 Mem = UsbHcAllocMemFromBlock (Block, AllocSize / USBHC_MEM_UNIT);\r
456\r
457 if (Mem != NULL) {\r
458 ZeroMem (Mem, Size);\r
459 break;\r
460 }\r
461 }\r
462\r
463 if (Mem != NULL) {\r
464 return Mem;\r
465 }\r
466\r
467 //\r
468 // Create a new memory block if there is not enough memory\r
469 // in the pool. If the allocation size is larger than the\r
470 // default page number, just allocate a large enough memory\r
471 // block. Otherwise allocate default pages.\r
472 //\r
473 if (AllocSize > EFI_PAGES_TO_SIZE (USBHC_MEM_DEFAULT_PAGES)) {\r
474 Pages = EFI_SIZE_TO_PAGES (AllocSize);\r
475 } else {\r
476 Pages = USBHC_MEM_DEFAULT_PAGES;\r
477 }\r
1436aea4 478\r
d987459f
SZ
479 NewBlock = UsbHcAllocMemBlock (Pages);\r
480\r
481 if (NewBlock == NULL) {\r
482 return NULL;\r
483 }\r
484\r
485 //\r
486 // Add the new memory block to the pool, then allocate memory from it\r
487 //\r
488 UsbHcInsertMemBlockToPool (Head, NewBlock);\r
489 Mem = UsbHcAllocMemFromBlock (NewBlock, AllocSize / USBHC_MEM_UNIT);\r
490\r
491 if (Mem != NULL) {\r
492 ZeroMem (Mem, Size);\r
493 }\r
494\r
495 return Mem;\r
496}\r
497\r
498/**\r
499 Free the allocated memory back to the memory pool.\r
500\r
501 @param Pool The memory pool of the host controller.\r
502 @param Mem The memory to free.\r
503 @param Size The size of the memory to free.\r
504\r
505**/\r
506VOID\r
507UsbHcFreeMem (\r
1436aea4
MK
508 IN USBHC_MEM_POOL *Pool,\r
509 IN VOID *Mem,\r
510 IN UINTN Size\r
d987459f
SZ
511 )\r
512{\r
1436aea4
MK
513 USBHC_MEM_BLOCK *Head;\r
514 USBHC_MEM_BLOCK *Block;\r
515 UINT8 *ToFree;\r
516 UINTN AllocSize;\r
517 UINTN Byte;\r
518 UINTN Bit;\r
519 UINTN Count;\r
d987459f
SZ
520\r
521 Head = Pool->Head;\r
522 AllocSize = USBHC_MEM_ROUND (Size);\r
1436aea4 523 ToFree = (UINT8 *)Mem;\r
d987459f
SZ
524\r
525 for (Block = Head; Block != NULL; Block = Block->Next) {\r
526 //\r
527 // scan the memory block list for the memory block that\r
528 // completely contains the memory to free.\r
529 //\r
530 if ((Block->BufHost <= ToFree) && ((ToFree + AllocSize) <= (Block->BufHost + Block->BufLen))) {\r
531 //\r
532 // compute the start byte and bit in the bit array\r
533 //\r
1436aea4
MK
534 Byte = ((ToFree - Block->BufHost) / USBHC_MEM_UNIT) / 8;\r
535 Bit = ((ToFree - Block->BufHost) / USBHC_MEM_UNIT) % 8;\r
d987459f
SZ
536\r
537 //\r
2048c585 538 // reset associated bits in bit array\r
d987459f
SZ
539 //\r
540 for (Count = 0; Count < (AllocSize / USBHC_MEM_UNIT); Count++) {\r
541 ASSERT (USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));\r
542\r
1436aea4 543 Block->Bits[Byte] = (UINT8)(Block->Bits[Byte] ^ USB_HC_BIT (Bit));\r
d987459f
SZ
544 NEXT_BIT (Byte, Bit);\r
545 }\r
546\r
547 break;\r
548 }\r
549 }\r
550\r
551 //\r
552 // If Block == NULL, it means that the current memory isn't\r
553 // in the host controller's pool. This is critical because\r
554 // the caller has passed in a wrong memory pointer\r
555 //\r
556 ASSERT (Block != NULL);\r
557\r
558 //\r
559 // Release the current memory block if it is empty and not the head\r
560 //\r
561 if ((Block != Head) && UsbHcIsMemBlockEmpty (Block)) {\r
47ab3970 562 UsbHcUnlinkMemBlock (Head, Block);\r
d987459f
SZ
563 UsbHcFreeMemBlock (Pool, Block);\r
564 }\r
565}\r
566\r
567/**\r
568 Allocates pages at a specified alignment.\r
569\r
570 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
571\r
572 @param Pages The number of pages to allocate.\r
573 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
574 @param HostAddress The system memory address to map to the PCI controller.\r
575 @param DeviceAddress The resulting map address for the bus master PCI controller to\r
576 use to access the hosts HostAddress.\r
b575ca32 577 @param Mapping A resulting value to pass to Unmap().\r
d987459f
SZ
578\r
579 @retval EFI_SUCCESS Success to allocate aligned pages.\r
580 @retval EFI_INVALID_PARAMETER Pages or Alignment is not valid.\r
581 @retval EFI_OUT_OF_RESOURCES Do not have enough resources to allocate memory.\r
582\r
583**/\r
584EFI_STATUS\r
585UsbHcAllocateAlignedPages (\r
1436aea4
MK
586 IN UINTN Pages,\r
587 IN UINTN Alignment,\r
588 OUT VOID **HostAddress,\r
589 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
590 OUT VOID **Mapping\r
d987459f
SZ
591 )\r
592{\r
593 EFI_STATUS Status;\r
b575ca32 594 VOID *Memory;\r
b575ca32 595 EFI_PHYSICAL_ADDRESS DeviceMemory;\r
d987459f
SZ
596\r
597 //\r
598 // Alignment must be a power of two or zero.\r
599 //\r
600 ASSERT ((Alignment & (Alignment - 1)) == 0);\r
601\r
602 if ((Alignment & (Alignment - 1)) != 0) {\r
603 return EFI_INVALID_PARAMETER;\r
604 }\r
605\r
606 if (Pages == 0) {\r
607 return EFI_INVALID_PARAMETER;\r
608 }\r
609\r
610 if (Alignment > EFI_PAGE_SIZE) {\r
2bbbdeee 611 Status = IoMmuAllocateAlignedBuffer (\r
d987459f 612 Pages,\r
2bbbdeee 613 Alignment,\r
b575ca32
JY
614 &Memory,\r
615 &DeviceMemory,\r
616 Mapping\r
d987459f
SZ
617 );\r
618 if (EFI_ERROR (Status)) {\r
619 return EFI_OUT_OF_RESOURCES;\r
620 }\r
d987459f
SZ
621 } else {\r
622 //\r
623 // Do not over-allocate pages in this case.\r
624 //\r
b575ca32 625 Status = IoMmuAllocateBuffer (\r
d987459f 626 Pages,\r
b575ca32
JY
627 &Memory,\r
628 &DeviceMemory,\r
629 Mapping\r
d987459f
SZ
630 );\r
631 if (EFI_ERROR (Status)) {\r
632 return EFI_OUT_OF_RESOURCES;\r
633 }\r
d987459f
SZ
634 }\r
635\r
1436aea4 636 *HostAddress = Memory;\r
2bbbdeee 637 *DeviceAddress = DeviceMemory;\r
d987459f
SZ
638\r
639 return EFI_SUCCESS;\r
640}\r
641\r
642/**\r
643 Frees memory that was allocated with UsbHcAllocateAlignedPages().\r
644\r
645 @param HostAddress The system memory address to map to the PCI controller.\r
646 @param Pages The number of pages to free.\r
b575ca32 647 @param Mapping The mapping value returned from Map().\r
d987459f
SZ
648\r
649**/\r
650VOID\r
651UsbHcFreeAlignedPages (\r
1436aea4
MK
652 IN VOID *HostAddress,\r
653 IN UINTN Pages,\r
654 IN VOID *Mapping\r
d987459f
SZ
655 )\r
656{\r
657 ASSERT (Pages != 0);\r
b575ca32
JY
658\r
659 IoMmuFreeBuffer (Pages, HostAddress, Mapping);\r
d987459f 660}\r