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
|
/*
* $Id$
*/
#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 */
#include <rtems.h>
#include <string.h>
void init_rtc( void )
{
int 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 0
if (s) printf("RTC BIOS diagnostic error %b\n", s, RTCDG_BITS);
#endif
}
/* convert 2 digit BCD number */
static int bcd( unsigned int i )
{
return ((i/16)*10 + (i%16));
}
/* convert years to seconds (from 1970) */
static unsigned long ytos( int y )
{
int i;
unsigned long ret;
ret = 0;
for(i = 1970; i < y; i++) {
if (i % 4) ret += 365*24*60*60;
else ret += 366*24*60*60;
}
return ret;
}
/* convert months to seconds */
static unsigned long mtos( int m, int leap )
{
int i;
unsigned long ret;
ret = 0;
for(i=1;i<m;i++) {
switch(i){
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
ret += 31*24*60*60;
break;
case 4: case 6: case 9: case 11:
ret += 30*24*60*60;
break;
case 2:
if (leap)
ret += 29*24*60*60;
else
ret += 28*24*60*60;
}
}
return ret;
}
static inline unsigned int rtcin( unsigned int what )
{
unsigned int r;
outport_byte( IO_RTC, what );
inport_byte( IO_RTC+1, r );
return r;
}
/*
* Initialize the time of day register, based on the time base which is, e.g.
* from a filesystem.
*/
long rtc_read( rtems_time_of_day * tod )
{
int sa;
unsigned long sec = 0;
memset( tod, 0, sizeof *tod );
/* 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;
#if 0
sec = ytos( tod->year );
sec += mtos( tod->month, tod->year % 4 == 0 );
sec += tod->day * 24*60*60;
sec += tod->hour * 60*60; /* hour */
sec += tod->minute * 60; /* minutes */
sec += tod->second; /* seconds */
#else
sec = 0;
#endif
return sec;
}
/* from djgpp: include before rtems.h to avoid conflicts */
#undef delay
#include <dos.h>
void rtc_set_dos_date( void )
{
int s;
struct date date;
struct time time;
/* 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) {
#if 0
printf("RTC BIOS diagnostic error %b\n", s, RTCDG_BITS);
#else
return;
#endif
}
/* check for presence of clock */
s = rtcin(RTC_STATUSA);
if ( s == 0xff || s == 0 ) {
#if 0
printf( "Real-time clock not found\n" );
#endif
return;
}
/* ready for a read? */
while ((s & RTCSA_TUP) == RTCSA_TUP)
s = rtcin(RTC_STATUSA);
date.da_year = bcd(rtcin(RTC_YEAR)) + 1900; /* year */
if ( date.da_year < 1970) date.da_year += 100;
date.da_year -= 1980;
date.da_mon = bcd(rtcin(RTC_MONTH)); /* month */
date.da_day = bcd(rtcin(RTC_DAY)); /* day */
(void)bcd(rtcin(RTC_WDAY)); /* weekday */
time.ti_hour = bcd(rtcin(RTC_HRS)); /* hour */
time.ti_min = bcd(rtcin(RTC_MIN)); /* minutes */
time.ti_sec = bcd(rtcin(RTC_SEC)); /* seconds */
time.ti_hund = 0;
setdate( & date );
settime( & time );
}
|