~ahs3/+junk/cq-qemu

« back to all changes in this revision

Viewing changes to hw/mc146818rtc.c

  • Committer: Al Stone
  • Date: 2012-02-09 01:17:20 UTC
  • Revision ID: albert.stone@canonical.com-20120209011720-tztl7ik3qayz80p4
first commit to bzr for qemu

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "apic.h"
 
29
#include "isa.h"
 
30
#include "mc146818rtc.h"
 
31
 
 
32
//#define DEBUG_CMOS
 
33
//#define DEBUG_COALESCED
 
34
 
 
35
#ifdef DEBUG_CMOS
 
36
# define CMOS_DPRINTF(format, ...)      printf(format, ## __VA_ARGS__)
 
37
#else
 
38
# define CMOS_DPRINTF(format, ...)      do { } while (0)
 
39
#endif
 
40
 
 
41
#ifdef DEBUG_COALESCED
 
42
# define DPRINTF_C(format, ...)      printf(format, ## __VA_ARGS__)
 
43
#else
 
44
# define DPRINTF_C(format, ...)      do { } while (0)
 
45
#endif
 
46
 
 
47
#define RTC_REINJECT_ON_ACK_COUNT 20
 
48
 
 
49
#define RTC_SECONDS             0
 
50
#define RTC_SECONDS_ALARM       1
 
51
#define RTC_MINUTES             2
 
52
#define RTC_MINUTES_ALARM       3
 
53
#define RTC_HOURS               4
 
54
#define RTC_HOURS_ALARM         5
 
55
#define RTC_ALARM_DONT_CARE    0xC0
 
56
 
 
57
#define RTC_DAY_OF_WEEK         6
 
58
#define RTC_DAY_OF_MONTH        7
 
59
#define RTC_MONTH               8
 
60
#define RTC_YEAR                9
 
61
 
 
62
#define RTC_REG_A               10
 
63
#define RTC_REG_B               11
 
64
#define RTC_REG_C               12
 
65
#define RTC_REG_D               13
 
66
 
 
67
#define REG_A_UIP 0x80
 
68
 
 
69
#define REG_B_SET  0x80
 
70
#define REG_B_PIE  0x40
 
71
#define REG_B_AIE  0x20
 
72
#define REG_B_UIE  0x10
 
73
#define REG_B_SQWE 0x08
 
74
#define REG_B_DM   0x04
 
75
#define REG_B_24H  0x02
 
76
 
 
77
#define REG_C_UF   0x10
 
78
#define REG_C_IRQF 0x80
 
79
#define REG_C_PF   0x40
 
80
#define REG_C_AF   0x20
 
81
 
 
82
typedef struct RTCState {
 
83
    ISADevice dev;
 
84
    MemoryRegion io;
 
85
    uint8_t cmos_data[128];
 
86
    uint8_t cmos_index;
 
87
    struct tm current_tm;
 
88
    int32_t base_year;
 
89
    qemu_irq irq;
 
90
    qemu_irq sqw_irq;
 
91
    int it_shift;
 
92
    /* periodic timer */
 
93
    QEMUTimer *periodic_timer;
 
94
    int64_t next_periodic_time;
 
95
    /* second update */
 
96
    int64_t next_second_time;
 
97
    uint16_t irq_reinject_on_ack_count;
 
98
    uint32_t irq_coalesced;
 
99
    uint32_t period;
 
100
    QEMUTimer *coalesced_timer;
 
101
    QEMUTimer *second_timer;
 
102
    QEMUTimer *second_timer2;
 
103
    Notifier clock_reset_notifier;
 
104
} RTCState;
 
105
 
 
106
static void rtc_set_time(RTCState *s);
 
107
static void rtc_copy_date(RTCState *s);
 
108
 
 
109
#ifdef TARGET_I386
 
110
static void rtc_coalesced_timer_update(RTCState *s)
 
111
{
 
112
    if (s->irq_coalesced == 0) {
 
113
        qemu_del_timer(s->coalesced_timer);
 
114
    } else {
 
115
        /* divide each RTC interval to 2 - 8 smaller intervals */
 
116
        int c = MIN(s->irq_coalesced, 7) + 1; 
 
117
        int64_t next_clock = qemu_get_clock_ns(rtc_clock) +
 
118
            muldiv64(s->period / c, get_ticks_per_sec(), 32768);
 
119
        qemu_mod_timer(s->coalesced_timer, next_clock);
 
120
    }
 
121
}
 
