]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - 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
1/*++\r
2\r
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
11\r
12Module Name:\r
13\r
14 EhciMem.c\r
15\r
16Abstract:\r
17\r
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
43\r
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
49\r
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
76 (*MemoryHeader)->BitArraySizeInBytes = ((*MemoryHeader)->MemoryBlockSizeInBytes / MEM_UNIT_SIZE) / 8;\r
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
86\r
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
115 // If returned Mapped size is less than the size\r
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
124\r
125 //\r
126 // Data structure involved by host controller\r
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
138\r
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
243\r
244 //\r
245 // allocate unit is 32 bytes (align on 32 byte)\r
246 //\r
247 if (AllocSize & (MEM_UNIT_SIZE - 1)) {\r
248 RealAllocSize = (AllocSize / MEM_UNIT_SIZE + 1) * MEM_UNIT_SIZE;\r
249 } else {\r
250 RealAllocSize = AllocSize;\r
251 }\r
252\r
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
264 (VOID **) Pool,\r
265 RealAllocSize / MEM_UNIT_SIZE\r
266 );\r
267 if (!EFI_ERROR (Status)) {\r
268 break;\r
269 }\r
270 }\r
271\r
272 gBS->RestoreTPL (OldTpl);\r
273\r
274 if (!EFI_ERROR (Status)) {\r
275 ZeroMem (*Pool, AllocSize);\r
276 return EFI_SUCCESS;\r
277 }\r
278\r
279\r
280 //\r
281 // There is no enough memory,\r
282 // Create a new Memory Block\r
283 //\r
284\r
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
309 (VOID **) Pool,\r
310 RealAllocSize / MEM_UNIT_SIZE\r
311 );\r
312\r
313 gBS->RestoreTPL (OldTpl);\r
314\r
315 if (!EFI_ERROR (Status)) {\r
316 ZeroMem (*Pool, AllocSize);\r
317 }\r
318\r
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
363 if (AllocSize & (MEM_UNIT_SIZE - 1)) {\r
364 RealAllocSize = (AllocSize / MEM_UNIT_SIZE + 1) * MEM_UNIT_SIZE;\r
365 } else {\r
366 RealAllocSize = AllocSize;\r
367 }\r
368\r
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
382 StartBytePos = ((Pool - TempHeaderPtr->MemoryBlockPtr) / MEM_UNIT_SIZE) / 8;\r
383 StartBitPos = (UINT8) (((Pool - TempHeaderPtr->MemoryBlockPtr) / MEM_UNIT_SIZE) & 0x7);\r
384\r
385 //\r
386 // reset associated bits in bit arry\r
387 //\r
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
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
404\r
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
490 EFI_NOT_FOUND Can't find the free memory\r
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
519 ByteValue = ByteValue >> 1;\r
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
575\r
576 //\r
577 // Found enough free space.\r
578 //\r
579\r
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
592\r
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
600\r
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
606 ASSERT ((MemoryHeader->BitArrayPtr[TempBytePos] & bit (Index) )== 0);\r
607 MemoryHeader->BitArrayPtr[TempBytePos] |= bit (Index);\r
608 Index++;\r
609 if (Index == 8) {\r
610 TempBytePos += 1;\r
611 Index = 0;\r
612 }\r
613 }\r
614\r
615 *Pool = MemoryHeader->MemoryBlockPtr + (FoundBytePos * 8 + FoundBitPos) * MEM_UNIT_SIZE;\r
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
637 FALSE Not Empty\r
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
687 NeedFreeMemoryHeader->Next = NULL;\r
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
711\r
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
749\r
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