Statistics
| Branch: | Revision:

root / hw / mc146818rtc.c @ a08d4367

History | View | Annotate | Download (20.9 kB)

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
#define REG_C_UF   0x10
61
#define REG_C_IRQF 0x80
62
#define REG_C_PF   0x40
63
#define REG_C_AF   0x20
64

    
65
struct RTCState {
66
    uint8_t cmos_data[128];
67
    uint8_t cmos_index;
68
    struct tm current_tm;
69
    int base_year;
70
    qemu_irq irq;
71
    qemu_irq sqw_irq;
72
    int it_shift;
73
    /* periodic timer */
74
    QEMUTimer *periodic_timer;
75
    int64_t next_periodic_time;
76
    /* second update */
77
    int64_t next_second_time;
78
#ifdef TARGET_I386
79
    uint32_t irq_coalesced;
80
    uint32_t period;
81
    QEMUTimer *coalesced_timer;
82
#endif
83
    QEMUTimer *second_timer;
84
    QEMUTimer *second_timer2;
85
};
86

    
87
static void rtc_irq_raise(qemu_irq irq) {
88
    /* When HPET is operating in legacy mode, RTC interrupts are disabled
89
     * We block qemu_irq_raise, but not qemu_irq_lower, in case legacy
90
     * mode is established while interrupt is raised. We want it to
91
     * be lowered in any case
92
     */
93
#if defined TARGET_I386 || defined TARGET_X86_64
94
    if (!hpet_in_legacy_mode())
95
#endif
96
        qemu_irq_raise(irq);
97
}
98

    
99
static void rtc_set_time(RTCState *s);
100
static void rtc_copy_date(RTCState *s);
101

    
102
#ifdef TARGET_I386
103
static void rtc_coalesced_timer_update(RTCState *s)
104
{
105
    if (s->irq_coalesced == 0) {
106
        qemu_del_timer(s->coalesced_timer);
107
    } else {
108
        /* divide each RTC interval to 2 - 8 smaller intervals */
109
        int c = MIN(s->irq_coalesced, 7) + 1; 
110
        int64_t next_clock = qemu_get_clock(vm_clock) +
111
                muldiv64(s->period / c, ticks_per_sec, 32768);
112
        qemu_mod_timer(s->coalesced_timer, next_clock);
113
    }
114
}
115

    
116
static void rtc_coalesced_timer(void *opaque)
117
{
118
    RTCState *s = opaque;
119

    
120
    if (s->irq_coalesced != 0) {
121
        apic_reset_irq_delivered();
122
        s->cmos_data[RTC_REG_C] |= 0xc0;
123
        rtc_irq_raise(s->irq);
124
        if (apic_get_irq_delivered()) {
125
            s->irq_coalesced--;
126
        }
127
    }
128

    
129
    rtc_coalesced_timer_update(s);
130
}
131
#endif
132

    
133
static void rtc_timer_update(RTCState *s, int64_t current_time)
134
{
135
    int period_code, period;
136
    int64_t cur_clock, next_irq_clock;
137
    int enable_pie;
138

    
139
    period_code = s->cmos_data[RTC_REG_A] & 0x0f;
140
#if defined TARGET_I386 || defined TARGET_X86_64
141
    /* disable periodic timer if hpet is in legacy mode, since interrupts are
142
     * disabled anyway.
143
     */
144
    enable_pie = !hpet_in_legacy_mode();
145
#else
146
    enable_pie = 1;
147
#endif
148
    if (period_code != 0
149
        && (((s->cmos_data[RTC_REG_B] & REG_B_PIE) && enable_pie)
150
            || ((s->cmos_data[RTC_REG_B] & REG_B_SQWE) && s->sqw_irq))) {
151
        if (period_code <= 2)
152
            period_code += 7;
153
        /* period in 32 Khz cycles */
154
        period = 1 << (period_code - 1);
155
#ifdef TARGET_I386
156
        if(period != s->period)
157
            s->irq_coalesced = (s->irq_coalesced * s->period) / period;
158
        s->period = period;
159
#endif
160
        /* compute 32 khz clock */
161
        cur_clock = muldiv64(current_time, 32768, ticks_per_sec);
162
        next_irq_clock = (cur_clock & ~(period - 1)) + period;
163
        s->next_periodic_time = muldiv64(next_irq_clock, ticks_per_sec, 32768) + 1;
164
        qemu_mod_timer(s->periodic_timer, s->next_periodic_time);
165
    } else {
166
#ifdef TARGET_I386
167
        s->irq_coalesced = 0;
168
#endif
169
        qemu_del_timer(s->periodic_timer);
170
    }
171
}
172

    
173
static void rtc_periodic_timer(void *opaque)
174
{
175
    RTCState *s = opaque;
176

    
177
    rtc_timer_update(s, s->next_periodic_time);
178
    if (s->cmos_data[RTC_REG_B] & REG_B_PIE) {
179
        s->cmos_data[RTC_REG_C] |= 0xc0;
180
#ifdef TARGET_I386
181
        if(rtc_td_hack) {
182
            apic_reset_irq_delivered();
183
            rtc_irq_raise(s->irq);
184
            if (!apic_get_irq_delivered()) {
185
                s->irq_coalesced++;
186
                rtc_coalesced_timer_update(s);
187
            }
188
        } else
189
#endif
190
        rtc_irq_raise(s->irq);
191
    }
192
    if (s->cmos_data[RTC_REG_B] & REG_B_SQWE) {
193
        /* Not square wave at all but we don't want 2048Hz interrupts!
194
           Must be seen as a pulse.  */
195
        qemu_irq_raise(s->sqw_irq);
196
    }
197
}
198

    
199
static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
200
{
201
    RTCState *s = opaque;
202

    
203
    if ((addr & 1) == 0) {
204
        s->cmos_index = data & 0x7f;
205
    } else {
206
#ifdef DEBUG_CMOS
207
        printf("cmos: write index=0x%02x val=0x%02x\n",
208
               s->cmos_index, data);
209
#endif
210
        switch(s->cmos_index) {
211
        case RTC_SECONDS_ALARM:
212
        case RTC_MINUTES_ALARM:
213
        case RTC_HOURS_ALARM:
214
            /* XXX: not supported */
215
            s->cmos_data[s->cmos_index] = data;
216
            break;
217
        case RTC_SECONDS:
218
        case RTC_MINUTES:
219
        case RTC_HOURS:
220
        case RTC_DAY_OF_WEEK:
221
        case RTC_DAY_OF_MONTH:
222
        case RTC_MONTH:
223
        case RTC_YEAR:
224
            s->cmos_data[s->cmos_index] = data;
225
            /* if in set mode, do not update the time */
226
            if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
227
                rtc_set_time(s);
228
            }
229
            break;
230
        case RTC_REG_A:
231
            /* UIP bit is read only */
232
            s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
233
                (s->cmos_data[RTC_REG_A] & REG_A_UIP);
234
            rtc_timer_update(s, qemu_get_clock(vm_clock));
235
            break;
236
        case RTC_REG_B:
237
            if (data & REG_B_SET) {
238
                /* set mode: reset UIP mode */
239
                s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
240
                data &= ~REG_B_UIE;
241
            } else {
242
                /* if disabling set mode, update the time */
243
                if (s->cmos_data[RTC_REG_B] & REG_B_SET) {
244
                    rtc_set_time(s);
245
                }
246
            }
247
            s->cmos_data[RTC_REG_B] = data;
248
            rtc_timer_update(s, qemu_get_clock(vm_clock));
249
            break;
250
        case RTC_REG_C:
251
        case RTC_REG_D:
252
            /* cannot write to them */
253
            break;
254
        default:
255
            s->cmos_data[s->cmos_index] = data;
256
            break;
257
        }
258
    }
