DragonFly BSD
DragonFly submit List (threaded) for 2003-12
[Date Prev][Date Next]  [Thread Prev][Thread Next]  [Date Index][Thread Index]

pcib newbus handling


From: Joerg Sonnenberger <joerg@xxxxxxxxxxxxxxxxx>
Date: Sat, 20 Dec 2003 18:34:10 +0100

Hi all,
attached patch adds the pcib interface from FreeBSD 5. This
is the version of Dec. 2000 to keep the diff small.
The PCI compat patch is required.

I haven't kept the Alpha PCI hose support since Alphas are
unsupported ATM anyway. When that platform is resurrected,
the bus space functions have to be updated to handled that.

bus/pci/i386/pcibus.c can be removed afterwards. This should
be tested. I am not sure wether our AT PIC claims IRQ 2,
perhaps we should conditionally bump irq_rman.rm_start to 3
in the !APIC_IO && !PC98 case.

Joerg
diff -uNr sys.old/bus/pci/i386/pci_bus.c sys/bus/pci/i386/pci_bus.c
--- sys.old/bus/pci/i386/pci_bus.c	Thu Jan  1 00:00:00 1970
+++ sys/bus/pci/i386/pci_bus.c	Sat Dec 20 17:08:07 2003
@@ -0,0 +1,556 @@
+/*
+ * Copyright (c) 1997, Stefan Esser <se@xxxxxxxxxxx>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice unmodified, this list of conditions, and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/i386/pci/pci_bus.c,v 1.71 2000/10/16 07:25:08 imp Exp $
+ * $DragonFly$
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+
+#include <bus/pci/pcivar.h>
+#include <bus/pci/pcireg.h>
+#include <bus/isa/isavar.h>
+#include <machine/nexusvar.h>
+#include <bus/pci/i386/pci_cfgreg.h>
+#include <machine/segments.h>
+#include <machine/pc/bios.h>
+
+#include "pcib_if.h"
+
+static int
+nexus_pcib_maxslots(device_t dev)
+{
+	return 31;
+}
+
+/* read configuration space register */
+
+static u_int32_t
+nexus_pcib_read_config(device_t dev, int bus, int slot, int func,
+		       int reg, int bytes)
+{
+	return(pci_cfgregread(bus, slot, func, reg, bytes));
+}
+
+/* write configuration space register */
+
+static void
+nexus_pcib_write_config(device_t dev, int bus, int slot, int func,
+			int reg, u_int32_t data, int bytes)
+{
+	pci_cfgregwrite(bus, slot, func, reg, data, bytes);
+}
+
+/* route interrupt */
+
+static int
+nexus_pcib_route_interrupt(device_t bus, device_t device, int pin)
+{
+	return(pci_cfgintr(nexus_get_pcibus(bus), pci_get_slot(device), pin, pci_get_irq(device)));
+}
+
+static devclass_t	pcib_devclass;
+
+static const char *
+nexus_pcib_is_host_bridge(int bus, int slot, int func,
+			  u_int32_t id, u_int8_t class, u_int8_t subclass,
+			  u_int8_t *busnum)
+{
+	const char *s = NULL;
+	static u_int8_t pxb[4];	/* hack for 450nx */
+
+	*busnum = 0;
+
+	switch (id) {
+	case 0x12258086:
+		s = "Intel 824?? host to PCI bridge";
+		/* XXX This is a guess */
+		/* *busnum = nexus_pcib_read_config(0, bus, slot, func, 0x41, 1); */
+		*busnum = bus;
+		break;
+	case 0x71208086:
+		s = "Intel 82810 (i810 GMCH) Host To Hub bridge";
+		break;
+	case 0x71228086:
+		s = "Intel 82810-DC100 (i810-DC100 GMCH) Host To Hub bridge";
+		break;
+	case 0x71248086:
+		s = "Intel 82810E (i810E GMCH) Host To Hub bridge";
+		break;
+	case 0x71808086:
+		s = "Intel 82443LX (440 LX) host to PCI bridge";
+		break;
+	case 0x71908086:
+		s = "Intel 82443BX (440 BX) host to PCI bridge";
+		break;
+	case 0x71928086:
+		s = "Intel 82443BX host to PCI bridge (AGP disabled)";
+		break;
+	case 0x71948086:
+		s = "Intel 82443MX host to PCI bridge";
+		break;
+	case 0x71a08086:
+		s = "Intel 82443GX host to PCI bridge";
+		break;
+	case 0x71a18086:
+		s = "Intel 82443GX host to AGP bridge";
+		break;
+	case 0x71a28086:
+		s = "Intel 82443GX host to PCI bridge (AGP disabled)";
+		break;
+	case 0x84c48086:
+		s = "Intel 82454KX/GX (Orion) host to PCI bridge";
+		*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x4a, 1);
+		break;
+	case 0x84ca8086:
+		/*
+		 * For the 450nx chipset, there is a whole bundle of
+		 * things pretending to be host bridges. The MIOC will 
+		 * be seen first and isn't really a pci bridge (the
+		 * actual busses are attached to the PXB's). We need to 
+		 * read the registers of the MIOC to figure out the
+		 * bus numbers for the PXB channels.
+		 *
+		 * Since the MIOC doesn't have a pci bus attached, we
+		 * pretend it wasn't there.
+		 */
+		pxb[0] = nexus_pcib_read_config(0, bus, slot, func,
+						0xd0, 1); /* BUSNO[0] */
+		pxb[1] = nexus_pcib_read_config(0, bus, slot, func,
+						0xd1, 1) + 1;	/* SUBA[0]+1 */
+		pxb[2] = nexus_pcib_read_config(0, bus, slot, func,
+						0xd3, 1); /* BUSNO[1] */
+		pxb[3] = nexus_pcib_read_config(0, bus, slot, func,
+						0xd4, 1) + 1;	/* SUBA[1]+1 */
+		return NULL;
+	case 0x84cb8086:
+		switch (slot) {
+		case 0x12:
+			s = "Intel 82454NX PXB#0, Bus#A";
+			*busnum = pxb[0];
+			break;
+		case 0x13:
+			s = "Intel 82454NX PXB#0, Bus#B";
+			*busnum = pxb[1];
+			break;
+		case 0x14:
+			s = "Intel 82454NX PXB#1, Bus#A";
+			*busnum = pxb[2];
+			break;
+		case 0x15:
+			s = "Intel 82454NX PXB#1, Bus#B";
+			*busnum = pxb[3];
+			break;
+		}
+		break;
+
+		/* AMD -- vendor 0x1022 */
+	case 0x70061022:
+		s = "AMD-751 host to PCI bridge";
+		break;
+
+		/* SiS -- vendor 0x1039 */
+	case 0x04961039:
+		s = "SiS 85c496";
+		break;
+	case 0x04061039:
+		s = "SiS 85c501";
+		break;
+	case 0x06011039:
+		s = "SiS 85c601";
+		break;
+	case 0x55911039:
+		s = "SiS 5591 host to PCI bridge";
+		break;
+	case 0x00011039:
+		s = "SiS 5591 host to AGP bridge";
+		break;
+
+		/* VLSI -- vendor 0x1004 */
+	case 0x00051004:
+		s = "VLSI 82C592 Host to PCI bridge";
+		break;
+
+		/* XXX Here is MVP3, I got the datasheet but NO M/B to test it  */
+		/* totally. Please let me know if anything wrong.            -F */
+		/* XXX need info on the MVP3 -- any takers? */
+	case 0x05981106:
+		s = "VIA 82C598MVP (Apollo MVP3) host bridge";
+		break;
+
+		/* AcerLabs -- vendor 0x10b9 */
+		/* Funny : The datasheet told me vendor id is "10b8",sub-vendor */
+		/* id is '10b9" but the register always shows "10b9". -Foxfair  */
+	case 0x154110b9:
+		s = "AcerLabs M1541 (Aladdin-V) PCI host bridge";
+		break;
+
+		/* OPTi -- vendor 0x1045 */
+	case 0xc7011045:
+		s = "OPTi 82C700 host to PCI bridge";
+		break;
+	case 0xc8221045:
+		s = "OPTi 82C822 host to PCI Bridge";
+		break;
+
+		/* ServerWorks -- vendor 0x1166 */
+	case 0x00051166:
+		s = "ServerWorks NB6536 2.0HE host to PCI bridge";
+		*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
+		break;
+	
+	case 0x00061166:
+		/* FALLTHROUGH */
+	case 0x00081166:
+		s = "ServerWorks host to PCI bridge";
+		*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
+		break;
+
+	case 0x00091166:
+		s = "ServerWorks NB6635 3.0LE host to PCI bridge";
+		*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
+		break;
+
+		/* Integrated Micro Solutions -- vendor 0x10e0 */
+	case 0x884910e0:
+		s = "Integrated Micro Solutions VL Bridge";
+		break;
+
+	default:
+		if (class == PCIC_BRIDGE && subclass == PCIS_BRIDGE_HOST)
+			s = "Host to PCI bridge";
+		break;
+	}
+
+	return s;
+}
+
+/*
+ * Scan the first pci bus for host-pci bridges and add pcib instances
+ * to the nexus for each bridge.
+ */
+static void
+nexus_pcib_identify(driver_t *driver, device_t parent)
+{
+	int bus, slot, func;
+	u_int8_t  hdrtype;
+	int found = 0;
+	int pcifunchigh;
+	int found824xx = 0;
+	device_t child;
+	devclass_t pci_devclass;
+
+	if (pci_cfgregopen() == 0)
+		return;
+	/*
+	 * Check to see if we haven't already had a PCI bus added
+	 * via some other means.  If we have, bail since otherwise
+	 * we're going to end up duplicating it.
+	 */
+	if ((pci_devclass = devclass_find("pci")) && 
+		devclass_get_device(pci_devclass, 0))
+		return;
+
+
+	bus = 0;
+ retry:
+	for (slot = 0; slot <= PCI_SLOTMAX; slot++) {
+		func = 0;
+		hdrtype = nexus_pcib_read_config(0, bus, slot, func,
+						 PCIR_HEADERTYPE, 1);
+		if (hdrtype & PCIM_MFDEV)
+			pcifunchigh = 7;
+		else
+			pcifunchigh = 0;
+		for (func = 0; func <= pcifunchigh; func++) {
+			/*
+			 * Read the IDs and class from the device.
+			 */
+			u_int32_t id;
+			u_int8_t class, subclass, busnum;
+			const char *s;
+			device_t *devs;
+			int ndevs, i;
+
+			id = nexus_pcib_read_config(0, bus, slot, func,
+						    PCIR_DEVVENDOR, 4);
+			if (id == -1)
+				continue;
+			class = nexus_pcib_read_config(0, bus, slot, func,
+						       PCIR_CLASS, 1);
+			subclass = nexus_pcib_read_config(0, bus, slot, func,
+							  PCIR_SUBCLASS, 1);
+
+			s = nexus_pcib_is_host_bridge(bus, slot, func,
+						      id, class, subclass,
+						      &busnum);
+			if (s == NULL)
+				continue;
+
+			/*
+			 * Check to see if the physical bus has already
+			 * been seen.  Eg: hybrid 32 and 64 bit host
+			 * bridges to the same logical bus.
+			 */
+			if (device_get_children(parent, &devs, &ndevs) == 0) {
+				for (i = 0; s != NULL && i < ndevs; i++) {
+					if (strcmp(device_get_name(devs[i]),
+					    "pcib") != 0)
+						continue;
+					if (nexus_get_pcibus(devs[i]) == busnum)
+						s = NULL;
+				}
+				free(devs, M_TEMP);
+			}
+
+			if (s == NULL)
+				continue;
+			/*
+			 * Add at priority 100 to make sure we
+			 * go after any motherboard resources
+			 */
+			child = BUS_ADD_CHILD(parent, 100,
+					      "pcib", busnum);
+			device_set_desc(child, s);
+			nexus_set_pcibus(child, busnum);
+
+			found = 1;
+			if (id == 0x12258086)
+				found824xx = 1;
+		}
+	}
+	if (found824xx && bus == 0) {
+		bus++;
+		goto retry;
+	}
+
+	/*
+	 * Make sure we add at least one bridge since some old
+	 * hardware doesn't actually have a host-pci bridge device.
+	 * Note that pci_cfgregopen() thinks we have PCI devices..
+	 */
+	if (!found) {
+		if (bootverbose)
+			printf(
+	"nexus_pcib_identify: no bridge found, adding pcib0 anyway\n");
+		child = BUS_ADD_CHILD(parent, 100, "pcib", 0);
+		nexus_set_pcibus(child, 0);
+	}
+}
+
+static int
+nexus_pcib_probe(device_t dev)
+{
+	devclass_t pci_devclass;
+
+	if (pci_cfgregopen() == 0)
+		return ENXIO;
+	/*
+	 * Check to see if we haven't already had a PCI bus added
+	 * via some other means.  If we have, bail since otherwise
+	 * we're going to end up duplicating it.
+	 */
+	if ((pci_devclass = devclass_find("pci")) && 
+		devclass_get_device(pci_devclass, device_get_unit(dev)))
+		return ENXIO;
+
+	return 0;
+}
+
+static int
+nexus_pcib_attach(device_t dev)
+{
+	device_t child;
+
+	child = device_add_child(dev, "pci", device_get_unit(dev));
+
+	return bus_generic_attach(dev);
+}
+
+static int
+nexus_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+
+	switch (which) {
+	case  PCIB_IVAR_BUS:
+		*result = nexus_get_pcibus(dev);
+		return 0;
+	}
+	return ENOENT;
+}
+
+static int
+nexus_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
+{
+
+	switch (which) {
+	case  PCIB_IVAR_BUS:
+		nexus_set_pcibus(dev, value);
+		return 0;
+	}
+	return ENOENT;
+}
+
+
+static device_method_t nexus_pcib_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_identify,	nexus_pcib_identify),
+	DEVMETHOD(device_probe,		nexus_pcib_probe),
+	DEVMETHOD(device_attach,	nexus_pcib_attach),
+	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
+	DEVMETHOD(device_suspend,	bus_generic_suspend),
+	DEVMETHOD(device_resume,	bus_generic_resume),
+
+	/* Bus interface */
+	DEVMETHOD(bus_print_child,	bus_generic_print_child),
+	DEVMETHOD(bus_read_ivar,	nexus_pcib_read_ivar),
+	DEVMETHOD(bus_write_ivar,	nexus_pcib_write_ivar),
+	DEVMETHOD(bus_alloc_resource,	bus_generic_alloc_resource),
+	DEVMETHOD(bus_release_resource,	bus_generic_release_resource),
+	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
+	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
+
+	/* pcib interface */
+	DEVMETHOD(pcib_maxslots,	nexus_pcib_maxslots),
+	DEVMETHOD(pcib_read_config,	nexus_pcib_read_config),
+	DEVMETHOD(pcib_write_config,	nexus_pcib_write_config),
+	DEVMETHOD(pcib_route_interrupt,	nexus_pcib_route_interrupt),
+
+	{ 0, 0 }
+};
+
+static driver_t nexus_pcib_driver = {
+	"pcib",
+	nexus_pcib_methods,
+	1,
+};
+
+DRIVER_MODULE(pcib, nexus, nexus_pcib_driver, pcib_devclass, 0, 0);
+
+
+/*
+ * Provide a device to "eat" the host->pci bridges that we dug up above
+ * and stop them showing up twice on the probes.  This also stops them
+ * showing up as 'none' in pciconf -l.
+ */
+static int
+pci_hostb_probe(device_t dev)
+{
+
+	if (pci_get_class(dev) == PCIC_BRIDGE &&
+	    pci_get_subclass(dev) == PCIS_BRIDGE_HOST) {
+		device_set_desc(dev, "Host to PCI bridge");
+		device_quiet(dev);
+		return 0;
+	}
+	return ENXIO;
+}
+
+static int
+pci_hostb_attach(device_t dev)
+{
+
+	return 0;
+}
+
+static device_method_t pci_hostb_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		pci_hostb_probe),
+	DEVMETHOD(device_attach,	pci_hostb_attach),
+	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
+	DEVMETHOD(device_suspend,	bus_generic_suspend),
+	DEVMETHOD(device_resume,	bus_generic_resume),
+
+	{ 0, 0 }
+};
+static driver_t pci_hostb_driver = {
+	"hostb",
+	pci_hostb_methods,
+	1,
+};
+static devclass_t pci_hostb_devclass;
+
+DRIVER_MODULE(hostb, pci, pci_hostb_driver, pci_hostb_devclass, 0, 0);
+
+
+/*
+ * Install placeholder to claim the resources owned by the
+ * PCI bus interface.  This could be used to extract the 
+ * config space registers in the extreme case where the PnP
+ * ID is available and the PCI BIOS isn't, but for now we just
+ * eat the PnP ID and do nothing else.
+ *
+ * XXX we should silence this probe, as it will generally confuse 
+ * people.
+ */
+static struct isa_pnp_id pcibus_pnp_ids[] = {
+	{ 0x030ad041 /* PNP030A */, "PCI Bus" },
+	{ 0 }
+};
+
+static int
+pcibus_pnp_probe(device_t dev)
+{
+	int result;
+	
+	if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, pcibus_pnp_ids)) <= 0)
+		device_quiet(dev);
+	return(result);
+}
+
+static int
+pcibus_pnp_attach(device_t dev)
+{
+	return(0);
+}
+
+static device_method_t pcibus_pnp_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		pcibus_pnp_probe),
+	DEVMETHOD(device_attach,	pcibus_pnp_attach),
+	DEVMETHOD(device_detach,	bus_generic_detach),
+	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
+	DEVMETHOD(device_suspend,	bus_generic_suspend),
+	DEVMETHOD(device_resume,	bus_generic_resume),
+	{ 0, 0 }
+};
+
+static driver_t pcibus_pnp_driver = {
+	"pcibus_pnp",
+	pcibus_pnp_methods,
+	1,		/* no softc */
+};
+
+static devclass_t pcibus_pnp_devclass;
+
+DRIVER_MODULE(pcibus_pnp, isa, pcibus_pnp_driver, pcibus_pnp_devclass, 0, 0);
diff -uNr sys.old/bus/pci/i386/pci_cfgreg.c sys/bus/pci/i386/pci_cfgreg.c
--- sys.old/bus/pci/i386/pci_cfgreg.c	Thu Aug  7 21:16:47 2003
+++ sys/bus/pci/i386/pci_cfgreg.c	Sat Dec 20 17:08:07 2003
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD: src/sys/i386/isa/pci_cfgreg.c,v 1.1.2.7 2001/11/28 05:47:03 imp Exp $
+ * $FreeBSD: src/sys/i386/pci/pci_cfgreg.c,v 1.101 2003/02/18 03:36:48 peter Exp $
  * $DragonFly: src/sys/bus/pci/i386/pci_cfgreg.c,v 1.3 2003/08/07 21:16:47 dillon Exp $
  *
  */
