PERFORCE change 151604 for review
Nathan Whitehorn
nwhitehorn at FreeBSD.org
Mon Oct 20 13:45:36 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=151604
Change 151604 by nwhitehorn at 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, ®,
+ 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 at freebsd.org>
* Copyright (c) 2000, Michael Smith <msmith at 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, ®,
+ 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, ®,
+ 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, ®,
+ 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) <<<
More information about the p4-projects
mailing list