mc146818rtc.c 27.8 KB
Newer Older
B
bellard 已提交
1 2
/*
 * QEMU MC146818 RTC emulation
3
 *
B
bellard 已提交
4
 * Copyright (c) 2003-2004 Fabrice Bellard
5
 *
B
bellard 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
24
#include "hw/hw.h"
25
#include "qemu/timer.h"
26
#include "sysemu/sysemu.h"
P
Paolo Bonzini 已提交
27
#include "hw/timer/mc146818rtc.h"
28
#include "qapi/visitor.h"
B
bellard 已提交
29

30
#ifdef TARGET_I386
P
Paolo Bonzini 已提交
31
#include "hw/i386/apic.h"
32 33
#endif

B
bellard 已提交
34
//#define DEBUG_CMOS
B
Blue Swirl 已提交
35
//#define DEBUG_COALESCED
B
bellard 已提交
36

37 38 39 40 41 42
#ifdef DEBUG_CMOS
# define CMOS_DPRINTF(format, ...)      printf(format, ## __VA_ARGS__)
#else
# define CMOS_DPRINTF(format, ...)      do { } while (0)
#endif

B
Blue Swirl 已提交
43 44 45 46 47 48
#ifdef DEBUG_COALESCED
# define DPRINTF_C(format, ...)      printf(format, ## __VA_ARGS__)
#else
# define DPRINTF_C(format, ...)      do { } while (0)
#endif

49
#define NSEC_PER_SEC    1000000000LL
50 51 52 53 54
#define SEC_PER_MIN     60
#define MIN_PER_HOUR    60
#define SEC_PER_HOUR    3600
#define HOUR_PER_DAY    24
#define SEC_PER_DAY     86400
55

G
Gleb Natapov 已提交
56
#define RTC_REINJECT_ON_ACK_COUNT 20
P
Paolo Bonzini 已提交
57
#define RTC_CLOCK_RATE            32768
58
#define UIP_HOLD_LENGTH           (8 * NSEC_PER_SEC / 32768)
59

60
typedef struct RTCState {
61
    ISADevice dev;
62
    MemoryRegion io;
63 64
    uint8_t cmos_data[128];
    uint8_t cmos_index;
65
    int32_t base_year;
66 67 68
    uint64_t base_rtc;
    uint64_t last_update;
    int64_t offset;
P
pbrook 已提交
69
    qemu_irq irq;
70
    qemu_irq sqw_irq;
71
    int it_shift;
72 73 74
    /* periodic timer */
    QEMUTimer *periodic_timer;
    int64_t next_periodic_time;
75 76
    /* update-ended timer */
    QEMUTimer *update_timer;
77
    uint64_t next_alarm_time;
78
    uint16_t irq_reinject_on_ack_count;
79 80
    uint32_t irq_coalesced;
    uint32_t period;
81
    QEMUTimer *coalesced_timer;
82
    Notifier clock_reset_notifier;
83
    LostTickPolicy lost_tick_policy;
84
    Notifier suspend_notifier;
85
} RTCState;
86 87

static void rtc_set_time(RTCState *s);
88
static void rtc_update_time(RTCState *s);
89
static void rtc_set_cmos(RTCState *s, const struct tm *tm);
90
static inline int rtc_from_bcd(RTCState *s, int a);
91
static uint64_t get_next_alarm(RTCState *s);
92

Y
Yang Zhang 已提交
93 94 95 96 97 98
static inline bool rtc_running(RTCState *s)
{
    return (!(s->cmos_data[RTC_REG_B] & REG_B_SET) &&
            (s->cmos_data[RTC_REG_A] & 0x70) <= 0x20);
}

99 100 101 102 103 104 105 106 107
static uint64_t get_guest_rtc_ns(RTCState *s)
{
    uint64_t guest_rtc;
    uint64_t guest_clock = qemu_get_clock_ns(rtc_clock);

    guest_rtc = s->base_rtc * NSEC_PER_SEC
                 + guest_clock - s->last_update + s->offset;
    return guest_rtc;
}
108

109 110 111 112 113 114 115 116
#ifdef TARGET_I386
static void rtc_coalesced_timer_update(RTCState *s)
{
    if (s->irq_coalesced == 0) {
        qemu_del_timer(s->coalesced_timer);
    } else {
        /* divide each RTC interval to 2 - 8 smaller intervals */
        int c = MIN(s->irq_coalesced, 7) + 1; 
117
        int64_t next_clock = qemu_get_clock_ns(rtc_clock) +
P
Paolo Bonzini 已提交
118
            muldiv64(s->period / c, get_ticks_per_sec(), RTC_CLOCK_RATE);
119 120 121 122 123 124 125 126 127 128 129
        qemu_mod_timer(s->coalesced_timer, next_clock);
    }
}

