Implement KeQueryPerformanceCounter() and move all timer related stuff to
authorGé van Geldorp <ge@gse.nl>
Thu, 19 Jun 2003 16:00:03 +0000 (16:00 +0000)
committerGé van Geldorp <ge@gse.nl>
Thu, 19 Jun 2003 16:00:03 +0000 (16:00 +0000)
a single file timer.c

svn path=/trunk/; revision=4926

reactos/hal/halx86/Makefile
reactos/hal/halx86/perfcnt.c [deleted file]
reactos/hal/halx86/timer.c [new file with mode: 0644]
reactos/hal/halx86/udelay.c [deleted file]

index 2ac742d..b8d26a2 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.9 2003/04/27 18:12:15 ekohl Exp $
+# $Id: Makefile,v 1.10 2003/06/19 16:00:03 gvg Exp $
 
 PATH_TO_TOP = ../..
 
@@ -55,14 +55,13 @@ HAL_OBJECTS = \
        misc.o \
        mp.o \
        pci.o \
-       perfcnt.o \
        portio.o \
        reboot.o \
        spinlock.o \
        sysbus.o \
        sysinfo.o \
        time.o \
-       udelay.o
+       timer.o
 
        #pwroff.o
 
diff --git a/reactos/hal/halx86/perfcnt.c b/reactos/hal/halx86/perfcnt.c
deleted file mode 100644 (file)
index e8644ec..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* $Id: perfcnt.c,v 1.3 2002/09/08 10:22:24 chorns Exp $
- *
- * COPYRIGHT:      See COPYING in the top level directory
- * PROJECT:        ReactOS kernel
- * FILE:           ntoskrnl/hal/x86/perfcnt.c
- * PURPOSE:        Performance counter functions
- * PROGRAMMER:     David Welch (welch@mcmail.com)
- *                 Eric Kohl (ekohl@rz-online.de)
- * UPDATE HISTORY:
- *                 09/06/2000: Created
- */
-
-
-/* INCLUDES ***************************************************************/
-
-#include <ddk/ntddk.h>
-
-/* FUNCTIONS **************************************************************/
-
-
-VOID STDCALL
-HalCalibratePerformanceCounter(ULONG Count)
-{
-   ULONG i;
-
-   /* save flags and disable interrupts */
-   __asm__("pushf\n\t" \
-          "cli\n\t");
-
-   for (i = 0; i < Count; i++);
-
-   /* restore flags */
-   __asm__("popf\n\t");
-}
-
-
-LARGE_INTEGER STDCALL
-KeQueryPerformanceCounter(PLARGE_INTEGER PerformanceFreq)
-/*
- * FUNCTION: Queries the finest grained running count avaiable in the system
- * ARGUMENTS:
- *         PerformanceFreq (OUT) = The routine stores the number of 
- *                                 performance counters tick per second here
- * RETURNS: The performance counter value in HERTZ
- * NOTE: Returns the system tick count or the time-stamp on the pentium
- */
-{
-  if (PerformanceFreq != NULL)
-    {
-      PerformanceFreq->QuadPart = 0;
-      return *PerformanceFreq;
-    }
-  else
-    {
-     LARGE_INTEGER Value;
-
-     Value.QuadPart = 0; 
-     return Value;
-    }
-}
-
-/* EOF */
diff --git a/reactos/hal/halx86/timer.c b/reactos/hal/halx86/timer.c
new file mode 100644 (file)
index 0000000..6e0825a
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * ReactOS kernel
+ * Copyright (C) 2000 David Welch <welch@cwcom.net>
+ * Copyright (C) 1999 Gareth Owen <gaz@athene.co.uk>, Ramon von Handel
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * 
+ * This software is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write
+ * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+ * MA 02139, USA.  
+ *
+ */
+/* $Id: timer.c,v 1.1 2003/06/19 16:00:03 gvg Exp $
+ *
+ * PROJECT:        ReactOS kernel
+ * FILE:           ntoskrnl/hal/x86/udelay.c
+ * PURPOSE:        Busy waiting
+ * PROGRAMMER:     David Welch (david.welch@seh.ox.ac.uk)
+ * UPDATE HISTORY:
+ *                 06/11/99 Created
+ */
+
+/* INCLUDES ***************************************************************/
+
+#include <ddk/ntddk.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+/* GLOBALS ******************************************************************/
+
+static unsigned int delay_count = 1;
+
+#define        TMR_CTRL        0x43    /*      I/O for control         */
+#define                TMR_CNT0        0x40    /*      I/O for counter 0       */
+#define                TMR_CNT1        0x41    /*      I/O for counter 1       */
+#define                TMR_CNT2        0x42    /*      I/O for counter 2       */
+
+#define                TMR_SC0         0       /*      Select channel 0        */
+#define                TMR_SC1         0x40    /*      Select channel 1        */
+#define                TMR_SC2         0x80    /*      Select channel 2        */
+
+#define                TMR_LOW         0x10    /*      RW low byte only        */
+#define                TMR_HIGH        0x20    /*      RW high byte only       */
+#define                TMR_BOTH        0x30    /*      RW both bytes           */
+
+#define                TMR_MD0         0       /*      Mode 0                  */
+#define                TMR_MD1         0x2     /*      Mode 1                  */
+#define                TMR_MD2         0x4     /*      Mode 2                  */
+#define                TMR_MD3         0x6     /*      Mode 3                  */
+#define                TMR_MD4         0x8     /*      Mode 4                  */
+#define                TMR_MD5         0xA     /*      Mode 5                  */
+
+#define                TMR_BCD         1       /*      BCD mode                */
+
+#define                TMR_LATCH       0       /*      Latch command           */
+
+#define                TMR_READ        0xF0    /*    Read command              */
+#define                TMR_CNT         0x20    /*    CNT bit  (Active low, subtract it) */
+#define                TMR_STAT        0x10    /*    Status bit  (Active low, subtract it) */
+#define                TMR_CH2         0x8     /*    Channel 2 bit             */
+#define                TMR_CH1         0x4     /*    Channel 1 bit             */
+#define                TMR_CH0         0x2     /*    Channel 0 bit             */
+
+#define MILLISEC        10                     /* Number of millisec between interrupts */
+#define HZ              (1000 / MILLISEC)      /* Number of interrupts per second */
+#define CLOCK_TICK_RATE 1193182                /* Clock frequency of the timer chip */
+#define LATCH           (CLOCK_TICK_RATE / HZ) /* Count to program into the timer chip */
+#define PRECISION       8                      /* Number of bits to calibrate for delay loop */
+
+static BOOLEAN UdelayCalibrated = FALSE;
+
+/* FUNCTIONS **************************************************************/
+
+VOID STDCALL
+__KeStallExecutionProcessor(ULONG Loops)
+{
+   register unsigned int i;
+   for (i=0; i<Loops;i++);
+}
+
+VOID STDCALL KeStallExecutionProcessor(ULONG Microseconds)
+{
+   __KeStallExecutionProcessor((delay_count*Microseconds)/1000);
+}
+
+static ULONG Read8254Timer(VOID)
+{
+  ULONG Count;
+
+  /* save flags and disable interrupts */
+  __asm__("pushf\n\t" \
+          "cli\n\t");
+
+  WRITE_PORT_UCHAR((PUCHAR) TMR_CTRL, TMR_SC0 | TMR_LATCH);
+  Count = READ_PORT_UCHAR((PUCHAR) TMR_CNT0);
+  Count |= READ_PORT_UCHAR((PUCHAR) TMR_CNT0) << 8;
+
+  /* restore flags */
+  __asm__("popf\n\t");
+
+  return Count;
+}
+
+
+static VOID WaitFor8254Wraparound(VOID)
+{
+  ULONG CurCount, PrevCount = ~0;
+  LONG Delta;
+
+  CurCount = Read8254Timer();
+
+  do
+    {
+      PrevCount = CurCount;
+      CurCount = Read8254Timer();
+      Delta = CurCount - PrevCount;
+
+      /*
+       * This limit for delta seems arbitrary, but it isn't, it's
+       * slightly above the level of error a buggy Mercury/Neptune
+       * chipset timer can cause.
+       */
+
+    }
+   while (Delta < 300);
+}
+
+VOID HalpCalibrateStallExecution(VOID)
+{
+  ULONG i;
+  ULONG calib_bit;
+  ULONG CurCount;
+
+  if (UdelayCalibrated)
+    {
+      return;
+    }
+
+  UdelayCalibrated = TRUE;
+
+  DbgPrint("Calibrating delay loop... [");
+
+  /* Initialise timer interrupt with MILLISEC ms interval        */
+  WRITE_PORT_UCHAR((PUCHAR) TMR_CTRL, TMR_SC0 | TMR_BOTH | TMR_MD2);  /* binary, mode 2, LSB/MSB, ch 0 */
+  WRITE_PORT_UCHAR((PUCHAR) TMR_CNT0, LATCH & 0xff); /* LSB */
+  WRITE_PORT_UCHAR((PUCHAR) TMR_CNT0, LATCH >> 8); /* MSB */
+
+  /* Stage 1:  Coarse calibration                                   */
+
+  WaitFor8254Wraparound();
+
+  delay_count = 1;
+
+  do
+    {
+      delay_count <<= 1;                  /* Next delay count to try */
+
+      WaitFor8254Wraparound();
+
+      __KeStallExecutionProcessor(delay_count);      /* Do the delay */
+
+      CurCount = Read8254Timer();
+    }
+  while (CurCount > LATCH / 2);
+
+  delay_count >>= 1;              /* Get bottom value for delay     */
+
+  /* Stage 2:  Fine calibration                                     */
+  DbgPrint("delay_count: %d", delay_count);
+
+  calib_bit = delay_count;        /* Which bit are we going to test */
+
+  for (i = 0; i < PRECISION; i++)
+    {
+      calib_bit >>= 1;            /* Next bit to calibrate          */
+      if (!calib_bit)
+       {
+         break;                  /* If we have done all bits, stop */
+       }
+
+      delay_count |= calib_bit;   /* Set the bit in delay_count */
+
+      WaitFor8254Wraparound();
+
+      __KeStallExecutionProcessor(delay_count);      /* Do the delay */
+
+      CurCount = Read8254Timer();
+      if (CurCount <= LATCH / 2)   /* If a tick has passed, turn the */
+       {                          /* calibrated bit back off        */
+         delay_count &= ~calib_bit;
+       }
+    }
+
+  /* We're finished:  Do the finishing touches                      */
+
+  delay_count /= (MILLISEC / 2);   /* Calculate delay_count for 1ms */
+
+  DbgPrint("]\n");
+  DbgPrint("delay_count: %d\n", delay_count);
+  DbgPrint("CPU speed: %d\n", delay_count / 250);
+#if 0
+  DbgPrint("About to start delay loop test\n");
+  DbgPrint("Waiting for five minutes...");
+  for (i = 0; i < (5*60*1000*20); i++)
+    {
+      KeStallExecutionProcessor(50);
+    }
+  DbgPrint("finished\n");
+  for(;;);
+#endif
+}
+
+
+VOID STDCALL
+HalCalibratePerformanceCounter(ULONG Count)
+{
+   ULONG i;
+
+   /* save flags and disable interrupts */
+   __asm__("pushf\n\t" \
+          "cli\n\t");
+
+   for (i = 0; i < Count; i++);
+
+   /* restore flags */
+   __asm__("popf\n\t");
+}
+
+
+LARGE_INTEGER STDCALL
+KeQueryPerformanceCounter(PLARGE_INTEGER PerformanceFreq)
+/*
+ * FUNCTION: Queries the finest grained running count available in the system
+ * ARGUMENTS:
+ *         PerformanceFreq (OUT) = The routine stores the number of 
+ *                                 performance counter ticks per second here
+ * RETURNS: The number of performance counter ticks since boot
+ */
+{
+  LARGE_INTEGER TicksOld;
+  LARGE_INTEGER TicksNew;
+  LARGE_INTEGER Value;
+  ULONG CountsLeft;
+
+  if (NULL != PerformanceFreq)
+    {
+      PerformanceFreq->QuadPart = CLOCK_TICK_RATE;
+    }
+
+  do
+    {
+      KeQueryTickCount(&TicksOld);
+      CountsLeft = Read8254Timer();
+      Value.QuadPart = TicksOld.QuadPart * LATCH + (LATCH - CountsLeft);
+      KeQueryTickCount(&TicksNew);
+    }
+  while (TicksOld.QuadPart != TicksNew.QuadPart);
+
+  return Value;
+}
+
+/* EOF */
diff --git a/reactos/hal/halx86/udelay.c b/reactos/hal/halx86/udelay.c
deleted file mode 100644 (file)
index 8fce207..0000000
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * ReactOS kernel
- * Copyright (C) 2000 David Welch <welch@cwcom.net>
- * Copyright (C) 1999 Gareth Owen <gaz@athene.co.uk>, Ramon von Handel
- * Copyright (C) 1991, 1992 Linus Torvalds
- * 
- * This software is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; see the file COPYING. If not, write
- * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
- * MA 02139, USA.  
- *
- */
-/* $Id: udelay.c,v 1.3 2002/09/08 10:22:25 chorns Exp $
- *
- * PROJECT:        ReactOS kernel
- * FILE:           ntoskrnl/hal/x86/udelay.c
- * PURPOSE:        Busy waiting
- * PROGRAMMER:     David Welch (david.welch@seh.ox.ac.uk)
- * UPDATE HISTORY:
- *                 06/11/99 Created
- */
-
-/* INCLUDES ***************************************************************/
-
-#include <ddk/ntddk.h>
-
-#define NDEBUG
-#include <internal/debug.h>
-
-/* GLOBALS ******************************************************************/
-
-static unsigned int delay_count = 1;
-
-#define MILLISEC     (10)
-#define FREQ         (1000/MILLISEC)
-
-#define PRECISION    (8)
-
-#define        TMR_CTRL        0x43    /*      I/O for control         */
-#define                TMR_CNT0        0x40    /*      I/O for counter 0       */
-#define                TMR_CNT1        0x41    /*      I/O for counter 1       */
-#define                TMR_CNT2        0x42    /*      I/O for counter 2       */
-
-#define                TMR_SC0         0       /*      Select channel 0        */
-#define                TMR_SC1         0x40    /*      Select channel 1        */
-#define                TMR_SC2         0x80    /*      Select channel 2        */
-
-#define                TMR_LOW         0x10    /*      RW low byte only        */
-#define                TMR_HIGH        0x20    /*      RW high byte only       */
-#define                TMR_BOTH        0x30    /*      RW both bytes           */
-
-#define                TMR_MD0         0       /*      Mode 0                  */
-#define                TMR_MD1         0x2     /*      Mode 1                  */
-#define                TMR_MD2         0x4     /*      Mode 2                  */
-#define                TMR_MD3         0x6     /*      Mode 3                  */
-#define                TMR_MD4         0x8     /*      Mode 4                  */
-#define                TMR_MD5         0xA     /*      Mode 5                  */
-
-#define                TMR_BCD         1       /*      BCD mode                */
-
-#define                TMR_LATCH       0       /*      Latch command           */
-
-#define                TMR_READ        0xF0    /*    Read command              */
-#define                TMR_CNT         0x20    /*    CNT bit  (Active low, subtract it) */
-#define                TMR_STAT        0x10    /*    Status bit  (Active low, subtract it) */
-#define                TMR_CH2         0x8     /*    Channel 2 bit             */
-#define                TMR_CH1         0x4     /*    Channel 1 bit             */
-#define                TMR_CH0         0x2     /*    Channel 0 bit             */
-
-static BOOLEAN UdelayCalibrated = FALSE;
-
-/* FUNCTIONS **************************************************************/
-
-void init_pit(float h, unsigned char channel)
-{
-       unsigned int temp=0;
-       
-       temp = 1193180/h;
-       
-//     WRITE_PORT_UCHAR((PUCHAR)TMR_CTRL, 
-//                      (channel*0x40) + TMR_BOTH + TMR_MD3);
-        WRITE_PORT_UCHAR((PUCHAR)TMR_CTRL,
-                        (channel*0x40) + TMR_BOTH + TMR_MD2);
-       WRITE_PORT_UCHAR((PUCHAR)(0x40+channel), 
-                        (unsigned char) temp);
-       WRITE_PORT_UCHAR((PUCHAR)(0x40+channel), 
-                        (unsigned char) (temp>>8));
-}
-
-VOID STDCALL
-__KeStallExecutionProcessor(ULONG Loops)
-{
-   register unsigned int i;
-   for (i=0; i<Loops;i++);
-}
-
-VOID STDCALL KeStallExecutionProcessor(ULONG Microseconds)
-{
-   __KeStallExecutionProcessor((delay_count*Microseconds)/1000);
-}
-
-#define HZ (100)
-#define CLOCK_TICK_RATE (1193182)
-#define LATCH (CLOCK_TICK_RATE / HZ)
-
-static ULONG Read8254Timer(VOID)
-{
-       ULONG Count;
-
-       WRITE_PORT_UCHAR((PUCHAR)0x43, 0x00);
-       Count = READ_PORT_UCHAR((PUCHAR)0x40);
-       Count |= READ_PORT_UCHAR((PUCHAR)0x40) << 8;
-       return Count;
-}
-
-
-static VOID WaitFor8254Wraparound(VOID)
-{
-       ULONG CurCount, PrevCount = ~0;
-       LONG Delta;
-
-       CurCount = Read8254Timer();
-
-       do {
-               PrevCount = CurCount;
-               CurCount = Read8254Timer();
-               Delta = CurCount - PrevCount;
-
-       /*
-        * This limit for delta seems arbitrary, but it isn't, it's
-        * slightly above the level of error a buggy Mercury/Neptune
-        * chipset timer can cause.
-        */
-
-       } while (Delta < 300);
-}
-
-VOID HalpCalibrateStallExecution(VOID)
-{
-   ULONG i;
-   ULONG calib_bit;
-        ULONG CurCount;
-
-   if (UdelayCalibrated)
-      return;
-
-   UdelayCalibrated = TRUE;
-
-   DbgPrint("Calibrating delay loop... [");
-
-   /* Initialise timer interrupt with MILLISECOND ms interval        */
-   WRITE_PORT_UCHAR((PUCHAR)0x43, 0x34);  /* binary, mode 2, LSB/MSB, ch 0 */
-   WRITE_PORT_UCHAR((PUCHAR)0x40, LATCH & 0xff); /* LSB */
-   WRITE_PORT_UCHAR((PUCHAR)0x40, LATCH >> 8); /* MSB */
-
-   /* Stage 1:  Coarse calibration                                   */
-
-   WaitFor8254Wraparound();
-
-   delay_count = 1;
-
-   do {
-      delay_count <<= 1;                  /* Next delay count to try */
-
-      WaitFor8254Wraparound();
-
-      __KeStallExecutionProcessor(delay_count);      /* Do the delay */
-
-           CurCount = Read8254Timer();
-   } while (CurCount > LATCH / 2);
-
-   delay_count >>= 1;              /* Get bottom value for delay     */
-
-   /* Stage 2:  Fine calibration                                     */
-   DbgPrint("delay_count: %d", delay_count);
-
-   calib_bit = delay_count;        /* Which bit are we going to test */
-
-   for(i=0;i<PRECISION;i++) {
-      calib_bit >>= 1;             /* Next bit to calibrate          */
-      if(!calib_bit) break;        /* If we have done all bits, stop */
-
-      delay_count |= calib_bit;        /* Set the bit in delay_count */
-
-      WaitFor8254Wraparound();
-
-      __KeStallExecutionProcessor(delay_count);      /* Do the delay */
-
-      CurCount = Read8254Timer();
-      if (CurCount <= LATCH / 2)   /* If a tick has passed, turn the */
-        delay_count &= ~calib_bit; /* calibrated bit back off        */
-   }
-
-   /* We're finished:  Do the finishing touches                      */
-
-   delay_count /= (MILLISEC / 2);   /* Calculate delay_count for 1ms */
-
-   DbgPrint("]\n");
-   DbgPrint("delay_count: %d\n", delay_count);
-   DbgPrint("CPU speed: %d\n", delay_count/250);
-#if 0
-   DbgPrint("About to start delay loop test\n");
-   DbgPrint("Waiting for five minutes...");
-   for (i = 0; i < (5*60*1000*20); i++)
-     {
-       KeStallExecutionProcessor(50);
-     }
-   DbgPrint("finished\n");
-   for(;;);
-#endif
-}
-
-/* EOF */