Index: c/src/lib/libbsp/i386/pc386/ChangeLog
===================================================================
--- c/src/lib/libbsp/i386/pc386/ChangeLog	(revision 24b6d2f9a868e6f68aebb231f4177c84b4759319)
+++ c/src/lib/libbsp/i386/pc386/ChangeLog	(revision fb573a71f1fdec968446b1bb39856fa1ac958e24)
@@ -1,2 +1,13 @@
+2005-08-23  Karel Gardas  <kgardas@objectsecurity.com>>
+
+	* timer/timer.c: Enhance to use either interupt-based timer
+	functions on older CPUs or to use TSC-based timer functions on
+	more recent (Pentium and above) CPUs. The decision is made in
+	Timer_initialize function when it is called for the first time
+	based on a result obtained from cpuid instruction during the BSP
+	initialization phase. During the first call, there are also late
+	bindings to the implementation functions initialized to
+	appropriate values.
+
 2005-09-29	Thomas Doerfler <Thomas.Doerfler@imd-systems.de>
 
Index: c/src/lib/libbsp/i386/pc386/timer/timer.c
===================================================================
--- c/src/lib/libbsp/i386/pc386/timer/timer.c	(revision 24b6d2f9a868e6f68aebb231f4177c84b4759319)
+++ c/src/lib/libbsp/i386/pc386/timer/timer.c	(revision fb573a71f1fdec968446b1bb39856fa1ac958e24)
@@ -39,5 +39,4 @@
 +--------------------------------------------------------------------------*/
 
-
 #include <stdlib.h>
 
@@ -52,5 +51,5 @@
 #define SLOW_DOWN_IO  0x80     	/* io which does nothing */
 
-#define TWO_MS	(rtems_unsigned32)(2000)     /* TWO_MS = 2000us (sic!) */
+#define TWO_MS	(uint32_t)(2000)     /* TWO_MS = 2000us (sic!) */
 
 #define MSK_NULL_COUNT 0x40	/* bit counter available for reading */
@@ -60,7 +59,10 @@
 | Global Variables
 +--------------------------------------------------------------------------*/
-volatile rtems_unsigned32 Ttimer_val;
+volatile uint32_t         Ttimer_val;
 rtems_boolean    	  Timer_driver_Find_average_overhead = TRUE;
 volatile unsigned int     fastLoop1ms, slowLoop1ms;
+void (*Timer_initialize_function)(void) = 0;
+uint32_t (*Read_timer_function)(void) = 0;
+void (*Timer_exit_function)(void) = 0;
 
 /*-------------------------------------------------------------------------+
@@ -69,9 +71,15 @@
 extern void timerisr(void);
        /* timer (int 08h) Interrupt Service Routine (defined in 'timerisr.s') */
+extern int x86_capability;
+
+/*
+ * forward declarations
+ */
+
+void Timer_exit();
 
 /*-------------------------------------------------------------------------+
 | Pentium optimized timer handling.
 +--------------------------------------------------------------------------*/
-#if defined(pentium)
 
 /*-------------------------------------------------------------------------+
@@ -80,5 +88,5 @@
 | Global Variables: None.
 |        Arguments: None.
-|          Returns: Value of PENTIUM on-chip cycle counter. 
+|          Returns: Value of PENTIUM on-chip cycle counter.
 +--------------------------------------------------------------------------*/
 static inline unsigned long long
@@ -91,5 +99,4 @@
 } /* rdtsc */
 
-
 /*-------------------------------------------------------------------------+
 |         Function: Timer_exit
@@ -98,11 +105,10 @@
 | Global Variables: None.
 |        Arguments: None.
-|          Returns: Nothing. 
-+--------------------------------------------------------------------------*/
-void
-Timer_exit(void)
-{
-} /* Timer_exit */
-
+|          Returns: Nothing.
++--------------------------------------------------------------------------*/
+void
+tsc_timer_exit(void)
+{
+} /* tsc_timer_exit */
 
 /*-------------------------------------------------------------------------+
@@ -111,8 +117,8 @@
 | Global Variables: Ttimer_val.
 |        Arguments: None.
-|          Returns: Nothing. 
-+--------------------------------------------------------------------------*/
-void
-Timer_initialize(void)
+|          Returns: Nothing.
++--------------------------------------------------------------------------*/
+void
+tsc_timer_initialize(void)
 {
   static rtems_boolean First = TRUE;
@@ -125,6 +131,5 @@
   }
   Ttimer_val = rdtsc(); /* read starting time */