122
 
 
123
static void rtc_coalesced_timer(void *opaque)
 
124
{
 
125
    RTCState *s = opaque;
 
126
 
 
127
    if (s->irq_coalesced != 0) {
 
128
        apic_reset_irq_delivered();
 
129
        s->cmos_data[RTC_REG_C] |= 0xc0;
 
130
        DPRINTF_C("cmos: injecting from timer\n");
 
131
        qemu_irq_raise(s->irq);
 
132
        if (apic_get_irq_delivered()) {
 
133
            s->irq_coalesced--;
 
134
            DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
 
135
                      s->irq_coalesced);
 
136
        }
 
137
    }
 
138
 
 
139
    rtc_coalesced_timer_update(s);
 
140
}
 
141
#endif
 
142
 
 
143
static void rtc_timer_update(RTCState *s, int64_t current_time)
 
144
{
 
145
    int period_code, period;
 
146
    int64_t cur_clock, next_irq_clock;
 
147
 
 
148
    period_code = s->cmos_data[RTC_REG_A] & 0x0f;
 
149
    if (period_code != 0
 
150
        && ((s->cmos_data[RTC_REG_B] & REG_B_PIE)
 
151
            || ((s->cmos_data[RTC_REG_B] & REG_B_SQWE) && s->sqw_irq))) {
 
152
        if (period_code <= 2)
 
153
            period_code += 7;
 
154
        /* period in 32 Khz cycles */
 
155
        period = 1 << (period_code - 1);
 
156
#ifdef TARGET_I386
 
157
        if (period != s->period) {
 
158
            s->irq_coalesced = (s->irq_coalesced * s->period) / period;
 
159
            DPRINTF_C("cmos: coalesced irqs scaled to %d\n", s->irq_coalesced);
 
160
        }
 
161
        s->period = period;
 
162
#endif
 
163
        /* compute 32 khz clock */
 
164
        cur_clock = muldiv64(current_time, 32768, get_ticks_per_sec());
 
165
        next_irq_clock = (cur_clock & ~(period - 1)) + period;
 
166
        s->next_periodic_time =
 
167
            muldiv64(next_irq_clock, get_ticks_per_sec(), 32768) + 1;
 
168
        qemu_mod_timer(s->periodic_timer, s->next_periodic_time);
 
169
    } else {
 
170
#ifdef TARGET_I386
 
171
        s->irq_coalesced = 0;
 
172
#endif
 
173
        qemu_del_timer(s->periodic_timer);
 
174
    }
 
175
}
 
176
 
 
177
static void rtc_periodic_timer(void *opaque)
 
178
{
 
179
    RTCState *s = opaque;
 
180
 
 
181
    rtc_timer_update(s, s->next_periodic_time);
 
182
    if (s->cmos_data[RTC_REG_B] & REG_B_PIE) {
 
183
        s->cmos_data[RTC_REG_C] |= 0xc0;
 
184
#ifdef TARGET_I386
 
185
        if(rtc_td_hack) {
 
186
            if (s->irq_reinject_on_ack_count >= RTC_REINJECT_ON_ACK_COUNT)
 
187
                s->irq_reinject_on_ack_count = 0;               
 
188
            apic_reset_irq_delivered();
 
189
            qemu_irq_raise(s->irq);
 
190
            if (!apic_get_irq_delivered()) {
 
191
                s->irq_coalesced++;
 
192
                rtc_coalesced_timer_update(s);
 
193
                DPRINTF_C("cmos: coalesced irqs increased to %d\n",
 
194
                          s->irq_coalesced);
 
195
            }
 
196
        } else
 
197
#endif
 
198
        qemu_irq_raise(s->irq);
 
199
    }
 
200
    if (s->cmos_data[RTC_REG_B] & REG_B_SQWE) {
 
201
        /* Not square wave at all but we don't want 2048Hz interrupts!
 
202
           Must be seen as a pulse.  */
 
203
        qemu_irq_raise(s->sqw_irq);
 
204
    }
 
205
}
 
206
 
 
207
static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
 
