PERFORCE change 65745 for review

John Baldwin jhb at FreeBSD.org
Tue Nov 23 23:10:50 GMT 2004


http://perforce.freebsd.org/chv.cgi?CH=65745

Change 65745 by jhb at jhb_slimer on 2004/11/23 23:10:26

	IFC @65733.

Affected files ...

.. //depot/projects/smpng/sys/alpha/alpha/interrupt.c#31 integrate
.. //depot/projects/smpng/sys/arm/arm/intr.c#5 integrate
.. //depot/projects/smpng/sys/arm/xscale/i80321/uart_bus_i80321.c#2 integrate
.. //depot/projects/smpng/sys/arm/xscale/i80321/uart_cpu_i80321.c#2 integrate
.. //depot/projects/smpng/sys/boot/Makefile#17 integrate
.. //depot/projects/smpng/sys/boot/efi/Makefile#2 integrate
.. //depot/projects/smpng/sys/boot/efi/libefi/arch/ia64/ldscript.ia64#7 delete
.. //depot/projects/smpng/sys/boot/efi/libefi/arch/ia64/start.S#7 delete
.. //depot/projects/smpng/sys/boot/efi/loader/Makefile#12 delete
.. //depot/projects/smpng/sys/boot/efi/loader/conf.c#9 delete
.. //depot/projects/smpng/sys/boot/efi/loader/main.c#15 delete
.. //depot/projects/smpng/sys/boot/efi/loader/version#5 delete
.. //depot/projects/smpng/sys/boot/ia64/Makefile#4 integrate
.. //depot/projects/smpng/sys/boot/ia64/efi/Makefile#1 branch
.. //depot/projects/smpng/sys/boot/ia64/efi/conf.c#1 branch
.. //depot/projects/smpng/sys/boot/ia64/efi/ldscript.ia64#1 branch
.. //depot/projects/smpng/sys/boot/ia64/efi/main.c#1 branch
.. //depot/projects/smpng/sys/boot/ia64/efi/start.S#1 branch
.. //depot/projects/smpng/sys/boot/ia64/efi/version#1 branch
.. //depot/projects/smpng/sys/conf/files.alpha#32 integrate
.. //depot/projects/smpng/sys/conf/files.amd64#24 integrate
.. //depot/projects/smpng/sys/conf/files.arm#3 integrate
.. //depot/projects/smpng/sys/conf/files.i386#71 integrate
.. //depot/projects/smpng/sys/conf/files.ia64#46 integrate
.. //depot/projects/smpng/sys/conf/files.pc98#65 integrate
.. //depot/projects/smpng/sys/dev/acpica/acpi_pci_link.c#23 integrate
.. //depot/projects/smpng/sys/dev/acpica/acpi_pcib.c#27 integrate
.. //depot/projects/smpng/sys/dev/acpica/acpi_pcib_acpi.c#17 integrate
.. //depot/projects/smpng/sys/dev/acpica/acpi_pcib_pci.c#8 integrate
.. //depot/projects/smpng/sys/dev/acpica/acpi_pcibvar.h#4 integrate
.. //depot/projects/smpng/sys/geom/gate/g_gate.c#8 integrate
.. //depot/projects/smpng/sys/kern/sys_pipe.c#49 integrate
.. //depot/projects/smpng/sys/netgraph/ng_cisco.c#10 integrate
.. //depot/projects/smpng/sys/netgraph/ng_iface.c#16 integrate
.. //depot/projects/smpng/sys/netgraph/ng_one2many.c#11 integrate
.. //depot/projects/smpng/sys/netgraph/ng_one2many.h#4 integrate
.. //depot/projects/smpng/sys/netinet/tcp_input.c#63 integrate
.. //depot/projects/smpng/sys/netinet/tcp_subr.c#59 integrate
.. //depot/projects/smpng/sys/netinet/tcp_timer.c#20 integrate

Differences ...

==== //depot/projects/smpng/sys/alpha/alpha/interrupt.c#31 (text+ko) ====

@@ -33,7 +33,7 @@
 
 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
 /* __KERNEL_RCSID(0, "$NetBSD: interrupt.c,v 1.23 1998/02/24 07:38:01 thorpej Exp $");*/
