From owner-freebsd-acpi@FreeBSD.ORG Tue Jun 1 12:30:33 2004 Return-Path: Delivered-To: freebsd-acpi@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 21DA116A582 for ; Tue, 1 Jun 2004 12:30:33 -0700 (PDT) Received: from mail6.speakeasy.net (mail6.speakeasy.net [216.254.0.206]) by mx1.FreeBSD.org (Postfix) with ESMTP id 2B5F843D54 for ; Tue, 1 Jun 2004 12:30:32 -0700 (PDT) (envelope-from jhb@FreeBSD.org) Received: (qmail 4543 invoked from network); 1 Jun 2004 19:30:31 -0000 Received: from dsl027-160-063.atl1.dsl.speakeasy.net (HELO server.baldwin.cx) ([216.27.160.63]) (envelope-sender ) encrypted SMTP for ; 1 Jun 2004 19:30:31 -0000 Received: from 10.50.41.233 (gw1.twc.weather.com [216.133.140.1]) by server.baldwin.cx (8.12.11/8.12.11) with ESMTP id i51JUQ04058615; Tue, 1 Jun 2004 15:30:26 -0400 (EDT) (envelope-from jhb@FreeBSD.org) From: John Baldwin To: acpi@FreeBSD.org Date: Tue, 1 Jun 2004 15:31:09 -0400 User-Agent: KMail/1.6 MIME-Version: 1.0 Content-Disposition: inline Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Message-Id: <200406011531.09077.jhb@FreeBSD.org> X-Spam-Checker-Version: SpamAssassin 2.63 (2004-01-11) on server.baldwin.cx cc: marcel@FreeBSD.org Subject: Patch: Defer bus_config_intr() until bus_alloc_resource().. X-BeenThere: freebsd-acpi@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: ACPI and power management development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 01 Jun 2004 19:30:33 -0000 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 <>< http://www.FreeBSD.org/~jhb/ "Power Users Use the Power to Serve" = http://www.FreeBSD.org