Add sbus_translate() to deal with slot address translations, including

new v3 PROM style "range" properties. This routine is also called from obio.c
(which can be viewed upon as just a another Sbus slot).
This commit is contained in:
pk 1996-03-31 22:27:15 +00:00
parent 345295ff08
commit 96f175d477

View File

@ -1,4 +1,4 @@
/* $NetBSD: sbus.c,v 1.8 1996/03/17 02:01:14 thorpej Exp $ */
/* $NetBSD: sbus.c,v 1.9 1996/03/31 22:27:15 pk Exp $ */
/*
* Copyright (c) 1992, 1993
@ -100,8 +100,9 @@ sbus_match(parent, vcf, aux)
register struct confargs *ca = aux;
register struct romaux *ra = &ca->ca_ra;
if (cputyp==CPU_SUN4)
if (CPU_ISSUN4)
return (0);
return (strcmp(cf->cf_driver->cd_name, ra->ra_name) == 0);
}
@ -117,8 +118,7 @@ sbus_attach(parent, self, aux)
register struct sbus_softc *sc = (struct sbus_softc *)self;
struct confargs *ca = aux;
register struct romaux *ra = &ca->ca_ra;
register int base, node, slot;
register int i;
register int node;
register char *name;
struct confargs oca;
@ -144,6 +144,9 @@ sbus_attach(parent, self, aux)
else
oca.ca_ra.ra_bp = NULL;
sc->sc_range = ra->ra_range;
sc->sc_nrange = ra->ra_nrange;
/*
* Loop through ROM children, fixing any relative addresses
* and then configuring each device.
@ -152,23 +155,60 @@ sbus_attach(parent, self, aux)
name = getpropstring(node, "name");
if (!romprop(&oca.ca_ra, name, node))
continue;
base = (int)oca.ca_ra.ra_paddr;
sbus_translate(self, &oca);
oca.ca_bustype = BUS_SBUS;
(void) config_found(&sc->sc_dev, (void *)&oca, sbus_print);
}
}
void
sbus_translate(dev, ca)
struct device *dev;
struct confargs *ca;
{
struct sbus_softc *sc = (struct sbus_softc *)dev;
register int base, slot;
register int i;
if (sc->sc_nrange == 0) {
/* Old-style Sbus configuration */
base = (int)ca->ca_ra.ra_paddr;
if (SBUS_ABS(base)) {
oca.ca_slot = SBUS_ABS_TO_SLOT(base);
oca.ca_offset = SBUS_ABS_TO_OFFSET(base);
ca->ca_slot = SBUS_ABS_TO_SLOT(base);
ca->ca_offset = SBUS_ABS_TO_OFFSET(base);
} else {
oca.ca_slot = slot = oca.ca_ra.ra_iospace;
oca.ca_offset = base;
oca.ca_ra.ra_paddr = (void *)SBUS_ADDR(slot, base);
ca->ca_slot = slot = ca->ca_ra.ra_iospace;
ca->ca_offset = base;
ca->ca_ra.ra_paddr =
(void *)SBUS_ADDR(slot, base);
/* Fix any remaining register banks */
for (i = 1; i < oca.ca_ra.ra_nreg; i++) {
base = (int)oca.ca_ra.ra_reg[i].rr_paddr;
oca.ca_ra.ra_reg[i].rr_paddr =
for (i = 1; i < ca->ca_ra.ra_nreg; i++) {
base = (int)ca->ca_ra.ra_reg[i].rr_paddr;
ca->ca_ra.ra_reg[i].rr_paddr =
(void *)SBUS_ADDR(slot, base);
}
}
oca.ca_bustype = BUS_SBUS;
(void) config_found(&sc->sc_dev, (void *)&oca, sbus_print);
} else {
ca->ca_slot = ca->ca_ra.ra_iospace;
ca->ca_offset = (int)ca->ca_ra.ra_paddr;
/* Translate into parent address spaces */
for (i = 0; i < ca->ca_ra.ra_nreg; i++) {
int j, cspace = ca->ca_ra.ra_reg[i].rr_iospace;
for (j = 0; j < sc->sc_nrange; j++) {
if (sc->sc_range[j].cspace == cspace) {
(int)ca->ca_ra.ra_reg[i].rr_paddr +=
sc->sc_range[j].poffset;
(int)ca->ca_ra.ra_reg[i].rr_iospace =
sc->sc_range[j].pspace;
break;
}
}
}
}
}
@ -181,7 +221,25 @@ sbus_establish(sd, dev)
register struct sbusdev *sd;
register struct device *dev;
{
register struct sbus_softc *sc = (struct sbus_softc *)dev->dv_parent;
register struct sbus_softc *sc;
register struct device *curdev;
/*
* We have to look for the sbus by name, since it is not necessarily
* our immediate parent (i.e. sun4m /iommu/sbus/espdma/esp)
* We don't just use the device structure of the above-attached
* sbus, since we might (in the future) support multiple sbus's.
*/
for (curdev = dev->dv_parent; ; curdev = curdev->dv_parent) {
if (!curdev || !curdev->dv_xname)
panic("sbus_establish: can't find sbus parent for %s",
(sd->sd_dev->dv_xname ? sd->sd_dev->dv_xname :
"<unknown>"));
if (strncmp(curdev->dv_xname, "sbus", 4) == 0)
break;
}
sc = (struct sbus_softc *) curdev;
sd->sd_dev = dev;
sd->sd_bchain = sc->sc_sbdev;