259
}
260

    
261
static inline int to_bcd(RTCState *s, int a)
262
{
263
    if (s->cmos_data[RTC_REG_B] & REG_B_DM) {
264
        return a;
265
    } else {
266
        return ((a / 10) << 4) | (a % 10);
267
    }
268
}
269

    
270
static inline int from_bcd(RTCState *s, int a)
271
{
272
    if (s->cmos_data[RTC_REG_B] & REG_B_DM) {
273
        return a;
274
    } else {
275
        return ((a >> 4) * 10) + (a & 0x0f);
276
    }
277
}
278

    
279
static void rtc_set_time(RTCState *s)
280
{
281
    struct tm *tm = &s->current_tm;
282

    
283
    tm->tm_sec = from_bcd(s, s->cmos_data[RTC_SECONDS]);
284
    tm->tm_min = from_bcd(s, s->cmos_data[RTC_MINUTES]);
285
    tm->tm_hour = from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
286
    if (!(s->cmos_data[RTC_REG_B] & 0x02) &&
287
        (s->cmos_data[RTC_HOURS] & 0x80)) {
288
        tm->tm_hour += 12;
289
    }
290
    tm->tm_wday = from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]) - 1;
291
    tm->tm_mday = from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
292
    tm->tm_mon = from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
293
    tm->tm_year = from_bcd(s, s->cmos_data[RTC_YEAR]) + s->base_year - 1900;
