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

4.104.114.84.95
Last change on this file since 60b791ad was 60b791ad, checked in by Joel Sherrill <joel.sherrill@…>, on Feb 17, 1998 at 11:46:28 PM

updated copyright to 1998

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