3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: hal/halx86/generic/timer.c
5 * PURPOSE: HAL Timer Routines
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
15 /* GLOBALS *******************************************************************/
17 BOOLEAN HalpClockSetMSRate
;
18 ULONG HalpCurrentTimeIncrement
;
19 ULONG HalpCurrentRollOver
;
20 ULONG HalpNextMSRate
= 14;
21 ULONG HalpLargestClockMS
= 15;
23 LARGE_INTEGER HalpRolloverTable
[15] =
42 /* PRIVATE FUNCTIONS *********************************************************/
46 HalpInitializeClock(VOID
)
48 PKPRCB Prcb
= KeGetCurrentPrcb();
52 TIMER_CONTROL_PORT_REGISTER TimerControl
;
54 /* Check the CPU Type */
55 if (Prcb
->CpuType
<= 4)
57 /* 486's or equal can't go higher then 10ms */
58 HalpLargestClockMS
= 10;
62 /* Get increment and rollover for the largest time clock ms possible */
63 Increment
= HalpRolloverTable
[HalpLargestClockMS
- 1].HighPart
;
64 RollOver
= (USHORT
)HalpRolloverTable
[HalpLargestClockMS
- 1].LowPart
;
66 /* Set the maximum and minimum increment with the kernel */
67 HalpCurrentTimeIncrement
= Increment
;
68 KeSetTimeIncrement(Increment
, HalpRolloverTable
[0].HighPart
);
70 /* Disable interrupts */
71 Flags
= __readeflags();
75 // Program the PIT for binary mode
77 TimerControl
.BcdMode
= FALSE
;
80 // Program the PIT to generate a normal rate wave (Mode 3) on channel 0.
81 // Channel 0 is used for the IRQ0 clock interval timer, and channel
82 // 1 is used for DRAM refresh.
84 // Mode 2 gives much better accuracy than Mode 3.
86 TimerControl
.OperatingMode
= PitOperatingMode2
;
87 TimerControl
.Channel
= PitChannel0
;
90 // Set the access mode that we'll use to program the reload value.
92 TimerControl
.AccessMode
= PitAccessModeLowHigh
;
95 // Now write the programming bits
97 __outbyte(TIMER_CONTROL_PORT
, TimerControl
.Bits
);
100 // Next we write the reload value for channel 0
102 __outbyte(TIMER_CHANNEL0_DATA_PORT
, RollOver
& 0xFF);
103 __outbyte(TIMER_CHANNEL0_DATA_PORT
, RollOver
>> 8);
105 /* Restore interrupts if they were previously enabled */
106 __writeeflags(Flags
);
108 /* Save rollover and return */
109 HalpCurrentRollOver
= RollOver
;
112 /* PUBLIC FUNCTIONS ***********************************************************/
119 HalCalibratePerformanceCounter(IN
volatile PLONG Count
,
120 IN ULONGLONG NewCount
)
124 /* Disable interrupts */
125 Flags
= __readeflags();
128 /* Do a decrement for this CPU */
129 _InterlockedDecrement(Count
);
131 /* Wait for other CPUs */
134 /* Restore interrupts if they were previously enabled */
135 __writeeflags(Flags
);
143 HalSetTimeIncrement(IN ULONG Increment
)
145 /* Round increment to ms */
148 /* Normalize between our minimum (1 ms) and maximum (variable) setting */
149 if (Increment
> HalpLargestClockMS
) Increment
= HalpLargestClockMS
;
150 if (Increment
<= 0) Increment
= 1;
152 /* Set the rate and tell HAL we want to change it */
153 HalpNextMSRate
= Increment
;
154 HalpClockSetMSRate
= TRUE
;
156 /* Return the increment */
157 return HalpRolloverTable
[Increment
- 1].HighPart
;