Statistics
| Branch: | Revision:

root / hw / mc146818rtc.c @ 322164e0

History | View | Annotate | Download (22 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 "mc146818rtc.h"
28

    
29
#ifdef TARGET_I386
30
#include "apic.h"
31
#endif
32

    
33
//#define DEBUG_CMOS
34
//#define DEBUG_COALESCED
35

    
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

    
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

    
48
#define RTC_REINJECT_ON_ACK_COUNT 20
49

    
50
typedef struct RTCState {
51
    ISADevice dev;
52
    MemoryRegion io;
53
    uint8_t cmos_data[128];
54
    uint8_t cmos_index;
55
    struct tm current_tm;
56
    int32_t base_year;
57
    qemu_irq irq;
58
    qemu_irq sqw_irq;
59
    int it_shift;
60
    /* periodic timer */
61
    QEMUTimer *periodic_timer;
62
    int64_t next_periodic_time;
63
    /* second update */
64
    int64_t next_second_time;
65
    uint16_t irq_reinject_on_ack_count;
66
    uint32_t irq_coalesced;
67
    uint32_t period;
68
    QEMUTimer *coalesced_timer;
69
    QEMUTimer *second_timer;
70
    QEMUTimer *second_timer2;
71
    Notifier clock_reset_notifier;
72
    LostTickPolicy lost_tick_policy;
73
    Notifier suspend_notifier;
74
} RTCState;
75

    
76
static void rtc_set_time(RTCState *s);
77
static void rtc_copy_date(RTCState *s);
78

    
79
#ifdef TARGET_I386
80
static void rtc_coalesced_timer_update(RTCState *s)
81
{
82
    if (s->irq_coalesced == 0) {
83
        qemu_del_timer(s->coalesced_timer);
84
    } else {
85
        /* divide each RTC interval to 2 - 8 smaller intervals */
86
        int c = MIN(s->irq_coalesced, 7) + 1; 
87
        int64_t next_clock = qemu_get_clock_ns(rtc_clock) +
88
            muldiv64(s->period / c, get_ticks_per_sec(), 32768);
89
        qemu_mod_timer(s->coalesced_timer, next_clock);
90
    }
91
}
92

    
93
static void rtc_coalesced_timer(void *opaque)
94
{
95
    RTCState *s = opaque;
96

    
97
    if (s->irq_coalesced != 0) {
98
        apic_reset_irq_delivered();
99
        s->cmos_data[RTC_REG_C] |= 0xc0;
100
        DPRINTF_C("cmos: injecting from timer\n");
101
        qemu_irq_raise(s->irq);
102
        if (apic_get_irq_delivered()) {
103
            s->irq_coalesced--;
104
            DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
105
                      s->irq_coalesced);
106
        }
107
    }
108

    
109
    rtc_coalesced_timer_update(s);
110
}
111
#endif
112

    
113
static void rtc_timer_update(RTCState *s, int64_t current_time)
114
{
115
    int period_code, period;
116
    int64_t cur_clock, next_irq_clock;
117

    
118
    period_code = s->cmos_data[RTC_REG_A] & 0x0f;
119
    if (period_code != 0
120
        && ((s->cmos_data[RTC_REG_B] & REG_B_PIE)
121
            || ((s->cmos_data[RTC_REG_B] & REG_B_SQWE) && s->sqw_irq))) {
122
        if (period_code <= 2)
123
            period_code += 7;
124
        /* period in 32 Khz cycles */
125
        period = 1 << (period_code - 1);
126
#ifdef TARGET_I386
127
        if (period != s->period) {
128
            s->irq_coalesced = (s->irq_coalesced * s->period) / period;
129
            DPRINTF_C("cmos: coalesced irqs scaled to %d\n", s->irq_coalesced);
130
        }
131
        s->period = period;
132
#endif
133
        /* compute 32 khz clock */
134
        cur_clock = muldiv64(current_time, 32768, get_ticks_per_sec());
135
        next_irq_clock = (cur_clock & ~(period - 1)) + period;
136
        s->next_periodic_time =
137
            muldiv64(next_irq_clock, get_ticks_per_sec(), 32768) + 1;
138
        qemu_mod_timer(s->periodic_timer, s->next_periodic_time);
139
    } else {
140
#ifdef TARGET_I386
141
        s->irq_coalesced = 0;
142
#endif
143
        qemu_del_timer(s->periodic_timer);
144
    }
145
}
146

    
147
static void rtc_periodic_timer(void *opaque)
148
{
149
    RTCState *s = opaque;
150

    
151
    rtc_timer_update(s, s->next_periodic_time);
152
    s->cmos_data[RTC_REG_C] |= REG_C_PF;
153
    if (s->cmos_data[RTC_REG_B] & REG_B_PIE) {
154
        s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
155
#ifdef TARGET_I386
156
        if (s->lost_tick_policy == LOST_TICK_SLEW) {
157
            if (s->irq_reinject_on_ack_count >= RTC_REINJECT_ON_ACK_COUNT)
158
                s->irq_reinject_on_ack_count = 0;                
159
            apic_reset_irq_delivered();
160
            qemu_irq_raise(s->irq);
161
            if (!apic_get_irq_delivered()) {
162
                s->irq_coalesced++;
163
                rtc_coalesced_timer_update(s);
164
                DPRINTF_C("cmos: coalesced irqs increased to %d\n",
165
                          s->irq_coalesced);
166
            }
167
        } else
168
#endif
169
        qemu_irq_raise(s->irq);
170
    }
171
    if (s->cmos_data[RTC_REG_B] & REG_B_SQWE) {
172
        /* Not square wave at all but we don't want 2048Hz interrupts!
173
           Must be seen as a pulse.  */
174
        qemu_irq_raise(s->sqw_irq);
175
    }
176
}
177

    
178
static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
179
{
180
    RTCState *s = opaque;
181

    
182
    if ((addr & 1) == 0) {
183
        s->cmos_index = data & 0x7f;
184
    } else {
185
        CMOS_DPRINTF("cmos: write index=0x%02x val=0x%02x\n",
186
                     s->cmos_index, data);
187
        switch(s->cmos_index) {
188
        case RTC_SECONDS_ALARM:
189
        case RTC_MINUTES_ALARM:
190
        case RTC_HOURS_ALARM:
191
            s->cmos_data[s->cmos_index] = data;
192
            break;
193
        case RTC_SECONDS:
194
        case RTC_MINUTES:
195
        case RTC_HOURS:
196
        case RTC_DAY_OF_WEEK:
197
        case RTC_DAY_OF_MONTH:
198
        case RTC_MONTH:
199
        case RTC_YEAR:
200
            s->cmos_data[s->cmos_index] = data;
201
            /* if in set mode, do not update the time */
202
            if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
203
                rtc_set_time(s);
204
            }
205
            break;
206
        case RTC_REG_A:
207
            /* UIP bit is read only */
208
            s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
209
                (s->cmos_data[RTC_REG_A] & REG_A_UIP);
210
            rtc_timer_update(s, qemu_get_clock_ns(rtc_clock));
211
            break;
212
        case RTC_REG_B:
213
            if (data & REG_B_SET) {
214
                /* set mode: reset UIP mode */
215
                s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
216
                data &= ~REG_B_UIE;
217
            } else {
218
                /* if disabling set mode, update the time */
219
                if (s->cmos_data[RTC_REG_B] & REG_B_SET) {
220
                    rtc_set_time(s);
221
                }
222
            }
223
            if (((s->cmos_data[RTC_REG_B] ^ data) & (REG_B_DM | REG_B_24H)) &&
224
                !(data & REG_B_SET)) {
225
                /* If the time format has changed and not in set mode,
226
                   update the registers immediately. */
227
                s->cmos_data[RTC_REG_B] = data;
228
                rtc_copy_date(s);
229
            } else {
230
                s->cmos_data[RTC_REG_B] = data;
231
            }
232
            rtc_timer_update(s, qemu_get_clock_ns(rtc_clock));
233
            break;
234
        case RTC_REG_C:
235
        case RTC_REG_D:
236
            /* cannot write to them */
237
            break;
238
        default:
239
            s->cmos_data[s->cmos_index] = data;
240
            break;
241
        }
242
    }
