- 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.
This commit is contained in:
Marius Strobl 2005-05-19 14:47:31 +00:00
parent 28629d2de8
commit 410f3d914e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=146391
2 changed files with 55 additions and 9 deletions

View file

@ -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++)

View file

@ -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