-__FBSDID("$FreeBSD: src/sys/alpha/alpha/interrupt.c,v 1.82 2004/07/20 06:32:32 alc Exp $");
+__FBSDID("$FreeBSD: src/sys/alpha/alpha/interrupt.c,v 1.83 2004/11/23 22:11:53 jhb Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -474,7 +474,7 @@
 		/*
 		 * Only one processor drives the actual timer.
 		 */
-		if (PCPU_GET(cpuid) == boot_cpu_id) {
+		if (PCPU_GET(cpuid) == 0) {
 #endif
 			(*platform.clockintr)(framep);
 			/* divide hz (1024) by 8 to get stathz (128) */

==== //depot/projects/smpng/sys/arm/arm/intr.c#5 (text+ko) ====

@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/arm/arm/intr.c,v 1.4 2004/11/12 21:49:05 cognet Exp $");
+__FBSDID("$FreeBSD: src/sys/arm/arm/intr.c,v 1.5 2004/11/23 16:31:16 cognet Exp $");
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/syslog.h> 
@@ -139,17 +139,16 @@
 			continue;
 		ih = TAILQ_FIRST(&ithd->it_handlers);
 		if (ih && ih->ih_flags & IH_FAST) {
+			oldirqstate = disable_interrupts(I32_bit);
 			TAILQ_FOREACH(ih, &ithd->it_handlers,
 			    ih_next) {
 				ih->ih_handler(ih->ih_argument ?
 				    ih->ih_argument : frame);
 			}
+			restore_interrupts(oldirqstate);
 			arm_unmask_irqs(1 << i);
-		} else if (ih) {
-			oldirqstate = enable_interrupts(I32_bit);
+		} else if (ih)
 			ithread_schedule(ithd);
-			restore_interrupts(oldirqstate);
-		}
 		irqnb |= arm_get_irqnb(frame);
 	}
 	td->td_intr_nesting_level--;

==== //depot/projects/smpng/sys/arm/xscale/i80321/uart_bus_i80321.c#2 (text+ko) ====

@@ -23,7 +23,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/arm/xscale/i80321/uart_bus_i80321.c,v 1.1 2004/09/23 22:45:36 cognet Exp $");
+__FBSDID("$FreeBSD: src/sys/arm/xscale/i80321/uart_bus_i80321.c,v 1.2 2004/11/23 16:30:50 cognet Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -59,7 +59,6 @@
 	sizeof(struct uart_softc),
 };
 
-extern struct uart_class uart_i8251_class;
 extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
 static int
 uart_i80321_probe(device_t dev)
@@ -68,7 +67,7 @@
 
 	sc = device_get_softc(dev);
 	sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs);
-	sc->sc_class = &uart_i8251_class;
+	sc->sc_class = &uart_ns8250_class;
 	bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas));
 	return(uart_bus_probe(dev, 0, 0, 0, 0));
 }

==== //depot/projects/smpng/sys/arm/xscale/i80321/uart_cpu_i80321.c#2 (text+ko) ====

