TianoCore EDK2 master
Loading...
Searching...
No Matches
LocalApicTimerDxe.c
Go to the documentation of this file.
1
12
13#include "LocalApicTimerDxe.h"
14
15//
16// The handle onto which the Timer Architectural Protocol will be installed
17//
18EFI_HANDLE mTimerHandle = NULL;
19
20//
21// The Timer Architectural Protocol that this driver produces
22//
28};
29
30//
31// Pointer to the CPU Architectural Protocol instance
32//
34
35//
36// The notification function to call on every timer interrupt.
37// A bug in the compiler prevents us from initializing this here.
38//
39EFI_TIMER_NOTIFY mTimerNotifyFunction;
40
41//
42// The current period of the timer interrupt
43//
44volatile UINT64 mTimerPeriod = 0;
45
46//
47// Worker Functions
48//
49
56VOID
57EFIAPI
59 IN EFI_EXCEPTION_TYPE InterruptType,
60 IN EFI_SYSTEM_CONTEXT SystemContext
61 )
62{
63 STATIC NESTED_INTERRUPT_STATE NestedInterruptState;
64 EFI_TPL OriginalTPL;
65
66 OriginalTPL = NestedInterruptRaiseTPL ();
67
68 SendApicEoi ();
69
70 if (mTimerNotifyFunction != NULL) {
71 //
72 // @bug : This does not handle missed timer interrupts
73 //
74 mTimerNotifyFunction (mTimerPeriod);
75 }
76
77 NestedInterruptRestoreTPL (OriginalTPL, SystemContext, &NestedInterruptState);
78}
79
112EFIAPI
116 )
117{
118 //
119 // Check for invalid parameters
120 //
121 if ((NotifyFunction == NULL) && (mTimerNotifyFunction == NULL)) {
122 return EFI_INVALID_PARAMETER;
123 }
124
125 if ((NotifyFunction != NULL) && (mTimerNotifyFunction != NULL)) {
126 return EFI_ALREADY_STARTED;
127 }
128
129 mTimerNotifyFunction = NotifyFunction;
130
131 return EFI_SUCCESS;
132}
133
163EFIAPI
166 IN UINT64 TimerPeriod
167 )
168{
169 UINT64 TimerCount;
170 UINT32 TimerFrequency;
171 UINT32 DivideValue = 1;
172
173 if (TimerPeriod == 0) {
174 //
175 // Disable timer interrupt for a TimerPeriod of 0
176 //
178 } else {
179 TimerFrequency = PcdGet32 (PcdFSBClock) / (UINT32)DivideValue;
180
181 //
182 // Convert TimerPeriod into local APIC counts
183 //
184 // TimerPeriod is in 100ns
185 // TimerPeriod/10000000 will be in seconds.
186 TimerCount = DivU64x32 (
187 MultU64x32 (TimerPeriod, TimerFrequency),
188 10000000
189 );
190
191 // Check for overflow
192 if (TimerCount > MAX_UINT32) {
193 TimerCount = MAX_UINT32;
194 /* TimerPeriod = (MAX_UINT32 / TimerFrequency) * 10000000; */
195 TimerPeriod = 429496730;
196 }
197
198 //
199 // Program the timer with the new count value
200 //
201 InitializeApicTimer (DivideValue, (UINT32)TimerCount, TRUE, LOCAL_APIC_TIMER_VECTOR);
202
203 //
204 // Enable timer interrupt
205 //
207 }
208
209 //
210 // Save the new timer period
211 //
212 mTimerPeriod = TimerPeriod;
213
214 return EFI_SUCCESS;
215}
216
234EFIAPI
237 OUT UINT64 *TimerPeriod
238 )
239{
240 if (TimerPeriod == NULL) {
241 return EFI_INVALID_PARAMETER;
242 }
243
244 *TimerPeriod = mTimerPeriod;
245
246 return EFI_SUCCESS;
247}
248
267EFIAPI
270 )
271{
272 EFI_TPL OriginalTPL;
273
275 //
276 // Invoke the registered handler
277 //
278 OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
279
280 if (mTimerNotifyFunction != NULL) {
281 //
282 // @bug : This does not handle missed timer interrupts
283 //
284 mTimerNotifyFunction (mTimerPeriod);
285 }
286
287 gBS->RestoreTPL (OriginalTPL);
288 } else {
289 return EFI_UNSUPPORTED;
290 }
291
292 return EFI_SUCCESS;
293}
294
307EFIAPI
309 IN EFI_HANDLE ImageHandle,
310 IN EFI_SYSTEM_TABLE *SystemTable
311 )
312{
313 EFI_STATUS Status;
314
315 //
316 // Initialize the pointer to our notify function.
317 //
318 mTimerNotifyFunction = NULL;
319
320 //
321 // Make sure the Timer Architectural Protocol is not already installed in the system
322 //
323 ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiTimerArchProtocolGuid);
324
325 //
326 // Find the CPU architectural protocol.
327 //
328 Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&mCpu);
329 ASSERT_EFI_ERROR (Status);
330
331 //
332 // Force the timer to be disabled
333 //
334 Status = TimerDriverSetTimerPeriod (&mTimer, 0);
335 ASSERT_EFI_ERROR (Status);
336
337 //
338 // Install interrupt handler for Local APIC Timer
339 //
340 Status = mCpu->RegisterInterruptHandler (
341 mCpu,
342 LOCAL_APIC_TIMER_VECTOR,
344 );
345 ASSERT_EFI_ERROR (Status);
346
347 //
348 // Force the timer to be enabled at its default period
349 //
350 Status = TimerDriverSetTimerPeriod (&mTimer, DEFAULT_TIMER_TICK_DURATION);
351 ASSERT_EFI_ERROR (Status);
352
353 //
354 // Install the Timer Architectural Protocol onto a new handle
355 //
356 Status = gBS->InstallMultipleProtocolInterfaces (
357 &mTimerHandle,
358 &gEfiTimerArchProtocolGuid,
359 &mTimer,
360 NULL
361 );
362 ASSERT_EFI_ERROR (Status);
363
364 return Status;
365}
UINT64 EFIAPI DivU64x32(IN UINT64 Dividend, IN UINT32 Divisor)
Definition: DivU64x32.c:29
UINT64 EFIAPI MultU64x32(IN UINT64 Multiplicand, IN UINT32 Multiplier)
Definition: MultU64x32.c:27
BOOLEAN EFIAPI GetApicTimerInterruptState(VOID)
Definition: BaseXApicLib.c:870
VOID EFIAPI EnableApicTimerInterrupt(VOID)
Definition: BaseXApicLib.c:835
VOID EFIAPI InitializeApicTimer(IN UINTN DivideValue, IN UINT32 InitCount, IN BOOLEAN PeriodicMode, IN UINT8 Vector)
Definition: BaseXApicLib.c:732
VOID EFIAPI SendApicEoi(VOID)
Definition: BaseXApicLib.c:885
VOID EFIAPI DisableApicTimerInterrupt(VOID)
Definition: BaseXApicLib.c:851
EFI_STATUS EFIAPI TimerDriverInitialize(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
EFI_STATUS EFIAPI TimerDriverRegisterHandler(IN EFI_TIMER_ARCH_PROTOCOL *This, IN EFI_TIMER_NOTIFY NotifyFunction)
EFI_STATUS EFIAPI TimerDriverGetTimerPeriod(IN EFI_TIMER_ARCH_PROTOCOL *This, OUT UINT64 *TimerPeriod)
EFI_STATUS EFIAPI TimerDriverSetTimerPeriod(IN EFI_TIMER_ARCH_PROTOCOL *This, IN UINT64 TimerPeriod)
EFI_STATUS EFIAPI TimerDriverGenerateSoftInterrupt(IN EFI_TIMER_ARCH_PROTOCOL *This)
VOID EFIAPI TimerInterruptHandler(IN EFI_EXCEPTION_TYPE InterruptType, IN EFI_SYSTEM_CONTEXT SystemContext)
#define NULL
Definition: Base.h:319
#define STATIC
Definition: Base.h:264
#define TRUE
Definition: Base.h:301
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define ASSERT_PROTOCOL_ALREADY_INSTALLED(Handle, Guid)
Definition: DebugLib.h:535
INTN EFI_EXCEPTION_TYPE
Definition: DebugSupport.h:35
VOID(EFIAPI * EFI_TIMER_NOTIFY)(IN UINT64 Time)
Definition: Timer.h:41
VOID EFIAPI NestedInterruptRestoreTPL(IN EFI_TPL InterruptedTPL, IN OUT EFI_SYSTEM_CONTEXT SystemContext, IN OUT NESTED_INTERRUPT_STATE *IsrState)
Definition: Tpl.c:93
EFI_TPL EFIAPI NestedInterruptRaiseTPL(VOID)
Definition: Tpl.c:29
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
VOID EFIAPI NotifyFunction(IN EFI_EVENT Event, IN VOID *Context)
Definition: ScsiBus.c:1492
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
UINTN EFI_TPL
Definition: UefiBaseType.h:41
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS