Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 20 Oct 2008 13:45:35 GMT
From:      Nathan Whitehorn <nwhitehorn@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 151604 for review
Message-ID:  <200810201345.m9KDjZxl097940@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=151604

Change 151604 by nwhitehorn@nwhitehorn_trantor on 2008/10/20 13:44:36

	Mega-commit for beginnings of real Mambo support. This includes the
	following:
	
		1. Finish transformation of PPC PCI code to use sparc64's
		   OFW PCI stuff.
		2. Merge some of sparc64's OFW code to sys/dev/ofw. The
		   sparc64 side of this still needs cleaning.
		3. Add ISA support on PowerPC.
		4. Add support for real device drivers hanging off nexus by
		   implementing bus_alloc_resource() to do something 
		   intelligent. This is necessary for ISA and OpenPIC
		   support on Mambo, and for SMU support and u3 PIC support
		   on real hardware.
		4. Add a driver for Mambo's OpenPIC. This apparently tries
		   to access registers it shouldn't, causing Mambo to die with
		   FATAL ERROR: accessing area for non existent proc
		   after probing the PIC.

Affected files ...

.. //depot/projects/ppc-g5/sys/conf/files.powerpc#6 edit
.. //depot/projects/ppc-g5/sys/dev/ofw/ofw_imap.c#1 add
.. //depot/projects/ppc-g5/sys/dev/ofw/ofw_imap.h#1 add
.. //depot/projects/ppc-g5/sys/powerpc/aim/nexus.c#3 edit
.. //depot/projects/ppc-g5/sys/powerpc/mambo/openpic_mambo.c#1 add
.. //depot/projects/ppc-g5/sys/powerpc/ofw/ofw_isa.c#1 add
.. //depot/projects/ppc-g5/sys/powerpc/ofw/ofw_isa.h#1 add
.. //depot/projects/ppc-g5/sys/powerpc/ofw/ofw_pcib_pci.c#4 edit
.. //depot/projects/ppc-g5/sys/powerpc/ofw/ofw_pcibus.c#2 edit
.. //depot/projects/ppc-g5/sys/powerpc/powermac/cpcht.c#5 edit
.. //depot/projects/ppc-g5/sys/powerpc/powermac/cpchtvar.h#2 edit
.. //depot/projects/ppc-g5/sys/powerpc/powermac/grackle.c#4 edit
.. //depot/projects/ppc-g5/sys/powerpc/powermac/gracklevar.h#2 edit
.. //depot/projects/ppc-g5/sys/powerpc/powermac/uninorth.c#5 edit
.. //depot/projects/ppc-g5/sys/powerpc/powermac/uninorthvar.h#5 edit
.. //depot/projects/ppc-g5/sys/powerpc/powerpc/autoconf.c#3 edit

Differences ...

==== //depot/projects/ppc-g5/sys/conf/files.powerpc#6 (text+ko) ====

@@ -37,6 +37,7 @@
 dev/ofw/ofw_bus_subr.c		optional	aim
 dev/ofw/ofw_console.c		optional	aim
 dev/ofw/ofw_disk.c		optional	ofwd aim
+dev/ofw/ofw_imap.c		optional	aim
 dev/powermac_nvram/powermac_nvram.c optional	powermac_nvram powermac
 dev/quicc/quicc_bfe_ocp.c	optional	quicc mpc85xx
 dev/scc/scc_bfe_macio.c		optional	scc powermac
@@ -105,6 +106,7 @@
 powerpc/mpc85xx/ocpbus.c	optional	mpc85xx
 powerpc/mpc85xx/opic.c		optional	mpc85xx
 powerpc/mpc85xx/pci_ocp.c	optional	pci mpc85xx
+powerpc/ofw/ofw_isa.c		optional	isa aim
 powerpc/ofw/ofw_pcibus.c	optional	pci aim
 powerpc/ofw/ofw_pcib_pci.c	optional	pci aim
 powerpc/ofw/ofw_syscons.c	optional	sc aim
@@ -149,6 +151,7 @@
 powerpc/powerpc/suswintr.c	standard
 powerpc/powerpc/syncicache.c	standard
 powerpc/powerpc/sys_machdep.c	standard
+powerpc/mambo/openpic_mambo.c	optional	mambo
 powerpc/psim/iobus.c 		optional	psim
 powerpc/psim/ata_iobus.c	optional	ata psim
 powerpc/psim/openpic_iobus.c	optional	psim

==== //depot/projects/ppc-g5/sys/powerpc/aim/nexus.c#3 (text+ko) ====

@@ -64,6 +64,8 @@
 #include <sys/cons.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
 
 #include <dev/ofw/openfirm.h>
 
