diff options
author | marius <marius@FreeBSD.org> | 2005-05-19 14:47:31 +0000 |
---|---|---|
committer | marius <marius@FreeBSD.org> | 2005-05-19 14:47:31 +0000 |
commit | 3aa0c43ebd643f73a0e5c127330cb85cd4540265 (patch) | |
tree | e5e0cd80c60db7a7a4ad0201be42672b21b10acc /sys/sparc64 | |
parent | 2c7980531b11c0f49441c47b1a5de78331694ed1 (diff) | |
download | FreeBSD-src-3aa0c43ebd643f73a0e5c127330cb85cd4540265.zip FreeBSD-src-3aa0c43ebd643f73a0e5c127330cb85cd4540265.tar.gz |
- Add an IVAR for retrieving the interrupt group number of the parent Sbus
device and which also applies to the children. This is very usefull for
drivers for the various subordinate busses so they don't need to fiddle
with the OFW node of their parent themselves. As SBus busses hang of the
nexus and we don't use the ofw_bus interface for nexus devices, yet, this
would also require special knowledge about this in the drivers for the
SBus children which these shouldn't need to have.
This includes switching to use an unshifted IGN in the sc_ign member of
the sbus(4) softc internally.
- For SBus child devices where there are variants that are actually split
split into two SBus devices (as opposed to the first half of the device
being a SBus device and the second half hanging off of the first one)
like 'auxio' and 'SUNW,fdtwo' or 'dma' and 'esp' probe the SBus device
which is a prerequisite to the driver attaching to the second one with
a lower order. This saves us from dealing with different probe orders
in the respective device drivers which generally is more hackish.
- Remove a stale comment about the 'specials' array above the attaching
of the child devices. This is a remnant of the NetBSD/sparc origin of
this code. There the 'specials' array is also used to probe certain
devices which are prerequisites to others first. Why NetBSD soley
relies on the devices having the expected order in the OFW tree on
sparc64 isn't clear to me, as far as I can tell OFW doesn't guaranteed
such things.
Diffstat (limited to 'sys/sparc64')
-rw-r--r-- | sys/sparc64/sbus/sbus.c | 56 | ||||
-rw-r--r-- | sys/sparc64/sbus/sbusvar.h | 8 |
2 files changed, 55 insertions, 9 deletions
diff --git a/sys/sparc64/sbus/sbus.c b/sys/sparc64/sbus/sbus.c index 9c5866b..1c245d3 100644 --- a/sys/sparc64/sbus/sbus.c +++ b/sys/sparc64/sbus/sbus.c @@ -212,6 +212,7 @@ static ofw_bus_get_name_t sbus_get_name; static ofw_bus_get_node_t sbus_get_node; static ofw_bus_get_type_t sbus_get_type; +static int sbus_inlist(const char *, const char **); static struct sbus_devinfo * sbus_setup_dinfo(struct sbus_softc *sc, phandle_t node, char *name); static void sbus_destroy_dinfo(struct sbus_devinfo *dinfo); @@ -261,6 +262,26 @@ DRIVER_MODULE(sbus, nexus, sbus_driver, sbus_devclass, 0, 0); #define OFW_SBUS_TYPE "sbus" #define OFW_SBUS_NAME "sbus" +static const char *sbus_order_first[] = { + "auxio", + "dma", + NULL +}; + +static int +sbus_inlist(const char *name, const char **list) +{ + int i; + + if (name == NULL) + return (0); + for (i = 0; list[i] != NULL; i++) { + if (strcmp(name, list[i]) == 0) + return (1); + } + return (0); +} + static int sbus_probe(device_t dev) { @@ -311,7 +332,7 @@ sbus_attach(device_t dev) if (OF_getprop(node, "interrupts", &intr, sizeof(intr)) == -1) panic("%s: cannot get IGN", __func__); - sc->sc_ign = intr & INTMAP_IGN_MASK; /* Find interrupt group no */ + sc->sc_ign = (intr & INTMAP_IGN_MASK) >> INTMAP_IGN_SHIFT; sc->sc_cbustag = sbus_alloc_bustag(sc); /* @@ -433,8 +454,6 @@ sbus_attach(device_t dev) /* * Loop through ROM children, fixing any relative addresses * and then configuring each device. - * `specials' is an array of device names that are treated - * specially: */ for (child = OF_child(node); child != 0; child = OF_peer(child)) { if ((OF_getprop_alloc(child, "name", 1, (void **)&cname)) == -1) @@ -445,8 +464,22 @@ sbus_attach(device_t dev) free(cname, M_OFWPROP); continue; } - if ((cdev = device_add_child(dev, NULL, -1)) == NULL) - panic("%s: device_add_child failed", __func__); + /* + * For devices where there are variants that are actually + * split into two SBus devices (as opposed to the first + * half of the device being a SBus device and the second + * half hanging off of the first one) like 'auxio' and + * 'SUNW,fdtwo' or 'dma' and 'esp' probe the SBus device + * which is a prerequisite to the driver attaching to the + * second one with a lower order. Saves us from dealing + * with different probe orders in the respective device + * drivers which generally is more hackish. + */ + cdev = device_add_child_ordered(dev, (OF_child(child) == 0 && + sbus_inlist(cname, sbus_order_first)) ? SBUS_ORDER_FIRST : + SBUS_ORDER_NORMAL, NULL, -1); + if (cdev == NULL) + panic("%s: device_add_child_ordered failed", __func__); device_set_ivars(cdev, sdi); } return (bus_generic_attach(dev)); @@ -511,7 +544,7 @@ sbus_setup_dinfo(struct sbus_softc *sc, phandle_t node, char *name) if ((iv & INTMAP_OBIO_MASK) == 0) iv |= slot << 3; /* Set the ign as appropriate. */ - iv |= sc->sc_ign; + iv |= sc->sc_ign << INTMAP_IGN_SHIFT; resource_list_add(&sdi->sdi_rl, SYS_RES_IRQ, i, iv, iv, 1); } @@ -578,8 +611,10 @@ sbus_probe_nomatch(device_t dev, device_t child) static int sbus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) { + struct sbus_softc *sc; struct sbus_devinfo *dinfo; + sc = device_get_softc(dev); if ((dinfo = device_get_ivars(child)) == NULL) return (ENOENT); switch (which) { @@ -589,13 +624,16 @@ sbus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) case SBUS_IVAR_CLOCKFREQ: *result = dinfo->sdi_clockfreq; break; + case SBUS_IVAR_IGN: + *result = sc->sc_ign; + break; case SBUS_IVAR_SLOT: *result = dinfo->sdi_slot; break; default: return (ENOENT); } - return 0; + return (0); } static struct resource_list * @@ -647,11 +685,11 @@ sbus_setup_intr(device_t dev, device_t child, struct resource *ires, int flags, intrclrptr = SBR_SLOT0_INT_CLR + (slot * 8 * 8) + (INTPRI(vec) * 8); /* Enable the interrupt, insert IGN. */ - intrmap = inr | sc->sc_ign; + intrmap = inr | (sc->sc_ign << INTMAP_IGN_SHIFT); } else { intrptr = SBR_SCSI_INT_MAP; /* Insert IGN */ - inr |= sc->sc_ign; + inr |= sc->sc_ign << INTMAP_IGN_SHIFT; for (i = 0; intrptr <= SBR_RESERVED_INT_MAP && INTVEC(intrmap = SYSIO_READ8(sc, intrptr)) != INTVEC(inr); intrptr += 8, i++) diff --git a/sys/sparc64/sbus/sbusvar.h b/sys/sparc64/sbus/sbusvar.h index 049fc6e..e4f2895 100644 --- a/sys/sparc64/sbus/sbusvar.h +++ b/sys/sparc64/sbus/sbusvar.h @@ -80,6 +80,12 @@ #define _SPARC64_SBUS_SBUSVAR_H_ /* + * Macros for probe order + */ +#define SBUS_ORDER_FIRST 10 +#define SBUS_ORDER_NORMAL 20 + +/* * PROM-reported DMA burst sizes for the SBus */ #define SBUS_BURST_1 0x1 @@ -98,6 +104,7 @@ enum sbus_device_ivars { SBUS_IVAR_BURSTSZ, SBUS_IVAR_CLOCKFREQ, + SBUS_IVAR_IGN, SBUS_IVAR_SLOT, }; @@ -109,6 +116,7 @@ enum sbus_device_ivars { SBUS_ACCESSOR(burstsz, BURSTSZ, int) SBUS_ACCESSOR(clockfreq, CLOCKFREQ, int) +SBUS_ACCESSOR(ign, IGN, int) SBUS_ACCESSOR(slot, SLOT, int) #undef SBUS_ACCESSOR |