]> Git Repo - qemu.git/blame - hw/mc146818rtc.c
RTC: Update the RTC clock only when reading it
[qemu.git] / hw / mc146818rtc.c
CommitLineData
80cabfad
FB
1/*
2 * QEMU MC146818 RTC emulation
5fafdf24 3 *
80cabfad 4 * Copyright (c) 2003-2004 Fabrice Bellard
5fafdf24 5 *
80cabfad
FB
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
87ecb68b
PB
24#include "hw.h"
25#include "qemu-timer.h"
26#include "sysemu.h"
1d914fa0 27#include "mc146818rtc.h"
80cabfad 28
d362e757
JK
29#ifdef TARGET_I386
30#include "apic.h"
31#endif
32
80cabfad 33//#define DEBUG_CMOS
aa6f63ff 34//#define DEBUG_COALESCED
80cabfad 35
ec51e364
IY
36#ifdef DEBUG_CMOS
37# define CMOS_DPRINTF(format, ...) printf(format, ## __VA_ARGS__)
38#else
39# define CMOS_DPRINTF(format, ...) do { } while (0)
40#endif
41
aa6f63ff
BS
42#ifdef DEBUG_COALESCED
43# define DPRINTF_C(format, ...) printf(format, ## __VA_ARGS__)
44#else
45# define DPRINTF_C(format, ...) do { } while (0)
46#endif
47
56038ef6
YZ
48#define NSEC_PER_SEC 1000000000LL
49
dd17765b 50#define RTC_REINJECT_ON_ACK_COUNT 20
e46deaba 51#define RTC_CLOCK_RATE 32768
56038ef6 52#define UIP_HOLD_LENGTH (8 * NSEC_PER_SEC / 32768)
ba32edab 53
1d914fa0 54typedef struct RTCState {
32e0c826 55 ISADevice dev;
b2c5009b 56 MemoryRegion io;
dff38e7b
FB
57 uint8_t cmos_data[128];
58 uint8_t cmos_index;
43f493af 59 struct tm current_tm;
32e0c826 60 int32_t base_year;
56038ef6
YZ
61 uint64_t base_rtc;
62 uint64_t last_update;
63 int64_t offset;
d537cf6c 64 qemu_irq irq;
100d9891 65 qemu_irq sqw_irq;
18c6e2ff 66 int it_shift;
dff38e7b
FB
67 /* periodic timer */
68 QEMUTimer *periodic_timer;
69 int64_t next_periodic_time;
56038ef6
YZ
70 /* update-ended timer */
71 QEMUTimer *update_timer;
ba32edab 72 uint16_t irq_reinject_on_ack_count;
73822ec8
AL
73 uint32_t irq_coalesced;
74 uint32_t period;
93b66569 75 QEMUTimer *coalesced_timer;
17604dac 76 Notifier clock_reset_notifier;
433acf0d 77 LostTickPolicy lost_tick_policy;
da98c8eb 78 Notifier suspend_notifier;
1d914fa0 79} RTCState;
dff38e7b
FB
80
81static void rtc_set_time(RTCState *s);
56038ef6
YZ
82static void rtc_update_time(RTCState *s);
83static void rtc_set_cmos(RTCState *s);
84static inline int rtc_from_bcd(RTCState *s, int a);
85
86static uint64_t get_guest_rtc_ns(RTCState *s)
87{
88 uint64_t guest_rtc;
89 uint64_t guest_clock = qemu_get_clock_ns(rtc_clock);
90
91 guest_rtc = s->base_rtc * NSEC_PER_SEC
92 + guest_clock - s->last_update + s->offset;
93 return guest_rtc;
94}
dff38e7b 95
93b66569
AL
96#ifdef TARGET_I386
97static void rtc_coalesced_timer_update(RTCState *s)
98{
99 if (s->irq_coalesced == 0) {
100 qemu_del_timer(s->coalesced_timer);
101 } else {
102 /* divide each RTC interval to 2 - 8 smaller intervals */
103 int c = MIN(s->irq_coalesced, 7) + 1;
74475455 104 int64_t next_clock = qemu_get_clock_ns(rtc_clock) +
e46deaba 105 muldiv64(s->period / c, get_ticks_per_sec(), RTC_CLOCK_RATE);
93b66569
AL
106 qemu_mod_timer(s->coalesced_timer, next_clock);
107 }
108}
109
110static void rtc_coalesced_timer(void *opaque)
111{
112 RTCState *s = opaque;
113
114 if (s->irq_coalesced != 0) {
115 apic_reset_irq_delivered();
116 s->cmos_data[RTC_REG_C] |= 0xc0;
aa6f63ff 117 DPRINTF_C("cmos: injecting from timer\n");
7d932dfd 118 qemu_irq_raise(s->irq);
93b66569
AL
119 if (apic_get_irq_delivered()) {
120 s->irq_coalesced--;
aa6f63ff
BS
121 DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
122 s->irq_coalesced);
93b66569
AL
123 }
124 }
125
126 rtc_coalesced_timer_update(s);
127}
128#endif
129
56038ef6 130/* handle periodic timer */
c4c18e24 131static void periodic_timer_update(RTCState *s, int64_t current_time)
dff38e7b
FB
132{
133 int period_code, period;
134 int64_t cur_clock, next_irq_clock;
135
136 period_code = s->cmos_data[RTC_REG_A] & 0x0f;
100d9891 137 if (period_code != 0
7d932dfd 138 && ((s->cmos_data[RTC_REG_B] & REG_B_PIE)
100d9891 139 || ((s->cmos_data[RTC_REG_B] & REG_B_SQWE) && s->sqw_irq))) {
dff38e7b
FB
140 if (period_code <= 2)
141 period_code += 7;
142 /* period in 32 Khz cycles */
143 period = 1 << (period_code - 1);
73822ec8 144#ifdef TARGET_I386
aa6f63ff 145 if (period != s->period) {
73822ec8 146 s->irq_coalesced = (s->irq_coalesced * s->period) / period;
aa6f63ff
BS
147 DPRINTF_C("cmos: coalesced irqs scaled to %d\n", s->irq_coalesced);
148 }
73822ec8
AL
149 s->period = period;
150#endif
dff38e7b 151 /* compute 32 khz clock */
e46deaba 152 cur_clock = muldiv64(current_time, RTC_CLOCK_RATE, get_ticks_per_sec());
dff38e7b 153 next_irq_clock = (cur_clock & ~(period - 1)) + period;
6875204c 154 s->next_periodic_time =
e46deaba 155 muldiv64(next_irq_clock, get_ticks_per_sec(), RTC_CLOCK_RATE) + 1;
dff38e7b
FB
156 qemu_mod_timer(s->periodic_timer, s->next_periodic_time);
157 } else {
73822ec8
AL
158#ifdef TARGET_I386
159 s->irq_coalesced = 0;
160#endif
dff38e7b
FB
161 qemu_del_timer(s->periodic_timer);
162 }
163}
164
165static void rtc_periodic_timer(void *opaque)
166{
167 RTCState *s = opaque;
168
c4c18e24 169 periodic_timer_update(s, s->next_periodic_time);
663447d4 170 s->cmos_data[RTC_REG_C] |= REG_C_PF;
100d9891 171 if (s->cmos_data[RTC_REG_B] & REG_B_PIE) {
663447d4 172 s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
93b66569 173#ifdef TARGET_I386
433acf0d 174 if (s->lost_tick_policy == LOST_TICK_SLEW) {
ba32edab
GN
175 if (s->irq_reinject_on_ack_count >= RTC_REINJECT_ON_ACK_COUNT)
176 s->irq_reinject_on_ack_count = 0;
93b66569 177 apic_reset_irq_delivered();
7d932dfd 178 qemu_irq_raise(s->irq);
93b66569
AL
179 if (!apic_get_irq_delivered()) {
180 s->irq_coalesced++;
181 rtc_coalesced_timer_update(s);
aa6f63ff
BS
182 DPRINTF_C("cmos: coalesced irqs increased to %d\n",
183 s->irq_coalesced);
93b66569
AL
184 }
185 } else
186#endif
7d932dfd 187 qemu_irq_raise(s->irq);
100d9891
AJ
188 }
189 if (s->cmos_data[RTC_REG_B] & REG_B_SQWE) {
190 /* Not square wave at all but we don't want 2048Hz interrupts!
191 Must be seen as a pulse. */
192 qemu_irq_raise(s->sqw_irq);
193 }
dff38e7b 194}
80cabfad 195
56038ef6
YZ
196/* handle update-ended timer */
197static void check_update_timer(RTCState *s)
198{
199 uint64_t next_update_time;
200 uint64_t guest_nsec;
201
202 /* From the data sheet: setting the SET bit does not prevent
203 * interrupts from occurring! However, it will prevent an
204 * alarm interrupt from occurring, because the time of day is
205 * not updated.
206 */
207 if ((s->cmos_data[RTC_REG_C] & REG_C_UF) &&
208 (s->cmos_data[RTC_REG_B] & REG_B_SET)) {
209 qemu_del_timer(s->update_timer);
210 return;
211 }
212 if ((s->cmos_data[RTC_REG_C] & REG_C_UF) &&
213 (s->cmos_data[RTC_REG_C] & REG_C_AF)) {
214 qemu_del_timer(s->update_timer);
215 return;
216 }
217
218 guest_nsec = get_guest_rtc_ns(s) % NSEC_PER_SEC;
219 /* reprogram to next second */
220 next_update_time = qemu_get_clock_ns(rtc_clock)
221 + NSEC_PER_SEC - guest_nsec;
222 if (next_update_time != qemu_timer_expire_time_ns(s->update_timer)) {
223 qemu_mod_timer(s->update_timer, next_update_time);
224 }
225}
226
227static inline uint8_t convert_hour(RTCState *s, uint8_t hour)
228{
229 if (!(s->cmos_data[RTC_REG_B] & REG_B_24H)) {
230 hour %= 12;
231 if (s->cmos_data[RTC_HOURS] & 0x80) {
232 hour += 12;
233 }
234 }
235 return hour;
236}
237
238static uint32_t check_alarm(RTCState *s)
239{
240 uint8_t alarm_hour, alarm_min, alarm_sec;
241 uint8_t cur_hour, cur_min, cur_sec;
242
243 alarm_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS_ALARM]);
244 alarm_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES_ALARM]);
245 alarm_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS_ALARM]);
246 alarm_hour = convert_hour(s, alarm_hour);
247
248 cur_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS]);
249 cur_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES]);
250 cur_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS]);
251 cur_hour = convert_hour(s, cur_hour);
252
253 if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0
254 || alarm_sec == cur_sec) &&
255 ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0
256 || alarm_min == cur_min) &&
257 ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0
258 || alarm_hour == cur_hour)) {
259 return 1;
260 }
261 return 0;
262
263}
264
265static void rtc_update_timer(void *opaque)
266{
267 RTCState *s = opaque;
268 int32_t irqs = REG_C_UF;
269 int32_t new_irqs;
270
271 /* UIP might have been latched, update time and clear it. */
272 rtc_update_time(s);
273 s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
274
275 if (check_alarm(s)) {
276 irqs |= REG_C_AF;
277 if (s->cmos_data[RTC_REG_B] & REG_B_AIE) {
278 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_RTC);
279 }
280 }
281 new_irqs = irqs & ~s->cmos_data[RTC_REG_C];
282 s->cmos_data[RTC_REG_C] |= irqs;
283 if ((new_irqs & s->cmos_data[RTC_REG_B]) != 0) {
284 s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
285 qemu_irq_raise(s->irq);
286 }
287 check_update_timer(s);
288}
289
b41a2cd1 290static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
80cabfad 291{
b41a2cd1 292 RTCState *s = opaque;
80cabfad
FB
293
294 if ((addr & 1) == 0) {
295 s->cmos_index = data & 0x7f;
296 } else {
ec51e364
IY
297 CMOS_DPRINTF("cmos: write index=0x%02x val=0x%02x\n",
298 s->cmos_index, data);
dff38e7b 299 switch(s->cmos_index) {
80cabfad
FB
300 case RTC_SECONDS_ALARM:
301 case RTC_MINUTES_ALARM:
302 case RTC_HOURS_ALARM:
80cabfad 303 s->cmos_data[s->cmos_index] = data;
56038ef6 304 check_update_timer(s);
80cabfad
FB
305 break;
306 case RTC_SECONDS:
307 case RTC_MINUTES:
308 case RTC_HOURS:
309 case RTC_DAY_OF_WEEK:
310 case RTC_DAY_OF_MONTH:
311 case RTC_MONTH:
312 case RTC_YEAR:
313 s->cmos_data[s->cmos_index] = data;
dff38e7b
FB
314 /* if in set mode, do not update the time */
315 if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
316 rtc_set_time(s);
56038ef6 317 check_update_timer(s);
dff38e7b 318 }
80cabfad
FB
319 break;
320 case RTC_REG_A:
dff38e7b
FB
321 /* UIP bit is read only */
322 s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
323 (s->cmos_data[RTC_REG_A] & REG_A_UIP);
c4c18e24 324 periodic_timer_update(s, qemu_get_clock_ns(rtc_clock));
56038ef6 325 check_update_timer(s);
dff38e7b 326 break;
80cabfad 327 case RTC_REG_B:
dff38e7b 328 if (data & REG_B_SET) {
56038ef6
YZ
329 /* update cmos to when the rtc was stopping */
330 if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
331 rtc_update_time(s);
332 }
dff38e7b
FB
333 /* set mode: reset UIP mode */
334 s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
335 data &= ~REG_B_UIE;
336 } else {
337 /* if disabling set mode, update the time */
338 if (s->cmos_data[RTC_REG_B] & REG_B_SET) {
56038ef6 339 s->offset = get_guest_rtc_ns(s) % NSEC_PER_SEC;
dff38e7b
FB
340 rtc_set_time(s);
341 }
342 }
9324cc50
YZ
343 /* if an interrupt flag is already set when the interrupt
344 * becomes enabled, raise an interrupt immediately. */
345 if (data & s->cmos_data[RTC_REG_C] & REG_C_MASK) {
346 s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
347 qemu_irq_raise(s->irq);
348 } else {
349 s->cmos_data[RTC_REG_C] &= ~REG_C_IRQF;
350 qemu_irq_lower(s->irq);
351 }
bedc572e 352 s->cmos_data[RTC_REG_B] = data;
c4c18e24 353 periodic_timer_update(s, qemu_get_clock_ns(rtc_clock));
56038ef6 354 check_update_timer(s);
80cabfad
FB
355 break;
356 case RTC_REG_C:
357 case RTC_REG_D:
358 /* cannot write to them */
359 break;
360 default:
361 s->cmos_data[s->cmos_index] = data;
362 break;
363 }
364 }
365}
366
abd0c6bd 367static inline int rtc_to_bcd(RTCState *s, int a)
80cabfad 368{
6f1bf24d 369 if (s->cmos_data[RTC_REG_B] & REG_B_DM) {
dff38e7b
FB
370 return a;
371 } else {
372 return ((a / 10) << 4) | (a % 10);
373 }
80cabfad
FB
374}
375
abd0c6bd 376static inline int rtc_from_bcd(RTCState *s, int a)
80cabfad 377{
6f1bf24d 378 if (s->cmos_data[RTC_REG_B] & REG_B_DM) {
dff38e7b
FB
379 return a;
380 } else {
381 return ((a >> 4) * 10) + (a & 0x0f);
382 }
383}
384
385static void rtc_set_time(RTCState *s)
386{
43f493af 387 struct tm *tm = &s->current_tm;
dff38e7b 388
abd0c6bd
PB
389 tm->tm_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS]);
390 tm->tm_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES]);
391 tm->tm_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
3b89eb43
PB
392 if (!(s->cmos_data[RTC_REG_B] & REG_B_24H)) {
393 tm->tm_hour %= 12;
394 if (s->cmos_data[RTC_HOURS] & 0x80) {
395 tm->tm_hour += 12;
396 }
43f493af 397 }
abd0c6bd
PB
398 tm->tm_wday = rtc_from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]) - 1;
399 tm->tm_mday = rtc_from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
400 tm->tm_mon = rtc_from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
401 tm->tm_year = rtc_from_bcd(s, s->cmos_data[RTC_YEAR]) + s->base_year - 1900;
80cd3478 402
56038ef6
YZ
403 s->base_rtc = mktimegm(tm);
404 s->last_update = qemu_get_clock_ns(rtc_clock);
405
80cd3478 406 rtc_change_mon_event(tm);
43f493af
FB
407}
408
56038ef6 409static void rtc_set_cmos(RTCState *s)
43f493af
FB
410{
411 const struct tm *tm = &s->current_tm;
42fc73a1 412 int year;
dff38e7b 413
abd0c6bd
PB
414 s->cmos_data[RTC_SECONDS] = rtc_to_bcd(s, tm->tm_sec);
415 s->cmos_data[RTC_MINUTES] = rtc_to_bcd(s, tm->tm_min);
c29cd656 416 if (s->cmos_data[RTC_REG_B] & REG_B_24H) {
43f493af 417 /* 24 hour format */
abd0c6bd 418 s->cmos_data[RTC_HOURS] = rtc_to_bcd(s, tm->tm_hour);
43f493af
FB
419 } else {
420 /* 12 hour format */
3b89eb43
PB
421 int h = (tm->tm_hour % 12) ? tm->tm_hour % 12 : 12;
422 s->cmos_data[RTC_HOURS] = rtc_to_bcd(s, h);
43f493af
FB
423 if (tm->tm_hour >= 12)
424 s->cmos_data[RTC_HOURS] |= 0x80;
425 }
abd0c6bd
PB
426 s->cmos_data[RTC_DAY_OF_WEEK] = rtc_to_bcd(s, tm->tm_wday + 1);
427 s->cmos_data[RTC_DAY_OF_MONTH] = rtc_to_bcd(s, tm->tm_mday);
428 s->cmos_data[RTC_MONTH] = rtc_to_bcd(s, tm->tm_mon + 1);
42fc73a1
AJ
429 year = (tm->tm_year - s->base_year) % 100;
430 if (year < 0)
431 year += 100;
abd0c6bd 432 s->cmos_data[RTC_YEAR] = rtc_to_bcd(s, year);
43f493af
FB
433}
434
56038ef6 435static void rtc_update_time(RTCState *s)
43f493af 436{
56038ef6
YZ
437 struct tm ret;
438 time_t guest_sec;
439 int64_t guest_nsec;
440
441 guest_nsec = get_guest_rtc_ns(s);
442 guest_sec = guest_nsec / NSEC_PER_SEC;
443 gmtime_r(&guest_sec, &ret);
444 s->current_tm = ret;
445 rtc_set_cmos(s);
43f493af
FB
446}
447
56038ef6 448static int update_in_progress(RTCState *s)
43f493af 449{
56038ef6 450 int64_t guest_nsec;
3b46e624 451
56038ef6
YZ
452 if (s->cmos_data[RTC_REG_B] & REG_B_SET) {
453 return 0;
dff38e7b 454 }
56038ef6
YZ
455 if (qemu_timer_pending(s->update_timer)) {
456 int64_t next_update_time = qemu_timer_expire_time_ns(s->update_timer);
457 /* Latch UIP until the timer expires. */
458 if (qemu_get_clock_ns(rtc_clock) >= (next_update_time - UIP_HOLD_LENGTH)) {
459 s->cmos_data[RTC_REG_A] |= REG_A_UIP;
460 return 1;
dff38e7b
FB
461 }
462 }
463
56038ef6
YZ
464 guest_nsec = get_guest_rtc_ns(s);
465 /* UIP bit will be set at last 244us of every second. */
466 if ((guest_nsec % NSEC_PER_SEC) >= (NSEC_PER_SEC - UIP_HOLD_LENGTH)) {
467 return 1;
dff38e7b 468 }
56038ef6 469 return 0;
80cabfad
FB
470}
471
b41a2cd1 472static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
80cabfad 473{
b41a2cd1 474 RTCState *s = opaque;
80cabfad
FB
475 int ret;
476 if ((addr & 1) == 0) {
477 return 0xff;
478 } else {
479 switch(s->cmos_index) {
480 case RTC_SECONDS:
481 case RTC_MINUTES:
482 case RTC_HOURS:
483 case RTC_DAY_OF_WEEK:
484 case RTC_DAY_OF_MONTH:
485 case RTC_MONTH:
486 case RTC_YEAR:
56038ef6
YZ
487 /* if not in set mode, calibrate cmos before
488 * reading*/
489 if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
490 rtc_update_time(s);
491 }
80cabfad
FB
492 ret = s->cmos_data[s->cmos_index];
493 break;
494 case RTC_REG_A:
56038ef6
YZ
495 if (update_in_progress(s)) {
496 s->cmos_data[s->cmos_index] |= REG_A_UIP;
497 } else {
498 s->cmos_data[s->cmos_index] &= ~REG_A_UIP;
499 }
80cabfad 500 ret = s->cmos_data[s->cmos_index];
80cabfad
FB
501 break;
502 case RTC_REG_C:
503 ret = s->cmos_data[s->cmos_index];
d537cf6c 504 qemu_irq_lower(s->irq);
fbc15e27 505 s->cmos_data[RTC_REG_C] = 0x00;
56038ef6
YZ
506 if (ret & (REG_C_UF | REG_C_AF)) {
507 check_update_timer(s);
508 }
ba32edab
GN
509#ifdef TARGET_I386
510 if(s->irq_coalesced &&
fbc15e27 511 (s->cmos_data[RTC_REG_B] & REG_B_PIE) &&
ba32edab
GN
512 s->irq_reinject_on_ack_count < RTC_REINJECT_ON_ACK_COUNT) {
513 s->irq_reinject_on_ack_count++;
fbc15e27 514 s->cmos_data[RTC_REG_C] |= REG_C_IRQF | REG_C_PF;
ba32edab 515 apic_reset_irq_delivered();
aa6f63ff 516 DPRINTF_C("cmos: injecting on ack\n");
ba32edab 517 qemu_irq_raise(s->irq);
aa6f63ff 518 if (apic_get_irq_delivered()) {
ba32edab 519 s->irq_coalesced--;
aa6f63ff
BS
520 DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
521 s->irq_coalesced);
522 }
ba32edab
GN
523 }
524#endif
80cabfad
FB
525 break;
526 default:
527 ret = s->cmos_data[s->cmos_index];
528 break;
529 }
ec51e364
IY
530 CMOS_DPRINTF("cmos: read index=0x%02x val=0x%02x\n",
531 s->cmos_index, ret);
80cabfad
FB
532 return ret;
533 }
534}
535
1d914fa0 536void rtc_set_memory(ISADevice *dev, int addr, int val)
dff38e7b 537{
1d914fa0 538 RTCState *s = DO_UPCAST(RTCState, dev, dev);
dff38e7b
FB
539 if (addr >= 0 && addr <= 127)
540 s->cmos_data[addr] = val;
541}
542
ea55ffb3
TS
543/* PC cmos mappings */
544#define REG_IBM_CENTURY_BYTE 0x32
545#define REG_IBM_PS2_CENTURY_BYTE 0x37
546
1d914fa0 547static void rtc_set_date_from_host(ISADevice *dev)
ea55ffb3 548{
1d914fa0 549 RTCState *s = DO_UPCAST(RTCState, dev, dev);
f6503059 550 struct tm tm;
ea55ffb3
TS
551 int val;
552
f6503059 553 qemu_get_timedate(&tm, 0);
56038ef6
YZ
554
555 s->base_rtc = mktimegm(&tm);
556 s->last_update = qemu_get_clock_ns(rtc_clock);
557 s->offset = 0;
558
559 /* set the CMOS date */
560 s->current_tm = tm;
561 rtc_set_cmos(s);
ea55ffb3 562
abd0c6bd 563 val = rtc_to_bcd(s, (tm.tm_year / 100) + 19);
1d914fa0
IY
564 rtc_set_memory(dev, REG_IBM_CENTURY_BYTE, val);
565 rtc_set_memory(dev, REG_IBM_PS2_CENTURY_BYTE, val);
ea55ffb3
TS
566}
567
6b075b8a 568static int rtc_post_load(void *opaque, int version_id)
80cabfad 569{
dff38e7b
FB
570 RTCState *s = opaque;
571
56038ef6
YZ
572 if (version_id <= 2) {
573 rtc_set_time(s);
574 s->offset = 0;
575 check_update_timer(s);
576 }
577
578#ifdef TARGET_I386
048c74c4 579 if (version_id >= 2) {
433acf0d 580 if (s->lost_tick_policy == LOST_TICK_SLEW) {
048c74c4
JQ
581 rtc_coalesced_timer_update(s);
582 }
048c74c4 583 }
6b075b8a 584#endif
73822ec8
AL
585 return 0;
586}
73822ec8 587
6b075b8a
JQ
588static const VMStateDescription vmstate_rtc = {
589 .name = "mc146818rtc",
56038ef6 590 .version_id = 3,
6b075b8a
JQ
591 .minimum_version_id = 1,
592 .minimum_version_id_old = 1,
593 .post_load = rtc_post_load,
594 .fields = (VMStateField []) {
595 VMSTATE_BUFFER(cmos_data, RTCState),
596 VMSTATE_UINT8(cmos_index, RTCState),
597 VMSTATE_INT32(current_tm.tm_sec, RTCState),
598 VMSTATE_INT32(current_tm.tm_min, RTCState),
599 VMSTATE_INT32(current_tm.tm_hour, RTCState),
600 VMSTATE_INT32(current_tm.tm_wday, RTCState),
601 VMSTATE_INT32(current_tm.tm_mday, RTCState),
602 VMSTATE_INT32(current_tm.tm_mon, RTCState),
603 VMSTATE_INT32(current_tm.tm_year, RTCState),
604 VMSTATE_TIMER(periodic_timer, RTCState),
605 VMSTATE_INT64(next_periodic_time, RTCState),
56038ef6 606 VMSTATE_UNUSED(3*8),
6b075b8a
JQ
607 VMSTATE_UINT32_V(irq_coalesced, RTCState, 2),
608 VMSTATE_UINT32_V(period, RTCState, 2),
56038ef6
YZ
609 VMSTATE_UINT64_V(base_rtc, RTCState, 3),
610 VMSTATE_UINT64_V(last_update, RTCState, 3),
611 VMSTATE_INT64_V(offset, RTCState, 3),
612 VMSTATE_TIMER_V(update_timer, RTCState, 3),
6b075b8a
JQ
613 VMSTATE_END_OF_LIST()
614 }
615};
616
17604dac
JK
617static void rtc_notify_clock_reset(Notifier *notifier, void *data)
618{
619 RTCState *s = container_of(notifier, RTCState, clock_reset_notifier);
620 int64_t now = *(int64_t *)data;
621
622 rtc_set_date_from_host(&s->dev);
c4c18e24 623 periodic_timer_update(s, now);
56038ef6 624 check_update_timer(s);
17604dac 625#ifdef TARGET_I386
433acf0d 626 if (s->lost_tick_policy == LOST_TICK_SLEW) {
17604dac
JK
627 rtc_coalesced_timer_update(s);
628 }
629#endif
630}
631
da98c8eb
GH
632/* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
633 BIOS will read it and start S3 resume at POST Entry */
634static void rtc_notify_suspend(Notifier *notifier, void *data)
635{
636 RTCState *s = container_of(notifier, RTCState, suspend_notifier);
637 rtc_set_memory(&s->dev, 0xF, 0xFE);
638}
639
eeb7c03c
GN
640static void rtc_reset(void *opaque)
641{
642 RTCState *s = opaque;
643
72716184
AL
644 s->cmos_data[RTC_REG_B] &= ~(REG_B_PIE | REG_B_AIE | REG_B_SQWE);
645 s->cmos_data[RTC_REG_C] &= ~(REG_C_UF | REG_C_IRQF | REG_C_PF | REG_C_AF);
56038ef6 646 check_update_timer(s);
eeb7c03c 647
72716184 648 qemu_irq_lower(s->irq);
eeb7c03c
GN
649
650#ifdef TARGET_I386
433acf0d
JK
651 if (s->lost_tick_policy == LOST_TICK_SLEW) {
652 s->irq_coalesced = 0;
653 }
eeb7c03c
GN
654#endif
655}
656
b2c5009b
RH
657static const MemoryRegionPortio cmos_portio[] = {
658 {0, 2, 1, .read = cmos_ioport_read, .write = cmos_ioport_write },
659 PORTIO_END_OF_LIST(),
660};
661
662static const MemoryRegionOps cmos_ops = {
663 .old_portio = cmos_portio
664};
665
57c9fafe 666static void rtc_get_date(Object *obj, Visitor *v, void *opaque,
18297050
AL
667 const char *name, Error **errp)
668{
57c9fafe 669 ISADevice *isa = ISA_DEVICE(obj);
18297050
AL
670 RTCState *s = DO_UPCAST(RTCState, dev, isa);
671
56038ef6 672 rtc_update_time(s);
18297050
AL
673 visit_start_struct(v, NULL, "struct tm", name, 0, errp);
674 visit_type_int32(v, &s->current_tm.tm_year, "tm_year", errp);
675 visit_type_int32(v, &s->current_tm.tm_mon, "tm_mon", errp);
676 visit_type_int32(v, &s->current_tm.tm_mday, "tm_mday", errp);
677 visit_type_int32(v, &s->current_tm.tm_hour, "tm_hour", errp);
678 visit_type_int32(v, &s->current_tm.tm_min, "tm_min", errp);
679 visit_type_int32(v, &s->current_tm.tm_sec, "tm_sec", errp);
680 visit_end_struct(v, errp);
681}
682
32e0c826 683static int rtc_initfn(ISADevice *dev)
dff38e7b 684{
32e0c826
GH
685 RTCState *s = DO_UPCAST(RTCState, dev, dev);
686 int base = 0x70;
80cabfad 687
80cabfad
FB
688 s->cmos_data[RTC_REG_A] = 0x26;
689 s->cmos_data[RTC_REG_B] = 0x02;
690 s->cmos_data[RTC_REG_C] = 0x00;
691 s->cmos_data[RTC_REG_D] = 0x80;
692
1d914fa0 693 rtc_set_date_from_host(dev);
ea55ffb3 694
93b66569 695#ifdef TARGET_I386
433acf0d
JK
696 switch (s->lost_tick_policy) {
697 case LOST_TICK_SLEW:
6875204c 698 s->coalesced_timer =
74475455 699 qemu_new_timer_ns(rtc_clock, rtc_coalesced_timer, s);
433acf0d
JK
700 break;
701 case LOST_TICK_DISCARD:
702 break;
703 default:
704 return -EINVAL;
705 }
93b66569 706#endif
433acf0d
JK
707
708 s->periodic_timer = qemu_new_timer_ns(rtc_clock, rtc_periodic_timer, s);
56038ef6
YZ
709 s->update_timer = qemu_new_timer_ns(rtc_clock, rtc_update_timer, s);
710 check_update_timer(s);
dff38e7b 711
17604dac
JK
712 s->clock_reset_notifier.notify = rtc_notify_clock_reset;
713 qemu_register_clock_reset_notifier(rtc_clock, &s->clock_reset_notifier);
714
da98c8eb
GH
715 s->suspend_notifier.notify = rtc_notify_suspend;
716 qemu_register_suspend_notifier(&s->suspend_notifier);
717
b2c5009b
RH
718 memory_region_init_io(&s->io, &cmos_ops, s, "rtc", 2);
719 isa_register_ioport(dev, &s->io, base);
dff38e7b 720
56038ef6 721 qdev_set_legacy_instance_id(&dev->qdev, base, 3);
a08d4367 722 qemu_register_reset(rtc_reset, s);
18297050 723
57c9fafe
AL
724 object_property_add(OBJECT(s), "date", "struct tm",
725 rtc_get_date, NULL, NULL, s, NULL);
18297050 726
32e0c826
GH
727 return 0;
728}
729
48a18b3c 730ISADevice *rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq)
32e0c826
GH
731{
732 ISADevice *dev;
7d932dfd 733 RTCState *s;
eeb7c03c 734
48a18b3c 735 dev = isa_create(bus, "mc146818rtc");
7d932dfd 736 s = DO_UPCAST(RTCState, dev, dev);
32e0c826 737 qdev_prop_set_int32(&dev->qdev, "base_year", base_year);
e23a1b33 738 qdev_init_nofail(&dev->qdev);
7d932dfd
JK
739 if (intercept_irq) {
740 s->irq = intercept_irq;
741 } else {
742 isa_init_irq(dev, &s->irq, RTC_ISA_IRQ);
743 }
1d914fa0 744 return dev;
80cabfad
FB
745}
746
39bffca2
AL
747static Property mc146818rtc_properties[] = {
748 DEFINE_PROP_INT32("base_year", RTCState, base_year, 1980),
749 DEFINE_PROP_LOSTTICKPOLICY("lost_tick_policy", RTCState,
750 lost_tick_policy, LOST_TICK_DISCARD),
751 DEFINE_PROP_END_OF_LIST(),
752};
753
8f04ee08
AL
754static void rtc_class_initfn(ObjectClass *klass, void *data)
755{
39bffca2 756 DeviceClass *dc = DEVICE_CLASS(klass);
8f04ee08
AL
757 ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
758 ic->init = rtc_initfn;
39bffca2
AL
759 dc->no_user = 1;
760 dc->vmsd = &vmstate_rtc;
761 dc->props = mc146818rtc_properties;
8f04ee08
AL
762}
763
39bffca2
AL
764static TypeInfo mc146818rtc_info = {
765 .name = "mc146818rtc",
766 .parent = TYPE_ISA_DEVICE,
767 .instance_size = sizeof(RTCState),
768 .class_init = rtc_class_initfn,
32e0c826
GH
769};
770
83f7d43a 771static void mc146818rtc_register_types(void)
100d9891 772{
39bffca2 773 type_register_static(&mc146818rtc_info);
100d9891 774}
83f7d43a
AF
775
776type_init(mc146818rtc_register_types)
This page took 0.899304 seconds and 4 git commands to generate.