@@ -105,7 +107,8 @@
 };
 
 struct nexus_softc {
-	struct rman	sc_rman;
+	struct rman	sc_intr_rman;
+	struct rman	sc_mem_rman;
 };
 
 /*
@@ -212,23 +215,24 @@
 	phandle_t	root;
 	phandle_t	child;
 	struct		nexus_softc *sc;
-	u_long		start, end;
 
 	if ((root = OF_peer(0)) == -1)
 		panic("nexus_probe: OF_peer failed.");
 
 	sc = device_get_softc(dev);
 
-	start = 0;
-	end = INTR_VECTORS - 1;
+	sc->sc_intr_rman.rm_type = RMAN_ARRAY;
+	sc->sc_intr_rman.rm_descr = "Interrupt request lines";
+	if (rman_init(&sc->sc_intr_rman) ||
+	    rman_manage_region(&sc->sc_intr_rman, 0, INTR_VECTORS - 1))
+		panic("nexus_probe IRQ rman");
+
+	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
+	sc->sc_mem_rman.rm_descr = "Device Memory";
+	if (rman_init(&sc->sc_mem_rman) ||
+	    rman_manage_region(&sc->sc_mem_rman, 0, ~0UL))
+		panic("nexus_probe mem rman");
 
-	sc->sc_rman.rm_start = start;
-	sc->sc_rman.rm_end = end;
-	sc->sc_rman.rm_type = RMAN_ARRAY;
-	sc->sc_rman.rm_descr = "Interrupt request lines";
-	if (rman_init(&sc->sc_rman) ||
-	    rman_manage_region(&sc->sc_rman, start, end))
-		panic("nexus_probe IRQ rman");
 
 	/*
 	 * Now walk the OFW tree to locate top-level devices
@@ -386,84 +390,116 @@
 {
 	struct nexus_softc *sc;
 	struct resource *rv;
+	struct rman	*rman;
+	int    needactivate;
+
+	needactivate = flags & RF_ACTIVE;
+	flags &= ~RF_ACTIVE;
+
+	sc = device_get_softc(bus);
+
+	if (type == SYS_RES_IRQ) {
+		rman = &sc->sc_intr_rman;
 
-	if (type != SYS_RES_IRQ) {
+		if (count == 0 || start + count - 1 != end) {
+			device_printf(bus, "invalid IRQ allocation from %s\n",
+			    device_get_nameunit(child));
+			return (NULL);
+		}
+	} else if (type == SYS_RES_IOPORT || type == SYS_RES_MEMORY) {
+		rman = &sc->sc_mem_rman;
+	} else {
 		device_printf(bus, "unknown resource request from %s\n",
 		    device_get_nameunit(child));
 		return (NULL);
 	}
 
-	if (count == 0 || start + count - 1 != end) {
-		device_printf(bus, "invalid IRQ allocation from %s\n",
+	rv = rman_reserve_resource(rman, start, end, count, flags, child);
+	if (rv == NULL) {
+		device_printf(bus, "Resource allocation failed for %s\n",
 		    device_get_nameunit(child));
 		return (NULL);
 	}
 
-	sc = device_get_softc(bus);
+	rman_set_rid(rv, *rid);
 
-	rv = rman_reserve_resource(&sc->sc_rman, start, end, count,
-	    flags, child);
-	if (rv == NULL) {
-		device_printf(bus, "IRQ allocation failed for %s\n",
-		    device_get_nameunit(child));
-	} else
-		rman_set_rid(rv, *rid);
+	if (needactivate) {
+		if (nexus_activate_resource(bus, child, type, *rid, rv) != 0) {
+			device_printf(bus,
+			    "Resource activation failed for %s\n",
+			    device_get_nameunit(child));
+			rman_release_resource(rv);
+			return (NULL);
+		}
+	}
 
 	return (rv);
 }
 
 static int
 nexus_activate_resource(device_t bus, device_t child, int type, int rid,
-    struct resource *res)
+struct resource *res)
 {
+	if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
+		vm_offset_t start;
+		void *p;
+		
+		start = (vm_offset_t)rman_get_start(res);
 
-	/* Not much to be done yet... */
+		p = pmap_mapdev(start, (vm_size_t)rman_get_size(res));
+		if (p == NULL)
+			return (ENOMEM);
+		rman_set_virtual(res, p);
+		rman_set_bustag(res, &bs_be_tag);
+		rman_set_bushandle(res, (u_long)p);
+	}
+
 	return (rman_activate_resource(res));
 }
 
 static int
 nexus_deactivate_resource(device_t bus, device_t child, int type, int rid,
-    struct resource *res)
+struct resource *res)
 {
 
-	/* Not much to be done yet... */
-	return (rman_deactivate_resource(res));
+/* Not much to be done yet... */
+return (rman_deactivate_resource(res));
 }
 
 static int
 nexus_release_resource(device_t bus, device_t child, int type, int rid,
-    struct resource *res)
+struct resource *res)
 {
 
-	if (type != SYS_RES_IRQ) {
-		device_printf(bus, "unknown resource request from %s\n",
-		    device_get_nameunit(child));
-		return (EINVAL);
-	}
+if (type != SYS_RES_IRQ) {
+	device_printf(bus, "unknown resource request from %s\n",
+	    device_get_nameunit(child));
+	return (EINVAL);
+}
 
-	return (rman_release_resource(res));
+return (rman_release_resource(res));
 }
 
 static device_t
 nexus_device_from_node(device_t parent, phandle_t node)
 {
-	device_t	cdev;
-	struct		nexus_devinfo *dinfo;
-	char		*name, *type, *compatible;
+device_t	cdev;
+struct		nexus_devinfo *dinfo;
+char		*name, *type, *compatible;
 
-	OF_getprop_alloc(node, "name", 1, (void **)&name);
-	OF_getprop_alloc(node, "device_type", 1, (void **)&type);
-	OF_getprop_alloc(node, "compatible", 1, (void **)&compatible);
-	cdev = device_add_child(parent, NULL, -1);
-	if (cdev != NULL) {
-		dinfo = malloc(sizeof(*dinfo), M_NEXUS, M_WAITOK);
-		dinfo->ndi_node = node;
-		dinfo->ndi_name = name;
-		dinfo->ndi_device_type = type;
-		dinfo->ndi_compatible = compatible;
-		device_set_ivars(cdev, dinfo);
-	} else
-		free(name, M_OFWPROP);
+OF_getprop_alloc(node, "name", 1, (void **)&name);
+OF_getprop_alloc(node, "device_type", 1, (void **)&type);
+OF_getprop_alloc(node, "compatible", 1, (void **)&compatible);
+cdev = device_add_child(parent, NULL, -1);
+if (cdev != NULL) {
+	dinfo = malloc(sizeof(*dinfo), M_NEXUS, M_WAITOK);
+	dinfo->ndi_node = node;
+	dinfo->ndi_name = name;
+	dinfo->ndi_device_type = type;
+	dinfo->ndi_compatible = compatible;
+	device_set_ivars(cdev, dinfo);
+} else
+	free(name, M_OFWPROP);
 
 	return (cdev);
 }

