diff options
Diffstat (limited to 'c/src/lib/libbsp/i386/go32/clock/ckinit.c')
-rw-r--r-- | c/src/lib/libbsp/i386/go32/clock/ckinit.c | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/i386/go32/clock/ckinit.c b/c/src/lib/libbsp/i386/go32/clock/ckinit.c new file mode 100644 index 0000000000..5ac1c10d98 --- /dev/null +++ b/c/src/lib/libbsp/i386/go32/clock/ckinit.c @@ -0,0 +1,135 @@ +/* Clock_initialize + * + * This routine initializes the 8254 timer under GO32. + * The tick frequency is 1 millisecond. + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * $Id$ + */ + +#include <bsp.h> +#include <clockdrv.h> +#include <stdlib.h> + +volatile rtems_unsigned32 Clock_driver_ticks; +rtems_unsigned32 Clock_isrs_per_tick; /* ISRs per tick */ +rtems_unsigned32 Clock_isrs; /* ISRs until next tick */ +rtems_isr_entry Old_ticker; + +rtems_device_driver Clock_initialize( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *pargp, + rtems_id tid, + rtems_unsigned32 *rval +) +{ + Install_clock( Clock_isr ); +} + +void ReInstall_clock( + rtems_isr_entry clock_isr +) +{ + rtems_unsigned32 isrlevel = 0; + + rtems_interrupt_disable( isrlevel ); + (void) set_vector( clock_isr, 0x8, 1 ); + rtems_interrupt_enable( isrlevel ); +} + +void Install_clock( + rtems_isr_entry clock_isr +) +{ + unsigned int microseconds_per_isr; + +#if 0 + /* Initialize clock from on-board real time clock. This breaks the */ + /* test code which assumes which assumes the application will do it. */ + { + rtems_time_of_day Now; + extern void init_rtc( void ); + extern long rtc_read( rtems_time_of_day * tod ); + init_rtc(); + if ( rtc_read( &Now ) >= 0 ) + clock_set( &Now ); + } +#endif + + /* Start by assuming hardware counter is large enough, then */ + /* scale it until it actually fits. */ + Clock_driver_ticks = 0; + Clock_isrs_per_tick = 1; + + if ( BSP_Configuration.microseconds_per_tick == 0 ) + microseconds_per_isr = 10000; /* default 10 ms */ + else + microseconds_per_isr = BSP_Configuration.microseconds_per_tick; + while ( US_TO_TICK(microseconds_per_isr) > 65535 ) { + Clock_isrs_per_tick *= 10; + microseconds_per_isr /= 10; + } + + /* Initialize count in ckisr.c */ + Clock_isrs = Clock_isrs_per_tick; + +#if 0 + /* This was dropped in the last revision. Its a nice thing to know. */ + TICKS_PER_SECOND = 1000000 / (Clock_isrs_per_tick * microseconds_per_isr); +#endif + + if ( BSP_Configuration.ticks_per_timeslice ) { + /* 105/88 approximates TIMER_TICK*1e-6 */ + unsigned int count = US_TO_TICK( microseconds_per_isr ); + + Old_ticker = (rtems_isr_entry) set_vector( clock_isr, 0x8, 1 ); + outport_byte( TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN ); + outport_byte( TIMER_CNTR0, count >> 0 & 0xff ); + outport_byte( TIMER_CNTR0, count >> 8 & 0xff ); + } + atexit( Clock_exit ); +} + +void Clock_exit( void ) +{ + if ( BSP_Configuration.ticks_per_timeslice ) { + 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, 1 ); + } +} + + +#if 0 && defined(pentium) +/* This can be used to get extremely accurate timing on a pentium. */ +/* It isn't supported. [bryce] */ +#define HZ 90.0 +volatile long long Last_RDTSC; +#define RDTSC()\ + ({ long long _now; __asm __volatile (".byte 0x0F,0x31":"=A"(_now)); _now; }) +long long Kernel_Time_ns( void ) +{ + extern rtems_unsigned32 _TOD_Ticks_per_second; + unsigned isrs_per_second = Clock_isrs_per_tick * _TOD_Ticks_per_second; + long long now; + int flags; + disable_intr( flags ); + now = 1e9 * Clock_driver_ticks / isrs_per_second + + (RDTSC() - Last_RDTSC) * (1000.0/HZ); + enable_intr( flags ); + return now; +} +#endif |