2003-06-19 16:00:03 +00:00
|
|
|
/*
|
2006-11-29 08:28:20 +00:00
|
|
|
* PROJECT: ReactOS HAL
|
|
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
|
|
* FILE: hal/halx86/generic/timer.c
|
|
|
|
* PURPOSE: HAL Timer Routines
|
|
|
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
2003-06-19 16:00:03 +00:00
|
|
|
*/
|
|
|
|
|
2006-11-29 08:28:20 +00:00
|
|
|
/* INCLUDES ******************************************************************/
|
2003-06-19 16:00:03 +00:00
|
|
|
|
2005-06-18 14:29:31 +00:00
|
|
|
#include <hal.h>
|
2005-06-19 22:53:49 +00:00
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
2003-06-19 16:00:03 +00:00
|
|
|
|
2006-11-28 08:11:14 +00:00
|
|
|
/* GLOBALS *******************************************************************/
|
2003-06-19 16:00:03 +00:00
|
|
|
|
2010-09-10 13:15:51 +00:00
|
|
|
ULONG HalpPerfCounterCutoff;
|
2006-11-28 08:11:14 +00:00
|
|
|
BOOLEAN HalpClockSetMSRate;
|
|
|
|
ULONG HalpCurrentTimeIncrement;
|
|
|
|
ULONG HalpCurrentRollOver;
|
|
|
|
ULONG HalpNextMSRate = 14;
|
|
|
|
ULONG HalpLargestClockMS = 15;
|
2003-06-19 16:00:03 +00:00
|
|
|
|
2006-11-28 08:11:14 +00:00
|
|
|
LARGE_INTEGER HalpRolloverTable[15] =
|
|
|
|
{
|
|
|
|
{{1197, 10032}},
|
|
|
|
{{2394, 20064}},
|
|
|
|
{{3591, 30096}},
|
|
|
|
{{4767, 39952}},
|
|
|
|
{{5964, 49984}},
|
|
|
|
{{7161, 60016}},
|
|
|
|
{{8358, 70048}},
|
|
|
|
{{9555, 80080}},
|
|
|
|
{{10731, 89936}},
|
|
|
|
{{11949, 100144}},
|
|
|
|
{{13125, 110000}},
|
|
|
|
{{14322, 120032}},
|
|
|
|
{{15519, 130064}},
|
|
|
|
{{16695, 139920}},
|
|
|
|
{{17892, 149952}}
|
|
|
|
};
|
|
|
|
|
|
|
|
/* PRIVATE FUNCTIONS *********************************************************/
|
2003-06-19 16:00:03 +00:00
|
|
|
|
2006-11-28 08:11:14 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
HalpInitializeClock(VOID)
|
|
|
|
{
|
|
|
|
PKPRCB Prcb = KeGetCurrentPrcb();
|
|
|
|
ULONG Increment;
|
|
|
|
USHORT RollOver;
|
Merge HAL changes 34743, 34812, 34839, 34917, 35515, 35771, 35902, 35904,
35905, 35906, 35942, 35947, 35948, 35949, 35953, 36013, 36388, 36389, 36570, 37873, 37991, 39151 from amd64 branch
svn path=/trunk/; revision=43173
2009-09-26 21:32:53 +00:00
|
|
|
ULONG_PTR Flags;
|
2010-01-08 04:31:19 +00:00
|
|
|
TIMER_CONTROL_PORT_REGISTER TimerControl;
|
2003-06-19 16:00:03 +00:00
|
|
|
|
2006-11-28 08:11:14 +00:00
|
|
|
/* Check the CPU Type */
|
|
|
|
if (Prcb->CpuType <= 4)
|
|
|
|
{
|
|
|
|
/* 486's or equal can't go higher then 10ms */
|
|
|
|
HalpLargestClockMS = 10;
|
|
|
|
HalpNextMSRate = 9;
|
|
|
|
}
|
2003-06-19 16:00:03 +00:00
|
|
|
|
2006-11-28 08:11:14 +00:00
|
|
|
/* Get increment and rollover for the largest time clock ms possible */
|
2010-01-08 04:31:19 +00:00
|
|
|
Increment = HalpRolloverTable[HalpLargestClockMS - 1].HighPart;
|
2006-11-28 08:11:14 +00:00
|
|
|
RollOver = (USHORT)HalpRolloverTable[HalpLargestClockMS - 1].LowPart;
|
2003-06-19 16:00:03 +00:00
|
|
|
|
2006-11-28 08:11:14 +00:00
|
|
|
/* Set the maximum and minimum increment with the kernel */
|
|
|
|
HalpCurrentTimeIncrement = Increment;
|
|
|
|
KeSetTimeIncrement(Increment, HalpRolloverTable[0].HighPart);
|
2003-06-19 16:00:03 +00:00
|
|
|
|
2006-11-28 08:11:14 +00:00
|
|
|
/* Disable interrupts */
|
2009-09-18 20:56:49 +00:00
|
|
|
Flags = __readeflags();
|
2006-11-28 08:11:14 +00:00
|
|
|
_disable();
|
2010-01-08 04:31:19 +00:00
|
|
|
|
2010-09-10 13:15:51 +00:00
|
|
|
/* Program the PIT for binary mode */
|
2010-01-08 04:31:19 +00:00
|
|
|
TimerControl.BcdMode = FALSE;
|
2003-06-19 16:00:03 +00:00
|
|
|
|
2010-09-10 13:15:51 +00:00
|
|
|
/*
|
|
|
|
* Program the PIT to generate a normal rate wave (Mode 3) on channel 0.
|
|
|
|
* Channel 0 is used for the IRQ0 clock interval timer, and channel
|
|
|
|
* 1 is used for DRAM refresh.
|
|
|
|
*
|
|
|
|
* Mode 2 gives much better accuracy than Mode 3.
|
|
|
|
*/
|
2010-01-08 04:31:19 +00:00
|
|
|
TimerControl.OperatingMode = PitOperatingMode2;
|
|
|
|
TimerControl.Channel = PitChannel0;
|
|
|
|
|
2010-09-10 13:15:51 +00:00
|
|
|
/* Set the access mode that we'll use to program the reload value */
|
2010-01-08 04:31:19 +00:00
|
|
|
TimerControl.AccessMode = PitAccessModeLowHigh;
|
|
|
|
|
2010-09-10 13:15:51 +00:00
|
|
|
/* Now write the programming bits */
|
2010-01-08 04:31:19 +00:00
|
|
|
__outbyte(TIMER_CONTROL_PORT, TimerControl.Bits);
|
|
|
|
|
2010-09-10 13:15:51 +00:00
|
|
|
/* Next we write the reload value for channel 0 */
|
2010-01-08 04:31:19 +00:00
|
|
|
__outbyte(TIMER_CHANNEL0_DATA_PORT, RollOver & 0xFF);
|
|
|
|
__outbyte(TIMER_CHANNEL0_DATA_PORT, RollOver >> 8);
|
2006-11-28 08:11:14 +00:00
|
|
|
|
2007-03-04 19:06:34 +00:00
|
|
|
/* Restore interrupts if they were previously enabled */
|
2009-09-18 20:56:49 +00:00
|
|
|
__writeeflags(Flags);
|
2006-11-28 08:11:14 +00:00
|
|
|
|
|
|
|
/* Save rollover and return */
|
|
|
|
HalpCurrentRollOver = RollOver;
|
|
|
|
}
|
|
|
|
|
2010-06-04 10:59:19 +00:00
|
|
|
#ifdef _M_IX86
|
2010-03-03 21:56:52 +00:00
|
|
|
#ifndef _MINIHAL_
|
2010-01-26 21:41:05 +00:00
|
|
|
VOID
|
|
|
|
FASTCALL
|
|
|
|
HalpClockInterruptHandler(IN PKTRAP_FRAME TrapFrame)
|
|
|
|
{
|
|
|
|
KIRQL Irql;
|
|
|
|
|
|
|
|
/* Enter trap */
|
|
|
|
KiEnterInterruptTrap(TrapFrame);
|
|
|
|
|
|
|
|
/* Start the interrupt */
|
|
|
|
if (HalBeginSystemInterrupt(CLOCK2_LEVEL, PRIMARY_VECTOR_BASE, &Irql))
|
|
|
|
{
|
|
|
|
/* Update the performance counter */
|
|
|
|
HalpPerfCounter.QuadPart += HalpCurrentRollOver;
|
2010-09-10 13:15:51 +00:00
|
|
|
HalpPerfCounterCutoff = KiEnableTimerWatchdog;
|
2010-01-26 21:41:05 +00:00
|
|
|
|
|
|
|
/* Check if someone changed the time rate */
|
|
|
|
if (HalpClockSetMSRate)
|
|
|
|
{
|
|
|
|
/* Not yet supported */
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
while (TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Update the system time -- the kernel will exit this trap */
|
|
|
|
KeUpdateSystemTime(TrapFrame, HalpCurrentTimeIncrement, Irql);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Spurious, just end the interrupt */
|
|
|
|
KiEoiHelper(TrapFrame);
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
FASTCALL
|
|
|
|
HalpProfileInterruptHandler(IN PKTRAP_FRAME TrapFrame)
|
|
|
|
{
|
|
|
|
KIRQL Irql;
|
|
|
|
|
|
|
|
/* Enter trap */
|
|
|
|
KiEnterInterruptTrap(TrapFrame);
|
|
|
|
|
|
|
|
/* Start the interrupt */
|
|
|
|
if (HalBeginSystemInterrupt(PROFILE_LEVEL, PRIMARY_VECTOR_BASE + 8, &Irql))
|
|
|
|
{
|
|
|
|
/* Profiling isn't yet enabled */
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
while (TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Spurious, just end the interrupt */
|
|
|
|
KiEoiHelper(TrapFrame);
|
|
|
|
}
|
2010-03-03 21:56:52 +00:00
|
|
|
#endif
|
2010-01-26 21:41:05 +00:00
|
|
|
|
2010-06-04 10:59:19 +00:00
|
|
|
#endif
|
2010-01-26 21:41:05 +00:00
|
|
|
|
2006-11-28 08:11:14 +00:00
|
|
|
/* PUBLIC FUNCTIONS ***********************************************************/
|
2003-06-19 16:00:03 +00:00
|
|
|
|
2004-01-12 22:36:04 +00:00
|
|
|
/*
|
2006-11-28 08:11:14 +00:00
|
|
|
* @implemented
|
2004-01-12 22:36:04 +00:00
|
|
|
*/
|
2006-11-28 08:11:14 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
HalCalibratePerformanceCounter(IN volatile PLONG Count,
|
|
|
|
IN ULONGLONG NewCount)
|
2003-06-19 16:00:03 +00:00
|
|
|
{
|
Merge HAL changes 34743, 34812, 34839, 34917, 35515, 35771, 35902, 35904,
35905, 35906, 35942, 35947, 35948, 35949, 35953, 36013, 36388, 36389, 36570, 37873, 37991, 39151 from amd64 branch
svn path=/trunk/; revision=43173
2009-09-26 21:32:53 +00:00
|
|
|
ULONG_PTR Flags;
|
2007-03-04 19:06:34 +00:00
|
|
|
|
2006-11-28 08:11:14 +00:00
|
|
|
/* Disable interrupts */
|
2009-09-18 20:56:49 +00:00
|
|
|
Flags = __readeflags();
|
2006-11-28 08:11:14 +00:00
|
|
|
_disable();
|
|
|
|
|
|
|
|
/* Do a decrement for this CPU */
|
2007-03-04 19:06:34 +00:00
|
|
|
_InterlockedDecrement(Count);
|
2006-11-28 08:11:14 +00:00
|
|
|
|
|
|
|
/* Wait for other CPUs */
|
|
|
|
while (*Count);
|
|
|
|
|
2007-03-04 19:06:34 +00:00
|
|
|
/* Restore interrupts if they were previously enabled */
|
2009-09-18 20:56:49 +00:00
|
|
|
__writeeflags(Flags);
|
2003-06-19 16:00:03 +00:00
|
|
|
}
|
|
|
|
|
2006-11-28 08:11:14 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
ULONG
|
|
|
|
NTAPI
|
|
|
|
HalSetTimeIncrement(IN ULONG Increment)
|
2003-06-19 16:00:03 +00:00
|
|
|
{
|
2006-11-28 08:11:14 +00:00
|
|
|
/* Round increment to ms */
|
|
|
|
Increment /= 10000;
|
|
|
|
|
|
|
|
/* Normalize between our minimum (1 ms) and maximum (variable) setting */
|
|
|
|
if (Increment > HalpLargestClockMS) Increment = HalpLargestClockMS;
|
2006-11-29 17:35:15 +00:00
|
|
|
if (Increment <= 0) Increment = 1;
|
2006-11-28 08:11:14 +00:00
|
|
|
|
|
|
|
/* Set the rate and tell HAL we want to change it */
|
|
|
|
HalpNextMSRate = Increment;
|
|
|
|
HalpClockSetMSRate = TRUE;
|
|
|
|
|
|
|
|
/* Return the increment */
|
|
|
|
return HalpRolloverTable[Increment - 1].HighPart;
|
2003-06-19 16:00:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* EOF */
|