==== //depot/projects/ppc-g5/sys/powerpc/ofw/ofw_pcib_pci.c#4 (text+ko) ====

@@ -35,6 +35,7 @@
 
 #include <dev/ofw/openfirm.h>
 #include <dev/ofw/ofw_pci.h>
+#include <dev/ofw/ofw_imap.h>
 #include <dev/ofw/ofw_bus.h>
 
 #include <dev/pci/pcivar.h>
@@ -46,6 +47,8 @@
 static int	ofw_pcib_pci_probe(device_t bus);
 static int	ofw_pcib_pci_attach(device_t bus);
 static phandle_t ofw_pcib_pci_get_node(device_t bus, device_t dev);
+static int	ofw_pcib_pci_route_interrupt(device_t bridge, device_t dev,
+		    int intpin);
 
 static device_method_t ofw_pcib_pci_methods[] = {
 	/* Device interface */
@@ -70,7 +73,7 @@
 	DEVMETHOD(pcib_maxslots,		pcib_maxslots),
 	DEVMETHOD(pcib_read_config,		pcib_read_config),
 	DEVMETHOD(pcib_write_config,	pcib_write_config),
-	DEVMETHOD(pcib_route_interrupt,	pcib_route_interrupt),
+	DEVMETHOD(pcib_route_interrupt,	ofw_pcib_pci_route_interrupt),
 
 	/* ofw_bus interface */
 	DEVMETHOD(ofw_bus_get_node,     ofw_pcib_pci_get_node),
@@ -80,8 +83,20 @@
 
 static devclass_t pcib_devclass;
 
+struct ofw_pcib_softc {
+        /*
+         * This is here so that we can use pci bridge methods, too - the
+         * generic routines only need the dev, secbus and subbus members
+         * filled.
+         */
+        struct pcib_softc       ops_pcib_sc;
+	phandle_t		ops_node;
+        struct ofw_bus_iinfo    ops_iinfo;
+};
+
+
 DEFINE_CLASS_0(pcib, ofw_pcib_pci_driver, ofw_pcib_pci_methods,
-    sizeof(struct pcib_softc));
+    sizeof(struct ofw_pcib_softc));
 DRIVER_MODULE(ofw_pcib, pci, ofw_pcib_pci_driver, pcib_devclass, 0, 0);
 
 static int
