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

4.104.114.95
Last change on this file since b62009c3 was b62009c3, checked in by Joel Sherrill <joel.sherrill@…>, on 02/07/08 at 21:28:11

2008-02-07 Joel Sherrill <joel.sherrill@…>

  • clock/ckinit.c: Rework clock driver to use template and to provide nanoseconds since last tick capability.
  • Property mode set to 100644
File size: 4.4 KB
Line 
1/*
2 *  Clock Tick Device Driver
3 *
4 *  History:
5 *    + Original driver was go32 clock by Joel Sherrill
6 *    + go32 clock driver hardware code was inserted into new
7 *      boilerplate when the pc386 BSP by:
8 *        Pedro Miguel Da Cruz Neto Romano <pmcnr@camoes.rnl.ist.utl.pt>
9 *        Jose Rufino <ruf@asterix.ist.utl.pt>
10 *    + Reworked by Joel Sherrill to use clock driver template.
11 *      This removes all boilerplate and leave original hardware
12 *      code I developed for the go32 BSP.
13 *
14 *  COPYRIGHT (c) 1989-2008.
15 *  On-Line Applications Research Corporation (OAR).
16 *
17 *  The license and distribution terms for this file may be
18 *  found in the file LICENSE in this distribution or at
19 *  http://www.rtems.com/license/LICENSE.
20 *
21 *  $Id$
22 */
23
24#include <bsp.h>
25#include <bsp/irq.h>
26#include <bspopts.h>
27
28#define CLOCK_VECTOR 0
29
30volatile uint32_t pc386_microseconds_per_isr;
31volatile uint32_t pc386_isrs_per_tick;
32uint32_t pc386_clock_click_count;
33
34
35/* this driver may need to count ISRs per tick */
36
37#define CLOCK_DRIVER_ISRS_PER_TICK pc386_isrs_per_tick
38
39#define Clock_driver_support_at_tick()
40
41#define Clock_driver_support_install_isr( _new, _old ) \
42  do { \
43  } while(0)
44
45uint32_t bsp_clock_nanoseconds_since_last_tick(void)
46{
47  uint32_t                 usecs, clicks, isrs;
48  uint32_t                 usecs1, usecs2;
49  uint8_t                  lsb, msb;
50  extern volatile uint32_t Clock_driver_isrs;
51  rtems_interrupt_level    level;
52
53  /*
54   * Fetch all the data in an interrupt critical section.
55   */
56  rtems_interrupt_disable(level);
57    outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_LATCH);
58    inport_byte(TIMER_CNTR0, lsb);
59    inport_byte(TIMER_CNTR0, msb);
60    isrs = Clock_driver_isrs;
61  rtems_interrupt_enable(level);
62
63  /*
64   *  Now do the math
65   */
66  /* convert values read into counter clicks */
67  clicks = ((msb << 8) | lsb);
68
69  /* whole ISRs we have done since the last tick */
70  usecs1 = (pc386_isrs_per_tick - isrs - 1) * pc386_microseconds_per_isr;
71
72  /* the partial ISR we in the middle of now */
73  usecs2 = pc386_microseconds_per_isr - TICK_TO_US(clicks);
74
75  /* total microseconds */
76  usecs = usecs1 + usecs2;
77  #if 0
78    printk( "usecs1=%d usecs2=%d ", usecs1, usecs2 );
79    printk( "maxclicks=%d clicks=%d ISRs=%d ISRsper=%d usersPer=%d usecs=%d\n",
80    pc386_clock_click_count, clicks,
81    Clock_driver_isrs, pc386_isrs_per_tick,
82    pc386_microseconds_per_isr, usecs );
83  #endif
84
85  /* return it in nanoseconds */
86  return usecs * 1000;
87}
88
89#define Clock_driver_nanoseconds_since_last_tick \
90  bsp_clock_nanoseconds_since_last_tick
91
92static void clockOn(
93  const rtems_irq_connect_data* unused
94)
95{
96  pc386_isrs_per_tick        = 1;
97  pc386_microseconds_per_isr = rtems_configuration_get_microseconds_per_tick();
98
99  while (US_TO_TICK(pc386_microseconds_per_isr) > 65535) {
100    pc386_isrs_per_tick  *= 10;
101    pc386_microseconds_per_isr /= 10;
102  }
103  pc386_clock_click_count = US_TO_TICK(pc386_microseconds_per_isr);
104
105  #if 0
106    printk( "configured usecs per tick=%d \n",
107      rtems_configuration_get_microseconds_per_tick() );
108    printk( "Microseconds per ISR =%d\n", pc386_microseconds_per_isr );
109    printk( "final ISRs per=%d\n", pc386_isrs_per_tick );
110    printk( "final timer counts=%d\n", pc386_clock_click_count );
111  #endif
112
113  outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
114  outport_byte(TIMER_CNTR0, pc386_clock_click_count >> 0 & 0xff);
115  outport_byte(TIMER_CNTR0, pc386_clock_click_count >> 8 & 0xff);
116}
117
118void clockOff(const rtems_irq_connect_data* unused)
119{
120  /* reset timer mode to standard (BIOS) value */
121  outport_byte(TIMER_MODE, TIMER_SEL0 | TIMER_16BIT | TIMER_RATEGEN);
122  outport_byte(TIMER_CNTR0, 0);
123  outport_byte(TIMER_CNTR0, 0);
124} /* Clock_exit */
125
126int clockIsOn(const rtems_irq_connect_data* unused)
127{
128  return ((i8259s_cache & 0x1) == 0);
129}
130
131/* a bit of a hack since the ISR models do not match */
132rtems_isr Clock_isr(
133  rtems_vector_number vector
134);
135static rtems_irq_connect_data clockIrqData = {
136  BSP_PERIODIC_TIMER,
137  (void *)Clock_isr,
138  0,
139  clockOn,
140  clockOff,
141  clockIsOn
142};
143
144#define Clock_driver_support_initialize_hardware() \
145  do { \
146    if (!BSP_install_rtems_irq_handler (&clockIrqData)) { \
147      printk("Unable to initialize system clock\n"); \
148      rtems_fatal_error_occurred(1); \
149    } \
150  } while (0)
151
152#define Clock_driver_support_shutdown_hardware() \
153  do { \
154    BSP_remove_rtems_irq_handler (&clockIrqData); \
155  } while (0)
156
157#include "../../../shared/clockdrv_shell.c"
158
Note: See TracBrowser for help on using the repository browser.