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