294
}
295

    
296
static void rtc_copy_date(RTCState *s)
297
{
298
    const struct tm *tm = &s->current_tm;
299
    int year;
300

    
301
    s->cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec);
302
    s->cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min);
303
    if (s->cmos_data[RTC_REG_B] & 0x02) {
304
        /* 24 hour format */
305
        s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour);
306
    } else {
307
        /* 12 hour format */
308
        s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour % 12);
309
        if (tm->tm_hour >= 12)
310
            s->cmos_data[RTC_HOURS] |= 0x80;
311
    }
312
    s->cmos_data[RTC_DAY_OF_WEEK] = to_bcd(s, tm->tm_wday + 1);
313
    s->cmos_data[RTC_DAY_OF_MONTH] = to_bcd(s, tm->tm_mday);
314
    s->cmos_data[RTC_MONTH] = to_bcd(s, tm->tm_mon + 1);
315
    year = (tm->tm_year - s->base_year) % 100;
316
    if (year < 0)
317
        year += 100;
318
    s->cmos_data[RTC_YEAR] = to_bcd(s, year);
319
}
320

    
321
/* month is between 0 and 11. */
322
static int get_days_in_month(int month, int year)
323
{
324
    static const int days_tab[12] = {
325
        31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
326
    };
327
    int d;
328
    if ((unsigned )month >= 12)
329
        return 31;
330
    d = days_tab[month];
331
    if (month == 1) {
332
        if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0))
333
            d++;
334
    }
335
    return d;
336
}
337

    
338
/* update 'tm' to the next second */
339
static void rtc_next_second(struct tm *tm)
340
{
341
    int days_in_month;
342

    
343
    tm->tm_sec++;
344
    if ((unsigned)tm->tm_sec >= 60) {
345
        tm->tm_sec = 0;
346
        tm->tm_min++;
347
        if ((unsigned)tm->tm_min >= 60) {
348
            tm->tm_min = 0;
349
            tm->tm_hour++;
350
            if ((unsigned)tm->tm_hour >= 24) {
351
                tm->tm_hour = 0;
352
                /* next day */
353
                tm->tm_wday++;
354
                if ((unsigned)tm->tm_wday >= 7)
355
                    tm->tm_wday = 0;
356
                days_in_month = get_days_in_month(tm->tm_mon,
357
                                                  tm->tm_year + 1900);
358
                tm->tm_mday++;
359
                if (tm->tm_mday < 1) {
360
                    tm->tm_mday = 1;
361
                } else if (tm->tm_mday > days_in_month) {
362
                    tm->tm_mday = 1;
363
                    tm->tm_mon++;
364
                    if (tm->tm_mon >= 12) {
365
                        tm->tm_mon = 0;
366
                        tm->tm_year++;
367
                    }
368
                }
369
            }
370
        }
371
    }
372
}
373

    
374

    
375
static void rtc_update_second(void *opaque)
376
{
377
    RTCState *s = opaque;
378
    int64_t delay;
379

    
380
    /* if the oscillator is not in normal operation, we do not update */
381
    if ((s->cmos_data[RTC_REG_A] & 0x70) != 0x20) {
382
        s->next_second_time += ticks_per_sec;
383
        qemu_mod_timer(s->second_timer, s->next_second_time);
384
    } else {
385
        rtc_next_second(&s->current_tm);
386

    
387
        if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
388
            /* update in progress bit */
389
            s->cmos_data[RTC_REG_A] |= REG_A_UIP;
390
        }
391
        /* should be 244 us = 8 / 32768 seconds, but currently the
392
           timers do not have the necessary resolution. */
393
        delay = (ticks_per_sec * 1) / 100;
394
        if (delay < 1)
395
            delay = 1;
396
        qemu_mod_timer(s->second_timer2,
397
                       s->next_second_time + delay);
398
    }
399
}
400

    
401
static void rtc_update_second2(void *opaque)
402
{
403
    RTCState *s = opaque;
404

    
405
    if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
406
        rtc_copy_date(s);
407
    }
