VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/AcpiTimerLib/AcpiTimerLib.c@ 58172

最後變更 在這個檔案從58172是 58172,由 vboxsync 提交於 9 年 前

EFI: Remove AcpiTimerLib from VBoxPkg and merge changes with OvmfPkg AcpiTimerLib

  • 屬性 svn:eol-style 設為 native
檔案大小: 8.1 KB
 
1/** @file
2 ACPI Timer implements one instance of Timer Library.
3
4 Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2011, Andrei Warkentin <[email protected]>
6
7 This program and the accompanying materials are
8 licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
11
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
15**/
16
17#include <Base.h>
18#include <Library/TimerLib.h>
19#include <Library/BaseLib.h>
20#include <Library/IoLib.h>
21#include <Library/PciLib.h>
22#include <Library/DebugLib.h>
23
24//
25// PIIX4 Power Management Base Address
26//
27#ifndef VBOX
28UINT32 mPmba = 0x400;
29#else
30UINT32 mPmba = 0x4000;
31#endif
32
33#define PCI_BAR_IO 0x1
34#define ACPI_TIMER_FREQUENCY 3579545
35#define ACPI_TIMER_COUNT_SIZE 0x01000000
36#define ACPI_TIMER_OFFSET 0x8
37
38/**
39 The constructor function enables ACPI IO space.
40
41 If ACPI I/O space not enabled, this function will enable it.
42 It will always return RETURN_SUCCESS.
43
44 @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS.
45
46**/
47#ifndef VBOX
48RETURN_STATUS
49EFIAPI
50AcpiTimerLibConstructor (
51 VOID
52 )
53{
54 UINT8 Device;
55
56 Device = 1;
57 // Device = 7;
58
59 if (PciRead8 (PCI_LIB_ADDRESS (0,Device,3,0x80)) & 1) {
60 mPmba = PciRead32 (PCI_LIB_ADDRESS (0,Device,3,0x40));
61 ASSERT (mPmba & PCI_BAR_IO);
62 mPmba &= ~PCI_BAR_IO;
63 } else {
64 PciAndThenOr32 (PCI_LIB_ADDRESS (0,Device,3,0x40),
65 (UINT32) ~0xfc0, mPmba);
66 PciOr8 (PCI_LIB_ADDRESS (0,Device,3,0x04), 0x01);
67 }
68
69 //
70 // ACPI Timer enable is in Bus 0, Device ?, Function 3
71 //
72 PciOr8 (PCI_LIB_ADDRESS (0,Device,3,0x80), 0x01);
73 return RETURN_SUCCESS;
74}
75#else
76RETURN_STATUS
77EFIAPI
78AcpiTimerLibConstructor (
79 VOID
80 )
81{
82 UINT8 u8Device = 7;
83 UINT16 u16VendorID = 0;
84 UINT16 u16DeviceID = 0;
85 u16VendorID = PciRead16(PCI_LIB_ADDRESS(0, u8Device, 0, 0));
86 u16DeviceID = PciRead16(PCI_LIB_ADDRESS(0, u8Device, 0, 2));
87 if ( u16VendorID != 0x8086
88 || u16DeviceID != 0x7113)
89 return RETURN_ABORTED;
90
91 if (PciRead8 (PCI_LIB_ADDRESS (0,u8Device,0,0x80)) & 1) {
92 mPmba = PciRead32 (PCI_LIB_ADDRESS (0, u8Device, 0, 0x40));
93 ASSERT (mPmba & PCI_BAR_IO);
94 DEBUG((DEBUG_INFO, "%a:%d mPmba:%x\n", __FUNCTION__, __LINE__, mPmba));
95 mPmba &= ~PCI_BAR_IO;
96 DEBUG((DEBUG_INFO, "%a:%d mPmba:%x\n", __FUNCTION__, __LINE__, mPmba));
97 } else {
98 PciAndThenOr32 (PCI_LIB_ADDRESS (0,u8Device,0,0x40),
99 (UINT32) ~0xfc0, mPmba);
100 PciOr8 (PCI_LIB_ADDRESS (0,u8Device,0,0x04), 0x01);
101 DEBUG((DEBUG_INFO, "%a:%d mPmba:%x\n", __FUNCTION__, __LINE__, mPmba));
102 }
103
104 //
105 // ACPI Timer enable is in Bus 0, Device ?, Function 3
106 //
107 PciOr8 (PCI_LIB_ADDRESS (0,u8Device,0,0x80), 0x01);
108 return RETURN_SUCCESS;
109}
110#endif
111
112/**
113 Internal function to read the current tick counter of ACPI.
114
115 Internal function to read the current tick counter of ACPI.
116
117 @return The tick counter read.
118
119**/
120STATIC
121UINT32
122InternalAcpiGetTimerTick (
123 VOID
124 )
125{
126 return IoRead32 (mPmba + ACPI_TIMER_OFFSET);
127}
128
129/**
130 Stalls the CPU for at least the given number of ticks.
131
132 Stalls the CPU for at least the given number of ticks. It's invoked by
133 MicroSecondDelay() and NanoSecondDelay().
134
135 @param Delay A period of time to delay in ticks.
136
137**/
138STATIC
139VOID
140InternalAcpiDelay (
141 IN UINT32 Delay
142 )
143{
144 UINT32 Ticks;
145 UINT32 Times;
146
147 Times = Delay >> 22;
148 Delay &= BIT22 - 1;
149 do {
150 //
151 // The target timer count is calculated here
152 //
153 Ticks = InternalAcpiGetTimerTick () + Delay;
154 Delay = BIT22;
155 //
156 // Wait until time out
157 // Delay >= 2^23 could not be handled by this function
158 // Timer wrap-arounds are handled correctly by this function
159 //
160 while (((Ticks - InternalAcpiGetTimerTick ()) & BIT23) == 0) {
161 CpuPause ();
162 }
163 } while (Times-- > 0);
164}
165
166/**
167 Stalls the CPU for at least the given number of microseconds.
168
169 Stalls the CPU for the number of microseconds specified by MicroSeconds.
170
171 @param MicroSeconds The minimum number of microseconds to delay.
172
173 @return MicroSeconds
174
175**/
176UINTN
177EFIAPI
178MicroSecondDelay (
179 IN UINTN MicroSeconds
180 )
181{
182 InternalAcpiDelay (
183 (UINT32)DivU64x32 (
184 MultU64x32 (
185 MicroSeconds,
186 ACPI_TIMER_FREQUENCY
187 ),
188 1000000u
189 )
190 );
191 return MicroSeconds;
192}
193
194/**
195 Stalls the CPU for at least the given number of nanoseconds.
196
197 Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
198
199 @param NanoSeconds The minimum number of nanoseconds to delay.
200
201 @return NanoSeconds
202
203**/
204UINTN
205EFIAPI
206NanoSecondDelay (
207 IN UINTN NanoSeconds
208 )
209{
210 InternalAcpiDelay (
211 (UINT32)DivU64x32 (
212 MultU64x32 (
213 NanoSeconds,
214 ACPI_TIMER_FREQUENCY
215 ),
216 1000000000u
217 )
218 );
219 return NanoSeconds;
220}
221
222/**
223 Retrieves the current value of a 64-bit free running performance counter.
224
225 Retrieves the current value of a 64-bit free running performance counter. The
226 counter can either count up by 1 or count down by 1. If the physical
227 performance counter counts by a larger increment, then the counter values
228 must be translated. The properties of the counter can be retrieved from
229 GetPerformanceCounterProperties().
230
231 @return The current value of the free running performance counter.
232
233**/
234UINT64
235EFIAPI
236GetPerformanceCounter (
237 VOID
238 )
239{
240 return (UINT64)InternalAcpiGetTimerTick ();
241}
242
243/**
244 Retrieves the 64-bit frequency in Hz and the range of performance counter
245 values.
246
247 If StartValue is not NULL, then the value that the performance counter starts
248 with immediately after is it rolls over is returned in StartValue. If
249 EndValue is not NULL, then the value that the performance counter end with
250 immediately before it rolls over is returned in EndValue. The 64-bit
251 frequency of the performance counter in Hz is always returned. If StartValue
252 is less than EndValue, then the performance counter counts up. If StartValue
253 is greater than EndValue, then the performance counter counts down. For
254 example, a 64-bit free running counter that counts up would have a StartValue
255 of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
256 that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
257
258 @param StartValue The value the performance counter starts with when it
259 rolls over.
260 @param EndValue The value that the performance counter ends with before
261 it rolls over.
262
263 @return The frequency in Hz.
264
265**/
266UINT64
267EFIAPI
268GetPerformanceCounterProperties (
269 OUT UINT64 *StartValue, OPTIONAL
270 OUT UINT64 *EndValue OPTIONAL
271 )
272{
273 if (StartValue != NULL) {
274 *StartValue = 0;
275 }
276
277 if (EndValue != NULL) {
278 *EndValue = ACPI_TIMER_COUNT_SIZE - 1;
279 }
280
281 return ACPI_TIMER_FREQUENCY;
282}
283
284/**
285 Converts elapsed ticks of performance counter to time in nanoseconds.
286
287 This function converts the elapsed ticks of running performance counter to
288 time value in unit of nanoseconds.
289
290 @param Ticks The number of elapsed ticks of running performance counter.
291
292 @return The elapsed time in nanoseconds.
293
294**/
295UINT64
296EFIAPI
297GetTimeInNanoSecond (
298 IN UINT64 Ticks
299 )
300{
301 UINT64 NanoSeconds;
302 UINT32 Remainder;
303
304 //
305 // Ticks
306 // Time = --------- x 1,000,000,000
307 // Frequency
308 //
309 NanoSeconds = MultU64x32 (DivU64x32Remainder (Ticks, ACPI_TIMER_FREQUENCY, &Remainder), 1000000000u);
310
311 //
312 // Frequency < 0x100000000, so Remainder < 0x100000000, then (Remainder * 1,000,000,000)
313 // will not overflow 64-bit.
314 //
315 NanoSeconds += DivU64x32 (MultU64x32 ((UINT64) Remainder, 1000000000u), ACPI_TIMER_FREQUENCY);
316
317 return NanoSeconds;
318}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette