aboutsummaryrefslogtreecommitdiff
path: root/hw/mc146818rtc.c
diff options
context:
space:
mode:
authoraliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>2008-12-17 23:28:44 +0000
committeraliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>2008-12-17 23:28:44 +0000
commit16b29ae1807b024bd5052301550f5d47dae958a2 (patch)
treeeeeb5072d4548b91f2111f3127737a374d89cab2 /hw/mc146818rtc.c
parent0bacd1300dbcd7f56bdbf1ca73438b6a68c31b8f (diff)
Add HPET emulation to qemu (Beth Kon)
This patch adds HPET emulation. It can be disabled with -disable-hpet. An hpet provides a more finely granular clocksource than otherwise available on PC. This means that latency-dependent applications (e.g. multimedia) will generally be smoother when using the HPET. Signed-off-by: Beth Kon <eak@us.ibm.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6081 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'hw/mc146818rtc.c')
-rw-r--r--hw/mc146818rtc.c29
1 files changed, 24 insertions, 5 deletions
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index ac41a947b8..d25b52b4d3 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -26,6 +26,7 @@
#include "sysemu.h"
#include "pc.h"
#include "isa.h"
+#include "hpet_emul.h"
//#define DEBUG_CMOS
@@ -69,6 +70,18 @@ struct RTCState {
QEMUTimer *second_timer2;
};
+static void rtc_irq_raise(qemu_irq irq) {
+ /* When HPET is operating in legacy mode, RTC interrupts are disabled
+ * We block qemu_irq_raise, but not qemu_irq_lower, in case legacy
+ * mode is established while interrupt is raised. We want it to
+ * be lowered in any case
+ */
+#if defined TARGET_I386 || defined TARGET_X86_64
+ if (!hpet_in_legacy_mode())
+#endif
+ qemu_irq_raise(irq);
+}
+
static void rtc_set_time(RTCState *s);
static void rtc_copy_date(RTCState *s);
@@ -78,8 +91,14 @@ static void rtc_timer_update(RTCState *s, int64_t current_time)
int64_t cur_clock, next_irq_clock;
period_code = s->cmos_data[RTC_REG_A] & 0x0f;
- if (period_code != 0 &&
- (s->cmos_data[RTC_REG_B] & REG_B_PIE)) {
+#if defined TARGET_I386 || defined TARGET_X86_64
+ /* disable periodic timer if hpet is in legacy mode, since interrupts are
+ * disabled anyway.
+ */
+ if (period_code != 0 && (s->cmos_data[RTC_REG_B] & REG_B_PIE) && !hpet_in_legacy_mode()) {
+#else
+ if (period_code != 0 && (s->cmos_data[RTC_REG_B] & REG_B_PIE)) {
+#endif
if (period_code <= 2)
period_code += 7;
/* period in 32 Khz cycles */
@@ -100,7 +119,7 @@ static void rtc_periodic_timer(void *opaque)
rtc_timer_update(s, s->next_periodic_time);
s->cmos_data[RTC_REG_C] |= 0xc0;
- qemu_irq_raise(s->irq);
+ rtc_irq_raise(s->irq);
}
static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
@@ -319,14 +338,14 @@ static void rtc_update_second2(void *opaque)
s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) {
s->cmos_data[RTC_REG_C] |= 0xa0;
- qemu_irq_raise(s->irq);
+ rtc_irq_raise(s->irq);
}
}
/* update ended interrupt */
if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
s->cmos_data[RTC_REG_C] |= 0x90;
- qemu_irq_raise(s->irq);
+ rtc_irq_raise(s->irq);
}
/* clear update in progress bit */