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