408

    
409
    /* check alarm */
410
    if (s->cmos_data[RTC_REG_B] & REG_B_AIE) {
411
        if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 ||
412
             s->cmos_data[RTC_SECONDS_ALARM] == s->current_tm.tm_sec) &&
413
            ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 ||
414
             s->cmos_data[RTC_MINUTES_ALARM] == s->current_tm.tm_mon) &&
415
            ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 ||
416
             s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) {
417

    
418
            s->cmos_data[RTC_REG_C] |= 0xa0;
419
            rtc_irq_raise(s->irq);
420
        }
421
    }
422

    
423
    /* update ended interrupt */
424
    if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
425
        s->cmos_data[RTC_REG_C] |= 0x90;
426
        rtc_irq_raise(s->irq);
427
    }
428

    
429
    /* clear update in progress bit */
430
    s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
431

    
432
    s->next_second_time += ticks_per_sec;
433
    qemu_mod_timer(s->second_timer, s->next_second_time);
434
}
435

    
436
static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
437
{
438
    RTCState *s = opaque;
439
    int ret;
440
    if ((addr & 1) == 0) {
441
        return 0xff;
442
    } else {
443
        switch(s->cmos_index) {
444
        case RTC_SECONDS:
445
        case RTC_MINUTES:
446
        case RTC_HOURS:
447
        case RTC_DAY_OF_WEEK:
448
        case RTC_DAY_OF_MONTH:
449
        case RTC_MONTH:
450
        case RTC_YEAR:
451
            ret = s->cmos_data[s->cmos_index];
452
            break;
453
        case RTC_REG_A:
454
            ret = s->cmos_data[s->cmos_index];
455
            break;
456
        case RTC_REG_C:
457
            ret = s->cmos_data[s->cmos_index];
458
            qemu_irq_lower(s->irq);
459
            s->cmos_data[RTC_REG_C] = 0x00;
460
            break;
461
        default:
462
            ret = s->cmos_data[s->cmos_index];
463
            break;
464
        }
465
#ifdef DEBUG_CMOS
466
        printf("cmos: read index=0x%02x val=0x%02x\n",
467
               s->cmos_index, ret);
468
#endif
469
        return ret;
470
    }
471
}
472

    
473
void rtc_set_memory(RTCState *s, int addr, int val)
474
{
475
    if (addr >= 0 && addr <= 127)
476
        s->cmos_data[addr] = val;
477
}
478

    
479
void rtc_set_date(RTCState *s, const struct tm *tm)
480
{
481
    s->current_tm = *tm;
482
    rtc_copy_date(s);
483
}
484

    
485
/* PC cmos mappings */
486
#define REG_IBM_CENTURY_BYTE        0x32
487
#define REG_IBM_PS2_CENTURY_BYTE    0x37
488

    
489
static void rtc_set_date_from_host(RTCState *s)
490
{
491
    struct tm tm;
492
    int val;
493

    
494
    /* set the CMOS date */
495
    qemu_get_timedate(&tm, 0);
496
    rtc_set_date(s, &tm);
497

    
498
    val = to_bcd(s, (tm.tm_year / 100) + 19);
499
    rtc_set_memory(s, REG_IBM_CENTURY_BYTE, val);
500
    rtc_set_memory(s, REG_IBM_PS2_CENTURY_BYTE, val);
501
}
502

    
503
static void rtc_save(QEMUFile *f, void *opaque)
504
{
505
    RTCState *s = opaque;
506

    
507
    qemu_put_buffer(f, s->cmos_data, 128);
508
    qemu_put_8s(f, &s->cmos_index);
509

    
510
    qemu_put_be32(f, s->current_tm.tm_sec);
511
    qemu_put_be32(f, s->current_tm.tm_min);
512
    qemu_put_be32(f, s->current_tm.tm_hour);
513
    qemu_put_be32(f, s->current_tm.tm_wday);
514
    qemu_put_be32(f, s->current_tm.tm_mday);
515
    qemu_put_be32(f, s->current_tm.tm_mon);
516
    qemu_put_be32(f, s->current_tm.tm_year);
517

    
518
    qemu_put_timer(f, s->periodic_timer);
519
    qemu_put_be64(f, s->next_periodic_time);
520

    
521
    qemu_put_be64(f, s->next_second_time);
522
    qemu_put_timer(f, s->second_timer);
523
    qemu_put_timer(f, s->second_timer2);
524
}
525

    
526
static int rtc_load(QEMUFile *f, void *opaque, int version_id)
527
{
528
    RTCState *s = opaque;
529

    
530
    if (version_id != 1)
531
        return -EINVAL;
532

    
533
    qemu_get_buffer(f, s->cmos_data, 128);
534
    qemu_get_8s(f, &s->cmos_index);
535

    
536
    s->current_tm.tm_sec=qemu_get_be32(f);
537
    s->current_tm.tm_min=qemu_get_be32(f);
538
    s->current_tm.tm_hour=qemu_get_be32(f);
539
    s->current_tm.tm_wday=qemu_get_be32(f);
540
    s->current_tm.tm_mday=qemu_get_be32(f);
541
    s->current_tm.tm_mon=qemu_get_be32(f);
542
    s->current_tm.tm_year=qemu_get_be32(f);
543

    
544
    qemu_get_timer(f, s->periodic_timer);
545
    s->next_periodic_time=qemu_get_be64(f);
546

    
547
    s->next_second_time=qemu_get_be64(f);
548
    qemu_get_timer(f, s->second_timer);
549
    qemu_get_timer(f, s->second_timer2);
550
    return 0;
551
}
552

    
553
#ifdef TARGET_I386
554
static void rtc_save_td(QEMUFile *f, void *opaque)
555
{
556
    RTCState *s = opaque;
557

    
558
    qemu_put_be32(f, s->irq_coalesced);
559
    qemu_put_be32(f, s->period);
560
}
561

    
562
static int rtc_load_td(QEMUFile *f, void *opaque, int version_id)
563
{
564
    RTCState *s = opaque;
565

    
566
    if (version_id != 1)
567
        return -EINVAL;
568

    
569
    s->irq_coalesced = qemu_get_be32(f);
570
    s->period = qemu_get_be32(f);
571
    rtc_coalesced_timer_update(s);
572
    return 0;
573
}
574
#endif
575

    
576
static void rtc_reset(void *opaque)
577
{
578
    RTCState *s = opaque;
579

    
580
    s->cmos_data[RTC_REG_B] &= ~(REG_B_PIE | REG_B_AIE | REG_B_SQWE);
581
    s->cmos_data[RTC_REG_C] &= ~(REG_C_UF | REG_C_IRQF | REG_C_PF | REG_C_AF);
582

    
583
    qemu_irq_lower(s->irq);
584

    
585
#ifdef TARGET_I386
586
    if (rtc_td_hack)
587
            s->irq_coalesced = 0;
588
#endif
589
}
590

    
591
RTCState *rtc_init_sqw(int base, qemu_irq irq, qemu_irq sqw_irq, int base_year)
592
{
593
    RTCState *s;
594

    
595
    s = qemu_mallocz(sizeof(RTCState));
596

    
597
    s->irq = irq;
598
    s->sqw_irq = sqw_irq;
599
    s->cmos_data[RTC_REG_A] = 0x26;
600
    s->cmos_data[RTC_REG_B] = 0x02;
601
    s->cmos_data[RTC_REG_C] = 0x00;
602
    s->cmos_data[RTC_REG_D] = 0x80;
603

    
604
    s->base_year = base_year;
605
    rtc_set_date_from_host(s);
606

    
607
    s->periodic_timer = qemu_new_timer(vm_clock,
608
                                       rtc_periodic_timer, s);
609
#ifdef TARGET_I386
610
    if (rtc_td_hack)
611
        s->coalesced_timer = qemu_new_timer(vm_clock, rtc_coalesced_timer, s);
612
#endif
613
    s->second_timer = qemu_new_timer(vm_clock,
614
                                     rtc_update_second, s);
615
    s->second_timer2 = qemu_new_timer(vm_clock,
616
                                      rtc_update_second2, s);
617

    
618
    s->next_second_time = qemu_get_clock(vm_clock) + (ticks_per_sec * 99) / 100;
619
    qemu_mod_timer(s->second_timer2, s->next_second_time);
620

    
621
    register_ioport_write(base, 2, 1, cmos_ioport_write, s);
622
    register_ioport_read(base, 2, 1, cmos_ioport_read, s);
623

    
624
    register_savevm("mc146818rtc", base, 1, rtc_save, rtc_load, s);
625
#ifdef TARGET_I386
626
    if (rtc_td_hack)
627
        register_savevm("mc146818rtc-td", base, 1, rtc_save_td, rtc_load_td, s);
628
#endif
629
    qemu_register_reset(rtc_reset, s);
630

    
631
    return s;
632
}
633

    
634
RTCState *rtc_init(int base, qemu_irq irq, int base_year)
635
{
636
    return rtc_init_sqw(base, irq, NULL, base_year);
637
}
638

    
639
/* Memory mapped interface */
640
static uint32_t cmos_mm_readb (void *opaque, target_phys_addr_t addr)
641
{
642
    RTCState *s = opaque;
643

    
644
    return cmos_ioport_read(s, addr >> s->it_shift) & 0xFF;
645
}
646

    
647
static void cmos_mm_writeb (void *opaque,
648
                            target_phys_addr_t addr, uint32_t value)
