diff options
Diffstat (limited to 'c/src/lib/libbsp/i386/go32/timer/timer.c')
-rw-r--r-- | c/src/lib/libbsp/i386/go32/timer/timer.c | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/i386/go32/timer/timer.c b/c/src/lib/libbsp/i386/go32/timer/timer.c new file mode 100644 index 0000000000..252c1a771f --- /dev/null +++ b/c/src/lib/libbsp/i386/go32/timer/timer.c @@ -0,0 +1,144 @@ +/* Timer_init() + * + * This routine initializes the timer on the IBM 386. + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * NOTE: It is important that the timer start/stop overhead be + * determined when porting or modifying this code. + * + * COPYRIGHT (c) 1989-1997. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may in + * the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <rtems.h> +#include <bsp.h> + +volatile rtems_unsigned32 Ttimer_val; +rtems_boolean Timer_driver_Find_average_overhead; + +#if defined(pentium) +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; +} +#else +#define US_PER_ISR 250 +extern rtems_isr timerisr(); +static rtems_isr_entry Old_Ticker; +#endif + +static void Timer_exit( void ) +{ +#if defined(pentium) + CLOCK_ENABLE(); +#else /* pentium */ + extern void rtc_set_dos_date( void ); + + /* reset to DOS value: */ + outport_byte( TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN ); + outport_byte( TIMER_CNTR0, 0 ); + outport_byte( TIMER_CNTR0, 0 ); + + /* reset time-of-day */ + rtc_set_dos_date(); + + /* re-enable old handler: assume it was one of ours */ + set_vector( (rtems_isr_entry)Old_Ticker, 0x8, 0 ); +#endif /* pentium */ +} + +void Timer_initialize() +{ + extern int atexit( void (*)(void) ); + + static int First = 1; + + if ( First ) { + First = 0; + + /* Try not to hose the system on return to DOS. */ + atexit( Timer_exit ); + +#if defined(pentium) + /* Disable the programmable timer so ticks don't interfere. */ + CLOCK_DISABLE(); +#else /* pentium */ + /* install a timer ISR */ + Old_Ticker = (rtems_isr_entry) set_vector( timerisr, 0x8, 0 ); + + /* Wait for ISR to be called at least once */ + Ttimer_val = 0; + while ( Ttimer_val == 0 ) + continue; + + /* 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 ); +#endif /* PENTIUM */ + } +#if defined(pentium) + Ttimer_val = rdtsc(); /* read starting time */ +#else + /* Wait for ISR to be called at least once */ + asm( "sti" ); + Ttimer_val = 0; + while ( Ttimer_val == 0 ) + continue; + Ttimer_val = 0; +#endif +} + +#define AVG_OVERHEAD 0 /* 0.1 microseconds to start/stop timer. */ +#define LEAST_VALID 1 /* Don't trust a value lower than this */ + + +int Read_timer() +{ + register rtems_unsigned32 total; +#if defined(pentium) + total = rdtsc() - Ttimer_val; +#else /* pentium */ + register rtems_unsigned8 lsb, msb; + register rtems_unsigned32 clicks; + 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 )); +#endif /* pentium */ + + if ( Timer_driver_Find_average_overhead == 1 ) + return total; + else if ( total < LEAST_VALID ) + return 0; /* below timer resolution */ + else + return total - AVG_OVERHEAD; +} + +rtems_status_code Empty_function( void ) +{ + return RTEMS_SUCCESSFUL; +} + + +void Set_find_average_overhead( + rtems_boolean find_flag +) +{ + Timer_driver_Find_average_overhead = find_flag; +} + |