@@ -103,6 +118,15 @@
 static int
 ofw_pcib_pci_attach(device_t dev)
 {
+	struct ofw_pcib_softc *sc;
+
+	sc = device_get_softc(dev);
+	sc->ops_pcib_sc.dev = dev;
+	sc->ops_node = ofw_bus_get_node(dev);
+
+	ofw_bus_setup_iinfo(sc->ops_node, &sc->ops_iinfo,
+	    sizeof(cell_t));
+
 	pcib_attach_common(dev);
 
 	device_add_child(dev, "pci", -1);
@@ -110,7 +134,7 @@
 	return (bus_generic_attach(dev));
 }
 
-phandle_t
+static phandle_t
 ofw_pcib_pci_get_node(device_t bridge, device_t dev)
 {
 	/* We have only one child, the PCI bus, so pass it our node */
@@ -118,3 +142,37 @@
 	return (ofw_bus_get_node(bridge));
 }
 
+static int
+ofw_pcib_pci_route_interrupt(device_t bridge, device_t dev, int intpin)
+{
+	struct ofw_pcib_softc *sc;
+	struct ofw_bus_iinfo *ii;
+	struct ofw_pci_register reg;
+	cell_t pintr, mintr;
+	uint8_t maskbuf[sizeof(reg) + sizeof(pintr)];
+
+	sc = device_get_softc(bridge);
+	ii = &sc->ops_iinfo;
+	if (ii->opi_imapsz > 0) {
+		pintr = intpin;
+		if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), ii, &reg,
+		    sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr),
+		    maskbuf)) {
+			/*
+			 * If we've found a mapping, return it and don't map
+			 * it again on higher levels - that causes problems
+			 * in some cases, and never seems to be required.
+			 */
+			return (mintr);
+		}
+	} else if (intpin >= 1 && intpin <= 4) {
+		/*
+		 * When an interrupt map is missing, we need to do the
+		 * standard PCI swizzle and continue mapping at the parent.
+		 */
+		return (pcib_route_interrupt(bridge, dev, intpin));
+	}
+	return (PCIB_ROUTE_INTERRUPT(device_get_parent(device_get_parent(
+	    bridge)), bridge, intpin));
+}
+

==== //depot/projects/ppc-g5/sys/powerpc/ofw/ofw_pcibus.c#2 (text+ko) ====

@@ -1,6 +1,4 @@
 /*-
- * Copyright (c) 1994 Charles M. Hannum.  All rights reserved.
- * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
  * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
  * Copyright (c) 2000, Michael Smith <msmith@freebsd.org>
  * Copyright (c) 2000, BSDi
@@ -30,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/powerpc/pci/ofw_pcibus.c 182108 2008-08-24 15:05:46Z marius $");
+__FBSDID("$FreeBSD: src/sys/sparc64/pci/ofw_pcibus.c,v 1.21 2008/08/24 15:05:46 marius Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -42,6 +40,7 @@
 #include <dev/ofw/ofw_bus.h>
 #include <dev/ofw/ofw_bus_subr.h>
 #include <dev/ofw/ofw_pci.h>
+#include <dev/ofw/ofw_imap.h>
 #include <dev/ofw/openfirm.h>
 
 #include <machine/bus.h>
@@ -54,10 +53,11 @@
 #include "pcib_if.h"
 #include "pci_if.h"
 
+typedef uint32_t ofw_pci_intr_t;
+
 /* Helper functions */
-static int  find_node_intr(phandle_t, u_int32_t *, u_int32_t *);
-static int  ofw_pci_find_intline(phandle_t node, uint32_t *irqs);
-static void ofw_pci_fixup_node(device_t dev, phandle_t node);
+static void ofw_pcibus_setup_device(device_t bridge, uint32_t clock,
+    u_int busno, u_int slot, u_int func);
 
 /* Methods */
 static device_probe_t ofw_pcibus_probe;
@@ -70,6 +70,8 @@
 	DEVMETHOD(device_probe,		ofw_pcibus_probe),
 	DEVMETHOD(device_attach,	ofw_pcibus_attach),
 
+	/* Bus interface */
+
 	/* PCI interface */
 	DEVMETHOD(pci_assign_interrupt, ofw_pcibus_assign_interrupt),
 