208
{
 
209
    RTCState *s = opaque;
 
210
 
 
211
    if ((addr & 1) == 0) {
 
212
        s->cmos_index = data & 0x7f;
 
213
    } else {
 
214
        CMOS_DPRINTF("cmos: write index=0x%02x val=0x%02x\n",
 
215
                     s->cmos_index, data);
 
216
        switch(s->cmos_index) {
 
217
        case RTC_SECONDS_ALARM:
 
218
        case RTC_MINUTES_ALARM:
 
219
        case RTC_HOURS_ALARM:
 
220
            s->cmos_data[s->cmos_index] = data;
 
221
            break;
 
222
        case RTC_SECONDS:
 
223
        case RTC_MINUTES:
 
224
        case RTC_HOURS:
 
225
        case RTC_DAY_OF_WEEK:
 
226
        case RTC_DAY_OF_MONTH:
 
227
        case RTC_MONTH:
 
228
        case RTC_YEAR:
 
229
            s->cmos_data[s->cmos_index] = data;
 
230
            /* if in set mode, do not update the time */
 
231
            if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
 
232
                rtc_set_time(s);
 
233
            }
 
234
            break;
 
235
        case RTC_REG_A:
 
236
            /* UIP bit is read only */
 
237
            s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
 
238
                (s->cmos_data[RTC_REG_A] & REG_A_UIP);
 
239
            rtc_timer_update(s, qemu_get_clock_ns(rtc_clock));
 
240
            break;
 
241
        case RTC_REG_B:
 
242
            if (data & REG_B_SET) {
 
243
                /* set mode: reset UIP mode */
 
244
                s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
 
245
                data &= ~REG_B_UIE;
 
246
            } else {
 
247
                /* if disabling set mode, update the time */
 
248
                if (s->cmos_data[RTC_REG_B] & REG_B_SET) {
 
249
                    rtc_set_time(s);
 
250
                }
 
251
            }
 
252
            if (((s->cmos_data[RTC_REG_B] ^ data) & (REG_B_DM | REG_B_24H)) &&
 
253
                !(data & REG_B_SET)) {
 
254
                /* If the time format has changed and not in set mode,
 
255
                   update the registers immediately. */
 
256
                s->cmos_data[RTC_REG_B] = data;
 
257
                rtc_copy_date(s);
 
258
            } else {
 
259
                s->cmos_data[RTC_REG_B] = data;
 
260
            }
 
261
            rtc_timer_update(s, qemu_get_clock_ns(rtc_clock));
 
262
            break;
 
263
        case RTC_REG_C:
 
264
        case RTC_REG_D:
 
265
            /* cannot write to them */
 
266
            break;
 
267
        default:
 
268
            s->cmos_data[s->cmos_index] = data;
 
269
            break;
 
270
        }
 
271
    }
 
272
}
 
273
 
 
274
static inline int rtc_to_bcd(RTCState *s, int a)
 
275
{
 
276
    if (s->cmos_data[RTC_REG_B] & REG_B_DM) {
 
277
        return a;
 
278
    } else {
 
279
        return ((a / 10) << 4) | (a % 10);
 
280
    }
 
281
}
 
282
 
 
283
static inline int rtc_from_bcd(RTCState *s, int a)
 
284
{
 
285
    if (s->cmos_data[RTC_REG_B] & REG_B_DM) {
 
286
        return a;
 
287
    } else {
 
288
        return ((a >> 4) * 10) + (a & 0x0f);
 
289
    }
 
290
}
 
291
 
 
292
static void rtc_set_time(RTCState *s)
 
293
{
 
294
    struct tm *tm = &s->current_tm;
 
295
 
 
296
    tm->tm_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS]);
 
297
    tm->tm_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES]);
 
298
    tm->tm_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
 
299
    if (!(s->cmos_data[RTC_REG_B] & REG_B_24H) &&
 
300
        (s->cmos_data[RTC_HOURS] & 0x80)) {
 
301
        tm->tm_hour += 12;
 
302
    }
 
303
    tm->tm_wday = rtc_from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]) - 1;
 
304
    tm->tm_mday = rtc_from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
 
305
    tm->tm_mon = rtc_from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
 
306
    tm->tm_year = rtc_from_bcd(s, s->cmos_data[RTC_YEAR]) + s->base_year - 1900;
 
307
 
 
308
    rtc_change_mon_event(tm);
 
309
}
 
310
 
 
311
static void rtc_copy_date(RTCState *s)
 