243
}
244

    
245
static inline int rtc_to_bcd(RTCState *s, int a)
246
{
247
    if (s->cmos_data[RTC_REG_B] & REG_B_DM) {
248
        return a;
249
    } else {
250
        return ((a / 10) << 4) | (a % 10);
251
    }
252
}
253

    
254
static inline int rtc_from_bcd(RTCState *s, int a)
255
{
256
    if (s->cmos_data[RTC_REG_B] & REG_B_DM) {
257
        return a;
258
    } else {
259
        return ((a >> 4) * 10) + (a & 0x0f);
260
    }
261
}
262

    
263
static void rtc_set_time(RTCState *s)
264
{
265
    struct tm *tm = &s->current_tm;
266

    
267
    tm->tm_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS]);
268
    tm->tm_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES]);
269
    tm->tm_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
270
    if (!(s->cmos_data[RTC_REG_B] & REG_B_24H)) {
271
        tm->tm_hour %= 12;
272
        if (s->cmos_data[RTC_HOURS] & 0x80) {
273
            tm->tm_hour += 12;
274
        }
275
    }
276
    tm->tm_wday = rtc_from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]) - 1;
277
    tm->tm_mday = rtc_from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
278
    tm->tm_mon = rtc_from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
279
    tm->tm_year = rtc_from_bcd(s, s->cmos_data[RTC_YEAR]) + s->base_year - 1900;
