]> git.proxmox.com Git - qemu.git/blob - hw/mc146818rtc.c
Add -rtc-td-hack option to fix time drift with RTC on Windows (Gleb Natapov)
[qemu.git] / hw / mc146818rtc.c
1 /*
2 * QEMU MC146818 RTC emulation
3 *
4 * Copyright (c) 2003-2004 Fabrice Bellard
5 *
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 */
24 #include "hw.h"
25 #include "qemu-timer.h"
26 #include "sysemu.h"
27 #include "pc.h"
28 #include "isa.h"
29 #include "hpet_emul.h"
30
31 //#define DEBUG_CMOS
32
33 #define RTC_SECONDS 0
34 #define RTC_SECONDS_ALARM 1
35 #define RTC_MINUTES 2
36 #define RTC_MINUTES_ALARM 3
37 #define RTC_HOURS 4
38 #define RTC_HOURS_ALARM 5
39 #define RTC_ALARM_DONT_CARE 0xC0
40
41 #define RTC_DAY_OF_WEEK 6
42 #define RTC_DAY_OF_MONTH 7
43 #define RTC_MONTH 8
44 #define RTC_YEAR 9
45
46 #define RTC_REG_A 10
47 #define RTC_REG_B 11
48 #define RTC_REG_C 12
49 #define RTC_REG_D 13
50
51 #define REG_A_UIP 0x80
52
53 #define REG_B_SET 0x80
54 #define REG_B_PIE 0x40
55 #define REG_B_AIE 0x20
56 #define REG_B_UIE 0x10
57 #define REG_B_DM 0x04
58
59 struct RTCState {
60 uint8_t cmos_data[128];
61 uint8_t cmos_index;
62 struct tm current_tm;
63 qemu_irq irq;
64 int it_shift;
65 /* periodic timer */
66 QEMUTimer *periodic_timer;
67 int64_t next_periodic_time;
68 /* second update */
69 int64_t next_second_time;
70 #ifdef TARGET_I386
71 uint32_t irq_coalesced;
72 uint32_t period;
73 #endif
74 QEMUTimer *second_timer;
75 QEMUTimer *second_timer2;
76 };
77
78 static void rtc_irq_raise(qemu_irq irq) {
79 /* When HPET is operating in legacy mode, RTC interrupts are disabled
80 * We block qemu_irq_raise, but not qemu_irq_lower, in case legacy
81 * mode is established while interrupt is raised. We want it to
82 * be lowered in any case
83 */
84 #if defined TARGET_I386 || defined TARGET_X86_64
85 if (!hpet_in_legacy_mode())
86 #endif
87 qemu_irq_raise(irq);
88 }
89
90 static void rtc_set_time(RTCState *s);
91 static void rtc_copy_date(RTCState *s);
92
93 static void rtc_timer_update(RTCState *s, int64_t current_time)
94 {
95 int period_code, period;
96 int64_t cur_clock, next_irq_clock;
97
98 period_code = s->cmos_data[RTC_REG_A] & 0x0f;
99 #if defined TARGET_I386 || defined TARGET_X86_64
100 /* disable periodic timer if hpet is in legacy mode, since interrupts are
101 * disabled anyway.
102 */
103 if (period_code != 0 && (s->cmos_data[RTC_REG_B] & REG_B_PIE) && !hpet_in_legacy_mode()) {
104 #else
105 if (period_code != 0 && (s->cmos_data[RTC_REG_B] & REG_B_PIE)) {
106 #endif
107 if (period_code <= 2)
108 period_code += 7;
109 /* period in 32 Khz cycles */
110 period = 1 << (period_code - 1);
111 #ifdef TARGET_I386
112 if(period != s->period)
113 s->irq_coalesced = (s->irq_coalesced * s->period) / period;
114 s->period = period;
115 #endif
116 /* compute 32 khz clock */
117 cur_clock = muldiv64(current_time, 32768, ticks_per_sec);
118 next_irq_clock = (cur_clock & ~(period - 1)) + period;
119 s->next_periodic_time = muldiv64(next_irq_clock, ticks_per_sec, 32768) + 1;
120 qemu_mod_timer(s->periodic_timer, s->next_periodic_time);
121 } else {
122 #ifdef TARGET_I386
123 s->irq_coalesced = 0;
124 #endif
125 qemu_del_timer(s->periodic_timer);
126 }
127 }
128
129 static void rtc_periodic_timer(void *opaque)
130 {
131 RTCState *s = opaque;
132
133 rtc_timer_update(s, s->next_periodic_time);
134 #ifdef TARGET_I386
135 if ((s->cmos_data[RTC_REG_C] & 0xc0) && rtc_td_hack) {
136 s->irq_coalesced++;
137 return;
138 }
139 #endif
140 s->cmos_data[RTC_REG_C] |= 0xc0;
141 rtc_irq_raise(s->irq);
142 }
143
144 static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
145 {
146 RTCState *s = opaque;
147
148 if ((addr & 1) == 0) {
149 s->cmos_index = data & 0x7f;
150 } else {
151 #ifdef DEBUG_CMOS
152 printf("cmos: write index=0x%02x val=0x%02x\n",
153 s->cmos_index, data);
154 #endif
155 switch(s->cmos_index) {
156 case RTC_SECONDS_ALARM:
157 case RTC_MINUTES_ALARM:
158 case RTC_HOURS_ALARM:
159 /* XXX: not supported */
160 s->cmos_data[s->cmos_index] = data;
161 break;
162 case RTC_SECONDS:
163 case RTC_MINUTES:
164 case RTC_HOURS:
165 case RTC_DAY_OF_WEEK:
166 case RTC_DAY_OF_MONTH:
167 case RTC_MONTH:
168 case RTC_YEAR:
169 s->cmos_data[s->cmos_index] = data;
170 /* if in set mode, do not update the time */
171 if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
172 rtc_set_time(s);
173 }
174 break;
175 case RTC_REG_A:
176 /* UIP bit is read only */
177 s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
178 (s->cmos_data[RTC_REG_A] & REG_A_UIP);
179 rtc_timer_update(s, qemu_get_clock(vm_clock));
180 break;
181 case RTC_REG_B:
182 if (data & REG_B_SET) {
183 /* set mode: reset UIP mode */
184 s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
185 data &= ~REG_B_UIE;
186 } else {
187 /* if disabling set mode, update the time */
188 if (s->cmos_data[RTC_REG_B] & REG_B_SET) {
189 rtc_set_time(s);
190 }
191 }
192 s->cmos_data[RTC_REG_B] = data;
193 rtc_timer_update(s, qemu_get_clock(vm_clock));
194 break;
195 case RTC_REG_C:
196 case RTC_REG_D:
197 /* cannot write to them */
198 break;
199 default:
200 s->cmos_data[s->cmos_index] = data;
201 break;
202 }
203 }
204 }
205
206 static inline int to_bcd(RTCState *s, int a)
207 {
208 if (s->cmos_data[RTC_REG_B] & REG_B_DM) {
209 return a;
210 } else {
211 return ((a / 10) << 4) | (a % 10);
212 }
213 }
214
215 static inline int from_bcd(RTCState *s, int a)
216 {
217 if (s->cmos_data[RTC_REG_B] & REG_B_DM) {
218 return a;
219 } else {
220 return ((a >> 4) * 10) + (a & 0x0f);
221 }
222 }
223
224 static void rtc_set_time(RTCState *s)
225 {
226 struct tm *tm = &s->current_tm;
227
228 tm->tm_sec = from_bcd(s, s->cmos_data[RTC_SECONDS]);
229 tm->tm_min = from_bcd(s, s->cmos_data[RTC_MINUTES]);
230 tm->tm_hour = from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
231 if (!(s->cmos_data[RTC_REG_B] & 0x02) &&
232 (s->cmos_data[RTC_HOURS] & 0x80)) {
233 tm->tm_hour += 12;
234 }
235 tm->tm_wday = from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]) - 1;
236 tm->tm_mday = from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
237 tm->tm_mon = from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
238 tm->tm_year = from_bcd(s, s->cmos_data[RTC_YEAR]) + 100;
239 }
240
241 static void rtc_copy_date(RTCState *s)
242 {
243 const struct tm *tm = &s->current_tm;
244
245 s->cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec);
246 s->cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min);
247 if (s->cmos_data[RTC_REG_B] & 0x02) {
248 /* 24 hour format */
249 s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour);
250 } else {
251 /* 12 hour format */
252 s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour % 12);
253 if (tm->tm_hour >= 12)
254 s->cmos_data[RTC_HOURS] |= 0x80;
255 }
256 s->cmos_data[RTC_DAY_OF_WEEK] = to_bcd(s, tm->tm_wday + 1);
257 s->cmos_data[RTC_DAY_OF_MONTH] = to_bcd(s, tm->tm_mday);
258 s->cmos_data[RTC_MONTH] = to_bcd(s, tm->tm_mon + 1);
259 s->cmos_data[RTC_YEAR] = to_bcd(s, tm->tm_year % 100);
260 }
261
262 /* month is between 0 and 11. */
263 static int get_days_in_month(int month, int year)
264 {
265 static const int days_tab[12] = {
266 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
267 };
268 int d;
269 if ((unsigned )month >= 12)
270 return 31;
271 d = days_tab[month];
272 if (month == 1) {
273 if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0))
274 d++;
275 }
276 return d;
277 }
278
279 /* update 'tm' to the next second */
280 static void rtc_next_second(struct tm *tm)
281 {
282 int days_in_month;
283
284 tm->tm_sec++;
285 if ((unsigned)tm->tm_sec >= 60) {
286 tm->tm_sec = 0;
287 tm->tm_min++;
288 if ((unsigned)tm->tm_min >= 60) {
289 tm->tm_min = 0;
290 tm->tm_hour++;
291 if ((unsigned)tm->tm_hour >= 24) {
292 tm->tm_hour = 0;
293 /* next day */
294 tm->tm_wday++;
295 if ((unsigned)tm->tm_wday >= 7)
296 tm->tm_wday = 0;
297 days_in_month = get_days_in_month(tm->tm_mon,
298 tm->tm_year + 1900);
299 tm->tm_mday++;
300 if (tm->tm_mday < 1) {
301 tm->tm_mday = 1;
302 } else if (tm->tm_mday > days_in_month) {
303 tm->tm_mday = 1;
304 tm->tm_mon++;
305 if (tm->tm_mon >= 12) {
306 tm->tm_mon = 0;
307 tm->tm_year++;
308 }
309 }
310 }
311 }
312 }
313 }
314
315
316 static void rtc_update_second(void *opaque)
317 {
318 RTCState *s = opaque;
319 int64_t delay;
320
321 /* if the oscillator is not in normal operation, we do not update */
322 if ((s->cmos_data[RTC_REG_A] & 0x70) != 0x20) {
323 s->next_second_time += ticks_per_sec;
324 qemu_mod_timer(s->second_timer, s->next_second_time);
325 } else {
326 rtc_next_second(&s->current_tm);
327
328 if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
329 /* update in progress bit */
330 s->cmos_data[RTC_REG_A] |= REG_A_UIP;
331 }
332 /* should be 244 us = 8 / 32768 seconds, but currently the
333 timers do not have the necessary resolution. */
334 delay = (ticks_per_sec * 1) / 100;
335 if (delay < 1)
336 delay = 1;
337 qemu_mod_timer(s->second_timer2,
338 s->next_second_time + delay);
339 }
340 }
341
342 static void rtc_update_second2(void *opaque)
343 {
344 RTCState *s = opaque;
345
346 if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
347 rtc_copy_date(s);
348 }
349
350 /* check alarm */
351 if (s->cmos_data[RTC_REG_B] & REG_B_AIE) {
352 if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 ||
353 s->cmos_data[RTC_SECONDS_ALARM] == s->current_tm.tm_sec) &&
354 ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 ||
355 s->cmos_data[RTC_MINUTES_ALARM] == s->current_tm.tm_mon) &&
356 ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 ||
357 s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) {
358
359 s->cmos_data[RTC_REG_C] |= 0xa0;
360 rtc_irq_raise(s->irq);
361 }
362 }
363
364 /* update ended interrupt */
365 if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
366 s->cmos_data[RTC_REG_C] |= 0x90;
367 rtc_irq_raise(s->irq);
368 }
369
370 /* clear update in progress bit */
371 s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
372
373 s->next_second_time += ticks_per_sec;
374 qemu_mod_timer(s->second_timer, s->next_second_time);
375 }
376
377 static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
378 {
379 RTCState *s = opaque;
380 int ret;
381 if ((addr & 1) == 0) {
382 return 0xff;
383 } else {
384 switch(s->cmos_index) {
385 case RTC_SECONDS:
386 case RTC_MINUTES:
387 case RTC_HOURS:
388 case RTC_DAY_OF_WEEK:
389 case RTC_DAY_OF_MONTH:
390 case RTC_MONTH:
391 case RTC_YEAR:
392 ret = s->cmos_data[s->cmos_index];
393 break;
394 case RTC_REG_A:
395 ret = s->cmos_data[s->cmos_index];
396 break;
397 case RTC_REG_C:
398 ret = s->cmos_data[s->cmos_index];
399 qemu_irq_lower(s->irq);
400 #ifdef TARGET_I386
401 if(s->irq_coalesced) {
402 apic_reset_irq_delivered();
403 qemu_irq_raise(s->irq);
404 if (apic_get_irq_delivered())
405 s->irq_coalesced--;
406 break;
407 }
408 #endif
409 s->cmos_data[RTC_REG_C] = 0x00;
410 break;
411 default:
412 ret = s->cmos_data[s->cmos_index];
413 break;
414 }
415 #ifdef DEBUG_CMOS
416 printf("cmos: read index=0x%02x val=0x%02x\n",
417 s->cmos_index, ret);
418 #endif
419 return ret;
420 }
421 }
422
423 void rtc_set_memory(RTCState *s, int addr, int val)
424 {
425 if (addr >= 0 && addr <= 127)
426 s->cmos_data[addr] = val;
427 }
428
429 void rtc_set_date(RTCState *s, const struct tm *tm)
430 {
431 s->current_tm = *tm;
432 rtc_copy_date(s);
433 }
434
435 /* PC cmos mappings */
436 #define REG_IBM_CENTURY_BYTE 0x32
437 #define REG_IBM_PS2_CENTURY_BYTE 0x37
438
439 static void rtc_set_date_from_host(RTCState *s)
440 {
441 struct tm tm;
442 int val;
443
444 /* set the CMOS date */
445 qemu_get_timedate(&tm, 0);
446 rtc_set_date(s, &tm);
447
448 val = to_bcd(s, (tm.tm_year / 100) + 19);
449 rtc_set_memory(s, REG_IBM_CENTURY_BYTE, val);
450 rtc_set_memory(s, REG_IBM_PS2_CENTURY_BYTE, val);
451 }
452
453 static void rtc_save(QEMUFile *f, void *opaque)
454 {
455 RTCState *s = opaque;
456
457 qemu_put_buffer(f, s->cmos_data, 128);
458 qemu_put_8s(f, &s->cmos_index);
459
460 qemu_put_be32(f, s->current_tm.tm_sec);
461 qemu_put_be32(f, s->current_tm.tm_min);
462 qemu_put_be32(f, s->current_tm.tm_hour);
463 qemu_put_be32(f, s->current_tm.tm_wday);
464 qemu_put_be32(f, s->current_tm.tm_mday);
465 qemu_put_be32(f, s->current_tm.tm_mon);
466 qemu_put_be32(f, s->current_tm.tm_year);
467
468 qemu_put_timer(f, s->periodic_timer);
469 qemu_put_be64(f, s->next_periodic_time);
470
471 qemu_put_be64(f, s->next_second_time);
472 qemu_put_timer(f, s->second_timer);
473 qemu_put_timer(f, s->second_timer2);
474 }
475
476 static int rtc_load(QEMUFile *f, void *opaque, int version_id)
477 {
478 RTCState *s = opaque;
479
480 if (version_id != 1)
481 return -EINVAL;
482
483 qemu_get_buffer(f, s->cmos_data, 128);
484 qemu_get_8s(f, &s->cmos_index);
485
486 s->current_tm.tm_sec=qemu_get_be32(f);
487 s->current_tm.tm_min=qemu_get_be32(f);
488 s->current_tm.tm_hour=qemu_get_be32(f);
489 s->current_tm.tm_wday=qemu_get_be32(f);
490 s->current_tm.tm_mday=qemu_get_be32(f);
491 s->current_tm.tm_mon=qemu_get_be32(f);
492 s->current_tm.tm_year=qemu_get_be32(f);
493
494 qemu_get_timer(f, s->periodic_timer);
495 s->next_periodic_time=qemu_get_be64(f);
496
497 s->next_second_time=qemu_get_be64(f);
498 qemu_get_timer(f, s->second_timer);
499 qemu_get_timer(f, s->second_timer2);
500 return 0;
501 }
502
503 #ifdef TARGET_I386
504 static void rtc_save_td(QEMUFile *f, void *opaque)
505 {
506 RTCState *s = opaque;
507
508 qemu_put_be32(f, s->irq_coalesced);
509 qemu_put_be32(f, s->period);
510 }
511
512 static int rtc_load_td(QEMUFile *f, void *opaque, int version_id)
513 {
514 RTCState *s = opaque;
515
516 if (version_id != 1)
517 return -EINVAL;
518
519 s->irq_coalesced = qemu_get_be32(f);
520 s->period = qemu_get_be32(f);
521 return 0;
522 }
523 #endif
524
525 RTCState *rtc_init(int base, qemu_irq irq)
526 {
527 RTCState *s;
528
529 s = qemu_mallocz(sizeof(RTCState));
530 if (!s)
531 return NULL;
532
533 s->irq = irq;
534 s->cmos_data[RTC_REG_A] = 0x26;
535 s->cmos_data[RTC_REG_B] = 0x02;
536 s->cmos_data[RTC_REG_C] = 0x00;
537 s->cmos_data[RTC_REG_D] = 0x80;
538
539 rtc_set_date_from_host(s);
540
541 s->periodic_timer = qemu_new_timer(vm_clock,
542 rtc_periodic_timer, s);
543 s->second_timer = qemu_new_timer(vm_clock,
544 rtc_update_second, s);
545 s->second_timer2 = qemu_new_timer(vm_clock,
546 rtc_update_second2, s);
547
548 s->next_second_time = qemu_get_clock(vm_clock) + (ticks_per_sec * 99) / 100;
549 qemu_mod_timer(s->second_timer2, s->next_second_time);
550
551 register_ioport_write(base, 2, 1, cmos_ioport_write, s);
552 register_ioport_read(base, 2, 1, cmos_ioport_read, s);
553
554 register_savevm("mc146818rtc", base, 1, rtc_save, rtc_load, s);
555 #ifdef TARGET_I386
556 if (rtc_td_hack)
557 register_savevm("mc146818rtc-td", base, 1, rtc_save_td, rtc_load_td, s);
558 #endif
559 return s;
560 }
561
562 /* Memory mapped interface */
563 static uint32_t cmos_mm_readb (void *opaque, target_phys_addr_t addr)
564 {
565 RTCState *s = opaque;
566
567 return cmos_ioport_read(s, addr >> s->it_shift) & 0xFF;
568 }
569
570 static void cmos_mm_writeb (void *opaque,
571 target_phys_addr_t addr, uint32_t value)
572 {
573 RTCState *s = opaque;
574
575 cmos_ioport_write(s, addr >> s->it_shift, value & 0xFF);
576 }
577
578 static uint32_t cmos_mm_readw (void *opaque, target_phys_addr_t addr)
579 {
580 RTCState *s = opaque;
581 uint32_t val;
582
583 val = cmos_ioport_read(s, addr >> s->it_shift) & 0xFFFF;
584 #ifdef TARGET_WORDS_BIGENDIAN
585 val = bswap16(val);
586 #endif
587 return val;
588 }
589
590 static void cmos_mm_writew (void *opaque,
591 target_phys_addr_t addr, uint32_t value)
592 {
593 RTCState *s = opaque;
594 #ifdef TARGET_WORDS_BIGENDIAN
595 value = bswap16(value);
596 #endif
597 cmos_ioport_write(s, addr >> s->it_shift, value & 0xFFFF);
598 }
599
600 static uint32_t cmos_mm_readl (void *opaque, target_phys_addr_t addr)
601 {
602 RTCState *s = opaque;
603 uint32_t val;
604
605 val = cmos_ioport_read(s, addr >> s->it_shift);
606 #ifdef TARGET_WORDS_BIGENDIAN
607 val = bswap32(val);
608 #endif
609 return val;
610 }
611
612 static void cmos_mm_writel (void *opaque,
613 target_phys_addr_t addr, uint32_t value)
614 {
615 RTCState *s = opaque;
616 #ifdef TARGET_WORDS_BIGENDIAN
617 value = bswap32(value);
618 #endif
619 cmos_ioport_write(s, addr >> s->it_shift, value);
620 }
621
622 static CPUReadMemoryFunc *rtc_mm_read[] = {
623 &cmos_mm_readb,
624 &cmos_mm_readw,
625 &cmos_mm_readl,
626 };
627
628 static CPUWriteMemoryFunc *rtc_mm_write[] = {
629 &cmos_mm_writeb,
630 &cmos_mm_writew,
631 &cmos_mm_writel,
632 };
633
634 RTCState *rtc_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq)
635 {
636 RTCState *s;
637 int io_memory;
638
639 s = qemu_mallocz(sizeof(RTCState));
640 if (!s)
641 return NULL;
642
643 s->irq = irq;
644 s->cmos_data[RTC_REG_A] = 0x26;
645 s->cmos_data[RTC_REG_B] = 0x02;
646 s->cmos_data[RTC_REG_C] = 0x00;
647 s->cmos_data[RTC_REG_D] = 0x80;
648
649 rtc_set_date_from_host(s);
650
651 s->periodic_timer = qemu_new_timer(vm_clock,
652 rtc_periodic_timer, s);
653 s->second_timer = qemu_new_timer(vm_clock,
654 rtc_update_second, s);
655 s->second_timer2 = qemu_new_timer(vm_clock,
656 rtc_update_second2, s);
657
658 s->next_second_time = qemu_get_clock(vm_clock) + (ticks_per_sec * 99) / 100;
659 qemu_mod_timer(s->second_timer2, s->next_second_time);
660
661 io_memory = cpu_register_io_memory(0, rtc_mm_read, rtc_mm_write, s);
662 cpu_register_physical_memory(base, 2 << it_shift, io_memory);
663
664 register_savevm("mc146818rtc", base, 1, rtc_save, rtc_load, s);
665 #ifdef TARGET_I386
666 if (rtc_td_hack)
667 register_savevm("mc146818rtc-td", base, 1, rtc_save_td, rtc_load_td, s);
668 #endif
669 return s;
670 }