source: rtems/c/src/lib/libbsp/i386/pc386/timer/timer.c @ 2d7d605

4.104.114.84.9
Last change on this file since 2d7d605 was 2d7d605, checked in by Joel Sherrill <joel.sherrill@…>, on Aug 19, 1998 at 2:41:23 PM

Patch from Aleksey <qqi@…>:

It fixes netboot build problem, KA9Q configuration
for pc386, some compiler wardning, it also removed some stuff
ifdef'ed with '#if 0'.

  • Property mode set to 100644
File size: 10.0 KB
Line 
1/*-------------------------------------------------------------------------+
2| timer.c v1.1 - PC386 BSP - 1997/08/07
3+--------------------------------------------------------------------------+
4| This file contains the PC386 timer package.
5+--------------------------------------------------------------------------+
6| NOTE: It is important that the timer start/stop overhead be determined
7|       when porting or modifying this code.
8+--------------------------------------------------------------------------+
9| (C) Copyright 1997 -
10| - NavIST Group - Real-Time Distributed Systems and Industrial Automation
11|
12| http://pandora.ist.utl.pt
13|
14| Instituto Superior Tecnico * Lisboa * PORTUGAL
15+--------------------------------------------------------------------------+
16| Disclaimer:
17|
18| This file is provided "AS IS" without warranty of any kind, either
19| expressed or implied.
20+--------------------------------------------------------------------------+
21| This code is base on:
22|   timer.c,v 1.7 1995/12/19 20:07:43 joel Exp - go32 BSP
23| With the following copyright notice:
24| **************************************************************************
25| *  COPYRIGHT (c) 1989-1998.
26| *  On-Line Applications Research Corporation (OAR).
27| *  Copyright assigned to U.S. Government, 1994.
28| *
29| *  The license and distribution terms for this file may be
30| *  found in found in the file LICENSE in this distribution or at
31| *  http://www.OARcorp.com/rtems/license.html.
32| **************************************************************************
33|
34|  $Id$
35+--------------------------------------------------------------------------*/
36
37
38#include <stdlib.h>
39
40#include <bsp.h>
41#include <irq.h>
42
43/*-------------------------------------------------------------------------+
44| Constants
45+--------------------------------------------------------------------------*/
46#define AVG_OVERHEAD  0              /* 0.1 microseconds to start/stop timer. */
47#define LEAST_VALID   1              /* Don't trust a value lower than this.  */
48
49/*-------------------------------------------------------------------------+
50| Global Variables
51+--------------------------------------------------------------------------*/
52volatile rtems_unsigned32 Ttimer_val;
53         rtems_boolean    Timer_driver_Find_average_overhead = TRUE;
54
55/*-------------------------------------------------------------------------+
56| External Prototypes
57+--------------------------------------------------------------------------*/
58extern void timerisr(void);
59       /* timer (int 08h) Interrupt Service Routine (defined in 'timerisr.s') */
60
61/*-------------------------------------------------------------------------+
62| Pentium optimized timer handling.
63+--------------------------------------------------------------------------*/
64#if defined(pentium)
65
66/*-------------------------------------------------------------------------+
67|         Function: rdtsc
68|      Description: Read the value of PENTIUM on-chip cycle counter.
69| Global Variables: None.
70|        Arguments: None.
71|          Returns: Value of PENTIUM on-chip cycle counter.
72+--------------------------------------------------------------------------*/
73static inline unsigned long long
74rdtsc(void)
75{
76  /* Return the value of the on-chip cycle counter. */
77  unsigned long long result;
78  asm volatile(".byte 0x0F, 0x31" : "=A" (result));
79  return result;
80} /* rdtsc */
81
82
83/*-------------------------------------------------------------------------+
84|         Function: Timer_exit
85|      Description: Timer cleanup routine at RTEMS exit. NOTE: This routine is
86|                   not really necessary, since there will be a reset at exit.
87| Global Variables: None.
88|        Arguments: None.
89|          Returns: Nothing.
90+--------------------------------------------------------------------------*/
91void
92Timer_exit(void)
93{
94} /* Timer_exit */
95
96
97/*-------------------------------------------------------------------------+
98|         Function: Timer_initialize
99|      Description: Timer initialization routine.
100| Global Variables: Ttimer_val.
101|        Arguments: None.
102|          Returns: Nothing.
103+--------------------------------------------------------------------------*/
104void
105Timer_initialize(void)
106{
107  static rtems_boolean First = TRUE;
108
109  if (First)
110  {
111    First = FALSE;
112
113    atexit(Timer_exit); /* Try not to hose the system at exit. */
114  }
115  Ttimer_val = rdtsc(); /* read starting time */
116} /* Timer_initialize */
117
118
119/*-------------------------------------------------------------------------+
120|         Function: Read_timer
121|      Description: Read hardware timer value.
122| Global Variables: Ttimer_val, Timer_driver_Find_average_overhead.
123|        Arguments: None.
124|          Returns: Nothing.
125+--------------------------------------------------------------------------*/
126rtems_unsigned32
127Read_timer(void)
128{
129  register rtems_unsigned32 total;
130
131  total =  (rtems_unsigned32)(rdtsc() - Ttimer_val);
132
133  if (Timer_driver_Find_average_overhead)
134    return total;
135  else if (total < LEAST_VALID)
136    return 0; /* below timer resolution */
137  else
138    return (total - AVG_OVERHEAD);
139} /* Read_timer */
140
141#else /* pentium */
142
143/*-------------------------------------------------------------------------+
144| Non-Pentium timer handling.
145+--------------------------------------------------------------------------*/
146#define US_PER_ISR   250  /* Number of micro-seconds per timer interruption */
147
148
149/*-------------------------------------------------------------------------+
150|         Function: Timer_exit
151|      Description: Timer cleanup routine at RTEMS exit. NOTE: This routine is
152|                   not really necessary, since there will be a reset at exit.
153| Global Variables: None.
154|        Arguments: None.
155|          Returns: Nothing.
156+--------------------------------------------------------------------------*/
157static void
158timerOff(const rtems_raw_irq_connect_data* used)
159{
160    /*
161     * disable interrrupt at i8259 level
162     */
163     pc386_irq_disable_at_i8259s(used->idtIndex - PC386_IRQ_VECTOR_BASE);
164     /* reset timer mode to standard (DOS) value */
165     outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
166     outport_byte(TIMER_CNTR0, 0);
167     outport_byte(TIMER_CNTR0, 0);
168} /* Timer_exit */
169
170
171static void 
172timerOn(const rtems_raw_irq_connect_data* used)
173{
174     /* load timer for US_PER_ISR microsecond period */
175     outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
176     outport_byte(TIMER_CNTR0, US_TO_TICK(US_PER_ISR) >> 0 & 0xff);
177     outport_byte(TIMER_CNTR0, US_TO_TICK(US_PER_ISR) >> 8 & 0xff);
178    /*
179     * enable interrrupt at i8259 level
180     */
181     pc386_irq_enable_at_i8259s(used->idtIndex - PC386_IRQ_VECTOR_BASE);
182}
183
184static int 
185timerIsOn(const rtems_raw_irq_connect_data *used)
186{
187     return pc386_irq_enabled_at_i8259s(used->idtIndex - PC386_IRQ_VECTOR_BASE);}
188
189static rtems_raw_irq_connect_data timer_raw_irq_data = {
190  PC_386_PERIODIC_TIMER + PC386_IRQ_VECTOR_BASE,
191  timerisr,
192  timerOn,
193  timerOff,
194  timerIsOn
195};
196
197/*-------------------------------------------------------------------------+
198|         Function: Timer_exit
199|      Description: Timer cleanup routine at RTEMS exit. NOTE: This routine is
200|                   not really necessary, since there will be a reset at exit.
201| Global Variables: None.
202|        Arguments: None.
203|          Returns: Nothing.
204+--------------------------------------------------------------------------*/
205void
206Timer_exit(void)
207{
208  i386_delete_idt_entry (&timer_raw_irq_data);
209} /* Timer_exit */
210
211/*-------------------------------------------------------------------------+
212|         Function: Timer_initialize
213|      Description: Timer initialization routine.
214| Global Variables: Ttimer_val.
215|        Arguments: None.
216|          Returns: Nothing.
217+--------------------------------------------------------------------------*/
218void
219Timer_initialize(void)
220{
221  static rtems_boolean First = TRUE;
222
223  if (First)
224  {
225    First = FALSE;
226
227    atexit(Timer_exit); /* Try not to hose the system at exit. */
228    if (!i386_set_idt_entry (&timer_raw_irq_data)) {
229      printk("raw handler connexion failed\n");
230      rtems_fatal_error_occurred(1);
231    }
232  }
233  /* wait for ISR to be called at least once */
234  Ttimer_val = 0;
235  while (Ttimer_val == 0)
236    continue;
237  Ttimer_val = 0;
238} /* Timer_initialize */
239
240
241/*-------------------------------------------------------------------------+
242|         Function: Read_timer
243|      Description: Read hardware timer value.
244| Global Variables: Ttimer_val, Timer_driver_Find_average_overhead.
245|        Arguments: None.
246|          Returns: Nothing.
247+--------------------------------------------------------------------------*/
248rtems_unsigned32
249Read_timer(void)
250{
251  register rtems_unsigned32 total, clicks;
252  register rtems_unsigned8  lsb, msb;
253
254  outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_LATCH);
255  inport_byte(TIMER_CNTR0, lsb);
256  inport_byte(TIMER_CNTR0, msb);
257  clicks = (msb << 8) | lsb;
258  total  = (Ttimer_val * US_PER_ISR) + (US_PER_ISR - TICK_TO_US(clicks));
259
260  if (Timer_driver_Find_average_overhead)
261    return total;
262  else if (total < LEAST_VALID)
263    return 0; /* below timer resolution */
264  else
265    return (total - AVG_OVERHEAD);
266}
267
268#endif /* pentium */
269
270
271/*-------------------------------------------------------------------------+
272|         Function: Empty_function
273|      Description: Empty function used in time tests.
274| Global Variables: None.
275|        Arguments: None.
276|          Returns: Nothing.
277+--------------------------------------------------------------------------*/
278rtems_status_code Empty_function(void)
279{
280  return RTEMS_SUCCESSFUL;
281} /* Empty function */
282 
283
284/*-------------------------------------------------------------------------+
285|         Function: Set_find_average_overhead
286|      Description: Set internal Timer_driver_Find_average_overhead flag value.
287| Global Variables: Timer_driver_Find_average_overhead.
288|        Arguments: find_flag - new value of the flag.
289|          Returns: Nothing.
290+--------------------------------------------------------------------------*/
291void
292Set_find_average_overhead(rtems_boolean find_flag)
293{
294  Timer_driver_Find_average_overhead = find_flag;
295} /* Set_find_average_overhead */
Note: See TracBrowser for help on using the repository browser.