ReactOS  0.4.15-dev-5112-g22d8c0f
timer.c File Reference
#include <hal.h>
#include <debug.h>
Include dependency graph for timer.c:

Go to the source code of this file.

Macros

#define NDEBUG
 
#define PIT_LATCH   0x00
 

Functions

FORCEINLINE ULONG HalpRead8254Value (void)
 
VOID NTAPI HalpSetTimerRollOver (USHORT RollOver)
 
VOID NTAPI HalpInitializeClock (VOID)
 
VOID NTAPI HalCalibratePerformanceCounter (IN volatile PLONG Count, IN ULONGLONG NewCount)
 
ULONG NTAPI HalSetTimeIncrement (IN ULONG Increment)
 
LARGE_INTEGER NTAPI KeQueryPerformanceCounter (PLARGE_INTEGER PerformanceFrequency)
 

Variables

HALP_ROLLOVER HalpRolloverTable [15]
 
LARGE_INTEGER HalpLastPerfCounter
 
LARGE_INTEGER HalpPerfCounter
 
ULONG HalpPerfCounterCutoff
 
BOOLEAN HalpClockSetMSRate
 
ULONG HalpCurrentTimeIncrement
 
ULONG HalpCurrentRollOver
 
ULONG HalpNextMSRate = 14
 
ULONG HalpLargestClockMS = 15
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 13 of file timer.c.

◆ PIT_LATCH

#define PIT_LATCH   0x00

Definition at line 18 of file timer.c.

Function Documentation

◆ HalCalibratePerformanceCounter()

VOID NTAPI HalCalibratePerformanceCounter ( IN volatile PLONG  Count,
IN ULONGLONG  NewCount 
)

Definition at line 212 of file timer.c.

214 {
216 
217  /* Disable interrupts */
218  Flags = __readeflags();
219  _disable();
220 
221  /* Do a decrement for this CPU */
223 
224  /* Wait for other CPUs */
225  while (*Count);
226 
227  /* Restore interrupts if they were previously enabled */
229 }
uint32_t ULONG_PTR
Definition: typedefs.h:65
__INTRIN_INLINE uintptr_t __readeflags(void)
Definition: intrin_x86.h:1666
long __cdecl _InterlockedDecrement(_Interlocked_operand_ long volatile *_Addend)
int Count
Definition: noreturn.cpp:7
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
__INTRIN_INLINE void __writeeflags(uintptr_t Value)
Definition: intrin_x86.h:1661
void __cdecl _disable(void)
Definition: intrin_arm.h:365

◆ HalpInitializeClock()

VOID NTAPI HalpInitializeClock ( VOID  )

Definition at line 92 of file timer.c.

93 {
95  USHORT RollOver;
96 
97  DPRINT("HalpInitializeClock()\n");
98 
99 #if defined(SARCH_PC98)
101 #endif
102 
103  /* Get increment and rollover for the largest time clock ms possible */
105  RollOver = (USHORT)HalpRolloverTable[HalpLargestClockMS - 1].RollOver;
106 
107  /* Set the maximum and minimum increment with the kernel */
109 
110  /* Set the rollover value for the timer */
111  HalpSetTimerRollOver(RollOver);
112 
113  /* Save rollover and increment */
114  HalpCurrentRollOver = RollOver;
116 }
VOID NTAPI KeSetTimeIncrement(IN ULONG MaxIncrement, IN ULONG MinIncrement)
Definition: ntoskrnl.c:28
VOID NTAPI HalpInitializeClockPc98(VOID)
Definition: clock.c:62
ULONG Increment
Definition: halp.h:229
ULONG HalpCurrentRollOver
Definition: timer.c:27
HALP_ROLLOVER HalpRolloverTable[15]
Definition: clock.c:15
ULONG HalpLargestClockMS
Definition: timer.c:29
unsigned short USHORT
Definition: pedump.c:61
ULONG HalpCurrentTimeIncrement
Definition: timer.c:25
unsigned int ULONG
Definition: retypes.h:1
VOID NTAPI HalpSetTimerRollOver(USHORT RollOver)
Definition: timer.c:53
#define DPRINT
Definition: sndvol32.h:71
IN OUT PLONG IN OUT PLONG Addend IN OUT PLONG IN LONG Increment
Definition: CrNtStubs.h:42

◆ HalpRead8254Value()

FORCEINLINE ULONG HalpRead8254Value ( void  )

Definition at line 35 of file timer.c.

