source: rtems/c/src/lib/libbsp/i386/go32/clock/ckinit.c @ 9700578

4.104.114.84.95
Last change on this file since 9700578 was 9700578, checked in by Joel Sherrill <joel.sherrill@…>, on Oct 30, 1995 at 9:54:45 PM

SPARC port passes all tests

  • Property mode set to 100644
File size: 4.9 KB
Line 
1/*  Clock_initialize
2 *
3 *  This routine initializes the 8254 timer under GO32.
4 *  The tick frequency is 1 millisecond.
5 *
6 *  Input parameters:  NONE
7 *
8 *  Output parameters:  NONE
9 *
10 *  $Id$
11 */
12
13#include <bsp.h>
14#include <rtems/libio.h>
15
16#include <stdlib.h>
17
18volatile rtems_unsigned32 Clock_driver_ticks;
19rtems_unsigned32 Clock_isrs_per_tick;  /* ISRs per tick */
20rtems_unsigned32 Clock_isrs;   /* ISRs until next tick */
21rtems_isr_entry  Old_ticker;
22
23#define CLOCK_VECTOR 0x8
24
25void Clock_exit( void );
26
27/*
28 * These are set by clock driver during its init
29 */
30 
31rtems_device_major_number rtems_clock_major = ~0;
32rtems_device_minor_number rtems_clock_minor;
33
34rtems_isr Clock_isr(
35  rtems_vector_number vector
36)
37{
38    /* touch interrupt controller for irq0 (0x20+0) */
39    outport_byte( 0x20, 0x20 );
40
41    Clock_driver_ticks += 1;
42
43#if 0 && defined(pentium)
44    {
45      extern long long Last_RDTSC;
46      __asm __volatile( ".byte 0x0F, 0x31" : "=A" (Last_RDTSC) );
47    }
48#endif
49
50    if ( Clock_isrs == 1 ) {
51      rtems_clock_tick();
52      Clock_isrs = Clock_isrs_per_tick;
53    } else {
54      Clock_isrs -= 1;
55    }
56}
57
58void Install_clock(
59  rtems_isr_entry clock_isr
60)
61{
62    unsigned int microseconds_per_isr;
63
64#if 0
65    /* Initialize clock from on-board real time clock.  This breaks the */
66    /* test code which assumes which assumes the application will do it. */
67    {
68       rtems_time_of_day Now;
69       extern void init_rtc( void );
70       extern long rtc_read( rtems_time_of_day * tod );
71       init_rtc();
72       if ( rtc_read( &Now ) >= 0 )
73         clock_set( &Now );
74       }
75#endif
76
77    /* Start by assuming hardware counter is large enough, then */
78    /* scale it until it actually fits.    */
79    Clock_driver_ticks = 0;
80    Clock_isrs_per_tick = 1;
81
82    if ( BSP_Configuration.microseconds_per_tick == 0 )
83       microseconds_per_isr = 10000; /* default 10 ms */
84    else
85       microseconds_per_isr = BSP_Configuration.microseconds_per_tick;
86    while ( US_TO_TICK(microseconds_per_isr) > 65535 )  {
87      Clock_isrs_per_tick  *= 10;
88      microseconds_per_isr /= 10;
89    }
90
91    /* Initialize count in ckisr.c */
92    Clock_isrs = Clock_isrs_per_tick;
93
94#if 0
95    /* This was dropped in the last revision.  Its a nice thing to know. */
96    TICKS_PER_SECOND = 1000000 / (Clock_isrs_per_tick * microseconds_per_isr);
97#endif
98
99    if ( BSP_Configuration.ticks_per_timeslice )  {
100      /* 105/88 approximates TIMER_TICK*1e-6 */
101      unsigned int count = US_TO_TICK( microseconds_per_isr );
102
103      Old_ticker = (rtems_isr_entry) set_vector( clock_isr, CLOCK_VECTOR, 1 );
104      outport_byte( TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN );
105      outport_byte( TIMER_CNTR0, count >> 0 & 0xff );
106      outport_byte( TIMER_CNTR0, count >> 8 & 0xff );
107    } 
108    atexit( Clock_exit );
109}
110
111void Clock_exit( void )
112{
113  if ( BSP_Configuration.ticks_per_timeslice ) {
114 extern void rtc_set_dos_date( void );
115
116 /* reset to DOS value: */
117 outport_byte( TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN );
118 outport_byte( TIMER_CNTR0, 0 );
119 outport_byte( TIMER_CNTR0, 0 );
120
121 /* reset time-of-day */
122 rtc_set_dos_date();
123 
124 /* re-enable old handler: assume it was one of ours */
125 set_vector( (rtems_isr_entry)Old_ticker, CLOCK_VECTOR, 1 );
126  }
127}
128
129rtems_device_driver Clock_initialize(
130  rtems_device_major_number major,
131  rtems_device_minor_number minor,
132  void *pargp
133)
134{
135  Install_clock( Clock_isr );
136 
137  /*
138   * make major/minor avail to others such as shared memory driver
139   */
140 
141  rtems_clock_major = major;
142  rtems_clock_minor = minor;
143 
144  return RTEMS_SUCCESSFUL;
145}
146 
147rtems_device_driver Clock_control(
148  rtems_device_major_number major,
149  rtems_device_minor_number minor,
150  void *pargp
151)
152{
153    rtems_unsigned32 isrlevel;
154    rtems_libio_ioctl_args_t *args = pargp;
155 
156    if (args == 0)
157        goto done;
158 
159    /*
160     * This is hokey, but until we get a defined interface
161     * to do this, it will just be this simple...
162     */
163 
164    if (args->command == rtems_build_name('I', 'S', 'R', ' '))
165    {
166        Clock_isr(CLOCK_VECTOR);
167    }
168    else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
169    {
170      rtems_interrupt_disable( isrlevel );
171       (void) set_vector( args->buffer, CLOCK_VECTOR, 1 );
172      rtems_interrupt_enable( isrlevel );
173    }
174 
175done:
176    return RTEMS_SUCCESSFUL;
177}
178
179#if 0 && defined(pentium)
180/* This can be used to get extremely accurate timing on a pentium. */
181/* It isn't supported. [bryce]      */
182#define HZ 90.0
183volatile long long Last_RDTSC;
184#define RDTSC()\
185  ({ long long _now; __asm __volatile (".byte 0x0F,0x31":"=A"(_now)); _now; })
186
187long long Kernel_Time_ns( void )
188{
189    extern rtems_unsigned32 _TOD_Ticks_per_second;
190    unsigned isrs_per_second = Clock_isrs_per_tick * _TOD_Ticks_per_second;
191    long long now;
192    int flags;
193    disable_intr( flags );
194    now = 1e9 * Clock_driver_ticks / isrs_per_second
195       + (RDTSC() - Last_RDTSC) * (1000.0/HZ);
196    enable_intr( flags );
197    return now;
198}
199#endif
Note: See TracBrowser for help on using the repository browser.