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

4.104.114.84.95
Last change on this file since ba2d45e6 was 7150f00f, checked in by Joel Sherrill <joel.sherrill@…>, on 12/01/97 at 22:06:48

Inclusion of PC386 BSP submitted by Pedro Miguel Da Cruz Neto Romano
<pmcnr@…> and Jose Rufino <ruf@…>
of NavIST (http://pandora.ist.utl.pt/).

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