diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2012-10-01 14:22:08 +0200 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2012-10-05 08:02:30 -0500 |
commit | b8994faf2a8d6fc791669bb432bdb3a7a1711013 (patch) | |
tree | c1876480b0f09dd97806039e26451a151720c8d0 /hw | |
parent | e67edb943f0c812530aaae2491da56f9542f928b (diff) |
rtc: implement century byte
Implement the century byte in the RTC emulation, and test that it works.
This leads to some annoying compatibility code because we need to treat
a value of 2000 for the base_year property as "use the century byte
properly" (which would be a value of 0).
The century byte will now be always-zero, rather than always-20,
for the MIPS Magnum machine whose base_year is 1980. Commit 42fc73a
(Support epoch of 1980 in RTC emulation for MIPS Magnum, 2009-01-24)
correctly said:
With an epoch of 1980 and a year of 2009, one could argue that [the
century byte] should hold either 0, 1, 19 or 20. NT 3.50 on MIPS
does not read the century byte.
so I picked the simplest and most sensible implementation which is to
return 0 for 1980-2079, 1 for 2080-2179 and so on.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/mc146818rtc.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c index a7d20d5c25..332a77d4dc 100644 --- a/hw/mc146818rtc.c +++ b/hw/mc146818rtc.c @@ -519,7 +519,9 @@ static void rtc_get_time(RTCState *s, struct tm *tm) 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; - tm->tm_year = rtc_from_bcd(s, s->cmos_data[RTC_YEAR]) + s->base_year - 1900; + 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; } static void rtc_set_time(RTCState *s) @@ -552,10 +554,9 @@ static void rtc_set_cmos(RTCState *s, const struct tm *tm) 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); - year = (tm->tm_year - s->base_year) % 100; - if (year < 0) - year += 100; - s->cmos_data[RTC_YEAR] = rtc_to_bcd(s, year); + 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); } static void rtc_update_time(RTCState *s) @@ -673,7 +674,6 @@ static void rtc_set_date_from_host(ISADevice *dev) { RTCState *s = DO_UPCAST(RTCState, dev, dev); struct tm tm; - int val; qemu_get_timedate(&tm, 0); @@ -683,9 +683,6 @@ static void rtc_set_date_from_host(ISADevice *dev) /* set the CMOS date */ rtc_set_cmos(s, &tm); - - val = rtc_to_bcd(s, (tm.tm_year / 100) + 19); - rtc_set_memory(dev, RTC_CENTURY, val); } static int rtc_post_load(void *opaque, int version_id) @@ -810,6 +807,18 @@ static int rtc_initfn(ISADevice *dev) s->cmos_data[RTC_REG_C] = 0x00; s->cmos_data[RTC_REG_D] = 0x80; + /* 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; + } + rtc_set_date_from_host(dev); #ifdef TARGET_I386 |