@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/arm/xscale/i80321/uart_cpu_i80321.c,v 1.1 2004/09/23 22:45:36 cognet Exp $");
+__FBSDID("$FreeBSD: src/sys/arm/xscale/i80321/uart_cpu_i80321.c,v 1.2 2004/11/23 16:30:50 cognet Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -55,7 +55,7 @@
 int
 uart_cpu_getdev(int devtype, struct uart_devinfo *di)
 {
-	di->ops = uart_i8251_ops;
+	di->ops = uart_ns8250_ops;
 	di->bas.chan = 0;
 	di->bas.bst = &obio_bs_tag;
 	di->bas.regshft = 0;

==== //depot/projects/smpng/sys/boot/Makefile#17 (text+ko) ====

@@ -1,10 +1,15 @@
-# $FreeBSD: src/sys/boot/Makefile,v 1.24 2004/08/16 15:45:24 marius Exp $
+# $FreeBSD: src/sys/boot/Makefile,v 1.25 2004/11/23 05:52:00 marcel Exp $
 
 .if !defined(NOFORTH)
 # Build the add-in FORTH interpreter.
 SUBDIR+=		ficl
 .endif
 
+# Build EFI library.
+.if ${MACHINE_ARCH} == "ia64"
+SUBDIR+=		efi
+.endif
+
 # Build Open Firmware library.
 .if ${MACHINE_ARCH} == "powerpc" || ${MACHINE_ARCH} == "sparc64"
 SUBDIR+=		ofw
@@ -19,9 +24,4 @@
 #SUBDIR+=		arc
 #.endif
 
-# Build EFI executable on ia64.
-.if ${MACHINE_ARCH} == "ia64"
-SUBDIR+=		efi
-.endif
-
 .include <bsd.subdir.mk>

==== //depot/projects/smpng/sys/boot/efi/Makefile#2 (text+ko) ====

@@ -1,5 +1,5 @@
-# $FreeBSD: src/sys/boot/efi/Makefile,v 1.1 2001/06/09 16:49:48 dfr Exp $
+# $FreeBSD: src/sys/boot/efi/Makefile,v 1.2 2004/11/23 06:04:51 marcel Exp $
 
-SUBDIR=		libefi loader
+SUBDIR=		libefi
 
 .include <bsd.subdir.mk>

==== //depot/projects/smpng/sys/boot/ia64/Makefile#4 (text+ko) ====

@@ -1,5 +1,5 @@
-# $FreeBSD: src/sys/boot/ia64/Makefile,v 1.3 2004/09/24 04:21:14 marcel Exp $
+# $FreeBSD: src/sys/boot/ia64/Makefile,v 1.4 2004/11/23 06:03:03 marcel Exp $
 
-SUBDIR=		ski
+SUBDIR=		efi ski
 
 .include <bsd.subdir.mk>

==== //depot/projects/smpng/sys/conf/files.alpha#32 (text+ko) ====

@@ -1,7 +1,7 @@
 # This file tells config what files go into building a kernel,
 # files marked standard are always included.
 #
-# $FreeBSD: src/sys/conf/files.alpha,v 1.114 2004/08/01 11:40:51 markm Exp $
+# $FreeBSD: src/sys/conf/files.alpha,v 1.115 2004/11/23 00:00:43 imp Exp $
 #
 # The long compile-with and dependency lines are required because of
 # limitations in config: backslash-newline doesn't work in strings, and
@@ -179,7 +179,6 @@
 dev/kbd/atkbd.c			optional	atkbd
 dev/kbd/atkbdc.c		optional	atkbdc
 dev/kbd/kbd.c			optional	atkbd
-dev/kbd/kbd.c			optional	kbd
 dev/kbd/kbd.c			optional	sc
 dev/kbd/kbd.c			optional	ukbd
 dev/ppc/ppc.c			optional        ppc

==== //depot/projects/smpng/sys/conf/files.amd64#24 (text+ko) ====

@@ -1,7 +1,7 @@
 # This file tells config what files go into building a kernel,
 # files marked standard are always included.
 #
-# $FreeBSD: src/sys/conf/files.amd64,v 1.50 2004/09/28 07:29:54 markm Exp $
+# $FreeBSD: src/sys/conf/files.amd64,v 1.51 2004/11/23 00:00:43 imp Exp $
 #
 # The long compile-with and dependency lines are required because of
 # limitations in config: backslash-newline doesn't work in strings, and
@@ -123,7 +123,6 @@
 dev/kbd/atkbd.c			optional	atkbd
 dev/kbd/atkbdc.c		optional	atkbdc
 dev/kbd/kbd.c			optional	atkbd
-dev/kbd/kbd.c			optional	kbd
 dev/kbd/kbd.c			optional	sc
 dev/kbd/kbd.c			optional	ukbd
 dev/mem/memutil.c		optional	mem

==== //depot/projects/smpng/sys/conf/files.arm#3 (text+ko) ====

@@ -1,4 +1,4 @@
-# $FreeBSD: src/sys/conf/files.arm,v 1.3 2004/05/14 23:42:54 cognet Exp $
+# $FreeBSD: src/sys/conf/files.arm,v 1.4 2004/11/22 22:20:50 cognet Exp $
 arm/arm/autoconf.c	standard
 arm/arm/bcopy_page.S	standard
 arm/arm/bcopyinout.S		standard
@@ -29,6 +29,7 @@
 arm/arm/intr.c			standard
 arm/arm/locore.S		standard	no-obj
 arm/arm/machdep.c		standard
+arm/arm/mem.c			optional	mem
 arm/arm/nexus.c			optional	nexus
 arm/arm/nexus_io.c		optional	nexus
 arm/arm/nexus_io_asm.S		optional	nexus

==== //depot/projects/smpng/sys/conf/files.i386#71 (text+ko) ====

@@ -1,7 +1,7 @@
 # This file tells config what files go into building a kernel,
 # files marked standard are always included.
 #
-# $FreeBSD: src/sys/conf/files.i386,v 1.508 2004/11/15 05:54:14 imp Exp $
+# $FreeBSD: src/sys/conf/files.i386,v 1.509 2004/11/23 00:00:43 imp Exp $
 #
 # The long compile-with and dependency lines are required because of
 # limitations in config: backslash-newline doesn't work in strings, and
@@ -157,7 +157,6 @@
 dev/kbd/atkbd.c			optional	atkbd
 dev/kbd/atkbdc.c		optional	atkbdc
 dev/kbd/kbd.c			optional	atkbd
-dev/kbd/kbd.c			optional	kbd
 dev/kbd/kbd.c			optional	sc
 dev/kbd/kbd.c			optional	ukbd
 dev/kbd/kbd.c			optional	vt

==== //depot/projects/smpng/sys/conf/files.ia64#46 (text+ko) ====

@@ -1,7 +1,7 @@
 # This file tells config what files go into building a kernel,
 # files marked standard are always included.
 #
-# $FreeBSD: src/sys/conf/files.ia64,v 1.73 2004/09/25 04:27:44 marcel Exp $
+# $FreeBSD: src/sys/conf/files.ia64,v 1.74 2004/11/23 00:00:43 imp Exp $
 #
 # The long compile-with and dependency lines are required because of
 # limitations in config: backslash-newline doesn't work in strings, and
@@ -55,7 +55,6 @@
 dev/kbd/atkbd.c			optional	atkbd
 dev/kbd/atkbdc.c		optional	atkbdc
 dev/kbd/kbd.c			optional	atkbd
-dev/kbd/kbd.c			optional	kbd
 dev/kbd/kbd.c			optional	sc
 dev/kbd/kbd.c			optional	ukbd
 dev/ppc/ppc.c			optional	ppc isa

==== //depot/projects/smpng/sys/conf/files.pc98#65 (text+ko) ====

@@ -3,7 +3,7 @@
 #
 # modified for PC-9801
 #
-# $FreeBSD: src/sys/conf/files.pc98,v 1.306 2004/08/30 23:03:56 peter Exp $
+# $FreeBSD: src/sys/conf/files.pc98,v 1.307 2004/11/23 00:00:43 imp Exp $
 #
 # The long compile-with and dependency lines are required because of
 # limitations in config: backslash-newline doesn't work in strings, and
@@ -105,7 +105,6 @@
 dev/fb/fb.c			optional	gdc
 dev/fb/splash.c			optional	splash
 dev/fe/if_fe_cbus.c		optional	fe isa
-dev/kbd/kbd.c			optional	kbd
 dev/kbd/kbd.c			optional	sc
 dev/kbd/kbd.c			optional	ukbd
 dev/kbd/kbd.c			optional	pckbd

==== //depot/projects/smpng/sys/dev/acpica/acpi_pci_link.c#23 (text+ko) ====

@@ -25,17 +25,22 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_pci_link.c,v 1.33 2004/09/25 06:15:56 njl Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_pci_link.c,v 1.34 2004/11/23 22:26:44 jhb Exp $");
 
 #include "opt_acpi.h"
 #include <sys/param.h>
+#include <sys/bus.h>
 #include <sys/kernel.h>
-#include <sys/bus.h>
+#include <sys/limits.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
 
 #include "acpi.h"
 #include <dev/acpica/acpivar.h>
 #include <dev/acpica/acpi_pcibvar.h>
 
+#include <machine/pci_cfgreg.h>
+#include <dev/pci/pcireg.h>
 #include <dev/pci/pcivar.h>
 #include "pcib_if.h"
 
@@ -43,1119 +48,714 @@
 #define _COMPONENT	ACPI_BUS
 ACPI_MODULE_NAME("PCI_LINK")
 
-TAILQ_HEAD(acpi_pci_link_entries, acpi_pci_link_entry);
-static struct acpi_pci_link_entries acpi_pci_link_entries;
 ACPI_SERIAL_DECL(pci_link, "ACPI PCI link");
 
-TAILQ_HEAD(acpi_prt_entries, acpi_prt_entry);
-static struct acpi_prt_entries acpi_prt_entries;
+#define NUM_ISA_INTERRUPTS	16
+#define NUM_ACPI_INTERRUPTS	256
+
+/*
+ * An ACPI PCI link device may contain multiple links.  Each link has its
+ * own ACPI resource.  _PRT entries specify which link is being used via
+ * the Source Index.
+ */
+
+struct link;
+
+struct acpi_pci_link_softc {
+	int	pl_num_links;
+	struct link *pl_links;
+};
+
+struct link {
+	struct acpi_pci_link_softc *l_sc;
+	uint8_t	l_bios_irq;
+	uint8_t	l_irq;
+	uint8_t	l_initial_irq;
+	int	l_res_index;
+	int	l_num_irqs;
+	int	*l_irqs;
+	int	l_references;
+	int	l_routed:1;
+	int	l_isa_irq:1;
+	ACPI_RESOURCE l_prs_template;
+};
+
+struct link_res_request {
+	struct acpi_pci_link_softc *sc;
+	int	count;
+};
+
+MALLOC_DEFINE(M_PCI_LINK, "PCI Link", "ACPI PCI Link structures");
 
-static int	irq_penalty[MAX_ACPI_INTERRUPTS];
+static int pci_link_interrupt_weights[NUM_ACPI_INTERRUPTS];
+static int pci_link_bios_isa_irqs;
 
-static int	acpi_pci_link_is_valid_irq(struct acpi_pci_link_entry *link,
-		    UINT8 irq);
-static void	acpi_pci_link_update_irq_penalty(device_t dev, int busno);
-static void	acpi_pci_link_set_bootdisabled_priority(void);
-static void	acpi_pci_link_fixup_bootdisabled_link(void);
+static char *pci_link_ids[] = { "PNP0C0F", NULL };
 
 /*
- * PCI link object management
+ * Fetch the short name associated with an ACPI handle and save it in the
+ * passed in buffer.
  */
-
-static void
-acpi_pci_link_dump_polarity(UINT32 ActiveHighLow)
+static ACPI_STATUS
+acpi_short_name(ACPI_HANDLE handle, char *buffer, size_t buflen)
 {
+	ACPI_BUFFER buf;
 
-	switch (ActiveHighLow) {
-	case ACPI_ACTIVE_HIGH:
-		printf("high,");
-		break;
-	case ACPI_ACTIVE_LOW:
-		printf("low,");
-		break;
-	default:
-		printf("unknown,");
-		break;
-	}
+	buf.Length = buflen;
+	buf.Pointer = buffer;
+	return (AcpiGetName(handle, ACPI_SINGLE_NAME, &buf));
 }
 
-static void
-acpi_pci_link_dump_trigger(UINT32 EdgeLevel)
+static int
+acpi_pci_link_probe(device_t dev)
 {
+	char descr[64], name[10];
 
-	switch (EdgeLevel) {
-	case ACPI_EDGE_SENSITIVE:
-		printf("edge,");
-		break;
-	case ACPI_LEVEL_SENSITIVE:
-		printf("level,");
-		break;
-	default:
-		printf("unknown,");
-		break;
+	/*
+	 * We explicitly do not check _STA since not all systems set it to
+	 * sensible values.
+	 */
+	if (!acpi_disabled("pci_link") &&
+	    ACPI_ID_PROBE(device_get_parent(dev), dev, pci_link_ids) != NULL) {
+		if (ACPI_FAILURE(acpi_short_name(acpi_get_handle(dev), name,
+			    sizeof(name))))
+			device_set_desc(dev, "ACPI PCI Link");
+		else {
+			snprintf(descr, sizeof(descr), "ACPI PCI Link %s",
+			    name);
+			device_set_desc_copy(dev, descr);
+		}
+		return (0);
 	}
+	return (ENXIO);
 }
 
-static void
-acpi_pci_link_dump_sharemode(UINT32 SharedExclusive)
+static ACPI_STATUS
+acpi_count_resources(ACPI_RESOURCE *res, void *context)
 {
+	int *count;
 
-	switch (SharedExclusive) {
-	case ACPI_EXCLUSIVE:
-		printf("exclusive");
-		break;
-	case ACPI_SHARED:
-		printf("sharable");
-		break;
-	default:
-		printf("unknown");
-		break;
-	}
+	count = (int *)context;
+	(*count)++;
+	return (AE_OK);
 }
 
-static void
-acpi_pci_link_entry_dump(struct acpi_prt_entry *entry)
+static ACPI_STATUS
+link_add_crs(ACPI_RESOURCE *res, void *context)
 {
-	UINT8			i;
-	ACPI_RESOURCE_IRQ	*Irq;
-	ACPI_RESOURCE_EXT_IRQ	*ExtIrq;
-	struct acpi_pci_link_entry *link;
+	struct link_res_request *req;
+	struct link *link;
 
-	if (entry == NULL || entry->pci_link == NULL)
-		return;
-	link = entry->pci_link;
-
-	printf("%s irq%c%2d: ", acpi_name(link->handle),
-	    (link->flags & ACPI_LINK_ROUTED) ? '*' : ' ', link->current_irq);
-
-	printf("[");
-	if (link->number_of_interrupts)
-		printf("%2d", link->interrupts[0]);
-	for (i = 1; i < link->number_of_interrupts; i++)
-		printf("%3d", link->interrupts[i]);
-	printf("] %2d+ ", link->initial_irq);
-
-	switch (link->possible_resources.Id) {
+	ACPI_SERIAL_ASSERT(pci_link);
+	req = (struct link_res_request *)context;
+	link = &req->sc->pl_links[req->count];
+	req->count++;
+	switch (res->Id) {
 	case ACPI_RSTYPE_IRQ:
-		Irq = &link->possible_resources.Data.Irq;
-		acpi_pci_link_dump_polarity(Irq->ActiveHighLow);
-		acpi_pci_link_dump_trigger(Irq->EdgeLevel);
-		acpi_pci_link_dump_sharemode(Irq->SharedExclusive);
-		break;
 	case ACPI_RSTYPE_EXT_IRQ:
-		ExtIrq = &link->possible_resources.Data.ExtendedIrq;
-		acpi_pci_link_dump_polarity(ExtIrq->ActiveHighLow);
-		acpi_pci_link_dump_trigger(ExtIrq->EdgeLevel);
-		acpi_pci_link_dump_sharemode(ExtIrq->SharedExclusive);
+		if (res->Id == ACPI_RSTYPE_IRQ) {
+			if (res->Data.Irq.NumberOfInterrupts > 0) {
+				KASSERT(res->Data.Irq.NumberOfInterrupts == 1,
+				    ("%s: too many interrupts", __func__));
+				link->l_irq = res->Data.Irq.Interrupts[0];
+			}
+		} else if (res->Data.ExtendedIrq.NumberOfInterrupts > 0) {
+			KASSERT(res->Data.ExtendedIrq.NumberOfInterrupts == 1,
+			    ("%s: too many interrupts", __func__));
+			link->l_irq = res->Data.ExtendedIrq.Interrupts[0];
+		}
+
+		/*
+		 * An IRQ of zero means that the link isn't routed.
+		 */
+		if (link->l_irq == 0)
+			link->l_irq = PCI_INVALID_IRQ;
 		break;
 	}
-
-	printf(" %d.%d.%d\n", entry->busno,
-	    (int)(ACPI_ADR_PCI_SLOT(entry->prt.Address)),
-	    (int)entry->prt.Pin);
+	return (AE_OK);
 }
 
+/*
+ * Populate the set of possible IRQs for each device.
+ */
 static ACPI_STATUS
-acpi_pci_link_get_object_status(ACPI_HANDLE handle, UINT32 *sta)
+link_add_prs(ACPI_RESOURCE *res, void *context)
 {
-	ACPI_DEVICE_INFO	*devinfo;
-	ACPI_BUFFER		buf;
-	ACPI_STATUS		error;
+	struct link_res_request *req;
+	struct link *link;
+	UINT32 *irqs;
+	int i;
 
-	ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
-
-	if (handle == NULL || sta == NULL) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "invalid argument\n"));
-		return_ACPI_STATUS (AE_BAD_PARAMETER);
-	}
-
-	buf.Pointer = NULL;
-	buf.Length = ACPI_ALLOCATE_BUFFER;
-	error = AcpiGetObjectInfo(handle, &buf);
-	if (ACPI_FAILURE(error)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-		    "couldn't get object info %s - %s\n",
-		    acpi_name(handle), AcpiFormatException(error)));
-		return_ACPI_STATUS (error);
-	}
-
-	devinfo = (ACPI_DEVICE_INFO *)buf.Pointer;
-	if ((devinfo->Valid & ACPI_VALID_HID) == 0 ||
-	    strcmp(devinfo->HardwareId.Value, "PNP0C0F") != 0) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "invalid hardware ID - %s\n",
-		    acpi_name(handle)));
-		AcpiOsFree(buf.Pointer);
-		return_ACPI_STATUS (AE_TYPE);
-	}
-
-	if ((devinfo->Valid & ACPI_VALID_STA) != 0) {
-		*sta = devinfo->CurrentStatus;
-	} else {
-		ACPI_DEBUG_PRINT((ACPI_DB_WARN, "invalid status - %s\n",
-		    acpi_name(handle)));
-		*sta = 0;
-	}
-
-	AcpiOsFree(buf.Pointer);
-	return_ACPI_STATUS (AE_OK);
-}
-
-static ACPI_STATUS
-acpi_pci_link_get_irq_resources(ACPI_RESOURCE *resources,
-    UINT8 *number_of_interrupts, UINT8 interrupts[])
-{
-	UINT8			count;
-	UINT8			i;
-	UINT32			NumberOfInterrupts;
-	UINT32			*Interrupts;
-
-	ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
-
-	if (resources == NULL || number_of_interrupts == NULL) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "invalid argument\n"));
-		return_ACPI_STATUS (AE_BAD_PARAMETER);
-	}
-
-	*number_of_interrupts = 0;
-	NumberOfInterrupts = 0;
-	Interrupts = NULL;
-
-	if (resources->Id == ACPI_RSTYPE_START_DPF)
-		resources = ACPI_NEXT_RESOURCE(resources);
-
-	if (resources->Id != ACPI_RSTYPE_IRQ &&
-	    resources->Id != ACPI_RSTYPE_EXT_IRQ) {
-		printf("acpi link get: resource %d is not an IRQ\n",
-		    resources->Id);
-		return_ACPI_STATUS (AE_TYPE);
-	}
-
-	switch (resources->Id) {
+	ACPI_SERIAL_ASSERT(pci_link);
+	req = (struct link_res_request *)context;
+	link = &req->sc->pl_links[req->count];
+	req->count++;
+	switch (res->Id) {
 	case ACPI_RSTYPE_IRQ:
-		NumberOfInterrupts = resources->Data.Irq.NumberOfInterrupts;
-		Interrupts = resources->Data.Irq.Interrupts;
-		break;
 	case ACPI_RSTYPE_EXT_IRQ:
-		NumberOfInterrupts =
-		    resources->Data.ExtendedIrq.NumberOfInterrupts;
-		Interrupts = resources->Data.ExtendedIrq.Interrupts;
-		break;
-	}
 
-	if (NumberOfInterrupts == 0)
-		return_ACPI_STATUS (AE_NULL_ENTRY);
+		/*
+		 * Stash a copy of the resource for later use when doing
+		 * _SRS.
+		 */
+		bcopy(res, &link->l_prs_template, sizeof(ACPI_RESOURCE));
+		if (res->Id == ACPI_RSTYPE_IRQ) {
+			link->l_num_irqs = res->Data.Irq.NumberOfInterrupts;
+			irqs = res->Data.Irq.Interrupts;
+		} else {
+			link->l_num_irqs =
+			    res->Data.ExtendedIrq.NumberOfInterrupts;
+			irqs = res->Data.ExtendedIrq.Interrupts;
+		}
+		if (link->l_num_irqs == 0)
+			break;
 
-	count = 0;
-	for (i = 0; i < NumberOfInterrupts; i++) {
-		if (i >= MAX_POSSIBLE_INTERRUPTS) {
-			ACPI_DEBUG_PRINT((ACPI_DB_WARN, "too many IRQs (%d)\n",
-			    i));
-			break;
+		/*
+		 * Save a list of the valid IRQs.  Also, if all of the
+		 * valid IRQs are ISA IRQs, then mark this link as
+		 * routed via an ISA interrupt.
+		 */
+		link->l_isa_irq = 1;
+		link->l_irqs = malloc(sizeof(int) * link->l_num_irqs,
+		    M_PCI_LINK, M_WAITOK | M_ZERO);
+		for (i = 0; i < link->l_num_irqs; i++) {
+			link->l_irqs[i] = irqs[i];
+			if (irqs[1] >= NUM_ISA_INTERRUPTS)
+				link->l_isa_irq = 0;
 		}
-		if (Interrupts[i] == 0) {
-			ACPI_DEBUG_PRINT((ACPI_DB_WARN, "invalid IRQ %d\n",
-			    Interrupts[i]));
-			continue;
-		}
-		interrupts[count] = Interrupts[i];
-		count++;
+		break;
 	}
-	*number_of_interrupts = count;
-
-	return_ACPI_STATUS (AE_OK);
+	return (AE_OK);
 }
 
-static ACPI_STATUS
-acpi_pci_link_get_current_irq(struct acpi_pci_link_entry *link, UINT8 *irq)
+static int
+link_valid_irq(struct link *link, int irq)
 {
-	ACPI_STATUS		error;
-	ACPI_BUFFER		buf;
-	ACPI_RESOURCE		*resources;
-	UINT8			number_of_interrupts;
-	UINT8			interrupts[MAX_POSSIBLE_INTERRUPTS];;
+	int i;
 
-	ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
+	ACPI_SERIAL_ASSERT(pci_link);
 
-	if (link == NULL || irq == NULL) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "invalid argument\n"));
-		return_ACPI_STATUS (AE_BAD_PARAMETER);
-	}
+	/* Invalid interrupts are never valid. */
+	if (!PCI_INTERRUPT_VALID(irq))
+		return (0);
 
