implement hal reusing most code from x86
[reactos.git] / reactos / 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 = 0;
52
53 /* Check the CPU Type */
54 if (Prcb->CpuType <= 4)
55 {
56 /* 486's or equal can't go higher then 10ms */
57 HalpLargestClockMS = 10;
58 HalpNextMSRate = 9;
59 }
60
61 /* Get increment and rollover for the largest time clock ms possible */
62 Increment= HalpRolloverTable[HalpLargestClockMS - 1].HighPart;
63 RollOver = (USHORT)HalpRolloverTable[HalpLargestClockMS - 1].LowPart;
64
65 /* Set the maximum and minimum increment with the kernel */
66 HalpCurrentTimeIncrement = Increment;
67 KeSetTimeIncrement(Increment, HalpRolloverTable[0].HighPart);
68
69 /* Disable interrupts */
70 Ke386SaveFlags(Flags);
71 _disable();
72
73 /* Set the rollover */
74 __outbyte(TIMER_CONTROL_PORT, TIMER_SC0 | TIMER_BOTH | TIMER_MD2);
75 __outbyte(TIMER_DATA_PORT0, RollOver & 0xFF);
76 __outbyte(TIMER_DATA_PORT0, RollOver >> 8);
77
78 /* Restore interrupts if they were previously enabled */
79 Ke386RestoreFlags(Flags);
80
81 /* Save rollover and return */
82 HalpCurrentRollOver = RollOver;
83 }
84
85 /* PUBLIC FUNCTIONS ***********************************************************/
86
87 /*
88 * @implemented
89 */
90 VOID
91 NTAPI
92 HalCalibratePerformanceCounter(IN volatile PLONG Count,
93 IN ULONGLONG NewCount)
94 {
95 ULONG_PTR Flags = 0;
96
97 /* Disable interrupts */
98 Ke386SaveFlags(Flags);
99 _disable();
100
101 /* Do a decrement for this CPU */
102 _InterlockedDecrement(Count);
103
104 /* Wait for other CPUs */
105 while (*Count);
106
107 /* Restore interrupts if they were previously enabled */
108 Ke386RestoreFlags(Flags);
109 }
110
111 /*
112 * @implemented
113 */
114 ULONG
115 NTAPI
116 HalSetTimeIncrement(IN ULONG Increment)
117 {
118 /* Round increment to ms */
119 Increment /= 10000;
120
121 /* Normalize between our minimum (1 ms) and maximum (variable) setting */
122 if (Increment > HalpLargestClockMS) Increment = HalpLargestClockMS;
123 if (Increment <= 0) Increment = 1;
124
125 /* Set the rate and tell HAL we want to change it */
126 HalpNextMSRate = Increment;
127 HalpClockSetMSRate = TRUE;
128
129 /* Return the increment */
130 return HalpRolloverTable[Increment - 1].HighPart;
131 }
132
133 /* EOF */