]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Misc/Stall.c
MdeModulePkg: Clean up source files
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Misc / Stall.c
CommitLineData
23c98c94 1/** @file\r
504214c4 2 UEFI Miscellaneous boot Services Stall service implementation\r
28a00297 3\r
d1102dba 4Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
cd5ebaa0 5This program and the accompanying materials\r
28a00297 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
504214c4 13**/\r
28a00297 14\r
15//\r
16// Include statements\r
17//\r
18\r
9c4ac31c 19#include "DxeMain.h"\r
28a00297 20\r
a62da87e 21/**\r
d1102dba
LG
22 Internal worker function to call the Metronome Architectural Protocol for\r
23 the number of ticks specified by the UINT64 Counter value. WaitForTick()\r
a62da87e 24 service of the Metronome Architectural Protocol uses a UINT32 for the number\r
25 of ticks to wait, so this function loops when Counter is larger than 0xffffffff.\r
28a00297 26\r
a62da87e 27 @param Counter Number of ticks to wait.\r
28\r
29**/\r
30VOID\r
31CoreInternalWaitForTick (\r
32 IN UINT64 Counter\r
33 )\r
34{\r
769e4531 35 while (RShiftU64 (Counter, 32) > 0) {\r
a62da87e 36 gMetronome->WaitForTick (gMetronome, 0xffffffff);\r
37 Counter -= 0xffffffff;\r
38 }\r
39 gMetronome->WaitForTick (gMetronome, (UINT32)Counter);\r
40}\r
28a00297 41\r
162ed594 42/**\r
28a00297 43 Introduces a fine-grained stall.\r
44\r
162ed594 45 @param Microseconds The number of microseconds to stall execution.\r
28a00297 46\r
022c6d45 47 @retval EFI_SUCCESS Execution was stalled for at least the requested\r
48 amount of microseconds.\r
162ed594 49 @retval EFI_NOT_AVAILABLE_YET gMetronome is not available yet\r
28a00297 50\r
162ed594 51**/\r
52EFI_STATUS\r
53EFIAPI\r
54CoreStall (\r
55 IN UINTN Microseconds\r
56 )\r
28a00297 57{\r
a62da87e 58 UINT64 Counter;\r
28a00297 59 UINT32 Remainder;\r
a62da87e 60 UINTN Index;\r
28a00297 61\r
62 if (gMetronome == NULL) {\r
63 return EFI_NOT_AVAILABLE_YET;\r
64 }\r
65\r
66 //\r
a62da87e 67 // Counter = Microseconds * 10 / gMetronome->TickPeriod\r
68 // 0x1999999999999999 = (2^64 - 1) / 10\r
28a00297 69 //\r
6dee8f78 70 if ((UINT64) Microseconds > 0x1999999999999999ULL) {\r
a62da87e 71 //\r
d1102dba 72 // Microseconds is too large to multiple by 10 first. Perform the divide\r
a62da87e 73 // operation first and loop 10 times to avoid 64-bit math overflow.\r
74 //\r
75 Counter = DivU64x32Remainder (\r
76 Microseconds,\r
77 gMetronome->TickPeriod,\r
78 &Remainder\r
79 );\r
80 for (Index = 0; Index < 10; Index++) {\r
81 CoreInternalWaitForTick (Counter);\r
d1102dba 82 }\r
a62da87e 83\r
84 if (Remainder != 0) {\r
85 //\r
d1102dba 86 // If Remainder was not zero, then normally, Counter would be rounded\r
a62da87e 87 // up by 1 tick. In this case, since a loop for 10 counts was used\r
88 // to emulate the multiply by 10 operation, Counter needs to be rounded\r
89 // up by 10 counts.\r
90 //\r
91 CoreInternalWaitForTick (10);\r
92 }\r
93 } else {\r
94 //\r
95 // Calculate the number of ticks by dividing the number of microseconds by\r
96 // the TickPeriod. Calculation is based on 100ns unit.\r
97 //\r
98 Counter = DivU64x32Remainder (\r
99 MultU64x32 (Microseconds, 10),\r
100 gMetronome->TickPeriod,\r
101 &Remainder\r
102 );\r
103 if (Remainder != 0) {\r
104 //\r
105 // If Remainder is not zero, then round Counter up by one tick.\r
106 //\r
107 Counter++;\r
108 }\r
109 CoreInternalWaitForTick (Counter);\r
28a00297 110 }\r
111\r
28a00297 112 return EFI_SUCCESS;\r
113}\r