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 50  
51 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 60 struct RTCState {
60 61 uint8_t cmos_data[128];
... ... @@ -62,6 +63,7 @@ struct RTCState {
62 63 struct tm current_tm;
63 64 int base_year;
64 65 qemu_irq irq;
  66 + qemu_irq sqw_irq;
65 67 int it_shift;
66 68 /* periodic timer */
67 69 QEMUTimer *periodic_timer;
... ... @@ -95,16 +97,20 @@ static void rtc_timer_update(RTCState *s, int64_t current_time)
95 97 {
96 98 int period_code, period;
97 99 int64_t cur_clock, next_irq_clock;
  100 + int enable_pie;
98 101  
99 102 period_code = s->cmos_data[RTC_REG_A] & 0x0f;
100 103 #if defined TARGET_I386 || defined TARGET_X86_64
101 104 /* disable periodic timer if hpet is in legacy mode, since interrupts are
102 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 108 #else
106   - if (period_code != 0 && (s->cmos_data[RTC_REG_B] & REG_B_PIE)) {
  109 + enable_pie = 1;
107 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 114 if (period_code <= 2)
109 115 period_code += 7;
110 116 /* period in 32 Khz cycles */
... ... @@ -138,8 +144,15 @@ static void rtc_periodic_timer(void *opaque)
138 144 return;
139 145 }
140 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 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 540 }
528 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 545 RTCState *s;
533 546  
534 547 s = qemu_mallocz(sizeof(RTCState));
535 548  
536 549 s->irq = irq;
  550 + s->sqw_irq = sqw_irq;
537 551 s->cmos_data[RTC_REG_A] = 0x26;
538 552 s->cmos_data[RTC_REG_B] = 0x02;
539 553 s->cmos_data[RTC_REG_C] = 0x00;
... ... @@ -563,6 +577,11 @@ RTCState *rtc_init(int base, qemu_irq irq, int base_year)
563 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 585 /* Memory mapped interface */
567 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 90 typedef struct RTCState RTCState;
91 91  
92 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 94 RTCState *rtc_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq,
94 95 int base_year);
95 96 void rtc_set_memory(RTCState *s, int addr, int val);
... ...