1 |
30 |
unneback |
/*-------------------------------------------------------------------------+
|
2 |
|
|
| rtc.c v1.1 - PC386 BSP - 1997/08/07
|
3 |
|
|
+--------------------------------------------------------------------------+
|
4 |
|
|
| This file contains the real time clock manipulation package for the
|
5 |
|
|
| PC386 board.
|
6 |
|
|
+--------------------------------------------------------------------------+
|
7 |
|
|
| (C) Copyright 1997 -
|
8 |
|
|
| - NavIST Group - Real-Time Distributed Systems and Industrial Automation
|
9 |
|
|
|
|
10 |
|
|
| http://pandora.ist.utl.pt
|
11 |
|
|
|
|
12 |
|
|
| Instituto Superior Tecnico * Lisboa * PORTUGAL
|
13 |
|
|
+--------------------------------------------------------------------------+
|
14 |
|
|
| Disclaimer:
|
15 |
|
|
|
|
16 |
|
|
| This file is provided "AS IS" without warranty of any kind, either
|
17 |
|
|
| expressed or implied.
|
18 |
|
|
+--------------------------------------------------------------------------+
|
19 |
|
|
| This code is based on:
|
20 |
|
|
| rtc.c,v 1.4 1995/12/19 20:07:15 joel Exp - go32 BSP
|
21 |
|
|
| With the following copyright notice:
|
22 |
|
|
| **************************************************************************
|
23 |
|
|
| * COPYRIGHT (c) 1989-1999.
|
24 |
|
|
| * On-Line Applications Research Corporation (OAR).
|
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: rtc.c,v 1.2 2001-09-27 11:59:47 chris Exp $
|
32 |
|
|
+--------------------------------------------------------------------------*/
|
33 |
|
|
|
34 |
|
|
|
35 |
|
|
#include <string.h>
|
36 |
|
|
|
37 |
|
|
#include <bsp.h>
|
38 |
|
|
|
39 |
|
|
/*-------------------------------------------------------------------------+
|
40 |
|
|
| Constants
|
41 |
|
|
+--------------------------------------------------------------------------*/
|
42 |
|
|
#define IO_RTC 0x70 /* RTC */
|
43 |
|
|
|
44 |
|
|
#define RTC_SEC 0x00 /* seconds */
|
45 |
|
|
#define RTC_SECALRM 0x01 /* seconds alarm */
|
46 |
|
|
#define RTC_MIN 0x02 /* minutes */
|
47 |
|
|
#define RTC_MINALRM 0x03 /* minutes alarm */
|
48 |
|
|
#define RTC_HRS 0x04 /* hours */
|
49 |
|
|
#define RTC_HRSALRM 0x05 /* hours alarm */
|
50 |
|
|
#define RTC_WDAY 0x06 /* week day */
|
51 |
|
|
#define RTC_DAY 0x07 /* day of month */
|
52 |
|
|
#define RTC_MONTH 0x08 /* month of year */
|
53 |
|
|
#define RTC_YEAR 0x09 /* month of year */
|
54 |
|
|
#define RTC_STATUSA 0x0a /* status register A */
|
55 |
|
|
#define RTCSA_TUP 0x80 /* time update, don't look now */
|
56 |
|
|
|
57 |
|
|
#define RTC_STATUSB 0x0b /* status register B */
|
58 |
|
|
|
59 |
|
|
#define RTC_INTR 0x0c /* status register C (R) interrupt source */
|
60 |
|
|
#define RTCIR_UPDATE 0x10 /* update intr */
|
61 |
|
|
#define RTCIR_ALARM 0x20 /* alarm intr */
|
62 |
|
|
#define RTCIR_PERIOD 0x40 /* periodic intr */
|
63 |
|
|
#define RTCIR_INT 0x80 /* interrupt output signal */
|
64 |
|
|
|
65 |
|
|
#define RTC_STATUSD 0x0d /* status register D (R) Lost Power */
|
66 |
|
|
#define RTCSD_PWR 0x80 /* clock lost power */
|
67 |
|
|
|
68 |
|
|
#define RTC_DIAG 0x0e /* status register E - bios diagnostic */
|
69 |
|
|
#define RTCDG_BITS "\020\010clock_battery\007ROM_cksum\006config_unit\005memory_size\004fixed_disk\003invalid_time"
|
70 |
|
|
|
71 |
|
|
#define RTC_CENTURY 0x32 /* current century - increment in Dec99 */
|
72 |
|
|
|
73 |
|
|
|
74 |
|
|
/*-------------------------------------------------------------------------+
|
75 |
|
|
| Auxiliary Functions
|
76 |
|
|
+--------------------------------------------------------------------------*/
|
77 |
|
|
/*-------------------------------------------------------------------------+
|
78 |
|
|
| Function: bcd
|
79 |
|
|
| Description: Convert 2 digit number to its BCD representation.
|
80 |
|
|
| Global Variables: None.
|
81 |
|
|
| Arguments: i - Number to convert.
|
82 |
|
|
| Returns: BCD representation of number.
|
83 |
|
|
+--------------------------------------------------------------------------*/
|
84 |
|
|
static inline rtems_unsigned8
|
85 |
|
|
bcd(rtems_unsigned8 i)
|
86 |
|
|
{
|
87 |
|
|
return ((i / 16) * 10 + (i % 16));
|
88 |
|
|
} /* bcd */
|
89 |
|
|
|
90 |
|
|
#define QUICK_READ /* Quick read of the RTC: don't return number of seconds. */
|
91 |
|
|
|
92 |
|
|
#ifndef QUICK_READ
|
93 |
|
|
|
94 |
|
|
#define SECS_PER_DAY (24 * 60 * 60)
|
95 |
|
|
#define SECS_PER_REG_YEAR (365 * SECS_PER_DAY)
|
96 |
|
|
|
97 |
|
|
/*-------------------------------------------------------------------------+
|
98 |
|
|
| Function: ytos
|
99 |
|
|
| Description: Convert years to seconds (since 1970).
|
100 |
|
|
| Global Variables: None.
|
101 |
|
|
| Arguments: y - year to convert (1970 <= y <= 2100).
|
102 |
|
|
| Returns: number of seconds since 1970.
|
103 |
|
|
+--------------------------------------------------------------------------*/
|
104 |
|
|
static inline rtems_unsigned32
|
105 |
|
|
ytos(rtems_unsigned16 y)
|
106 |
|
|
{ /* v NUM LEAP YEARS v */
|
107 |
|
|
return ((y - 1970) * SECS_PER_REG_YEAR + (y - 1970 + 1) / 4 * SECS_PER_DAY);
|
108 |
|
|
} /* ytos */
|
109 |
|
|
|
110 |
|
|
|
111 |
|
|
/*-------------------------------------------------------------------------+
|
112 |
|
|
| Function: mtos
|
113 |
|
|
| Description: Convert months to seconds since January.
|
114 |
|
|
| Global Variables: None.
|
115 |
|
|
| Arguments: m - month to convert, leap - is this a month of a leap year.
|
116 |
|
|
| Returns: number of seconds since January.
|
117 |
|
|
+--------------------------------------------------------------------------*/
|
118 |
|
|
static inline rtems_unsigned32
|
119 |
|
|
mtos(rtems_unsigned8 m, rtems_boolean leap)
|
120 |
|
|
{
|
121 |
|
|
static rtems_unsigned16 daysMonth[] = { 0, 0, 31, 59, 90, 120, 151, 181,
|
122 |
|
|
212, 243, 273, 304, 334, 365 };
|
123 |
|
|
/* Days since beginning of year until beginning of month. */
|
124 |
|
|
|
125 |
|
|
return ((daysMonth[m] + (leap ? 1 : 0)) * SECS_PER_DAY);
|
126 |
|
|
} /* mtos */
|
127 |
|
|
|
128 |
|
|
#endif /* QUICK_READ */
|
129 |
|
|
|
130 |
|
|
/*-------------------------------------------------------------------------+
|
131 |
|
|
| Function: rtcin
|
132 |
|
|
| Description: Perform action on RTC and return its result.
|
133 |
|
|
| Global Variables: None.
|
134 |
|
|
| Arguments: what - what to write to RTC port (what to do).
|
135 |
|
|
| Returns: result received from RTC port after action performed.
|
136 |
|
|
+--------------------------------------------------------------------------*/
|
137 |
|
|
static inline rtems_unsigned8
|
138 |
|
|
rtcin(rtems_unsigned8 what)
|
139 |
|
|
{
|
140 |
|
|
rtems_unsigned8 r;
|
141 |
|
|
|
142 |
|
|
outport_byte(IO_RTC, what);
|
143 |
|
|
inport_byte (IO_RTC+1, r);
|
144 |
|
|
return r;
|
145 |
|
|
} /* rtcin */
|
146 |
|
|
|
147 |
|
|
|
148 |
|
|
/*-------------------------------------------------------------------------+
|
149 |
|
|
| Functions
|
150 |
|
|
+--------------------------------------------------------------------------*/
|
151 |
|
|
/*-------------------------------------------------------------------------+
|
152 |
|
|
| Function: init_rtc
|
153 |
|
|
| Description: Initialize real-time clock (RTC).
|
154 |
|
|
| Global Variables: None.
|
155 |
|
|
| Arguments: None.
|
156 |
|
|
| Returns: Nothing.
|
157 |
|
|
+--------------------------------------------------------------------------*/
|
158 |
|
|
void
|
159 |
|
|
init_rtc(void)
|
160 |
|
|
{
|
161 |
|
|
rtems_unsigned8 s;
|
162 |
|
|
|
163 |
|
|
/* initialize brain-dead battery powered clock */
|
164 |
|
|
outport_byte(IO_RTC, RTC_STATUSA);
|
165 |
|
|
outport_byte(IO_RTC+1, 0x26);
|
166 |
|
|
outport_byte(IO_RTC, RTC_STATUSB);
|
167 |
|
|
outport_byte(IO_RTC+1, 2);
|
168 |
|
|
|
169 |
|
|
outport_byte(IO_RTC, RTC_DIAG);
|
170 |
|
|
inport_byte (IO_RTC+1, s);
|
171 |
|
|
if (s)
|
172 |
|
|
printk("RTC BIOS diagnostic error %b\n", s);
|
173 |
|
|
|
174 |
|
|
/* FIXME: This was last line's original version. How was it supposed to work?
|
175 |
|
|
printf("RTC BIOS diagnostic error %b\n", s, RTCDG_BITS); */
|
176 |
|
|
} /* init_rtc */
|
177 |
|
|
|
178 |
|
|
|
179 |
|
|
/*-------------------------------------------------------------------------+
|
180 |
|
|
| Function: rtc_read
|
181 |
|
|
| Description: Read present time from RTC and return it.
|
182 |
|
|
| Global Variables: None.
|
183 |
|
|
| Arguments: tod - to return present time in 'rtems_time_of_day' format.
|
184 |
|
|
| Returns: number of seconds from 1970/01/01 corresponding to 'tod'.
|
185 |
|
|
+--------------------------------------------------------------------------*/
|
186 |
|
|
long int
|
187 |
|
|
rtc_read(rtems_time_of_day *tod)
|
188 |
|
|
{
|
189 |
|
|
rtems_unsigned8 sa;
|
190 |
|
|
rtems_unsigned32 sec = 0;
|
191 |
|
|
|
192 |
|
|
memset(tod, 0, sizeof *tod); /* zero tod structure */
|
193 |
|
|
|
194 |
|
|
/* do we have a realtime clock present? (otherwise we loop below) */
|
195 |
|
|
sa = rtcin(RTC_STATUSA);
|
196 |
|
|
if (sa == 0xff || sa == 0)
|
197 |
|
|
return -1;
|
198 |
|
|
|
199 |
|
|
/* ready for a read? */
|
200 |
|
|
while ((sa&RTCSA_TUP) == RTCSA_TUP)
|
201 |
|
|
sa = rtcin(RTC_STATUSA);
|
202 |
|
|
|
203 |
|
|
tod->year = bcd(rtcin(RTC_YEAR)) + 1900; /* year */
|
204 |
|
|
if (tod->year < 1970) tod->year += 100;
|
205 |
|
|
tod->month = bcd(rtcin(RTC_MONTH)); /* month */
|
206 |
|
|
tod->day = bcd(rtcin(RTC_DAY)); /* day */
|
207 |
|
|
(void) bcd(rtcin(RTC_WDAY)); /* weekday */
|
208 |
|
|
tod->hour = bcd(rtcin(RTC_HRS)); /* hour */
|
209 |
|
|
tod->minute = bcd(rtcin(RTC_MIN)); /* minutes */
|
210 |
|
|
tod->second = bcd(rtcin(RTC_SEC)); /* seconds */
|
211 |
|
|
tod->ticks = 0;
|
212 |
|
|
|
213 |
|
|
#ifndef QUICK_READ /* Quick read of the RTC: don't return number of seconds. */
|
214 |
|
|
sec = ytos(tod->year);
|
215 |
|
|
sec += mtos(tod->month, (tod->year % 4) == 0);
|
216 |
|
|
sec += tod->day * SECS_PER_DAY;
|
217 |
|
|
sec += tod->hour * 60 * 60; /* hour */
|
218 |
|
|
sec += tod->minute * 60; /* minutes */
|
219 |
|
|
sec += tod->second; /* seconds */
|
220 |
|
|
#endif /* QUICK_READ */
|
221 |
|
|
|
222 |
|
|
return (long int)sec;
|
223 |
|
|
} /* rtc_read */
|
224 |
|
|
|
225 |
|
|
|