]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/EhciPei/UsbHcMem.c
MdeModulePkg EhciPei: Remove a redundant function
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / EhciPei / UsbHcMem.c
CommitLineData
4b1bf81c 1/** @file\r
2PEIM to produce gPeiUsb2HostControllerPpiGuid based on gPeiUsbControllerPpiGuid\r
3which is used to enable recovery function from USB Drivers.\r
4\r
d1102dba
LG
5Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>\r
6\r
4b1bf81c 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 "EhcPeim.h"\r
19\r
20/**\r
21 Allocate a block of memory to be used by the buffer pool.\r
22\r
23 @param Ehc The EHCI device.\r
24 @param Pool The buffer pool to allocate memory for.\r
25 @param Pages How many pages to allocate.\r
26\r
27 @return The allocated memory block or NULL if failed.\r
28\r
29**/\r
30USBHC_MEM_BLOCK *\r
31UsbHcAllocMemBlock (\r
32 IN PEI_USB2_HC_DEV *Ehc,\r
33 IN USBHC_MEM_POOL *Pool,\r
34 IN UINTN Pages\r
35 )\r
36{\r
37 USBHC_MEM_BLOCK *Block;\r
38 VOID *BufHost;\r
39 VOID *Mapping;\r
40 EFI_PHYSICAL_ADDRESS MappedAddr;\r
41 EFI_STATUS Status;\r
42 UINTN PageNumber;\r
43 EFI_PHYSICAL_ADDRESS TempPtr;\r
44\r
45 Mapping = NULL;\r
46 PageNumber = sizeof(USBHC_MEM_BLOCK)/PAGESIZE +1;\r
47 Status = PeiServicesAllocatePages (\r
48 EfiBootServicesCode,\r
49 PageNumber,\r
50 &TempPtr\r
51 );\r
52\r
53 if (EFI_ERROR (Status)) {\r
54 return NULL;\r
55 }\r
56 ZeroMem ((VOID *)(UINTN)TempPtr, PageNumber*EFI_PAGE_SIZE);\r
d1102dba 57\r
4b1bf81c 58 //\r
59 // each bit in the bit array represents USBHC_MEM_UNIT\r
60 // bytes of memory in the memory block.\r
61 //\r
62 ASSERT (USBHC_MEM_UNIT * 8 <= EFI_PAGE_SIZE);\r
d1102dba 63\r
4b1bf81c 64 Block = (USBHC_MEM_BLOCK*)(UINTN)TempPtr;\r
65 Block->BufLen = EFI_PAGES_TO_SIZE (Pages);\r
66 Block->BitsLen = Block->BufLen / (USBHC_MEM_UNIT * 8);\r
d1102dba 67\r
4b1bf81c 68 PageNumber = (Block->BitsLen)/PAGESIZE +1;\r
69 Status = PeiServicesAllocatePages (\r
70 EfiBootServicesCode,\r
71 PageNumber,\r
72 &TempPtr\r
73 );\r
d1102dba 74\r
4b1bf81c 75 if (EFI_ERROR (Status)) {\r
76 return NULL;\r
77 }\r
d1102dba 78 ZeroMem ((VOID *)(UINTN)TempPtr, PageNumber*EFI_PAGE_SIZE);\r
4b1bf81c 79\r
80 Block->Bits = (UINT8 *)(UINTN)TempPtr;\r
81\r
2c656af0
SZ
82 Status = IoMmuAllocateBuffer (\r
83 Ehc->IoMmu,\r
4b1bf81c 84 Pages,\r
2c656af0
SZ
85 (VOID **) &BufHost,\r
86 &MappedAddr,\r
87 &Mapping\r
4b1bf81c 88 );\r
2c656af0
SZ
89 if (EFI_ERROR (Status)) {\r
90 return NULL;\r
91 }\r
92 ZeroMem (BufHost, Pages*EFI_PAGE_SIZE);\r
4b1bf81c 93\r
4b1bf81c 94 //\r
95 // Check whether the data structure used by the host controller\r
96 // should be restricted into the same 4G\r
97 //\r
98 if (Pool->Check4G && (Pool->Which4G != USB_HC_HIGH_32BIT (MappedAddr))) {\r
99 return NULL;\r
100 }\r
101\r
102 Block->BufHost = BufHost;\r
103 Block->Buf = (UINT8 *) ((UINTN) MappedAddr);\r
104 Block->Mapping = Mapping;\r
105 Block->Next = NULL;\r
106\r
107 return Block;\r
108\r
109}\r
110\r
111/**\r
112 Free the memory block from the memory pool.\r
113\r
2c656af0 114 @param Ehc The EHCI device.\r
4b1bf81c 115 @param Pool The memory pool to free the block from.\r
116 @param Block The memory block to free.\r
117\r
118**/\r
119VOID\r
120UsbHcFreeMemBlock (\r
2c656af0 121 IN PEI_USB2_HC_DEV *Ehc,\r
4b1bf81c 122 IN USBHC_MEM_POOL *Pool,\r
123 IN USBHC_MEM_BLOCK *Block\r
124 )\r
125{\r
126 ASSERT ((Pool != NULL) && (Block != NULL));\r
2c656af0
SZ
127\r
128 IoMmuFreeBuffer (Ehc->IoMmu, EFI_SIZE_TO_PAGES (Block->BufLen), Block->BufHost, Block->Mapping);\r
4b1bf81c 129}\r
130\r
131/**\r
132 Alloc some memory from the block.\r
133\r
134 @param Block The memory block to allocate memory from.\r
135 @param Units Number of memory units to allocate.\r
136\r
137 @return The pointer to the allocated memory. If couldn't allocate the needed memory,\r
138 the return value is NULL.\r
139\r
140**/\r
141VOID *\r
142UsbHcAllocMemFromBlock (\r
143 IN USBHC_MEM_BLOCK *Block,\r
144 IN UINTN Units\r
145 )\r
146{\r
147 UINTN Byte;\r
148 UINT8 Bit;\r
149 UINTN StartByte;\r
150 UINT8 StartBit;\r
151 UINTN Available;\r
152 UINTN Count;\r
153\r
154 ASSERT ((Block != 0) && (Units != 0));\r
155\r
156 StartByte = 0;\r
157 StartBit = 0;\r
158 Available = 0;\r
159\r
160 for (Byte = 0, Bit = 0; Byte < Block->BitsLen;) {\r
161 //\r
162 // If current bit is zero, the corresponding memory unit is\r
163 // available, otherwise we need to restart our searching.\r
164 // Available counts the consective number of zero bit.\r
165 //\r
166 if (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit)) {\r
167 Available++;\r
168\r
169 if (Available >= Units) {\r
170 break;\r
171 }\r
172\r
173 NEXT_BIT (Byte, Bit);\r
174\r
175 } else {\r
176 NEXT_BIT (Byte, Bit);\r
177\r
178 Available = 0;\r
179 StartByte = Byte;\r
180 StartBit = Bit;\r
181 }\r
182 }\r
183\r
184 if (Available < Units) {\r
185 return NULL;\r
186 }\r
d1102dba 187\r
4b1bf81c 188 //\r
189 // Mark the memory as allocated\r
190 //\r
191 Byte = StartByte;\r
192 Bit = StartBit;\r
193\r
194 for (Count = 0; Count < Units; Count++) {\r
195 ASSERT (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));\r
196\r
197 Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] | (UINT8) USB_HC_BIT (Bit));\r
198 NEXT_BIT (Byte, Bit);\r
199 }\r
200\r
201 return Block->Buf + (StartByte * 8 + StartBit) * USBHC_MEM_UNIT;\r
202}\r
203\r
2c656af0
SZ
204/**\r
205 Calculate the corresponding pci bus address according to the Mem parameter.\r
206\r
207 @param Pool The memory pool of the host controller.\r
208 @param Mem The pointer to host memory.\r
209 @param Size The size of the memory region.\r
210\r
211 @return the pci memory address\r
212**/\r
213EFI_PHYSICAL_ADDRESS\r
214UsbHcGetPciAddressForHostMem (\r
215 IN USBHC_MEM_POOL *Pool,\r
216 IN VOID *Mem,\r
217 IN UINTN Size\r
218 )\r
219{\r
220 USBHC_MEM_BLOCK *Head;\r
221 USBHC_MEM_BLOCK *Block;\r
222 UINTN AllocSize;\r
223 EFI_PHYSICAL_ADDRESS PhyAddr;\r
224 UINTN Offset;\r
225\r
226 Head = Pool->Head;\r
227 AllocSize = USBHC_MEM_ROUND (Size);\r
228\r
229 if (Mem == NULL) {\r
230 return 0;\r
231 }\r
232\r
233 for (Block = Head; Block != NULL; Block = Block->Next) {\r
234 //\r
235 // scan the memory block list for the memory block that\r
236 // completely contains the allocated memory.\r
237 //\r
238 if ((Block->BufHost <= (UINT8 *) Mem) && (((UINT8 *) Mem + AllocSize) <= (Block->BufHost + Block->BufLen))) {\r
239 break;\r
240 }\r
241 }\r
242\r
243 ASSERT ((Block != NULL));\r
244 //\r
245 // calculate the pci memory address for host memory address.\r
246 //\r
247 Offset = (UINT8 *)Mem - Block->BufHost;\r
248 PhyAddr = (EFI_PHYSICAL_ADDRESS)(UINTN) (Block->Buf + Offset);\r
249 return PhyAddr;\r
250}\r
251\r
4b1bf81c 252/**\r
253 Insert the memory block to the pool's list of the blocks.\r
254\r
255 @param Head The head of the memory pool's block list.\r
256 @param Block The memory block to insert.\r
257\r
258**/\r
259VOID\r
260UsbHcInsertMemBlockToPool (\r
261 IN USBHC_MEM_BLOCK *Head,\r
262 IN USBHC_MEM_BLOCK *Block\r
263 )\r
264{\r
265 ASSERT ((Head != NULL) && (Block != NULL));\r
266 Block->Next = Head->Next;\r
267 Head->Next = Block;\r
268}\r
269\r
270/**\r
271 Is the memory block empty?\r
272\r
273 @param Block The memory block to check.\r
274\r
275 @retval TRUE The memory block is empty.\r
276 @retval FALSE The memory block isn't empty.\r
277\r
278**/\r
279BOOLEAN\r
280UsbHcIsMemBlockEmpty (\r
281 IN USBHC_MEM_BLOCK *Block\r
282 )\r
283{\r
284 UINTN Index;\r
285\r
d1102dba 286\r
4b1bf81c 287 for (Index = 0; Index < Block->BitsLen; Index++) {\r
288 if (Block->Bits[Index] != 0) {\r
289 return FALSE;\r
290 }\r
291 }\r
292\r
293 return TRUE;\r
294}\r
295\r
4b1bf81c 296\r
297/**\r
298 Initialize the memory management pool for the host controller.\r
d1102dba 299\r
4b1bf81c 300 @param Ehc The EHCI device.\r
301 @param Check4G Whether the host controller requires allocated memory.\r
302 from one 4G address space.\r
303 @param Which4G The 4G memory area each memory allocated should be from.\r
304\r
305 @retval EFI_SUCCESS The memory pool is initialized.\r
306 @retval EFI_OUT_OF_RESOURCE Fail to init the memory pool.\r
307\r
308**/\r
309USBHC_MEM_POOL *\r
310UsbHcInitMemPool (\r
311 IN PEI_USB2_HC_DEV *Ehc,\r
312 IN BOOLEAN Check4G,\r
313 IN UINT32 Which4G\r
314 )\r
315{\r
316 USBHC_MEM_POOL *Pool;\r
317 UINTN PageNumber;\r
318 EFI_STATUS Status;\r
319 EFI_PHYSICAL_ADDRESS TempPtr;\r
d1102dba 320\r
4b1bf81c 321 PageNumber = sizeof(USBHC_MEM_POOL)/PAGESIZE +1;\r
322 Status = PeiServicesAllocatePages (\r
323 EfiBootServicesCode,\r
324 PageNumber,\r
325 &TempPtr\r
326 );\r
327\r
328 if (EFI_ERROR (Status)) {\r
329 return NULL;\r
330 }\r
d1102dba 331 ZeroMem ((VOID *)(UINTN)TempPtr, PageNumber*EFI_PAGE_SIZE);\r
4b1bf81c 332\r
d1102dba 333 Pool = (USBHC_MEM_POOL *) ((UINTN) TempPtr);\r
4b1bf81c 334\r
335 Pool->Check4G = Check4G;\r
336 Pool->Which4G = Which4G;\r
337 Pool->Head = UsbHcAllocMemBlock (Ehc, Pool, USBHC_MEM_DEFAULT_PAGES);\r
338\r
339 if (Pool->Head == NULL) {\r
340 Pool = NULL;\r
341 }\r
342\r
343 return Pool;\r
344}\r
345\r
346/**\r
347 Release the memory management pool.\r
2c656af0
SZ
348\r
349 @param Ehc The EHCI device.\r
4b1bf81c 350 @param Pool The USB memory pool to free.\r
351\r
352 @retval EFI_DEVICE_ERROR Fail to free the memory pool.\r
353 @retval EFI_SUCCESS The memory pool is freed.\r
354\r
355**/\r
356EFI_STATUS\r
357UsbHcFreeMemPool (\r
2c656af0 358 IN PEI_USB2_HC_DEV *Ehc,\r
4b1bf81c 359 IN USBHC_MEM_POOL *Pool\r
360 )\r
361{\r
362 USBHC_MEM_BLOCK *Block;\r
363\r
364 ASSERT (Pool->Head != NULL);\r
365\r
366 //\r
367 // Unlink all the memory blocks from the pool, then free them.\r
4b1bf81c 368 //\r
2c656af0
SZ
369 for (Block = Pool->Head->Next; Block != NULL; Block = Block->Next) {\r
370 UsbHcFreeMemBlock (Ehc, Pool, Block);\r
4b1bf81c 371 }\r
372\r
2c656af0 373 UsbHcFreeMemBlock (Ehc, Pool, Pool->Head);\r
4b1bf81c 374\r
375 return EFI_SUCCESS;\r
376}\r
377\r
378/**\r
379 Allocate some memory from the host controller's memory pool\r
380 which can be used to communicate with host controller.\r
d1102dba 381\r
4b1bf81c 382 @param Ehc The EHCI device.\r
383 @param Pool The host controller's memory pool.\r
384 @param Size Size of the memory to allocate.\r
385\r
386 @return The allocated memory or NULL.\r
387\r
388**/\r
389VOID *\r
390UsbHcAllocateMem (\r
391 IN PEI_USB2_HC_DEV *Ehc,\r
392 IN USBHC_MEM_POOL *Pool,\r
393 IN UINTN Size\r
394 )\r
395{\r
396 USBHC_MEM_BLOCK *Head;\r
397 USBHC_MEM_BLOCK *Block;\r
398 USBHC_MEM_BLOCK *NewBlock;\r
399 VOID *Mem;\r
400 UINTN AllocSize;\r
401 UINTN Pages;\r
402\r
403 Mem = NULL;\r
404 AllocSize = USBHC_MEM_ROUND (Size);\r
405 Head = Pool->Head;\r
406 ASSERT (Head != NULL);\r
407\r
408 //\r
409 // First check whether current memory blocks can satisfy the allocation.\r
410 //\r
411 for (Block = Head; Block != NULL; Block = Block->Next) {\r
412 Mem = UsbHcAllocMemFromBlock (Block, AllocSize / USBHC_MEM_UNIT);\r
413\r
414 if (Mem != NULL) {\r
415 ZeroMem (Mem, Size);\r
416 break;\r
417 }\r
418 }\r
419\r
420 if (Mem != NULL) {\r
421 return Mem;\r
422 }\r
423\r
424 //\r
425 // Create a new memory block if there is not enough memory\r
426 // in the pool. If the allocation size is larger than the\r
427 // default page number, just allocate a large enough memory\r
428 // block. Otherwise allocate default pages.\r
429 //\r
430 if (AllocSize > EFI_PAGES_TO_SIZE (USBHC_MEM_DEFAULT_PAGES)) {\r
431 Pages = EFI_SIZE_TO_PAGES (AllocSize) + 1;\r
432 } else {\r
433 Pages = USBHC_MEM_DEFAULT_PAGES;\r
434 }\r
435 NewBlock = UsbHcAllocMemBlock (Ehc,Pool, Pages);\r
436\r
437 if (NewBlock == NULL) {\r
438 return NULL;\r
439 }\r
d1102dba 440\r
4b1bf81c 441 //\r
442 // Add the new memory block to the pool, then allocate memory from it\r
443 //\r
444 UsbHcInsertMemBlockToPool (Head, NewBlock);\r
445 Mem = UsbHcAllocMemFromBlock (NewBlock, AllocSize / USBHC_MEM_UNIT);\r
446\r
447 if (Mem != NULL) {\r
448 ZeroMem (Mem, Size);\r
449 }\r
450\r
451 return Mem;\r
452}\r
453\r
454/**\r
455 Free the allocated memory back to the memory pool.\r
456\r
2c656af0 457 @param Ehc The EHCI device.\r
4b1bf81c 458 @param Pool The memory pool of the host controller.\r
459 @param Mem The memory to free.\r
460 @param Size The size of the memory to free.\r
461\r
462**/\r
463VOID\r
464UsbHcFreeMem (\r
2c656af0 465 IN PEI_USB2_HC_DEV *Ehc,\r
4b1bf81c 466 IN USBHC_MEM_POOL *Pool,\r
467 IN VOID *Mem,\r
468 IN UINTN Size\r
469 )\r
470{\r
471 USBHC_MEM_BLOCK *Head;\r
472 USBHC_MEM_BLOCK *Block;\r
473 UINT8 *ToFree;\r
474 UINTN AllocSize;\r
475 UINTN Byte;\r
476 UINTN Bit;\r
477 UINTN Count;\r
478\r
479 Head = Pool->Head;\r
480 AllocSize = USBHC_MEM_ROUND (Size);\r
481 ToFree = (UINT8 *) Mem;\r
482\r
483 for (Block = Head; Block != NULL; Block = Block->Next) {\r
484 //\r
485 // scan the memory block list for the memory block that\r
486 // completely contains the memory to free.\r
487 //\r
488 if ((Block->Buf <= ToFree) && ((ToFree + AllocSize) <= (Block->Buf + Block->BufLen))) {\r
489 //\r
490 // compute the start byte and bit in the bit array\r
491 //\r
492 Byte = ((ToFree - Block->Buf) / USBHC_MEM_UNIT) / 8;\r
493 Bit = ((ToFree - Block->Buf) / USBHC_MEM_UNIT) % 8;\r
494\r
495 //\r
2048c585 496 // reset associated bits in bit array\r
4b1bf81c 497 //\r
498 for (Count = 0; Count < (AllocSize / USBHC_MEM_UNIT); Count++) {\r
499 ASSERT (USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));\r
500\r
501 Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] ^ USB_HC_BIT (Bit));\r
502 NEXT_BIT (Byte, Bit);\r
503 }\r
504\r
505 break;\r
506 }\r
507 }\r
508\r
509 //\r
510 // If Block == NULL, it means that the current memory isn't\r
511 // in the host controller's pool. This is critical because\r
512 // the caller has passed in a wrong memory point\r
513 //\r
514 ASSERT (Block != NULL);\r
515\r
516 //\r
517 // Release the current memory block if it is empty and not the head\r
518 //\r
519 if ((Block != Head) && UsbHcIsMemBlockEmpty (Block)) {\r
2c656af0 520 UsbHcFreeMemBlock (Ehc, Pool, Block);\r
4b1bf81c 521 }\r
522\r
523 return ;\r
524}\r