-	*irq = 0;
-	buf.Pointer = NULL;
-	buf.Length = ACPI_ALLOCATE_BUFFER;
-	error = AcpiGetCurrentResources(link->handle, &buf);
-	if (ACPI_FAILURE(error)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-		    "couldn't get PCI interrupt link device _CRS %s - %s\n",
-		    acpi_name(link->handle), AcpiFormatException(error)));
-		return_ACPI_STATUS (error);
-	}
-	if (buf.Pointer == NULL) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-		    "couldn't allocate memory - %s\n",
-		    acpi_name(link->handle)));
-		return_ACPI_STATUS (AE_NO_MEMORY);
-	}
+	/* Any interrupt in the list of possible interrupts is valid. */
+	for (i = 0; i < link->l_num_irqs; i++)
+		if (link->l_irqs[i] == irq)
+			 return (1);
 
-	resources = (ACPI_RESOURCE *) buf.Pointer;
-	number_of_interrupts = 0;
-	bzero(interrupts, sizeof(interrupts));
-	error = acpi_pci_link_get_irq_resources(resources,
-		    &number_of_interrupts, interrupts);
-	AcpiOsFree(buf.Pointer);
+	/*
+	 * For links routed via an ISA interrupt, if the SCI is routed via
+	 * an ISA interrupt, the SCI is always treated as a valid IRQ.
+	 */
+	if (link->l_isa_irq && AcpiGbl_FADT->SciInt == irq &&
+	    irq < NUM_ISA_INTERRUPTS)
+		return (1);
 