312
{
 
313
    const struct tm *tm = &s->current_tm;
 
314
    int year;
 
315
 
 
316
    s->cmos_data[RTC_SECONDS] = rtc_to_bcd(s, tm->tm_sec);
 
317
    s->cmos_data[RTC_MINUTES] = rtc_to_bcd(s, tm->tm_min);
 
318
    if (s->cmos_data[RTC_REG_B] & REG_B_24H) {
 
319
        /* 24 hour format */
 
320
        s->cmos_data[RTC_HOURS] = rtc_to_bcd(s, tm->tm_hour);
 
321
    } else {
 
322
        /* 12 hour format */
 
323
        s->cmos_data[RTC_HOURS] = rtc_to_bcd(s, tm->tm_hour % 12);
 
324
        if (tm->tm_hour >= 12)
 
325
            s->cmos_data[RTC_HOURS] |= 0x80;
 
326
    }
 
327
    s->cmos_data[RTC_DAY_OF_WEEK] = rtc_to_bcd(s, tm->tm_wday + 1);
 
328
    s->cmos_data[RTC_DAY_OF_MONTH] = rtc_to_bcd(s, tm->tm_mday);
 
329
    s->cmos_data[RTC_MONTH] = rtc_to_bcd(s, tm->tm_mon + 1);
 
330
    year = (tm->tm_year - s->base_year) % 100;
 
331
    if (year < 0)
 
332
        year += 100;
 
333
    s->cmos_data[RTC_YEAR] = rtc_to_bcd(s, year);
 
334
}
 
335
 
 
336
/* month is between 0 and 11. */
 
337
static int get_days_in_month(int month, int year)
 
338
{
 
339
    static const int days_tab[12] = {
 
340
        31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
 
341
    };
 
342
    int d;
 
343
    if ((unsigned )month >= 12)
 
344
        return 31;
 
345
    d = days_tab[month];
 
346
    if (month == 1) {
 
347
        if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0))
 
348
            d++;
 
349
    }
 
350
    return d;
 
351
}
 
352
 
 
353
/* update 'tm' to the next second */
 
354
static void rtc_next_second(struct tm *tm)
 
355
{
 
356
    int days_in_month;
 
357
 
 
358
    tm->tm_sec++;
 
359
    if ((unsigned)tm->tm_sec >= 60) {
 
360
        tm->tm_sec = 0;
 
361
        tm->tm_min++;
 
362
        if ((unsigned)tm->tm_min >= 60) {
 
363
            tm->tm_min = 0;
 
364
            tm->tm_hour++;
 
365
            if ((unsigned)tm->tm_hour >= 24) {
 
366
                tm->tm_hour = 0;
 
367
                /* next day */
 
368
                tm->tm_wday++;
 
369
                if ((unsigned)tm->tm_wday >= 7)
 
370
                    tm->tm_wday = 0;
 
371
                days_in_month = get_days_in_month(tm->tm_mon,
 
372
                                                  tm->tm_year + 1900);
 
373
                tm->tm_mday++;
 
374
                if (tm->tm_mday < 1) {
 
375
                    tm->tm_mday = 1;
 
376
                } else if (tm->tm_mday > days_in_month) {
 
377
                    tm->tm_mday = 1;
 
378
                    tm->tm_mon++;
 
379
                    if (tm->tm_mon >= 12) {
 
380
                        tm->tm_mon = 0;
 
381
                        tm->tm_year++;
 
382
                    }
 
383
                }
 
384
            }
 
385
        }
 
386
    }
 
387
}
 
388
 
 
389
 
 
390
static void rtc_update_second(void *opaque)
 
391
{
 
392
    RTCState *s = opaque;
 
393
    int64_t delay;
 
394
 
 
395
    /* if the oscillator is not in normal operation, we do not update */
 
396
    if ((s->cmos_data[RTC_REG_A] & 0x70) != 0x20) {
 
397
        s->next_second_time += get_ticks_per_sec();
 
398
        qemu_mod_timer(s->second_timer, s->next_second_time);
 
399
    } else {
 
400
        rtc_next_second(&s->current_tm);
 
401
 
 
402
        if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
 
403
            /* update in progress bit */
 
404
            s->cmos_data[RTC_REG_A] |= REG_A_UIP;
 
405
        }
 
406
        /* should be 244 us = 8 / 32768 seconds, but currently the
 
407
           timers do not have the necessary resolution. */
 
408
        delay = (get_ticks_per_sec() * 1) / 100;
 
409
        if (delay < 1)
 
410
            delay = 1;
 
411
        qemu_mod_timer(s->second_timer2,
 
412
                       s->next_second_time + delay);
 
413
    }
 