@@ -36,15 +36,14 @@
 #include <sys/kernel.h>
 #include <sys/module.h>
 #include <sys/malloc.h>
+#include <sys/lock.h>
 #include <vm/vm.h>
 #include <vm/pmap.h>
 #include <machine/md_var.h>
 #include <bus/pci/pcivar.h>
 #include <bus/pci/pcireg.h>
 #include <bus/isa/isavar.h>
-#include "pcibus.h"
-/* #include <machine/nexusvar.h> */
-#include <machine/pci_cfgreg.h>
+#include <bus/pci/i386/pci_cfgreg.h>
 #include <machine/segments.h>
 #include <machine/pc/bios.h>
 
@@ -52,41 +51,65 @@
 #include <machine/smp.h>
 #endif /* APIC_IO */
 
+#include "pcib_if.h"
+
+#define PRVERB(a) do {							\
+	if (bootverbose)						\
+		printf a ;						\
+} while(0)
+
 static int cfgmech;
 static int devmax;
 
-#define PRVERB(a) printf a
+static int	pci_cfgintr_valid(struct PIR_entry *pe, int pin, int irq);
 static int	pci_cfgintr_unique(struct PIR_entry *pe, int pin);
 static int	pci_cfgintr_linked(struct PIR_entry *pe, int pin);
 static int	pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int pin);
 static int	pci_cfgintr_virgin(struct PIR_entry *pe, int pin);
 
+static void	pci_print_irqmask(u_int16_t irqs);
+static void	pci_print_route_table(struct PIR_table *prt, int size);
 static int	pcireg_cfgread(int bus, int slot, int func, int reg, int bytes);
 static void	pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes);
 static int	pcireg_cfgopen(void);
 
-static struct PIR_table	*pci_route_table;
-static int		pci_route_count;
+static struct PIR_table *pci_route_table;
+static int pci_route_count;
+
+/*
+ * Some BIOS writers seem to want to ignore the spec and put
+ * 0 in the intline rather than 255 to indicate none.  Some use
+ * numbers in the range 128-254 to indicate something strange and
+ * apparently undocumented anywhere.  Assume these are completely bogus
+ * and map them to 255, which means "none".
+ */
+static __inline__ int 
+pci_i386_map_intline(int line)
+{
+	if (line == 0 || line >= 128)
+		return (PCI_INVALID_IRQ);
+	return (line);
+}
 
 static u_int16_t
 pcibios_get_version(void)
 {
-    struct bios_regs args;
+	struct bios_regs args;
 
-    if (PCIbios.entry == 0) {
-	PRVERB(("pcibios: No call entry point\n"));
-	return (0);
-    }
-    args.eax = PCIBIOS_BIOS_PRESENT;
-    if (bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL))) {
-	PRVERB(("pcibios: BIOS_PRESENT call failed\n"));
-	return (0);
-    }
-    if (args.edx != 0x20494350) {
-	PRVERB(("pcibios: BIOS_PRESENT didn't return 'PCI ' in edx\n"));
-	return (0);
-    }
-    return (args.ebx & 0xffff);
+	if (PCIbios.ventry == 0) {
+		PRVERB(("pcibios: No call entry point\n"));
+		return (0);
+	}
+	args.eax = PCIBIOS_BIOS_PRESENT;
+	if (bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL))) {
+		PRVERB(("pcibios: BIOS_PRESENT call failed\n"));
+		return (0);
+	}
+	if (args.edx != 0x20494350) {
+		PRVERB(("pcibios: BIOS_PRESENT didn't return 'PCI ' in edx\n"));
+		return (0);
+	}
+	return (args.ebx & 0xffff);
 }
 
 /* 
@@ -95,92 +118,122 @@
 int
 pci_cfgregopen(void)
 {
-    static int			opened = 0;
-    u_long			sigaddr;
-    static struct PIR_table	*pt;
-    u_int8_t			ck, *cv;
-    int				i;
-
-    if (opened)
-	return(1);
+	static int		opened = 0;
+	u_long			sigaddr;
+	static struct PIR_table	*pt;
+	u_int16_t		v;
+	u_int8_t		ck, *cv;
+	int			i;
+
+	if (opened)
+		return(1);
+
+	if (pcireg_cfgopen() == 0)
+		return(0);
+
+	v = pcibios_get_version();
+	if (v > 0)
+		printf("pcibios: BIOS version %x.%02x\n", (v & 0xff00) >> 8,
+		    v & 0xff);
 
-    if (pcireg_cfgopen() == 0)
-	return(0);
-
-    /*
-     * Look for the interrupt routing table.
-     */
-    /* We use PCI BIOS's PIR table if it's available */
-    if (pcibios_get_version() >= 0x0210 && pt == NULL && 
-      (sigaddr = bios_sigsearch(0, "$PIR", 4, 16, 0)) != 0) {
-	pt = (struct PIR_table *)(uintptr_t)BIOS_PADDRTOVADDR(sigaddr);
-	for (cv = (u_int8_t *)pt, ck = 0, i = 0; i < (pt->pt_header.ph_length); i++) {
-	    ck += cv[i];
-	}
-	if (ck == 0) {
-	    pci_route_table = pt;
-	    pci_route_count = (pt->pt_header.ph_length - sizeof(struct PIR_header)) / sizeof(struct PIR_entry);
-	    printf("Using $PIR table, %d entries at %p\n", pci_route_count, pci_route_table);
+	/*
+	 * Look for the interrupt routing table.
+	 *
+	 * We use PCI BIOS's PIR table if it's available $PIR is the
+	 * standard way to do this.  Sadly, some machines are not
+	 * standards conforming and have _PIR instead.  We shrug and cope
+	 * by looking for both.
+	 */
+	if (pcibios_get_version() >= 0x0210 && pt == NULL) {
+		sigaddr = bios_sigsearch(0, "$PIR", 4, 16, 0);
+		if (sigaddr == 0)
+			sigaddr = bios_sigsearch(0, "_PIR", 4, 16, 0);
+		if (sigaddr != 0) {
+			pt = (struct PIR_table *)(uintptr_t)
+			    BIOS_PADDRTOVADDR(sigaddr);
+			for (cv = (u_int8_t *)pt, ck = 0, i = 0;
+			     i < (pt->pt_header.ph_length); i++) {
+				ck += cv[i];
+			}
+			if (ck == 0 && pt->pt_header.ph_length >
+			    sizeof(struct PIR_header)) {
+				pci_route_table = pt;
+				pci_route_count = (pt->pt_header.ph_length -
+				    sizeof(struct PIR_header)) / 
+				    sizeof(struct PIR_entry);
+				printf("Using $PIR table, %d entries at %p\n",
+				    pci_route_count, pci_route_table);
+				if (bootverbose)
+					pci_print_route_table(pci_route_table,
+					    pci_route_count);
+			}
+		}
 	}
-    }
-
-    opened = 1;
-    return(1);
+	opened = 1;
+	return(1);
 }
 
 /* 
  * Read configuration space register
  */
