summaryrefslogtreecommitdiff
path: root/sys/arch/sparc64/dev
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2005-03-05 01:44:53 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2005-03-05 01:44:53 +0000
commitcb4e539861dbd56824e1bc742c6914bee17d1b2e (patch)
tree828f19cfd1a2b7fc8489b8644235decd3068f55d /sys/arch/sparc64/dev
parenta4385619703fa827222d5c66f6db70c70b021412 (diff)
Preliminary xbox support: attaches, memory mapping and interrupts work, but
DMA transfers are not implemented yet, and are disabled (which causes drivers to SBus cards on the xbox to fail to attach). In practice, this allows frame buffers to work, maybe more devices; DMA support will be worked on in the near future.
Diffstat (limited to 'sys/arch/sparc64/dev')
-rw-r--r--sys/arch/sparc64/dev/sbus.c170
-rw-r--r--sys/arch/sparc64/dev/sbusvar.h3
2 files changed, 121 insertions, 52 deletions
diff --git a/sys/arch/sparc64/dev/sbus.c b/sys/arch/sparc64/dev/sbus.c
index df871d30ff6..18c1932ca65 100644
--- a/sys/arch/sparc64/dev/sbus.c
+++ b/sys/arch/sparc64/dev/sbus.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sbus.c,v 1.21 2005/01/27 21:17:50 miod Exp $ */
+/* $OpenBSD: sbus.c,v 1.22 2005/03/05 01:44:52 miod Exp $ */
/* $NetBSD: sbus.c,v 1.46 2001/10/07 20:30:41 eeh Exp $ */
/*-
@@ -118,6 +118,7 @@
#include <sparc64/dev/iommuvar.h>
#include <sparc64/dev/sbusreg.h>
#include <dev/sbus/sbusvar.h>
+#include <dev/sbus/xboxvar.h>
#include <uvm/uvm_extern.h>
@@ -136,32 +137,37 @@ int sbus_debug = 0;
void sbusreset(int);
-static bus_space_tag_t sbus_alloc_bustag(struct sbus_softc *);
-static bus_dma_tag_t sbus_alloc_dmatag(struct sbus_softc *);
-static int sbus_get_intr(struct sbus_softc *, int,
+bus_space_tag_t sbus_alloc_bustag(struct sbus_softc *, int);
+bus_dma_tag_t sbus_alloc_dmatag(struct sbus_softc *, bus_dma_tag_t);
+int sbus_get_intr(struct sbus_softc *, int,
struct sbus_intr **, int *, int);
-static int sbus_overtemp(void *);
-static int _sbus_bus_map(bus_space_tag_t, bus_space_tag_t,
+int sbus_overtemp(void *);
+int _sbus_bus_map(bus_space_tag_t, bus_space_tag_t,
bus_addr_t, /*offset*/
bus_size_t, /*size*/
int, /*flags*/
bus_space_handle_t *);
-static void *sbus_intr_establish(bus_space_tag_t, bus_space_tag_t,
+void *sbus_intr_establish(bus_space_tag_t, bus_space_tag_t,
int, /*Sbus interrupt level*/
int, /*`device class' priority*/
int, /*flags*/
int (*)(void *), /*handler*/
void *, /*handler arg*/
const char *); /*what*/
-
+void sbus_attach_common(struct sbus_softc *, int, int);
/* autoconfiguration driver */
-int sbus_match(struct device *, void *, void *);
-void sbus_attach(struct device *, struct device *, void *);
+void sbus_mb_attach(struct device *, struct device *, void *);
+void sbus_xbox_attach(struct device *, struct device *, void *);
+int sbus_mb_match(struct device *, void *, void *);
+int sbus_xbox_match(struct device *, void *, void *);
+struct cfattach sbus_mb_ca = {
+ sizeof(struct sbus_softc), sbus_mb_match, sbus_mb_attach
+};
-struct cfattach sbus_ca = {
- sizeof(struct sbus_softc), sbus_match, sbus_attach
+struct cfattach sbus_xbox_ca = {
+ sizeof(struct sbus_softc), sbus_xbox_match, sbus_xbox_attach
};
struct cfdriver sbus_cd = {
@@ -232,7 +238,7 @@ sbus_print(void *args, const char *busname)
}
int
-sbus_match(struct device *parent, void *vcf, void *aux)
+sbus_mb_match(struct device *parent, void *vcf, void *aux)
{
struct cfdata *cf = vcf;
struct mainbus_attach_args *ma = aux;
@@ -240,35 +246,39 @@ sbus_match(struct device *parent, void *vcf, void *aux)
return (strcmp(cf->cf_driver->cd_name, ma->ma_name) == 0);
}
-/*
- * Attach an Sbus.
- */
+int
+sbus_xbox_match(struct device *parent, void *vcf, void *aux)
+{
+ struct xbox_softc *xsc = (struct xbox_softc *)parent;
+
+ /* Prevent multiple attachments */
+ if (xsc->sc_attached == 0) {
+ xsc->sc_attached = 1;
+ return (1);
+ }
+
+ return (0);
+}
+
void
-sbus_attach(struct device *parent, struct device *self, void *aux)
+sbus_xbox_attach(struct device *parent, struct device *self, void *aux)
{
struct sbus_softc *sc = (struct sbus_softc *)self;
- struct mainbus_attach_args *ma = aux;
- struct intrhand *ih;
- struct sysioreg *sysio;
- int ipl;
- char *name;
- int node = ma->ma_node;
- int node0, error;
- bus_space_tag_t sbt;
- struct sbus_attach_args sa;
+ struct xbox_softc *xsc = (struct xbox_softc *)parent;
+ struct sbus_softc *sbus = (struct sbus_softc *)parent->dv_parent;
+ struct xbox_attach_args *xa = aux;
+ int node = xa->xa_node;
- sc->sc_bustag = ma->ma_bustag;
- sc->sc_dmatag = ma->ma_dmatag;
- /* Find interrupt group no */
- sc->sc_ign = ma->ma_interrupts[0] & INTMAP_IGN;
+ sc->sc_master = sbus->sc_master;
- bus_space_map(sc->sc_bustag,
- ma->ma_address[0], sizeof(struct sysioreg),
- BUS_SPACE_MAP_PROMADDRESS, &sc->sc_bh);
- sysio = bus_space_vaddr(sc->sc_bustag, sc->sc_bh);
+ sc->sc_bustag = xa->xa_bustag;
+ sc->sc_dmatag = sbus_alloc_dmatag(sc, xa->xa_dmatag);
- /* Setup interrupt translation tables */
- sc->sc_intr2ipl = intr_sbus2ipl_4u;
+ /*
+ * Parent has already done the address translation computations.
+ */
+ sc->sc_nrange = xsc->sc_nrange;
+ sc->sc_range = xsc->sc_range;
/*
* Record clock frequency for synchronous SCSI.
@@ -277,13 +287,26 @@ sbus_attach(struct device *parent, struct device *self, void *aux)
sc->sc_clockfreq = getpropint(node, "clock-frequency", 25*1000*1000);
printf(": clock = %s MHz\n", clockfreq(sc->sc_clockfreq));
- sbt = sbus_alloc_bustag(sc);
- sc->sc_dmatag = sbus_alloc_dmatag(sc);
+ sbus_attach_common(sc, node, 1);
+}
- /*
- * Get the SBus burst transfer size if burst transfers are supported
- */
- sc->sc_burst = getpropint(node, "burst-sizes", 0);
+void
+sbus_mb_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct sbus_softc *sc = (struct sbus_softc *)self;
+ struct mainbus_attach_args *ma = aux;
+ int node = ma->ma_node;
+ struct intrhand *ih;
+ int ipl, error;
+ struct sysioreg *sysio;
+ char *name;
+
+ sc->sc_master = sc;
+
+ sc->sc_bustag = ma->ma_bustag;
+
+ /* Find interrupt group no */
+ sc->sc_ign = ma->ma_interrupts[0] & INTMAP_IGN;
/*
* Collect address translations from the OBP.
@@ -293,6 +316,18 @@ sbus_attach(struct device *parent, struct device *self, void *aux)
if (error)
panic("%s: error getting ranges property", sc->sc_dev.dv_xname);
+ /*
+ * Record clock frequency for synchronous SCSI.
+ * IS THIS THE CORRECT DEFAULT??
+ */
+ sc->sc_clockfreq = getpropint(node, "clock-frequency", 25*1000*1000);
+ printf(": clock = %s MHz\n", clockfreq(sc->sc_clockfreq));
+
+ bus_space_map(sc->sc_bustag,
+ ma->ma_address[0], sizeof(struct sysioreg),
+ BUS_SPACE_MAP_PROMADDRESS, &sc->sc_bh);
+ sysio = bus_space_vaddr(sc->sc_bustag, sc->sc_bh);
+
/* initialize the IOMMU */
/* punch in our copies */
@@ -351,6 +386,31 @@ sbus_attach(struct device *parent, struct device *self, void *aux)
panic("sbus iommu: can't toss first dvma page");
}
+ sc->sc_dmatag = sbus_alloc_dmatag(sc, ma->ma_dmatag);
+
+ sbus_attach_common(sc, node, 0);
+}
+
+/*
+ * Attach an Sbus (main part).
+ */
+void
+sbus_attach_common(struct sbus_softc *sc, int node, int indirect)
+{
+ bus_space_tag_t sbt;
+ struct sbus_attach_args sa;
+ int node0;
+
+ /* Setup interrupt translation tables */
+ sc->sc_intr2ipl = intr_sbus2ipl_4u;
+
+ sbt = sbus_alloc_bustag(sc, indirect);
+
+ /*
+ * Get the SBus burst transfer size if burst transfers are supported
+ */
+ sc->sc_burst = getpropint(node, "burst-sizes", 0);
+
/*
* Loop through ROM children, fixing any relative addresses
* and then configuring each device.
@@ -512,7 +572,7 @@ sbus_establish(struct sbusdev *sd, struct device *dev)
* 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.
+ * sbus, since we support multiple sbus's.
*/
for (curdev = dev->dv_parent; ; curdev = curdev->dv_parent) {
if (!curdev || !curdev->dv_xname)
@@ -657,6 +717,9 @@ sbus_intr_establish(bus_space_tag_t t, bus_space_tag_t t0, int pri, int level,
int ipl;
long vec = pri;
+ /* Pick the master SBus as all do not have IOMMU registers */
+ sc = sc->sc_master;
+
sysio = bus_space_vaddr(sc->sc_bustag, sc->sc_bh);
if ((flags & BUS_INTR_ESTABLISH_SOFTINTR) != 0)
@@ -760,8 +823,8 @@ sbus_intr_establish(bus_space_tag_t t, bus_space_tag_t t0, int pri, int level,
return (ih);
}
-static bus_space_tag_t
-sbus_alloc_bustag(struct sbus_softc *sc)
+bus_space_tag_t
+sbus_alloc_bustag(struct sbus_softc *sc, int indirect)
{
struct sparc_bus_space_tag *sbt;
@@ -773,7 +836,10 @@ sbus_alloc_bustag(struct sbus_softc *sc)
snprintf(sbt->name, sizeof(sbt->name), "%s",
sc->sc_dev.dv_xname);
sbt->cookie = sc;
- sbt->parent = sc->sc_bustag;
+ if (indirect)
+ sbt->parent = sc->sc_bustag->parent;
+ else
+ sbt->parent = sc->sc_bustag;
sbt->default_type = SBUS_BUS_SPACE;
sbt->asi = ASI_PRIMARY;
sbt->sasi = ASI_PRIMARY;
@@ -784,10 +850,10 @@ sbus_alloc_bustag(struct sbus_softc *sc)
}
-static bus_dma_tag_t
-sbus_alloc_dmatag(struct sbus_softc *sc)
+bus_dma_tag_t
+sbus_alloc_dmatag(struct sbus_softc *sc, bus_dma_tag_t psdt)
{
- bus_dma_tag_t sdt, psdt = sc->sc_dmatag;
+ bus_dma_tag_t sdt;
sdt = (bus_dma_tag_t)
malloc(sizeof(struct sparc_bus_dma_tag), M_DEVBUF, M_NOWAIT);
@@ -807,7 +873,6 @@ sbus_alloc_dmatag(struct sbus_softc *sc)
sdt->_dmamem_free = iommu_dvmamem_free;
sdt->_dmamem_map = iommu_dvmamem_map;
sdt->_dmamem_unmap = iommu_dvmamem_unmap;
- sc->sc_dmatag = sdt;
return (sdt);
}
@@ -818,7 +883,10 @@ sbus_dmamap_create(bus_dma_tag_t t, bus_dma_tag_t t0, bus_size_t size,
{
struct sbus_softc *sc = t->_cookie;
+ /* Disallow DMA on secondary SBuses for now */
+ if (sc != sc->sc_master)
+ return (EINVAL);
+
return (iommu_dvmamap_create(t, t0, &sc->sc_sb, size, nsegments,
maxsegsz, boundary, flags, dmamp));
}
-
diff --git a/sys/arch/sparc64/dev/sbusvar.h b/sys/arch/sparc64/dev/sbusvar.h
index f05ea6d05eb..cb3715c76a6 100644
--- a/sys/arch/sparc64/dev/sbusvar.h
+++ b/sys/arch/sparc64/dev/sbusvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sbusvar.h,v 1.6 2003/06/02 23:27:55 millert Exp $ */
+/* $OpenBSD: sbusvar.h,v 1.7 2005/03/05 01:44:52 miod Exp $ */
/* $NetBSD: sbusvar.h,v 1.7 1999/06/05 05:30:43 mrg Exp $ */
/*-
@@ -111,6 +111,7 @@ struct sbus_softc {
struct iommu_state sc_is; /* IOMMU state, see iommureg.h */
struct strbuf_ctl sc_sb; /* Streaming buffer control */
int64_t sc_flush; /* Streaming buffer flush */
+ struct sbus_softc *sc_master; /* main SBus */
};
bus_addr_t sbus_bus_addr(bus_space_tag_t, u_int, u_int);