-} /* Timer_initialize */
-
+} /* tsc_timer_initialize */
 
 /*-------------------------------------------------------------------------+
@@ -133,12 +138,12 @@
 | Global Variables: Ttimer_val, Timer_driver_Find_average_overhead.
 |        Arguments: None.
-|          Returns: Nothing. 
-+--------------------------------------------------------------------------*/
-rtems_unsigned32
-Read_timer(void)
-{
-  register rtems_unsigned32 total;
-
-  total =  (rtems_unsigned32)(rdtsc() - Ttimer_val);
+|          Returns: Nothing.
++--------------------------------------------------------------------------*/
+uint32_t
+tsc_read_timer(void)
+{
+  register uint32_t         total;
+
+  total =  (uint32_t)(rdtsc() - Ttimer_val);
 
   if (Timer_driver_Find_average_overhead)
@@ -148,7 +153,5 @@
   else
     return (total - AVG_OVERHEAD);
-} /* Read_timer */
-
-#else /* pentium */
+} /* tsc_read_timer */
 
 /*-------------------------------------------------------------------------+
@@ -156,5 +159,4 @@
 +--------------------------------------------------------------------------*/
 #define US_PER_ISR   250  /* Number of micro-seconds per timer interruption */
-
 
 /*-------------------------------------------------------------------------+
@@ -164,5 +166,5 @@
 | Global Variables: None.
 |        Arguments: None.
-|          Returns: Nothing. 
+|          Returns: Nothing.
 +--------------------------------------------------------------------------*/
 static void
@@ -179,6 +181,5 @@
 } /* Timer_exit */
 
-
-static void 
+static void
 timerOn(const rtems_raw_irq_connect_data* used)
 {
@@ -193,8 +194,9 @@
 }
 
-static int 
+static int
 timerIsOn(const rtems_raw_irq_connect_data *used)
 {
-     return BSP_irq_enabled_at_i8259s(used->idtIndex - BSP_IRQ_VECTOR_BASE);}
+     return BSP_irq_enabled_at_i8259s(used->idtIndex - BSP_IRQ_VECTOR_BASE);
+}
 
 static rtems_raw_irq_connect_data timer_raw_irq_data = {
@@ -212,8 +214,8 @@
 | Global Variables: None.
 |        Arguments: None.
-|          Returns: Nothing. 
-+--------------------------------------------------------------------------*/
-void
-Timer_exit(void)
+|          Returns: Nothing.
++--------------------------------------------------------------------------*/
+void
+i386_timer_exit(void)
 {
   i386_delete_idt_entry (&timer_raw_irq_data);
@@ -225,8 +227,8 @@
 | Global Variables: Ttimer_val.
 |        Arguments: None.
-|          Returns: Nothing. 
-+--------------------------------------------------------------------------*/
-void
-Timer_initialize(void)
+|          Returns: Nothing.
++--------------------------------------------------------------------------*/
+void
+i386_timer_initialize(void)
 {
   static rtems_boolean First = TRUE;
@@ -249,5 +251,4 @@
 } /* Timer_initialize */
 
-
 /*-------------------------------------------------------------------------+
 |         Function: Read_timer
@@ -255,11 +256,11 @@
 | Global Variables: Ttimer_val, Timer_driver_Find_average_overhead.
 |        Arguments: None.
-|          Returns: Nothing. 
-+--------------------------------------------------------------------------*/
-rtems_unsigned32
-Read_timer(void)
-{
-  register rtems_unsigned32 total, clicks;
-  register rtems_unsigned8  lsb, msb;
+|          Returns: Nothing.
++--------------------------------------------------------------------------*/
+uint32_t
+i386_read_timer(void)
+{
+  register uint32_t         total, clicks;
+  register uint8_t          lsb, msb;
 
   outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_LATCH);
@@ -277,6 +278,47 @@
 }
 
-#endif /* pentium */
-
+/*
+ * General timer functions using either TSC-based implementation
+ * or interrupt-based implementation
+ */
+
+void
+Timer_initialize(void)
+{
+    static rtems_boolean First = TRUE;
+
+    if (First) {
+        if (x86_capability & (1 << 4) ) {
+#if defined(DEBUG)
+            printk("TSC: timer initialization\n");
+#endif
+            Timer_initialize_function = &tsc_timer_initialize;
+            Read_timer_function = &tsc_read_timer;
+            Timer_exit_function = &tsc_timer_exit;
+        }
+        else {
+#if defined(DEBUG)
+            printk("ISR: timer initialization\n");
+#endif
+            Timer_initialize_function = &i386_timer_initialize;
+            Read_timer_function = &i386_read_timer;
+            Timer_exit_function = &i386_timer_exit;
+        }
+        First = FALSE;
+    }
+    (*Timer_initialize_function)();
+}
+
+uint32_t
+Read_timer()
+{
+    return (*Read_timer_function)();
+}
+
+void
+Timer_exit()
+{
+    return (*Timer_exit_function)();
+}
 
 /*-------------------------------------------------------------------------+
@@ -285,5 +327,5 @@
 | Global Variables: None.
 |        Arguments: None.
-|          Returns: Nothing. 
+|          Returns: Nothing.
 +--------------------------------------------------------------------------*/
 rtems_status_code Empty_function(void)
@@ -291,5 +333,4 @@
   return RTEMS_SUCCESSFUL;
 } /* Empty function */
- 
 
 /*-------------------------------------------------------------------------+
@@ -298,5 +339,5 @@
 | Global Variables: Timer_driver_Find_average_overhead.
 |        Arguments: find_flag - new value of the flag.
-|          Returns: Nothing. 
+|          Returns: Nothing.
 +--------------------------------------------------------------------------*/
 void
@@ -320,9 +361,8 @@
 }
 
