Properly setup the IO APIC for ISA and pciide compat interrupts too.

Makes ACPI kernels works again with pciide controllers in compat mode.
This commit is contained in:
bouyer 2007-11-18 18:44:17 +00:00
parent 2795528241
commit 29d8eba17f
2 changed files with 102 additions and 11 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: isa_machdep.c,v 1.8 2007/02/22 21:38:23 bouyer Exp $ */
/* $NetBSD: isa_machdep.c,v 1.9 2007/11/18 18:44:17 bouyer Exp $ */
/* NetBSD isa_machdep.c,v 1.11 2004/06/20 18:04:08 thorpej Exp */
/*-
@ -73,7 +73,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: isa_machdep.c,v 1.8 2007/02/22 21:38:23 bouyer Exp $");
__KERNEL_RCSID(0, "$NetBSD: isa_machdep.c,v 1.9 2007/11/18 18:44:17 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -95,6 +95,15 @@ __KERNEL_RCSID(0, "$NetBSD: isa_machdep.c,v 1.8 2007/02/22 21:38:23 bouyer Exp $
#include <uvm/uvm_extern.h>
#ifdef XEN3
#include "ioapic.h"
#endif
#if NIOAPIC > 0
#include <machine/i82093var.h>
#include <machine/mpconfig.h>
#endif
static int _isa_dma_may_bounce(bus_dma_tag_t, bus_dmamap_t, int, int *);
struct x86_bus_dma_tag isa_bus_dma_tag = {
@ -152,11 +161,42 @@ isa_intr_establish(ic, irq, type, level, ih_fun, ih_arg)
{
int evtch;
char evname[8];
struct xen_intr_handle ih;
#if NIOAPIC > 0
struct pic *pic = NULL;
#endif
evtch = bind_pirq_to_evtch(irq);
ih.pirq = irq;
#if NIOAPIC > 0
if (mp_busses != NULL) {
if (intr_find_mpmapping(mp_isa_bus, irq, &ih) == 0 ||
intr_find_mpmapping(mp_eisa_bus, irq, &ih) == 0) {
if (!APIC_IRQ_ISLEGACY(ih.pirq)) {
pic = (struct pic *)
ioapic_find(APIC_IRQ_APIC(ih.pirq));
if (pic == NULL) {
printf("isa_intr_establish: "
"unknown apic %d\n",
APIC_IRQ_APIC(ih.pirq));
return NULL;
}
}
} else
printf("isa_intr_establish: no MP mapping found\n");
}
#endif
evtch = xen_intr_map(&ih.pirq, type);
if (evtch == -1)
return NULL;
snprintf(evname, sizeof(evname), "irq%d", irq);
#if NIOAPIC > 0
if (pic)
snprintf(evname, sizeof(evname), "%s pin %d",
pic->pic_name, APIC_IRQ_PIN(ih.pirq));
else
#endif
snprintf(evname, sizeof(evname), "irq%d", irq);
return (void *)pirq_establish(irq, evtch, ih_fun, ih_arg, level,
evname);

View File

@ -1,4 +1,4 @@
/* $NetBSD: pciide_machdep.c,v 1.6 2006/09/28 18:53:16 bouyer Exp $ */
/* $NetBSD: pciide_machdep.c,v 1.7 2007/11/18 18:44:17 bouyer Exp $ */
/*
* Copyright (c) 1998 Christopher G. Demetriou. All rights reserved.
@ -41,7 +41,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: pciide_machdep.c,v 1.6 2006/09/28 18:53:16 bouyer Exp $");
__KERNEL_RCSID(0, "$NetBSD: pciide_machdep.c,v 1.7 2007/11/18 18:44:17 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -54,6 +54,15 @@ __KERNEL_RCSID(0, "$NetBSD: pciide_machdep.c,v 1.6 2006/09/28 18:53:16 bouyer Ex
#include <machine/evtchn.h>
#ifdef XEN3
#include "ioapic.h"
#endif
#if NIOAPIC > 0
#include <machine/i82093var.h>
#include <machine/mpbiosvar.h>
#endif
void *
pciide_machdep_compat_intr_establish(dev, pa, chan, func, arg)
struct device *dev;
@ -64,6 +73,12 @@ pciide_machdep_compat_intr_establish(dev, pa, chan, func, arg)
{
struct pintrhand *ih;
char evname[8];
struct xen_intr_handle xenih;
#if NIOAPIC > 0
struct pic *pic = NULL;
#endif
int evtch;
#ifndef XEN3
physdev_op_t physdev_op;
@ -74,15 +89,51 @@ pciide_machdep_compat_intr_establish(dev, pa, chan, func, arg)
if (HYPERVISOR_physdev_op(&physdev_op) < 0)
panic("HYPERVISOR_physdev_op(PHYSDEVOP_PCI_INITIALISE_DEVICE)");
#endif /* !XEN3 */
snprintf(evname, sizeof(evname), "irq%d", PCIIDE_COMPAT_IRQ(chan));
xenih.pirq = PCIIDE_COMPAT_IRQ(chan);
#if NIOAPIC > 0
if (mp_busses != NULL) {
if (intr_find_mpmapping(mp_isa_bus, xenih.pirq, &xenih) == 0 ||
intr_find_mpmapping(mp_eisa_bus, xenih.pirq, &xenih) == 0) {
if (!APIC_IRQ_ISLEGACY(xenih.pirq)) {
pic = (struct pic *)
ioapic_find(APIC_IRQ_APIC(xenih.pirq));
if (pic == NULL) {
printf("pciide_machdep_compat_intr_establish: "
"unknown apic %d\n",
APIC_IRQ_APIC(xenih.pirq));
return NULL;
}
}
} else
printf("pciide_machdep_compat_intr_establish: "
"no MP mapping found\n");
}
#endif
evtch = xen_intr_map(&xenih.pirq, IST_EDGE);
if (evtch == -1)
return NULL;
#if NIOAPIC > 0
if (pic)
snprintf(evname, sizeof(evname), "%s pin %d",
pic->pic_name, APIC_IRQ_PIN(xenih.pirq));
else
#endif
snprintf(evname, sizeof(evname), "irq%d",
PCIIDE_COMPAT_IRQ(chan));
ih = pirq_establish(PCIIDE_COMPAT_IRQ(chan),
bind_pirq_to_evtch(PCIIDE_COMPAT_IRQ(chan)), func, arg, IPL_BIO,
evname);
evtch, func, arg, IPL_BIO, evname);
if (ih == NULL)
return NULL;
printf("%s: %s channel using event channel %d for irq %d\n",
dev->dv_xname, PCIIDE_CHANNEL_NAME(chan), ih->evtch, ih->pirq);
printf("%s: %s channel interrupting at ",
dev->dv_xname, PCIIDE_CHANNEL_NAME(chan));
#if NIOAPIC > 0
if (pic)
printf("%s pin %d", pic->pic_name, APIC_IRQ_PIN(xenih.pirq));
else
#endif
printf("irq %d", ih->pirq);
printf(", event channel %d\n", ih->evtch);
return (void *)ih;
}