280

    
281
    rtc_change_mon_event(tm);
282
}
283

    
284
static void rtc_copy_date(RTCState *s)
285
{
286
    const struct tm *tm = &s->current_tm;
287
    int year;
288

    
289
    s->cmos_data[RTC_SECONDS] = rtc_to_bcd(s, tm->tm_sec);
290
    s->cmos_data[RTC_MINUTES] = rtc_to_bcd(s, tm->tm_min);
291
    if (s->cmos_data[RTC_REG_B] & REG_B_24H) {
292
        /* 24 hour format */
293
        s->cmos_data[RTC_HOURS] = rtc_to_bcd(s, tm->tm_hour);
294
    } else {
295
        /* 12 hour format */
296
        int h = (tm->tm_hour % 12) ? tm->tm_hour % 12 : 12;
297
        s->cmos_data[RTC_HOURS] = rtc_to_bcd(s, h);
298
        if (tm->tm_hour >= 12)
299
            s->cmos_data[RTC_HOURS] |= 0x80;
300
    }
301
    s->cmos_data[RTC_DAY_OF_WEEK] = rtc_to_bcd(s, tm->tm_wday + 1);
302
    s->cmos_data[RTC_DAY_OF_MONTH] = rtc_to_bcd(s, tm->tm_mday);
303
    s->cmos_data[RTC_MONTH] = rtc_to_bcd(s, tm->tm_mon + 1);
304
    year = (tm->tm_year - s->base_year) % 100;
305
    if (year < 0)
306
        year += 100;
307
    s->cmos_data[RTC_YEAR] = rtc_to_bcd(s, year);
308
}
309

    
310
/* month is between 0 and 11. */
311
static int get_days_in_month(int month, int year)
312
{
313
    static const int days_tab[12] = {
314
        31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
315
    };
316
    int d;
317
    if ((unsigned )month >= 12)
318
        return 31;
319
    d = days_tab[month];
320
    if (month == 1) {
321
        if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0))
322
            d++;
323
    }
324
    return d;
