PERFORCE change 93837 for review
Kip Macy
kmacy at FreeBSD.org
Thu Mar 23 03:29:39 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=93837
Change 93837 by kmacy at kmacy_storage:sun4vtmp on 2006/03/23 03:28:39
integrate roto-tilled nexus driver from Marius
Affected files ...
.. //depot/projects/kmacy_sun4v/src/sys/sun4v/include/nexusvar.h#2 edit
.. //depot/projects/kmacy_sun4v/src/sys/sun4v/include/ofw_nexus.h#1 add
.. //depot/projects/kmacy_sun4v/src/sys/sun4v/sun4v/nexus.c#2 edit
Differences ...
==== //depot/projects/kmacy_sun4v/src/sys/sun4v/include/nexusvar.h#2 (text+ko) ====
@@ -28,31 +28,8 @@
#ifndef _MACHINE_NEXUSVAR_H_
#define _MACHINE_NEXUSVAR_H_
-enum nexus_ivars {
- NEXUS_IVAR_NODE,
- NEXUS_IVAR_NAME,
- NEXUS_IVAR_DEVICE_TYPE,
- NEXUS_IVAR_MODEL,
- NEXUS_IVAR_REG,
- NEXUS_IVAR_NREG,
- NEXUS_IVAR_INTERRUPTS,
- NEXUS_IVAR_NINTERRUPTS,
- NEXUS_IVAR_DMATAG,
-};
+extern struct bus_dma_tag nexus_dmatag;
-#define NEXUS_ACCESSOR(var, ivar, type) \
- __BUS_ACCESSOR(nexus, var, NEXUS, ivar, type)
+#endif /* _MACHINE_NEXUSVAR_H_ */
-NEXUS_ACCESSOR(node, NODE, phandle_t)
-NEXUS_ACCESSOR(name, NAME, char *)
-NEXUS_ACCESSOR(device_type, DEVICE_TYPE, char *)
-NEXUS_ACCESSOR(model, MODEL, char *)
-NEXUS_ACCESSOR(reg, REG, struct upa_regs *)
-NEXUS_ACCESSOR(nreg, NREG, int)
-NEXUS_ACCESSOR(interrupts, INTERRUPTS, u_int *)
-NEXUS_ACCESSOR(ninterrupts, NINTERRUPTS, int)
-NEXUS_ACCESSOR(dmatag, DMATAG, bus_dma_tag_t)
-#undef NEXUS_ACCESSOR
-
-#endif /* _MACHINE_NEXUSVAR_H_ */
==== //depot/projects/kmacy_sun4v/src/sys/sun4v/sun4v/nexus.c#2 (text+ko) ====
@@ -1,6 +1,7 @@
/*-
* Copyright 1998 Massachusetts Institute of Technology
* Copyright 2001 by Thomas Moestl <tmm at FreeBSD.org>.
+ * Copyright 2006 by Marius Strobl <marius at FreeBSD.org>.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and
@@ -37,20 +38,21 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
-#include <sys/cons.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
#include <dev/ofw/openfirm.h>
#include <machine/bus.h>
-#include <machine/frame.h>
+#include <machine/bus_common.h>
#include <machine/intr_machdep.h>
#include <machine/nexusvar.h>
-#include <machine/ofw_upa.h>
+#include <machine/ofw_nexus.h>
#include <machine/resource.h>
-#include <machine/upa.h>
+#include <machine/ver.h>
#include <sys/rman.h>
@@ -67,18 +69,13 @@
* work for all Open Firmware based machines...
*/
-static MALLOC_DEFINE(M_NEXUS, "nexus", "nexus device information");
+struct nexus_devinfo {
+ struct ofw_bus_devinfo ndi_obdinfo;
+ struct resource_list ndi_rl;
-struct nexus_devinfo {
- phandle_t ndi_node;
/* Some common properties. */
- char *ndi_name;
- char *ndi_device_type;
- char *ndi_model;
- struct upa_regs *ndi_reg;
+ struct nexus_regs *ndi_reg;
int ndi_nreg;
- u_int *ndi_interrupts;
- int ndi_ninterrupts;
};
struct nexus_softc {
@@ -88,16 +85,23 @@
static device_probe_t nexus_probe;
static device_attach_t nexus_attach;
+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;
+static bus_get_resource_list_t nexus_get_resource_list;
static bus_activate_resource_t nexus_activate_resource;
static bus_deactivate_resource_t nexus_deactivate_resource;
static bus_release_resource_t nexus_release_resource;
+static ofw_bus_get_devinfo_t nexus_get_devinfo;
+static int nexus_inlist(const char *, const char **);
+static struct nexus_devinfo * nexus_setup_dinfo(device_t, phandle_t);
+static void nexus_destroy_dinfo(struct nexus_devinfo *);
+static int nexus_print_res(struct nexus_devinfo *);
+
static device_method_t nexus_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, nexus_probe),
@@ -107,56 +111,65 @@
DEVMETHOD(device_suspend, bus_generic_suspend),
DEVMETHOD(device_resume, bus_generic_resume),
- /* Bus interface. */
+ /* 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_write_ivar, bus_generic_write_ivar),
DEVMETHOD(bus_add_child, nexus_add_child),
- DEVMETHOD(bus_print_child, bus_generic_print_child),
- DEVMETHOD(bus_probe_nomatch, nexus_probe_nomatch),
- DEVMETHOD(bus_read_ivar, nexus_read_ivar),
- DEVMETHOD(bus_setup_intr, nexus_setup_intr),
- DEVMETHOD(bus_teardown_intr, nexus_teardown_intr),
DEVMETHOD(bus_alloc_resource, nexus_alloc_resource),
DEVMETHOD(bus_activate_resource, nexus_activate_resource),
DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource),
DEVMETHOD(bus_release_resource, nexus_release_resource),
+ DEVMETHOD(bus_setup_intr, nexus_setup_intr),
+ DEVMETHOD(bus_teardown_intr, nexus_teardown_intr),
+ DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
+ DEVMETHOD(bus_get_resource_list, nexus_get_resource_list),
+
+ /* ofw_bus interface */
+ DEVMETHOD(ofw_bus_get_devinfo, nexus_get_devinfo),
+ DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
+ DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
+ DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
+ DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
+ DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
{ 0, 0 }
};
-static driver_t nexus_driver = {
- "nexus",
- nexus_methods,
- sizeof(struct nexus_softc),
-};
-
static devclass_t nexus_devclass;
+DEFINE_CLASS_0(nexus, nexus_driver, nexus_methods, sizeof(struct nexus_softc));
DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0);
-static char *nexus_excl_name[] = {
+static const char *nexus_excl_name[] = {
"aliases",
+ "associations",
"chosen",
"counter-timer", /* No separate device; handled by psycho/sbus */
"memory",
"openprom",
"options",
"packages",
+ "rsc",
"virtual-memory",
NULL
};
-static char *nexus_excl_type[] = {
+static const char *nexus_excl_type[] = {
"cpu",
NULL
};
extern struct bus_space_tag nexus_bustag;
-extern struct bus_dma_tag nexus_dmatag;
static int
-nexus_inlist(char *name, char *list[])
+nexus_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);
@@ -179,26 +192,25 @@
static int
nexus_attach(device_t dev)
{
- phandle_t root;
- phandle_t child;
+ struct nexus_devinfo *ndi;
+ struct nexus_softc *sc;
device_t cdev;
- struct nexus_devinfo *dinfo;
- struct nexus_softc *sc;
- char *name, *type;
+ phandle_t node;
- if ((root = OF_peer(0)) == -1)
- panic("nexus_probe: OF_peer failed.");
+ node = OF_peer(0);
+ if (node == -1)
+ panic("%s: OF_peer failed.", __func__);
sc = device_get_softc(dev);
sc->sc_intr_rman.rm_type = RMAN_ARRAY;
sc->sc_intr_rman.rm_descr = "Interrupts";
sc->sc_mem_rman.rm_type = RMAN_ARRAY;
- sc->sc_mem_rman.rm_descr = "UPA Device Memory";
+ sc->sc_mem_rman.rm_descr = "Device Memory";
if (rman_init(&sc->sc_intr_rman) != 0 ||
rman_init(&sc->sc_mem_rman) != 0 ||
rman_manage_region(&sc->sc_intr_rman, 0, IV_MAX - 1) != 0 ||
- rman_manage_region(&sc->sc_mem_rman, UPA_MEMSTART, UPA_MEMEND) != 0)
- panic("nexus_attach(): failed to set up rmans");
+ rman_manage_region(&sc->sc_mem_rman, 0ULL, ~0ULL) != 0)
+ panic("%s: failed to set up rmans.", __func__);
/*
* Allow devices to identify.
@@ -208,32 +220,17 @@
/*
* Now walk the OFW tree and attach top-level devices.
*/
- for (child = OF_child(root); child != 0; child = OF_peer(child)) {
- if (child == -1)
- panic("nexus_attach(): OF_child() failed.");
- if (OF_getprop_alloc(child, "name", 1, (void **)&name) == -1)
+ for (node = OF_child(node); node > 0; node = OF_peer(node)) {
+ if ((ndi = nexus_setup_dinfo(dev, node)) == NULL)
continue;
- OF_getprop_alloc(child, "device_type", 1, (void **)&type);
- if (NEXUS_EXCLUDED(name, type)) {
- free(name, M_OFWPROP);
- free(type, M_OFWPROP);
+ cdev = device_add_child(dev, NULL, -1);
+ if (cdev == NULL) {
+ device_printf(dev, "<%s>: device_add_child failed\n",
+ ndi->ndi_obdinfo.obd_name);
+ nexus_destroy_dinfo(ndi);
continue;
}
- cdev = device_add_child(dev, NULL, -1);
- if (cdev == NULL)
- panic("nexus_attach(): device_add_child() failed.");
- dinfo = malloc(sizeof(*dinfo), M_NEXUS, M_WAITOK);
- dinfo->ndi_node = child;
- dinfo->ndi_name = name;
- dinfo->ndi_device_type = type;
- OF_getprop_alloc(child, "model", 1,
- (void **)&dinfo->ndi_model);
- dinfo->ndi_nreg = OF_getprop_alloc(child, "reg",
- sizeof(*dinfo->ndi_reg), (void **)&dinfo->ndi_reg);
- dinfo->ndi_ninterrupts = OF_getprop_alloc(child,
- "interrupts", sizeof(*dinfo->ndi_interrupts),
- (void **)&dinfo->ndi_interrupts);
- device_set_ivars(cdev, dinfo);
+ device_set_ivars(cdev, ndi);
}
return (bus_generic_attach(dev));
}
@@ -242,73 +239,42 @@
nexus_add_child(device_t dev, int order, const char *name, int unit)
{
device_t cdev;
- struct nexus_devinfo *dinfo;
+ struct nexus_devinfo *ndi;
cdev = device_add_child_ordered(dev, order, name, unit);
if (cdev == NULL)
return (NULL);
- dinfo = malloc(sizeof(*dinfo), M_NEXUS, M_NOWAIT | M_ZERO);
- if (dinfo == NULL)
- return (NULL);
+ ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO);
+ ndi->ndi_obdinfo.obd_node = -1;
+ ndi->ndi_obdinfo.obd_name = strdup(name, M_OFWPROP);
+ resource_list_init(&ndi->ndi_rl);
+ device_set_ivars(cdev, ndi);
- dinfo->ndi_node = -1;
- dinfo->ndi_name = strdup(name, M_OFWPROP);
- device_set_ivars(cdev, dinfo);
-
return (cdev);
}
-static void
-nexus_probe_nomatch(device_t dev, device_t child)
+static int
+nexus_print_child(device_t dev, device_t child)
{
- char *type;
+ int rv;
- if ((type = nexus_get_device_type(child)) == NULL)
- type = "(unknown)";
- device_printf(dev, "<%s>, type %s (no driver attached)\n",
- nexus_get_name(child), type);
+ rv = bus_print_child_header(dev, child);
+ rv += nexus_print_res(device_get_ivars(child));
+ rv += bus_print_child_footer(dev, child);
+ return (rv);
}
-static int
-nexus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+static void
+nexus_probe_nomatch(device_t dev, device_t child)
{
- struct nexus_devinfo *dinfo;
+ const char *type;
- if ((dinfo = device_get_ivars(child)) == 0)
- return (ENOENT);
- switch (which) {
- case NEXUS_IVAR_NODE:
- *result = dinfo->ndi_node;
- break;
- case NEXUS_IVAR_NAME:
- *result = (uintptr_t)dinfo->ndi_name;
- break;
- case NEXUS_IVAR_DEVICE_TYPE:
- *result = (uintptr_t)dinfo->ndi_device_type;
- break;
- case NEXUS_IVAR_MODEL:
- *result = (uintptr_t)dinfo->ndi_model;
- break;
- case NEXUS_IVAR_REG:
- *result = (uintptr_t)dinfo->ndi_reg;
- break;
- case NEXUS_IVAR_NREG:
- *result = dinfo->ndi_nreg;
- break;
- case NEXUS_IVAR_INTERRUPTS:
- *result = (uintptr_t)dinfo->ndi_interrupts;
- break;
- case NEXUS_IVAR_NINTERRUPTS:
- *result = dinfo->ndi_ninterrupts;
- break;
- case NEXUS_IVAR_DMATAG:
- *result = (uintptr_t)&nexus_dmatag;
- break;
- default:
- return (ENOENT);
- }
- return 0;
+ device_printf(dev, "<%s>", ofw_bus_get_name(child));
+ nexus_print_res(device_get_ivars(child));
+ type = ofw_bus_get_type(child);
+ printf(" type %s (no driver attached)\n",
+ type != NULL ? type : "unknown");
}
static int
@@ -318,7 +284,7 @@
int error;
if (res == NULL)
- panic("nexus_setup_intr: NULL interrupt resource!");
+ panic("%s: NULL interrupt resource!", __func__);
if ((rman_get_flags(res) & RF_SHAREABLE) == 0)
flags |= INTR_EXCL;
@@ -346,12 +312,31 @@
nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
- struct nexus_softc *sc = device_get_softc(bus);
- struct resource *rv;
- struct rman *rm;
- int needactivate = flags & RF_ACTIVE;
+ struct nexus_softc *sc;
+ struct rman *rm;
+ struct resource *rv;
+ struct resource_list_entry *rle;
+ int isdefault, needactivate, passthrough;
+
+ isdefault = (start == 0UL && end == ~0UL);
+ needactivate = flags & RF_ACTIVE;
+ passthrough = (device_get_parent(child) != bus);
+ sc = device_get_softc(bus);
+ rle = NULL;
- flags &= ~RF_ACTIVE;
+ if (!passthrough) {
+ rle = resource_list_find(BUS_GET_RESOURCE_LIST(bus, child),
+ type, *rid);
+ if (rle == NULL)
+ return (NULL);
+ if (rle->res != NULL)
+ panic("%s: resource entry is busy", __func__);
+ if (isdefault) {
+ start = rle->start;
+ count = ulmax(count, rle->count);
+ end = ulmax(rle->end, start + count - 1);
+ }
+ }
switch (type) {
case SYS_RES_IRQ:
@@ -364,6 +349,7 @@
return (NULL);
}
+ flags &= ~RF_ACTIVE;
rv = rman_reserve_resource(rm, start, end, count, flags, child);
if (rv == NULL)
return (NULL);
@@ -379,6 +365,9 @@
}
}
+ if (!passthrough)
+ rle->res = rv;
+
return (rv);
}
@@ -413,3 +402,113 @@
}
return (rman_release_resource(r));
}
+
+static struct resource_list *
+nexus_get_resource_list(device_t dev, device_t child)
+{
+ struct nexus_devinfo *ndi;
+
+ ndi = device_get_ivars(child);
+ return (&ndi->ndi_rl);
+}
+
+static const struct ofw_bus_devinfo *
+nexus_get_devinfo(device_t dev, device_t child)
+{
+ struct nexus_devinfo *ndi;
+
+ ndi = device_get_ivars(child);
+ return (&ndi->ndi_obdinfo);
+}
+
+static struct nexus_devinfo *
+nexus_setup_dinfo(device_t dev, phandle_t node)
+{
+ struct nexus_devinfo *ndi;
+ struct nexus_regs *reg;
+ bus_addr_t phys;
+ bus_size_t size;
+ uint32_t ign;
+ uint32_t *intr;
+ int i;
+ int nintr;
+ int nreg;
+
+ ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO);
+ if (ofw_bus_gen_setup_devinfo(&ndi->ndi_obdinfo, node) != 0) {
+ free(ndi, M_DEVBUF);
+ return (NULL);
+ }
+ if (NEXUS_EXCLUDED(ndi->ndi_obdinfo.obd_name,
+ ndi->ndi_obdinfo.obd_type)) {
+ ofw_bus_gen_destroy_devinfo(&ndi->ndi_obdinfo);
+ free(ndi, M_DEVBUF);
+ return (NULL);
+ }
+ 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);
+ 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);
+ }
+ free(reg, M_OFWPROP);
+
+ nintr = OF_getprop_alloc(node, "interrupts", 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);
+ }
+
+ return (ndi);
+}
+
+static void
+nexus_destroy_dinfo(struct nexus_devinfo *ndi)
+{
+
+ resource_list_free(&ndi->ndi_rl);
+ ofw_bus_gen_destroy_devinfo(&ndi->ndi_obdinfo);
+ free(ndi, M_DEVBUF);
+}
+
+static int
+nexus_print_res(struct nexus_devinfo *ndi)
+{
+ int rv;
+
+ rv = 0;
+ rv += resource_list_print_type(&ndi->ndi_rl, "mem", SYS_RES_MEMORY,
+ "%#lx");
+ rv += resource_list_print_type(&ndi->ndi_rl, "irq", SYS_RES_IRQ,
+ "%ld");
+ return (rv);
+}
+
+
More information about the p4-projects
mailing list