static void rtc_coalesced_timer(void *opaque)
{
    RTCState *s = opaque;

    if (s->irq_coalesced != 0) {
        apic_reset_irq_delivered();
        s->cmos_data[RTC_REG_C] |= 0xc0;
B
Blue Swirl 已提交
130
        DPRINTF_C("cmos: injecting from timer\n");
131
        qemu_irq_raise(s->irq);
132 133
        if (apic_get_irq_delivered()) {
            s->irq_coalesced--;
B
Blue Swirl 已提交
134 135
            DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
                      s->irq_coalesced);
136 137 138 139 140 141 142
        }
    }

    rtc_coalesced_timer_update(s);
}
#endif

143
/* handle periodic timer */
Y
Yang Zhang 已提交
144
static void periodic_timer_update(RTCState *s, int64_t current_time)
145 146 147 148 149
{
    int period_code, period;
    int64_t cur_clock, next_irq_clock;

    period_code = s->cmos_data[RTC_REG_A] & 0x0f;
150
    if (period_code != 0
151
        && ((s->cmos_data[RTC_REG_B] & REG_B_PIE)
152
            || ((s->cmos_data[RTC_REG_B] & REG_B_SQWE) && s->sqw_irq))) {
153 154 155 156
        if (period_code <= 2)
            period_code += 7;
        /* period in 32 Khz cycles */
        period = 1 << (period_code - 1);
157
#ifdef TARGET_I386
B
Blue Swirl 已提交
158
        if (period != s->period) {
159
            s->irq_coalesced = (s->irq_coalesced * s->period) / period;
B
Blue Swirl 已提交
160 161
            DPRINTF_C("cmos: coalesced irqs scaled to %d\n", s->irq_coalesced);
        }
162 163
        s->period = period;
#endif
164
        /* compute 32 khz clock */
P
Paolo Bonzini 已提交
165
        cur_clock = muldiv64(current_time, RTC_CLOCK_RATE, get_ticks_per_sec());
166
        next_irq_clock = (cur_clock & ~(period - 1)) + period;
J
Jan Kiszka 已提交
167
        s->next_periodic_time =
P
Paolo Bonzini 已提交
168
            muldiv64(next_irq_clock, get_ticks_per_sec(), RTC_CLOCK_RATE) + 1;
169 170
        qemu_mod_timer(s->periodic_timer, s->next_periodic_time);
    } else {
171 172 173
#ifdef TARGET_I386
        s->irq_coalesced = 0;
#endif
174 175 176 177 178 179 180 181
        qemu_del_timer(s->periodic_timer);
    }
}

static void rtc_periodic_timer(void *opaque)
{
    RTCState *s = opaque;

Y
Yang Zhang 已提交
182
    periodic_timer_update(s, s->next_periodic_time);
183
    s->cmos_data[RTC_REG_C] |= REG_C_PF;
184
    if (s->cmos_data[RTC_REG_B] & REG_B_PIE) {
185
        s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
186
#ifdef TARGET_I386
187
        if (s->lost_tick_policy == LOST_TICK_SLEW) {
188 189
            if (s->irq_reinject_on_ack_count >= RTC_REINJECT_ON_ACK_COUNT)
                s->irq_reinject_on_ack_count = 0;		
190
            apic_reset_irq_delivered();
191
            qemu_irq_raise(s->irq);
192 193 194
            if (!apic_get_irq_delivered()) {
                s->irq_coalesced++;
                rtc_coalesced_timer_update(s);
B
Blue Swirl 已提交
195 196
                DPRINTF_C("cmos: coalesced irqs increased to %d\n",
                          s->irq_coalesced);
197 198 199
            }
        } else
#endif
200
        qemu_irq_raise(s->irq);
201 202 203 204 205 206
    }
    if (s->cmos_data[RTC_REG_B] & REG_B_SQWE) {
        /* Not square wave at all but we don't want 2048Hz interrupts!
           Must be seen as a pulse.  */
        qemu_irq_raise(s->sqw_irq);
    }
207
}
B
bellard 已提交
208

