2 * Copyright 2005-2007, Axel Dörfler, axeld@pinc-software.de
3 * Copyright 2003, Jeff Ward, jeff@r2d2.stcloudstate.edu. All rights reserved.
5 * Distributed under the terms of the MIT License.
9 #include <arch/real_time_clock.h>
11 #include <boot/kernel_args.h>
13 #include <real_time_clock.h>
14 #include <real_time_data.h>
17 #define CMOS_ADDR_PORT 0x70
18 #define CMOS_DATA_PORT 0x71
38 numh
= (bcd
& 0xf0) >> 4;
40 return numh
* 10 + numl
;
45 int_to_bcd(uint32 number
)
56 return (high
<< 4) | low
;
61 same_time(const cmos_time
*time1
, const cmos_time
*time2
)
63 return time1
->second
== time2
->second
64 && time1
->minute
== time2
->minute
65 && time1
->hour
== time2
->hour
66 && time1
->day
== time2
->day
67 && time1
->month
== time2
->month
68 && time1
->year
== time2
->year
69 && time1
->century
== time2
->century
;
78 // Wait until bit 7 of Status Register A (indicating whether or not an update is in
79 // progress) is clear if we are reading one of the clock data registers...
81 out8(0x0a, CMOS_ADDR_PORT
);
82 while ((in8(CMOS_DATA_PORT
) & 0x80) && --waitTime
);
85 // then read the value.
86 out8(addr
, CMOS_ADDR_PORT
);
87 return in8(CMOS_DATA_PORT
);
92 cmos_write(uint8 addr
, uint8 data
)
94 out8(addr
, CMOS_ADDR_PORT
);
95 out8(data
, CMOS_DATA_PORT
);
100 set_24_hour_mode(void)
104 status_b
= cmos_read(0x0b);
106 cmos_write(0x0b, status_b
);
111 read_cmos_clock(cmos_time
*cmos
)
115 cmos
->century
= cmos_read(0x32);
116 cmos
->year
= cmos_read(0x09);
117 cmos
->month
= cmos_read(0x08);
118 cmos
->day
= cmos_read(0x07);
119 cmos
->hour
= cmos_read(0x04);
120 cmos
->minute
= cmos_read(0x02);
121 cmos
->second
= cmos_read(0x00);
126 write_cmos_clock(cmos_time
*cmos
)
130 cmos_write(0x32, cmos
->century
);
131 cmos_write(0x09, cmos
->year
);
132 cmos_write(0x08, cmos
->month
);
133 cmos_write(0x07, cmos
->day
);
134 cmos_write(0x04, cmos
->hour
);
135 cmos_write(0x02, cmos
->minute
);
136 cmos_write(0x00, cmos
->second
);
141 cmos_to_secs(const cmos_time
*cmos
)
144 t
.tm_year
= bcd_to_int(cmos
->century
) * 100 + bcd_to_int(cmos
->year
)
145 - RTC_EPOCH_BASE_YEAR
;
146 t
.tm_mon
= bcd_to_int(cmos
->month
) - 1;
147 t
.tm_mday
= bcd_to_int(cmos
->day
);
148 t
.tm_hour
= bcd_to_int(cmos
->hour
);
149 t
.tm_min
= bcd_to_int(cmos
->minute
);
150 t
.tm_sec
= bcd_to_int(cmos
->second
);
152 return rtc_tm_to_secs(&t
);
157 secs_to_cmos(uint32 seconds
, cmos_time
*cmos
)
162 rtc_secs_to_tm(seconds
, &t
);
164 wholeYear
= t
.tm_year
+ RTC_EPOCH_BASE_YEAR
;
166 cmos
->century
= int_to_bcd(wholeYear
/ 100);
167 cmos
->year
= int_to_bcd(wholeYear
% 100);
168 cmos
->month
= int_to_bcd(t
.tm_mon
+ 1);
169 cmos
->day
= int_to_bcd(t
.tm_mday
);
170 cmos
->hour
= int_to_bcd(t
.tm_hour
);
171 cmos
->minute
= int_to_bcd(t
.tm_min
);
172 cmos
->second
= int_to_bcd(t
.tm_sec
);
180 arch_rtc_init(struct kernel_args
*args
, struct real_time_data
*data
)
182 data
->arch_data
.system_time_conversion_factor
183 = args
->arch_args
.system_time_cv_factor
;
189 arch_rtc_get_hw_time(void)
197 // We will read the clock twice and make sure both reads are equal. This will prevent
198 // problems that would occur if the clock is read during an update (e.g. if we read the hour
199 // at 8:59:59, the clock gets changed, and then we read the minute and second, we would
200 // be off by a whole hour)
202 read_cmos_clock(&cmos1
);
203 read_cmos_clock(&cmos2
);
204 } while (!same_time(&cmos1
, &cmos2
) && --waitTime
);
206 // Convert the CMOS data to seconds since 1970.
207 return cmos_to_secs(&cmos1
);
212 arch_rtc_set_hw_time(uint32 seconds
)
216 secs_to_cmos(seconds
, &cmos
);
217 write_cmos_clock(&cmos
);
222 arch_rtc_set_system_time_offset(struct real_time_data
*data
, bigtime_t offset
)
224 atomic_set64(&data
->arch_data
.system_time_offset
, offset
);
229 arch_rtc_get_system_time_offset(struct real_time_data
*data
)
231 return atomic_get64(&data
->arch_data
.system_time_offset
);