summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/i386/pc386/clock/rtc.c
blob: 076e06c7e5bf7b405a191f2e8c6bb682360eefcf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
/*-------------------------------------------------------------------------+
| rtc.c v1.1 - PC386 BSP - 1997/08/07
+--------------------------------------------------------------------------+
| This file contains the real time clock manipulation package for the
| PC386 board.
+--------------------------------------------------------------------------+
| (C) Copyright 1997 -
| - NavIST Group - Real-Time Distributed Systems and Industrial Automation
|
| http://pandora.ist.utl.pt
|
| Instituto Superior Tecnico * Lisboa * PORTUGAL
+--------------------------------------------------------------------------+
| Disclaimer:
|
| This file is provided "AS IS" without warranty of any kind, either
| expressed or implied.
+--------------------------------------------------------------------------+
| This code is based on:
|   rtc.c,v 1.4 1995/12/19 20:07:15 joel Exp - go32 BSP
| With the following copyright notice:
| **************************************************************************
| * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.                      *
| * On-Line Applications Research Corporation (OAR).                       *
| * All rights assigned to U.S. Government, 1994.                          *
| *                                                                        *
| * This material may be reproduced by or for the U.S. Government pursuant *
| * to the copyright license under the clause at DFARS 252.227-7013.  This *
| * notice must appear in all copies of this file and its derivatives.     *
| **************************************************************************
+--------------------------------------------------------------------------*/


#include <string.h>

#include <bsp.h>

/*-------------------------------------------------------------------------+
| Constants
+--------------------------------------------------------------------------*/
#define IO_RTC         0x70  /* RTC                                    */

#define RTC_SEC        0x00  /* seconds                                */
#define RTC_SECALRM    0x01  /* seconds alarm                          */
#define RTC_MIN        0x02  /* minutes                                */
#define RTC_MINALRM    0x03  /* minutes alarm                          */
#define RTC_HRS        0x04  /* hours                                  */
#define RTC_HRSALRM    0x05  /* hours alarm                            */
#define RTC_WDAY       0x06  /* week day                               */
#define RTC_DAY        0x07  /* day of month                           */
#define RTC_MONTH      0x08  /* month of year                          */
#define RTC_YEAR       0x09  /* month of year                          */
#define RTC_STATUSA    0x0a  /* status register A                      */
#define  RTCSA_TUP     0x80  /* time update, don't look now            */

#define RTC_STATUSB    0x0b  /* status register B                      */

#define RTC_INTR       0x0c  /* status register C (R) interrupt source */
#define  RTCIR_UPDATE  0x10  /* update intr                            */
#define  RTCIR_ALARM   0x20  /* alarm intr                             */
#define  RTCIR_PERIOD  0x40  /* periodic intr                          */
#define  RTCIR_INT     0x80  /* interrupt output signal                */

#define RTC_STATUSD    0x0d  /* status register D (R) Lost Power       */
#define  RTCSD_PWR     0x80  /* clock lost power                       */

#define RTC_DIAG       0x0e  /* status register E - bios diagnostic    */
#define RTCDG_BITS     "\020\010clock_battery\007ROM_cksum\006config_unit\005memory_size\004fixed_disk\003invalid_time"

#define RTC_CENTURY    0x32  /* current century - increment in Dec99   */


/*-------------------------------------------------------------------------+
| Auxiliary Functions
+--------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------+
|         Function: bcd
|      Description: Convert 2 digit number to its BCD representation.
| Global Variables: None.
|        Arguments: i - Number to convert.
|          Returns: BCD representation of number. 
+--------------------------------------------------------------------------*/
static inline rtems_unsigned8
bcd(rtems_unsigned8 i)
{
  return ((i / 16) * 10 + (i % 16));
} /* bcd */

#define QUICK_READ  /* Quick read of the RTC: don't return number of seconds. */

#ifndef QUICK_READ

#define SECS_PER_DAY      (24 * 60 * 60)
#define SECS_PER_REG_YEAR (365 * SECS_PER_DAY)

/*-------------------------------------------------------------------------+
|         Function: ytos
|      Description: Convert years to seconds (since 1970).
| Global Variables: None.
|        Arguments: y - year to convert (1970 <= y <= 2100).
|          Returns: number of seconds since 1970. 
+--------------------------------------------------------------------------*/
static inline rtems_unsigned32
ytos(rtems_unsigned16 y)
{                                       /* v NUM LEAP YEARS v */
  return ((y - 1970) * SECS_PER_REG_YEAR + (y - 1970 + 1) / 4 * SECS_PER_DAY);
} /* ytos */