-	if (ACPI_FAILURE(error)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_WARN,
-		    "couldn't get current IRQ from interrupt link %s - %s\n",
-		    acpi_name(link->handle), AcpiFormatException(error)));
-		return_ACPI_STATUS (error);
-	}
-
-	if (number_of_interrupts == 0) {
-		ACPI_DEBUG_PRINT((ACPI_DB_WARN,
-		    "PCI interrupt link device _CRS data is corrupted - %s\n",
-		    acpi_name(link->handle)));
-		return_ACPI_STATUS (AE_NULL_ENTRY);
-	}
-
-	*irq = interrupts[0];
-
-	return_ACPI_STATUS (AE_OK);
+	/* If the interrupt wasn't found in the list it is not valid. */
+	return (0);
 }
 
-static ACPI_STATUS
-acpi_pci_link_add_link(ACPI_HANDLE handle, struct acpi_prt_entry *entry)
+static void
+acpi_pci_link_dump(struct acpi_pci_link_softc *sc)
 {
-	ACPI_STATUS		error;
-	ACPI_BUFFER		buf;
-	ACPI_RESOURCE		*resources;
-	struct acpi_pci_link_entry *link;
+	struct link *link;
+	int i, j;
 
-	ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 	ACPI_SERIAL_ASSERT(pci_link);
-
-	entry->pci_link = NULL;
-	TAILQ_FOREACH(link, &acpi_pci_link_entries, links) {
-		if (link->handle == handle) {
-			entry->pci_link = link;
-			link->references++;
-			return_ACPI_STATUS (AE_OK);
-		}
+	printf("Index  IRQ  Rtd  Ref  IRQs\n");
+	for (i = 0; i < sc->pl_num_links; i++) {
+		link = &sc->pl_links[i];
+		printf("%5d  %3d   %c   %3d ", i, link->l_irq,
+		    link->l_routed ? 'Y' : 'N',  link->l_references);
+		if (link->l_num_irqs == 0)
+			printf(" none");
+		else for (j = 0; j < link->l_num_irqs; j++)
+			printf(" %d", link->l_irqs[j]);
+		printf("\n");
 	}
+}
 
-	link = AcpiOsAllocate(sizeof(struct acpi_pci_link_entry));
-	if (link == NULL) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-		    "couldn't allocate memory - %s\n", acpi_name(handle)));
-		return_ACPI_STATUS (AE_NO_MEMORY);
-	}
+static int
+acpi_pci_link_attach(device_t dev)
+{
+	struct acpi_pci_link_softc *sc;
+	struct link_res_request req;
+	ACPI_STATUS status;
+	int i;
 
-	buf.Pointer = NULL;
-	buf.Length = ACPI_ALLOCATE_BUFFER;
-
-	bzero(link, sizeof(struct acpi_pci_link_entry));
-	link->handle = handle;
+	sc = device_get_softc(dev);
+	ACPI_SERIAL_BEGIN(pci_link);
 
 	/*
-	 * Get the IRQ configured at boot-time.  If successful, set this
-	 * as the initial IRQ.
+	 * Count the number of current resources so we know how big of
+	 * a link array to allocate.
 	 */
-	error = acpi_pci_link_get_current_irq(link, &link->current_irq);
-	if (ACPI_SUCCESS(error)) {
-		link->initial_irq = link->current_irq;
-	} else {
-		ACPI_DEBUG_PRINT((ACPI_DB_WARN,
-		    "couldn't get current IRQ from interrupt link %s - %s\n",
-		    acpi_name(handle), AcpiFormatException(error)));
-		link->initial_irq = 0;
-	}
+	status = AcpiWalkResources(acpi_get_handle(dev), "_CRS",
+	    acpi_count_resources, &sc->pl_num_links);
+	if (ACPI_FAILURE(status))
+		return (ENXIO);
+	if (sc->pl_num_links == 0)
+		return (0);
+	sc->pl_links = malloc(sizeof(struct link) * sc->pl_num_links,
+	    M_PCI_LINK, M_WAITOK | M_ZERO);
 
-	error = AcpiGetPossibleResources(handle, &buf);
-	if (ACPI_FAILURE(error)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_WARN,
-		    "couldn't get interrupt link device _PRS data %s - %s\n",
-		    acpi_name(handle), AcpiFormatException(error)));
-		goto out;
+	/* Initialize the child links. */
+	for (i = 0; i < sc->pl_num_links; i++) {
+		sc->pl_links[i].l_irq = PCI_INVALID_IRQ;
+		sc->pl_links[i].l_bios_irq = PCI_INVALID_IRQ;
+		sc->pl_links[i].l_res_index = i;
+		sc->pl_links[i].l_sc = sc;
+		sc->pl_links[i].l_isa_irq = 0;
 	}
