Patch: Defer bus_config_intr() until bus_alloc_resource()..
John Baldwin
jhb at FreeBSD.org
Tue Jun 1 12:30:33 PDT 2004
I need the patch below in order to turn on bus_config_intr() when using the
I/O APICs. The original problem is that the _CRS of link devices is
configured which is the PIC IRQ and thus screws up intpins when using the
APIC. It basically takes bus_config_intr() out of the resource parsing code
and does the config when an IRQ is allocated via bus_alloc_resource() for
normal devices, and when a PCI IRQ is routed for PCI link devices.
--- //depot/vendor/freebsd/src/sys/dev/acpica/acpi.c 2004/05/06 01:05:39
+++ //depot/user/jhb/acpipci/dev/acpica/acpi.c 2004/05/28 10:02:20
@@ -849,15 +849,82 @@
return (0);
}
+static void
+acpi_config_intr(device_t dev, u_int irq, int trig, int pol)
+{
+
+ BUS_CONFIG_INTR(dev, irq, (trig == ACPI_EDGE_SENSITIVE) ?
+ INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL, (pol == ACPI_ACTIVE_HIGH) ?
+ INTR_POLARITY_HIGH : INTR_POLARITY_LOW);
+}
+
static struct resource *
acpi_alloc_resource(device_t bus, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
struct acpi_device *ad = device_get_ivars(child);
struct resource_list *rl = &ad->ad_rl;
+ struct resource *res;
+ ACPI_RESOURCE *ares;
+ ACPI_BUFFER buf;
+ char *curr, *last;
+ int i;
- return (resource_list_alloc(rl, bus, child, type, rid, start, end, count,
- flags));
+ res = resource_list_alloc(rl, bus, child, type, rid, start, end, count,
+ flags);
+ if (res == NULL || device_get_parent(child) != bus)
+ return (res);
+ switch (type) {
+ case SYS_RES_IRQ:
+ buf.Length = ACPI_ALLOCATE_BUFFER;
+ if (ACPI_FAILURE((AcpiGetCurrentResources(ad->ad_handle, &buf))))
+ break;
+ i = 0;
+ curr = buf.Pointer;
+ last = (char *)buf.Pointer + buf.Length;
+ while (curr < last) {
+ ares = (ACPI_RESOURCE *)curr;
+ curr += ares->Length;
+ switch (ares->Id) {
+ case ACPI_RSTYPE_END_TAG:
+ curr = last;
+ break;
+ case ACPI_RSTYPE_IRQ:
+ if (ares->Data.Irq.NumberOfInterrupts != 1)
+ break;
+ if (i != *rid) {
+ i++;
+ break;
+ }
+ KASSERT(ares->Data.Irq.Interrupts[0] ==
+ rman_get_start(res),
+ ("IRQ resources do not match"));
+ acpi_config_intr(child,
+ ares->Data.Irq.Interrupts[0],
+ ares->Data.Irq.EdgeLevel,
+ ares->Data.Irq.ActiveHighLow);
+ break;
+ case ACPI_RSTYPE_EXT_IRQ:
+ if (ares->Data.ExtendedIrq.NumberOfInterrupts != 1)
+ break;
+ if (i != *rid) {
+ i++;
+ break;
+ }
+ KASSERT(ares->Data.ExtendedIrq.Interrupts[0] ==
+ rman_get_start(res),
+ ("IRQ resources do not match"));
+ acpi_config_intr(child,
+ ares->Data.ExtendedIrq.Interrupts[0],
+ ares->Data.ExtendedIrq.EdgeLevel,
+ ares->Data.ExtendedIrq.ActiveHighLow);
+ break;
+ }
+ }
+ AcpiOsFree(buf.Pointer);
+ break;
+ }
+ return (res);
}
static int
--- //depot/vendor/freebsd/src/sys/dev/acpica/acpi_pcib.c 2004/05/05 19:22:26
+++ //depot/user/jhb/acpipci/dev/acpica/acpi_pcib.c 2004/05/28 06:38:57
@@ -121,10 +121,11 @@
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
+ crsres = NULL;
buf.Pointer = NULL;
crsbuf.Pointer = NULL;
prsbuf.Pointer = NULL;
- interrupt = 255;
+ interrupt = PCI_INVALID_IRQ;
/* ACPI numbers pins 0-3, not 1-4 like the BIOS. */
pin--;
@@ -348,6 +349,7 @@
/* XXX Data.Irq and Data.ExtendedIrq are implicitly structure-copied. */
crsbuf.Pointer = NULL;
+ crsres = NULL;
if (prsres->Id == ACPI_RSTYPE_IRQ) {
resbuf.Id = ACPI_RSTYPE_IRQ;
resbuf.Length = ACPI_SIZEOF_RESOURCE(ACPI_RESOURCE_IRQ);
@@ -378,6 +380,7 @@
AcpiFormatException(status));
goto out;
}
+ crsres = &resbuf;
/* Return the interrupt we just routed. */
device_printf(pcib, "slot %d INT%c routed to irq %d via %s\n",
@@ -386,6 +389,20 @@
interrupt = Interrupts[0];
out:
+ if (PCI_INTERRUPT_VALID(interrupt) && crsres != NULL) {
+ int trig, pol;
+
+ if (crsres->Id == ACPI_RSTYPE_IRQ) {
+ trig = crsres->Data.Irq.EdgeLevel;
+ pol = crsres->Data.Irq.ActiveHighLow;
+ } else {
+ trig = crsres->Data.ExtendedIrq.EdgeLevel;
+ pol = crsres->Data.ExtendedIrq.ActiveHighLow;
+ }
+ BUS_CONFIG_INTR(dev, interrupt, (trig == ACPI_EDGE_SENSITIVE) ?
+ INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL, (pol == ACPI_ACTIVE_HIGH) ?
+ INTR_POLARITY_HIGH : INTR_POLARITY_LOW);
+ }
if (crsbuf.Pointer != NULL)
AcpiOsFree(crsbuf.Pointer);
if (prsbuf.Pointer != NULL)
@@ -393,6 +410,5 @@
if (buf.Pointer != NULL)
AcpiOsFree(buf.Pointer);
- /* XXX APIC_IO interrupt mapping? */
return_VALUE (interrupt);
}
--- //depot/vendor/freebsd/src/sys/dev/acpica/acpi_resource.c 2004/04/09
11:15:38
+++ //depot/user/jhb/acpipci/dev/acpica/acpi_resource.c 2004/05/28 10:02:20
@@ -495,9 +495,6 @@
return;
bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1);
- BUS_CONFIG_INTR(dev, *irq, (trig == ACPI_EDGE_SENSITIVE) ?
- INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL, (pol == ACPI_ACTIVE_HIGH) ?
- INTR_POLARITY_HIGH : INTR_POLARITY_LOW);
}
static void
--
John Baldwin <jhb at FreeBSD.org> <>< http://www.FreeBSD.org/~jhb/
"Power Users Use the Power to Serve" = http://www.FreeBSD.org
More information about the freebsd-acpi
mailing list