diff options
author | aurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162> | 2009-04-07 22:28:50 +0000 |
---|---|---|
committer | aurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162> | 2009-04-07 22:28:50 +0000 |
commit | 100d9891d61956e503f4ef6f69f73bf2f74b7818 (patch) | |
tree | 955d57f0de6b0ba7dd11a996a429bc384fb63861 | |
parent | 9ea0b7a1395e5580a7c5f5e296870fff9c130256 (diff) |
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 <gingold@adacore.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@7031 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r-- | hw/mc146818rtc.c | 39 | ||||
-rw-r--r-- | 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) { @@ -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); |