summaryrefslogblamecommitdiffstats
path: root/c/src/lib/libbsp/i386/go32/clock/ckinit.c
blob: 5ac1c10d98c7af3346433a5b16774d03e165f963 (plain) (tree)






































































































































                                                                              
/*  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