-static u_int32_t
-pci_do_cfgregread(int bus, int slot, int func, int reg, int bytes)
-{
-    return(pcireg_cfgread(bus, slot, func, reg, bytes));
-}
-
 u_int32_t
 pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
 {
+	uint32_t line;
 #ifdef APIC_IO
-    /*
-     * If we are using the APIC, the contents of the intline register will probably
-     * be wrong (since they are set up for use with the PIC.
-     * Rather than rewrite these registers (maybe that would be smarter) we trap
-     * attempts to read them and translate to our private vector numbers.
-     */
-    if ((reg == PCIR_INTLINE) && (bytes == 1)) {
-	int	pin, line;
-
-	pin = pci_do_cfgregread(bus, slot, func, PCIR_INTPIN, 1);
-	line = pci_do_cfgregread(bus, slot, func, PCIR_INTLINE, 1);
-
-	if (pin != 0) {
-	    int airq;
-
-	    airq = pci_apic_irq(bus, slot, pin);
-	    if (airq >= 0) {
-		/* PCI specific entry found in MP table */
-		if (airq != line)
-		    undirect_pci_irq(line);
-		return(airq);
-	    } else {
-		/* 
-		 * PCI interrupts might be redirected to the
-		 * ISA bus according to some MP tables. Use the
-		 * same methods as used by the ISA devices
-		 * devices to find the proper IOAPIC int pin.
-		 */
-		airq = isa_apic_irq(line);
-		if ((airq >= 0) && (airq != line)) {
-		    /* XXX: undirect_pci_irq() ? */
-		    undirect_isa_irq(line);
-		    return(airq);
+	uint32_t pin;
+
+	/*
+	 * If we are using the APIC, the contents of the intline
+	 * register will probably be wrong (since they are set up for
+	 * use with the PIC.  Rather than rewrite these registers
+	 * (maybe that would be smarter) we trap attempts to read them
+	 * and translate to our private vector numbers.
+	 */
+	if ((reg == PCIR_INTLINE) && (bytes == 1)) {
+
+		pin = pcireg_cfgread(bus, slot, func, PCIR_INTPIN, 1);
+		line = pcireg_cfgread(bus, slot, func, PCIR_INTLINE, 1);
+
+		if (pin != 0) {
+			int airq;
+
+			airq = pci_apic_irq(bus, slot, pin);
+			if (airq >= 0) {
+				/* PCI specific entry found in MP table */
+				if (airq != line)
+					undirect_pci_irq(line);
+				return(airq);
+			} else {
+				/* 
+				 * PCI interrupts might be redirected
+				 * to the ISA bus according to some MP
+				 * tables. Use the same methods as
+				 * used by the ISA devices devices to
+				 * find the proper IOAPIC int pin.
+				 */
+				airq = isa_apic_irq(line);
+				if ((airq >= 0) && (airq != line)) {
+					/* XXX: undirect_pci_irq() ? */
+					undirect_isa_irq(line);
+					return(airq);
+				}
+			}
 		}
-	    }
+		return(line);
+	}
+#else
+	/*
+	 * Some BIOS writers seem to want to ignore the spec and put
+	 * 0 in the intline rather than 255 to indicate none.  The rest of
+	 * the code uses 255 as an invalid IRQ.
+	 */
+	if (reg == PCIR_INTLINE && bytes == 1) {
+		line = pcireg_cfgread(bus, slot, func, PCIR_INTLINE, 1);
+		return pci_i386_map_intline(line);
 	}
-	return(line);
-    }
 #endif /* APIC_IO */
-    return(pci_do_cfgregread(bus, slot, func, reg, bytes));
+	return(pcireg_cfgread(bus, slot, func, reg, bytes));
 }
 
 /* 
@@ -189,89 +242,158 @@
 void
 pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes)
 {
-    return(pcireg_cfgwrite(bus, slot, func, reg, data, bytes));
-}
-
-int
-pci_cfgread(pcicfgregs *cfg, int reg, int bytes)
-{
-	return(pci_cfgregread(cfg->bus, cfg->slot, cfg->func, reg, bytes));
-}
 
-void
-pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
-{
-	pci_cfgregwrite(cfg->bus, cfg->slot, cfg->func, reg, data, bytes);
+	pcireg_cfgwrite(bus, slot, func, reg, data, bytes);
 }
 
-
 /*
  * Route a PCI interrupt
- *
- * XXX we don't do anything "right" with the function number in the PIR table
- *     (because the consumer isn't currently passing it in).  We don't care
- *     anyway, due to the way PCI interrupts are assigned.
  */
 int
-pci_cfgintr(int bus, int device, int pin)
+pci_cfgintr(int bus, int device, int pin, int oldirq)
 {
-    struct PIR_entry	*pe;
-    int			i, irq;
-    struct bios_regs	args;
-    u_int16_t		v;
-    int already = 0;
-    
-    v = pcibios_get_version();
-    if (v < 0x0210) {
-	PRVERB((
-	  "pci_cfgintr: BIOS %x.%02x doesn't support interrupt routing\n",
-	  (v & 0xff00) >> 8, v & 0xff));
-	return (255);
-    }
-    if ((bus < 0) || (bus > 255) || (device < 0) || (device > 255) ||
-      (pin < 1) || (pin > 4))
-	return(255);
-
-    /*
-     * Scan the entry table for a contender
-     */
-    for (i = 0, pe = &pci_route_table->pt_entry[0]; i < pci_route_count; i++, pe++) {
-	if ((bus != pe->pe_bus) || (device != pe->pe_device))
-	    continue;
-
-	irq = pci_cfgintr_linked(pe, pin);
-	if (irq != 255)
-	     already = 1;
-	if (irq == 255)
-	    irq = pci_cfgintr_unique(pe, pin);
-	if (irq == 255)
-	    irq = pci_cfgintr_virgin(pe, pin);
-
-	if (irq == 255)
-	    break;
+	struct PIR_entry	*pe;
+	int			i, irq;
+	struct bios_regs	args;
+ 	int already = 0;
+ 	int errok = 0;
+
+    if(pin==1 && device==9)
+	already = 10;
+    if(pin==1 && device==10)
+	already = 6;
+
+    if(already)
+    {
+	u_long intr;
+	u_char irq = already;
+	
+#define PCI_INTERRUPT_REG 0x3c
+#define	PCI_INTERRUPT_LINE_SHIFT		0
+#define	PCI_INTERRUPT_LINE_MASK			0xff
+#define	PCI_INTERRUPT_LINE(icr) \
+	    (((icr) >> PCI_INTERRUPT_LINE_SHIFT) & PCI_INTERRUPT_LINE_MASK)
+
+	intr = pci_cfgregread(bus, device, 0 , PCI_INTERRUPT_REG, 4);
+	if (irq != PCI_INTERRUPT_LINE(intr)) {
+		intr &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT);
+		intr |= (irq << PCI_INTERRUPT_LINE_SHIFT);
+		pci_cfgregwrite(bus, device,0 , PCI_INTERRUPT_REG, intr, 4);
+	}
+
+	return irq;
+    }
+
+    already = 0;
+
+	v = pcibios_get_version();
+	if (v < 0x0210) {
+		PRVERB((
+		"pci_cfgintr: BIOS %x.%02x doesn't support interrupt routing\n",
+		    (v & 0xff00) >> 8, v & 0xff));
+		return (PCI_INVALID_IRQ);
+	}
+	if ((bus < 0) || (bus > 255) || (device < 0) || (device > 255) ||
+	    (pin < 1) || (pin > 4))
+		return(PCI_INVALID_IRQ);
 
 	/*
-	 * Ask the BIOS to route the interrupt
+	 * Scan the entry table for a contender
 	 */
-	args.eax = PCIBIOS_ROUTE_INTERRUPT;
-	args.ebx = (bus << 8) | (device << 3);
-	args.ecx = (irq << 8) | (0xa + pin - 1);	/* pin value is 0xa - 0xd */
-	if (bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL)) && !already) {
-	    /*
-	     * XXX if it fails, we should try to smack the router
-	     * hardware directly.
-	     * XXX Also, there may be other choices that we can try that
-	     * will work.
-	     */
-	    PRVERB(("pci_cfgintr: ROUTE_INTERRUPT failed.\n"));
-	    return(255);
+	for (i = 0, pe = &pci_route_table->pt_entry[0]; i < pci_route_count; 
+	     i++, pe++) {
+		if ((bus != pe->pe_bus) || (device != pe->pe_device))
+			continue;
+		/*
+		 * A link of 0 means that this intpin is not connected to
+		 * any other device's interrupt pins and is not connected to
+		 * any of the Interrupt Router's interrupt pins, so we can't
+		 * route it.
+		 */
+		if (pe->pe_intpin[pin - 1].link == 0)
+			continue;
+
+		if (pci_cfgintr_valid(pe, pin, oldirq)) {
+			printf("pci_cfgintr: %d:%d INT%c BIOS irq %d\n", bus,
+			    device, 'A' + pin - 1, oldirq);
+			return (oldirq);
+		}
+
+		/*
+		 * We try to find a linked interrupt, then we look to see
+		 * if the interrupt is uniquely routed, then we look for
+		 * a virgin interrupt.  The virgin interrupt should return
+		 * an interrupt we can route, but if that fails, maybe we
+		 * should try harder to route a different interrupt.
+		 * However, experience has shown that that's rarely the
+		 * failure mode we see.
+		 */
+		irq = pci_cfgintr_linked(pe, pin);
+		if (irq != PCI_INVALID_IRQ)
+			already = 1;
+		if (irq == PCI_INVALID_IRQ) {
+			irq = pci_cfgintr_unique(pe, pin);
+			if (irq != PCI_INVALID_IRQ)
+				errok = 1;
+		}
+		if (irq == PCI_INVALID_IRQ)
+			irq = pci_cfgintr_virgin(pe, pin);
+		if (irq == PCI_INVALID_IRQ)
+			break;
+
+		/*
+		 * Ask the BIOS to route the interrupt.  If we picked an
+		 * interrupt that failed, we should really try other
+		 * choices that the BIOS offers us.
+		 *
+		 * For uniquely routed interrupts, we need to try
+		 * to route them on some machines.  Yet other machines
+		 * fail to route, so we have to pretend that in that
+		 * case it worked.  Isn't pc hardware fun?
+		 *
+		 * NOTE: if we want to whack hardware to do this, then
+		 * I think the right way to do that would be to have
+		 * bridge drivers that do this.  I'm not sure that the
+		 * $PIR table would be valid for those interrupt
+		 * routers.
+		 */
+		args.eax = PCIBIOS_ROUTE_INTERRUPT;
+		args.ebx = (bus << 8) | (device << 3);
+		/* pin value is 0xa - 0xd */
+		args.ecx = (irq << 8) | (0xa + pin - 1);
+		if (!already &&
+		    bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL)) &&
+		    !errok) {
+			PRVERB(("pci_cfgintr: ROUTE_INTERRUPT failed.\n"));
+			return(PCI_INVALID_IRQ);
+		}
+		printf("pci_cfgintr: %d:%d INT%c routed to irq %d\n", bus, 
+		    device, 'A' + pin - 1, irq);
+		return(irq);
 	}
-	printf("pci_cfgintr: %d:%d INT%c routed to irq %d\n", bus, device, 'A' + pin - 1, irq);
-	return(irq);
-    }
 
