Commit 100d9891d61956e503f4ef6f69f73bf2f74b7818
1 parent
9ea0b7a1
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
Showing
2 changed files
with
30 additions
and
10 deletions
hw/mc146818rtc.c
| @@ -50,11 +50,12 @@ | @@ -50,11 +50,12 @@ | ||
| 50 | 50 | ||
| 51 | #define REG_A_UIP 0x80 | 51 | #define REG_A_UIP 0x80 |
| 52 | 52 | ||
| 53 | -#define REG_B_SET 0x80 | ||
| 54 | -#define REG_B_PIE 0x40 | ||
| 55 | -#define REG_B_AIE 0x20 | ||
| 56 | -#define REG_B_UIE 0x10 | ||
| 57 | -#define REG_B_DM 0x04 | 53 | +#define REG_B_SET 0x80 |
| 54 | +#define REG_B_PIE 0x40 | ||
| 55 | +#define REG_B_AIE 0x20 | ||
| 56 | +#define REG_B_UIE 0x10 | ||
| 57 | +#define REG_B_SQWE 0x08 | ||
| 58 | +#define REG_B_DM 0x04 | ||
| 58 | 59 | ||
| 59 | struct RTCState { | 60 | struct RTCState { |
| 60 | uint8_t cmos_data[128]; | 61 | uint8_t cmos_data[128]; |
| @@ -62,6 +63,7 @@ struct RTCState { | @@ -62,6 +63,7 @@ struct RTCState { | ||
| 62 | struct tm current_tm; | 63 | struct tm current_tm; |
| 63 | int base_year; | 64 | int base_year; |
| 64 | qemu_irq irq; | 65 | qemu_irq irq; |
| 66 | + qemu_irq sqw_irq; | ||
| 65 | int it_shift; | 67 | int it_shift; |
| 66 | /* periodic timer */ | 68 | /* periodic timer */ |
| 67 | QEMUTimer *periodic_timer; | 69 | QEMUTimer *periodic_timer; |
| @@ -95,16 +97,20 @@ static void rtc_timer_update(RTCState *s, int64_t current_time) | @@ -95,16 +97,20 @@ static void rtc_timer_update(RTCState *s, int64_t current_time) | ||
| 95 | { | 97 | { |
| 96 | int period_code, period; | 98 | int period_code, period; |
| 97 | int64_t cur_clock, next_irq_clock; | 99 | int64_t cur_clock, next_irq_clock; |
| 100 | + int enable_pie; | ||
| 98 | 101 | ||
| 99 | period_code = s->cmos_data[RTC_REG_A] & 0x0f; | 102 | period_code = s->cmos_data[RTC_REG_A] & 0x0f; |
| 100 | #if defined TARGET_I386 || defined TARGET_X86_64 | 103 | #if defined TARGET_I386 || defined TARGET_X86_64 |
| 101 | /* disable periodic timer if hpet is in legacy mode, since interrupts are | 104 | /* disable periodic timer if hpet is in legacy mode, since interrupts are |
| 102 | * disabled anyway. | 105 | * disabled anyway. |
| 103 | */ | 106 | */ |
| 104 | - if (period_code != 0 && (s->cmos_data[RTC_REG_B] & REG_B_PIE) && !hpet_in_legacy_mode()) { | 107 | + enable_pie = hpet_in_legacy_mode(); |
| 105 | #else | 108 | #else |
| 106 | - if (period_code != 0 && (s->cmos_data[RTC_REG_B] & REG_B_PIE)) { | 109 | + enable_pie = 1; |
| 107 | #endif | 110 | #endif |
| 111 | + if (period_code != 0 | ||
| 112 | + && (((s->cmos_data[RTC_REG_B] & REG_B_PIE) && enable_pie) | ||
| 113 | + || ((s->cmos_data[RTC_REG_B] & REG_B_SQWE) && s->sqw_irq))) { | ||
| 108 | if (period_code <= 2) | 114 | if (period_code <= 2) |
| 109 | period_code += 7; | 115 | period_code += 7; |
| 110 | /* period in 32 Khz cycles */ | 116 | /* period in 32 Khz cycles */ |
| @@ -138,8 +144,15 @@ static void rtc_periodic_timer(void *opaque) | @@ -138,8 +144,15 @@ static void rtc_periodic_timer(void *opaque) | ||
| 138 | return; | 144 | return; |
| 139 | } | 145 | } |
| 140 | #endif | 146 | #endif |
| 141 | - s->cmos_data[RTC_REG_C] |= 0xc0; | ||
| 142 | - rtc_irq_raise(s->irq); | 147 | + if (s->cmos_data[RTC_REG_B] & REG_B_PIE) { |
| 148 | + s->cmos_data[RTC_REG_C] |= 0xc0; | ||
| 149 | + rtc_irq_raise(s->irq); | ||
| 150 | + } | ||
| 151 | + if (s->cmos_data[RTC_REG_B] & REG_B_SQWE) { | ||
| 152 | + /* Not square wave at all but we don't want 2048Hz interrupts! | ||
| 153 | + Must be seen as a pulse. */ | ||
| 154 | + qemu_irq_raise(s->sqw_irq); | ||
| 155 | + } | ||
| 143 | } | 156 | } |
| 144 | 157 | ||
| 145 | static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data) | 158 | 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) | @@ -527,13 +540,14 @@ static int rtc_load_td(QEMUFile *f, void *opaque, int version_id) | ||
| 527 | } | 540 | } |
| 528 | #endif | 541 | #endif |
| 529 | 542 | ||
| 530 | -RTCState *rtc_init(int base, qemu_irq irq, int base_year) | 543 | +RTCState *rtc_init_sqw(int base, qemu_irq irq, qemu_irq sqw_irq, int base_year) |
| 531 | { | 544 | { |
| 532 | RTCState *s; | 545 | RTCState *s; |
| 533 | 546 | ||
| 534 | s = qemu_mallocz(sizeof(RTCState)); | 547 | s = qemu_mallocz(sizeof(RTCState)); |
| 535 | 548 | ||
| 536 | s->irq = irq; | 549 | s->irq = irq; |
| 550 | + s->sqw_irq = sqw_irq; | ||
| 537 | s->cmos_data[RTC_REG_A] = 0x26; | 551 | s->cmos_data[RTC_REG_A] = 0x26; |
| 538 | s->cmos_data[RTC_REG_B] = 0x02; | 552 | s->cmos_data[RTC_REG_B] = 0x02; |
| 539 | s->cmos_data[RTC_REG_C] = 0x00; | 553 | s->cmos_data[RTC_REG_C] = 0x00; |
| @@ -563,6 +577,11 @@ RTCState *rtc_init(int base, qemu_irq irq, int base_year) | @@ -563,6 +577,11 @@ RTCState *rtc_init(int base, qemu_irq irq, int base_year) | ||
| 563 | return s; | 577 | return s; |
| 564 | } | 578 | } |
| 565 | 579 | ||
| 580 | +RTCState *rtc_init(int base, qemu_irq irq, int base_year) | ||
| 581 | +{ | ||
| 582 | + return rtc_init_sqw(base, irq, NULL, base_year); | ||
| 583 | +} | ||
| 584 | + | ||
| 566 | /* Memory mapped interface */ | 585 | /* Memory mapped interface */ |
| 567 | static uint32_t cmos_mm_readb (void *opaque, target_phys_addr_t addr) | 586 | static uint32_t cmos_mm_readb (void *opaque, target_phys_addr_t addr) |
| 568 | { | 587 | { |
hw/pc.h
| @@ -90,6 +90,7 @@ void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq, | @@ -90,6 +90,7 @@ void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq, | ||
| 90 | typedef struct RTCState RTCState; | 90 | typedef struct RTCState RTCState; |
| 91 | 91 | ||
| 92 | RTCState *rtc_init(int base, qemu_irq irq, int base_year); | 92 | RTCState *rtc_init(int base, qemu_irq irq, int base_year); |
| 93 | +RTCState *rtc_init_sqw(int base, qemu_irq irq, qemu_irq sqw_irq, int base_year); | ||
| 93 | RTCState *rtc_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq, | 94 | RTCState *rtc_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq, |
| 94 | int base_year); | 95 | int base_year); |
| 95 | void rtc_set_memory(RTCState *s, int addr, int val); | 96 | void rtc_set_memory(RTCState *s, int addr, int val); |