209 210 211 212 213
/* handle update-ended timer */
static void check_update_timer(RTCState *s)
{
    uint64_t next_update_time;
    uint64_t guest_nsec;
214
    int next_alarm_sec;
215

Y
Yang Zhang 已提交
216 217 218 219
    /* From the data sheet: "Holding the dividers in reset prevents
     * interrupts from operating, while setting the SET bit allows"
     * them to occur.  However, it will prevent an alarm interrupt
     * from occurring, because the time of day is not updated.
220
     */
Y
Yang Zhang 已提交
221 222 223 224
    if ((s->cmos_data[RTC_REG_A] & 0x60) == 0x60) {
        qemu_del_timer(s->update_timer);
        return;
    }
225 226 227 228 229 230 231 232 233 234 235 236
    if ((s->cmos_data[RTC_REG_C] & REG_C_UF) &&
        (s->cmos_data[RTC_REG_B] & REG_B_SET)) {
        qemu_del_timer(s->update_timer);
        return;
    }
    if ((s->cmos_data[RTC_REG_C] & REG_C_UF) &&
        (s->cmos_data[RTC_REG_C] & REG_C_AF)) {
        qemu_del_timer(s->update_timer);
        return;
    }

    guest_nsec = get_guest_rtc_ns(s) % NSEC_PER_SEC;
237
    /* if UF is clear, reprogram to next second */
238 239
    next_update_time = qemu_get_clock_ns(rtc_clock)
        + NSEC_PER_SEC - guest_nsec;
240 241 242 243 244 245 246 247 248 249 250 251

    /* Compute time of next alarm.  One second is already accounted
     * for in next_update_time.
     */
    next_alarm_sec = get_next_alarm(s);
    s->next_alarm_time = next_update_time + (next_alarm_sec - 1) * NSEC_PER_SEC;

    if (s->cmos_data[RTC_REG_C] & REG_C_UF) {
        /* UF is set, but AF is clear.  Program the timer to target
         * the alarm time.  */
        next_update_time = s->next_alarm_time;
    }
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
    if (next_update_time != qemu_timer_expire_time_ns(s->update_timer)) {
        qemu_mod_timer(s->update_timer, next_update_time);
    }
}

static inline uint8_t convert_hour(RTCState *s, uint8_t hour)
{
    if (!(s->cmos_data[RTC_REG_B] & REG_B_24H)) {
        hour %= 12;
        if (s->cmos_data[RTC_HOURS] & 0x80) {
            hour += 12;
        }
    }
    return hour;
}

268
static uint64_t get_next_alarm(RTCState *s)
269
{
270 271 272 273
    int32_t alarm_sec, alarm_min, alarm_hour, cur_hour, cur_min, cur_sec;
    int32_t hour, min, sec;

    rtc_update_time(s);
274 275 276 277

    alarm_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS_ALARM]);
    alarm_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES_ALARM]);
    alarm_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS_ALARM]);
278
    alarm_hour = alarm_hour == -1 ? -1 : convert_hour(s, alarm_hour);
279 280 281 282 283 284

    cur_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS]);
    cur_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES]);
    cur_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS]);
    cur_hour = convert_hour(s, cur_hour);

285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
    if (alarm_hour == -1) {
        alarm_hour = cur_hour;
        if (alarm_min == -1) {
            alarm_min = cur_min;
            if (alarm_sec == -1) {
                alarm_sec = cur_sec + 1;
            } else if (cur_sec > alarm_sec) {
                alarm_min++;
            }
        } else if (cur_min == alarm_min) {
            if (alarm_sec == -1) {
                alarm_sec = cur_sec + 1;
            } else {
                if (cur_sec > alarm_sec) {
                    alarm_hour++;
                }
            }
            if (alarm_sec == SEC_PER_MIN) {
                /* wrap to next hour, minutes is not in don't care mode */
                alarm_sec = 0;
                alarm_hour++;
            }
        } else if (cur_min > alarm_min) {
            alarm_hour++;
        }
    } else if (cur_hour == alarm_hour) {
        if (alarm_min == -1) {
            alarm_min = cur_min;
            if (alarm_sec == -1) {
                alarm_sec = cur_sec + 1;
            } else if (cur_sec > alarm_sec) {
                alarm_min++;
            }

            if (alarm_sec == SEC_PER_MIN) {
                alarm_sec = 0;
                alarm_min++;
            }
            /* wrap to next day, hour is not in don't care mode */
            alarm_min %= MIN_PER_HOUR;
        } else if (cur_min == alarm_min) {
            if (alarm_sec == -1) {
                alarm_sec = cur_sec + 1;
            }
            /* wrap to next day, hours+minutes not in don't care mode */
            alarm_sec %= SEC_PER_MIN;
        }
332 333
    }

334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
    /* values that are still don't care fire at the next min/sec */
    if (alarm_min == -1) {
        alarm_min = 0;
    }
    if (alarm_sec == -1) {
        alarm_sec = 0;
    }

    /* keep values in range */
    if (alarm_sec == SEC_PER_MIN) {
        alarm_sec = 0;
        alarm_min++;
    }
    if (alarm_min == MIN_PER_HOUR) {
        alarm_min = 0;
        alarm_hour++;
    }
    alarm_hour %= HOUR_PER_DAY;

    hour = alarm_hour - cur_hour;
    min = hour * MIN_PER_HOUR + alarm_min - cur_min;
    sec = min * SEC_PER_MIN + alarm_sec - cur_sec;
    return sec <= 0 ? sec + SEC_PER_DAY : sec;
357 358 359 360 361 362 363 364
}

