From 100d9891d61956e503f4ef6f69f73bf2f74b7818 Mon Sep 17 00:00:00 2001 From: aurel32 Date: Tue, 7 Apr 2009 22:28:50 +0000 Subject: [PATCH] mc146818: add square wave output support This is necessary for es40 as the sqw output is directly connected to the core chipset. Signed-off-by: Tristan Gingold Signed-off-by: Aurelien Jarno git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@7031 c046a42c-6fe2-441c-8c8c-71466251a162 --- hw/mc146818rtc.c | 39 +++++++++++++++++++++++++++++---------- hw/pc.h | 1 + 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c index 5b08d72644..f6bb21d292 100644 --- a/hw/mc146818rtc.c +++ b/hw/mc146818rtc.c @@ -50,11 +50,12 @@ #define REG_A_UIP 0x80 -#define REG_B_SET 0x80 -#define REG_B_PIE 0x40 -#define REG_B_AIE 0x20 -#define REG_B_UIE 0x10 -#define REG_B_DM 0x04 +#define REG_B_SET 0x80 +#define REG_B_PIE 0x40 +#define REG_B_AIE 0x20 +#define REG_B_UIE 0x10 +#define REG_B_SQWE 0x08 +#define REG_B_DM 0x04 struct RTCState { uint8_t cmos_data[128]; @@ -62,6 +63,7 @@ struct RTCState { struct tm current_tm; int base_year; qemu_irq irq; + qemu_irq sqw_irq; int it_shift; /* periodic timer */ QEMUTimer *periodic_timer; @@ -95,16 +97,20 @@ static void rtc_timer_update(RTCState *s, int64_t current_time) { int period_code, period; int64_t cur_clock, next_irq_clock; + int enable_pie; period_code = s->cmos_data[RTC_REG_A] & 0x0f; #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()) { + enable_pie = hpet_in_legacy_mode(); #else - if (period_code != 0 && (s->cmos_data[RTC_REG_B] & REG_B_PIE)) { + enable_pie = 1; #endif + if (period_code != 0 + && (((s->cmos_data[RTC_REG_B] & REG_B_PIE) && enable_pie) + || ((s->cmos_data[RTC_REG_B] & REG_B_SQWE) && s->sqw_irq))) { if (period_code <= 2) period_code += 7; /* period in 32 Khz cycles */ @@ -138,8 +144,15 @@ static void rtc_periodic_timer(void *opaque) return; } #endif - s->cmos_data[RTC_REG_C] |= 0xc0; - rtc_irq_raise(s->irq); + if (s->cmos_data[RTC_REG_B] & REG_B_PIE) { + s->cmos_data[RTC_REG_C] |= 0xc0; + rtc_irq_raise(s->irq); + } + 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); + } } static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data) @@ -527,13 +540,14 @@ static int rtc_load_td(QEMUFile *f, void *opaque, int version_id) } #endif -RTCState *rtc_init(int base, qemu_irq irq, int base_year) +RTCState *rtc_init_sqw(int base, qemu_irq irq, qemu_irq sqw_irq, int base_year) { RTCState *s; s = qemu_mallocz(sizeof(RTCState)); s->irq = irq; + s->sqw_irq = sqw_irq; s->cmos_data[RTC_REG_A] = 0x26; s->cmos_data[RTC_REG_B] = 0x02; s->cmos_data[RTC_REG_C] = 0x00; @@ -563,6 +577,11 @@ RTCState *rtc_init(int base, qemu_irq irq, int base_year) return s; } +RTCState *rtc_init(int base, qemu_irq irq, int base_year) +{ + return rtc_init_sqw(base, irq, NULL, base_year); +} + /* Memory mapped interface */ static uint32_t cmos_mm_readb (void *opaque, target_phys_addr_t addr) { diff --git a/hw/pc.h b/hw/pc.h index 5b378d4d62..7345f04d7e 100644 --- a/hw/pc.h +++ b/hw/pc.h @@ -90,6 +90,7 @@ void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq, typedef struct RTCState RTCState; RTCState *rtc_init(int base, qemu_irq irq, int base_year); +RTCState *rtc_init_sqw(int base, qemu_irq irq, qemu_irq sqw_irq, int base_year); RTCState *rtc_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq, int base_year); void rtc_set_memory(RTCState *s, int addr, int val); -- 2.11.0