[IMM32] Improve ImmGetImeInfoEx (#3833)
[reactos.git] / hal / halppc / generic / timer.c
1 /*
2 * PROJECT: ReactOS HAL
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: hal/halppc/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 Flags = 0;
52
53 /* Get increment and rollover for the largest time clock ms possible */
54 Increment = HalpRolloverTable[HalpLargestClockMS - 1].HighPart;
55 RollOver = (USHORT)HalpRolloverTable[HalpLargestClockMS - 1].LowPart;
56
57 /* Set the maximum and minimum increment with the kernel */
58 HalpCurrentTimeIncrement = Increment;
59 KeSetTimeIncrement(Increment, HalpRolloverTable[0].HighPart);
60
61 /* Disable interrupts */
62 Flags = __readmsr();
63 _disable();
64
65 /* Set the rollover */
66 __outbyte(TIMER_CONTROL_PORT, TIMER_SC0 | TIMER_BOTH | TIMER_MD2);
67 __outbyte(TIMER_DATA_PORT0, RollOver & 0xFF);
68 __outbyte(TIMER_DATA_PORT0, RollOver >> 8);
69
70 /* Restore interrupts if they were previously enabled */
71 __writemsr(Flags);
72
73 /* Save rollover and return */
74 HalpCurrentRollOver = RollOver;
75 }
76
77 /* PUBLIC FUNCTIONS ***********************************************************/
78
79 /*
80 * @implemented
81 */
82 VOID
83 NTAPI
84 HalCalibratePerformanceCounter(IN volatile PLONG Count,
85 IN ULONGLONG NewCount)
86 {
87 ULONG Flags = 0;
88
89 /* Disable interrupts */
90 Flags = __readmsr();
91 _disable();
92
93 /* Do a decrement for this CPU */
94 _InterlockedDecrement(Count);
95
96 /* Wait for other CPUs */
97 while (*Count);
98
99 /* Restore interrupts if they were previously enabled */
100 __writemsr(Flags);
101 }
102
103 /*
104 * @implemented
105 */
106 ULONG
107 NTAPI
108 HalSetTimeIncrement(IN ULONG Increment)
109 {
110 /* Round increment to ms */
111 Increment /= 10000;
112
113 /* Normalize between our minimum (1 ms) and maximum (variable) setting */
114 if (Increment > HalpLargestClockMS) Increment = HalpLargestClockMS;
115 if (Increment <= 0) Increment = 1;
116
117 /* Set the rate and tell HAL we want to change it */
118 HalpNextMSRate = Increment;
119 HalpClockSetMSRate = TRUE;
120
121 /* Return the increment */
122 return HalpRolloverTable[Increment - 1].HighPart;
123 }
124
125 VOID
126 NTHALAPI
127 KeStallExecutionProcessor(ULONG USec)
128 {
129 LARGE_INTEGER Freq, Start = KeQueryPerformanceCounter(&Freq), End;
130 LARGE_INTEGER Timebase, Remainder;
131 Timebase.QuadPart = 1000000;
132 Freq.QuadPart *= USec;
133 End = RtlLargeIntegerDivide(Freq, Timebase, &Remainder);
134 End.QuadPart += Start.QuadPart;
135 while(End.QuadPart > __rdtsc());
136 }
137
138 /* EOF */