source: rtems/c/src/lib/libbsp/i386/pc386/clock/ckinit.c @ 0dd1d44

4.104.114.84.95
Last change on this file since 0dd1d44 was 0dd1d44, checked in by Joel Sherrill <joel.sherrill@…>, on Jan 11, 2000 at 5:34:20 PM

Removed old hack of using Configuration Table entry ticks_per_timeslice
being set to 0 to indicate that there should be no Clock Tick. This
was used by the Timing Tests to avoid clock tick overhead perturbing
execution times. Now the Timing Tests simply leave the Clock Tick
Driver out of the Device Driver Table.

  • Property mode set to 100644
File size: 9.2 KB
Line 
1/*-------------------------------------------------------------------------+
2| ckinit.c v1.1 - PC386 BSP - 1997/08/07
3+--------------------------------------------------------------------------+
4| This file contains the PC386 clock package.
5+--------------------------------------------------------------------------+
6| (C) Copyright 1997 -
7| - NavIST Group - Real-Time Distributed Systems and Industrial Automation
8|
9| http://pandora.ist.utl.pt
10|
11| Instituto Superior Tecnico * Lisboa * PORTUGAL
12+--------------------------------------------------------------------------+
13| Disclaimer:
14|
15| This file is provided "AS IS" without warranty of any kind, either
16| expressed or implied.
17+--------------------------------------------------------------------------+
18| This code is based on:
19|   ckinit.c,v 1.4 1995/12/19 20:07:13 joel Exp - go32 BSP
20| With the following copyright notice:
21| **************************************************************************
22| *  COPYRIGHT (c) 1989-1999.
23| *  On-Line Applications Research Corporation (OAR).
24| *
25| *  The license and distribution terms for this file may be
26| *  found in found in the file LICENSE in this distribution or at
27| *  http://www.OARcorp.com/rtems/license.html.
28| **************************************************************************
29|
30|  $Id$
31+--------------------------------------------------------------------------*/
32
33
34#include <stdlib.h>
35
36#include <bsp.h>
37#include <irq.h>
38#include <rtems/libio.h>
39
40/*-------------------------------------------------------------------------+
41| Macros
42+--------------------------------------------------------------------------*/
43#if 0
44/* This was dropped in the last revision.  Its a nice thing to know. */
45#define TICKS_PER_SECOND() \
46          (1000000 / (Clock_isrs_per_tick * microseconds_per_isr))
47#endif /* 0 */
48
49/*-------------------------------------------------------------------------+
50| Global Variables
51+--------------------------------------------------------------------------*/
52
53volatile rtems_unsigned32 Clock_driver_ticks;   /* Tick (interrupt) counter. */
54         rtems_unsigned32 Clock_isrs_per_tick;  /* ISRs per tick.            */
55         rtems_unsigned32 Clock_isrs;           /* ISRs until next tick.     */
56
57/* The following variables are set by the clock driver during its init */
58
59rtems_device_major_number rtems_clock_major = ~0;
60rtems_device_minor_number rtems_clock_minor;
61
62/*-------------------------------------------------------------------------+
63|         Function: clockIsr
64|      Description: Interrupt Service Routine for clock (0h) interruption.
65| Global Variables: Clock_driver_ticks, Clock_isrs.
66|        Arguments: vector - standard RTEMS argument - see documentation.
67|          Returns: standard return value - see documentation.
68+--------------------------------------------------------------------------*/
69static void clockIsr()
70{
71  /*-------------------------------------------------------------------------+
72  | PLEASE NOTE: The following is directly transcribed from the go32 BSP for
73  |              those who wish to use it with PENTIUM based machine. It needs
74  |              to be correctly integrated with the rest of the code!!!
75  +--------------------------------------------------------------------------*/
76
77#if 0 && defined(pentium) /* more accurate clock for PENTIUMs (not supported) */
78  {
79    extern long long Last_RDTSC;
80    __asm __volatile(".byte 0x0F, 0x31" : "=A" (Last_RDTSC));
81  }
82#endif /* 0 && pentium */
83
84  Clock_driver_ticks++;
85
86  if ( Clock_isrs == 1 )
87  {
88    rtems_clock_tick();
89    Clock_isrs = Clock_isrs_per_tick;
90  }
91  else
92    Clock_isrs--;
93
94} /* clockIsr */
95
96/*-------------------------------------------------------------------------+
97|         Function: Clock_exit
98|      Description: Clock cleanup routine at RTEMS exit. NOTE: This routine is
99|                   not really necessary, since there will be a reset at exit.
100| Global Variables: None.
101|        Arguments: None.
102|          Returns: Nothing.
103+--------------------------------------------------------------------------*/
104void clockOff(const rtems_irq_connect_data* unused)
105{
106  /* reset timer mode to standard (BIOS) value */
107  outport_byte(TIMER_MODE, TIMER_SEL0 | TIMER_16BIT | TIMER_RATEGEN);
108  outport_byte(TIMER_CNTR0, 0);
109  outport_byte(TIMER_CNTR0, 0);
110} /* Clock_exit */
111
112
113/*-------------------------------------------------------------------------+
114|         Function: Install_clock
115|      Description: Initialize and install clock interrupt handler.
116| Global Variables: None.
117|        Arguments: None.
118|          Returns: Nothing.
119+--------------------------------------------------------------------------*/
120static void clockOn(const rtems_irq_connect_data* unused)
121{
122  rtems_unsigned32  microseconds_per_isr;
123
124#if 0
125  /* Initialize clock from on-board real time clock.  This breaks the  */
126  /* test code which assumes which assumes the application will do it. */
127  {
128    rtems_time_of_day now;
129
130    /* External Prototypes */
131    extern void init_rtc(void);                /* defined in 'rtc.c' */
132    extern long rtc_read(rtems_time_of_day *); /* defined in 'rtc.c' */
133
134    init_rtc();
135    if (rtc_read(&now) >= 0)
136      clock_set(&now);
137  }
138#endif /* 0 */
139
140  /* Start by assuming hardware counter is large enough, then  scale it until
141     it actually fits. */
142
143  Clock_driver_ticks  = 0;
144  Clock_isrs_per_tick = 1;
145
146  if (BSP_Configuration.microseconds_per_tick == 0)
147    microseconds_per_isr = 10000; /* default 10 ms */
148  else
149    microseconds_per_isr = BSP_Configuration.microseconds_per_tick;
150  while (US_TO_TICK(microseconds_per_isr) > 65535)
151  {
152    Clock_isrs_per_tick  *= 10;
153    microseconds_per_isr /= 10;
154  }
155
156  Clock_isrs = Clock_isrs_per_tick; /* Initialize Clock_isrs */
157
158  {
159    /* 105/88 approximates TIMER_TICK * 1e-6 */
160    rtems_unsigned32 count = US_TO_TICK(microseconds_per_isr);
161
162    outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
163    outport_byte(TIMER_CNTR0, count >> 0 & 0xff);
164    outport_byte(TIMER_CNTR0, count >> 8 & 0xff);
165  } 
166
167} 
168
169int clockIsOn(const rtems_irq_connect_data* unused)
170{
171  return ((i8259s_cache & 0x1) == 0);
172}
173
174static rtems_irq_connect_data clockIrqData = {BSP_PERIODIC_TIMER,
175                                              clockIsr,
176                                              clockOn,
177                                              clockOff,
178                                              clockIsOn};
179                                             
180                                             
181
182/*-------------------------------------------------------------------------+
183| Clock device driver INITIALIZE entry point.
184+--------------------------------------------------------------------------+
185| Initilizes the clock driver.
186+--------------------------------------------------------------------------*/
187rtems_device_driver
188Clock_initialize(rtems_device_major_number major,
189                 rtems_device_minor_number minor,
190                 void                      *pargp)
191{
192
193  if (!BSP_install_rtems_irq_handler (&clockIrqData)) {
194    printk("Unable to initialize system clock\n");
195    rtems_fatal_error_occurred(1);
196  }
197  /* make major/minor avail to others such as shared memory driver */
198 
199  rtems_clock_major = major;
200  rtems_clock_minor = minor;
201 
202  return RTEMS_SUCCESSFUL;
203} /* Clock_initialize */
204
205                                             
206/*-------------------------------------------------------------------------+
207| Console device driver CONTROL entry point
208+--------------------------------------------------------------------------*/
209rtems_device_driver
210Clock_control(rtems_device_major_number major,
211              rtems_device_minor_number minor,
212              void                      *pargp)
213{
214  if (pargp != NULL)
215  {
216    rtems_libio_ioctl_args_t *args = pargp;
217       
218    /*-------------------------------------------------------------------------+
219    | This is hokey, but until we get a defined interface to do this, it will
220    | just be this simple...
221    +-------------------------------------------------------------------------*/
222 
223    if      (args->command == rtems_build_name('I', 'S', 'R', ' '))
224      clockIsr();
225    else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
226    {
227      if (!BSP_install_rtems_irq_handler (&clockIrqData)) {
228        printk("Error installing clock interrupt handler!\n");
229        rtems_fatal_error_occurred(1);
230      }
231    }
232  }
233
234  return RTEMS_SUCCESSFUL;
235} /* Clock_control */
236
237void Clock_exit()
238{
239  BSP_remove_rtems_irq_handler (&clockIrqData);
240}
241
242/*-------------------------------------------------------------------------+
243| PLEASE NOTE: The following is directly transcribed from the go32 BSP for
244|              those who wish to use it with PENTIUM based machine. It needs
245|              to be correctly integrated with the rest of the code!!!
246+--------------------------------------------------------------------------*/
247
248
249#if 0 && defined(pentium)
250
251/* This can be used to get extremely accurate timing on a pentium. */
252/* It isn't supported. [bryce]                                     */
253
254#define HZ 90.0
255
256volatile long long Last_RDTSC;
257
258#define RDTSC()\
259  ({ long long _now; __asm __volatile (".byte 0x0F,0x31":"=A"(_now)); _now; })
260
261long long Kernel_Time_ns( void )
262{
263  extern rtems_unsigned32 _TOD_Ticks_per_second;
264
265  unsigned  isrs_per_second = Clock_isrs_per_tick * _TOD_Ticks_per_second;
266  long long now;
267  int       flags;
268
269  disable_intr(flags);
270  now = 1e9 * Clock_driver_ticks / isrs_per_second +
271        (RDTSC() - Last_RDTSC) * (1000.0/HZ);
272  enable_intr(flags);
273  return now;
274} /* Kernel_Time_ns */
275
276#endif /* 0 && pentium */
Note: See TracBrowser for help on using the repository browser.