-    PRVERB(("pci_cfgintr: can't route an interrupt to %d:%d INT%c\n", bus, device, 'A' + pin - 1));
-    return(255);
+	PRVERB(("pci_cfgintr: can't route an interrupt to %d:%d INT%c\n", bus, 
+	    device, 'A' + pin - 1));
+	return(PCI_INVALID_IRQ);
+}
+
+/*
+ * Check to see if an existing IRQ setting is valid.
+ */
+static int
+pci_cfgintr_valid(struct PIR_entry *pe, int pin, int irq)
+{
+	uint32_t irqmask;
+
+	if (!PCI_INTERRUPT_VALID(irq))
+		return (0);
+	irqmask = pe->pe_intpin[pin - 1].irqs;
+	if (irqmask & (1 << irq)) {
+		PRVERB(("pci_cfgintr_valid: BIOS irq %d is valid\n", irq));
+		return (1);
+	}
+	return (0);
 }
 
 /*
@@ -280,14 +402,16 @@
 static int
 pci_cfgintr_unique(struct PIR_entry *pe, int pin)
 {
-    int		irq;
+	int		irq;
+	uint32_t	irqmask;
     
-    if (powerof2(pe->pe_intpin[pin - 1].irqs)) {
-	irq = ffs(pe->pe_intpin[pin - 1].irqs) - 1;
-	PRVERB(("pci_cfgintr_unique: hard-routed to irq %d\n", irq));
-	return(irq);
-    }
-    return(255);
+	irqmask = pe->pe_intpin[pin - 1].irqs;
+	if (irqmask != 0 && powerof2(irqmask)) {
+		irq = ffs(irqmask) - 1;
+		PRVERB(("pci_cfgintr_unique: hard-routed to irq %d\n", irq));
+		return(irq);
+	}
+	return(PCI_INVALID_IRQ);
 }
 
 /*
@@ -297,40 +421,43 @@
 static int
 pci_cfgintr_linked(struct PIR_entry *pe, int pin)
 {
-    struct PIR_entry	*oe;
-    struct PIR_intpin	*pi;
-    int			i, j, irq;
-
-    /*
-     * Scan table slots.
-     */
-    for (i = 0, oe = &pci_route_table->pt_entry[0]; i < pci_route_count; i++, oe++) {
-
-	/* scan interrupt pins */
-	for (j = 0, pi = &oe->pe_intpin[0]; j < 4; j++, pi++) {
-
-	    /* don't look at the entry we're trying to match with */
-	    if ((pe == oe) && (i == (pin - 1)))
-		continue;
-
-	    /* compare link bytes */
-	    if (pi->link != pe->pe_intpin[pin - 1].link)
-		continue;
-	    
-	    /* link destination mapped to a unique interrupt? */
-	    if (powerof2(pi->irqs)) {
-		irq = ffs(pi->irqs) - 1;
-		PRVERB(("pci_cfgintr_linked: linked (%x) to hard-routed irq %d\n",
-		       pi->link, irq));
-		return(irq);
-	    } 
+	struct PIR_entry	*oe;
+	struct PIR_intpin	*pi;
+	int			i, j, irq;
 
-	    /* look for the real PCI device that matches this table entry */
-	    if ((irq = pci_cfgintr_search(pe, oe->pe_bus, oe->pe_device, j, pin)) != 255)
-		return(irq);
+	/*
+	 * Scan table slots.
+	 */
+	for (i = 0, oe = &pci_route_table->pt_entry[0]; i < pci_route_count;
+	     i++, oe++) {
+		/* scan interrupt pins */
+		for (j = 0, pi = &oe->pe_intpin[0]; j < 4; j++, pi++) {
+
+			/* don't look at the entry we're trying to match */
+			if ((pe == oe) && (i == (pin - 1)))
+				continue;
+			/* compare link bytes */
+			if (pi->link != pe->pe_intpin[pin - 1].link)
+				continue;
+			/* link destination mapped to a unique interrupt? */
+			if (pi->irqs != 0 && powerof2(pi->irqs)) {
+				irq = ffs(pi->irqs) - 1;
+				PRVERB(("pci_cfgintr_linked: linked (%x) to hard-routed irq %d\n",
+				    pi->link, irq));
+				return(irq);
+			} 
+
+			/* 
+			 * look for the real PCI device that matches this 
+			 * table entry 
+			 */
+			irq = pci_cfgintr_search(pe, oe->pe_bus, oe->pe_device,
+			    j, pin);
+			if (irq != PCI_INVALID_IRQ)
+				return(irq);
+		}
 	}
-    }
-    return(255);
+	return(PCI_INVALID_IRQ);
 }
 
 /*
@@ -340,55 +467,51 @@
 static int
 pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int pin)
 {
-    devclass_t		pci_devclass;
-    device_t		*pci_devices;
-    int			pci_count;
-    device_t		*pci_children;
-    int			pci_childcount;
-    device_t		*busp, *childp;
-    int			i, j, irq;
-
-    /*
-     * Find all the PCI busses.
-     */
-    pci_count = 0;
-    if ((pci_devclass = devclass_find("pci")) != NULL)
-	devclass_get_devices(pci_devclass, &pci_devices, &pci_count);
-
-    /*
-     * Scan all the PCI busses/devices looking for this one.
-     */
-    irq = 255;
-    for (i = 0, busp = pci_devices; (i < pci_count) && (irq == 255); i++, busp++) {
-	pci_childcount = 0;
-	device_get_children(*busp, &pci_children, &pci_childcount);
+	devclass_t		pci_devclass;
+	device_t		*pci_devices;
+	int			pci_count;
+	device_t		*pci_children;
+	int			pci_childcount;
+	device_t		*busp, *childp;
+	int			i, j, irq;
+
+	/*
+	 * Find all the PCI busses.
+	 */
+	pci_count = 0;
+	if ((pci_devclass = devclass_find("pci")) != NULL)
+		devclass_get_devices(pci_devclass, &pci_devices, &pci_count);
+
+	/*
+	 * Scan all the PCI busses/devices looking for this one.
+	 */
+	irq = PCI_INVALID_IRQ;
+	for (i = 0, busp = pci_devices; (i < pci_count) && (irq == PCI_INVALID_IRQ);
+	     i++, busp++) {
+		pci_childcount = 0;
+		device_get_children(*busp, &pci_children, &pci_childcount);
 		
-	for (j = 0, childp = pci_children; j < pci_childcount; j++, childp++) {
-	    if ((pci_get_bus(*childp) == bus) &&
-		(pci_get_slot(*childp) == device) &&
-		(pci_get_intpin(*childp) == matchpin)) {
-		irq = pci_get_irq(*childp);
-		/*
-		 * Some BIOS writers seem to want to ignore the spec and put
-		 * 0 in the intline rather than 255 to indicate none.  Once
-		 * we've found one that matches, we break because there can
-		 * be no others (which is why test looks a little odd).
-		 */
-		if (irq == 0)
-		    irq = 255;
-		if (irq != 255)
-		    PRVERB(("pci_cfgintr_search: linked (%x) to configured irq %d at %d:%d:%d\n",
-		      pe->pe_intpin[pin - 1].link, irq,
-		      pci_get_bus(*childp), pci_get_slot(*childp), pci_get_function(*childp)));
-		break;
-	    }
+		for (j = 0, childp = pci_children; j < pci_childcount; j++, 
+		    childp++) {
+			if ((pci_get_bus(*childp) == bus) &&
+			    (pci_get_slot(*childp) == device) &&
+			    (pci_get_intpin(*childp) == matchpin)) {
+				irq = pci_i386_map_intline(pci_get_irq(*childp));
+				if (irq != PCI_INVALID_IRQ)
+					PRVERB(("pci_cfgintr_search: linked (%x) to configured irq %d at %d:%d:%d\n",
+					    pe->pe_intpin[pin - 1].link, irq,
+					    pci_get_bus(*childp),
+					    pci_get_slot(*childp), 
+					    pci_get_function(*childp)));
+				break;
+			}
+		}
+		if (pci_children != NULL)
+			free(pci_children, M_TEMP);
 	}
-	if (pci_children != NULL)
-	    free(pci_children, M_TEMP);
-    }
-    if (pci_devices != NULL)
-	free(pci_devices, M_TEMP);
-    return(irq);
+	if (pci_devices != NULL)
+		free(pci_devices, M_TEMP);
+	return(irq);
 }
 
 /*
@@ -397,30 +520,102 @@
 static int
 pci_cfgintr_virgin(struct PIR_entry *pe, int pin)
 {
-    int		irq, ibit;
+	int		irq, ibit;
     
-    /* first scan the set of PCI-only interrupts and see if any of these are routable */
-    for (irq = 0; irq < 16; irq++) {
-	ibit = (1 << irq);
-
-	/* can we use this interrupt? */
-	if ((pci_route_table->pt_header.ph_pci_irqs & ibit) &&
-	    (pe->pe_intpin[pin - 1].irqs & ibit)) {
-	    PRVERB(("pci_cfgintr_virgin: using routable PCI-only interrupt %d\n", irq));
-	    return(irq);
+	/*
+	 * first scan the set of PCI-only interrupts and see if any of these 
+	 * are routable
+	 */ 
+	for (irq = 0; irq < 16; irq++) {
+		ibit = (1 << irq);
+
+		/* can we use this interrupt? */
+		if ((pci_route_table->pt_header.ph_pci_irqs & ibit) &&
+		    (pe->pe_intpin[pin - 1].irqs & ibit)) {
+			PRVERB(("pci_cfgintr_virgin: using routable PCI-only interrupt %d\n", irq));
+			return(irq);
+		}
 	}
-    }
     
-    /* life is tough, so just pick an interrupt */
-    for (irq = 0; irq < 16; irq++) {
-	ibit = (1 << irq);
-    
-	if (pe->pe_intpin[pin - 1].irqs & ibit) {
-	    PRVERB(("pci_cfgintr_virgin: using routable interrupt %d\n", irq));
-	    return(irq);
+	/* life is tough, so just pick an interrupt */
+	for (irq = 0; irq < 16; irq++) {
+		ibit = (1 << irq);
+		if (pe->pe_intpin[pin - 1].irqs & ibit) {
+			PRVERB(("pci_cfgintr_virgin: using routable interrupt %d\n", irq));
+			return(irq);
+		}
 	}
-    }
-    return(255);
+	return(PCI_INVALID_IRQ);
+}
+
+static void
+pci_print_irqmask(u_int16_t irqs)
+{
+	int i, first;
+
+	if (irqs == 0) {
+		printf("none");
+		return;
+	}
+	first = 1;
+	for (i = 0; i < 16; i++, irqs >>= 1)
+		if (irqs & 1) {
+			if (!first)
+				printf(" ");
+			else
+				first = 0;
+			printf("%d", i);
+		}
+}
+
+/*
+ * Dump the contents of a PCI BIOS Interrupt Routing Table to the console.
+ */
+static void
+pci_print_route_table(struct PIR_table *prt, int size)
+{
+	struct PIR_entry *entry;
+	struct PIR_intpin *intpin;
+	int i, pin;
+
+	printf("PCI-Only Interrupts: ");
+	pci_print_irqmask(prt->pt_header.ph_pci_irqs);
+	printf("\nLocation  Bus Device Pin  Link  IRQs\n");
+	entry = &prt->pt_entry[0];
+	for (i = 0; i < size; i++, entry++) {
+		intpin = &entry->pe_intpin[0];
+		for (pin = 0; pin < 4; pin++, intpin++)
+			if (intpin->link != 0) {
+				if (entry->pe_slot == 0)
+					printf("embedded ");
+				else
+					printf("slot %-3d ", entry->pe_slot);
+				printf(" %3d  %3d    %c   0x%02x  ",
+				    entry->pe_bus, entry->pe_device,
+				    'A' + pin, intpin->link);
+				pci_print_irqmask(intpin->irqs);
+				printf("\n");
+			}
+	}
+}
+
+/*
+ * See if any interrupts for a given PCI bus are routed in the PIR.  Don't
+ * even bother looking if the BIOS doesn't support routing anyways.
+ */
+int
+pci_probe_route_table(int bus)
+{
+	int i;
+	u_int16_t v;
+
+	v = pcibios_get_version();
+	if (v < 0x0210)
+		return (0);
+	for (i = 0; i < pci_route_count; i++)
+		if (pci_route_table->pt_entry[i].pe_bus == bus)
+			return (1);
+	return (0);
 }
 
 /* 
@@ -431,214 +626,218 @@
 static int
 pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes)
 {
-    int dataport = 0;
+	int dataport = 0;
 
-    if (bus <= PCI_BUSMAX
-	&& slot < devmax
-	&& func <= PCI_FUNCMAX
-	&& reg <= PCI_REGMAX
-	&& bytes != 3
-	&& (unsigned) bytes <= 4
-	&& (reg & (bytes -1)) == 0) {
-	switch (cfgmech) {
-	case 1:
-	    outl(CONF1_ADDR_PORT, (1 << 31)
-		 | (bus << 16) | (slot << 11) 
-		 | (func << 8) | (reg & ~0x03));
-	    dataport = CONF1_DATA_PORT + (reg & 0x03);
-	    break;
-	case 2:
-	    outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1));
-	    outb(CONF2_FORWARD_PORT, bus);
-	    dataport = 0xc000 | (slot << 8) | reg;
-	    break;
+	if (bus <= PCI_BUSMAX
+	    && slot < devmax
+	    && func <= PCI_FUNCMAX
+	    && reg <= PCI_REGMAX
+	    && bytes != 3
+	    && (unsigned) bytes <= 4
+	    && (reg & (bytes - 1)) == 0) {
+		switch (cfgmech) {
+		case 1:
+			outl(CONF1_ADDR_PORT, (1 << 31)
+			    | (bus << 16) | (slot << 11) 
+			    | (func << 8) | (reg & ~0x03));
+			dataport = CONF1_DATA_PORT + (reg & 0x03);
+			break;
+		case 2:
+			outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1));
+			outb(CONF2_FORWARD_PORT, bus);
+			dataport = 0xc000 | (slot << 8) | reg;
+			break;
+		}
 	}
-    }
-    return (dataport);
+	return (dataport);
 }
 
 /* disable configuration space accesses */
 static void
 pci_cfgdisable(void)
 {
-    switch (cfgmech) {
-    case 1:
-	outl(CONF1_ADDR_PORT, 0);
-	break;
-    case 2:
-	outb(CONF2_ENABLE_PORT, 0);
-	outb(CONF2_FORWARD_PORT, 0);
-	break;
-    }
+	switch (cfgmech) {
+	case 1:
+		outl(CONF1_ADDR_PORT, 0);
+		break;
+	case 2:
+		outb(CONF2_ENABLE_PORT, 0);
+		outb(CONF2_FORWARD_PORT, 0);
+		break;
+	}
 }
 
 static int
 pcireg_cfgread(int bus, int slot, int func, int reg, int bytes)
 {
-    int data = -1;
-    int port;
+	int data = -1;
+	int port;
 
-    port = pci_cfgenable(bus, slot, func, reg, bytes);
-
-    if (port != 0) {
-	switch (bytes) {
-	case 1:
-	    data = inb(port);
-	    break;
-	case 2:
-	    data = inw(port);
-	    break;
-	case 4:
-	    data = inl(port);
-	    break;
+	port = pci_cfgenable(bus, slot, func, reg, bytes);
+	if (port != 0) {
+		switch (bytes) {
+		case 1:
+			data = inb(port);
+			break;
+		case 2:
+			data = inw(port);
+			break;
+		case 4:
+			data = inl(port);
+			break;
+		}
+		pci_cfgdisable();
 	}
-	pci_cfgdisable();
-    }
-    return (data);
+	return (data);
 }
 
 static void
 pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
 {
-    int port;
+	int port;
 
-    port = pci_cfgenable(bus, slot, func, reg, bytes);
-    if (port != 0) {
-	switch (bytes) {
-	case 1:
-	    outb(port, data);
-	    break;
-	case 2:
-	    outw(port, data);
-	    break;
-	case 4:
-	    outl(port, data);
-	    break;
+	port = pci_cfgenable(bus, slot, func, reg, bytes);
+	if (port != 0) {
+		switch (bytes) {
+		case 1:
+			outb(port, data);
+			break;
+		case 2:
+			outw(port, data);
+			break;
+		case 4:
+			outl(port, data);
+			break;
+		}
+		pci_cfgdisable();
 	}
-	pci_cfgdisable();
-    }
 }
 
 /* check whether the configuration mechanism has been correctly identified */
 static int
 pci_cfgcheck(int maxdev)
 {
-    u_char device;
-
-    if (bootverbose) 
-	printf("pci_cfgcheck:\tdevice ");
+	uint32_t id, class;
+	uint8_t header;
+	uint8_t device;
+	int port;
 
-    for (device = 0; device < maxdev; device++) {
-	unsigned id, class, header;
 	if (bootverbose) 
-	    printf("%d ", device);
+		printf("pci_cfgcheck:\tdevice ");
 
-	id = inl(pci_cfgenable(0, device, 0, 0, 4));
-	if (id == 0 || id == -1)
-	    continue;
-
-	class = inl(pci_cfgenable(0, device, 0, 8, 4)) >> 8;
-	if (bootverbose)
-	    printf("[class=%06x] ", class);
-	if (class == 0 || (class & 0xf870ff) != 0)
-	    continue;
+	for (device = 0; device < maxdev; device++) {
+		if (bootverbose) 
+			printf("%d ", device);
+
+		port = pci_cfgenable(0, device, 0, 0, 4);
+		id = inl(port);
+		if (id == 0 || id == 0xffffffff)
+			continue;
+
+		port = pci_cfgenable(0, device, 0, 8, 4);
+		class = inl(port) >> 8;
+		if (bootverbose)
+			printf("[class=%06x] ", class);
+		if (class == 0 || (class & 0xf870ff) != 0)
+			continue;
+
+		port = pci_cfgenable(0, device, 0, 14, 1);
+		header = inb(port);
+		if (bootverbose)
+			printf("[hdr=%02x] ", header);
+		if ((header & 0x7e) != 0)
+			continue;
 
-	header = inb(pci_cfgenable(0, device, 0, 14, 1));
-	if (bootverbose) 
-	    printf("[hdr=%02x] ", header);
-	if ((header & 0x7e) != 0)
-	    continue;
+		if (bootverbose)
+			printf("is there (id=%08x)\n", id);
 
-	if (bootverbose)
-	    printf("is there (id=%08x)\n", id);
+		pci_cfgdisable();
+		return (1);
+	}
+	if (bootverbose) 
+		printf("-- nothing found\n");
 
 	pci_cfgdisable();
-	return (1);
-    }
-    if (bootverbose) 
-	printf("-- nothing found\n");
-
-    pci_cfgdisable();
-    return (0);
+	return (0);
 }
 
 static int
 pcireg_cfgopen(void)
 {
-    unsigned long mode1res,oldval1;
-    unsigned char mode2res,oldval2;
-
-    oldval1 = inl(CONF1_ADDR_PORT);
-
-    if (bootverbose) {
-	printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n",
-	       oldval1);
-    }
+	uint32_t mode1res, oldval1;
+	uint8_t mode2res, oldval2;
 
-    if ((oldval1 & CONF1_ENABLE_MSK) == 0) {
+	oldval1 = inl(CONF1_ADDR_PORT);
 
-	cfgmech = 1;
-	devmax = 32;
+	if (bootverbose) {
+		printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08x\n",
+		    oldval1);
+	}
 
-	outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK);
-	outb(CONF1_ADDR_PORT +3, 0);
-	mode1res = inl(CONF1_ADDR_PORT);
-	outl(CONF1_ADDR_PORT, oldval1);
+	if ((oldval1 & CONF1_ENABLE_MSK) == 0) {
 
-	if (bootverbose)
-	    printf("pci_open(1a):\tmode1res=0x%08lx (0x%08lx)\n", 
-		   mode1res, CONF1_ENABLE_CHK);
+		cfgmech = 1;
+		devmax = 32;
 
-	if (mode1res) {
-	    if (pci_cfgcheck(32)) 
-		return (cfgmech);
-	}
+		outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK);
+		outb(CONF1_ADDR_PORT + 3, 0);
+		mode1res = inl(CONF1_ADDR_PORT);
+		outl(CONF1_ADDR_PORT, oldval1);
 
-	outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
-	mode1res = inl(CONF1_ADDR_PORT);
-	outl(CONF1_ADDR_PORT, oldval1);
+		if (bootverbose)
+			printf("pci_open(1a):\tmode1res=0x%08x (0x%08lx)\n", 
+			    mode1res, CONF1_ENABLE_CHK);
 
-	if (bootverbose)
-	    printf("pci_open(1b):\tmode1res=0x%08lx (0x%08lx)\n", 
-		   mode1res, CONF1_ENABLE_CHK1);
+		if (mode1res) {
+			if (pci_cfgcheck(32)) 
+				return (cfgmech);
+		}
 
-	if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) {
-	    if (pci_cfgcheck(32)) 
-		return (cfgmech);
+		outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
+		mode1res = inl(CONF1_ADDR_PORT);
+		outl(CONF1_ADDR_PORT, oldval1);
+
+		if (bootverbose)
+			printf("pci_open(1b):\tmode1res=0x%08x (0x%08lx)\n", 
+			    mode1res, CONF1_ENABLE_CHK1);
+
+		if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) {
+			if (pci_cfgcheck(32)) 
+				return (cfgmech);
+		}
 	}
-    }
 
-    oldval2 = inb(CONF2_ENABLE_PORT);
+	oldval2 = inb(CONF2_ENABLE_PORT);
 
-    if (bootverbose) {
-	printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n",
-	       oldval2);
-    }
+	if (bootverbose) {
+		printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n",
+		    oldval2);
+	}
 
-    if ((oldval2 & 0xf0) == 0) {
+	if ((oldval2 & 0xf0) == 0) {
 
-	cfgmech = 2;
-	devmax = 16;
+		cfgmech = 2;
+		devmax = 16;
 
-	outb(CONF2_ENABLE_PORT, CONF2_ENABLE_CHK);
-	mode2res = inb(CONF2_ENABLE_PORT);
-	outb(CONF2_ENABLE_PORT, oldval2);
+		outb(CONF2_ENABLE_PORT, CONF2_ENABLE_CHK);
+		mode2res = inb(CONF2_ENABLE_PORT);
+		outb(CONF2_ENABLE_PORT, oldval2);
 
-	if (bootverbose)
-	    printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n", 
-		   mode2res, CONF2_ENABLE_CHK);
+		if (bootverbose)
+			printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n", 
+			    mode2res, CONF2_ENABLE_CHK);
 
-	if (mode2res == CONF2_ENABLE_RES) {
-	    if (bootverbose)
-		printf("pci_open(2a):\tnow trying mechanism 2\n");
+		if (mode2res == CONF2_ENABLE_RES) {
+			if (bootverbose)
+				printf("pci_open(2a):\tnow trying mechanism 2\n");
 
-	    if (pci_cfgcheck(16)) 
-		return (cfgmech);
+			if (pci_cfgcheck(16)) 
+				return (cfgmech);
+		}
 	}
-    }
 