static void rtc_update_timer(void *opaque)
{
    RTCState *s = opaque;
    int32_t irqs = REG_C_UF;
    int32_t new_irqs;

Y
Yang Zhang 已提交
365 366
    assert((s->cmos_data[RTC_REG_A] & 0x60) != 0x60);

367 368 369 370
    /* UIP might have been latched, update time and clear it.  */
    rtc_update_time(s);
    s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;

371
    if (qemu_get_clock_ns(rtc_clock) >= s->next_alarm_time) {
372 373 374 375 376
        irqs |= REG_C_AF;
        if (s->cmos_data[RTC_REG_B] & REG_B_AIE) {
            qemu_system_wakeup_request(QEMU_WAKEUP_REASON_RTC);
        }
    }
377

378 379 380 381 382 383 384 385 386
    new_irqs = irqs & ~s->cmos_data[RTC_REG_C];
    s->cmos_data[RTC_REG_C] |= irqs;
    if ((new_irqs & s->cmos_data[RTC_REG_B]) != 0) {
        s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
        qemu_irq_raise(s->irq);
    }
    check_update_timer(s);
}

387 388
static void cmos_ioport_write(void *opaque, hwaddr addr,
                              uint64_t data, unsigned size)
B
bellard 已提交
389
{
B
bellard 已提交
390
    RTCState *s = opaque;
B
bellard 已提交
391 392 393 394

    if ((addr & 1) == 0) {
        s->cmos_index = data & 0x7f;
    } else {
395 396
        CMOS_DPRINTF("cmos: write index=0x%02x val=0x%02x\n",
                     s->cmos_index, data);
397
        switch(s->cmos_index) {
B
bellard 已提交
398 399 400 401
        case RTC_SECONDS_ALARM:
        case RTC_MINUTES_ALARM:
        case RTC_HOURS_ALARM:
            s->cmos_data[s->cmos_index] = data;
402
            check_update_timer(s);
B
bellard 已提交
403
            break;
404 405 406 407
	case RTC_IBM_PS2_CENTURY_BYTE:
            s->cmos_index = RTC_CENTURY;
            /* fall through */
        case RTC_CENTURY:
B
bellard 已提交
408 409 410 411 412 413 414 415
        case RTC_SECONDS:
        case RTC_MINUTES:
        case RTC_HOURS:
        case RTC_DAY_OF_WEEK:
        case RTC_DAY_OF_MONTH:
        case RTC_MONTH:
        case RTC_YEAR:
            s->cmos_data[s->cmos_index] = data;
416
            /* if in set mode, do not update the time */
Y
Yang Zhang 已提交
417
            if (rtc_running(s)) {
418
                rtc_set_time(s);
419
                check_update_timer(s);
420
            }
B
bellard 已提交
421 422
            break;
        case RTC_REG_A:
Y
Yang Zhang 已提交
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
            if ((data & 0x60) == 0x60) {
                if (rtc_running(s)) {
                    rtc_update_time(s);
                }
                /* What happens to UIP when divider reset is enabled is
                 * unclear from the datasheet.  Shouldn't matter much
                 * though.
                 */
                s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
            } else if (((s->cmos_data[RTC_REG_A] & 0x60) == 0x60) &&
                    (data & 0x70)  <= 0x20) {
                /* when the divider reset is removed, the first update cycle
                 * begins one-half second later*/
                if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
                    s->offset = 500000000;
                    rtc_set_time(s);
                }
                s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
            }
442 443 444
            /* UIP bit is read only */
            s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
                (s->cmos_data[RTC_REG_A] & REG_A_UIP);
Y
Yang Zhang 已提交
445
            periodic_timer_update(s, qemu_get_clock_ns(rtc_clock));
446
            check_update_timer(s);
447
            break;
B
bellard 已提交
448
        case RTC_REG_B:
449
            if (data & REG_B_SET) {
450
                /* update cmos to when the rtc was stopping */
Y
Yang Zhang 已提交
451
                if (rtc_running(s)) {
452 453
                    rtc_update_time(s);
                }
454 455 456 457 458
                /* set mode: reset UIP mode */
                s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
                data &= ~REG_B_UIE;
            } else {
                /* if disabling set mode, update the time */
Y
Yang Zhang 已提交
459 460
                if ((s->cmos_data[RTC_REG_B] & REG_B_SET) &&
                    (s->cmos_data[RTC_REG_A] & 0x70) <= 0x20) {
461
                    s->offset = get_guest_rtc_ns(s) % NSEC_PER_SEC;
462 463 464
                    rtc_set_time(s);
                }
            }
465 466 467 468 469 470 471 472 473
            /* if an interrupt flag is already set when the interrupt
             * becomes enabled, raise an interrupt immediately.  */
            if (data & s->cmos_data[RTC_REG_C] & REG_C_MASK) {
                s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
                qemu_irq_raise(s->irq);
            } else {
                s->cmos_data[RTC_REG_C] &= ~REG_C_IRQF;
                qemu_irq_lower(s->irq);
            }
474
            s->cmos_data[RTC_REG_B] = data;
Y
Yang Zhang 已提交
475
            periodic_timer_update(s, qemu_get_clock_ns(rtc_clock));
476
            check_update_timer(s);
B
bellard 已提交
477 478 479 480 481 482 483 484 485 486 487 488
            break;
        case RTC_REG_C:
        case RTC_REG_D:
            /* cannot write to them */
            break;
        default:
            s->cmos_data[s->cmos_index] = data;
            break;
        }
    }
}