36 {
37  ULONG TimerValue;
38 
39  /* Send counter latch command for channel 0 */
41  __nop();
42 
43  /* Read the value, LSB first */
44  TimerValue = __inbyte(TIMER_CHANNEL0_DATA_PORT);
45  __nop();
46  TimerValue |= __inbyte(TIMER_CHANNEL0_DATA_PORT) << 8;
47 
48  return TimerValue;
49 }
PPC_QUAL void __outbyte(unsigned long const Port, const unsigned char Data)
Definition: intrin_ppc.h:605
#define TIMER_CHANNEL0_DATA_PORT
Definition: halhw.h:67
#define PIT_LATCH
Definition: timer.c:18
void __nop(void)
Definition: intrin_x86.h:2034
unsigned int ULONG
Definition: retypes.h:1
#define TIMER_CONTROL_PORT
Definition: halhw.h:70
PPC_QUAL unsigned char __inbyte(const unsigned long Port)
Definition: intrin_ppc.h:539

Referenced by KeQueryPerformanceCounter().

◆ HalpSetTimerRollOver()

VOID NTAPI HalpSetTimerRollOver ( USHORT  RollOver)

Definition at line 53 of file timer.c.

54 {
56  TIMER_CONTROL_PORT_REGISTER TimerControl;
57 
58  /* Disable interrupts */
59  Flags = __readeflags();
60  _disable();
61 
62  /* Program the PIT for binary mode */
63  TimerControl.BcdMode = FALSE;
64 
65  /*
66  * Program the PIT to generate a normal rate wave (Mode 2) on channel 0.
67  * Channel 0 is used for the IRQ0 clock interval timer, and channel
68  * 1 is used for DRAM refresh.
69  *
70  * Mode 2 gives much better accuracy than Mode 3.
71  */
72  TimerControl.OperatingMode = PitOperatingMode2;
73  TimerControl.Channel = PitChannel0;
74 
75  /* Set the access mode that we'll use to program the reload value */
76  TimerControl.AccessMode = PitAccessModeLowHigh;
77 
78  /* Now write the programming bits */
79  __outbyte(TIMER_CONTROL_PORT, TimerControl.Bits);
80 
81  /* Next we write the reload value for channel 0 */
82  __outbyte(TIMER_CHANNEL0_DATA_PORT, RollOver & 0xFF);
83  __outbyte(TIMER_CHANNEL0_DATA_PORT, RollOver >> 8);
84 
85  /* Restore interrupts if they were previously enabled */
87 }
PPC_QUAL void __outbyte(unsigned long const Port, const unsigned char Data)
Definition: intrin_ppc.h:605
uint32_t ULONG_PTR
Definition: typedefs.h:65
__INTRIN_INLINE uintptr_t __readeflags(void)
Definition: intrin_x86.h:1666
#define FALSE
Definition: types.h:117
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define TIMER_CHANNEL0_DATA_PORT
Definition: halhw.h:67
__INTRIN_INLINE void __writeeflags(uintptr_t Value)
Definition: intrin_x86.h:1661
void __cdecl _disable(void)
Definition: intrin_arm.h:365
#define TIMER_CONTROL_PORT
Definition: halhw.h:70

Referenced by HalpInitializeClock().

◆ HalSetTimeIncrement()

ULONG NTAPI HalSetTimeIncrement ( IN ULONG  Increment)

Definition at line 236 of file timer.c.

237 {
238  /* Round increment to ms */
239  Increment /= 10000;
240 
241  /* Normalize between our minimum (1 ms) and maximum (variable) setting */
243  if (Increment <= 0) Increment = 1;
244 
245  /* Set the rate and tell HAL we want to change it */
248 
249  /* Return the increment */
251 }
BOOLEAN HalpClockSetMSRate
Definition: timer.c:25
#define TRUE
Definition: types.h:120
ULONG Increment
Definition: halp.h:229
ULONG HalpNextMSRate
Definition: timer.c:28
HALP_ROLLOVER HalpRolloverTable[15]
Definition: clock.c:15
ULONG HalpLargestClockMS
Definition: timer.c:29
IN OUT PLONG IN OUT PLONG Addend IN OUT PLONG IN LONG Increment
Definition: CrNtStubs.h:42

◆ KeQueryPerformanceCounter()

LARGE_INTEGER NTAPI KeQueryPerformanceCounter ( PLARGE_INTEGER PerformanceFrequency  )

Definition at line 255 of file timer.c.

