Commit 100d9891d61956e503f4ef6f69f73bf2f74b7818

Authored by aurel32
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 {
@@ -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);