P
Paul Brook 已提交
489
static inline int rtc_to_bcd(RTCState *s, int a)
B
bellard 已提交
490
{
A
aurel32 已提交
491
    if (s->cmos_data[RTC_REG_B] & REG_B_DM) {
492 493 494 495
        return a;
    } else {
        return ((a / 10) << 4) | (a % 10);
    }
B
bellard 已提交
496 497
}

P
Paul Brook 已提交
498
static inline int rtc_from_bcd(RTCState *s, int a)
B
bellard 已提交
499
{
500 501 502
    if ((a & 0xc0) == 0xc0) {
        return -1;
    }
A
aurel32 已提交
503
    if (s->cmos_data[RTC_REG_B] & REG_B_DM) {
504 505 506 507 508 509
        return a;
    } else {
        return ((a >> 4) * 10) + (a & 0x0f);
    }
}

510
static void rtc_get_time(RTCState *s, struct tm *tm)
511
{
P
Paul Brook 已提交
512 513 514
    tm->tm_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS]);
    tm->tm_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES]);
    tm->tm_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
P
Paolo Bonzini 已提交
515 516 517 518 519
    if (!(s->cmos_data[RTC_REG_B] & REG_B_24H)) {
        tm->tm_hour %= 12;
        if (s->cmos_data[RTC_HOURS] & 0x80) {
            tm->tm_hour += 12;
        }
520
    }
P
Paul Brook 已提交
521 522 523
    tm->tm_wday = rtc_from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]) - 1;
    tm->tm_mday = rtc_from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
    tm->tm_mon = rtc_from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
P
Paolo Bonzini 已提交
524 525 526
    tm->tm_year =
        rtc_from_bcd(s, s->cmos_data[RTC_YEAR]) + s->base_year +
        rtc_from_bcd(s, s->cmos_data[RTC_CENTURY]) * 100 - 1900;
527 528 529 530 531
}

static void rtc_set_time(RTCState *s)
{
    struct tm tm;
532

533 534
    rtc_get_time(s, &tm);
    s->base_rtc = mktimegm(&tm);
535 536
    s->last_update = qemu_get_clock_ns(rtc_clock);

537
    rtc_change_mon_event(&tm);
538 539
}

540
static void rtc_set_cmos(RTCState *s, const struct tm *tm)
541
{
542
    int year;
543

P
Paul Brook 已提交
544 545
    s->cmos_data[RTC_SECONDS] = rtc_to_bcd(s, tm->tm_sec);
    s->cmos_data[RTC_MINUTES] = rtc_to_bcd(s, tm->tm_min);
A
Aurelien Jarno 已提交
546
    if (s->cmos_data[RTC_REG_B] & REG_B_24H) {
547
        /* 24 hour format */
P
Paul Brook 已提交
548
        s->cmos_data[RTC_HOURS] = rtc_to_bcd(s, tm->tm_hour);
549 550
    } else {
        /* 12 hour format */
P
Paolo Bonzini 已提交
551 552
        int h = (tm->tm_hour % 12) ? tm->tm_hour % 12 : 12;
        s->cmos_data[RTC_HOURS] = rtc_to_bcd(s, h);
553 554 555
        if (tm->tm_hour >= 12)
            s->cmos_data[RTC_HOURS] |= 0x80;
    }
P
Paul Brook 已提交
556 557 558
    s->cmos_data[RTC_DAY_OF_WEEK] = rtc_to_bcd(s, tm->tm_wday + 1);
    s->cmos_data[RTC_DAY_OF_MONTH] = rtc_to_bcd(s, tm->tm_mday);
    s->cmos_data[RTC_MONTH] = rtc_to_bcd(s, tm->tm_mon + 1);
P
Paolo Bonzini 已提交
559 560 561
    year = tm->tm_year + 1900 - s->base_year;
    s->cmos_data[RTC_YEAR] = rtc_to_bcd(s, year % 100);
    s->cmos_data[RTC_CENTURY] = rtc_to_bcd(s, year / 100);
562 563
}

564
static void rtc_update_time(RTCState *s)
565
{
566 567 568 569 570 571 572
    struct tm ret;
    time_t guest_sec;
    int64_t guest_nsec;

    guest_nsec = get_guest_rtc_ns(s);
    guest_sec = guest_nsec / NSEC_PER_SEC;
    gmtime_r(&guest_sec, &ret);
573 574 575 576 577

    /* Is SET flag of Register B disabled? */
    if ((s->cmos_data[RTC_REG_B] & REG_B_SET) == 0) {
        rtc_set_cmos(s, &ret);
    }
578 579
}