325
}
326

    
327
/* update 'tm' to the next second */
328
static void rtc_next_second(struct tm *tm)
329
{
330
    int days_in_month;
331

    
332
    tm->tm_sec++;
333
    if ((unsigned)tm->tm_sec >= 60) {
334
        tm->tm_sec = 0;
335
        tm->tm_min++;
336
        if ((unsigned)tm->tm_min >= 60) {
337
            tm->tm_min = 0;
338
            tm->tm_hour++;
339
            if ((unsigned)tm->tm_hour >= 24) {
340
                tm->tm_hour = 0;
341
                /* next day */
342
                tm->tm_wday++;
343
                if ((unsigned)tm->tm_wday >= 7)
344
                    tm->tm_wday = 0;
345
                days_in_month = get_days_in_month(tm->tm_mon,
346
                                                  tm->tm_year + 1900);
347
                tm->tm_mday++;
348
                if (tm->tm_mday < 1) {
349
                    tm->tm_mday = 1;
350
                } else if (tm->tm_mday > days_in_month) {
351
                    tm->tm_mday = 1;
352
                    tm->tm_mon++;
353
                    if (tm->tm_mon >= 12) {
354
                        tm->tm_mon = 0;
355
                        tm->tm_year++;
356
                    }
357
                }
358
            }
359
        }
360
    }
361
}
362

    
363

    
364
static void rtc_update_second(void *opaque)
365
{
366
    RTCState *s = opaque;
367
    int64_t delay;
368

    
369
    /* if the oscillator is not in normal operation, we do not update */
370
    if ((s->cmos_data[RTC_REG_A] & 0x70) != 0x20) {
371
        s->next_second_time += get_ticks_per_sec();
372
        qemu_mod_timer(s->second_timer, s->next_second_time);
373
    } else {
374
        rtc_next_second(&s->current_tm);
375

    
376
        if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
377
            /* update in progress bit */
378
            s->cmos_data[RTC_REG_A] |= REG_A_UIP;
379
        }
380
        /* should be 244 us = 8 / 32768 seconds, but currently the
381
           timers do not have the necessary resolution. */
382
        delay = (get_ticks_per_sec() * 1) / 100;
383
        if (delay < 1)
384
            delay = 1;
385
        qemu_mod_timer(s->second_timer2,
386
                       s->next_second_time + delay);
387
    }
388
}
389

    
390
static void rtc_update_second2(void *opaque)
391
{
392
    RTCState *s = opaque;
393

    
394
    if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
395
        rtc_copy_date(s);
396
    }
397

    
398
    /* check alarm */
399
    if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 ||
400
         rtc_from_bcd(s, s->cmos_data[RTC_SECONDS_ALARM]) == s->current_tm.tm_sec) &&
401
        ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 ||
402
         rtc_from_bcd(s, s->cmos_data[RTC_MINUTES_ALARM]) == s->current_tm.tm_min) &&
403
        ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 ||
404
         rtc_from_bcd(s, s->cmos_data[RTC_HOURS_ALARM]) == s->current_tm.tm_hour)) {
405

    
406
        s->cmos_data[RTC_REG_C] |= REG_C_AF;
407
        if (s->cmos_data[RTC_REG_B] & REG_B_AIE) {
408
            qemu_system_wakeup_request(QEMU_WAKEUP_REASON_RTC);
409
            qemu_irq_raise(s->irq);
410
            s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
411
        }
412
    }
413

    
414
    /* update ended interrupt */
415
    s->cmos_data[RTC_REG_C] |= REG_C_UF;
416
    if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
417
        s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
418
        qemu_irq_raise(s->irq);
419
    }
420

    
421
    /* clear update in progress bit */
422
    s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
423

    
424
    s->next_second_time += get_ticks_per_sec();
425
    qemu_mod_timer(s->second_timer, s->next_second_time);
