Revision 7d932dfd hw/hpet.c
b/hw/hpet.c | ||
---|---|---|
30 | 30 |
#include "qemu-timer.h" |
31 | 31 |
#include "hpet_emul.h" |
32 | 32 |
#include "sysbus.h" |
33 |
#include "mc146818rtc.h" |
|
33 | 34 |
|
34 | 35 |
//#define HPET_DEBUG |
35 | 36 |
#ifdef HPET_DEBUG |
... | ... | |
58 | 59 |
SysBusDevice busdev; |
59 | 60 |
uint64_t hpet_offset; |
60 | 61 |
qemu_irq irqs[HPET_NUM_IRQ_ROUTES]; |
62 |
uint8_t rtc_irq_level; |
|
61 | 63 |
HPETTimer timer[HPET_NUM_TIMERS]; |
62 | 64 |
|
63 | 65 |
/* Memory-mapped, software visible registers */ |
... | ... | |
69 | 71 |
|
70 | 72 |
static HPETState *hpet_statep; |
71 | 73 |
|
72 |
uint32_t hpet_in_legacy_mode(void)
|
|
74 |
static uint32_t hpet_in_legacy_mode(HPETState *s)
|
|
73 | 75 |
{ |
74 |
if (!hpet_statep) { |
|
75 |
return 0; |
|
76 |
} |
|
77 |
return hpet_statep->config & HPET_CFG_LEGACY; |
|
76 |
return s->config & HPET_CFG_LEGACY; |
|
78 | 77 |
} |
79 | 78 |
|
80 | 79 |
static uint32_t timer_int_route(struct HPETTimer *timer) |
... | ... | |
166 | 165 |
{ |
167 | 166 |
int route; |
168 | 167 |
|
169 |
if (timer->tn <= 1 && hpet_in_legacy_mode()) { |
|
168 |
if (timer->tn <= 1 && hpet_in_legacy_mode(timer->state)) {
|
|
170 | 169 |
/* if LegacyReplacementRoute bit is set, HPET specification requires |
171 | 170 |
* timer0 be routed to IRQ0 in NON-APIC or IRQ2 in the I/O APIC, |
172 | 171 |
* timer1 be routed to IRQ8 in NON-APIC or IRQ8 in the I/O APIC. |
173 | 172 |
*/ |
174 |
route = (timer->tn == 0) ? 0 : 8;
|
|
173 |
route = (timer->tn == 0) ? 0 : RTC_ISA_IRQ;
|
|
175 | 174 |
} else { |
176 | 175 |
route = timer_int_route(timer); |
177 | 176 |
} |
... | ... | |
515 | 514 |
/* i8254 and RTC are disabled when HPET is in legacy mode */ |
516 | 515 |
if (activating_bit(old_val, new_val, HPET_CFG_LEGACY)) { |
517 | 516 |
hpet_pit_disable(); |
517 |
qemu_irq_lower(s->irqs[RTC_ISA_IRQ]); |
|
518 | 518 |
} else if (deactivating_bit(old_val, new_val, HPET_CFG_LEGACY)) { |
519 | 519 |
hpet_pit_enable(); |
520 |
qemu_set_irq(s->irqs[RTC_ISA_IRQ], s->rtc_irq_level); |
|
520 | 521 |
} |
521 | 522 |
break; |
522 | 523 |
case HPET_CFG + 4: |
... | ... | |
607 | 608 |
count = 1; |
608 | 609 |
} |
609 | 610 |
|
611 |
static void hpet_handle_rtc_irq(void *opaque, int n, int level) |
|
612 |
{ |
|
613 |
HPETState *s = FROM_SYSBUS(HPETState, opaque); |
|
614 |
|
|
615 |
s->rtc_irq_level = level; |
|
616 |
if (!hpet_in_legacy_mode(s)) { |
|
617 |
qemu_set_irq(s->irqs[RTC_ISA_IRQ], level); |
|
618 |
} |
|
619 |
} |
|
620 |
|
|
610 | 621 |
static int hpet_init(SysBusDevice *dev) |
611 | 622 |
{ |
612 | 623 |
HPETState *s = FROM_SYSBUS(HPETState, dev); |
... | ... | |
625 | 636 |
timer->state = s; |
626 | 637 |
} |
627 | 638 |
|
639 |
isa_reserve_irq(RTC_ISA_IRQ); |
|
640 |
qdev_init_gpio_in(&dev->qdev, hpet_handle_rtc_irq, 1); |
|
641 |
|
|
628 | 642 |
/* HPET Area */ |
629 | 643 |
iomemtype = cpu_register_io_memory(hpet_ram_read, |
630 | 644 |
hpet_ram_write, s); |
Also available in: Unified diff