580
static int update_in_progress(RTCState *s)
581
{
582
    int64_t guest_nsec;
583

Y
Yang Zhang 已提交
584
    if (!rtc_running(s)) {
585
        return 0;
586
    }
587 588 589 590 591 592
    if (qemu_timer_pending(s->update_timer)) {
        int64_t next_update_time = qemu_timer_expire_time_ns(s->update_timer);
        /* Latch UIP until the timer expires.  */
        if (qemu_get_clock_ns(rtc_clock) >= (next_update_time - UIP_HOLD_LENGTH)) {
            s->cmos_data[RTC_REG_A] |= REG_A_UIP;
            return 1;
593 594 595
        }
    }

596 597 598 599
    guest_nsec = get_guest_rtc_ns(s);
    /* UIP bit will be set at last 244us of every second. */
    if ((guest_nsec % NSEC_PER_SEC) >= (NSEC_PER_SEC - UIP_HOLD_LENGTH)) {
        return 1;
600
    }
601
    return 0;
B
bellard 已提交
602 603
}

604 605
static uint64_t cmos_ioport_read(void *opaque, hwaddr addr,
                                 unsigned size)
B
bellard 已提交
606
{
B
bellard 已提交
607
    RTCState *s = opaque;
B
bellard 已提交
608 609 610 611 612
    int ret;
    if ((addr & 1) == 0) {
        return 0xff;
    } else {
        switch(s->cmos_index) {
613 614 615 616
	case RTC_IBM_PS2_CENTURY_BYTE:
            s->cmos_index = RTC_CENTURY;
            /* fall through */
        case RTC_CENTURY:
B
bellard 已提交
617 618 619 620 621 622 623
        case RTC_SECONDS:
        case RTC_MINUTES:
        case RTC_HOURS:
        case RTC_DAY_OF_WEEK:
        case RTC_DAY_OF_MONTH:
        case RTC_MONTH:
        case RTC_YEAR:
624 625
            /* if not in set mode, calibrate cmos before
             * reading*/
Y
Yang Zhang 已提交
626
            if (rtc_running(s)) {
627 628
                rtc_update_time(s);
            }
B
bellard 已提交
629 630 631
            ret = s->cmos_data[s->cmos_index];
            break;
        case RTC_REG_A:
632 633 634 635 636
            if (update_in_progress(s)) {
                s->cmos_data[s->cmos_index] |= REG_A_UIP;
            } else {
                s->cmos_data[s->cmos_index] &= ~REG_A_UIP;
            }
B
bellard 已提交
637 638 639 640
            ret = s->cmos_data[s->cmos_index];
            break;
        case RTC_REG_C:
            ret = s->cmos_data[s->cmos_index];
P
pbrook 已提交
641
            qemu_irq_lower(s->irq);
642
            s->cmos_data[RTC_REG_C] = 0x00;
643 644 645
            if (ret & (REG_C_UF | REG_C_AF)) {
                check_update_timer(s);
            }
646 647
#ifdef TARGET_I386
            if(s->irq_coalesced &&
648
                    (s->cmos_data[RTC_REG_B] & REG_B_PIE) &&
649 650
                    s->irq_reinject_on_ack_count < RTC_REINJECT_ON_ACK_COUNT) {
                s->irq_reinject_on_ack_count++;
651
                s->cmos_data[RTC_REG_C] |= REG_C_IRQF | REG_C_PF;
652
                apic_reset_irq_delivered();
B
Blue Swirl 已提交
653
                DPRINTF_C("cmos: injecting on ack\n");
654
                qemu_irq_raise(s->irq);
B
Blue Swirl 已提交
655
                if (apic_get_irq_delivered()) {
656
                    s->irq_coalesced--;
B
Blue Swirl 已提交
657 658 659
                    DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
                              s->irq_coalesced);
                }
660 661
            }
#endif
B
bellard 已提交
662 663 664 665 666
            break;
        default:
            ret = s->cmos_data[s->cmos_index];
            break;
        }
667 668
        CMOS_DPRINTF("cmos: read index=0x%02x val=0x%02x\n",
                     s->cmos_index, ret);
B
bellard 已提交
669 670 671 672
        return ret;
    }
}

673
void rtc_set_memory(ISADevice *dev, int addr, int val)
674
{
675
    RTCState *s = DO_UPCAST(RTCState, dev, dev);
676 677 678 679
    if (addr >= 0 && addr <= 127)
        s->cmos_data[addr] = val;
}

680
static void rtc_set_date_from_host(ISADevice *dev)
681
{
682
    RTCState *s = DO_UPCAST(RTCState, dev, dev);
683
    struct tm tm;
684

685
    qemu_get_timedate(&tm, 0);
686 687 688 689 690 691

    s->base_rtc = mktimegm(&tm);
    s->last_update = qemu_get_clock_ns(rtc_clock);
    s->offset = 0;

    /* set the CMOS date */
692
    rtc_set_cmos(s, &tm);
693 694
}

