diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2015-03-22 12:46:00 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2015-03-22 12:46:00 +0000 |
commit | a38153695da29e7fa1433e8315c63a920a1bc972 (patch) | |
tree | 4f9838bbd6743305953a3aa368a746da9a87bab7 /sys/arch/sparc/dev | |
parent | 6ae4e951e6b669c7bb69fd13cc51d5abb8c16e07 (diff) |
Do the right thing in qec_fix_range() when connected to an sbus(4) without
`ranges' property, i.e. sun4c, so that child devices can attach correctly.
This makes be(4) work on sun4c.
Diffstat (limited to 'sys/arch/sparc/dev')
-rw-r--r-- | sys/arch/sparc/dev/qec.c | 55 |
1 files changed, 40 insertions, 15 deletions
diff --git a/sys/arch/sparc/dev/qec.c b/sys/arch/sparc/dev/qec.c index f532682f509..d4af90d799b 100644 --- a/sys/arch/sparc/dev/qec.c +++ b/sys/arch/sparc/dev/qec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: qec.c,v 1.21 2014/07/22 10:35:35 mpi Exp $ */ +/* $OpenBSD: qec.c,v 1.22 2015/03/22 12:45:59 miod Exp $ */ /* * Copyright (c) 1998 Theo de Raadt and Jason L. Wright. @@ -58,7 +58,7 @@ int qecprint(void *, const char *); int qecmatch(struct device *, void *, void *); void qecattach(struct device *, struct device *, void *); -void qec_fix_range(struct qec_softc *, struct sbus_softc *); +int qec_fix_range(struct qec_softc *, struct sbus_softc *); void qec_translate(struct qec_softc *, struct confargs *); struct cfattach qec_ca = { @@ -138,7 +138,8 @@ qecattach(parent, self, aux) node = sc->sc_node = ca->ca_ra.ra_node; - qec_fix_range(sc, (struct sbus_softc *)parent); + if (qec_fix_range(sc, (struct sbus_softc *)parent) != 0) + return; /* * Get transfer burst size from PROM @@ -193,7 +194,7 @@ qecattach(parent, self, aux) } } -void +int qec_fix_range(sc, sbp) struct qec_softc *sc; struct sbus_softc *sbp; @@ -204,24 +205,48 @@ qec_fix_range(sc, sbp) sc->sc_range = (struct rom_range *)malloc(rlen, M_DEVBUF, M_NOWAIT); if (sc->sc_range == NULL) { - printf("%s: PROM ranges too large: %d\n", - sc->sc_dev.dv_xname, rlen); - return; + printf(": PROM ranges too large: %d\n", rlen); + return EINVAL; } sc->sc_nrange = rlen / sizeof(struct rom_range); (void)getprop(sc->sc_node, "ranges", sc->sc_range, rlen); - for (i = 0; i < sc->sc_nrange; i++) { - for (j = 0; j < sbp->sc_nrange; j++) { - if (sc->sc_range[i].pspace == sbp->sc_range[j].cspace) { - sc->sc_range[i].poffset += - sbp->sc_range[j].poffset; - sc->sc_range[i].pspace = - sbp->sc_range[j].pspace; - break; + if (sbp->sc_nrange == 0) { + /* + * Old-style SBus configuration: we need to compute the + * physical address of the board's base, in order to be + * able to compute proper physical addresses in + * qec_translate() below. + */ + struct rom_reg rr[RA_MAXREG]; + int reglen; + + reglen = getprop(sc->sc_node, "reg", rr, sizeof rr); + /* shouldn't happen */ + if (reglen <= 0 || reglen % sizeof(struct rom_reg) != 0) { + printf(": unexpected \"reg\" property layout\n"); + return EINVAL; + } + for (i = 0; i < sc->sc_nrange; i++) { + sc->sc_range[i].poffset += + sc->sc_paddr - rr[0].rr_paddr; + } + } else { + for (i = 0; i < sc->sc_nrange; i++) { + for (j = 0; j < sbp->sc_nrange; j++) { + if (sc->sc_range[i].pspace == + sbp->sc_range[j].cspace) { + sc->sc_range[i].poffset += + sbp->sc_range[j].poffset; + sc->sc_range[i].pspace = + sbp->sc_range[j].pspace; + break; + } } } } + + return 0; } /* |