svn commit: r186728 - in head/sys: dev/ofw powerpc/powermac
Nathan Whitehorn
nwhitehorn at FreeBSD.org
Sat Jan 3 11:38:48 PST 2009
Author: nwhitehorn
Date: Sat Jan 3 19:38:47 2009
New Revision: 186728
URL: http://svn.freebsd.org/changeset/base/186728
Log:
Fix the OFW interrupt map parser to use its own idea of the number of interrupt
cells in the map, instead of using a value passed to it and then panicing if it
disagrees. This fixes interrupt map parsing for PCI bridges on some Apple
Uninorth PCI controllers.
Reported by: marcel
Tested on: G4 iBook, Sun Ultra 5
Modified:
head/sys/dev/ofw/ofw_bus_subr.c
head/sys/dev/ofw/openfirm.c
head/sys/dev/ofw/openfirm.h
head/sys/powerpc/powermac/grackle.c
head/sys/powerpc/powermac/gracklevar.h
head/sys/powerpc/powermac/macio.c
head/sys/powerpc/powermac/uninorth.c
head/sys/powerpc/powermac/uninorthvar.h
Modified: head/sys/dev/ofw/ofw_bus_subr.c
==============================================================================
--- head/sys/dev/ofw/ofw_bus_subr.c Sat Jan 3 18:51:49 2009 (r186727)
+++ head/sys/dev/ofw/ofw_bus_subr.c Sat Jan 3 19:38:47 2009 (r186728)
@@ -146,18 +146,6 @@ ofw_bus_gen_get_type(device_t bus, devic
return (obd->obd_type);
}
-static int
-ofw_bus_searchprop(phandle_t node, char *propname, void *buf, int buflen)
-{
- int rv;
-
- for (; node != 0; node = OF_parent(node)) {
- if ((rv = OF_getprop(node, propname, buf, buflen)) != -1)
- return (rv);
- }
- return (-1);
-}
-
void
ofw_bus_setup_iinfo(phandle_t node, struct ofw_bus_iinfo *ii, int intrsz)
{
@@ -249,17 +237,16 @@ ofw_bus_search_intrmap(void *intr, int i
mptr = imap;
i = imapsz;
- tsz = physsz + intrsz + sizeof(phandle_t) + rintrsz;
while (i > 0) {
- KASSERT(i >= tsz, ("ofw_bus_search_intrmap: truncated map"));
bcopy(mptr + physsz + intrsz, &parent, sizeof(parent));
- if (ofw_bus_searchprop(parent, "#interrupt-cells",
+ if (OF_searchprop(parent, "#interrupt-cells",
&pintrsz, sizeof(pintrsz)) == -1)
pintrsz = 1; /* default */
pintrsz *= sizeof(pcell_t);
- if (pintrsz != rintrsz)
- panic("ofw_bus_search_intrmap: expected interrupt cell "
- "size incorrect: %d > %d", rintrsz, pintrsz);
+
+ /* Compute the map stride size */
+ tsz = physsz + intrsz + sizeof(phandle_t) + pintrsz;
+ KASSERT(i >= tsz, ("ofw_bus_search_intrmap: truncated map"));
/*
* XXX: Apple hardware uses a second cell to set information
Modified: head/sys/dev/ofw/openfirm.c
==============================================================================
--- head/sys/dev/ofw/openfirm.c Sat Jan 3 18:51:49 2009 (r186727)
+++ head/sys/dev/ofw/openfirm.c Sat Jan 3 19:38:47 2009 (r186728)
@@ -220,6 +220,23 @@ OF_getprop(phandle_t package, const char
}
/*
+ * Resursively search the node and its parent for the given property, working
+ * downward from the node to the device tree root. Returns the value of the
+ * first match.
+ */
+ssize_t
+OF_searchprop(phandle_t node, char *propname, void *buf, size_t len)
+{
+ ssize_t rv;
+
+ for (; node != 0; node = OF_parent(node)) {
+ if ((rv = OF_getprop(node, propname, buf, len)) != -1)
+ return (rv);
+ }
+ return (-1);
+}
+
+/*
* Store the value of a property of a package into newly allocated memory
* (using the M_OFWPROP malloc pool and M_WAITOK). elsz is the size of a
* single element, the number of elements is return in number.
Modified: head/sys/dev/ofw/openfirm.h
==============================================================================
--- head/sys/dev/ofw/openfirm.h Sat Jan 3 18:51:49 2009 (r186727)
+++ head/sys/dev/ofw/openfirm.h Sat Jan 3 19:38:47 2009 (r186728)
@@ -104,6 +104,8 @@ phandle_t OF_parent(phandle_t node);
ssize_t OF_getproplen(phandle_t node, const char *propname);
ssize_t OF_getprop(phandle_t node, const char *propname, void *buf,
size_t len);
+ssize_t OF_searchprop(phandle_t node, char *propname, void *buf,
+ size_t len);
ssize_t OF_getprop_alloc(phandle_t node, const char *propname,
int elsz, void **buf);
int OF_nextprop(phandle_t node, const char *propname, char *buf,
Modified: head/sys/powerpc/powermac/grackle.c
==============================================================================
--- head/sys/powerpc/powermac/grackle.c Sat Jan 3 18:51:49 2009 (r186727)
+++ head/sys/powerpc/powermac/grackle.c Sat Jan 3 19:38:47 2009 (r186728)
@@ -165,7 +165,7 @@ static int
grackle_attach(device_t dev)
{
struct grackle_softc *sc;
- phandle_t node, iparent;
+ phandle_t node;
u_int32_t busrange[2];
struct grackle_range *rp, *io, *mem[2];
int nmem, i, error;
@@ -254,14 +254,6 @@ grackle_attach(device_t dev)
ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(cell_t));
- /* We need the number of interrupt cells to read the imap */
- if (OF_getprop(node, "interrupt-parent", &iparent,sizeof(iparent)) <= 0)
- iparent = node;
-
- if (OF_getprop(iparent,"#interrupt-cells",&sc->sc_icells,
- sizeof(sc->sc_icells)) <= 0)
- sc->sc_icells = 1;
-
device_add_child(dev, "pci", device_get_unit(dev));
return (bus_generic_attach(dev));
}
@@ -348,15 +340,14 @@ grackle_route_interrupt(device_t bus, de
{
struct grackle_softc *sc;
struct ofw_pci_register reg;
- uint32_t pintr, mintr[2];
+ 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[0])*sc->sc_icells, maskbuf))
- return (mintr[0]);
+ sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), maskbuf))
+ return (mintr);
/* Maybe it's a real interrupt, not an intpin */
if (pin > 4)
Modified: head/sys/powerpc/powermac/gracklevar.h
==============================================================================
--- head/sys/powerpc/powermac/gracklevar.h Sat Jan 3 18:51:49 2009 (r186727)
+++ head/sys/powerpc/powermac/gracklevar.h Sat Jan 3 19:38:47 2009 (r186728)
@@ -52,7 +52,6 @@ struct grackle_softc {
struct rman sc_mem_rman;
bus_space_tag_t sc_memt;
bus_dma_tag_t sc_dmat;
- int sc_icells;
struct ofw_bus_iinfo sc_pci_iinfo;
};
Modified: head/sys/powerpc/powermac/macio.c
==============================================================================
--- head/sys/powerpc/powermac/macio.c Sat Jan 3 18:51:49 2009 (r186727)
+++ head/sys/powerpc/powermac/macio.c Sat Jan 3 19:38:47 2009 (r186728)
@@ -185,7 +185,6 @@ macio_add_intr(phandle_t devnode, struct
{
int *intr;
int i, nintr;
- phandle_t iparent;
int icells;
if (dinfo->mdi_ninterrupts >= 6) {
@@ -193,10 +192,9 @@ macio_add_intr(phandle_t devnode, struct
return;
}
- icells = 1;
-
- if (OF_getprop(devnode, "interrupt-parent", &iparent, sizeof(iparent)) == sizeof(iparent))
- OF_getprop(iparent, "#interrupt-cells", &icells, sizeof(icells));
+ if (OF_searchprop(devnode, "#interrupt-cells", &icells, sizeof(icells))
+ <= 0)
+ icells = 1;
nintr = OF_getprop_alloc(devnode, "interrupts", sizeof(*intr),
(void **)&intr);
Modified: head/sys/powerpc/powermac/uninorth.c
==============================================================================
--- head/sys/powerpc/powermac/uninorth.c Sat Jan 3 18:51:49 2009 (r186727)
+++ head/sys/powerpc/powermac/uninorth.c Sat Jan 3 19:38:47 2009 (r186728)
@@ -164,7 +164,7 @@ uninorth_attach(device_t dev)
{
struct uninorth_softc *sc;
const char *compatible;
- phandle_t node, child, iparent;
+ phandle_t node, child;
u_int32_t reg[2], busrange[2];
struct uninorth_range *rp, *io, *mem[2];
int nmem, i, error;
@@ -296,12 +296,6 @@ uninorth_attach(device_t dev)
ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(cell_t));
- /* We need the number of interrupt cells to read the imap */
- sc->sc_icells = 2;
- if (OF_getprop(node, "interrupt-parent", &iparent,sizeof(iparent)) > 0)
- OF_getprop(iparent,"#interrupt-cells",&sc->sc_icells,
- sizeof(sc->sc_icells));
-
device_add_child(dev, "pci", device_get_unit(dev));
return (bus_generic_attach(dev));
}
@@ -370,15 +364,14 @@ uninorth_route_interrupt(device_t bus, d
{
struct uninorth_softc *sc;
struct ofw_pci_register reg;
- uint32_t pintr, mintr[2];
+ 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[0])*sc->sc_icells, maskbuf))
- return (mintr[0]);
+ sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), maskbuf))
+ return (mintr);
/* Maybe it's a real interrupt, not an intpin */
if (pin > 4)
Modified: head/sys/powerpc/powermac/uninorthvar.h
==============================================================================
--- head/sys/powerpc/powermac/uninorthvar.h Sat Jan 3 18:51:49 2009 (r186727)
+++ head/sys/powerpc/powermac/uninorthvar.h Sat Jan 3 19:38:47 2009 (r186728)
@@ -64,7 +64,6 @@ struct uninorth_softc {
struct ofw_bus_iinfo sc_pci_iinfo;
int sc_u3;
- int sc_icells;
};
struct unin_chip_softc {
More information about the svn-src-all
mailing list