d99e6981 |
1 | /** @file\r |
2 | Timer Library functions built upon ITC on IPF.\r |
3 | \r |
4 | Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>\r |
5 | This program and the accompanying materials\r |
6 | are licensed and made available under the terms and conditions of the BSD License\r |
7 | which accompanies this distribution. The full text of the license may be found at\r |
8 | http://opensource.org/licenses/bsd-license.php.\r |
9 | \r |
10 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r |
11 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r |
12 | \r |
13 | **/\r |
14 | \r |
15 | #include <Base.h>\r |
16 | #include <Library/TimerLib.h>\r |
17 | #include <Library/BaseLib.h>\r |
18 | #include <Library/PalLib.h>\r |
19 | \r |
20 | \r |
21 | /**\r |
22 | Performs a delay measured as number of ticks.\r |
23 | \r |
24 | An internal function to perform a delay measured as number of ticks. It's\r |
25 | invoked by MicroSecondDelay() and NanoSecondDelay().\r |
26 | \r |
27 | @param Delay The number of ticks to delay.\r |
28 | \r |
29 | **/\r |
30 | VOID\r |
31 | EFIAPI\r |
32 | InternalIpfDelay (\r |
33 | IN INT64 Delay\r |
34 | )\r |
35 | {\r |
36 | INT64 Ticks;\r |
37 | \r |
38 | //\r |
39 | // The target timer count is calculated here\r |
40 | //\r |
41 | Ticks = (INT64)AsmReadItc () + Delay;\r |
42 | \r |
43 | //\r |
44 | // Wait until time out\r |
45 | // Delay > 2^63 could not be handled by this function\r |
46 | // Timer wrap-arounds are handled correctly by this function\r |
47 | //\r |
48 | while (Ticks - (INT64)AsmReadItc() >= 0);\r |
49 | }\r |
50 | \r |
51 | /**\r |
52 | Stalls the CPU for at least the given number of microseconds.\r |
53 | \r |
54 | Stalls the CPU for the number of microseconds specified by MicroSeconds.\r |
55 | \r |
56 | @param MicroSeconds The minimum number of microseconds to delay.\r |
57 | \r |
58 | @return The value of MicroSeconds inputted.\r |
59 | \r |
60 | **/\r |
61 | UINTN\r |
62 | EFIAPI\r |
63 | MicroSecondDelay (\r |
64 | IN UINTN MicroSeconds\r |
65 | )\r |
66 | {\r |
67 | InternalIpfDelay (\r |
68 | GetPerformanceCounterProperties (NULL, NULL) *\r |
69 | MicroSeconds /\r |
70 | 1000000\r |
71 | );\r |
72 | return MicroSeconds;\r |
73 | }\r |
74 | \r |
75 | /**\r |
76 | Stalls the CPU for at least the given number of nanoseconds.\r |
77 | \r |
78 | Stalls the CPU for the number of nanoseconds specified by NanoSeconds.\r |
79 | \r |
80 | @param NanoSeconds The minimum number of nanoseconds to delay.\r |
81 | \r |
82 | @return The value of NanoSeconds inputted.\r |
83 | \r |
84 | **/\r |
85 | UINTN\r |
86 | EFIAPI\r |
87 | NanoSecondDelay (\r |
88 | IN UINTN NanoSeconds\r |
89 | )\r |
90 | {\r |
91 | InternalIpfDelay (\r |
92 | GetPerformanceCounterProperties (NULL, NULL) *\r |
93 | NanoSeconds /\r |
94 | 1000000000\r |
95 | );\r |
96 | return NanoSeconds;\r |
97 | }\r |
98 | \r |
99 | /**\r |
100 | Retrieves the current value of a 64-bit free running performance counter.\r |
101 | \r |
102 | The counter can either count up by 1 or count down by 1. If the physical\r |
103 | performance counter counts by a larger increment, then the counter values\r |
104 | must be translated. The properties of the counter can be retrieved from\r |
105 | GetPerformanceCounterProperties().\r |
106 | \r |
107 | @return The current value of the free running performance counter.\r |
108 | \r |
109 | **/\r |
110 | UINT64\r |
111 | EFIAPI\r |
112 | GetPerformanceCounter (\r |
113 | VOID\r |
114 | )\r |
115 | {\r |
116 | return AsmReadItc ();\r |
117 | }\r |
118 | \r |
119 | /**\r |
120 | Retrieves the 64-bit frequency in Hz and the range of performance counter\r |
121 | values.\r |
122 | \r |
123 | If StartValue is not NULL, then the value that the performance counter starts\r |
124 | with immediately after is it rolls over is returned in StartValue. If\r |
125 | EndValue is not NULL, then the value that the performance counter end with\r |
126 | immediately before it rolls over is returned in EndValue. The 64-bit\r |
127 | frequency of the performance counter in Hz is always returned. If StartValue\r |
128 | is less than EndValue, then the performance counter counts up. If StartValue\r |
129 | is greater than EndValue, then the performance counter counts down. For\r |
130 | example, a 64-bit free running counter that counts up would have a StartValue\r |
131 | of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter\r |
132 | that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.\r |
133 | \r |
134 | @param StartValue The value the performance counter starts with when it\r |
135 | rolls over.\r |
136 | @param EndValue The value that the performance counter ends with before\r |
137 | it rolls over.\r |
138 | \r |
139 | @return The frequency in Hz.\r |
140 | \r |
141 | **/\r |
142 | UINT64\r |
143 | EFIAPI\r |
144 | GetPerformanceCounterProperties (\r |
145 | OUT UINT64 *StartValue, OPTIONAL\r |
146 | OUT UINT64 *EndValue OPTIONAL\r |
147 | )\r |
148 | {\r |
149 | PAL_CALL_RETURN PalRet;\r |
150 | UINT64 BaseFrequence;\r |
151 | \r |
152 | if (StartValue != NULL) {\r |
153 | *StartValue = 0;\r |
154 | }\r |
155 | \r |
156 | if (EndValue != NULL) {\r |
157 | *EndValue = (UINT64)(-1);\r |
158 | }\r |
159 | \r |
160 | PalRet = PalCall (PAL_FREQ_BASE, 0, 0, 0);\r |
161 | if (PalRet.Status != 0) {\r |
162 | return 1000000;\r |
163 | }\r |
164 | BaseFrequence = PalRet.r9;\r |
165 | \r |
166 | PalRet = PalCall (PAL_FREQ_RATIOS, 0, 0, 0);\r |
167 | if (PalRet.Status != 0) {\r |
168 | return 1000000;\r |
169 | }\r |
170 | \r |
171 | return BaseFrequence * (PalRet.r11 >> 32) / (UINT32)PalRet.r11;\r |
172 | }\r |