@@ -100,6 +102,7 @@
 static int
 ofw_pcibus_probe(device_t dev)
 {
+
 	if (ofw_bus_get_node(dev) == 0)
 		return (ENXIO);
 	device_set_desc(dev, "OFW PCI bus");
@@ -107,6 +110,22 @@
 	return (0);
 }
 
+/*
+ * Perform miscellaneous setups the firmware usually does not do for us.
+ */
+static void
+ofw_pcibus_setup_device(device_t bridge, uint32_t clock, u_int busno,
+    u_int slot, u_int func)
+{
+	/*
+	 * The preset in the intline register is usually wrong.  Reset
+	 * it to 255, so that the PCI code will reroute the interrupt if
+	 * needed.
+	 */
+	PCIB_WRITE_CONFIG(bridge, busno, slot, func, PCIR_INTLINE,
+	    PCI_INVALID_IRQ, 1);
+}
+
 static int
 ofw_pcibus_attach(device_t dev)
 {
@@ -114,6 +133,7 @@
 	struct ofw_pci_register pcir;
 	struct ofw_pcibus_devinfo *dinfo;
 	phandle_t node, child;
+	uint32_t clock;
 	u_int busno, domain, func, slot;
 
 	pcib = device_get_parent(dev);
@@ -124,44 +144,44 @@
 		    domain, busno);
 	node = ofw_bus_get_node(dev);
 
+	if (OF_getprop(ofw_bus_get_node(pcib), "clock-frequency", &clock,
+	    sizeof(clock)) == -1)
+		clock = 33000000;
 	for (child = OF_child(node); child != 0; child = OF_peer(child)) {
 		if (OF_getprop(child, "reg", &pcir, sizeof(pcir)) == -1)
 			continue;
 		slot = OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi);
 		func = OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi);
-
 		/* Some OFW device trees contain dupes. */
 		if (pci_find_dbsf(domain, busno, slot, func) != NULL)
 			continue;
-
-		ofw_pci_fixup_node(pcib, child);
-
+		ofw_pcibus_setup_device(pcib, clock, busno, slot, func);
 		dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(pcib,
 		    domain, busno, slot, func, sizeof(*dinfo));
-
 		if (dinfo == NULL)
 			continue;
-
-		/* Set up OFW devinfo */
 		if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, child) !=
 		    0) {
 			pci_freecfg((struct pci_devinfo *)dinfo);
 			continue;
 		}
-
 		pci_add_child(dev, (struct pci_devinfo *)dinfo);
 
 		/*
-		 * Some devices don't have an intpin set, but do have
-		 * interrupts. Add them to the appropriate resource list.
-		 */
-		if (dinfo->opd_dinfo.cfg.intpin == 0) {
-			uint32_t irqs[4];
+                 * Some devices don't have an intpin set, but do have
+                 * interrupts. These are fully specified, and set in the
+		 * interrupts property, so add that value to the device's
+		 * resource list.
+                 */
+                if (dinfo->opd_dinfo.cfg.intpin == 0) {
+                        ofw_pci_intr_t intr;
 
-			if (ofw_pci_find_intline(child, irqs) > 0)
-				resource_list_add(&dinfo->opd_dinfo.resources, 
-				    SYS_RES_IRQ, 0, irqs[0], irqs[0], 1);
-		}
+			if (OF_getprop(child, "interrupts", &intr, 
+			    sizeof(intr)) > 0) {
+                                resource_list_add(&dinfo->opd_dinfo.resources,
+                                    SYS_RES_IRQ, 0, intr, intr, 1);
+			}
+                }
 	}
 
 	return (bus_generic_attach(dev));
@@ -170,18 +190,34 @@
 static int
 ofw_pcibus_assign_interrupt(device_t dev, device_t child)
 {
-	uint32_t irqs[4];
+	ofw_pci_intr_t intr;
+	int isz;
 
-	device_printf(child,"Assigning interrupt\n");
+	/* Any AAPL,interrupts property gets priority and is fully spec'ed */
 
-	if (ofw_pci_find_intline(ofw_bus_get_node(child), irqs) < 0)
-		return PCI_INVALID_IRQ;
+	isz = OF_getprop(ofw_bus_get_node(child), "AAPL,interrupts", &intr, 
+	    sizeof(intr));
+	if (isz == sizeof(intr)) {
+		return (intr);
+	}
 
-	device_printf(child,"IRQ %d\n",irqs[0]);
-
-	return irqs[0];
-
-//	return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, intr));
+	isz = OF_getprop(ofw_bus_get_node(child), "interrupts", &intr, 
+	    sizeof(intr));
+	if (isz != sizeof(intr)) {
+		/* No property; our best guess is the intpin. */
+		intr = pci_get_intpin(child);
+	}
+	/*
+	 * If we got intr from a property, it may or may not be an intpin.
+	 * For on-board devices, it frequently is not, and is completely out
+	 * of the valid intpin range.  For PCI slots, it hopefully is,
+	 * otherwise we will have trouble interfacing with non-OFW buses
+	 * such as cardbus.
+	 * Since we cannot tell which it is without violating layering, we
+	 * will always use the route_interrupt method, and treat exceptions
+	 * on the level they become apparent.
+	 */
+	return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, intr));
 }
 
 static const struct ofw_bus_devinfo *