J
Juan Quintela 已提交
695
static int rtc_post_load(void *opaque, int version_id)
B
bellard 已提交
696
{
697 698
    RTCState *s = opaque;

699 700 701 702 703 704 705
    if (version_id <= 2) {
        rtc_set_time(s);
        s->offset = 0;
        check_update_timer(s);
    }

#ifdef TARGET_I386
706
    if (version_id >= 2) {
707
        if (s->lost_tick_policy == LOST_TICK_SLEW) {
708 709 710
            rtc_coalesced_timer_update(s);
        }
    }
J
Juan Quintela 已提交
711
#endif
712 713 714
    return 0;
}

J
Juan Quintela 已提交
715 716
static const VMStateDescription vmstate_rtc = {
    .name = "mc146818rtc",
717
    .version_id = 3,
J
Juan Quintela 已提交
718 719 720 721 722 723
    .minimum_version_id = 1,
    .minimum_version_id_old = 1,
    .post_load = rtc_post_load,
    .fields      = (VMStateField []) {
        VMSTATE_BUFFER(cmos_data, RTCState),
        VMSTATE_UINT8(cmos_index, RTCState),
P
Paolo Bonzini 已提交
724
        VMSTATE_UNUSED(7*4),
J
Juan Quintela 已提交
725 726
        VMSTATE_TIMER(periodic_timer, RTCState),
        VMSTATE_INT64(next_periodic_time, RTCState),
727
        VMSTATE_UNUSED(3*8),
J
Juan Quintela 已提交
728 729
        VMSTATE_UINT32_V(irq_coalesced, RTCState, 2),
        VMSTATE_UINT32_V(period, RTCState, 2),
730 731 732 733
        VMSTATE_UINT64_V(base_rtc, RTCState, 3),
        VMSTATE_UINT64_V(last_update, RTCState, 3),
        VMSTATE_INT64_V(offset, RTCState, 3),
        VMSTATE_TIMER_V(update_timer, RTCState, 3),
734
        VMSTATE_UINT64_V(next_alarm_time, RTCState, 3),
J
Juan Quintela 已提交
735 736 737 738
        VMSTATE_END_OF_LIST()
    }
};

739 740 741 742 743 744
static void rtc_notify_clock_reset(Notifier *notifier, void *data)
{
    RTCState *s = container_of(notifier, RTCState, clock_reset_notifier);
    int64_t now = *(int64_t *)data;

    rtc_set_date_from_host(&s->dev);
Y
Yang Zhang 已提交
745
    periodic_timer_update(s, now);
746
    check_update_timer(s);
747
#ifdef TARGET_I386
748
    if (s->lost_tick_policy == LOST_TICK_SLEW) {
749 750 751 752 753
        rtc_coalesced_timer_update(s);
    }
#endif
}

754 755 756 757 758 759 760 761
/* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
   BIOS will read it and start S3 resume at POST Entry */
static void rtc_notify_suspend(Notifier *notifier, void *data)
{
    RTCState *s = container_of(notifier, RTCState, suspend_notifier);
    rtc_set_memory(&s->dev, 0xF, 0xFE);
}

G
Gleb Natapov 已提交
762 763 764 765
static void rtc_reset(void *opaque)
{
    RTCState *s = opaque;

766 767
    s->cmos_data[RTC_REG_B] &= ~(REG_B_PIE | REG_B_AIE | REG_B_SQWE);
    s->cmos_data[RTC_REG_C] &= ~(REG_C_UF | REG_C_IRQF | REG_C_PF | REG_C_AF);
768
    check_update_timer(s);
G
Gleb Natapov 已提交
769

770
    qemu_irq_lower(s->irq);
G
Gleb Natapov 已提交
771 772

#ifdef TARGET_I386
773 774 775
    if (s->lost_tick_policy == LOST_TICK_SLEW) {
        s->irq_coalesced = 0;
    }
G
Gleb Natapov 已提交
776 777 778
#endif
}

779
static const MemoryRegionOps cmos_ops = {
780 781 782 783 784 785 786
    .read = cmos_ioport_read,
    .write = cmos_ioport_write,
    .impl = {
        .min_access_size = 1,
        .max_access_size = 1,
    },
    .endianness = DEVICE_LITTLE_ENDIAN,
787 788
};

789
static void rtc_get_date(Object *obj, Visitor *v, void *opaque,
790 791
                         const char *name, Error **errp)
{
792
    ISADevice *isa = ISA_DEVICE(obj);
793
    RTCState *s = DO_UPCAST(RTCState, dev, isa);
794
    struct tm current_tm;
795

796
    rtc_update_time(s);
797
    rtc_get_time(s, &current_tm);
798
    visit_start_struct(v, NULL, "struct tm", name, 0, errp);
799 800 801 802 803 804
    visit_type_int32(v, &current_tm.tm_year, "tm_year", errp);
    visit_type_int32(v, &current_tm.tm_mon, "tm_mon", errp);
    visit_type_int32(v, &current_tm.tm_mday, "tm_mday", errp);
    visit_type_int32(v, &current_tm.tm_hour, "tm_hour", errp);
    visit_type_int32(v, &current_tm.tm_min, "tm_min", errp);
    visit_type_int32(v, &current_tm.tm_sec, "tm_sec", errp);
805 806 807
    visit_end_struct(v, errp);
}