-	if (buf.Pointer == NULL) {
-		ACPI_DEBUG_PRINT((ACPI_DB_WARN,
-		    "_PRS buffer is empty - %s\n", acpi_name(handle)));
-		error = AE_NO_MEMORY;
-		goto out;
+	req.count = 0;
+	req.sc = sc;
+	status = AcpiWalkResources(acpi_get_handle(dev), "_CRS",
+	    link_add_crs, &req);
+	if (ACPI_FAILURE(status))
+		goto fail;
+	req.count = 0;
+	status = AcpiWalkResources(acpi_get_handle(dev), "_PRS",
+	    link_add_prs, &req);
+	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
+		goto fail;
+	if (bootverbose) {
+		device_printf(dev, "Links after initial probe:\n");
+		acpi_pci_link_dump(sc);
 	}
 
-	/* Skip any DPF descriptors.  XXX We should centralize this code. */
-	resources = (ACPI_RESOURCE *) buf.Pointer;
-	if (resources->Id == ACPI_RSTYPE_START_DPF)
-		resources = ACPI_NEXT_RESOURCE(resources);
-
-	/* XXX This only handles one resource, ignoring SourceIndex. */
-	bcopy(resources, &link->possible_resources,
-	    sizeof(link->possible_resources));
-
-	error = acpi_pci_link_get_irq_resources(resources,
-	    &link->number_of_interrupts, link->interrupts);
-	if (ACPI_FAILURE(error)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_WARN,
-		    "couldn't get possible IRQs from interrupt link %s - %s\n",
-		    acpi_name(handle), AcpiFormatException(error)));
-		goto out;
+	/* Verify initial IRQs if we have _PRS. */
+	if (status != AE_NOT_FOUND)
+		for (i = 0; i < sc->pl_num_links; i++)
+			if (!link_valid_irq(&sc->pl_links[i],
+			    sc->pl_links[i].l_irq))
+				sc->pl_links[i].l_irq = PCI_INVALID_IRQ;
+	if (bootverbose) {
+		device_printf(dev, "Links after initial validation:\n");
+		acpi_pci_link_dump(sc);
 	}
 