@@ -193,167 +229,3 @@
 	return (&dinfo->opd_obdinfo);
 }
 
-static void
-ofw_pci_fixup_node(device_t dev, phandle_t node)
-{
-	uint32_t	csr, intr, irqs[4];
-	struct		ofw_pci_register addr[8];
-	int		len, i;
-
-	len = OF_getprop(node, "assigned-addresses", addr, sizeof(addr));
-	if (len < (int)sizeof(struct ofw_pci_register)) {
-		return;
-	}
-
-	csr = PCIB_READ_CONFIG(dev, OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi),
-	    OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi),
-	    OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_COMMAND, 4);
-	csr &= ~(PCIM_CMD_PORTEN | PCIM_CMD_MEMEN);
-
-	for (i = 0; i < len / sizeof(struct ofw_pci_register); i++) {
-		switch (addr[i].phys_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
-		case OFW_PCI_PHYS_HI_SPACE_IO:
-			csr |= PCIM_CMD_PORTEN;
-			break;
-		case OFW_PCI_PHYS_HI_SPACE_MEM32:
-			csr |= PCIM_CMD_MEMEN;
-			break;
-		}
-	}
-
-	PCIB_WRITE_CONFIG(dev, OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi),
-	    OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi),
-	    OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_COMMAND, csr, 4);
-
-	if (ofw_pci_find_intline(node, irqs) != -1) {
-		intr = PCIB_READ_CONFIG(dev,
-		    OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi),
-		    OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi),
-		    OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_INTLINE, 2);
-		intr &= ~(0xff);
-		intr |= irqs[0] & 0xff;
-		PCIB_WRITE_CONFIG(dev,
-		    OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi),
-		    OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi),
-		    OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_INTLINE,
-		    intr, 2);
-	}
-}
-
-static int
-ofw_pci_find_intline(phandle_t node, uint32_t *irqs)
-{
-	uint32_t	npintr, paddr[4];
-	struct		ofw_pci_register addr[8];
-	int		len;
-
-	len = OF_getprop(node, "assigned-addresses", addr, sizeof(addr));
-	if (len < (int)sizeof(struct ofw_pci_register)) 
-		return -1;
-	/*
-	 * Create PCI interrupt-map array element. pci-mid/pci-lo
-	 * aren't required, but the 'interrupts' property needs
-	 * to be appended
-	 */
-	npintr = 0;
-	OF_getprop(node, "interrupts", &npintr, 4);
-	paddr[0] = addr[0].phys_hi;
-	paddr[1] = 0;
-	paddr[2] = 0;
-	paddr[3] = npintr;
-
-	return find_node_intr(node, paddr, irqs);
-}
-
-static int
-find_node_intr(phandle_t node, u_int32_t *addr, u_int32_t *intr)
-{
-	phandle_t	parent, iparent;
-	int		len, mlen, match, i;
-	u_int32_t	map[160], *mp, imask[8], maskedaddr[8], icells;
-	char		name[32];
-
-	len = OF_getprop(node, "AAPL,interrupts", intr, 4);
-	if (len == 4) {
-		return (len);
-	}
-
-	parent = OF_parent(node);
-	len = OF_getprop(parent, "interrupt-map", map, sizeof(map));
-	mlen = OF_getprop(parent, "interrupt-map-mask", imask, sizeof(imask));
-
-	if (len == -1 || mlen == -1)
-		goto nomap;
-
-	memcpy(maskedaddr, addr, mlen);
-	for (i = 0; i < mlen/4; i++)
-		maskedaddr[i] &= imask[i];
-
-	mp = map;
-	while (len > mlen) {
-		match = bcmp(maskedaddr, mp, mlen);
-		mp += mlen / 4;
-		len -= mlen;
-
-		/*
-		 * We must read "#interrupt-cells" for each time because
-		 * interrupt-parent may be different.
-		 */
-		iparent = *mp++;
-		len -= 4;
-		if (OF_getprop(iparent, "#interrupt-cells", &icells, 4) != 4)
-			goto nomap;
-
-		/* Found. */
-		if (match == 0) {
-			bcopy(mp, intr, icells * 4);
-			return (icells * 4);
-		}
-
-		mp += icells;
-		len -= icells * 4;
-	}
-
-nomap:
-	/*
-	 * Check for local properties indicating interrupts
-	 */
-
-	len = OF_getprop(node, "interrupts", intr, 16);
-	if (OF_getprop(node, "interrupt-parent", &iparent, sizeof(iparent)) ==
-	   sizeof(iparent)) {
-		OF_getprop(iparent, "#interrupt-cells", &icells, sizeof(icells));
-		for (i = 0; i < len/icells/4; i++)
-			intr[i] = intr[i*icells];
-
-		return (len);
-	}
-	
-
-	/*
-	 * If the node has no interrupt property and the parent is a PCI
-	 * bridge, use the parent's interrupt.  This occurs on a PCI slot.
-	 */
-	bzero(name, sizeof(name));
-	OF_getprop(parent, "name", name, sizeof(name));
-	if (strcmp(name, "pci-bridge") == 0) {
-		len = OF_getprop(parent, "AAPL,interrupts", intr, 4);
-		if (len == 4) {
-			return (len);
-		}
-
-		/*
-		 * XXX I don't know what is the correct local address.
-		 * XXX Use the first entry for now.
-		 */
-		len = OF_getprop(parent, "interrupt-map", map, sizeof(map));
-		if (len >= 36) {
-			addr = &map[5];
-			/* XXX Use 0 for 'interrupts' for compat */
-			return (find_node_intr(parent, addr, intr));
-		}
-	}
-
-	return (-1);
-}
-