808
static int rtc_initfn(ISADevice *dev)
809
{
810 811
    RTCState *s = DO_UPCAST(RTCState, dev, dev);
    int base = 0x70;
B
bellard 已提交
812 813 814 815 816 817

    s->cmos_data[RTC_REG_A] = 0x26;
    s->cmos_data[RTC_REG_B] = 0x02;
    s->cmos_data[RTC_REG_C] = 0x00;
    s->cmos_data[RTC_REG_D] = 0x80;

P
Paolo Bonzini 已提交
818 819 820 821 822 823 824 825 826 827 828 829
    /* This is for historical reasons.  The default base year qdev property
     * was set to 2000 for most machine types before the century byte was
     * implemented.
     *
     * This if statement means that the century byte will be always 0
     * (at least until 2079...) for base_year = 1980, but will be set
     * correctly for base_year = 2000.
     */
    if (s->base_year == 2000) {
        s->base_year = 0;
    }

830
    rtc_set_date_from_host(dev);
831

832
#ifdef TARGET_I386
833 834
    switch (s->lost_tick_policy) {
    case LOST_TICK_SLEW:
J
Jan Kiszka 已提交
835
        s->coalesced_timer =
836
            qemu_new_timer_ns(rtc_clock, rtc_coalesced_timer, s);
837 838 839 840 841 842
        break;
    case LOST_TICK_DISCARD:
        break;
    default:
        return -EINVAL;
    }
843
#endif
844 845

    s->periodic_timer = qemu_new_timer_ns(rtc_clock, rtc_periodic_timer, s);
846 847
    s->update_timer = qemu_new_timer_ns(rtc_clock, rtc_update_timer, s);
    check_update_timer(s);
848

849 850 851
    s->clock_reset_notifier.notify = rtc_notify_clock_reset;
    qemu_register_clock_reset_notifier(rtc_clock, &s->clock_reset_notifier);

852 853 854
    s->suspend_notifier.notify = rtc_notify_suspend;
    qemu_register_suspend_notifier(&s->suspend_notifier);

855 856
    memory_region_init_io(&s->io, &cmos_ops, s, "rtc", 2);
    isa_register_ioport(dev, &s->io, base);
857

858
    qdev_set_legacy_instance_id(&dev->qdev, base, 3);
859
    qemu_register_reset(rtc_reset, s);
860

861 862
    object_property_add(OBJECT(s), "date", "struct tm",
                        rtc_get_date, NULL, NULL, s, NULL);
863

864 865 866
    return 0;
}

867
ISADevice *rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq)
868 869
{
    ISADevice *dev;
870
    RTCState *s;
G
Gleb Natapov 已提交
871

872
    dev = isa_create(bus, "mc146818rtc");
873
    s = DO_UPCAST(RTCState, dev, dev);
874
    qdev_prop_set_int32(&dev->qdev, "base_year", base_year);
M
Markus Armbruster 已提交
875
    qdev_init_nofail(&dev->qdev);
876 877 878 879 880
    if (intercept_irq) {
        s->irq = intercept_irq;
    } else {
        isa_init_irq(dev, &s->irq, RTC_ISA_IRQ);
    }
881
    return dev;
B
bellard 已提交
882 883
}

884 885 886 887 888 889 890
static Property mc146818rtc_properties[] = {
    DEFINE_PROP_INT32("base_year", RTCState, base_year, 1980),
    DEFINE_PROP_LOSTTICKPOLICY("lost_tick_policy", RTCState,
                               lost_tick_policy, LOST_TICK_DISCARD),
    DEFINE_PROP_END_OF_LIST(),
};

891 892
static void rtc_class_initfn(ObjectClass *klass, void *data)
{
893
    DeviceClass *dc = DEVICE_CLASS(klass);
894 895
    ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
    ic->init = rtc_initfn;
896 897 898
    dc->no_user = 1;
    dc->vmsd = &vmstate_rtc;
    dc->props = mc146818rtc_properties;
899 900
}

901
static const TypeInfo mc146818rtc_info = {
902 903 904 905
    .name          = "mc146818rtc",
    .parent        = TYPE_ISA_DEVICE,
    .instance_size = sizeof(RTCState),
    .class_init    = rtc_class_initfn,
906 907
};

A
Andreas Färber 已提交
908
static void mc146818rtc_register_types(void)
909
{
910
    type_register_static(&mc146818rtc_info);
911
}
A
Andreas Färber 已提交
912 913

type_init(mc146818rtc_register_types)