414
}
 
415
 
 
416
static void rtc_update_second2(void *opaque)
 
417
{
 
418
    RTCState *s = opaque;
 
419
 
 
420
    if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
 
421
        rtc_copy_date(s);
 
422
    }
 
423
 
 
424
    /* check alarm */
 
425
    if (s->cmos_data[RTC_REG_B] & REG_B_AIE) {
 
426
        if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 ||
 
427
             rtc_from_bcd(s, s->cmos_data[RTC_SECONDS_ALARM]) == s->current_tm.tm_sec) &&
 
428
            ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 ||
 
429
             rtc_from_bcd(s, s->cmos_data[RTC_MINUTES_ALARM]) == s->current_tm.tm_min) &&
 
430
            ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 ||
 
431
             rtc_from_bcd(s, s->cmos_data[RTC_HOURS_ALARM]) == s->current_tm.tm_hour)) {
 
432
 
 
433
            s->cmos_data[RTC_REG_C] |= 0xa0;
 
434
            qemu_irq_raise(s->irq);
 
435
        }
 
436
    }
 
437
 
 
438
    /* update ended interrupt */
 
439
    s->cmos_data[RTC_REG_C] |= REG_C_UF;
 
440
    if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
 
441
        s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
 
442
        qemu_irq_raise(s->irq);
 
443
    }
 
444
 
 
445
    /* clear update in progress bit */
 
446
    s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
 
447
 
 
448
    s->next_second_time += get_ticks_per_sec();
 
449
    qemu_mod_timer(s->second_timer, s->next_second_time);
 
450
}
 
451
 
 
452
static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
 
453
{
 
454
    RTCState *s = opaque;
 
455
    int ret;
 
456
    if ((addr & 1) == 0) {
 
457
        return 0xff;
 
458
    } else {
 
459
        switch(s->cmos_index) {
 
460
        case RTC_SECONDS:
 
461
        case RTC_MINUTES:
 
462
        case RTC_HOURS:
 
463
        case RTC_DAY_OF_WEEK:
 
464
        case RTC_DAY_OF_MONTH:
 
465
        case RTC_MONTH:
 
466
        case RTC_YEAR:
 
467
            ret = s->cmos_data[s->cmos_index];
 
468
            break;
 
469
        case RTC_REG_A:
 
470
            ret = s->cmos_data[s->cmos_index];
 
471
            break;
 
472
        case RTC_REG_C:
 
473
            ret = s->cmos_data[s->cmos_index];
 
474
            qemu_irq_lower(s->irq);
 
475
#ifdef TARGET_I386
 
476
            if(s->irq_coalesced &&
 
477
                    s->irq_reinject_on_ack_count < RTC_REINJECT_ON_ACK_COUNT) {
 
478
                s->irq_reinject_on_ack_count++;
 
479
                apic_reset_irq_delivered();
 
480
                DPRINTF_C("cmos: injecting on ack\n");
 
481
                qemu_irq_raise(s->irq);
 
482
                if (apic_get_irq_delivered()) {
 
483
                    s->irq_coalesced--;
 
484
                    DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
 
485
                              s->irq_coalesced);
 
486
                }
 
487
                break;
 
488
            }
 
489
#endif
 
490
 
 
491
            s->cmos_data[RTC_REG_C] = 0x00;
 
492
            break;
 
493
        default:
 
494
            ret = s->cmos_data[s->cmos_index];
 
495
            break;
 
496
        }
 
497
        CMOS_DPRINTF("cmos: read index=0x%02x val=0x%02x\n",
 
498
                     s->cmos_index, ret);
 
499
        return ret;
 
500
    }
 
501
}
 
502
 
 
503
void rtc_set_memory(ISADevice *dev, int addr, int val)
 
504
{
 
505
    RTCState *s = DO_UPCAST(RTCState, dev, dev);
 
506
    if (addr >= 0 && addr <= 127)
 
507
        s->cmos_data[addr] = val;
 
508
}
 
509
 
 
510
void rtc_set_date(ISADevice *dev, const struct tm *tm)
 