649
{
650
    RTCState *s = opaque;
651

    
652
    cmos_ioport_write(s, addr >> s->it_shift, value & 0xFF);
653
}
654

    
655
static uint32_t cmos_mm_readw (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) & 0xFFFF;
661
#ifdef TARGET_WORDS_BIGENDIAN
662
    val = bswap16(val);
663
#endif
664
    return val;
665
}
666

    
667
static void cmos_mm_writew (void *opaque,
668
                            target_phys_addr_t addr, uint32_t value)
669
{
670
    RTCState *s = opaque;
671
#ifdef TARGET_WORDS_BIGENDIAN
672
    value = bswap16(value);
673
#endif
674
    cmos_ioport_write(s, addr >> s->it_shift, value & 0xFFFF);
675
}
676

    
677
static uint32_t cmos_mm_readl (void *opaque, target_phys_addr_t addr)
678
{
679
    RTCState *s = opaque;
680
    uint32_t val;
681

    
682
    val = cmos_ioport_read(s, addr >> s->it_shift);
683
#ifdef TARGET_WORDS_BIGENDIAN
684
    val = bswap32(val);
685
#endif
686
    return val;
687
}
688

    
689
static void cmos_mm_writel (void *opaque,
690
                            target_phys_addr_t addr, uint32_t value)