/*-------------------------------------------------------------------------+
|         Function: mtos
|      Description: Convert months to seconds since January.
| Global Variables: None.
|        Arguments: m - month to convert, leap - is this a month of a leap year.
|          Returns: number of seconds since January. 
+--------------------------------------------------------------------------*/
static inline rtems_unsigned32
mtos(rtems_unsigned8 m, rtems_boolean leap)
{
  static rtems_unsigned16 daysMonth[] = { 0, 0, 31,  59,  90, 120, 151, 181,
				               212, 243, 273, 304, 334, 365 };
    /* Days since beginning of year until beginning of month. */

  return ((daysMonth[m] + (leap ? 1 : 0)) * SECS_PER_DAY);
} /* mtos */

#endif /* QUICK_READ */

/*-------------------------------------------------------------------------+
|         Function: rtcin
|      Description: Perform action on RTC and return its result.
| Global Variables: None.
|        Arguments: what - what to write to RTC port (what to do).
|          Returns: result received from RTC port after action performed. 
+--------------------------------------------------------------------------*/
static inline rtems_unsigned8
rtcin(rtems_unsigned8 what)
{
    rtems_unsigned8 r;

    outport_byte(IO_RTC,   what);
    inport_byte (IO_RTC+1, r);
    return r;
} /* rtcin */


/*-------------------------------------------------------------------------+
| Functions
+--------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------+
|         Function: init_rtc
|      Description: Initialize real-time clock (RTC).
| Global Variables: None.
|        Arguments: None.
|          Returns: Nothing. 
+--------------------------------------------------------------------------*/
void
init_rtc(void)
{
  rtems_unsigned8 s;

  /* initialize brain-dead battery powered clock */
  outport_byte(IO_RTC,   RTC_STATUSA);
  outport_byte(IO_RTC+1, 0x26);
  outport_byte(IO_RTC,   RTC_STATUSB);
  outport_byte(IO_RTC+1, 2);

  outport_byte(IO_RTC,   RTC_DIAG);
  inport_byte (IO_RTC+1, s);
  if (s)
    printk("RTC BIOS diagnostic error %b\n", s);

  /* FIXME: This was last line's original version. How was it supposed to work?
       printf("RTC BIOS diagnostic error %b\n", s, RTCDG_BITS); */
} /* init_rtc */


/*-------------------------------------------------------------------------+
|         Function: rtc_read
|      Description: Read present time from RTC and return it.
| Global Variables: None.
|        Arguments: tod - to return present time in 'rtems_time_of_day' format.
|          Returns: number of seconds from 1970/01/01 corresponding to 'tod'. 
+--------------------------------------------------------------------------*/
long int
rtc_read(rtems_time_of_day *tod)
{
  rtems_unsigned8  sa;
  rtems_unsigned32 sec = 0;

  memset(tod, 0, sizeof *tod); /* zero tod structure */

  /* do we have a realtime clock present? (otherwise we loop below) */
  sa = rtcin(RTC_STATUSA);
  if (sa == 0xff || sa == 0)
    return -1;

  /* ready for a read? */
  while ((sa&RTCSA_TUP) == RTCSA_TUP)
    sa = rtcin(RTC_STATUSA);

  tod->year	= bcd(rtcin(RTC_YEAR)) + 1900;  /* year    */
  if (tod->year < 1970)	tod->year += 100;	
  tod->month	= bcd(rtcin(RTC_MONTH));        /* month   */
  tod->day	= bcd(rtcin(RTC_DAY));          /* day     */
  (void)          bcd(rtcin(RTC_WDAY));         /* weekday */
  tod->hour	= bcd(rtcin(RTC_HRS));          /* hour    */
  tod->minute	= bcd(rtcin(RTC_MIN));          /* minutes */
  tod->second	= bcd(rtcin(RTC_SEC));          /* seconds */
  tod->ticks	= 0;

#ifndef QUICK_READ  /* Quick read of the RTC: don't return number of seconds. */
  sec =  ytos(tod->year);
  sec += mtos(tod->month, (tod->year % 4) == 0);
  sec += tod->day * SECS_PER_DAY;
  sec += tod->hour * 60 * 60;                     /* hour    */
  sec += tod->minute * 60;                        /* minutes */
  sec += tod->second;                             /* seconds */
#endif /* QUICK_READ */

  return (long int)sec;
} /* rtc_read */