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