[HAL]
authorThomas Faber <thomas.faber@reactos.org>
Sat, 29 Aug 2015 16:45:00 +0000 (16:45 +0000)
committerThomas Faber <thomas.faber@reactos.org>
Sat, 29 Aug 2015 16:45:00 +0000 (16:45 +0000)
- Implement HalStartProfileInterrupt, HalSetProfileInterval, and HalpProfileInterruptHandler
Now kernrate works!
CORE-10066 #resolve

svn path=/trunk/; revision=68863

reactos/hal/halx86/generic/profil.c
reactos/hal/halx86/generic/timer.c
reactos/hal/halx86/include/halp.h

index 186d009..a04ae3f 100644 (file)
 #define NDEBUG
 #include <debug.h>
 
+/* 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;
 }
index fafb209..a6bf742 100644 (file)
@@ -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 */
index f27b7a3..91388bd 100644 (file)
@@ -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);