==== //depot/projects/ppc-g5/sys/powerpc/powermac/cpcht.c#5 (text+ko) ====

@@ -37,6 +37,7 @@
 
 #include <dev/pci/pcivar.h>
 #include <dev/pci/pcireg.h>
+#include <isa/isavar.h>
 
 #include <machine/bus.h>
 #include <machine/md_var.h>
@@ -46,6 +47,7 @@
 #include <sys/rman.h>
 
 #include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_imap.h>
 #include <dev/ofw/ofw_bus_subr.h>
 #include <powerpc/powermac/cpchtvar.h>
 
@@ -133,14 +135,13 @@
 
 	root = ofw_bus_get_node(dev);
 
-	if (OF_getprop(root, "reg", reg, sizeof(reg)) < 24)
+	if (OF_getprop(root, "reg", reg, sizeof(reg)) < 8)
 		return (ENXIO);
 
 	for (child = OF_child(root); child != 0; child = OF_peer(child)) {
 		dinfo = malloc(sizeof(*dinfo), M_CPCHT, M_WAITOK | M_ZERO);
 
-                if (ofw_bus_gen_setup_devinfo(dinfo, child) 
-		    != 0) {
+                if (ofw_bus_gen_setup_devinfo(dinfo, child) != 0) {
                         free(dinfo, M_CPCHT);
                         continue;
                 }
@@ -165,6 +166,56 @@
 }
 
 /*
+ * CPC ISA Device interface.
+ */
+static int		cpcisa_probe(device_t);
+
+/*
+ * Driver methods.
+ */
+static device_method_t	cpcisa_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		cpcisa_probe),
+	DEVMETHOD(device_attach,	isab_attach),
+
+	/* Bus interface */
+	DEVMETHOD(bus_print_child,	bus_generic_print_child),
+	DEVMETHOD(bus_read_ivar,	bus_generic_read_ivar),
+	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
+	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
+	DEVMETHOD(bus_alloc_resource,	bus_generic_alloc_resource),
+	DEVMETHOD(bus_activate_resource,bus_generic_activate_resource),
+
+	{0,0}
+};
+
+static driver_t	cpcisa_driver = {
+	"isab",
+	cpcisa_methods,
+	0
+};
+
+DRIVER_MODULE(cpcisa, cpcht, cpcisa_driver, isab_devclass, 0, 0);
+
+static int
+cpcisa_probe(device_t dev)
+{
+	const char	*type;
+
+	type = ofw_bus_get_type(dev);
+
+	if (type == NULL)
+		return (ENXIO);
+
+	if (strcmp(type, "isa") != 0)
+		return (ENXIO);
+
+	device_set_desc(dev, "HyperTransport-ISA bridge");
+	
+	return (0);
+}
+
+/*
  * CPC PCI Device interface.
  */
 static int		cpcpci_probe(device_t);
@@ -351,6 +402,8 @@
 		}
 	}
 
+	ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(cell_t));
+
 	device_add_child(dev, "pci", device_get_unit(dev));
 
 	return (bus_generic_attach(dev));