426
}
427

    
428
static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
429
{
430
    RTCState *s = opaque;
431
    int ret;
432
    if ((addr & 1) == 0) {
433
        return 0xff;
434
    } else {
435
        switch(s->cmos_index) {
436
        case RTC_SECONDS:
437
        case RTC_MINUTES:
438
        case RTC_HOURS:
439
        case RTC_DAY_OF_WEEK:
440
        case RTC_DAY_OF_MONTH:
441
        case RTC_MONTH:
442
        case RTC_YEAR:
443
            ret = s->cmos_data[s->cmos_index];
444
            break;
445
        case RTC_REG_A:
446
            ret = s->cmos_data[s->cmos_index];
447
            break;
448
        case RTC_REG_C:
449
            ret = s->cmos_data[s->cmos_index];
450
            qemu_irq_lower(s->irq);
451
            s->cmos_data[RTC_REG_C] = 0x00;
452
#ifdef TARGET_I386
453
            if(s->irq_coalesced &&
454
                    (s->cmos_data[RTC_REG_B] & REG_B_PIE) &&
455
                    s->irq_reinject_on_ack_count < RTC_REINJECT_ON_ACK_COUNT) {
456
                s->irq_reinject_on_ack_count++;
457
                s->cmos_data[RTC_REG_C] |= REG_C_IRQF | REG_C_PF;
458
                apic_reset_irq_delivered();
459
                DPRINTF_C("cmos: injecting on ack\n");
460
                qemu_irq_raise(s->irq);
461
                if (apic_get_irq_delivered()) {
462
                    s->irq_coalesced--;
463
                    DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
464
                              s->irq_coalesced);
465
                }
466
            }
467
#endif
468
            break;
469
        default:
470
            ret = s->cmos_data[s->cmos_index];
471
            break;
472
        }
473
        CMOS_DPRINTF("cmos: read index=0x%02x val=0x%02x\n",
474
                     s->cmos_index, ret);
475
        return ret;
476
    }
477
}
478

    
479
void rtc_set_memory(ISADevice *dev, int addr, int val)
480
{
481
    RTCState *s = DO_UPCAST(RTCState, dev, dev);
482
    if (addr >= 0 && addr <= 127)
483
        s->cmos_data[addr] = val;
484
}
485

    
486
void rtc_set_date(ISADevice *dev, const struct tm *tm)
487
{
488
    RTCState *s = DO_UPCAST(RTCState, dev, dev);
489
    s->current_tm = *tm;
490
    rtc_copy_date(s);
491
}
492

    
493
/* PC cmos mappings */
494
#define REG_IBM_CENTURY_BYTE        0x32
495
#define REG_IBM_PS2_CENTURY_BYTE    0x37
496

    
497
static void rtc_set_date_from_host(ISADevice *dev)
498
{
499
    RTCState *s = DO_UPCAST(RTCState, dev, dev);
500
    struct tm tm;
501
    int val;
502

    
503
    /* set the CMOS date */
504
    qemu_get_timedate(&tm, 0);
505
    rtc_set_date(dev, &tm);
506

    
507
    val = rtc_to_bcd(s, (tm.tm_year / 100) + 19);
508
    rtc_set_memory(dev, REG_IBM_CENTURY_BYTE, val);
509
    rtc_set_memory(dev, REG_IBM_PS2_CENTURY_BYTE, val);
510
}
511

    
512
static int rtc_post_load(void *opaque, int version_id)
513
{
514
#ifdef TARGET_I386
515
    RTCState *s = opaque;
516

    
517
    if (version_id >= 2) {
518
        if (s->lost_tick_policy == LOST_TICK_SLEW) {
519
            rtc_coalesced_timer_update(s);
520
        }
521
    }
522
#endif
523
    return 0;
524
}
525

    
526
static const VMStateDescription vmstate_rtc = {
527
    .name = "mc146818rtc",
528
    .version_id = 2,
529
    .minimum_version_id = 1,
530
    .minimum_version_id_old = 1,
531
    .post_load = rtc_post_load,
532
    .fields      = (VMStateField []) {
533
        VMSTATE_BUFFER(cmos_data, RTCState),
534
        VMSTATE_UINT8(cmos_index, RTCState),
535
        VMSTATE_INT32(current_tm.tm_sec, RTCState),
536
        VMSTATE_INT32(current_tm.tm_min, RTCState),
537
        VMSTATE_INT32(current_tm.tm_hour, RTCState),
538
        VMSTATE_INT32(current_tm.tm_wday, RTCState),
539
        VMSTATE_INT32(current_tm.tm_mday, RTCState),
540
        VMSTATE_INT32(current_tm.tm_mon, RTCState),
541
        VMSTATE_INT32(current_tm.tm_year, RTCState),
542
        VMSTATE_TIMER(periodic_timer, RTCState),
543
        VMSTATE_INT64(next_periodic_time, RTCState),
544
        VMSTATE_INT64(next_second_time, RTCState),
545
        VMSTATE_TIMER(second_timer, RTCState),
546
        VMSTATE_TIMER(second_timer2, RTCState),
547
        VMSTATE_UINT32_V(irq_coalesced, RTCState, 2),
548
        VMSTATE_UINT32_V(period, RTCState, 2),
549
        VMSTATE_END_OF_LIST()
550
    }
551
};
552

    
553
static void rtc_notify_clock_reset(Notifier *notifier, void *data)
554
{
555
    RTCState *s = container_of(notifier, RTCState, clock_reset_notifier);
556
    int64_t now = *(int64_t *)data;
557

    
558
    rtc_set_date_from_host(&s->dev);
559
    s->next_second_time = now + (get_ticks_per_sec() * 99) / 100;
560
    qemu_mod_timer(s->second_timer2, s->next_second_time);
561
    rtc_timer_update(s, now);
562
#ifdef TARGET_I386
563
    if (s->lost_tick_policy == LOST_TICK_SLEW) {
564
        rtc_coalesced_timer_update(s);
565
    }
566
#endif
567
}
568

    
569
/* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
570
   BIOS will read it and start S3 resume at POST Entry */