-	if (link->number_of_interrupts == 0) {
-		ACPI_DEBUG_PRINT((ACPI_DB_WARN,
-		    "interrupt link device _PRS data is corrupted - %s\n",
-		    acpi_name(handle)));
-		error = AE_NULL_ENTRY;
-		goto out;
-	}
+	/* Save initial IRQs. */
+	for (i = 0; i < sc->pl_num_links; i++)
+		sc->pl_links[i].l_initial_irq = sc->pl_links[i].l_irq;
 
 	/*
 	 * Try to disable this link.  If successful, set the current IRQ to
 	 * zero and flags to indicate this link is not routed.  If we can't
 	 * run _DIS (i.e., the method doesn't exist), assume the initial
 	 * IRQ was routed by the BIOS.
-	 *
-	 * XXX Since we detect link devices via _PRT entries but run long
-	 * after APIC mode has been enabled, we don't get a chance to
-	 * disable links that will be unused (especially in APIC mode).
-	 * Leaving them enabled can cause duplicate interrupts for some
-	 * devices.  The right fix is to probe links via their PNPID, so we
-	 * see them no matter what the _PRT says.
 	 */
-	if (ACPI_SUCCESS(AcpiEvaluateObject(handle, "_DIS", NULL, NULL))) {
-		link->current_irq = 0;
-		link->flags = ACPI_LINK_NONE;
-	} else
-		link->flags = ACPI_LINK_ROUTED;
-
-	/*
-	 * If the initial IRQ is invalid (not in _PRS), set it to 0 and
-	 * mark this link as not routed.  We won't use it as the preferred
-	 * interrupt later when we route.
-	 */
-	if (!acpi_pci_link_is_valid_irq(link, link->initial_irq) &&
-	    link->initial_irq != 0) {
-		printf("ACPI link %s has invalid initial irq %d, ignoring\n",
-		    acpi_name(handle), link->initial_irq);
-		link->initial_irq = 0;
-		link->flags = ACPI_LINK_NONE;
+	if (ACPI_SUCCESS(AcpiEvaluateObject(acpi_get_handle(dev), "_DIS", NULL,
+		    NULL)))
+		for (i = 0; i < sc->pl_num_links; i++)
+			sc->pl_links[i].l_irq = PCI_INVALID_IRQ;
+	else
+		for (i = 0; i < sc->pl_num_links; i++)
+			if (PCI_INTERRUPT_VALID(sc->pl_links[i].l_irq))
+				sc->pl_links[i].l_routed = 1;
+	if (bootverbose) {
+		device_printf(dev, "Links after disable:\n");
+		acpi_pci_link_dump(sc);
 	}
+	ACPI_SERIAL_END(pci_link);
+	return (0);
+fail:
+	ACPI_SERIAL_END(pci_link);
+	for (i = 0; i < sc->pl_num_links; i++)
+		if (sc->pl_links[i].l_irqs != NULL)
+			free(sc->pl_links[i].l_irqs, M_PCI_LINK);
+	free(sc->pl_links, M_PCI_LINK);
+	return (ENXIO);
+}

>>> TRUNCATED FOR MAIL (1000 lines) <<<


More information about the p4-projects mailing list