Hopefully create a branch and not destroy the svn repository.
[reactos.git] / hal / halx86 / generic / timer.c
1 /*
2 * PROJECT: ReactOS HAL
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)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <hal.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* GLOBALS *******************************************************************/
16
17 BOOLEAN HalpClockSetMSRate;
18 ULONG HalpCurrentTimeIncrement;
19 ULONG HalpCurrentRollOver;
20 ULONG HalpNextMSRate = 14;
21 ULONG HalpLargestClockMS = 15;
22
23 LARGE_INTEGER HalpRolloverTable[15] =
24 {
25 {{1197, 10032}},
26 {{2394, 20064}},
27 {{3591, 30096}},
28 {{4767, 39952}},
29 {{5964, 49984}},
30 {{7161, 60016}},
31 {{8358, 70048}},
32 {{9555, 80080}},
33 {{10731, 89936}},
34 {{11949, 100144}},
35 {{13125, 110000}},
36 {{14322, 120032}},
37 {{15519, 130064}},
38 {{16695, 139920}},
39 {{17892, 149952}}
40 };
41
42 /* PRIVATE FUNCTIONS *********************************************************/
43
44 VOID
45 NTAPI
46 HalpInitializeClock(VOID)
47 {
48 PKPRCB Prcb = KeGetCurrentPrcb();
49 ULONG Increment;
50 USHORT RollOver;
51 ULONG_PTR Flags;
52 TIMER_CONTROL_PORT_REGISTER TimerControl;
53
54 /* Check the CPU Type */
55 if (Prcb->CpuType <= 4)
56 {
57 /* 486's or equal can't go higher then 10ms */
58 HalpLargestClockMS = 10;
59 HalpNextMSRate = 9;
60 }
61
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;
65
66 /* Set the maximum and minimum increment with the kernel */
67 HalpCurrentTimeIncrement = Increment;
68 KeSetTimeIncrement(Increment, HalpRolloverTable[0].HighPart);
69
70 /* Disable interrupts */
71 Flags = __readeflags();
72 _disable();
73
74 //
75 // Program the PIT for binary mode
76 //
77 TimerControl.BcdMode = FALSE;
78
79 //
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.
83 //
84 // Mode 2 gives much better accuracy than Mode 3.
85 //
86 TimerControl.OperatingMode = PitOperatingMode2;
87 TimerControl.Channel = PitChannel0;
88
89 //
90 // Set the access mode that we'll use to program the reload value.
91 //
92 TimerControl.AccessMode = PitAccessModeLowHigh;
93
94 //
95 // Now write the programming bits
96 //
97 __outbyte(TIMER_CONTROL_PORT, TimerControl.Bits);
98
99 //
100 // Next we write the reload value for channel 0
101 //
102 __outbyte(TIMER_CHANNEL0_DATA_PORT, RollOver & 0xFF);
103 __outbyte(TIMER_CHANNEL0_DATA_PORT, RollOver >> 8);
104
105 /* Restore interrupts if they were previously enabled */
106 __writeeflags(Flags);
107
108 /* Save rollover and return */
109 HalpCurrentRollOver = RollOver;
110 }
111
112 /* PUBLIC FUNCTIONS ***********************************************************/
113
114 /*
115 * @implemented
116 */
117 VOID
118 NTAPI
119 HalCalibratePerformanceCounter(IN volatile PLONG Count,
120 IN ULONGLONG NewCount)
121 {
122 ULONG_PTR Flags;
123
124 /* Disable interrupts */
125 Flags = __readeflags();
126 _disable();
127
128 /* Do a decrement for this CPU */
129 _InterlockedDecrement(Count);
130
131 /* Wait for other CPUs */
132 while (*Count);
133
134 /* Restore interrupts if they were previously enabled */
135 __writeeflags(Flags);
136 }
137
138 /*
139 * @implemented
140 */
141 ULONG
142 NTAPI
143 HalSetTimeIncrement(IN ULONG Increment)
144 {
145 /* Round increment to ms */
146 Increment /= 10000;
147
148 /* Normalize between our minimum (1 ms) and maximum (variable) setting */
149 if (Increment > HalpLargestClockMS) Increment = HalpLargestClockMS;
150 if (Increment <= 0) Increment = 1;
151
152 /* Set the rate and tell HAL we want to change it */
153 HalpNextMSRate = Increment;
154 HalpClockSetMSRate = TRUE;
155
156 /* Return the increment */
157 return HalpRolloverTable[Increment - 1].HighPart;
158 }
159
160 /* EOF */