511
{
 
512
    RTCState *s = DO_UPCAST(RTCState, dev, dev);
 
513
    s->current_tm = *tm;
 
514
    rtc_copy_date(s);
 
515
}
 
516
 
 
517
/* PC cmos mappings */
 
518
#define REG_IBM_CENTURY_BYTE        0x32
 
519
#define REG_IBM_PS2_CENTURY_BYTE    0x37
 
520
 
 
521
static void rtc_set_date_from_host(ISADevice *dev)
 
522
{
 
523
    RTCState *s = DO_UPCAST(RTCState, dev, dev);
 
524
    struct tm tm;
 
525
    int val;
 
526
 
 
527
    /* set the CMOS date */
 
528
    qemu_get_timedate(&tm, 0);
 
529
    rtc_set_date(dev, &tm);
 
530
 
 
531
    val = rtc_to_bcd(s, (tm.tm_year / 100) + 19);
 
532
    rtc_set_memory(dev, REG_IBM_CENTURY_BYTE, val);
 
533
    rtc_set_memory(dev, REG_IBM_PS2_CENTURY_BYTE, val);
 
534
}
 
535
 
 
536
static int rtc_post_load(void *opaque, int version_id)
 
537
{
 
538
#ifdef TARGET_I386
 
539
    RTCState *s = opaque;
 
540
 
 
541
    if (version_id >= 2) {
 
542
        if (rtc_td_hack) {
 
543
            rtc_coalesced_timer_update(s);
 
544
        }
 
545
    }
 
546
#endif
 
547
    return 0;
 
548
}
 
549
 
 
550
static const VMStateDescription vmstate_rtc = {
 
551
    .name = "mc146818rtc",
 
552
    .version_id = 2,
 
553
    .minimum_version_id = 1,
 
554
    .minimum_version_id_old = 1,
 
555
    .post_load = rtc_post_load,
 
556
    .fields      = (VMStateField []) {
 
557
        VMSTATE_BUFFER(cmos_data, RTCState),
 
558
        VMSTATE_UINT8(cmos_index, RTCState),
 
559
        VMSTATE_INT32(current_tm.tm_sec, RTCState),
 
560
        VMSTATE_INT32(current_tm.tm_min, RTCState),
 
561
        VMSTATE_INT32(current_tm.tm_hour, RTCState),
 
562
        VMSTATE_INT32(current_tm.tm_wday, RTCState),
 
563
        VMSTATE_INT32(current_tm.tm_mday, RTCState),
 
564
        VMSTATE_INT32(current_tm.tm_mon, RTCState),
 
565
        VMSTATE_INT32(current_tm.tm_year, RTCState),
 
566
        VMSTATE_TIMER(periodic_timer, RTCState),
 
567
        VMSTATE_INT64(next_periodic_time, RTCState),
 
568
        VMSTATE_INT64(next_second_time, RTCState),
 
569
        VMSTATE_TIMER(second_timer, RTCState),
 
570
        VMSTATE_TIMER(second_timer2, RTCState),
 
571
        VMSTATE_UINT32_V(irq_coalesced, RTCState, 2),
 
572
        VMSTATE_UINT32_V(period, RTCState, 2),
 
573
        VMSTATE_END_OF_LIST()
 
574
    }
 
575
};
 
576
 
 
577
static void rtc_notify_clock_reset(Notifier *notifier, void *data)
 
578
{
 
579
    RTCState *s = container_of(notifier, RTCState, clock_reset_notifier);
 
580
    int64_t now = *(int64_t *)data;
 
581
 
 
582
    rtc_set_date_from_host(&s->dev);
 
583
    s->next_second_time = now + (get_ticks_per_sec() * 99) / 100;
 
584
    qemu_mod_timer(s->second_timer2, s->next_second_time);
 
585
    rtc_timer_update(s, now);
 
586
#ifdef TARGET_I386
 
587
    if (rtc_td_hack) {
 
588
        rtc_coalesced_timer_update(s);
 
589
    }
 
590
#endif
 
591
}
 
592
 
 
593
static void rtc_reset(void *opaque)
 
