xref: /reactos/hal/halx86/apic/apictimer.c (revision 407c54ba)
1 /*
2  * PROJECT:         ReactOS HAL
3  * LICENSE:         GPL - See COPYING in the top level directory
4  * FILE:            hal/halx86/apic/apictimer.c
5  * PURPOSE:         System Profiling
6  * PROGRAMMERS:     Timo Kreuzer (timo.kreuzer@reactos.org)
7  */
8 
9 /* INCLUDES ******************************************************************/
10 
11 #include <hal.h>
12 #define NDEBUG
13 #include <debug.h>
14 
15 #include "apic.h"
16 
17 extern LARGE_INTEGER HalpCpuClockFrequency;
18 
19 /* HAL profiling variables */
20 BOOLEAN HalIsProfiling = FALSE;
21 ULONGLONG HalCurProfileInterval = 10000000;
22 ULONGLONG HalMinProfileInterval = 1000;
23 ULONGLONG HalMaxProfileInterval = 10000000;
24 
25 /* TIMER FUNCTIONS ************************************************************/
26 
27 VOID
28 NTAPI
29 ApicSetTimerInterval(ULONG MicroSeconds)
30 {
31     LVT_REGISTER LvtEntry;
32     ULONGLONG TimerInterval;
33 
34     /* Calculate the Timer interval */
35     TimerInterval = HalpCpuClockFrequency.QuadPart * MicroSeconds / 1000000;
36 
37     /* Set the count interval */
38     ApicWrite(APIC_TICR, (ULONG)TimerInterval);
39 
40     /* Set to periodic */
41     LvtEntry.Long = 0;
42     LvtEntry.TimerMode = 1;
43     LvtEntry.Vector = APIC_PROFILE_VECTOR;
44     LvtEntry.Mask = 0;
45     ApicWrite(APIC_TMRLVTR, LvtEntry.Long);
46 
47 }
48 
49 VOID
50 NTAPI
51 ApicInitializeTimer(ULONG Cpu)
52 {
53 
54     /* Initialize the TSC */
55     //HalpInitializeTsc();
56 
57     /* Set clock multiplier to 1 */
58     ApicWrite(APIC_TDCR, TIMER_DV_DivideBy1);
59 
60     ApicSetTimerInterval(1000);
61 
62 // KeSetTimeIncrement
63 }
64 
65 
66 /* PUBLIC FUNCTIONS ***********************************************************/
67 
68 VOID
69 NTAPI
70 HalInitializeProfiling(VOID)
71 {
72     KeGetPcr()->HalReserved[HAL_PROFILING_INTERVAL] = HalCurProfileInterval;
73     KeGetPcr()->HalReserved[HAL_PROFILING_MULTIPLIER] = 1; /* TODO: HACK */
74 }
75 
76 VOID
77 NTAPI
78 HalStartProfileInterrupt(IN KPROFILE_SOURCE ProfileSource)
79 {
80     LVT_REGISTER LvtEntry;
81 
82     /* Only handle ProfileTime */
83     if (ProfileSource == ProfileTime)
84     {
85         /* OK, we are profiling now */
86         HalIsProfiling = TRUE;
87 
88         /* Set interrupt interval */
89         ApicWrite(APIC_TICR, KeGetPcr()->HalReserved[HAL_PROFILING_INTERVAL]);
90 
91         /* Unmask it */
92         LvtEntry.Long = 0;
93         LvtEntry.TimerMode = 1;
94         LvtEntry.Vector = APIC_PROFILE_VECTOR;
95         LvtEntry.Mask = 0;
96         ApicWrite(APIC_TMRLVTR, LvtEntry.Long);
97     }
98 }
99 
100 VOID
101 NTAPI
102 HalStopProfileInterrupt(IN KPROFILE_SOURCE ProfileSource)
103 {
104     LVT_REGISTER LvtEntry;
105 
106     /* Only handle ProfileTime */
107     if (ProfileSource == ProfileTime)
108     {
109         /* We are not profiling */
110         HalIsProfiling = FALSE;
111 
112         /* Mask interrupt */
113         LvtEntry.Long = 0;
114         LvtEntry.TimerMode = 1;
115         LvtEntry.Vector = APIC_PROFILE_VECTOR;
116         LvtEntry.Mask = 1;
117         ApicWrite(APIC_TMRLVTR, LvtEntry.Long);
118     }
119 }
120 
121 ULONG_PTR
122 NTAPI
123 HalSetProfileInterval(IN ULONG_PTR Interval)
124 {
125     ULONGLONG TimerInterval;
126     ULONGLONG FixedInterval;
127 
128     FixedInterval = (ULONGLONG)Interval;
129 
130     /* Check bounds */
131     if (FixedInterval < HalMinProfileInterval)
132     {
133         FixedInterval = HalMinProfileInterval;
134     }
135     else if (FixedInterval > HalMaxProfileInterval)
136     {
137         FixedInterval = HalMaxProfileInterval;
138     }
139 
140     /* Remember interval */
141     HalCurProfileInterval = FixedInterval;
142 
143     /* Recalculate interval for APIC */
144     TimerInterval = FixedInterval * KeGetPcr()->HalReserved[HAL_PROFILING_MULTIPLIER] / HalMaxProfileInterval;
145 
146     /* Remember recalculated interval in PCR */
147     KeGetPcr()->HalReserved[HAL_PROFILING_INTERVAL] = (ULONG)TimerInterval;
148 
149     /* And set it */
150     ApicWrite(APIC_TICR, (ULONG)TimerInterval);
151 
152     return Interval;
153 }
154