summaryrefslogtreecommitdiff
path: root/sys/arch/sparc/dev/sbus.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/sparc/dev/sbus.c')
-rw-r--r--sys/arch/sparc/dev/sbus.c132
1 files changed, 91 insertions, 41 deletions
diff --git a/sys/arch/sparc/dev/sbus.c b/sys/arch/sparc/dev/sbus.c
index 77ba2349467..32e52e31533 100644
--- a/sys/arch/sparc/dev/sbus.c
+++ b/sys/arch/sparc/dev/sbus.c
@@ -1,4 +1,4 @@
-/* $NetBSD: sbus.c,v 1.6 1995/02/01 12:37:28 pk Exp $ */
+/* $NetBSD: sbus.c,v 1.10 1996/04/22 02:35:03 abrown Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -49,6 +49,7 @@
*/
#include <sys/param.h>
+#include <sys/systm.h>
#include <sys/device.h>
#include <machine/autoconf.h>
@@ -56,12 +57,19 @@
#include <sparc/dev/sbusreg.h>
#include <sparc/dev/sbusvar.h>
+int sbus_print __P((void *, char *));
+void sbusreset __P((int));
+
/* autoconfiguration driver */
void sbus_attach __P((struct device *, struct device *, void *));
int sbus_match __P((struct device *, void *, void *));
-struct cfdriver sbuscd = {
- NULL, "sbus", sbus_match, sbus_attach,
- DV_DULL, sizeof(struct sbus_softc)
+
+struct cfattach sbus_ca = {
+ sizeof(struct sbus_softc), sbus_match, sbus_attach
+};
+
+struct cfdriver sbus_cd = {
+ NULL, "sbus", DV_DULL
};
/*
@@ -92,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);
}
@@ -109,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;
@@ -131,11 +139,19 @@ sbus_attach(parent, self, aux)
sc->sc_clockfreq = getpropint(node, "clock-frequency", 25*1000*1000);
printf(": clock = %s MHz\n", clockfreq(sc->sc_clockfreq));
+ /*
+ * Get the SBus burst transfer size if burst transfers are supported
+ */
+ sc->sc_burst = getpropint(node, "burst-sizes", 0);
+
if (ra->ra_bp != NULL && strcmp(ra->ra_bp->name, "sbus") == 0)
oca.ca_ra.ra_bp = ra->ra_bp + 1;
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.
@@ -144,23 +160,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;
+ }
+ }
+ }
}
}
@@ -173,7 +226,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;
@@ -188,7 +259,7 @@ sbusreset(sbus)
int sbus;
{
register struct sbusdev *sd;
- struct sbus_softc *sc = sbuscd.cd_devs[sbus];
+ struct sbus_softc *sc = sbus_cd.cd_devs[sbus];
struct device *dev;
printf("reset %s:", sc->sc_dev.dv_xname);
@@ -200,24 +271,3 @@ sbusreset(sbus)
}
}
}
-
-/*
- * Returns true if this device is in a slave slot, so that drivers
- * can bail rather than fail.
- */
-int
-sbus_slavecheck(self, ca)
- struct device *self;
- struct confargs *ca;
-{
- int slave_only;
-
- slave_only = getpropint(findroot(), "slave-only", 8);
-
- if (slave_only & (1<<ca->ca_slot)) {
- printf("%s: slave sbus slot -- not supported\n",
- self->dv_xname);
- return (1);
- }
- return (0);
-}