summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/i386/pc386/timer/timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libbsp/i386/pc386/timer/timer.c')
-rw-r--r--c/src/lib/libbsp/i386/pc386/timer/timer.c256
1 files changed, 256 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/i386/pc386/timer/timer.c b/c/src/lib/libbsp/i386/pc386/timer/timer.c
new file mode 100644
index 0000000000..0cbca572e8
--- /dev/null
+++ b/c/src/lib/libbsp/i386/pc386/timer/timer.c
@@ -0,0 +1,256 @@
+/*-------------------------------------------------------------------------+
+| timer.c v1.1 - PC386 BSP - 1997/08/07
++--------------------------------------------------------------------------+
+| This file contains the PC386 timer package.
++--------------------------------------------------------------------------+
+| NOTE: It is important that the timer start/stop overhead be determined
+| when porting or modifying this code.
++--------------------------------------------------------------------------+
+| (C) Copyright 1997 -
+| - NavIST Group - Real-Time Distributed Systems and Industrial Automation
+|
+| http://pandora.ist.utl.pt
+|
+| Instituto Superior Tecnico * Lisboa * PORTUGAL
++--------------------------------------------------------------------------+
+| Disclaimer:
+|
+| This file is provided "AS IS" without warranty of any kind, either
+| expressed or implied.
++--------------------------------------------------------------------------+
+| This code is base on:
+| timer.c,v 1.7 1995/12/19 20:07:43 joel Exp - go32 BSP
+| With the following copyright notice:
+| **************************************************************************
+| * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. *
+| * On-Line Applications Research Corporation (OAR). *
+| * All rights assigned to U.S. Government, 1994. *
+| * *
+| * This material may be reproduced by or for the U.S. Government pursuant *
+| * to the copyright license under the clause at DFARS 252.227-7013. This *
+| * notice must appear in all copies of this file and its derivatives. *
+| **************************************************************************
++--------------------------------------------------------------------------*/
+
+
+#include <stdlib.h>
+
+#include <bsp.h>
+#include <irq.h>
+
+/*-------------------------------------------------------------------------+
+| Constants
++--------------------------------------------------------------------------*/
+#define TIMER_IRQ 0x00 /* Timer IRQ. */
+#define AVG_OVERHEAD 0 /* 0.1 microseconds to start/stop timer. */
+#define LEAST_VALID 1 /* Don't trust a value lower than this. */
+
+/*-------------------------------------------------------------------------+
+| Global Variables
++--------------------------------------------------------------------------*/
+volatile rtems_unsigned32 Ttimer_val;
+ rtems_boolean Timer_driver_Find_average_overhead = TRUE;
+
+/*-------------------------------------------------------------------------+
+| Pentium optimized timer handling.
++--------------------------------------------------------------------------*/
+#if defined(pentium)
+
+/*-------------------------------------------------------------------------+
+| Function: rdtsc
+| Description: Read the value of PENTIUM on-chip cycle counter.
+| Global Variables: None.
+| Arguments: None.
+| Returns: Value of PENTIUM on-chip cycle counter.
++--------------------------------------------------------------------------*/
+static inline unsigned long long
+rdtsc(void)
+{
+ /* Return the value of the on-chip cycle counter. */
+ unsigned long long result;
+ asm volatile(".byte 0x0F, 0x31" : "=A" (result));
+ return result;
+} /* rdtsc */
+
+
+/*-------------------------------------------------------------------------+
+| Function: Timer_exit
+| Description: Timer cleanup routine at RTEMS exit. NOTE: This routine is
+| not really necessary, since there will be a reset at exit.
+| Global Variables: None.
+| Arguments: None.
+| Returns: Nothing.
++--------------------------------------------------------------------------*/
+void
+Timer_exit(void)
+{
+ PC386_disableIrq(TIMER_IRQ);
+} /* Timer_exit */
+
+
+/*-------------------------------------------------------------------------+
+| Function: Timer_initialize
+| Description: Timer initialization routine.
+| Global Variables: Ttimer_val.
+| Arguments: None.
+| Returns: Nothing.
++--------------------------------------------------------------------------*/
+void
+Timer_initialize(void)
+{
+ static rtems_boolean First = TRUE;
+
+ if (First)
+ {
+ First = FALSE;
+
+ atexit(Timer_exit); /* Try not to hose the system at exit. */
+ PC386_enableIrq(TIMER_IRQ);
+ /* Disable the programmable timer so ticks don't interfere. */
+ }
+ Ttimer_val = rdtsc(); /* read starting time */
+} /* Timer_initialize */
+
+
+/*-------------------------------------------------------------------------+
+| Function: Read_timer
+| Description: Read hardware timer value.
+| 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);
+
+ if (Timer_driver_Find_average_overhead)
+ return total;
+ else if (total < LEAST_VALID)
+ return 0; /* below timer resolution */
+ else
+ return (total - AVG_OVERHEAD);
+} /* Read_timer */
+
+#else /* pentium */
+
+/*-------------------------------------------------------------------------+
+| Non-Pentium timer handling.
++--------------------------------------------------------------------------*/
+#define US_PER_ISR 250 /* Number of micro-seconds per timer interruption */
+
+/*-------------------------------------------------------------------------+
+| External Prototypes
++--------------------------------------------------------------------------*/
+extern rtems_isr timerisr(rtems_vector_number);
+ /* timer (int 08h) Interrupt Service Routine (defined in 'timerisr.s') */
+
+/*-------------------------------------------------------------------------+
+| Function: Timer_exit
+| Description: Timer cleanup routine at RTEMS exit. NOTE: This routine is
+| not really necessary, since there will be a reset at exit.
+| Global Variables: None.
+| Arguments: None.
+| Returns: Nothing.
++--------------------------------------------------------------------------*/
+void
+Timer_exit(void)
+{
+ /* reset timer mode to standard (DOS) value */
+ outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
+ outport_byte(TIMER_CNTR0, 0);
+ outport_byte(TIMER_CNTR0, 0);
+} /* Timer_exit */
+
+
+/*-------------------------------------------------------------------------+
+| Function: Timer_initialize
+| Description: Timer initialization routine.
+| Global Variables: Ttimer_val.
+| Arguments: None.
+| Returns: Nothing.
++--------------------------------------------------------------------------*/
+void
+Timer_initialize(void)
+{
+ static rtems_boolean First = TRUE;
+
+ if (First)
+ {
+ First = FALSE;
+
+ atexit(Timer_exit); /* Try not to hose the system at exit. */
+
+ /* install a raw interrupt handler for timer */
+ PC386_installRawIrqHandler(TIMER_IRQ, timerisr);
+
+ /* load timer for US_PER_ISR microsecond period */
+ outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
+ outport_byte(TIMER_CNTR0, US_TO_TICK(US_PER_ISR) >> 0 & 0xff);
+ outport_byte(TIMER_CNTR0, US_TO_TICK(US_PER_ISR) >> 8 & 0xff);
+ }
+ /* wait for ISR to be called at least once */
+ Ttimer_val = 0;
+ while (Ttimer_val == 0)
+ continue;
+ Ttimer_val = 0;
+} /* Timer_initialize */
+
+
+/*-------------------------------------------------------------------------+
+| Function: Read_timer
+| Description: Read hardware timer value.
+| 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;
+
+ outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_LATCH);
+ inport_byte(TIMER_CNTR0, lsb);
+ inport_byte(TIMER_CNTR0, msb);
+ clicks = (msb << 8) | lsb;
+ total = (Ttimer_val * US_PER_ISR) + (US_PER_ISR - TICK_TO_US(clicks));
+
+ if (Timer_driver_Find_average_overhead)
+ return total;
+ else if (total < LEAST_VALID)
+ return 0; /* below timer resolution */
+ else
+ return (total - AVG_OVERHEAD);
+}
+
+#endif /* pentium */
+
+
+/*-------------------------------------------------------------------------+
+| Function: Empty_function
+| Description: Empty function used in time tests.
+| Global Variables: None.
+| Arguments: None.
+| Returns: Nothing.
++--------------------------------------------------------------------------*/
+rtems_status_code Empty_function(void)
+{
+ return RTEMS_SUCCESSFUL;
+} /* Empty function */
+
+
+/*-------------------------------------------------------------------------+
+| Function: Set_find_average_overhead
+| Description: Set internal Timer_driver_Find_average_overhead flag value.
+| Global Variables: Timer_driver_Find_average_overhead.
+| Arguments: find_flag - new value of the flag.
+| Returns: Nothing.
++--------------------------------------------------------------------------*/
+void
+Set_find_average_overhead(rtems_boolean find_flag)
+{
+ Timer_driver_Find_average_overhead = find_flag;
+} /* Set_find_average_overhead */