256 {
257  LARGE_INTEGER CurrentPerfCounter;
258  ULONG CounterValue, ClockDelta;
259  KIRQL OldIrql;
260 
261  /* If caller wants performance frequency, return hardcoded value */
262  if (PerformanceFrequency) PerformanceFrequency->QuadPart = PIT_FREQUENCY;
263 
264  /* Check if we were called too early */
265  if (HalpCurrentRollOver == 0) return HalpPerfCounter;
266 
267  /* Check if interrupts are disabled */
269 
270  /* Raise irql to DISPATCH_LEVEL */
273 
274  do
275  {
276  /* Get the current performance counter value */
277  CurrentPerfCounter = HalpPerfCounter;
278 
279  /* Read the 8254 counter value */
280  CounterValue = HalpRead8254Value();
281 
282  /* Repeat if the value has changed (a clock interrupt happened) */
283  } while (CurrentPerfCounter.QuadPart != HalpPerfCounter.QuadPart);
284 
285  /* After someone changed the clock rate, during the first clock cycle we
286  might see a counter value larger than the rollover. In this case we
287  pretend it already has the new rollover value. */
288  if (CounterValue > HalpCurrentRollOver) CounterValue = HalpCurrentRollOver;
289 
290  /* The interrupt is issued on the falling edge of the OUT line, when the
291  counter changes from 1 to max. Calculate a clock delta, so that directly
292  after the interrupt it is 0, going up to (HalpCurrentRollOver - 1). */
293  ClockDelta = HalpCurrentRollOver - CounterValue;
294 
295  /* Add the clock delta */
296  CurrentPerfCounter.QuadPart += ClockDelta;
297 
298  /* Check if the value is smaller then before, this means, we somehow
299  missed an interrupt. This is a sign that the timer interrupt
300  is very inaccurate. Probably a virtual machine. */
301  if (CurrentPerfCounter.QuadPart < HalpLastPerfCounter.QuadPart)
302  {
303  /* We missed an interrupt. Assume we will receive it later */
304  CurrentPerfCounter.QuadPart += HalpCurrentRollOver;
305  }
306 
307  /* Update the last counter value */
308  HalpLastPerfCounter = CurrentPerfCounter;
309 
310  /* Restore previous irql */
312 
313  /* Return the result */
314  return CurrentPerfCounter;
315 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
UCHAR KIRQL
Definition: env_spec_w32.h:591
__INTRIN_INLINE uintptr_t __readeflags(void)
Definition: intrin_x86.h:1666
ULONG HalpCurrentRollOver
Definition: timer.c:27
KIRQL FASTCALL KfRaiseIrql(IN KIRQL NewIrql)
Definition: pic.c:187
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
VOID FASTCALL KfLowerIrql(IN KIRQL NewIrql)
Definition: pic.c:232
ULONG PIT_FREQUENCY
Definition: clock.c:17
LARGE_INTEGER HalpPerfCounter
Definition: timer.c:23
LARGE_INTEGER HalpLastPerfCounter
Definition: timer.c:22
unsigned int ULONG
Definition: retypes.h:1
FORCEINLINE ULONG HalpRead8254Value(void)
Definition: timer.c:35
LONGLONG QuadPart
Definition: typedefs.h:114
#define EFLAGS_INTERRUPT_MASK
Definition: ketypes.h:126

Variable Documentation

◆ HalpClockSetMSRate

BOOLEAN HalpClockSetMSRate

Definition at line 25 of file timer.c.

Referenced by HalSetTimeIncrement().

◆ HalpCurrentRollOver

ULONG HalpCurrentRollOver

Definition at line 27 of file timer.c.

Referenced by HalpInitializeClock(), and KeQueryPerformanceCounter().

◆ HalpCurrentTimeIncrement

ULONG HalpCurrentTimeIncrement

Definition at line 26 of file timer.c.

◆ HalpLargestClockMS

ULONG HalpLargestClockMS = 15

Definition at line 29 of file timer.c.

Referenced by HalpInitializeClock(), and HalSetTimeIncrement().

◆ HalpLastPerfCounter

LARGE_INTEGER HalpLastPerfCounter

Definition at line 22 of file timer.c.

Referenced by KeQueryPerformanceCounter().

◆ HalpNextMSRate

ULONG HalpNextMSRate = 14

Definition at line 28 of file timer.c.

Referenced by HalSetTimeIncrement().

◆ HalpPerfCounter

LARGE_INTEGER HalpPerfCounter

Definition at line 23 of file timer.c.

Referenced by KeQueryPerformanceCounter().

◆ HalpPerfCounterCutoff

ULONG HalpPerfCounterCutoff

Definition at line 24 of file timer.c.

◆ HalpRolloverTable

HALP_ROLLOVER HalpRolloverTable[15]

Definition at line 15 of file clock.c.

Referenced by HalpInitializeClock(), HalpInitializeClockPc98(), and HalSetTimeIncrement().