PERFORCE change 94869 for review
John-Mark Gurney
jmg at FreeBSD.org
Sun Apr 9 21:00:05 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=94869
Change 94869 by jmg at jmg_carbon-60 on 2006/04/09 20:59:06
first attempt at reorginizing the nexus.. this makes devhandle an
ivar, instead of having children pull it from RES_MEMORY, and this
also sets up all the interrupts as resources from interrupt-map..
They are indexed by rid on the child, and return the parent's
interrupt #...
vnex will need to be updated, and I'll do this shortly...
also teach hv_pci to pass through interrupt's to the layer, this
could get pci ints working..
Affected files ...
.. //depot/projects/kmacy_sun4v/src/sys/sun4v/include/hv_pcivar.h#7 edit
.. //depot/projects/kmacy_sun4v/src/sys/sun4v/include/nexusvar.h#3 edit
.. //depot/projects/kmacy_sun4v/src/sys/sun4v/sun4v/hv_pci.c#30 edit
.. //depot/projects/kmacy_sun4v/src/sys/sun4v/sun4v/nexus.c#4 edit
Differences ...
==== //depot/projects/kmacy_sun4v/src/sys/sun4v/include/hv_pcivar.h#7 (text+ko) ====
@@ -36,8 +36,7 @@
struct bus_dma_tag hs_dmatag;
- struct resource *hs_intr;
- void *hs_intrcookie;
+ struct resource *hs_intr[4];
struct rman hs_pci_intr_rman;
==== //depot/projects/kmacy_sun4v/src/sys/sun4v/include/nexusvar.h#3 (text+ko) ====
@@ -30,6 +30,15 @@
extern struct bus_dma_tag nexus_dmatag;
-#endif /* _MACHINE_NEXUSVAR_H_ */
+enum nexus_ivars {
+ NEXUS_IVAR_DEVHANDLE,
+};
+
+#define NEXUS_ACCESSOR(var, ivar, type) \
+ __BUS_ACCESSOR(nexus, var, NEXUS, ivar, type)
+NEXUS_ACCESSOR(devhandle, DEVHANDLE, uint64_t)
+#undef NEXUS_ACCESSOR
+
+#endif /* _MACHINE_NEXUSVAR_H_ */
==== //depot/projects/kmacy_sun4v/src/sys/sun4v/sun4v/hv_pci.c#30 (text+ko) ====
@@ -189,29 +189,12 @@
sc->hs_devhandle = SUN4V_REG_SPEC2CFG_HDL(reg);
#endif
- rid = 0;
- if ((sc->hs_intr = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
- RF_SHAREABLE | RF_ACTIVE)) == NULL) {
- device_printf(dev, "couldn't map interrupt\n");
- return ENXIO;
- }
-
- /* XXX - Should this be _CLK since we are redistributing intrs? */
- error = bus_setup_intr(dev, sc->hs_intr, INTR_MPSAFE|INTR_TYPE_MISC,
- hvpci_intr, sc, &sc->hs_intrcookie);
- if (error) {
- bus_release_resource(dev, SYS_RES_IRQ,
- rman_get_rid(sc->hs_intr), sc->hs_intr);
- device_printf(dev, "bus_setup_intr: %d\n", error);
- return error;
- }
-
/* initalize intr resources */
sc->hs_pci_intr_rman.rm_type = RMAN_ARRAY;
sc->hs_pci_intr_rman.rm_descr = "HyperVisor PCI Interrupts";
if (rman_init(&sc->hs_pci_intr_rman) != 0 ||
/* XXX - no clue where this should start or end */
- rman_manage_region(&sc->hs_pci_intr_rman, 0, 10) != 0)
+ rman_manage_region(&sc->hs_pci_intr_rman, 0, 3) != 0)
panic("%s: failed to set up intr rman", __func__);
/* Pull in the ra addresses out of OFW */
@@ -417,9 +400,37 @@
hvpci_setup_intr(device_t dev, device_t child, struct resource *ires,
int flags, driver_intr_t *intr, void *arg, void **cookiep)
{
+ struct hvpci_softc *sc;
+ device_t parent;
+ int pciintr;
- device_printf(dev, "attempted setup_intr: child: %p, ires: %p, flags: %#x, intr: %p, arg: %p, cookiep: %p\n",
- child, ires, flags, intr, arg, cookiep);
+ sc = device_get_softc(dev);
+ parent = device_get_parent(dev);
+
+ /* we use 0 through 3 for INTx interrupts, while sun uses 1 through 4 */
+ pciintr = rman_get_start(ires);
+ KASSERT(pciintr >= 0 && pciintr <= 3,
+ ("interrupt out of range"));
+ rid = pciintr + 1;
+ if (sc->hs_intr[pciintr] != NULL)
+ return (EBUSY);
+
+ if ((sc->hs_intr[pciintr] = bus_alloc_resource_any(parent, SYS_RES_IRQ,
+ &rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
+ device_printf(dev, "couldn't alloc interrupt\n");
+ return (ENXIO);
+ }
+
+ error = bus_setup_intr(parent, sc->hs_intr[pciintr], flags, intr, arg,
+ cookiep);
+ if (error) {
+ bus_release_resource(parent, SYS_RES_IRQ,
+ rman_get_rid(sc->hs_intr[pciintr]), sc->hs_intr[pciintr]);
+ sc->hs_intr[pciintr] = NULL;
+ device_printf(dev, "bus_setup_intr: %d\n", error);
+ return (error);
+ }
+
return (0);
}
@@ -427,6 +438,22 @@
hvpci_teardown_intr(device_t dev, device_t child, struct resource *vec,
void *cookie)
{
+ struct hvpci_softc *sc;
+ device_t parent;
+ int pciintr;
+ int error;
+
+ sc = device_get_softc(dev);
+ parent = device_get_parent(dev);
+ pciintr = rman_get_start(vec);
+
+ error = bus_teardown_intr(parent, sc->hs_intr[pciintr], cookie);
+ if (error)
+ return (error);
+
+ bus_release_resource(parent, SYS_RES_IRQ,
+ rman_get_rid(sc->hs_intr[pciintr]), sc->hs_intr[pciintr]);
+ sc->hs_intr[pciintr] = NULL;
return (0);
}
==== //depot/projects/kmacy_sun4v/src/sys/sun4v/sun4v/nexus.c#4 (text+ko) ====
@@ -73,9 +73,7 @@
struct ofw_bus_devinfo ndi_obdinfo;
struct resource_list ndi_rl;
- /* Some common properties. */
- struct nexus_regs *ndi_reg;
- int ndi_nreg;
+ devhandle_t ndi_devhandle;
};
struct nexus_softc {
@@ -88,6 +86,7 @@
static bus_print_child_t nexus_print_child;
static bus_add_child_t nexus_add_child;
static bus_probe_nomatch_t nexus_probe_nomatch;
+static bus_read_ivar_t nexus_read_ivar;
static bus_setup_intr_t nexus_setup_intr;
static bus_teardown_intr_t nexus_teardown_intr;
static bus_alloc_resource_t nexus_alloc_resource;
@@ -114,7 +113,7 @@
/* Bus interface */
DEVMETHOD(bus_print_child, nexus_print_child),
DEVMETHOD(bus_probe_nomatch, nexus_probe_nomatch),
- DEVMETHOD(bus_read_ivar, bus_generic_read_ivar),
+ DEVMETHOD(bus_read_ivar, nexus_read_ivar),
DEVMETHOD(bus_write_ivar, bus_generic_write_ivar),
DEVMETHOD(bus_add_child, nexus_add_child),
DEVMETHOD(bus_alloc_resource, nexus_alloc_resource),
@@ -279,6 +278,25 @@
type != NULL ? type : "unknown");
}
+static int
+nexus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+ struct nexus_devinfo *ndi;
+
+ ndi = device_get_ivars(child);
+
+ switch (which) {
+ case NEXUS_IVAR_DEVHANDLE:
+ *(uint64_t *)result = ndi->ndi_devhandle;
+ break;
+
+ default:
+ return (ENOENT);
+ }
+
+ return (0);
+}
+
#ifdef SUN4V
@@ -286,29 +304,25 @@
nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
driver_intr_t *intr, void *arg, void **cookiep)
{
+ struct nexus_devinfo *ndi;
+ uint64_t ihdl;
+ uint64_t ino;
+ int error, cpuid;
- uint64_t reg, nreg;
- uint64_t ihdl, cfg;
- uint64_t ino, nino;
- int error, cpuid;
+ ndi = device_get_ivars(child);
if (res == NULL)
panic("%s: NULL interrupt resource!", __func__);
printf("dev=%s child=%s\n", ofw_bus_get_name(dev), ofw_bus_get_name(child));
- if ((error = bus_get_resource(child, SYS_RES_MEMORY, 0, ®, &nreg)))
- goto fail;
-
- if ((error = bus_get_resource(child, SYS_RES_IRQ, 0, &ino, &nino)))
- goto fail;
+ ino = rman_get_start(ires);
printf("child=%s reg=0x%lx ino=0x%lx\n", ofw_bus_get_name(child),
- reg, ino);
+ ndi->ndi_devhandle, ino);
- cfg = SUN4V_REG_SPEC2CFG_HDL(reg);
-
- if (hvio_intr_devino_to_sysino(cfg, (uint32_t)ino, &ihdl) != H_EOK) {
+ if (hvio_intr_devino_to_sysino(ndi->ndi_devhandle, (uint32_t)ino,
+ &ihdl) != H_EOK) {
error = ENXIO;
goto fail;
}
@@ -509,9 +523,9 @@
struct nexus_regs *reg;
bus_addr_t phys;
bus_size_t size;
- uint32_t ign;
+ uint32_t ign, naddrcell, nintrcell;
uint32_t *intr;
- int i;
+ int i, rid;
int nintr;
int nreg;
@@ -528,44 +542,39 @@
}
resource_list_init(&ndi->ndi_rl);
nreg = OF_getprop_alloc(node, "reg", sizeof(*reg), (void **)®);
- if (nreg == -1) {
- device_printf(dev, "<%s>: incomplete\n",
- ndi->ndi_obdinfo.obd_name);
+ if (nreg != 1) {
+ device_printf(dev, "<%s>: incomplete: %d\n",
+ ndi->ndi_obdinfo.obd_name, nreg);
nexus_destroy_dinfo(ndi);
return (NULL);
}
- for (i = 0; i < nreg; i++) {
- phys = NEXUS_REG_PHYS(®[i]);
- size = NEXUS_REG_SIZE(®[i]);
- resource_list_add(&ndi->ndi_rl, SYS_RES_MEMORY, i, phys,
- phys + size - 1, size);
- }
+ phys = NEXUS_REG_PHYS(®[0]);
+ ndi->ndi_devhandle = SUN4V_REG_SPEC2CFG_HDL(phys);
free(reg, M_OFWPROP);
- nintr = OF_getprop_alloc(node, "interrupts", sizeof(*intr),
+ if (OF_getprop(node, "#address-cells", &naddrcell,
+ sizeof *naddrcell) != sizeof *naddrcell || OF_getprop(node,
+ "#interrupt-cells", &nintrcell, sizeof *nintrcell) !=
+ sizeof *nintrcell || nintrcell != 1)
+ panic("can't get cell sizes"); /* or invalid intr cell size */
+
+ nintr = OF_getprop_alloc(node, "interrupt-map", sizeof(*intr),
(void **)&intr);
- if (nintr > 0) {
-#ifndef SUN4V
- if (OF_getprop(node, cpu_impl < CPU_IMPL_ULTRASPARCIII ?
- "upa-portid" : "portid", &ign, sizeof(ign)) <= 0) {
- device_printf(dev, "<%s>: could not determine portid\n",
- ndi->ndi_obdinfo.obd_name);
- nexus_destroy_dinfo(ndi);
- return (NULL);
- }
-
- /* XXX Starfire */
- ign = (ign << INTMAP_IGN_SHIFT) & INTMAP_IGN_MASK;
-#else
- ign = 0;
-#endif
- for (i = 0; i < nintr; i++) {
- intr[i] |= ign;
- resource_list_add(&ndi->ndi_rl, SYS_RES_IRQ, i, intr[i],
- intr[i], 1);
- }
- free(intr, M_OFWPROP);
+ for (i = 0; i < nintr; rid++, i += naddrcell + nintrcell + 2) {
+ /*
+ * interrupt-map is:
+ * addr,intr,phandle,parent's intr
+ */
+ rid = intr[i + naddrcell];
+ * XXX - technically, we need to pull the parent's
+ * #interrupt-cells, but we'll assume it's 1 like we enforce
+ * nintercell to be above.
+ */
+ resource_list_add(&ndi->ndi_rl, SYS_RES_IRQ, rid,
+ intr[i + naddrcell + nintercell + 1],
+ intr[i + naddrcell + nintercell + 1], 1);
}
+ free(intr, M_OFWPROP);
return (ndi);
}
More information about the p4-projects
mailing list