594
{
 
595
    RTCState *s = opaque;
 
596
 
 
597
    s->cmos_data[RTC_REG_B] &= ~(REG_B_PIE | REG_B_AIE | REG_B_SQWE);
 
598
    s->cmos_data[RTC_REG_C] &= ~(REG_C_UF | REG_C_IRQF | REG_C_PF | REG_C_AF);
 
599
 
 
600
    qemu_irq_lower(s->irq);
 
601
 
 
602
#ifdef TARGET_I386
 
603
    if (rtc_td_hack)
 
604
            s->irq_coalesced = 0;
 
605
#endif
 
606
}
 
607
 
 
608
static const MemoryRegionPortio cmos_portio[] = {
 
609
    {0, 2, 1, .read = cmos_ioport_read, .write = cmos_ioport_write },
 
610
    PORTIO_END_OF_LIST(),
 
611
};
 
612
 
 
613
static const MemoryRegionOps cmos_ops = {
 
614
    .old_portio = cmos_portio
 
615
};
 
616
 
 
617
static int rtc_initfn(ISADevice *dev)
 
618
{
 
619
    RTCState *s = DO_UPCAST(RTCState, dev, dev);
 
620
    int base = 0x70;
 
621
 
 
622
    s->cmos_data[RTC_REG_A] = 0x26;
 
623
    s->cmos_data[RTC_REG_B] = 0x02;
 
624
    s->cmos_data[RTC_REG_C] = 0x00;
 
625
    s->cmos_data[RTC_REG_D] = 0x80;
 
626
 
 
627
    rtc_set_date_from_host(dev);
 
628
 
 
629
    s->periodic_timer = qemu_new_timer_ns(rtc_clock, rtc_periodic_timer, s);
 
630
#ifdef TARGET_I386
 
631
    if (rtc_td_hack)
 
632
        s->coalesced_timer =
 
633
            qemu_new_timer_ns(rtc_clock, rtc_coalesced_timer, s);
 
634
#endif
 
635
    s->second_timer = qemu_new_timer_ns(rtc_clock, rtc_update_second, s);
 
636
    s->second_timer2 = qemu_new_timer_ns(rtc_clock, rtc_update_second2, s);
 
637
 
 
638
    s->clock_reset_notifier.notify = rtc_notify_clock_reset;
 
639
    qemu_register_clock_reset_notifier(rtc_clock, &s->clock_reset_notifier);
 
640
 
 
641
    s->next_second_time =
 
642
        qemu_get_clock_ns(rtc_clock) + (get_ticks_per_sec() * 99) / 100;
 
643
    qemu_mod_timer(s->second_timer2, s->next_second_time);
 
644
 
 
645
    memory_region_init_io(&s->io, &cmos_ops, s, "rtc", 2);
 
646
    isa_register_ioport(dev, &s->io, base);
 
647
 
 
648
    qdev_set_legacy_instance_id(&dev->qdev, base, 2);
 
649
    qemu_register_reset(rtc_reset, s);
 
650
    return 0;
 
651
}
 
652
 
 
653
ISADevice *rtc_init(int base_year, qemu_irq intercept_irq)
 
654
{
 
655
    ISADevice *dev;
 
656
    RTCState *s;
 
657
 
 
658
    dev = isa_create("mc146818rtc");
 
659
    s = DO_UPCAST(RTCState, dev, dev);
 
660
    qdev_prop_set_int32(&dev->qdev, "base_year", base_year);
 
661
    qdev_init_nofail(&dev->qdev);
 
662
    if (intercept_irq) {
 
663
        s->irq = intercept_irq;
 
664
    } else {
 
665
        isa_init_irq(dev, &s->irq, RTC_ISA_IRQ);
 
666
    }
 
667
    return dev;
 
668
}
 
669
 
 
670
static ISADeviceInfo mc146818rtc_info = {
 
671
    .qdev.name     = "mc146818rtc",
 
672
    .qdev.size     = sizeof(RTCState),
 
673
    .qdev.no_user  = 1,
 
674
    .qdev.vmsd     = &vmstate_rtc,
 
675
    .init          = rtc_initfn,
 
676
    .qdev.props    = (Property[]) {
 
677
        DEFINE_PROP_INT32("base_year", RTCState, base_year, 1980),
 
678
        DEFINE_PROP_END_OF_LIST(),
 
679
    }
 
680
};
 
681
 
 
682
static void mc146818rtc_register(void)
 
683
{
 
684
    isa_qdev_register(&mc146818rtc_info);
 
685
}
 
686
device_init(mc146818rtc_register)