ReactOS 0.4.15-dev-6067-g0b695a6
rtctimer.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS HAL
3 * LICENSE: GNU GPL - See COPYING in the top level directory
4 * FILE: hal/halx86/apic/rtctimer.c
5 * PURPOSE: HAL APIC Management and Control Code
6 * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
7 * REFERENCES: https://wiki.osdev.org/RTC
8 * https://forum.osdev.org/viewtopic.php?f=13&t=20825&start=0
9 * http://www.bioscentral.com/misc/cmosmap.htm
10 */
11
12/* INCLUDES *******************************************************************/
13
14#include <hal.h>
15#include "apicp.h"
16#define NDEBUG
17#include <debug.h>
18
19/* GLOBALS ********************************************************************/
20
21static const UCHAR RtcMinimumClockRate = 6; /* Minimum rate 6: 1024 Hz / 0.97 ms */
22static const UCHAR RtcMaximumClockRate = 10; /* Maximum rate 10: 64 Hz / 15.6 ms */
23static UCHAR HalpCurrentClockRate = 10; /* Initial rate 10: 64 Hz / 15.6 ms */
31
58{
59 /* Calculate frequency */
60 ULONG Frequency = 32768 >> (Rate - 1);
61
62 /* Calculate interval in 0.1ns interval: Interval = (1 / Frequency) * 10,000,000,000 */
63 return 10000000000ULL / Frequency;
64}
65
66VOID
68{
69 UCHAR RegisterA;
70 ULONG PreciseIncrement;
71
72 /* Update the global values */
73 HalpCurrentClockRate = ClockRate;
74 PreciseIncrement = RtcClockRateToPreciseIncrement(ClockRate);
75 HalpCurrentTimeIncrement = PreciseIncrement / 1000;
76 HalpCurrentFractionalIncrement = PreciseIncrement % 1000;
77
78 /* Acquire CMOS lock */
80
81 // TODO: disable NMI
82
83 /* Read value of register A */
84 RegisterA = HalpReadCmos(RTC_REGISTER_A);
85
86 /* Change lower 4 bits to new rate */
87 RegisterA &= 0xF0;
88 RegisterA |= ClockRate;
89
90 /* Write the new value */
91 HalpWriteCmos(RTC_REGISTER_A, RegisterA);
92
93 /* Release CMOS lock */
95}
96
97CODE_SEG("INIT")
98VOID
101{
102 ULONG_PTR EFlags;
103 UCHAR RegisterB;
104
105 /* Save EFlags and disable interrupts */
106 EFlags = __readeflags();
107 _disable();
108
109 // TODO: disable NMI
110
111 /* Acquire CMOS lock */
113
114 /* Enable the periodic interrupt in the CMOS */
115 RegisterB = HalpReadCmos(RTC_REGISTER_B);
117
118 /* Release CMOS lock */
120
121 /* Set initial rate */
123
124 /* Restore interrupt state */
125 __writeeflags(EFlags);
126
127 /* Calculate minumum and maximum increment */
130
131 /* Notify the kernel about the maximum and minimum increment */
133
134 /* Enable the timer interrupt */
136
137 DPRINT1("Clock initialized\n");
138}
139
140VOID
143{
144 ULONG LastIncrement;
145 KIRQL Irql;
146
147 /* Enter trap */
148 KiEnterInterruptTrap(TrapFrame);
149#ifdef _M_AMD64
150 /* This is for debugging */
151 TrapFrame->ErrorCode = 0xc10c4;
152#endif
153
154 /* Start the interrupt */
156 {
157 /* Spurious, just end the interrupt */
158 KiEoiHelper(TrapFrame);
159 }
160
161 /* Read register C, so that the next interrupt can happen */
163
164 /* Save increment */
165 LastIncrement = HalpCurrentTimeIncrement;
166
167 /* Check if the running fraction has accounted for 100 ns */
169 if (HalpRunningFraction >= 1000)
170 {
171 LastIncrement++;
172 HalpRunningFraction -= 1000;
173 }
174
175 /* Check if someone changed the time rate */
177 {
178 /* Set new clock rate */
180
181 /* We're done */
183 }
184
185 /* Update the system time -- on x86 the kernel will exit this trap */
186 KeUpdateSystemTime(TrapFrame, LastIncrement, Irql);
187}
188
189ULONG
190NTAPI
192{
193 UCHAR Rate;
194 ULONG CurrentIncrement;
195
196 /* Lookup largest value below given Increment */
197 for (Rate = RtcMinimumClockRate; Rate <= RtcMaximumClockRate; Rate++)
198 {
199 /* Check if this is the largest rate possible */
200 CurrentIncrement = RtcClockRateToPreciseIncrement(Rate + 1) / 1000;
201 if (Increment > CurrentIncrement) break;
202 }
203
204 /* Set the rate and tell HAL we want to change it */
205 HalpNextClockRate = Rate;
207
208 /* Return the real increment */
209 return RtcClockRateToPreciseIncrement(Rate) / 1000;
210}
unsigned char BOOLEAN
#define APIC_CLOCK_VECTOR
Definition: apicp.h:44
#define DPRINT1
Definition: precomp.h:8
VOID NTAPI KeSetTimeIncrement(IN ULONG MaxIncrement, IN ULONG MinIncrement)
Definition: ntoskrnl.c:28
_Out_ PKIRQL Irql
Definition: csq.h:179
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
UCHAR KIRQL
Definition: env_spec_w32.h:591
IN OUT PLONG IN OUT PLONG Addend IN OUT PLONG IN LONG Increment
Definition: CrNtStubs.h:46
BOOLEAN NTAPI HalBeginSystemInterrupt(IN KIRQL Irql, IN ULONG Vector, OUT PKIRQL OldIrql)
Definition: pic.c:321
BOOLEAN NTAPI HalEnableSystemInterrupt(IN ULONG Vector, IN KIRQL Irql, IN KINTERRUPT_MODE InterruptMode)
Definition: pic.c:295
VOID FASTCALL KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame, IN ULONG Increment, IN KIRQL OldIrql)
Definition: time.c:64
VOID NTAPI HalpReleaseCmosSpinLock(VOID)
Definition: spinlock.c:243
VOID NTAPI HalpAcquireCmosSpinLock(VOID)
Definition: spinlock.c:226
VOID NTAPI HalpWriteCmos(_In_ UCHAR Reg, _In_ UCHAR Value)
Definition: cmos.c:132
UCHAR NTAPI HalpReadCmos(_In_ UCHAR Reg)
Definition: cmos.c:123
#define RTC_REG_B_PI
Definition: halhw.h:16
#define RTC_REGISTER_B
Definition: halhw.h:15
#define RTC_REGISTER_C
Definition: halhw.h:17
void __cdecl _disable(void)
Definition: intrin_arm.h:365
__INTRIN_INLINE void __writeeflags(uintptr_t Value)
Definition: intrin_x86.h:1669
__INTRIN_INLINE uintptr_t __readeflags(void)
Definition: intrin_x86.h:1674
static CODE_SEG("PAGE")
Definition: isapnp.c:1482
#define CLOCK_LEVEL
Definition: ketypes.h:16
#define FASTCALL
Definition: nt_native.h:50
DECLSPEC_NORETURN VOID FASTCALL KiEoiHelper(IN PKTRAP_FRAME TrapFrame)
Definition: traphdlr.c:126
VOID FASTCALL HalpClockInterruptHandler(IN PKTRAP_FRAME TrapFrame)
Definition: rtctimer.c:142
static UCHAR HalpCurrentClockRate
Definition: rtctimer.c:23
ULONG NTAPI HalSetTimeIncrement(IN ULONG Increment)
Definition: rtctimer.c:191
static BOOLEAN HalpSetClockRate
Definition: rtctimer.c:29
static const UCHAR RtcMinimumClockRate
Definition: rtctimer.c:21
static ULONG HalpCurrentFractionalIncrement
Definition: rtctimer.c:27
static const UCHAR RtcMaximumClockRate
Definition: rtctimer.c:22
static UCHAR HalpNextClockRate
Definition: rtctimer.c:30
static ULONG HalpCurrentTimeIncrement
Definition: rtctimer.c:24
static ULONG HalpRunningFraction
Definition: rtctimer.c:28
VOID RtcSetClockRate(UCHAR ClockRate)
Definition: rtctimer.c:67
FORCEINLINE ULONG RtcClockRateToPreciseIncrement(UCHAR Rate)
Converts the CMOS RTC rate into the time increment in 100ns intervals.
Definition: rtctimer.c:57
VOID NTAPI HalpInitializeClock(VOID)
Definition: rtctimer.c:100
static ULONG HalpMinimumTimeIncrement
Definition: rtctimer.c:25
static ULONG HalpMaximumTimeIncrement
Definition: rtctimer.c:26
@ Latched
Definition: miniport.h:81
static LARGE_INTEGER Frequency
Definition: clock.c:41
FORCEINLINE VOID KiEnterInterruptTrap(IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:368
#define NTAPI
Definition: typedefs.h:36
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define FORCEINLINE
Definition: wdftypes.h:67
#define RTC_REGISTER_A
Definition: xboxrtc.c:21
unsigned char UCHAR
Definition: xmlstorage.h:181