aboutsummaryrefslogtreecommitdiff
path: root/hw/timer
diff options
context:
space:
mode:
authorLiu Ping Fan <qemulist@gmail.com>2013-12-08 17:38:16 +0800
committerMichael S. Tsirkin <mst@redhat.com>2013-12-11 20:11:08 +0200
commit0d63b2dd31464cfccc80bbeedc24e3863fe4c895 (patch)
tree4c7b362d3ab3320b66898824532275877a49d42e /hw/timer
parent4c41425d2e79f267b2236da31abedb866777d92f (diff)
downloadqemu-0d63b2dd31464cfccc80bbeedc24e3863fe4c895.zip
qemu-0d63b2dd31464cfccc80bbeedc24e3863fe4c895.tar.gz
qemu-0d63b2dd31464cfccc80bbeedc24e3863fe4c895.tar.bz2
hpet: inverse polarity when pin above ISA_NUM_IRQS
According to hpet spec, hpet irq is high active. But according to ICH spec, there is inversion before the input of ioapic. So the OS will expect low active on this IRQ line. (On bare metal, if OS driver claims high active on this line, spurious irq is generated) We fold the emulation of this inversion inside the hpet logic. Signed-off-by: Liu Ping Fan <pingfank@linux.vnet.ibm.com> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/timer')
-rw-r--r--hw/timer/hpet.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
index 2eb75ea..0aee2c1 100644
--- a/hw/timer/hpet.c
+++ b/hw/timer/hpet.c
@@ -198,13 +198,23 @@ static void update_irq(struct HPETTimer *timer, int set)
if (!set || !timer_enabled(timer) || !hpet_enabled(timer->state)) {
s->isr &= ~mask;
if (!timer_fsb_route(timer)) {
- qemu_irq_lower(s->irqs[route]);
+ /* fold the ICH PIRQ# pin's internal inversion logic into hpet */
+ if (route >= ISA_NUM_IRQS) {
+ qemu_irq_raise(s->irqs[route]);
+ } else {
+ qemu_irq_lower(s->irqs[route]);
+ }
}
} else if (timer_fsb_route(timer)) {
stl_le_phys(timer->fsb >> 32, timer->fsb & 0xffffffff);
} else if (timer->config & HPET_TN_TYPE_LEVEL) {
s->isr |= mask;
- qemu_irq_raise(s->irqs[route]);
+ /* fold the ICH PIRQ# pin's internal inversion logic into hpet */
+ if (route >= ISA_NUM_IRQS) {
+ qemu_irq_lower(s->irqs[route]);
+ } else {
+ qemu_irq_raise(s->irqs[route]);
+ }
} else {
s->isr &= ~mask;
qemu_irq_pulse(s->irqs[route]);