-
-/*-------------------------------------------------------------------------+
-| Description: Reads the current value of the timer, and converts the 
-|			   number of ticks to micro-seconds.	
-| Returns: number of clock bits elapsed since last load. 
+/*-------------------------------------------------------------------------+
+| Description: Reads the current value of the timer, and converts the
+|			   number of ticks to micro-seconds.
+| Returns: number of clock bits elapsed since last load.
 +--------------------------------------------------------------------------*/
 unsigned int readTimer0()
@@ -339,5 +379,5 @@
   if (status & RB_OUTPUT )
   	count += lastLoadedValue;
-  
+
   return (2*lastLoadedValue - count);
 }
@@ -373,10 +413,10 @@
   unsigned int slowLoopGranularity, fastLoopGranularity;
   rtems_interrupt_level  level;
-  
+
 #ifdef DEBUG_CALIBRATE
   printk( "Calibrate_loop_1ms is starting,  please wait ( but not too loooong. )\n" );
-#endif  
+#endif
   targetClockBits = US_TO_TICK(1000);
-  
+
   rtems_interrupt_disable(level);
   /*
@@ -385,5 +425,5 @@
   Timer0Reset();
   readTimer0();
-  /* 
+  /*
    * Compute the minimal offset to apply due to read counter register.
    */
@@ -438,5 +478,5 @@
   }
   slowLoopGranularity = (res - offset - emptyCall)/ 10;
-  
+
   if (slowLoopGranularity == 0) {
     printk("Problem #3 in Calibrate_loop_1ms in file libbsp/i386/pc386/timer/timer.c\n");
@@ -445,15 +485,15 @@
 
   targetClockBits += offset;
-#ifdef DEBUG_CALIBRATE  
+#ifdef DEBUG_CALIBRATE
   printk("offset = %u, emptyCall = %u, targetClockBits = %u\n",
 	 offset, emptyCall, targetClockBits);
   printk("slowLoopGranularity = %u fastLoopGranularity =  %u\n",
 	 slowLoopGranularity, fastLoopGranularity);
-#endif  
+#endif
   slowLoop1ms = (targetClockBits - emptyCall) / slowLoopGranularity;
   if (slowLoop1ms != 0) {
     fastLoop1ms = targetClockBits % slowLoopGranularity;
     if (fastLoop1ms > emptyCall) fastLoop1ms -= emptyCall;
-  }    
+  }
   else
     fastLoop1ms = targetClockBits - emptyCall / fastLoopGranularity;
@@ -463,5 +503,5 @@
      * calibrate slow loop
      */
-  
+
     while(1)
       {
@@ -498,5 +538,5 @@
    * calibrate fast loop
    */
-  
+
   if (fastLoopGranularity != 0 ) {
     while(1) {
@@ -526,9 +566,9 @@
     }
   }
-#ifdef DEBUG_CALIBRATE  
+#ifdef DEBUG_CALIBRATE
   printk("slowLoop1ms = %u, fastLoop1ms = %u\n", slowLoop1ms, fastLoop1ms);
-#endif  
+#endif
   rtems_interrupt_enable(level);
-  
+
 }
 
@@ -538,5 +578,5 @@
 | Global Variables: loop1ms
 |        Arguments: timeToWait
-|          Returns: Nothing. 
+|          Returns: Nothing.
 +--------------------------------------------------------------------------*/
 void
@@ -551,8 +591,2 @@
 
 }
-
-
-
-
-
-
