Commit 0d63b2dd authored by Liu Ping Fan's avatar Liu Ping Fan Committed by Michael S. Tsirkin
Browse files

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: default avatarLiu Ping Fan <pingfank@linux.vnet.ibm.com>
Reviewed-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
Reviewed-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent 4c41425d
Loading
Loading
Loading
Loading
+12 −2
Original line number Original line Diff line number Diff line
@@ -198,13 +198,23 @@ static void update_irq(struct HPETTimer *timer, int set)
    if (!set || !timer_enabled(timer) || !hpet_enabled(timer->state)) {
    if (!set || !timer_enabled(timer) || !hpet_enabled(timer->state)) {
        s->isr &= ~mask;
        s->isr &= ~mask;
        if (!timer_fsb_route(timer)) {
        if (!timer_fsb_route(timer)) {
            /* 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]);
                qemu_irq_lower(s->irqs[route]);
            }
            }
        }
    } else if (timer_fsb_route(timer)) {
    } else if (timer_fsb_route(timer)) {
        stl_le_phys(timer->fsb >> 32, timer->fsb & 0xffffffff);
        stl_le_phys(timer->fsb >> 32, timer->fsb & 0xffffffff);
    } else if (timer->config & HPET_TN_TYPE_LEVEL) {
    } else if (timer->config & HPET_TN_TYPE_LEVEL) {
        s->isr |= mask;
        s->isr |= mask;
        /* 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]);
            qemu_irq_raise(s->irqs[route]);
        }
    } else {
    } else {
        s->isr &= ~mask;
        s->isr &= ~mask;
        qemu_irq_pulse(s->irqs[route]);
        qemu_irq_pulse(s->irqs[route]);