@@ -540,6 +593,19 @@
 static int
 cpcpci_route_interrupt(device_t bus, device_t dev, int pin)
 {
-	return (0);
+	struct cpcpci_softc *sc;
+	struct ofw_pci_register reg;
+	uint32_t pintr, mintr;
+	uint8_t maskbuf[sizeof(reg) + sizeof(pintr)];
+
+	sc = device_get_softc(bus);
+	pintr = pin;
+	if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, &reg,
+	    sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), maskbuf))
+		return (mintr);
+
+	device_printf(bus, "could not route pin %d for device %d.%d\n",
+	    pin, pci_get_slot(dev), pci_get_function(dev));
+	return (PCI_INVALID_IRQ);
 }
 

==== //depot/projects/ppc-g5/sys/powerpc/powermac/cpchtvar.h#2 (text+ko) ====

@@ -52,6 +52,7 @@
 	bus_space_tag_t		sc_iot;
 	bus_space_tag_t		sc_memt;
 	bus_dma_tag_t		sc_dmat;
+	struct ofw_bus_iinfo	sc_pci_iinfo;
 };
 
 #endif  /* _POWERPC_POWERMAC_CPCHTVAR_H_ */

==== //depot/projects/ppc-g5/sys/powerpc/powermac/grackle.c#4 (text+ko) ====

@@ -37,6 +37,7 @@
 #include <dev/ofw/openfirm.h>
 #include <dev/ofw/ofw_pci.h>
 #include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_imap.h>
 
 #include <dev/pci/pcivar.h>
 #include <dev/pci/pcireg.h>
@@ -251,6 +252,8 @@
 		}
 	}
 
+	ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(cell_t));
+
 	device_add_child(dev, "pci", device_get_unit(dev));
 	return (bus_generic_attach(dev));
 }
@@ -335,8 +338,20 @@
 static int
 grackle_route_interrupt(device_t bus, device_t dev, int pin)
 {
+	struct grackle_softc *sc;
+	struct ofw_pci_register reg;
+	uint32_t pintr, mintr;
+	uint8_t maskbuf[sizeof(reg) + sizeof(pintr)];
 
-	return (0);
+	sc = device_get_softc(bus);
+	pintr = pin;
+	if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, &reg,
+	    sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), maskbuf))
+		return (mintr);
+
+	device_printf(bus, "could not route pin %d for device %d.%d\n",
+	    pin, pci_get_slot(dev), pci_get_function(dev));
+	return (PCI_INVALID_IRQ);
 }
 
 static int

==== //depot/projects/ppc-g5/sys/powerpc/powermac/gracklevar.h#2 (text+ko) ====

@@ -52,6 +52,8 @@
 	struct			rman sc_mem_rman;
 	bus_space_tag_t		sc_memt;
 	bus_dma_tag_t		sc_dmat;
+
+	struct ofw_bus_iinfo	sc_pci_iinfo;
 };
 
 /*

==== //depot/projects/ppc-g5/sys/powerpc/powermac/uninorth.c#5 (text+ko) ====

@@ -35,6 +35,7 @@
 #include <dev/ofw/openfirm.h>
 #include <dev/ofw/ofw_pci.h>
 #include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_imap.h>
 
 #include <dev/pci/pcivar.h>
 #include <dev/pci/pcireg.h>
@@ -294,6 +295,8 @@
 		}
 	}
 
+	ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(cell_t));
+
 	device_add_child(dev, "pci", device_get_unit(dev));
 	return (bus_generic_attach(dev));
 }
@@ -360,8 +363,20 @@
 static int
 uninorth_route_interrupt(device_t bus, device_t dev, int pin)
 {
+	struct uninorth_softc *sc;
+	struct ofw_pci_register reg;
+	uint32_t pintr, mintr;
+	uint8_t maskbuf[sizeof(reg) + sizeof(pintr)];
 
-	return (0);
+	sc = device_get_softc(bus);
+	pintr = pin;
+	if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, &reg,
+	    sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), maskbuf))
+		return (mintr);
+
+	device_printf(bus, "could not route pin %d for device %d.%d\n",
+	    pin, pci_get_slot(dev), pci_get_function(dev));
+	return (PCI_INVALID_IRQ);
 }
 
 static int

==== //depot/projects/ppc-g5/sys/powerpc/powermac/uninorthvar.h#5 (text+ko) ====

@@ -61,6 +61,7 @@
 	bus_space_tag_t		sc_iot;
 	bus_space_tag_t		sc_memt;
 	bus_dma_tag_t		sc_dmat;
+	struct ofw_bus_iinfo	sc_pci_iinfo;
 
 	int			sc_u3;
 };


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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200810201345.m9KDjZxl097940>