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

4.104.114.84.95
Last change on this file since f05b2ac was f05b2ac, checked in by Ralf Corsepius <ralf.corsepius@…>, on 04/21/04 at 16:01:48

Remove duplicate white lines.

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