562d2849 |
1 | /*++\r |
2 | \r |
3 | Copyright (c) 2006, Intel Corporation \r |
4 | All rights reserved. This program and the accompanying materials \r |
5 | are licensed and made available under the terms and conditions of the BSD License \r |
6 | which accompanies this distribution. The full text of the license may be found at \r |
7 | http://opensource.org/licenses/bsd-license.php \r |
8 | \r |
9 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r |
10 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r |
11 | \r |
12 | Module Name:\r |
13 | \r |
14 | EhciMem.c\r |
15 | \r |
16 | Abstract: \r |
17 | \r |
18 | \r |
19 | Revision History\r |
20 | --*/\r |
21 | \r |
22 | #include "Ehci.h"\r |
23 | \r |
24 | \r |
25 | EFI_STATUS\r |
26 | CreateMemoryBlock (\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 |
33 | Routine 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 |
38 | Arguments:\r |
39 | \r |
40 | HcDev - USB2_HC_DEV\r |
41 | MemoryHeader - MEMORY_MANAGE_HEADER to output\r |
42 | MemoryBlockSizeInPages - MemoryBlockSizeInPages\r |
43 | \r |
44 | Returns:\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 / 32) / 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 |
153 | EFI_STATUS\r |
154 | FreeMemoryHeader (\r |
155 | IN USB2_HC_DEV *HcDev,\r |
156 | IN MEMORY_MANAGE_HEADER *MemoryHeader\r |
157 | )\r |
158 | /*++\r |
159 | \r |
160 | Routine Description:\r |
161 | \r |
162 | Free Memory Header\r |
163 | \r |
164 | Arguments:\r |
165 | \r |
166 | HcDev - USB2_HC_DEV\r |
167 | MemoryHeader - MemoryHeader to be freed\r |
168 | \r |
169 | Returns:\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 |
204 | EFI_STATUS\r |
205 | EhciAllocatePool (\r |
206 | IN USB2_HC_DEV *HcDev,\r |
207 | OUT UINT8 **Pool,\r |
208 | IN UINTN AllocSize\r |
209 | )\r |
210 | /*++\r |
211 | \r |
212 | Routine Description:\r |
213 | \r |
214 | Ehci Allocate Pool\r |
215 | \r |
216 | Arguments:\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 |
222 | Returns:\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 & 0x1F) {\r |
248 | RealAllocSize = (AllocSize / 32 + 1) * 32;\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 |
ffac4bcb |
264 | (VOID **) Pool,\r |
562d2849 |
265 | RealAllocSize / 32\r |
266 | );\r |
267 | if (!EFI_ERROR (Status)) {\r |
268 | ZeroMem (*Pool, AllocSize);\r |
269 | gBS->RestoreTPL (OldTpl);\r |
270 | return EFI_SUCCESS;\r |
271 | }\r |
272 | }\r |
273 | \r |
274 | gBS->RestoreTPL (OldTpl);\r |
275 | \r |
276 | //\r |
277 | // There is no enough memory,\r |
278 | // Create a new Memory Block\r |
279 | //\r |
280 | \r |
281 | //\r |
282 | // if pool size is larger than NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES,\r |
283 | // just allocate a large enough memory block.\r |
284 | //\r |
285 | if (RealAllocSize > EFI_PAGES_TO_SIZE (NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES)) {\r |
286 | MemoryBlockSizeInPages = EFI_SIZE_TO_PAGES (RealAllocSize) + 1;\r |
287 | } else {\r |
288 | MemoryBlockSizeInPages = NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES;\r |
289 | }\r |
290 | \r |
291 | Status = CreateMemoryBlock (HcDev, &NewMemoryHeader, MemoryBlockSizeInPages);\r |
292 | if (EFI_ERROR (Status)) {\r |
293 | return Status;\r |
294 | }\r |
295 | \r |
296 | OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY + 1);\r\r |
297 | \r |
298 | //\r |
299 | // Link the new Memory Block to the Memory Header list\r |
300 | //\r |
301 | InsertMemoryHeaderToList (MemoryHeader, NewMemoryHeader);\r |
302 | \r |
303 | Status = AllocMemInMemoryBlock (\r |
304 | NewMemoryHeader,\r |
ffac4bcb |
305 | (VOID **) Pool,\r |
562d2849 |
306 | RealAllocSize / 32\r |
307 | );\r |
308 | if (!EFI_ERROR (Status)) {\r |
309 | ZeroMem (*Pool, AllocSize);\r |
310 | }\r |
311 | \r |
312 | gBS->RestoreTPL (OldTpl);\r |
313 | return Status;\r |
314 | }\r |
315 | \r |
316 | VOID\r |
317 | EhciFreePool (\r |
318 | IN USB2_HC_DEV *HcDev,\r |
319 | IN UINT8 *Pool,\r |
320 | IN UINTN AllocSize\r |
321 | )\r |
322 | /*++\r |
323 | \r |
324 | Routine Description:\r |
325 | \r |
326 | Uhci Free Pool\r |
327 | \r |
328 | Arguments:\r |
329 | \r |
330 | HcDev - USB_HC_DEV\r |
331 | Pool - Pool to free\r |
332 | AllocSize - Pool size\r |
333 | \r |
334 | Returns:\r |
335 | \r |
336 | VOID\r |
337 | \r |
338 | --*/\r |
339 | {\r |
340 | MEMORY_MANAGE_HEADER *MemoryHeader;\r |
341 | MEMORY_MANAGE_HEADER *TempHeaderPtr;\r |
342 | UINTN StartBytePos;\r |
343 | UINTN Index;\r |
344 | UINT8 StartBitPos;\r |
345 | UINT8 Index2;\r |
346 | UINTN Count;\r |
347 | UINTN RealAllocSize;\r |
348 | EFI_TPL OldTpl;\r |
349 | \r |
350 | OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY + 1);\r |
351 | \r |
352 | MemoryHeader = HcDev->MemoryHeader;\r |
353 | \r |
354 | //\r |
355 | // allocate unit is 32 byte (align on 32 byte)\r |
356 | //\r |
357 | if (AllocSize & 0x1F) {\r |
358 | RealAllocSize = (AllocSize / 32 + 1) * 32;\r |
359 | } else {\r |
360 | RealAllocSize = AllocSize;\r |
361 | }\r |
362 | \r |
363 | //\r |
364 | // scan the memory header linked list for\r |
365 | // the asigned memory to free.\r |
366 | //\r |
367 | for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL; TempHeaderPtr = TempHeaderPtr->Next) {\r |
368 | \r |
369 | if ((Pool >= TempHeaderPtr->MemoryBlockPtr) &&\r |
370 | ((Pool + RealAllocSize) <= (TempHeaderPtr->MemoryBlockPtr + TempHeaderPtr->MemoryBlockSizeInBytes))\r |
371 | ) {\r |
372 | //\r |
373 | // Pool is in the Memory Block area,\r |
374 | // find the start byte and bit in the bit array\r |
375 | //\r |
376 | StartBytePos = ((Pool - TempHeaderPtr->MemoryBlockPtr) / 32) / 8;\r |
377 | StartBitPos = (UINT8) (((Pool - TempHeaderPtr->MemoryBlockPtr) / 32) & 0x7);\r |
378 | \r |
379 | //\r |
380 | // reset associated bits in bit arry\r |
381 | //\r |
382 | for (Index = StartBytePos, Index2 = StartBitPos, Count = 0; Count < (RealAllocSize / 32); Count++) {\r |
383 | TempHeaderPtr->BitArrayPtr[Index] ^= (UINT8) (bit (Index2));\r |
384 | Index2++;\r |
385 | if (Index2 == 8) {\r |
386 | Index += 1;\r |
387 | Index2 = 0;\r |
388 | }\r |
389 | }\r |
390 | //\r |
391 | // break the loop\r |
392 | //\r |
393 | break;\r |
394 | }\r |
395 | }\r |
396 | \r |
397 | //\r |
398 | // Release emptied memory blocks (only if the memory block is not\r |
399 | // the first one in the memory header list\r |
400 | //\r |
401 | for (TempHeaderPtr = MemoryHeader->Next; TempHeaderPtr != NULL;) {\r |
402 | \r |
403 | ASSERT (MemoryHeader->Next != NULL);\r |
404 | \r |
405 | if (IsMemoryBlockEmptied (TempHeaderPtr)) {\r |
406 | \r |
407 | DelinkMemoryBlock (MemoryHeader, TempHeaderPtr);\r |
408 | //\r |
409 | // when the TempHeaderPtr is freed in FreeMemoryHeader(),\r |
410 | // the TempHeaderPtr is pointing to nonsense content.\r |
411 | //\r |
412 | gBS->RestoreTPL (OldTpl);\r |
413 | FreeMemoryHeader (HcDev, TempHeaderPtr);\r |
414 | OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY + 1);\r |
415 | //\r |
416 | // reset the TempHeaderPtr, continue search for\r |
417 | // another empty memory block.\r |
418 | //\r |
419 | TempHeaderPtr = MemoryHeader->Next;\r |
420 | continue;\r |
421 | }\r |
422 | \r |
423 | TempHeaderPtr = TempHeaderPtr->Next;\r |
424 | }\r |
425 | \r |
426 | gBS->RestoreTPL (OldTpl);\r |
427 | }\r |
428 | \r |
429 | VOID\r |
430 | InsertMemoryHeaderToList (\r |
431 | IN MEMORY_MANAGE_HEADER *MemoryHeader,\r |
432 | IN MEMORY_MANAGE_HEADER *NewMemoryHeader\r |
433 | )\r |
434 | /*++\r |
435 | \r |
436 | Routine Description:\r |
437 | \r |
438 | Insert Memory Header To List\r |
439 | \r |
440 | Arguments:\r |
441 | \r |
442 | MemoryHeader - MEMORY_MANAGE_HEADER\r |
443 | NewMemoryHeader - MEMORY_MANAGE_HEADER\r |
444 | \r |
445 | Returns:\r |
446 | \r |
447 | VOID\r |
448 | \r |
449 | --*/\r |
450 | {\r |
451 | MEMORY_MANAGE_HEADER *TempHeaderPtr;\r |
452 | \r |
453 | for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL; TempHeaderPtr = TempHeaderPtr->Next) {\r |
454 | if (TempHeaderPtr->Next == NULL) {\r |
455 | TempHeaderPtr->Next = NewMemoryHeader;\r |
456 | break;\r |
457 | }\r |
458 | }\r |
459 | }\r |
460 | \r |
461 | EFI_STATUS\r |
462 | AllocMemInMemoryBlock (\r |
463 | IN MEMORY_MANAGE_HEADER *MemoryHeader,\r |
464 | OUT VOID **Pool,\r |
465 | IN UINTN NumberOfMemoryUnit\r |
466 | )\r |
467 | /*++\r |
468 | \r |
469 | Routine Description:\r |
470 | \r |
471 | Alloc Memory In MemoryBlock\r |
472 | \r |
473 | Arguments:\r |
474 | \r |
475 | MemoryHeader - MEMORY_MANAGE_HEADER\r |
476 | Pool - Place to store pointer to memory\r |
477 | NumberOfMemoryUnit - Number Of Memory Unit\r |
478 | \r |
479 | Returns:\r |
480 | \r |
481 | EFI_SUCCESS Success\r |
482 | EFI_NOT_FOUND Can't find the free memory \r |
483 | \r |
484 | --*/\r |
485 | {\r |
486 | UINTN TempBytePos;\r |
487 | UINTN FoundBytePos;\r |
488 | UINT8 Index;\r |
489 | UINT8 FoundBitPos;\r |
490 | UINT8 ByteValue;\r |
491 | UINT8 BitValue;\r |
492 | UINTN NumberOfZeros;\r |
493 | UINTN Count;\r |
494 | \r |
495 | FoundBytePos = 0;\r |
496 | FoundBitPos = 0;\r |
497 | ByteValue = MemoryHeader->BitArrayPtr[0];\r |
498 | NumberOfZeros = 0;\r |
499 | Index = 0;\r |
500 | \r |
501 | for (TempBytePos = 0; TempBytePos < MemoryHeader->BitArraySizeInBytes;) {\r |
502 | \r |
503 | //\r |
504 | // Pop out BitValue from a byte in TempBytePos.\r |
505 | //\r |
506 | BitValue = (UINT8) (ByteValue & 0x1);\r |
507 | \r |
508 | //\r |
509 | // right shift the byte\r |
510 | //\r |
511 | ByteValue /= 2;\r |
512 | \r |
513 | if (BitValue == 0) {\r |
514 | //\r |
515 | // Found a free bit, the NumberOfZeros only record the number\r |
516 | // of those consecutive zeros\r |
517 | //\r |
518 | NumberOfZeros++;\r |
519 | //\r |
520 | // Found enough consecutive free space, break the loop\r |
521 | //\r |
522 | if (NumberOfZeros >= NumberOfMemoryUnit) {\r |
523 | break;\r |
524 | }\r |
525 | } else {\r |
526 | //\r |
527 | // Encountering a '1', meant the bit is ocupied.\r |
528 | //\r |
529 | if (NumberOfZeros >= NumberOfMemoryUnit) {\r |
530 | //\r |
531 | // Found enough consecutive free space,break the loop\r |
532 | //\r |
533 | break;\r |
534 | } else {\r |
535 | //\r |
536 | // the NumberOfZeros only record the number of those consecutive zeros,\r |
537 | // so reset the NumberOfZeros to 0 when encountering '1' before finding\r |
538 | // enough consecutive '0's\r |
539 | //\r |
540 | NumberOfZeros = 0;\r |
541 | //\r |
542 | // reset the (FoundBytePos,FoundBitPos) to the position of '1'\r |
543 | //\r |
544 | FoundBytePos = TempBytePos;\r |
545 | FoundBitPos = Index;\r |
546 | }\r |
547 | }\r |
548 | \r |
549 | //\r |
550 | // step forward a bit\r |
551 | //\r |
552 | Index++;\r |
553 | if (Index == 8) {\r |
554 | //\r |
555 | // step forward a byte, getting the byte value,\r |
556 | // and reset the bit pos.\r |
557 | //\r |
558 | TempBytePos += 1;\r |
559 | ByteValue = MemoryHeader->BitArrayPtr[TempBytePos];\r |
560 | Index = 0;\r |
561 | }\r |
562 | }\r |
563 | \r |
564 | if (NumberOfZeros < NumberOfMemoryUnit) {\r |
565 | return EFI_NOT_FOUND;\r |
566 | }\r |
567 | \r |
568 | //\r |
569 | // Found enough free space.\r |
570 | //\r |
571 | \r |
572 | //\r |
573 | // The values recorded in (FoundBytePos,FoundBitPos) have two conditions:\r |
574 | // 1)(FoundBytePos,FoundBitPos) record the position\r |
575 | // of the last '1' before the consecutive '0's, it must\r |
576 | // be adjusted to the start position of the consecutive '0's.\r |
577 | // 2)the start address of the consecutive '0's is just the start of\r |
578 | // the bitarray. so no need to adjust the values of\r |
579 | // (FoundBytePos,FoundBitPos).\r |
580 | //\r |
581 | if ((MemoryHeader->BitArrayPtr[FoundBytePos] & bit (FoundBitPos)) != 0) {\r |
582 | FoundBitPos += 1;\r |
583 | }\r |
584 | \r |
585 | //\r |
586 | // Have the (FoundBytePos,FoundBitPos) make sense.\r |
587 | //\r |
588 | if (FoundBitPos > 7) {\r |
589 | FoundBytePos += 1;\r |
590 | FoundBitPos -= 8;\r |
591 | }\r |
592 | \r |
593 | //\r |
594 | // Set the memory as allocated\r |
595 | //\r |
596 | for (TempBytePos = FoundBytePos, Index = FoundBitPos, Count = 0; Count < NumberOfMemoryUnit; Count++) {\r |
597 | \r |
598 | MemoryHeader->BitArrayPtr[TempBytePos] |= bit (Index);\r |
599 | Index++;\r |
600 | if (Index == 8) {\r |
601 | TempBytePos += 1;\r |
602 | Index = 0;\r |
603 | }\r |
604 | }\r |
605 | \r |
606 | *Pool = MemoryHeader->MemoryBlockPtr + (FoundBytePos * 8 + FoundBitPos) * 32;\r |
607 | \r |
608 | return EFI_SUCCESS;\r |
609 | }\r |
610 | \r |
611 | BOOLEAN\r |
612 | IsMemoryBlockEmptied (\r |
613 | IN MEMORY_MANAGE_HEADER *MemoryHeaderPtr\r |
614 | )\r |
615 | /*++\r |
616 | \r |
617 | Routine Description:\r |
618 | \r |
619 | Is Memory Block Emptied\r |
620 | \r |
621 | Arguments:\r |
622 | \r |
623 | MemoryHeaderPtr - MEMORY_MANAGE_HEADER\r |
624 | \r |
625 | Returns:\r |
626 | \r |
627 | TRUE Empty\r |
628 | FALSE Not Empty \r |
629 | \r |
630 | --*/\r |
631 | {\r |
632 | UINTN Index;\r |
633 | \r |
634 | for (Index = 0; Index < MemoryHeaderPtr->BitArraySizeInBytes; Index++) {\r |
635 | if (MemoryHeaderPtr->BitArrayPtr[Index] != 0) {\r |
636 | return FALSE;\r |
637 | }\r |
638 | }\r |
639 | \r |
640 | return TRUE;\r |
641 | }\r |
642 | \r |
643 | VOID\r |
644 | DelinkMemoryBlock (\r |
645 | IN MEMORY_MANAGE_HEADER *FirstMemoryHeader,\r |
646 | IN MEMORY_MANAGE_HEADER *NeedFreeMemoryHeader\r |
647 | )\r |
648 | /*++\r |
649 | \r |
650 | Routine Description:\r |
651 | \r |
652 | Delink Memory Block\r |
653 | \r |
654 | Arguments:\r |
655 | \r |
656 | FirstMemoryHeader - MEMORY_MANAGE_HEADER\r |
657 | NeedFreeMemoryHeader - MEMORY_MANAGE_HEADER\r |
658 | \r |
659 | Returns:\r |
660 | \r |
661 | VOID\r |
662 | \r |
663 | --*/\r |
664 | {\r |
665 | MEMORY_MANAGE_HEADER *TempHeaderPtr;\r |
666 | \r |
667 | if ((FirstMemoryHeader == NULL) || (NeedFreeMemoryHeader == NULL)) {\r |
668 | return ;\r |
669 | }\r |
670 | \r |
671 | for (TempHeaderPtr = FirstMemoryHeader; TempHeaderPtr != NULL; TempHeaderPtr = TempHeaderPtr->Next) {\r |
672 | \r |
673 | if (TempHeaderPtr->Next == NeedFreeMemoryHeader) {\r |
674 | //\r |
675 | // Link the before and after\r |
676 | //\r |
677 | TempHeaderPtr->Next = NeedFreeMemoryHeader->Next;\r |
678 | break;\r |
679 | }\r |
680 | }\r |
681 | }\r |
682 | \r |
683 | EFI_STATUS\r |
684 | InitialMemoryManagement (\r |
685 | IN USB2_HC_DEV *HcDev\r |
686 | )\r |
687 | /*++\r |
688 | \r |
689 | Routine Description:\r |
690 | \r |
691 | Initialize Memory Management\r |
692 | \r |
693 | Arguments:\r |
694 | \r |
695 | HcDev - USB2_HC_DEV\r |
696 | \r |
697 | Returns:\r |
698 | \r |
699 | EFI_SUCCESS Success\r |
700 | EFI_DEVICE_ERROR Fail\r |
701 | \r |
702 | --*/\r |
703 | {\r |
704 | EFI_STATUS Status;\r |
705 | MEMORY_MANAGE_HEADER *MemoryHeader;\r |
706 | UINTN MemPages;\r |
707 | \r |
708 | MemPages = NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES;\r |
709 | Status = CreateMemoryBlock (HcDev, &MemoryHeader, MemPages);\r |
710 | if (EFI_ERROR (Status)) {\r |
711 | Status = EFI_OUT_OF_RESOURCES;\r |
712 | goto exit;\r |
713 | }\r |
714 | \r |
715 | HcDev->MemoryHeader = MemoryHeader;\r |
716 | \r |
717 | exit:\r |
718 | return Status;\r |
719 | }\r |
720 | \r |
721 | EFI_STATUS\r |
722 | DeinitialMemoryManagement (\r |
723 | IN USB2_HC_DEV *HcDev\r |
724 | )\r |
725 | /*++\r |
726 | \r |
727 | Routine Description:\r |
728 | \r |
729 | Deinitialize Memory Management\r |
730 | \r |
731 | Arguments:\r |
732 | \r |
733 | HcDev - USB2_HC_DEV\r |
734 | \r |
735 | Returns:\r |
736 | \r |
737 | EFI_SUCCESS Success\r |
738 | EFI_DEVICE_ERROR Fail\r |
739 | \r |
740 | --*/\r |
741 | {\r |
742 | MEMORY_MANAGE_HEADER *TempHeaderPtr;\r |
743 | \r |
744 | for (TempHeaderPtr = HcDev->MemoryHeader->Next; TempHeaderPtr != NULL;) {\r |
745 | \r |
746 | DelinkMemoryBlock (HcDev->MemoryHeader, TempHeaderPtr);\r |
747 | //\r |
748 | // when the TempHeaderPtr is freed in FreeMemoryHeader(),\r |
749 | // the TempHeaderPtr is pointing to nonsense content.\r |
750 | //\r |
751 | FreeMemoryHeader (HcDev, TempHeaderPtr);\r |
752 | //\r |
753 | // reset the TempHeaderPtr,continue free another memory block.\r |
754 | //\r |
755 | TempHeaderPtr = HcDev->MemoryHeader->Next;\r |
756 | }\r |
757 | \r |
758 | FreeMemoryHeader (HcDev, HcDev->MemoryHeader);\r |
759 | \r |
760 | return EFI_SUCCESS;\r |
761 | }\r |