summaryrefslogtreecommitdiffstats
path: root/sys/sparc64/sbus/sbus.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/sparc64/sbus/sbus.c')
-rw-r--r--sys/sparc64/sbus/sbus.c158
1 files changed, 74 insertions, 84 deletions
diff --git a/sys/sparc64/sbus/sbus.c b/sys/sparc64/sbus/sbus.c
index dbe3859..f9f78da 100644
--- a/sys/sparc64/sbus/sbus.c
+++ b/sys/sparc64/sbus/sbus.c
@@ -108,7 +108,6 @@ struct sbus_rd {
struct sbus_softc {
device_t sc_dev;
bus_dma_tag_t sc_cdmatag;
- bus_space_tag_t sc_cbustag;
int sc_clockfreq; /* clock frequency (in Hz) */
int sc_nrange;
struct sbus_rd *sc_rd;
@@ -137,9 +136,9 @@ static bus_read_ivar_t sbus_read_ivar;
static bus_get_resource_list_t sbus_get_resource_list;
static bus_setup_intr_t sbus_setup_intr;
static bus_alloc_resource_t sbus_alloc_resource;
-static bus_release_resource_t sbus_release_resource;
static bus_activate_resource_t sbus_activate_resource;
-static bus_deactivate_resource_t sbus_deactivate_resource;
+static bus_adjust_resource_t sbus_adjust_resource;
+static bus_release_resource_t sbus_release_resource;
static bus_get_dma_tag_t sbus_get_dma_tag;
static ofw_bus_get_devinfo_t sbus_get_devinfo;
@@ -153,7 +152,6 @@ static void sbus_intr_assign(void *);
static void sbus_intr_clear(void *);
static int sbus_find_intrmap(struct sbus_softc *, u_int, bus_addr_t *,
bus_addr_t *);
-static bus_space_tag_t sbus_alloc_bustag(struct sbus_softc *);
static driver_intr_t sbus_overtemp;
static driver_intr_t sbus_pwrfail;
static int sbus_print_res(struct sbus_devinfo *);
@@ -171,10 +169,11 @@ static device_method_t sbus_methods[] = {
DEVMETHOD(bus_probe_nomatch, sbus_probe_nomatch),
DEVMETHOD(bus_read_ivar, sbus_read_ivar),
DEVMETHOD(bus_alloc_resource, sbus_alloc_resource),
- DEVMETHOD(bus_activate_resource, sbus_activate_resource),
- DEVMETHOD(bus_deactivate_resource, sbus_deactivate_resource),
+ DEVMETHOD(bus_activate_resource, sbus_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_adjust_resource, sbus_adjust_resource),
DEVMETHOD(bus_release_resource, sbus_release_resource),
- DEVMETHOD(bus_setup_intr, sbus_setup_intr),
+ DEVMETHOD(bus_setup_intr, sbus_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_get_resource_list, sbus_get_resource_list),
@@ -284,7 +283,6 @@ sbus_attach(device_t dev)
if (OF_getprop(node, "interrupts", &prop, sizeof(prop)) == -1)
panic("%s: cannot get IGN", __func__);
sc->sc_ign = INTIGN(prop);
- sc->sc_cbustag = sbus_alloc_bustag(sc);
/*
* Record clock frequency for synchronous SCSI.
@@ -343,7 +341,6 @@ sbus_attach(device_t dev)
sc->sc_burst =
(SBUS_BURST64_DEF << SBUS_BURST64_SHIFT) | SBUS_BURST_DEF;
-
/* initalise the IOMMU */
/* punch in our copies */
@@ -375,7 +372,7 @@ sbus_attach(device_t dev)
sc->sc_cdmatag->dt_cookie = &sc->sc_is;
sc->sc_cdmatag->dt_mt = &iommu_dma_methods;
- /*
+ /*
* Hunt through all the interrupt mapping regs and register our
* interrupt controller for the corresponding interrupt vectors.
* We do this early in order to be able to catch stray interrupts.
@@ -701,12 +698,12 @@ sbus_setup_intr(device_t dev, device_t child, struct resource *ires, int flags,
/*
* Make sure the vector is fully specified and we registered
* our interrupt controller for it.
- */
+ */
vec = rman_get_start(ires);
if (INTIGN(vec) != sc->sc_ign || intr_vectors[vec].iv_ic != &sbus_ic) {
device_printf(dev, "invalid interrupt vector 0x%lx\n", vec);
- return (EINVAL);
- }
+ return (EINVAL);
+ }
return (bus_generic_setup_intr(dev, child, ires, flags, filt, intr,
arg, cookiep));
}
@@ -721,14 +718,12 @@ sbus_alloc_resource(device_t bus, device_t child, int type, int *rid,
struct resource_list *rl;
struct resource_list_entry *rle;
device_t schild;
- bus_space_handle_t bh;
bus_addr_t toffs;
bus_size_t tend;
int i, slot;
- int isdefault, needactivate, passthrough;
+ int isdefault, passthrough;
isdefault = (start == 0UL && end == ~0UL);
- needactivate = flags & RF_ACTIVE;
passthrough = (device_get_parent(child) != bus);
rle = NULL;
sc = device_get_softc(bus);
@@ -751,7 +746,6 @@ sbus_alloc_resource(device_t bus, device_t child, int type, int *rid,
}
}
rm = NULL;
- bh = toffs = tend = 0;
schild = child;
while (device_get_parent(schild) != bus)
schild = device_get_parent(schild);
@@ -768,24 +762,21 @@ sbus_alloc_resource(device_t bus, device_t child, int type, int *rid,
toffs = start - sc->sc_rd[i].rd_coffset;
tend = end - sc->sc_rd[i].rd_coffset;
rm = &sc->sc_rd[i].rd_rman;
- bh = sc->sc_rd[i].rd_bushandle;
break;
}
if (rm == NULL)
return (NULL);
- flags &= ~RF_ACTIVE;
- rv = rman_reserve_resource(rm, toffs, tend, count, flags,
- child);
+
+ rv = rman_reserve_resource(rm, toffs, tend, count, flags &
+ ~RF_ACTIVE, child);
if (rv == NULL)
return (NULL);
rman_set_rid(rv, *rid);
- rman_set_bustag(rv, sc->sc_cbustag);
- rman_set_bushandle(rv, bh + rman_get_start(rv));
- if (needactivate) {
- if (bus_activate_resource(child, type, *rid, rv)) {
- rman_release_resource(rv);
- return (NULL);
- }
+
+ if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child,
+ type, *rid, rv)) {
+ rman_release_resource(rv);
+ return (NULL);
}
if (!passthrough)
rle->res = rv;
@@ -799,41 +790,53 @@ static int
sbus_activate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
- void *p;
- int error;
+ struct sbus_softc *sc;
+ struct bus_space_tag *tag;
+ int i;
- if (type == SYS_RES_IRQ) {
- return (BUS_ACTIVATE_RESOURCE(device_get_parent(bus),
- child, type, rid, r));
- }
- if (type == SYS_RES_MEMORY) {
- /*
- * Need to memory-map the device space, as some drivers
- * depend on the virtual address being set and usable.
- */
- error = sparc64_bus_mem_map(rman_get_bustag(r),
- rman_get_bushandle(r), rman_get_size(r), 0, 0, &p);
- if (error != 0)
- return (error);
- rman_set_virtual(r, p);
+ switch (type) {
+ case SYS_RES_IRQ:
+ return (bus_generic_activate_resource(bus, child, type, rid,
+ r));
+ case SYS_RES_MEMORY:
+ sc = device_get_softc(bus);
+ for (i = 0; i < sc->sc_nrange; i++) {
+ if (rman_is_region_manager(r,
+ &sc->sc_rd[i].rd_rman) != 0) {
+ tag = sparc64_alloc_bus_tag(r,
+ rman_get_bustag(sc->sc_sysio_res),
+ SBUS_BUS_SPACE, NULL);
+ if (tag == NULL)
+ return (ENOMEM);
+ rman_set_bustag(r, tag);
+ rman_set_bushandle(r,
+ sc->sc_rd[i].rd_bushandle +
+ rman_get_start(r));
+ return (rman_activate_resource(r));
+ }
+ }
+ /* FALLTHROUGH */
+ default:
+ return (EINVAL);
}
- return (rman_activate_resource(r));
}
static int
-sbus_deactivate_resource(device_t bus, device_t child, int type, int rid,
- struct resource *r)
+sbus_adjust_resource(device_t bus, device_t child, int type,
+ struct resource *r, u_long start, u_long end)
{
+ struct sbus_softc *sc;
+ int i;
- if (type == SYS_RES_IRQ) {
- return (BUS_DEACTIVATE_RESOURCE(device_get_parent(bus),
- child, type, rid, r));
- }
if (type == SYS_RES_MEMORY) {
- sparc64_bus_mem_unmap(rman_get_virtual(r), rman_get_size(r));
- rman_set_virtual(r, NULL);
+ sc = device_get_softc(bus);
+ for (i = 0; i < sc->sc_nrange; i++)
+ if (rman_is_region_manager(r,
+ &sc->sc_rd[i].rd_rman) != 0)
+ return (rman_adjust_resource(r, start, end));
+ return (EINVAL);
}
- return (rman_deactivate_resource(r));
+ return (bus_generic_adjust_resource(bus, child, type, r, start, end));
}
static int
@@ -846,23 +849,26 @@ sbus_release_resource(device_t bus, device_t child, int type, int rid,
passthrough = (device_get_parent(child) != bus);
rl = BUS_GET_RESOURCE_LIST(bus, child);
- if (type == SYS_RES_IRQ)
- return (resource_list_release(rl, bus, child, type, rid, r));
- if ((rman_get_flags(r) & RF_ACTIVE) != 0) {
- error = bus_deactivate_resource(child, type, rid, r);
+ if (type == SYS_RES_MEMORY) {
+ if ((rman_get_flags(r) & RF_ACTIVE) != 0) {
+ error = bus_deactivate_resource(child, type, rid, r);
+ if (error)
+ return (error);
+ }
+ error = rman_release_resource(r);
if (error != 0)
return (error);
+ if (!passthrough) {
+ rle = resource_list_find(rl, type, rid);
+ KASSERT(rle != NULL,
+ ("%s: resource entry not found!", __func__));
+ KASSERT(rle->res != NULL,
+ ("%s: resource entry is not busy", __func__));
+ rle->res = NULL;
+ }
+ return (0);
}
- error = rman_release_resource(r);
- if (error != 0 || passthrough)
- return (error);
- rle = resource_list_find(rl, type, rid);
- if (rle == NULL)
- panic("%s: cannot find resource", __func__);
- if (rle->res == NULL)
- panic("%s: resource entry is not busy", __func__);
- rle->res = NULL;
- return (0);
+ return (resource_list_release(rl, bus, child, type, rid, r));
}
static bus_dma_tag_t
@@ -918,22 +924,6 @@ sbus_pwrfail(void *arg)
shutdown_nice(0);
}
-static bus_space_tag_t
-sbus_alloc_bustag(struct sbus_softc *sc)
-{
- bus_space_tag_t sbt;
-
- sbt = (bus_space_tag_t)malloc(sizeof(struct bus_space_tag), M_DEVBUF,
- M_NOWAIT | M_ZERO);
- if (sbt == NULL)
- panic("%s: out of memory", __func__);
-
- sbt->bst_cookie = sc;
- sbt->bst_parent = rman_get_bustag(sc->sc_sysio_res);
- sbt->bst_type = SBUS_BUS_SPACE;
- return (sbt);
-}
-
static int
sbus_print_res(struct sbus_devinfo *sdi)
{
OpenPOWER on IntegriCloud