From 410f3d914ed63cf118fd9470e726cca5b444ab4e Mon Sep 17 00:00:00 2001 From: Marius Strobl Date: Thu, 19 May 2005 14:47:31 +0000 Subject: - 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. --- sys/sparc64/sbus/sbus.c | 56 ++++++++++++++++++++++++++++++++++++++-------- sys/sparc64/sbus/sbusvar.h | 8 +++++++ 2 files changed, 55 insertions(+), 9 deletions(-) (limited to 'sys/sparc64') diff --git a/sys/sparc64/sbus/sbus.c b/sys/sparc64/sbus/sbus.c index 9c5866b05016..1c245d342786 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 049fc6e1d8ed..e4f2895e261a 100644 --- a/sys/sparc64/sbus/sbusvar.h +++ b/sys/sparc64/sbus/sbusvar.h @@ -79,6 +79,12 @@ #ifndef _SPARC64_SBUS_SBUSVAR_H_ #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 */ @@ -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 -- cgit v1.2.3