-    cfgmech = 0;
-    devmax = 0;
-    return (cfgmech);
+	cfgmech = 0;
+	devmax = 0;
+	return (cfgmech);
 }
 
diff -uNr sys.old/bus/pci/i386/pci_cfgreg.h sys/bus/pci/i386/pci_cfgreg.h
--- sys.old/bus/pci/i386/pci_cfgreg.h	Thu Jan  1 00:00:00 1970
+++ sys/bus/pci/i386/pci_cfgreg.h	Sat Dec 20 17:08:07 2003
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1997, Stefan Esser <se@xxxxxxxxxxx>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice unmodified, this list of conditions, and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/i386/include/pci_cfgreg.h,v 1.9 2003/02/18 03:36:48 peter Exp $
+ * $DragonFly$
+ *
+ */
+
+#define CONF1_ADDR_PORT    0x0cf8
+#define CONF1_DATA_PORT    0x0cfc
+
+#define CONF1_ENABLE       0x80000000ul
+#define CONF1_ENABLE_CHK   0x80000000ul
+#define CONF1_ENABLE_MSK   0x7ff00000ul
+#define CONF1_ENABLE_CHK1  0xff000001ul
+#define CONF1_ENABLE_MSK1  0x80000001ul
+#define CONF1_ENABLE_RES1  0x80000000ul
+
+#define CONF2_ENABLE_PORT  0x0cf8
+#ifdef PC98
+#define CONF2_FORWARD_PORT 0x0cf9
+#else
+#define CONF2_FORWARD_PORT 0x0cfa
+#endif
+
+#define CONF2_ENABLE_CHK   0x0e
+#define CONF2_ENABLE_RES   0x0e
+
+int		pci_cfgregopen(void);
+u_int32_t	pci_cfgregread(int bus, int slot, int func, int reg, int bytes);
+void		pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes);
+int		pci_cfgintr(int bus, int device, int pin, int oldirq);
+int		pci_probe_route_table(int bus);
+
+#define PCI_INVALID_IRQ		255
+#define PCI_INTERRUPT_VALID(x)	((x) != PCI_INVALID_IRQ)
diff -uNr sys.old/bus/pci/pci.c sys/bus/pci/pci.c
--- sys.old/bus/pci/pci.c	Sat Dec 20 16:56:09 2003
+++ sys/bus/pci/pci.c	Sat Dec 20 17:08:07 2003
@@ -24,6 +24,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/pci/pci.c,v 1.141.2.15 2002/04/30 17:48:18 tmm Exp $
+ * merged in revision 1.167, skipped 1.162 and 1.166
  * $DragonFly: src/sys/bus/pci/pci.c,v 1.6 2003/11/17 00:54:39 asmodai Exp $
  *
  */
@@ -62,6 +63,8 @@
 #include "pcireg.h"
 #include "pcivar.h"
 
+#include "pcib_if.h"
+
 #ifdef __alpha__
 #include <machine/rpb.h>
 #endif
@@ -72,7 +75,7 @@
 
 static devclass_t	pci_devclass;
 
-static void		pci_read_extcap(pcicfgregs *cfg);
+static void		pci_read_extcap(device_t dev, pcicfgregs *cfg);
 
 struct pci_quirk {
 	u_int32_t devid;	/* Vendor/device of the card */
@@ -219,109 +222,115 @@
 /* read config data specific to header type 1 device (PCI to PCI bridge) */
 
 static void *
-pci_readppb(pcicfgregs *cfg)
+pci_readppb(device_t pcib, int b, int s, int f)
 {
 	pcih1cfgregs *p;
 
-	p = malloc(sizeof (pcih1cfgregs), M_DEVBUF, M_WAITOK);
+	p = malloc(sizeof (pcih1cfgregs), M_DEVBUF, M_WAITOK | M_ZERO);
 	if (p == NULL)
 		return (NULL);
 
-	bzero(p, sizeof *p);
-
-	p->secstat = pci_cfgread(cfg, PCIR_SECSTAT_1, 2);
-	p->bridgectl = pci_cfgread(cfg, PCIR_BRIDGECTL_1, 2);
+	p->secstat = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECSTAT_1, 2);
+	p->bridgectl = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_BRIDGECTL_1, 2);
 
-	p->seclat = pci_cfgread(cfg, PCIR_SECLAT_1, 1);
+	p->seclat = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECLAT_1, 1);
 
-	p->iobase = PCI_PPBIOBASE (pci_cfgread(cfg, PCIR_IOBASEH_1, 2),
-				   pci_cfgread(cfg, PCIR_IOBASEL_1, 1));
-	p->iolimit = PCI_PPBIOLIMIT (pci_cfgread(cfg, PCIR_IOLIMITH_1, 2),
-				     pci_cfgread(cfg, PCIR_IOLIMITL_1, 1));
+	p->iobase = PCI_PPBIOBASE (PCIB_READ_CONFIG(pcib, b, s, f,
+						    PCIR_IOBASEH_1, 2),
+				   PCIB_READ_CONFIG(pcib, b, s, f,
+				   		    PCIR_IOBASEL_1, 1));
+	p->iolimit = PCI_PPBIOLIMIT (PCIB_READ_CONFIG(pcib, b, s, f,
+						      PCIR_IOLIMITH_1, 2),
+				     PCIB_READ_CONFIG(pcib, b, s, f,
+				     		      PCIR_IOLIMITL_1, 1));
 
 	p->membase = PCI_PPBMEMBASE (0,
-				     pci_cfgread(cfg, PCIR_MEMBASE_1, 2));
+				     PCIB_READ_CONFIG(pcib, b, s, f,
+				     		      PCIR_MEMBASE_1, 2));
 	p->memlimit = PCI_PPBMEMLIMIT (0,
-				       pci_cfgread(cfg, PCIR_MEMLIMIT_1, 2));
+				       PCIB_READ_CONFIG(pcib, b, s, f,
+				       		        PCIR_MEMLIMIT_1, 2));
 
 	p->pmembase = PCI_PPBMEMBASE (
-		(pci_addr_t)pci_cfgread(cfg, PCIR_PMBASEH_1, 4),
-		pci_cfgread(cfg, PCIR_PMBASEL_1, 2));
+		(pci_addr_t)PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PMBASEH_1, 4),
+		PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PMBASEL_1, 2));
 
 	p->pmemlimit = PCI_PPBMEMLIMIT (
-		(pci_addr_t)pci_cfgread(cfg, PCIR_PMLIMITH_1, 4),
-		pci_cfgread(cfg, PCIR_PMLIMITL_1, 2));
+		(pci_addr_t)PCIB_READ_CONFIG(pcib, b, s, f,
+					     PCIR_PMLIMITH_1, 4),
+		PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PMLIMITL_1, 2));
 	return (p);
 }
 
 /* read config data specific to header type 2 device (PCI to CardBus bridge) */
 
 static void *
-pci_readpcb(pcicfgregs *cfg)
+pci_readpcb(device_t pcib, int b, int s, int f)
 {
 	pcih2cfgregs *p;
 
-	p = malloc(sizeof (pcih2cfgregs), M_DEVBUF, M_WAITOK);
+	p = malloc(sizeof (pcih2cfgregs), M_DEVBUF, M_WAITOK | M_ZERO);
 	if (p == NULL)
 		return (NULL);
 
-	bzero(p, sizeof *p);
-
-	p->secstat = pci_cfgread(cfg, PCIR_SECSTAT_2, 2);
-	p->bridgectl = pci_cfgread(cfg, PCIR_BRIDGECTL_2, 2);
+	p->secstat = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECSTAT_2, 2);
+	p->bridgectl = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_BRIDGECTL_2, 2);
 	
-	p->seclat = pci_cfgread(cfg, PCIR_SECLAT_2, 1);
+	p->seclat = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECLAT_2, 1);
 
-	p->membase0 = pci_cfgread(cfg, PCIR_MEMBASE0_2, 4);
-	p->memlimit0 = pci_cfgread(cfg, PCIR_MEMLIMIT0_2, 4);
-	p->membase1 = pci_cfgread(cfg, PCIR_MEMBASE1_2, 4);
-	p->memlimit1 = pci_cfgread(cfg, PCIR_MEMLIMIT1_2, 4);
-
-	p->iobase0 = pci_cfgread(cfg, PCIR_IOBASE0_2, 4);
-	p->iolimit0 = pci_cfgread(cfg, PCIR_IOLIMIT0_2, 4);
-	p->iobase1 = pci_cfgread(cfg, PCIR_IOBASE1_2, 4);
-	p->iolimit1 = pci_cfgread(cfg, PCIR_IOLIMIT1_2, 4);
+	p->membase0 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_MEMBASE0_2, 4);
+	p->memlimit0 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_MEMLIMIT0_2, 4);
+	p->membase1 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_MEMBASE1_2, 4);
+	p->memlimit1 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_MEMLIMIT1_2, 4);
+
+	p->iobase0 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOBASE0_2, 4);
+	p->iolimit0 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOLIMIT0_2, 4);
+	p->iobase1 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOBASE1_2, 4);
+	p->iolimit1 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOLIMIT1_2, 4);
 
-	p->pccardif = pci_cfgread(cfg, PCIR_PCCARDIF_2, 4);
+	p->pccardif = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PCCARDIF_2, 4);
 	return p;
 }
 
 /* extract header type specific config data */
 
 static void
-pci_hdrtypedata(pcicfgregs *cfg)
+pci_hdrtypedata(device_t pcib, int b, int s, int f, pcicfgregs *cfg)
 {
+#define REG(n,w)	PCIB_READ_CONFIG(pcib, b, s, f, n, w)
 	switch (cfg->hdrtype) {
 	case 0:
-		cfg->subvendor      = pci_cfgread(cfg, PCIR_SUBVEND_0, 2);
-		cfg->subdevice      = pci_cfgread(cfg, PCIR_SUBDEV_0, 2);
+		cfg->subvendor      = REG(PCIR_SUBVEND_0, 2);
+		cfg->subdevice      = REG(PCIR_SUBDEV_0, 2);
 		cfg->nummaps	    = PCI_MAXMAPS_0;
 		break;
 	case 1:
-		cfg->subvendor      = pci_cfgread(cfg, PCIR_SUBVEND_1, 2);
-		cfg->subdevice      = pci_cfgread(cfg, PCIR_SUBDEV_1, 2);
-		cfg->secondarybus   = pci_cfgread(cfg, PCIR_SECBUS_1, 1);
-		cfg->subordinatebus = pci_cfgread(cfg, PCIR_SUBBUS_1, 1);
+		cfg->subvendor      = REG(PCIR_SUBVEND_1, 2);
+		cfg->subdevice      = REG(PCIR_SUBDEV_1, 2);
+		cfg->secondarybus   = REG(PCIR_SECBUS_1, 1);
+		cfg->subordinatebus = REG(PCIR_SUBBUS_1, 1);
 		cfg->nummaps	    = PCI_MAXMAPS_1;
-		cfg->hdrspec        = pci_readppb(cfg);
+		cfg->hdrspec        = pci_readppb(pcib, b, s, f);
 		break;
 	case 2:
-		cfg->subvendor      = pci_cfgread(cfg, PCIR_SUBVEND_2, 2);
-		cfg->subdevice      = pci_cfgread(cfg, PCIR_SUBDEV_2, 2);
-		cfg->secondarybus   = pci_cfgread(cfg, PCIR_SECBUS_2, 1);
-		cfg->subordinatebus = pci_cfgread(cfg, PCIR_SUBBUS_2, 1);
+		cfg->subvendor      = REG(PCIR_SUBVEND_2, 2);
+		cfg->subdevice      = REG(PCIR_SUBDEV_2, 2);
+		cfg->secondarybus   = REG(PCIR_SECBUS_2, 1);
+		cfg->subordinatebus = REG(PCIR_SUBBUS_2, 1);
 		cfg->nummaps	    = PCI_MAXMAPS_2;
-		cfg->hdrspec        = pci_readpcb(cfg);
+		cfg->hdrspec        = pci_readpcb(pcib, b, s, f);
 		break;
 	}
+#undef REG
 }
 
 /* read configuration header into pcicfgrect structure */
 
 static struct pci_devinfo *
-pci_readcfg(pcicfgregs *probe)
+pci_read_device(device_t pcib, int b, int s, int f)
 {
-#define REG(n, w)	pci_cfgread(probe, n, w)
+#define REG(n, w)	PCIB_READ_CONFIG(pcib, b, s, f, n, w)
 
 	pcicfgregs *cfg = NULL;
 	struct pci_devinfo *devlist_entry;
@@ -331,33 +340,31 @@
 
 	devlist_entry = NULL;
 
-	if (pci_cfgread(probe, PCIR_DEVVENDOR, 4) != -1) {
+	if (PCIB_READ_CONFIG(pcib, b, s, f, PCIR_DEVVENDOR, 4) != -1) {
 
 		devlist_entry = malloc(sizeof(struct pci_devinfo),
-				       M_DEVBUF, M_WAITOK);
+				       M_DEVBUF, M_WAITOK | M_ZERO);
 		if (devlist_entry == NULL)
 			return (NULL);
-		bzero(devlist_entry, sizeof *devlist_entry);
 
 		cfg = &devlist_entry->cfg;
 		
-		cfg->hose               = probe->hose;
-		cfg->bus		= probe->bus;
-		cfg->slot		= probe->slot;
-		cfg->func		= probe->func;
-		cfg->vendor		= pci_cfgread(cfg, PCIR_VENDOR, 2);
-		cfg->device		= pci_cfgread(cfg, PCIR_DEVICE, 2);
-		cfg->cmdreg		= pci_cfgread(cfg, PCIR_COMMAND, 2);
-		cfg->statreg		= pci_cfgread(cfg, PCIR_STATUS, 2);
-		cfg->baseclass		= pci_cfgread(cfg, PCIR_CLASS, 1);
-		cfg->subclass		= pci_cfgread(cfg, PCIR_SUBCLASS, 1);
-		cfg->progif		= pci_cfgread(cfg, PCIR_PROGIF, 1);
-		cfg->revid		= pci_cfgread(cfg, PCIR_REVID, 1);
-		cfg->hdrtype		= pci_cfgread(cfg, PCIR_HEADERTYPE, 1);
-		cfg->cachelnsz		= pci_cfgread(cfg, PCIR_CACHELNSZ, 1);
-		cfg->lattimer		= pci_cfgread(cfg, PCIR_LATTIMER, 1);
-		cfg->intpin		= pci_cfgread(cfg, PCIR_INTPIN, 1);
-		cfg->intline		= pci_cfgread(cfg, PCIR_INTLINE, 1);
+		cfg->bus		= b;
+		cfg->slot		= s;
+		cfg->func		= f;
+		cfg->vendor		= REG(PCIR_VENDOR, 2);
+		cfg->device		= REG(PCIR_DEVICE, 2);
+		cfg->cmdreg		= REG(PCIR_COMMAND, 2);
+		cfg->statreg		= REG(PCIR_STATUS, 2);
+		cfg->baseclass		= REG(PCIR_CLASS, 1);
+		cfg->subclass		= REG(PCIR_SUBCLASS, 1);
+		cfg->progif		= REG(PCIR_PROGIF, 1);
+		cfg->revid		= REG(PCIR_REVID, 1);
+		cfg->hdrtype		= REG(PCIR_HEADERTYPE, 1);
+		cfg->cachelnsz		= REG(PCIR_CACHELNSZ, 1);
+		cfg->lattimer		= REG(PCIR_LATTIMER, 1);
+		cfg->intpin		= REG(PCIR_INTPIN, 1);
+		cfg->intline		= REG(PCIR_INTLINE, 1);
 #ifdef __alpha__
 		alpha_platform_assign_pciintr(cfg);
 #endif
@@ -390,17 +397,17 @@
 		}
 #endif /* APIC_IO */
 
-		cfg->mingnt		= pci_cfgread(cfg, PCIR_MINGNT, 1);
-		cfg->maxlat		= pci_cfgread(cfg, PCIR_MAXLAT, 1);
+		cfg->mingnt		= REG(PCIR_MINGNT, 1);
+		cfg->maxlat		= REG(PCIR_MAXLAT, 1);
 
 		cfg->mfdev		= (cfg->hdrtype & PCIM_MFDEV) != 0;
 		cfg->hdrtype		&= ~PCIM_MFDEV;
 
 		pci_fixancient(cfg);
-		pci_hdrtypedata(cfg);
+		pci_hdrtypedata(pcib, b, s, f, cfg);
 
 		if (REG(PCIR_STATUS, 2) & PCIM_STATUS_CAPPRESENT)
-			pci_read_extcap(cfg);
+			pci_read_extcap(pcib, cfg);
 
 		STAILQ_INSERT_TAIL(devlist_head, devlist_entry, pci_links);
 
@@ -427,9 +434,9 @@
 }
 
 static void