571
static void rtc_notify_suspend(Notifier *notifier, void *data)
572
{
573
    RTCState *s = container_of(notifier, RTCState, suspend_notifier);
574
    rtc_set_memory(&s->dev, 0xF, 0xFE);
575
}
576

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

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

    
584
    qemu_irq_lower(s->irq);
585

    
586
#ifdef TARGET_I386
587
    if (s->lost_tick_policy == LOST_TICK_SLEW) {
588
        s->irq_coalesced = 0;
589
    }
590
#endif
591
}
592

    
593
static const MemoryRegionPortio cmos_portio[] = {
594
    {0, 2, 1, .read = cmos_ioport_read, .write = cmos_ioport_write },
595
    PORTIO_END_OF_LIST(),
596
};
597

    
598
static const MemoryRegionOps cmos_ops = {
599
    .old_portio = cmos_portio
600
};
601

    
602
// FIXME add int32 visitor
603
static void visit_type_int32(Visitor *v, int *value, const char *name, Error **errp)
604
{
605
    int64_t val = *value;
606
    visit_type_int(v, &val, name, errp);
607
}
608

    
609
static void rtc_get_date(Object *obj, Visitor *v, void *opaque,
610
                         const char *name, Error **errp)
611
{
612
    ISADevice *isa = ISA_DEVICE(obj);
613
    RTCState *s = DO_UPCAST(RTCState, dev, isa);
614

    
615
    visit_start_struct(v, NULL, "struct tm", name, 0, errp);
616
    visit_type_int32(v, &s->current_tm.tm_year, "tm_year", errp);
617
    visit_type_int32(v, &s->current_tm.tm_mon, "tm_mon", errp);
618
    visit_type_int32(v, &s->current_tm.tm_mday, "tm_mday", errp);
619
    visit_type_int32(v, &s->current_tm.tm_hour, "tm_hour", errp);
620
    visit_type_int32(v, &s->current_tm.tm_min, "tm_min", errp);
621
    visit_type_int32(v, &s->current_tm.tm_sec, "tm_sec", errp);
622
    visit_end_struct(v, errp);
623
}
624

    
625
static int rtc_initfn(ISADevice *dev)
626
{
627
    RTCState *s = DO_UPCAST(RTCState, dev, dev);
628
    int base = 0x70;
629

    
630
    s->cmos_data[RTC_REG_A] = 0x26;
631
    s->cmos_data[RTC_REG_B] = 0x02;
632
    s->cmos_data[RTC_REG_C] = 0x00;
633
    s->cmos_data[RTC_REG_D] = 0x80;
634

    
635
    rtc_set_date_from_host(dev);
636

    
637
#ifdef TARGET_I386
638
    switch (s->lost_tick_policy) {
639
    case LOST_TICK_SLEW:
640
        s->coalesced_timer =
641
            qemu_new_timer_ns(rtc_clock, rtc_coalesced_timer, s);
642
        break;
643
    case LOST_TICK_DISCARD:
644
        break;
645
    default:
646
        return -EINVAL;
647
    }
648
#endif
649

    
650
    s->periodic_timer = qemu_new_timer_ns(rtc_clock, rtc_periodic_timer, s);
651
    s->second_timer = qemu_new_timer_ns(rtc_clock, rtc_update_second, s);
652
    s->second_timer2 = qemu_new_timer_ns(rtc_clock, rtc_update_second2, s);
653

    
654
    s->clock_reset_notifier.notify = rtc_notify_clock_reset;
655
    qemu_register_clock_reset_notifier(rtc_clock, &s->clock_reset_notifier);
656

    
657
    s->suspend_notifier.notify = rtc_notify_suspend;
658
    qemu_register_suspend_notifier(&s->suspend_notifier);
659

    
660
    s->next_second_time =
661
        qemu_get_clock_ns(rtc_clock) + (get_ticks_per_sec() * 99) / 100;
662
    qemu_mod_timer(s->second_timer2, s->next_second_time);
663

    
664
    memory_region_init_io(&s->io, &cmos_ops, s, "rtc", 2);
665
    isa_register_ioport(dev, &s->io, base);
666

    
667
    qdev_set_legacy_instance_id(&dev->qdev, base, 2);
668
    qemu_register_reset(rtc_reset, s);
669

    
670
    object_property_add(OBJECT(s), "date", "struct tm",
671
                        rtc_get_date, NULL, NULL, s, NULL);
672

    
673
    return 0;
674
}
675

    
676
ISADevice *rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq)
677
{
678
    ISADevice *dev;
679
    RTCState *s;
680

    
681
    dev = isa_create(bus, "mc146818rtc");
682
    s = DO_UPCAST(RTCState, dev, dev);
683
    qdev_prop_set_int32(&dev->qdev, "base_year", base_year);
684
    qdev_init_nofail(&dev->qdev);
685
    if (intercept_irq) {
686
        s->irq = intercept_irq;
687
    } else {
688
        isa_init_irq(dev, &s->irq, RTC_ISA_IRQ);
689
    }
690
    return dev;
691
}
692

    
693
static Property mc146818rtc_properties[] = {
694
    DEFINE_PROP_INT32("base_year", RTCState, base_year, 1980),
695
    DEFINE_PROP_LOSTTICKPOLICY("lost_tick_policy", RTCState,
696
                               lost_tick_policy, LOST_TICK_DISCARD),
697
    DEFINE_PROP_END_OF_LIST(),
698
};
699

    
700
static void rtc_class_initfn(ObjectClass *klass, void *data)
701
{
702
    DeviceClass *dc = DEVICE_CLASS(klass);
703
    ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
704
    ic->init = rtc_initfn;
705
    dc->no_user = 1;
706
    dc->vmsd = &vmstate_rtc;
707
    dc->props = mc146818rtc_properties;
708
}
709

    
710
static TypeInfo mc146818rtc_info = {
711
    .name          = "mc146818rtc",
712
    .parent        = TYPE_ISA_DEVICE,
713
    .instance_size = sizeof(RTCState),
714
    .class_init    = rtc_class_initfn,
715
};
716

    
717
static void mc146818rtc_register_types(void)
718
{
719
    type_register_static(&mc146818rtc_info);
720
}
721

    
722
type_init(mc146818rtc_register_types)