]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciMem.c
1. Add NULL QH to set as QH header;
[mirror_edk2.git] / EdkModulePkg / Bus / Pci / Ehci / Dxe / EhciMem.c
CommitLineData
562d2849 1/*++\r
2\r
4d1fe68e 3Copyright (c) 2006, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
562d2849 11\r
12Module Name:\r
13\r
14 EhciMem.c\r
4d1fe68e 15\r
16Abstract:\r
17\r
562d2849 18\r
19Revision History\r
20--*/\r
21\r
22#include "Ehci.h"\r
23\r
24\r
25EFI_STATUS\r
26CreateMemoryBlock (\r
27 IN USB2_HC_DEV *HcDev,\r
28 OUT MEMORY_MANAGE_HEADER **MemoryHeader,\r
29 IN UINTN MemoryBlockSizeInPages\r
30 )\r
31/*++\r
32\r
33Routine Description:\r
34\r
35 Use PciIo->AllocateBuffer to allocate common buffer for the memory block,\r
36 and use PciIo->Map to map the common buffer for Bus Master Read/Write.\r
37\r
38Arguments:\r
39\r
40 HcDev - USB2_HC_DEV\r
41 MemoryHeader - MEMORY_MANAGE_HEADER to output\r
42 MemoryBlockSizeInPages - MemoryBlockSizeInPages\r
4d1fe68e 43\r
562d2849 44Returns:\r
45\r
46 EFI_SUCCESS Success\r
47 EFI_OUT_OF_RESOURCES Fail for no resources\r
48 EFI_UNSUPPORTED Unsupported currently\r
4d1fe68e 49\r
562d2849 50--*/\r
51{\r
52 EFI_STATUS Status;\r
53 VOID *CommonBuffer;\r
54 EFI_PHYSICAL_ADDRESS MappedAddress;\r
55 UINTN MemoryBlockSizeInBytes;\r
56 VOID *Mapping;\r
57\r
58 //\r
59 // Allocate memory for MemoryHeader\r
60 //\r
61 *MemoryHeader = AllocateZeroPool (sizeof (MEMORY_MANAGE_HEADER));\r
62 if (*MemoryHeader == NULL) {\r
63 return EFI_OUT_OF_RESOURCES;\r
64 }\r
65\r
66 (*MemoryHeader)->Next = NULL;\r
67\r
68 //\r
69 // set Memory block size\r
70 //\r
71 (*MemoryHeader)->MemoryBlockSizeInBytes = EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages);\r
72\r
73 //\r
74 // each bit in Bit Array will manage 32 bytes memory in memory block\r
75 //\r
4d1fe68e 76 (*MemoryHeader)->BitArraySizeInBytes = ((*MemoryHeader)->MemoryBlockSizeInBytes / MEM_UNIT_SIZE) / 8;\r
562d2849 77\r
78 //\r
79 // Allocate memory for BitArray\r
80 //\r
81 (*MemoryHeader)->BitArrayPtr = AllocateZeroPool ((*MemoryHeader)->BitArraySizeInBytes);\r
82 if ((*MemoryHeader)->BitArrayPtr == NULL) {\r
83 gBS->FreePool (*MemoryHeader);\r
84 return EFI_OUT_OF_RESOURCES;\r
85 }\r
4d1fe68e 86\r
562d2849 87 //\r
88 // Memory Block uses MemoryBlockSizeInPages pages,\r
89 // and it is allocated as common buffer use.\r
90 //\r
91 Status = HcDev->PciIo->AllocateBuffer (\r
92 HcDev->PciIo,\r
93 AllocateAnyPages,\r
94 EfiBootServicesData,\r
95 MemoryBlockSizeInPages,\r
96 &CommonBuffer,\r
97 0\r
98 );\r
99 if (EFI_ERROR (Status)) {\r
100 gBS->FreePool ((*MemoryHeader)->BitArrayPtr);\r
101 gBS->FreePool (*MemoryHeader);\r
102 return EFI_OUT_OF_RESOURCES;\r
103 }\r
104\r
105 MemoryBlockSizeInBytes = EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages);\r
106 Status = HcDev->PciIo->Map (\r
107 HcDev->PciIo,\r
108 EfiPciIoOperationBusMasterCommonBuffer,\r
109 CommonBuffer,\r
110 &MemoryBlockSizeInBytes,\r
111 &MappedAddress,\r
112 &Mapping\r
113 );\r
114 //\r
4d1fe68e 115 // If returned Mapped size is less than the size\r
562d2849 116 // we request,do not support.\r
117 //\r
118 if (EFI_ERROR (Status) || (MemoryBlockSizeInBytes != EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages))) {\r
119 HcDev->PciIo->FreeBuffer (HcDev->PciIo, MemoryBlockSizeInPages, CommonBuffer);\r
120 gBS->FreePool ((*MemoryHeader)->BitArrayPtr);\r
121 gBS->FreePool (*MemoryHeader);\r
122 return EFI_UNSUPPORTED;\r
123 }\r
4d1fe68e 124\r
562d2849 125 //\r
4d1fe68e 126 // Data structure involved by host controller\r
562d2849 127 // should be restricted into the same 4G\r
128 //\r
129 if (HcDev->Is64BitCapable != 0) {\r
130 if (HcDev->High32BitAddr != GET_32B_TO_63B (MappedAddress)) {\r
131 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
132 HcDev->PciIo->FreeBuffer (HcDev->PciIo, MemoryBlockSizeInPages, CommonBuffer);\r
133 gBS->FreePool ((*MemoryHeader)->BitArrayPtr);\r
134 gBS->FreePool (*MemoryHeader);\r
135 return EFI_UNSUPPORTED;\r
136 }\r
137 }\r
4d1fe68e 138\r
562d2849 139 //\r
140 // Set Memory block initial address\r
141 //\r
142 (*MemoryHeader)->MemoryBlockPtr = (UINT8 *) ((UINTN) MappedAddress);\r
143 (*MemoryHeader)->Mapping = Mapping;\r
144\r
145 ZeroMem (\r
146 (*MemoryHeader)->MemoryBlockPtr,\r
147 EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages)\r
148 );\r
149\r
150 return EFI_SUCCESS;\r
151}\r
152\r
153EFI_STATUS\r
154FreeMemoryHeader (\r
155 IN USB2_HC_DEV *HcDev,\r
156 IN MEMORY_MANAGE_HEADER *MemoryHeader\r
157 )\r
158/*++\r
159\r
160Routine Description:\r
161\r
162 Free Memory Header\r
163\r
164Arguments:\r
165\r
166 HcDev - USB2_HC_DEV\r
167 MemoryHeader - MemoryHeader to be freed\r
168\r
169Returns:\r
170\r
171 EFI_SUCCESS Success\r
172 EFI_INVALID_PARAMETER Parameter is error\r
173\r
174--*/\r
175{\r
176 if ((MemoryHeader == NULL) || (HcDev == NULL)) {\r
177 return EFI_INVALID_PARAMETER;\r
178 }\r
179 //\r
180 // unmap the common buffer used by the memory block\r
181 //\r
182 HcDev->PciIo->Unmap (HcDev->PciIo, MemoryHeader->Mapping);\r
183\r
184 //\r
185 // free common buffer\r
186 //\r
187 HcDev->PciIo->FreeBuffer (\r
188 HcDev->PciIo,\r
189 EFI_SIZE_TO_PAGES (MemoryHeader->MemoryBlockSizeInBytes),\r
190 MemoryHeader->MemoryBlockPtr\r
191 );\r
192 //\r
193 // free bit array\r
194 //\r
195 gBS->FreePool (MemoryHeader->BitArrayPtr);\r
196 //\r
197 // free memory header\r
198 //\r
199 gBS->FreePool (MemoryHeader);\r
200\r
201 return EFI_SUCCESS;\r
202}\r
203\r
204EFI_STATUS\r
205EhciAllocatePool (\r
206 IN USB2_HC_DEV *HcDev,\r
207 OUT UINT8 **Pool,\r
208 IN UINTN AllocSize\r
209 )\r
210/*++\r
211\r
212Routine Description:\r
213\r
214 Ehci Allocate Pool\r
215\r
216Arguments:\r
217\r
218 HcDev - USB2_HC_DEV\r
219 Pool - Place to store pointer to the memory buffer\r
220 AllocSize - Alloc Size\r
221\r
222Returns:\r
223\r
224 EFI_SUCCESS Success\r
225 EFI_DEVICE_ERROR Fail\r
226\r
227--*/\r
228{\r
229 MEMORY_MANAGE_HEADER *MemoryHeader;\r
230 MEMORY_MANAGE_HEADER *TempHeaderPtr;\r
231 MEMORY_MANAGE_HEADER *NewMemoryHeader;\r
232 UINTN RealAllocSize;\r
233 UINTN MemoryBlockSizeInPages;\r
234 EFI_STATUS Status;\r
235 EFI_TPL OldTpl;\r
236\r
237 *Pool = NULL;\r
238\r
239 MemoryHeader = HcDev->MemoryHeader;\r
240 ASSERT (MemoryHeader != NULL);\r
241\r
242 OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY + 1);\r
4d1fe68e 243\r
562d2849 244 //\r
245 // allocate unit is 32 bytes (align on 32 byte)\r
246 //\r
4d1fe68e 247 if (AllocSize & (MEM_UNIT_SIZE - 1)) {\r
248 RealAllocSize = (AllocSize / MEM_UNIT_SIZE + 1) * MEM_UNIT_SIZE;\r
562d2849 249 } else {\r
250 RealAllocSize = AllocSize;\r
251 }\r
4d1fe68e 252\r
562d2849 253 //\r
254 // There may be linked MemoryHeaders.\r
255 // To allocate a free pool in Memory blocks,\r
256 // must search in the MemoryHeader link list\r
257 // until enough free pool is found.\r
258 //\r
259 Status = EFI_NOT_FOUND;\r
260 for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL; TempHeaderPtr = TempHeaderPtr->Next) {\r
261\r
262 Status = AllocMemInMemoryBlock (\r
263 TempHeaderPtr,\r
ffac4bcb 264 (VOID **) Pool,\r
4d1fe68e 265 RealAllocSize / MEM_UNIT_SIZE\r
562d2849 266 );\r
267 if (!EFI_ERROR (Status)) {\r
4d1fe68e 268 break;\r
562d2849 269 }\r
270 }\r
271\r
272 gBS->RestoreTPL (OldTpl);\r
4d1fe68e 273\r
274 if (!EFI_ERROR (Status)) {\r
275 ZeroMem (*Pool, AllocSize);\r
276 return EFI_SUCCESS;\r
277 }\r
278\r
279\r
562d2849 280 //\r
281 // There is no enough memory,\r
282 // Create a new Memory Block\r
283 //\r
4d1fe68e 284\r
562d2849 285 //\r
286 // if pool size is larger than NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES,\r
287 // just allocate a large enough memory block.\r
288 //\r
289 if (RealAllocSize > EFI_PAGES_TO_SIZE (NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES)) {\r
290 MemoryBlockSizeInPages = EFI_SIZE_TO_PAGES (RealAllocSize) + 1;\r
291 } else {\r
292 MemoryBlockSizeInPages = NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES;\r
293 }\r
294\r
295 Status = CreateMemoryBlock (HcDev, &NewMemoryHeader, MemoryBlockSizeInPages);\r
296 if (EFI_ERROR (Status)) {\r
297 return Status;\r
298 }\r
299\r
300 OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY + 1);\r\r
301 \r
302 //\r
303 // Link the new Memory Block to the Memory Header list\r
304 //\r
305 InsertMemoryHeaderToList (MemoryHeader, NewMemoryHeader);\r
306\r
307 Status = AllocMemInMemoryBlock (\r
308 NewMemoryHeader,\r
ffac4bcb 309 (VOID **) Pool,\r
4d1fe68e 310 RealAllocSize / MEM_UNIT_SIZE\r
562d2849 311 );\r
4d1fe68e 312\r
313 gBS->RestoreTPL (OldTpl);\r
314\r
562d2849 315 if (!EFI_ERROR (Status)) {\r
316 ZeroMem (*Pool, AllocSize);\r
317 }\r
318\r
562d2849 319 return Status;\r
320}\r
321\r
322VOID\r
323EhciFreePool (\r
324 IN USB2_HC_DEV *HcDev,\r
325 IN UINT8 *Pool,\r
326 IN UINTN AllocSize\r
327 )\r
328/*++\r
329\r
330Routine Description:\r
331\r
332 Uhci Free Pool\r
333\r
334Arguments:\r
335\r
336 HcDev - USB_HC_DEV\r
337 Pool - Pool to free\r
338 AllocSize - Pool size\r
339\r
340Returns:\r
341\r
342 VOID\r
343\r
344--*/\r
345{\r
346 MEMORY_MANAGE_HEADER *MemoryHeader;\r
347 MEMORY_MANAGE_HEADER *TempHeaderPtr;\r
348 UINTN StartBytePos;\r
349 UINTN Index;\r
350 UINT8 StartBitPos;\r
351 UINT8 Index2;\r
352 UINTN Count;\r
353 UINTN RealAllocSize;\r
354 EFI_TPL OldTpl;\r
355\r
356 OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY + 1);\r
357\r
358 MemoryHeader = HcDev->MemoryHeader;\r
359\r
360 //\r
361 // allocate unit is 32 byte (align on 32 byte)\r
362 //\r
4d1fe68e 363 if (AllocSize & (MEM_UNIT_SIZE - 1)) {\r
364 RealAllocSize = (AllocSize / MEM_UNIT_SIZE + 1) * MEM_UNIT_SIZE;\r
562d2849 365 } else {\r
366 RealAllocSize = AllocSize;\r
367 }\r
4d1fe68e 368\r
562d2849 369 //\r
370 // scan the memory header linked list for\r
371 // the asigned memory to free.\r
372 //\r
373 for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL; TempHeaderPtr = TempHeaderPtr->Next) {\r
374\r
375 if ((Pool >= TempHeaderPtr->MemoryBlockPtr) &&\r
376 ((Pool + RealAllocSize) <= (TempHeaderPtr->MemoryBlockPtr + TempHeaderPtr->MemoryBlockSizeInBytes))\r
377 ) {\r
378 //\r
379 // Pool is in the Memory Block area,\r
380 // find the start byte and bit in the bit array\r
381 //\r
4d1fe68e 382 StartBytePos = ((Pool - TempHeaderPtr->MemoryBlockPtr) / MEM_UNIT_SIZE) / 8;\r
383 StartBitPos = (UINT8) (((Pool - TempHeaderPtr->MemoryBlockPtr) / MEM_UNIT_SIZE) & 0x7);\r
562d2849 384\r
385 //\r
386 // reset associated bits in bit arry\r
387 //\r
4d1fe68e 388 for (Index = StartBytePos, Index2 = StartBitPos, Count = 0; Count < (RealAllocSize / MEM_UNIT_SIZE); Count++) {\r
389 ASSERT ((TempHeaderPtr->BitArrayPtr[Index] & bit (Index2) )== bit (Index2));\r
390\r
391 TempHeaderPtr->BitArrayPtr[Index] ^= (UINT8) (bit (Index2));\r
562d2849 392 Index2++;\r
393 if (Index2 == 8) {\r
394 Index += 1;\r
395 Index2 = 0;\r
396 }\r
397 }\r
398 //\r
399 // break the loop\r
400 //\r
401 break;\r
402 }\r
403 }\r
4d1fe68e 404\r
562d2849 405 //\r
406 // Release emptied memory blocks (only if the memory block is not\r
407 // the first one in the memory header list\r
408 //\r
409 for (TempHeaderPtr = MemoryHeader->Next; TempHeaderPtr != NULL;) {\r
410\r
411 ASSERT (MemoryHeader->Next != NULL);\r
412\r
413 if (IsMemoryBlockEmptied (TempHeaderPtr)) {\r
414\r
415 DelinkMemoryBlock (MemoryHeader, TempHeaderPtr);\r
416 //\r
417 // when the TempHeaderPtr is freed in FreeMemoryHeader(),\r
418 // the TempHeaderPtr is pointing to nonsense content.\r
419 //\r
420 gBS->RestoreTPL (OldTpl);\r
421 FreeMemoryHeader (HcDev, TempHeaderPtr);\r
422 OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY + 1);\r
423 //\r
424 // reset the TempHeaderPtr, continue search for\r
425 // another empty memory block.\r
426 //\r
427 TempHeaderPtr = MemoryHeader->Next;\r
428 continue;\r
429 }\r
430\r
431 TempHeaderPtr = TempHeaderPtr->Next;\r
432 }\r
433\r
434 gBS->RestoreTPL (OldTpl);\r
435}\r
436\r
437VOID\r
438InsertMemoryHeaderToList (\r
439 IN MEMORY_MANAGE_HEADER *MemoryHeader,\r
440 IN MEMORY_MANAGE_HEADER *NewMemoryHeader\r
441 )\r
442/*++\r
443\r
444Routine Description:\r
445\r
446 Insert Memory Header To List\r
447\r
448Arguments:\r
449\r
450 MemoryHeader - MEMORY_MANAGE_HEADER\r
451 NewMemoryHeader - MEMORY_MANAGE_HEADER\r
452\r
453Returns:\r
454\r
455 VOID\r
456\r
457--*/\r
458{\r
459 MEMORY_MANAGE_HEADER *TempHeaderPtr;\r
460\r
461 for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL; TempHeaderPtr = TempHeaderPtr->Next) {\r
462 if (TempHeaderPtr->Next == NULL) {\r
463 TempHeaderPtr->Next = NewMemoryHeader;\r
464 break;\r
465 }\r
466 }\r
467}\r
468\r
469EFI_STATUS\r
470AllocMemInMemoryBlock (\r
471 IN MEMORY_MANAGE_HEADER *MemoryHeader,\r
472 OUT VOID **Pool,\r
473 IN UINTN NumberOfMemoryUnit\r
474 )\r
475/*++\r
476\r
477Routine Description:\r
478\r
479 Alloc Memory In MemoryBlock\r
480\r
481Arguments:\r
482\r
483 MemoryHeader - MEMORY_MANAGE_HEADER\r
484 Pool - Place to store pointer to memory\r
485 NumberOfMemoryUnit - Number Of Memory Unit\r
486\r
487Returns:\r
488\r
489 EFI_SUCCESS Success\r
4d1fe68e 490 EFI_NOT_FOUND Can't find the free memory\r
562d2849 491\r
492--*/\r
493{\r
494 UINTN TempBytePos;\r
495 UINTN FoundBytePos;\r
496 UINT8 Index;\r
497 UINT8 FoundBitPos;\r
498 UINT8 ByteValue;\r
499 UINT8 BitValue;\r
500 UINTN NumberOfZeros;\r
501 UINTN Count;\r
502\r
503 FoundBytePos = 0;\r
504 FoundBitPos = 0;\r
505 ByteValue = MemoryHeader->BitArrayPtr[0];\r
506 NumberOfZeros = 0;\r
507 Index = 0;\r
508\r
509 for (TempBytePos = 0; TempBytePos < MemoryHeader->BitArraySizeInBytes;) {\r
510 \r
511 //\r
512 // Pop out BitValue from a byte in TempBytePos.\r
513 //\r
514 BitValue = (UINT8) (ByteValue & 0x1);\r
515 \r
516 //\r
517 // right shift the byte\r
518 //\r
4d1fe68e 519 ByteValue = ByteValue >> 1;\r
562d2849 520\r
521 if (BitValue == 0) {\r
522 //\r
523 // Found a free bit, the NumberOfZeros only record the number\r
524 // of those consecutive zeros\r
525 //\r
526 NumberOfZeros++;\r
527 //\r
528 // Found enough consecutive free space, break the loop\r
529 //\r
530 if (NumberOfZeros >= NumberOfMemoryUnit) {\r
531 break;\r
532 }\r
533 } else {\r
534 //\r
535 // Encountering a '1', meant the bit is ocupied.\r
536 //\r
537 if (NumberOfZeros >= NumberOfMemoryUnit) {\r
538 //\r
539 // Found enough consecutive free space,break the loop\r
540 //\r
541 break;\r
542 } else {\r
543 //\r
544 // the NumberOfZeros only record the number of those consecutive zeros,\r
545 // so reset the NumberOfZeros to 0 when encountering '1' before finding\r
546 // enough consecutive '0's\r
547 //\r
548 NumberOfZeros = 0;\r
549 //\r
550 // reset the (FoundBytePos,FoundBitPos) to the position of '1'\r
551 //\r
552 FoundBytePos = TempBytePos;\r
553 FoundBitPos = Index;\r
554 }\r
555 }\r
556 \r
557 //\r
558 // step forward a bit\r
559 //\r
560 Index++;\r
561 if (Index == 8) {\r
562 //\r
563 // step forward a byte, getting the byte value,\r
564 // and reset the bit pos.\r
565 //\r
566 TempBytePos += 1;\r
567 ByteValue = MemoryHeader->BitArrayPtr[TempBytePos];\r
568 Index = 0;\r
569 }\r
570 }\r
571\r
572 if (NumberOfZeros < NumberOfMemoryUnit) {\r
573 return EFI_NOT_FOUND;\r
574 }\r
4d1fe68e 575\r
562d2849 576 //\r
577 // Found enough free space.\r
578 //\r
4d1fe68e 579\r
562d2849 580 //\r
581 // The values recorded in (FoundBytePos,FoundBitPos) have two conditions:\r
582 // 1)(FoundBytePos,FoundBitPos) record the position\r
583 // of the last '1' before the consecutive '0's, it must\r
584 // be adjusted to the start position of the consecutive '0's.\r
585 // 2)the start address of the consecutive '0's is just the start of\r
586 // the bitarray. so no need to adjust the values of\r
587 // (FoundBytePos,FoundBitPos).\r
588 //\r
589 if ((MemoryHeader->BitArrayPtr[FoundBytePos] & bit (FoundBitPos)) != 0) {\r
590 FoundBitPos += 1;\r
591 }\r
4d1fe68e 592\r
562d2849 593 //\r
594 // Have the (FoundBytePos,FoundBitPos) make sense.\r
595 //\r
596 if (FoundBitPos > 7) {\r
597 FoundBytePos += 1;\r
598 FoundBitPos -= 8;\r
599 }\r
4d1fe68e 600\r
562d2849 601 //\r
602 // Set the memory as allocated\r
603 //\r
604 for (TempBytePos = FoundBytePos, Index = FoundBitPos, Count = 0; Count < NumberOfMemoryUnit; Count++) {\r
605\r
4d1fe68e 606 ASSERT ((MemoryHeader->BitArrayPtr[TempBytePos] & bit (Index) )== 0);\r
607 MemoryHeader->BitArrayPtr[TempBytePos] |= bit (Index);\r
562d2849 608 Index++;\r
609 if (Index == 8) {\r
610 TempBytePos += 1;\r
611 Index = 0;\r
612 }\r
613 }\r
614\r
4d1fe68e 615 *Pool = MemoryHeader->MemoryBlockPtr + (FoundBytePos * 8 + FoundBitPos) * MEM_UNIT_SIZE;\r
562d2849 616\r
617 return EFI_SUCCESS;\r
618}\r
619\r
620BOOLEAN\r
621IsMemoryBlockEmptied (\r
622 IN MEMORY_MANAGE_HEADER *MemoryHeaderPtr\r
623 )\r
624/*++\r
625\r
626Routine Description:\r
627\r
628 Is Memory Block Emptied\r
629\r
630Arguments:\r
631\r
632 MemoryHeaderPtr - MEMORY_MANAGE_HEADER\r
633\r
634Returns:\r
635\r
636 TRUE Empty\r
4d1fe68e 637 FALSE Not Empty\r
562d2849 638\r
639--*/\r
640{\r
641 UINTN Index;\r
642\r
643 for (Index = 0; Index < MemoryHeaderPtr->BitArraySizeInBytes; Index++) {\r
644 if (MemoryHeaderPtr->BitArrayPtr[Index] != 0) {\r
645 return FALSE;\r
646 }\r
647 }\r
648\r
649 return TRUE;\r
650}\r
651\r
652VOID\r
653DelinkMemoryBlock (\r
654 IN MEMORY_MANAGE_HEADER *FirstMemoryHeader,\r
655 IN MEMORY_MANAGE_HEADER *NeedFreeMemoryHeader\r
656 )\r
657/*++\r
658\r
659Routine Description:\r
660\r
661 Delink Memory Block\r
662\r
663Arguments:\r
664\r
665 FirstMemoryHeader - MEMORY_MANAGE_HEADER\r
666 NeedFreeMemoryHeader - MEMORY_MANAGE_HEADER\r
667\r
668Returns:\r
669\r
670 VOID\r
671\r
672--*/\r
673{\r
674 MEMORY_MANAGE_HEADER *TempHeaderPtr;\r
675\r
676 if ((FirstMemoryHeader == NULL) || (NeedFreeMemoryHeader == NULL)) {\r
677 return ;\r
678 }\r
679\r
680 for (TempHeaderPtr = FirstMemoryHeader; TempHeaderPtr != NULL; TempHeaderPtr = TempHeaderPtr->Next) {\r
681\r
682 if (TempHeaderPtr->Next == NeedFreeMemoryHeader) {\r
683 //\r
684 // Link the before and after\r
685 //\r
686 TempHeaderPtr->Next = NeedFreeMemoryHeader->Next;\r
4d1fe68e 687 NeedFreeMemoryHeader->Next = NULL;\r
562d2849 688 break;\r
689 }\r
690 }\r
691}\r
692\r
693EFI_STATUS\r
694InitialMemoryManagement (\r
695 IN USB2_HC_DEV *HcDev\r
696 )\r
697/*++\r
698\r
699Routine Description:\r
700\r
701 Initialize Memory Management\r
702\r
703Arguments:\r
704\r
705 HcDev - USB2_HC_DEV\r
706\r
707Returns:\r
708\r
709 EFI_SUCCESS Success\r
710 EFI_DEVICE_ERROR Fail\r
4d1fe68e 711\r
562d2849 712--*/\r
713{\r
714 EFI_STATUS Status;\r
715 MEMORY_MANAGE_HEADER *MemoryHeader;\r
716 UINTN MemPages;\r
717\r
718 MemPages = NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES;\r
719 Status = CreateMemoryBlock (HcDev, &MemoryHeader, MemPages);\r
720 if (EFI_ERROR (Status)) {\r
721 Status = EFI_OUT_OF_RESOURCES;\r
722 goto exit;\r
723 }\r
724\r
725 HcDev->MemoryHeader = MemoryHeader;\r
726\r
727exit:\r
728 return Status;\r
729}\r
730\r
731EFI_STATUS\r
732DeinitialMemoryManagement (\r
733 IN USB2_HC_DEV *HcDev\r
734 )\r
735/*++\r
736\r
737Routine Description:\r
738\r
739 Deinitialize Memory Management\r
740\r
741Arguments:\r
742\r
743 HcDev - USB2_HC_DEV\r
744\r
745Returns:\r
746\r
747 EFI_SUCCESS Success\r
748 EFI_DEVICE_ERROR Fail\r
4d1fe68e 749\r
562d2849 750--*/\r
751{\r
752 MEMORY_MANAGE_HEADER *TempHeaderPtr;\r
753\r
754 for (TempHeaderPtr = HcDev->MemoryHeader->Next; TempHeaderPtr != NULL;) {\r
755\r
756 DelinkMemoryBlock (HcDev->MemoryHeader, TempHeaderPtr);\r
757 //\r
758 // when the TempHeaderPtr is freed in FreeMemoryHeader(),\r
759 // the TempHeaderPtr is pointing to nonsense content.\r
760 //\r
761 FreeMemoryHeader (HcDev, TempHeaderPtr);\r
762 //\r
763 // reset the TempHeaderPtr,continue free another memory block.\r
764 //\r
765 TempHeaderPtr = HcDev->MemoryHeader->Next;\r
766 }\r
767\r
768 FreeMemoryHeader (HcDev, HcDev->MemoryHeader);\r
769\r
770 return EFI_SUCCESS;\r
771}\r