diff --git a/reactos/hal/halx86/generic/profil.c b/reactos/hal/halx86/generic/profil.c index 186d009b869..a04ae3fb1b6 100644 --- a/reactos/hal/halx86/generic/profil.c +++ b/reactos/hal/halx86/generic/profil.c @@ -13,6 +13,11 @@ #define NDEBUG #include +/* GLOBALS *******************************************************************/ + +BOOLEAN HalpProfilingStopped = TRUE; +UCHAR HalpProfileRate = 8; + /* FUNCTIONS *****************************************************************/ /* @@ -24,6 +29,8 @@ HalStopProfileInterrupt(IN KPROFILE_SOURCE ProfileSource) { UCHAR StatusB; + UNREFERENCED_PARAMETER(ProfileSource); + /* Acquire the CMOS lock */ HalpAcquireCmosSpinLock(); @@ -36,6 +43,8 @@ HalStopProfileInterrupt(IN KPROFILE_SOURCE ProfileSource) /* Write new value into Status Register B */ HalpWriteCmos(RTC_REGISTER_B, StatusB); + HalpProfilingStopped = TRUE; + /* Release the CMOS lock */ HalpReleaseCmosSpinLock(); } @@ -47,8 +56,27 @@ VOID NTAPI HalStartProfileInterrupt(IN KPROFILE_SOURCE ProfileSource) { - UNIMPLEMENTED; - return; + UCHAR StatusA, StatusB; + + UNREFERENCED_PARAMETER(ProfileSource); + + HalpProfilingStopped = FALSE; + + /* Acquire the CMOS lock */ + HalpAcquireCmosSpinLock(); + + /* Set the interval in Status Register A */ + StatusA = HalpReadCmos(RTC_REGISTER_A); + StatusA = (StatusA & 0xF0) | HalpProfileRate; + HalpWriteCmos(RTC_REGISTER_A, StatusA); + + /* Enable periodic interrupts in Status Register B */ + StatusB = HalpReadCmos(RTC_REGISTER_B); + StatusB = StatusB | RTC_REG_B_PI; + HalpWriteCmos(RTC_REGISTER_B, StatusB); + + /* Release the CMOS lock */ + HalpReleaseCmosSpinLock(); } /* @@ -58,6 +86,32 @@ ULONG_PTR NTAPI HalSetProfileInterval(IN ULONG_PTR Interval) { - UNIMPLEMENTED; - return Interval; + ULONG_PTR CurrentValue, NextValue; + UCHAR i; + + /* Normalize interval. 122100 ns is the smallest supported */ + Interval &= ~(1 << 31); + if (Interval < 1221) + Interval = 1221; + + /* Highest rate value of 15 means 500 ms */ + CurrentValue = 5000000; + for (i = 15; ; i--) + { + NextValue = (CurrentValue + 1) / 2; + if (Interval > CurrentValue - NextValue / 2) + break; + CurrentValue = NextValue; + } + + /* Interval as needed by RTC */ + HalpProfileRate = i; + + /* Reset the */ + if (!HalpProfilingStopped) + { + HalStartProfileInterrupt(0); + } + + return CurrentValue; } diff --git a/reactos/hal/halx86/generic/timer.c b/reactos/hal/halx86/generic/timer.c index fafb20982b3..a6bf742e4a2 100644 --- a/reactos/hal/halx86/generic/timer.c +++ b/reactos/hal/halx86/generic/timer.c @@ -188,9 +188,21 @@ HalpProfileInterruptHandler(IN PKTRAP_FRAME TrapFrame) /* Start the interrupt */ if (HalBeginSystemInterrupt(PROFILE_LEVEL, PRIMARY_VECTOR_BASE + 8, &Irql)) { - /* Profiling isn't yet enabled */ - UNIMPLEMENTED; - ASSERT(FALSE); + /* Spin until the interrupt pending bit is clear */ + HalpAcquireCmosSpinLock(); + while (HalpReadCmos(RTC_REGISTER_C) & RTC_REG_C_IRQ) + ; + HalpReleaseCmosSpinLock(); + + /* If profiling is enabled, call the kernel function */ + if (!HalpProfilingStopped) + { + KeProfileInterrupt(TrapFrame); + } + + /* Finish the interrupt */ + _disable(); + HalEndSystemInterrupt(Irql, TrapFrame); } /* Spurious, just end the interrupt */ diff --git a/reactos/hal/halx86/include/halp.h b/reactos/hal/halx86/include/halp.h index f27b7a3909a..91388bd06e7 100644 --- a/reactos/hal/halx86/include/halp.h +++ b/reactos/hal/halx86/include/halp.h @@ -68,6 +68,7 @@ ATTRIB_NORETURN #define RTC_REGISTER_B 0x0B #define RTC_REG_B_PI 0x40 #define RTC_REGISTER_C 0x0C +#define RTC_REG_C_IRQ 0x80 #define RTC_REGISTER_D 0x0D #define RTC_REGISTER_CENTURY 0x32 @@ -585,6 +586,9 @@ VOID HalpDispatchInterrupt2(VOID); DECLSPEC_NORETURN VOID FASTCALL HalpApcInterrupt2ndEntry(IN PKTRAP_FRAME TrapFrame); DECLSPEC_NORETURN VOID FASTCALL HalpDispatchInterrupt2ndEntry(IN PKTRAP_FRAME TrapFrame); +/* profil.c */ +extern BOOLEAN HalpProfilingStopped; + /* timer.c */ VOID NTAPI HalpInitializeClock(VOID); VOID HalpClockInterrupt(VOID);