691
{
692
    RTCState *s = opaque;
693
#ifdef TARGET_WORDS_BIGENDIAN
694
    value = bswap32(value);
695
#endif
696
    cmos_ioport_write(s, addr >> s->it_shift, value);
697
}
698

    
699
static CPUReadMemoryFunc *rtc_mm_read[] = {
700
    &cmos_mm_readb,
701
    &cmos_mm_readw,
702
    &cmos_mm_readl,
703
};
704

    
705
static CPUWriteMemoryFunc *rtc_mm_write[] = {
706
    &cmos_mm_writeb,
707
    &cmos_mm_writew,
708
    &cmos_mm_writel,
709
};
710

    
711
RTCState *rtc_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq,
712
                      int base_year)
713
{
714
    RTCState *s;
715
    int io_memory;
716

    
717
    s = qemu_mallocz(sizeof(RTCState));
718

    
719
    s->irq = irq;
720
    s->cmos_data[RTC_REG_A] = 0x26;
721
    s->cmos_data[RTC_REG_B] = 0x02;
722
    s->cmos_data[RTC_REG_C] = 0x00;
723
    s->cmos_data[RTC_REG_D] = 0x80;
724

    
725
    s->base_year = base_year;
726
    rtc_set_date_from_host(s);
727

    
728
    s->periodic_timer = qemu_new_timer(vm_clock,
729
                                       rtc_periodic_timer, s);
730
    s->second_timer = qemu_new_timer(vm_clock,
731
                                     rtc_update_second, s);
732
    s->second_timer2 = qemu_new_timer(vm_clock,
733
                                      rtc_update_second2, s);
734

    
735
    s->next_second_time = qemu_get_clock(vm_clock) + (ticks_per_sec * 99) / 100;
736
    qemu_mod_timer(s->second_timer2, s->next_second_time);
737

    
738
    io_memory = cpu_register_io_memory(rtc_mm_read, rtc_mm_write, s);
739
    cpu_register_physical_memory(base, 2 << it_shift, io_memory);
740

    
741
    register_savevm("mc146818rtc", base, 1, rtc_save, rtc_load, s);
742
#ifdef TARGET_I386
743
    if (rtc_td_hack)
744
        register_savevm("mc146818rtc-td", base, 1, rtc_save_td, rtc_load_td, s);
745
#endif
746
    qemu_register_reset(rtc_reset, s);
747
    return s;
748
}