-pci_read_extcap(pcicfgregs *cfg)
+pci_read_extcap(device_t pcib, pcicfgregs *cfg)
 {
-#define REG(n, w)	pci_cfgread(cfg, n, w)
+#define REG(n, w)	PCIB_READ_CONFIG(pcib, cfg->bus, cfg->slot, cfg->func, n, w)
 	int	ptr, nextptr, ptrptr;
 
 	switch (cfg->hdrtype) {
@@ -781,6 +788,7 @@
 static int
 pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
 {
+	device_t pci, pcib;
 	struct pci_io *io;
 	const char *name;
 	int error;
@@ -1022,17 +1030,30 @@
 	case PCIOCREAD:
 		io = (struct pci_io *)data;
 		switch(io->pi_width) {
-			pcicfgregs probe;
 		case 4:
 		case 2:
 		case 1:
-			probe.hose = -1;
-			probe.bus = io->pi_sel.pc_bus;
-			probe.slot = io->pi_sel.pc_dev;
-			probe.func = io->pi_sel.pc_func;
-			io->pi_data = pci_cfgread(&probe, 
-						  io->pi_reg, io->pi_width);
-			error = 0;
+			/*
+			 * Assume that the user-level bus number is
+			 * actually the pciN instance number. We map
+			 * from that to the real pcib+bus combination.
+			 */
+			pci = devclass_get_device(pci_devclass,
+						  io->pi_sel.pc_bus);
+			if (pci) {
+				int b = pcib_get_bus(pci);
+				pcib = device_get_parent(pci);
+				io->pi_data = 
+					PCIB_READ_CONFIG(pcib,
+							 b,
+							 io->pi_sel.pc_dev,
+							 io->pi_sel.pc_func,
+							 io->pi_reg,
+							 io->pi_width);
+				error = 0;
+			} else {
+				error = ENODEV;
+			}
 			break;
 		default:
 			error = ENODEV;
@@ -1043,17 +1064,30 @@
 	case PCIOCWRITE:
 		io = (struct pci_io *)data;
 		switch(io->pi_width) {
-			pcicfgregs probe;
 		case 4:
 		case 2:
 		case 1:
-			probe.hose = -1; 
-			probe.bus = io->pi_sel.pc_bus;
-			probe.slot = io->pi_sel.pc_dev;
-			probe.func = io->pi_sel.pc_func;
-			pci_cfgwrite(&probe, 
-				    io->pi_reg, io->pi_data, io->pi_width);
-			error = 0;
+			/*
+			 * Assume that the user-level bus number is
+			 * actually the pciN instance number. We map
+			 * from that to the real pcib+bus combination.
+			 */
+			pci = devclass_get_device(pci_devclass,
+						  io->pi_sel.pc_bus);
+			if (pci) {
+				int b = pcib_get_bus(pci);
+				pcib = device_get_parent(pci);
+				PCIB_WRITE_CONFIG(pcib,
+						  b,
+						  io->pi_sel.pc_dev,
+						  io->pi_sel.pc_func,
+						  io->pi_reg,
+						  io->pi_data,
+						  io->pi_width);
+				error = 0;
+			} else {
+				error = ENODEV;
+			}
 			break;
 		default:
 			error = ENODEV;
@@ -1105,6 +1139,8 @@
 
 		printf("found->\tvendor=0x%04x, dev=0x%04x, revid=0x%02x\n", 
 		       cfg->vendor, cfg->device, cfg->revid);
+		printf("\tbus=%d, slot=%d, func=%d\n",
+		       cfg->bus, cfg->slot, cfg->func);
 		printf("\tclass=%02x-%02x-%02x, hdrtype=0x%02x, mfdev=%d\n",
 		       cfg->baseclass, cfg->subclass, cfg->progif,
 		       cfg->hdrtype, cfg->mfdev);
@@ -1123,15 +1159,17 @@
 }
 
 static int
-pci_porten(pcicfgregs *cfg)
+pci_porten(device_t pcib, int b, int s, int f)
 {
-	return ((cfg->cmdreg & PCIM_CMD_PORTEN) != 0);
+	return (PCIB_READ_CONFIG(pcib, b, s, f, PCIR_COMMAND, 2)
+		& PCIM_CMD_PORTEN) != 0;
 }
 
 static int
-pci_memen(pcicfgregs *cfg)
+pci_memen(device_t pcib, int b, int s, int f)
 {
-	return ((cfg->cmdreg & PCIM_CMD_MEMEN) != 0);
+	return (PCIB_READ_CONFIG(pcib, b, s, f, PCIR_COMMAND, 2)
+		& PCIM_CMD_MEMEN) != 0;
 }
 
 /*
@@ -1139,26 +1177,28 @@
  * register is a 32bit map register or 2 if it is a 64bit register.
  */
 static int
-pci_add_map(device_t dev, pcicfgregs* cfg, int reg)
+pci_add_map(device_t pcib, int b, int s, int f, int reg,
+	    struct resource_list *rl)
 {
-	struct pci_devinfo *dinfo = device_get_ivars(dev);
-	struct resource_list *rl = &dinfo->resources;
 	u_int32_t map;
 	u_int64_t base;
 	u_int8_t ln2size;
 	u_int8_t ln2range;
 	u_int32_t testval;
-		
+
+#ifdef PCI_ENABLE_IO_MODES
+	u_int16_t cmd;
+#endif		
 	int type;
 
-	map = pci_cfgread(cfg, reg, 4);
+	map = PCIB_READ_CONFIG(pcib, b, s, f, reg, 4);
 
 	if (map == 0 || map == 0xffffffff)
 		return 1; /* skip invalid entry */
 
-	pci_cfgwrite(cfg, reg, 0xffffffff, 4);
-	testval = pci_cfgread(cfg, reg, 4);
-	pci_cfgwrite(cfg, reg, map, 4);
+	PCIB_WRITE_CONFIG(pcib, b, s, f, reg, 0xffffffff, 4);
+	testval = PCIB_READ_CONFIG(pcib, b, s, f, reg, 4);
+	PCIB_WRITE_CONFIG(pcib, b, s, f, reg, map, 4);
 
 	base = pci_mapbase(map);
 	if (pci_maptype(map) & PCI_MAPMEM)
@@ -1169,59 +1209,8 @@
 	ln2range = pci_maprange(testval);
 	if (ln2range == 64) {
 		/* Read the other half of a 64bit map register */
-		base |= (u_int64_t) pci_cfgread(cfg, reg + 4, 4) << 32;
+		base |= (u_int64_t) PCIB_READ_CONFIG(pcib, b, s, f, reg+4, 4);
 	}
-
-#ifdef __alpha__
-	/* 
-	 *  XXX: encode hose number in the base addr,
-	 *  This will go away once the bus_space functions
-	 *  can deal with multiple hoses 
-	 */
-
-	if (cfg->hose) {
-		u_int32_t mask, shift, maxh;
-
-		switch (hwrpb->rpb_type) {
-		case ST_DEC_4100:
-		case -ST_DEC_4100:
-			mask = 0xc0000000;
-			shift = 30;
-			maxh = 4;	/* not a hose. MCPCIA instance # */
-			break;
-		case ST_DEC_21000:
-			mask = 0xf8000000;
-			shift = 27;
-			maxh = 32;
-			break;
-		case ST_DEC_6600:
-			mask = 0x80000000;
-			shift = 31;
-			maxh = 2;
-			break;
-		default:
-			mask = 0;
-			shift = 0;
-			maxh = 0;
-			break;
-		}
-		if (base & mask) {
-			printf("base   addr = 0x%llx\n", (long long) base);
-			printf("mask   addr = 0x%lx\n", (long) mask);
-			printf("hacked addr = 0x%llx\n", (long long)
-			       (base | ((u_int64_t)cfg->hose << shift)));
-			panic("hose encoding hack would clobber base addr");
-			/* NOTREACHED */
-		}
-		if (cfg->hose >= maxh) {
-			panic("Hose %d - can only encode %d hose(s)",
-			    cfg->hose, maxh);
-			/* NOTREACHED */
-		}
-		base |= ((u_int64_t)cfg->hose << shift);
-	}
-#endif
-
 	/*
 	 * This code theoretically does the right thing, but has
 	 * undesirable side effects in some cases where
@@ -1229,18 +1218,20 @@
 	 * enabled.  Leave them alone by default.
 	 */
 #ifdef PCI_ENABLE_IO_MODES
-	if (type == SYS_RES_IOPORT && !pci_porten(cfg)) {
-		cfg->cmdreg |= PCIM_CMD_PORTEN;
-		pci_cfgwrite(cfg, PCIR_COMMAND, cfg->cmdreg, 2);
-	}
-	if (type == SYS_RES_MEMORY && !pci_memen(cfg)) {
-		cfg->cmdreg |= PCIM_CMD_MEMEN;
-		pci_cfgwrite(cfg, PCIR_COMMAND, cfg->cmdreg, 2);
+	if (type == SYS_RES_IOPORT && !pci_porten(pcib, b, s, f)) {
+		cmd = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_COMMAND, 2);
+		cmd |= PCIM_CMD_PORTEN;
+		PCIB_WRITE_CONFIG(pcib, b, s, f, PCIR_COMMAND, cmd, 2);
+	}
+	if (type == SYS_RES_MEMORY && !pci_memen(pcib, b, s, f)) {
+		cmd = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_COMMAND, 2);
+		cmd |= PCIM_CMD_MEMEN;
+		PCIB_WRITE_CONFIG(pcib, b, s, f, PCIR_COMMAND, cmd, 2);
 	}
 #else
-        if (type == SYS_RES_IOPORT && !pci_porten(cfg))
+        if (type == SYS_RES_IOPORT && !pci_porten(pcib, b, s, f))
                 return 1;
-        if (type == SYS_RES_MEMORY && !pci_memen(cfg))
+        if (type == SYS_RES_MEMORY && !pci_memen(pcib, b, s, f))
 		return 1;
 #endif
 
@@ -1258,21 +1249,22 @@
 }
 
 static void
-pci_add_resources(device_t dev, pcicfgregs* cfg)
+pci_add_resources(device_t pcib, int b, int s, int f, device_t dev)
 {
 	struct pci_devinfo *dinfo = device_get_ivars(dev);
+	pcicfgregs *cfg = &dinfo->cfg;
 	struct resource_list *rl = &dinfo->resources;
 	struct pci_quirk *q;
 	int i;
 
 	for (i = 0; i < cfg->nummaps;) {
-		i += pci_add_map(dev, cfg, PCIR_MAPS + i*4);
+		i += pci_add_map(pcib, b, s, f, PCIR_MAPS + i*4, rl);
 	}
 
 	for (q = &pci_quirks[0]; q->devid; q++) {
 		if (q->devid == ((cfg->device << 16) | cfg->vendor)
 		    && q->type == PCI_QUIRK_MAP_REG)
-			pci_add_map(dev, cfg, q->arg1);
+			pci_add_map(pcib, b, s, f, q->arg1, rl);
 	}
 
 	if (cfg->intpin > 0 && cfg->intline != 255)
@@ -1283,26 +1275,17 @@
 static void
 pci_add_children(device_t dev, int busno)
 {
-	pcicfgregs probe;
-
-#ifdef SIMOS
-#undef PCI_SLOTMAX
-#define PCI_SLOTMAX 0
-#endif
+	device_t pcib = device_get_parent(dev);
+	int maxslots;
+	int s, f;
 
-	bzero(&probe, sizeof probe);
-#ifdef __alpha__
-	probe.hose = pcib_get_hose(dev);
-#endif
-#ifdef __i386__
-	probe.hose = 0;
-#endif
-	probe.bus = busno;
+	maxslots = PCIB_MAXSLOTS(pcib);
 
-	for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) {
+	for (s = 0; s <= maxslots; s++) {
 		int pcifunchigh = 0;
-		for (probe.func = 0; probe.func <= pcifunchigh; probe.func++) {
-			struct pci_devinfo *dinfo = pci_readcfg(&probe);
+		for (f = 0; f <= pcifunchigh; f++) {
+			struct pci_devinfo *dinfo = 
+				pci_read_device(pcib, busno, s, f);
 			if (dinfo != NULL) {
 				if (dinfo->cfg.mfdev)
 					pcifunchigh = 7;
@@ -1310,19 +1293,34 @@
 				pci_print_verbose(dinfo);
 				dinfo->cfg.dev = device_add_child(dev, NULL, -1);
 				device_set_ivars(dinfo->cfg.dev, dinfo);
-				pci_add_resources(dinfo->cfg.dev, &dinfo->cfg);
+				pci_add_resources(pcib, busno, s, f,
+						  dinfo->cfg.dev);
 			}
 		}
 	}
 }
 
 static int
-pci_new_probe(device_t dev)
+pci_probe(device_t dev)
 {
-	static int once;
+	static int once, busno;
 
 	device_set_desc(dev, "PCI bus");
-	pci_add_children(dev, device_get_unit(dev));
+
+	if (bootverbose)
+		device_printf(dev, "physical bus=%d\n", pcib_get_bus(dev));
+
+	/*
+	 * Since there can be multiple independently numbered PCI
+	 * busses on some large alpha systems, we can't use the unit
+	 * number to decide what bus we are probing. We ask the parent
+	 * pcib what our bus number is.
+	 */
+	busno = pcib_get_bus(dev);
+	if (busno < 0)
+		return ENXIO;
+	pci_add_children(dev, busno);
+
 	if (!once) {
 		make_dev(&pcicdev, 0, UID_ROOT, GID_WHEEL, 0644, "pci");
 		once++;
@@ -1401,6 +1399,7 @@
 	desc = pci_ata_match(child);
 	if (!desc) desc = pci_usb_match(child);
 	if (!desc) desc = pci_vga_match(child);
+	if (!desc) desc = pci_chip_match(child);
 	if (!desc) {
 		desc = "unknown card";
 		unknown++;
@@ -1423,7 +1422,7 @@
 }
 
 static int
-pci_read_ivar(device_t dev, device_t child, int which, u_long *result)
+pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
 {
 	struct pci_devinfo *dinfo;
 	pcicfgregs *cfg;
@@ -1480,12 +1479,6 @@
 	case PCI_IVAR_SUBORDINATEBUS:
 		*result = cfg->subordinatebus;
 		break;
-	case PCI_IVAR_HOSE:
-		/*
-		 * Pass up to parent bridge.
-		 */
-		*result = pcib_get_hose(dev);
-		break;
 	default:
 		return ENOENT;
 	}
@@ -1536,8 +1529,8 @@
 {
 	struct pci_devinfo *dinfo = device_get_ivars(child);
 	struct resource_list *rl = &dinfo->resources;
-
-#ifdef __i386__		/* Only supported on x86 in stable */
+	
+#ifdef __i386__
 	pcicfgregs *cfg = &dinfo->cfg;
 	/*
 	 * Perform lazy resource allocation
@@ -1552,8 +1545,9 @@
 		if ((type == SYS_RES_IRQ) &&
 		    (cfg->intline == 255 || cfg->intline == 0) &&
 		    (cfg->intpin != 0) && (start == 0) && (end == ~0UL)) {
-			cfg->intline = pci_cfgintr(pci_get_bus(child),
-			    pci_get_slot(child), cfg->intpin);
+			cfg->intline = PCIB_ROUTE_INTERRUPT(
+				device_get_parent(dev), pci_get_slot(child),
+				cfg->intpin);
 			if (cfg->intline != 255) {
 				pci_write_config(child, PCIR_INTLINE,
 				    cfg->intline, 1);
@@ -1619,7 +1613,10 @@
 {
 	struct pci_devinfo *dinfo = device_get_ivars(child);
 	pcicfgregs *cfg = &dinfo->cfg;
-	return pci_cfgread(cfg, reg, width);
+
+	return PCIB_READ_CONFIG(device_get_parent(dev),
+				cfg->bus, cfg->slot, cfg->func,
+				reg, width);
 }
 
 static void
@@ -1628,7 +1625,10 @@
 {
 	struct pci_devinfo *dinfo = device_get_ivars(child);
 	pcicfgregs *cfg = &dinfo->cfg;
-	pci_cfgwrite(cfg, reg, val, width);
+
+	return PCIB_WRITE_CONFIG(device_get_parent(dev),
+				 cfg->bus, cfg->slot, cfg->func,
+				 reg, val, width);
 }
 
 static int
@@ -1648,7 +1648,7 @@
 
 static device_method_t pci_methods[] = {
 	/* Device interface */
-	DEVMETHOD(device_probe,		pci_new_probe),
+	DEVMETHOD(device_probe,		pci_probe),
 	DEVMETHOD(device_attach,	bus_generic_attach),
 	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
 	DEVMETHOD(device_suspend,	bus_generic_suspend),
diff -uNr sys.old/bus/pci/pci_compat.c sys/bus/pci/pci_compat.c
--- sys.old/bus/pci/pci_compat.c	Sat Dec 20 16:56:09 2003
+++ sys/bus/pci/pci_compat.c	Sat Dec 20 17:08:07 2003
@@ -69,6 +69,18 @@
 }
 
 int
+pci_cfgread (pcicfgregs *cfg, int reg, int bytes)
+{
+	return (pci_read_config(cfg->dev, reg, bytes));
+}
+
+void
+pci_cfgwrite (pcicfgregs *cfg, int reg, int data, int bytes)
+{
+	pci_write_config(cfg->dev, reg, data, bytes);
+}
+
+int
 pci_map_port(pcici_t cfg, u_long reg, pci_port_t* pa)
 {
 	int rid;
diff -uNr sys.old/bus/pci/pcib_if.m sys/bus/pci/pcib_if.m
--- sys.old/bus/pci/pcib_if.m	Thu Jan  1 00:00:00 1970
+++ sys/bus/pci/pcib_if.m	Sat Dec 20 17:08:07 2003
@@ -0,0 +1,82 @@
+#
+# Copyright (c) 2000 Doug Rabson
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: src/sys/pci/pcib_if.m,v 1.2 2000/10/16 19:43:44 imp Exp $
+# $DragonFly$
+#
+
+#include <sys/bus.h>
+
+INTERFACE pcib;
+
+#
+# Return the number of slots on the attached PCI bus.
+#
+METHOD int maxslots {
+	device_t	dev;
+};
+
+#
+# Read configuration space on the PCI bus. The bus, slot and func
+# arguments determine the device which is being read and the reg
+# argument is a byte offset into configuration space for that
+# device. The width argument (which should be 1, 2 or 4) specifies how
+# many byte of configuration space to read from that offset.
+#
+METHOD u_int32_t read_config {
+	device_t	dev;
+	int		bus;
+	int		slot;
+	int		func;
+	int		reg;
+	int		width;
+};
+
+#
+# Write configuration space on the PCI bus. The bus, slot and func
+# arguments determine the device which is being written and the reg
+# argument is a byte offset into configuration space for that
+# device. The value field is written to the configuration space, with
+# the number of bytes written depending on the width argument.
+#
+METHOD void write_config {
+	device_t	dev;
+	int		bus;
+	int		slot;
+	int		func;
+	int		reg;
+	u_int32_t	value;
+	int		width;
+};
+
+#
+# Route an interrupt.  Returns a value suitable for stuffing into 
+# a device's interrupt register.
+#
+METHOD int route_interrupt {
+	device_t bus;
+	device_t device;
+	int pin;
+};
diff -uNr sys.old/bus/pci/pcisupport.c sys/bus/pci/pcisupport.c
--- sys.old/bus/pci/pcisupport.c	Fri Oct 31 22:00:13 2003
+++ sys/bus/pci/pcisupport.c	Sat Dec 20 17:08:07 2003
@@ -58,6 +58,8 @@
 #include <vm/vm_object.h>
 #include <vm/pmap.h>
 
+#include "pcib_if.h"
+
 /*---------------------------------------------------------
 **
 **	Intel chipsets for 486 / Pentium processor
@@ -768,7 +770,7 @@
 	desc = pcib_match(dev);
 	if (desc) {
 		device_set_desc_copy(dev, desc);
-		return 0;
+		return -1000;
 	}
 
 	return ENXIO;
@@ -777,30 +779,71 @@
 static int pcib_attach(device_t dev)
 {
 	u_int8_t secondary;
+	device_t child;
 
 	chipset_attach(dev, device_get_unit(dev));
 
 	secondary = pci_get_secondarybus(dev);
 	if (secondary) {
-		device_add_child(dev, "pci", secondary);
+		child = device_add_child(dev, "pci", -1);
+		*(int*) device_get_softc(dev) = secondary;
 		return bus_generic_attach(dev);
 	} else
 		return 0;
 }
 
 static int
-pcib_read_ivar(device_t dev, device_t child, int which, u_long *result)
+pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
 {
-	if (which == PCIB_IVAR_HOSE) {
-		/*
-		 * Pass up to parent bus.
-		 */
-		*result = pci_get_hose(dev);
+	switch (which) {
+	case PCIB_IVAR_BUS:
+		*result = *(int*) device_get_softc(dev);
 		return(0);
 	}
 	return ENOENT;
 }
 
+static int
+pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
+{
+	switch (which) {
+	case PCIB_IVAR_BUS:
+		*(int*) device_get_softc(dev) = value;
+		return (0);
+	}
+	return ENOENT;
+}
+
+static int
+pcib_maxslots(device_t dev)
+{
+	return 31;
+}
+
+static u_int32_t
+pcib_read_config(device_t dev, int b, int s, int f,
+		 int reg, int width)
+{
+	/*
+	 * Pass through to the next ppb up the chain (i.e. our
+	 * grandparent).
+	 */
+	return PCIB_READ_CONFIG(device_get_parent(device_get_parent(dev)),
+				b, s, f, reg, width);
+}
+
+static void
+pcib_write_config(device_t dev, int b, int s, int f,
+		  int reg, int val, int width)
+{
+	/*
+	 * Pass through to the next ppb up the chain (i.e. our
+	 * grandparent).
+	 */
+	PCIB_WRITE_CONFIG(device_get_parent(device_get_parent(dev)),
+				b, s, f, reg, val, width);	
+}
+
 /*
  * Route an interrupt across a PCI bridge.
  */
@@ -849,6 +892,7 @@
 	/* Bus interface */
 	DEVMETHOD(bus_print_child,	bus_generic_print_child),
 	DEVMETHOD(bus_read_ivar,	pcib_read_ivar),
+	DEVMETHOD(bus_write_ivar,	pcib_write_ivar),
 	DEVMETHOD(bus_alloc_resource,	bus_generic_alloc_resource),
 	DEVMETHOD(bus_release_resource,	bus_generic_release_resource),
 	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
@@ -858,13 +902,19 @@
 
 	/* pci interface */
 	DEVMETHOD(pci_route_interrupt,	pcib_route_interrupt),
+
+	/* pcib interface */
+	DEVMETHOD(pcib_maxslots,	pcib_maxslots),
+	DEVMETHOD(pcib_read_config,	pcib_read_config),
+	DEVMETHOD(pcib_write_config,	pcib_write_config),
+
 	{ 0, 0 }
 };
 
 static driver_t pcib_driver = {
 	"pcib",
 	pcib_methods,
-	1,
+	sizeof(int),
 };
 
 static devclass_t pcib_devclass;
@@ -1166,8 +1216,8 @@
 }
 
 
-static const char*
-chip_match(device_t dev)
+const char*
+pci_chip_match(device_t dev)
 {
 	unsigned	rev;
 
@@ -1369,53 +1419,6 @@
 	return NULL;
 }
 
-static int chip_probe(device_t dev)
-{
-	const char *desc;
-
-	desc = chip_match(dev);
-	if (desc) {
-		if (pci_get_class(dev) == PCIC_BRIDGE
-		    && pci_get_subclass(dev) == PCIS_BRIDGE_HOST) {
-			/*
-			 * Suppress printing this device since the nexus
-			 * has already described it.
-			 */
-			device_quiet(dev);
-		}
-
-		device_set_desc_copy(dev, desc);
-		return -10000;	/* Low match priority */
-	}
-
-	return ENXIO;
-}
-
-static int chip_attach(device_t dev)
-{
-	chipset_attach(dev, device_get_unit(dev));
-
-	return 0;
-}
-
-static device_method_t chip_methods[] = {
-	/* Device interface */
-	DEVMETHOD(device_probe,		chip_probe),
-	DEVMETHOD(device_attach,	chip_attach),
-
-	{ 0, 0 }
-};
-
-static driver_t chip_driver = {
-	"chip",
-	chip_methods,
-	1,
-};
-
-static devclass_t chip_devclass;
-
-DRIVER_MODULE(chip, pci, chip_driver, chip_devclass, 0, 0);
-
 /*---------------------------------------------------------
 **
 **	Catchall driver for VGA devices
@@ -1932,20 +1935,34 @@
 **---------------------------------------------------------
 */
 
-static int
-ign_probe (device_t dev)
+static const char*
+ign_match(device_t dev)
 {
 	switch (pci_get_devid(dev)) {
 
 	case 0x10001042ul:	/* wd */
-		return 0;
-/*		return ("SMC FDC 37c665");*/
+		return ("SMC FDC 37c665");
 	};
+
+	return NULL;
+}
+
+static int
+ign_probe(device_t dev)
+{
+	const char *s;
+	
+	s = ign_match(dev);
+	if (s) {
+		device_set_desc(dev, s);
+		device_quiet(dev);
+		return -1000;
+	}
 	return ENXIO;
 }
 
 static int
-ign_attach (device_t dev)
+ign_attach(device_t dev)
 {
 	return 0;
 }
diff -uNr sys.old/bus/pci/pcivar.h sys/bus/pci/pcivar.h
--- sys.old/bus/pci/pcivar.h	Sat Dec 20 16:56:09 2003
+++ sys/bus/pci/pcivar.h	Sat Dec 20 17:08:07 2003
@@ -24,6 +24,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/pci/pcivar.h,v 1.41.2.2 2002/01/10 12:08:22 mdodd Exp $
+ * merged in revision 1.48
  * $DragonFly: src/sys/bus/pci/pcivar.h,v 1.2 2003/06/17 04:28:57 dillon Exp $
  *
  */
@@ -83,7 +84,6 @@
     u_int8_t	mfdev;		/* multi-function device (from hdrtype reg) */
     u_int8_t	nummaps;	/* actual number of PCI maps used */
 
-    u_int8_t    hose;           /* hose which bus is attached to */
     u_int8_t	bus;		/* config space bus address */
     u_int8_t	slot;		/* config space slot address */
     u_int8_t	func;		/* config space function number */
@@ -156,6 +156,7 @@
 const char *pci_ata_match(struct device *dev);
 const char *pci_usb_match(struct device *dev);
 const char *pci_vga_match(struct device *dev);
+const char *pci_chip_match(struct device *dev);
 
 /* low level PCI config register functions provided by pcibus.c */
 
@@ -197,7 +198,6 @@
 	PCI_IVAR_FUNCTION,
 	PCI_IVAR_SECONDARYBUS,
 	PCI_IVAR_SUBORDINATEBUS,
-	PCI_IVAR_HOSE,
 };
 
@@ -214,7 +214,7 @@
 									\
 static __inline void pci_set_ ## A(device_t dev, T t)			\
 {									\
-	u_long v = (u_long) t;						\
+	uintptr_t v = (uintptr_t) t;						\
 	BUS_WRITE_IVAR(device_get_parent(dev), dev, PCI_IVAR_ ## B, v);	\
 }
 
@@ -234,7 +234,8 @@
 PCI_ACCESSOR(function,		FUNCTION,	u_int8_t)
 PCI_ACCESSOR(secondarybus,	SECONDARYBUS,	u_int8_t)
 PCI_ACCESSOR(subordinatebus,	SUBORDINATEBUS,	u_int8_t)
-PCI_ACCESSOR(hose,		HOSE,		u_int32_t)
+
+#undef PCI_ACCESSOR
 
 static __inline u_int32_t
 pci_read_config(device_t dev, int reg, int width)
@@ -317,7 +318,7 @@
 
 /*typedef enum pci_device_ivars pcib_device_ivars;*/
 enum pcib_device_ivars {
-	PCIB_IVAR_HOSE,
+	PCIB_IVAR_BUS,
 };
 
 #define PCIB_ACCESSOR(A, B, T)						 \
@@ -331,11 +332,13 @@
 									 \
 static __inline void pcib_set_ ## A(device_t dev, T t)			 \
 {									 \
-	u_long v = (u_long) t;						 \
+	uintptr_t v = (uintptr_t) t;						 \
 	BUS_WRITE_IVAR(device_get_parent(dev), dev, PCIB_IVAR_ ## B, v); \
 }
 
-PCIB_ACCESSOR(hose,		HOSE,		u_int32_t)
+PCIB_ACCESSOR(bus,		BUS,		u_int32_t)
+
+#undef PCIB_ACCESSOR
 
 device_t pci_find_bsf(u_int8_t, u_int8_t, u_int8_t);
 device_t pci_find_device(u_int16_t, u_int16_t);
diff -uNr sys.old/conf/files sys/conf/files
--- sys.old/conf/files	Sat Dec 20 16:56:09 2003
+++ sys/conf/files	Sat Dec 20 17:08:07 2003
@@ -1106,6 +1106,7 @@
 	warning	"Old PCI driver compatability shims present."
 bus/pci/pcisupport.c		optional pci
 bus/pci/pci_if.m		optional pci
+bus/pci/pcib_if.m		optional pci
 dev/disk/simos/simos.c		optional simos
 dev/powermng/i386/alpm/alpm.c	optional alpm
 dev/misc/xrpu/xrpu.c		optional xrpu
diff -uNr sys.old/conf/files.i386 sys/conf/files.i386
--- sys.old/conf/files.i386	Sun Dec  7 19:23:36 2003
+++ sys/conf/files.i386	Sat Dec 20 17:08:07 2003
@@ -273,7 +273,7 @@
 dev/sound/isa/i386/pca/pcaudio.c	optional	pca
 bus/iicbus/i386/pcf.c			optional	pcf
 bus/pci/i386/pci_cfgreg.c		optional	pci
-bus/pci/i386/pcibus.c			optional	pci
+bus/pci/i386/pci_bus.c			optional	pci
 dev/video/pcvt/i386/pcvt_drv.c		optional	vt
 dev/video/pcvt/i386/pcvt_ext.c		optional	vt
 dev/video/pcvt/i386/pcvt_kbd.c		optional	vt
diff -uNr sys.old/i386/i386/nexus.c sys/i386/i386/nexus.c
--- sys.old/i386/i386/nexus.c	Thu Aug  7 21:17:22 2003
+++ sys/i386/i386/nexus.c	Sat Dec 20 17:08:07 2003
@@ -27,6 +27,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/i386/nexus.c,v 1.26.2.10 2003/02/22 13:16:45 imp Exp $
+ * Mostly updated to 1.37
  * $DragonFly: src/sys/i386/i386/nexus.c,v 1.3 2003/08/07 21:17:22 dillon Exp $
  */
 
@@ -57,12 +58,14 @@
 #include <vm/pmap.h>
 #include <machine/pmap.h>
 
+#include <machine/nexusvar.h>
 #include <machine/resource.h>
 #ifdef APIC_IO
 #include <machine/smp.h>
 #include <machine/mpapic.h>
 #endif
 
+#include <bus/isa/isavar.h>
 #ifdef PC98
 #include <pc98/pc98/pc98.h>
 #else
@@ -73,6 +76,7 @@
 static MALLOC_DEFINE(M_NEXUSDEV, "nexusdev", "Nexus device");
 struct nexus_device {
 	struct resource_list	nx_resources;
+	int			nx_pcibus;
 };
 
 #define DEVTONX(dev)	((struct nexus_device *)device_get_ivars(dev))
@@ -87,6 +91,8 @@
 				int unit);
 static	struct resource *nexus_alloc_resource(device_t, device_t, int, int *,
 					      u_long, u_long, u_long, u_int);
+static	int nexus_read_ivar(device_t, device_t, int, uintptr_t *);
+static	int nexus_write_ivar(device_t, device_t, int, uintptr_t);
 static	int nexus_activate_resource(device_t, device_t, int, int,
 				    struct resource *);
 static	int nexus_deactivate_resource(device_t, device_t, int, int,
@@ -113,8 +119,8 @@
 	/* Bus interface */
 	DEVMETHOD(bus_print_child,	nexus_print_child),
 	DEVMETHOD(bus_add_child,	nexus_add_child),
-	DEVMETHOD(bus_read_ivar,	bus_generic_read_ivar),
-	DEVMETHOD(bus_write_ivar,	bus_generic_write_ivar),
+	DEVMETHOD(bus_read_ivar,	nexus_read_ivar),
+	DEVMETHOD(bus_write_ivar,	nexus_write_ivar),
 	DEVMETHOD(bus_alloc_resource,	nexus_alloc_resource),
 	DEVMETHOD(bus_release_resource,	nexus_release_resource),
 	DEVMETHOD(bus_activate_resource, nexus_activate_resource),
@@ -144,36 +150,39 @@
 	device_quiet(dev);	/* suppress attach message for neatness */
 
 	/*
+	 * XXX working notes:
+	 *
+	 * - IRQ resource creation should be moved to the PIC/APIC driver.
+	 * - DRQ resource creation should be moved to the DMAC driver.
+	 * - The above should be sorted to probe earlier than any child busses.
+	 *
+	 * - Leave I/O and memory creation here, as child probes may need them.
+	 *   (especially e.g. ACPI)
+	 */
+
+
+	/*
 	 * IRQ's are on the mainboard on old systems, but on the ISA part
 	 * of PCI->ISA bridges.  There would be multiple sets of IRQs on
 	 * multi-ISA-bus systems.  PCI interrupts are routed to the ISA
 	 * component, so in a way, PCI can be a partial child of an ISA bus(!).
 	 * APIC interrupts are global though.
-	 * In the non-APIC case, disallow the use of IRQ 2.
+	 *
+	 * XXX We depend on the AT PIC driver correctly claiming IRQ 2
+	 *     to prevent its reuse elsewhere in the !APIC_IO case.
 	 */
 	irq_rman.rm_start = 0;
 	irq_rman.rm_type = RMAN_ARRAY;
 	irq_rman.rm_descr = "Interrupt request lines";
 #ifdef APIC_IO
 	irq_rman.rm_end = APIC_INTMAPSIZE - 1;
-	if (rman_init(&irq_rman)
-	    || rman_manage_region(&irq_rman,
-				  irq_rman.rm_start, irq_rman.rm_end))
-		panic("nexus_probe irq_rman");
 #else
 	irq_rman.rm_end = 15;
-#ifdef PC98
+#endif
 	if (rman_init(&irq_rman)
 	    || rman_manage_region(&irq_rman,
 				  irq_rman.rm_start, irq_rman.rm_end))
 		panic("nexus_probe irq_rman");
-#else
-	if (rman_init(&irq_rman)
-	    || rman_manage_region(&irq_rman, irq_rman.rm_start, 1)
-	    || rman_manage_region(&irq_rman, 3, irq_rman.rm_end))
-		panic("nexus_probe irq_rman");
-#endif /* PC98 */
-#endif
 
 	/*
 	 * ISA DMA on PCI systems is implemented in the ISA part of each
@@ -262,7 +271,7 @@
 	struct resource_list *rl = &ndev->nx_resources;
 	int retval = 0;
 
-	if (SLIST_FIRST(rl))
+	if (SLIST_FIRST(rl) || ndev->nx_pcibus != -1)
 		retval += printf(" at");
 	
 	retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx");
@@ -275,10 +284,13 @@
 static int
 nexus_print_child(device_t bus, device_t child)
 {
+	struct	nexus_device *ndev = DEVTONX(child);
 	int retval = 0;
 
 	retval += bus_print_child_header(bus, child);
 	retval += nexus_print_all_resources(child);
+	if (ndev->nx_pcibus != -1)
+		retval += printf(" pcibus %d", ndev->nx_pcibus);
 	retval += printf(" on motherboard\n");
 
 	return (retval);
@@ -294,6 +306,7 @@
 	if (!ndev)
 		return(0);
 	resource_list_init(&ndev->nx_resources);
+	ndev->nx_pcibus = -1;
 
 	child = device_add_child_ordered(bus, order, name, unit); 
 
@@ -303,6 +316,36 @@
 	return(child);
 }
 
+static int
+nexus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+	struct nexus_device *ndev = DEVTONX(child);
+	
+	switch (which) {
+	case NEXUS_IVAR_PCIBUS:
+		*result = ndev->nx_pcibus;
+		break;
+	default:
+		return ENOENT;
+	}
+	return 0;
+}
+
+static int
+nexus_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
+{
+	struct nexus_device *ndev = DEVTONX(child);
+	
+	switch (which) {
+	case NEXUS_IVAR_PCIBUS:
+		ndev->nx_pcibus = value;
+		break;
+	default:
+		return ENOENT;
+	}
+	return 0;
+}
+
 /*
  * Allocate a resource on behalf of child.  NB: child is usually going to be a
  * child of one of our descendants, not a direct child of nexus0.
@@ -405,18 +448,18 @@
 	if (rman_get_bustag(r) == I386_BUS_SPACE_MEM) {
 		caddr_t vaddr = 0;
 
-		if (r->r_end < 1024 * 1024) {
+		if (rman_get_end(r) < 1024 * 1024) {
 			/*
 			 * The first 1Mb is mapped at KERNBASE.
 			 */
-			vaddr = (caddr_t)(uintptr_t)(KERNBASE + r->r_start);
+			vaddr = (caddr_t)(uintptr_t)(KERNBASE + rman_get_start(r));
 		} else {
 			u_int32_t paddr;
 			u_int32_t psize;
 			u_int32_t poffs;
 
-			paddr = r->r_start;
-			psize = r->r_end - r->r_start;
+			paddr = rman_get_start(r);
+			psize = rman_get_size(r);
 
 			poffs = paddr - trunc_page(paddr);
 			vaddr = (caddr_t) pmap_mapdev(paddr-poffs, psize+poffs) + poffs;
@@ -440,10 +483,11 @@
 	/*
 	 * If this is a memory resource, unmap it.
 	 */
-	if ((rman_get_bustag(r) == I386_BUS_SPACE_MEM) && (r->r_end >= 1024 * 1024)) {
+	if ((rman_get_bustag(r) == I386_BUS_SPACE_MEM) &&
+	    (rman_get_end(r) >= 1024 * 1024)) {
 		u_int32_t psize;
 
-		psize = r->r_end - r->r_start;
+		psize = rman_get_size(r);
 		pmap_unmapdev((vm_offset_t)rman_get_virtual(r), psize);
 	}
 		
@@ -454,7 +498,7 @@
 nexus_release_resource(device_t bus, device_t child, int type, int rid,
 		       struct resource *r)
 {
-	if (r->r_flags & RF_ACTIVE) {
+	if (rman_get_flags(r) & RF_ACTIVE) {
 		int error = bus_deactivate_resource(child, type, rid, r);
 		if (error)
 			return error;
@@ -574,3 +618,51 @@
 
 	resource_list_delete(rl, type, rid);
 }
+
+/*
+ * Placeholder which claims PnP 'devices' which describe system
+ * resources.
+ */
+static struct isa_pnp_id sysresource_ids[] = {
+	{ 0x010cd041 /* PNP0c01 */, "System Memory" },
+	{ 0x020cd041 /* PNP0c02 */, "System Resource" },
+	{ 0 }
+};
+
+static int
+sysresource_probe(device_t dev)
+{
+	int	result;
+
+	if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, sysresource_ids)) >= 0) {
+		device_quiet(dev);
+	}
+	return (result);
+}
+
+static int
+sysresource_attach(device_t dev)
+{
+	return (0);
+}
+
+static device_method_t sysresource_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		sysresource_probe),
+	DEVMETHOD(device_attach,	sysresource_attach),
+	DEVMETHOD(device_detach,	bus_generic_detach),
+	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
+	DEVMETHOD(device_suspend,	bus_generic_suspend),
+	DEVMETHOD(device_resume,	bus_generic_resume),
+	{ 0, 0 }
+};
+
+static driver_t sysresource_driver = {
+	"sysresource",
+	sysresource_methods,
+	1,		/* no softc */
+};
+
+static devclass_t sysresource_devclass;
+
+DRIVER_MODULE(sysresource, isa, sysresource_driver, sysresource_devclass, 0, 0);
diff -uNr sys.old/i386/include/nexusvar.h sys/i386/include/nexusvar.h
--- sys.old/i386/include/nexusvar.h	Thu Jan  1 00:00:00 1970
+++ sys/i386/include/nexusvar.h	Sat Dec 20 17:08:07 2003
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 2000 Peter Wemm <peter@xxxxxxxxxxx>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/i386/include/nexusvar.h,v 1.1 2000/09/28 00:37:31 peter Exp $
+ * $DragonFly$
+ */
+
+#ifndef _MACHINE_NEXUSVAR_H_
+#define	_MACHINE_NEXUSVAR_H_	1
+
+enum nexus_device_ivars {
+	NEXUS_IVAR_PCIBUS
+};
+
+#define NEXUS_ACCESSOR(A, B, T)						  \
+									  \
+static __inline T nexus_get_ ## A(device_t dev)				  \
+{									  \
+	uintptr_t v;							  \
+	BUS_READ_IVAR(device_get_parent(dev), dev, NEXUS_IVAR_ ## B, &v); \
+	return (T) v;							  \
+}									  \
+									  \
+static __inline void nexus_set_ ## A(device_t dev, T t)			  \
+{									  \
+	uintptr_t v = (uintptr_t) t;					  \
+	BUS_WRITE_IVAR(device_get_parent(dev), dev, NEXUS_IVAR_ ## B, v); \
+}
+
+NEXUS_ACCESSOR(pcibus,			PCIBUS,		u_int32_t)
+
+#undef NEXUS_ACCESSOR
+
+#endif /* !_MACHINE_NEXUSVAR_H_ */
diff -uNr sys.old/sys/rman.h sys/sys/rman.h
--- sys.old/sys/rman.h	Sat Jul 19 21:14:50 2003
+++ sys/sys/rman.h	Sat Dec 20 17:08:07 2003
@@ -64,6 +64,7 @@
 #define	RF_TIMESHARE	0x0008	/* resource permits time-division sharing */
 #define	RF_WANTED	0x0010	/* somebody is waiting for this resource */
 #define	RF_FIRSTSHARE	0x0020	/* first in sharing list */
+#define	RF_PREFETCHABLE	0x0040	/* resource is prefetchable */
 
 #define	RF_ALIGNMENT_SHIFT	10 /* alignment size bit starts bit 10 */
 #define	RF_ALIGNMENT_MASK	(0x003F << RF_ALIGNMENT_SHIFT)
@@ -100,6 +101,8 @@
 
 #define rman_get_start(r)	((r)->r_start)
 #define rman_get_end(r)		((r)->r_end)
+#define rman_get_device(r)	((r)->r_dev)
+#define rman_get_size(r)	(((r)->r_end - (r)->r_start) +1 )
 #define rman_get_flags(r)	((r)->r_flags)
 #define	rman_set_virtual(r,v)	((r)->r_virtual = (v))
 #define	rman_get_virtual(r)	((r)->r_virtual)


[Date Prev][Date Next]  [Thread Prev][Thread Next]  [Date Index][Thread Index]