summaryrefslogtreecommitdiffstats
path: root/sys/powerpc
diff options
context:
space:
mode:
authorbenno <benno@FreeBSD.org>2002-04-15 12:29:18 +0000
committerbenno <benno@FreeBSD.org>2002-04-15 12:29:18 +0000
commita7de23a1adf28e09a232cda8afe3efe007016a35 (patch)
treef11c97da6bb2a63e0832036223a642de1d1b8bc4 /sys/powerpc
parentb6bf4c07cfa2b20a71ec5c6e20bf929d299043c5 (diff)
downloadFreeBSD-src-a7de23a1adf28e09a232cda8afe3efe007016a35.zip
FreeBSD-src-a7de23a1adf28e09a232cda8afe3efe007016a35.tar.gz
Add a nexus device.
Copied from: sparc64
Diffstat (limited to 'sys/powerpc')
-rw-r--r--sys/powerpc/aim/nexus.c233
-rw-r--r--sys/powerpc/include/nexusvar.h51
-rw-r--r--sys/powerpc/powerpc/nexus.c233
3 files changed, 517 insertions, 0 deletions
diff --git a/sys/powerpc/aim/nexus.c b/sys/powerpc/aim/nexus.c
new file mode 100644
index 0000000..31f4f0e
--- /dev/null
+++ b/sys/powerpc/aim/nexus.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright 1998 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*-
+ * Copyright 2001 by Thomas Moestl <tmm@FreeBSD.org>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: FreeBSD: src/sys/i386/i386/nexus.c,v 1.43 2001/02/09
+ *
+ * $FreeBSD$
+ */
+
+#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 <dev/ofw/openfirm.h>
+
+#include <machine/bus.h>
+#include <machine/frame.h>
+#include <machine/nexusvar.h>
+#include <machine/resource.h>
+
+/*
+ * The nexus (which is a pseudo-bus actually) iterates over the nodes that
+ * exist in OpenFirmware and adds them as devices to this bus so that drivers
+ * can be attached to them.
+ *
+ * Maybe this code should get into dev/ofw to some extent, as some of it should
+ * work for all OpenFirmware based machines...
+ */
+
+static MALLOC_DEFINE(M_NEXUS, "nexus", "nexus device information");
+
+struct nexus_devinfo {
+ phandle_t ndi_node;
+ /* Some common properties. */
+ char *ndi_name;
+ char *ndi_device_type;
+};
+
+struct nexus_softc {
+};
+
+static int nexus_probe(device_t);
+static void nexus_probe_nomatch(device_t, device_t);
+static int nexus_read_ivar(device_t, device_t, int, uintptr_t *);
+static int nexus_write_ivar(device_t, device_t, int, uintptr_t);
+
+static device_method_t nexus_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, nexus_probe),
+ DEVMETHOD(device_attach, bus_generic_attach),
+ DEVMETHOD(device_detach, bus_generic_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+
+ /* Bus interface. Resource management is business of the children... */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_probe_nomatch, nexus_probe_nomatch),
+ DEVMETHOD(bus_read_ivar, nexus_read_ivar),
+ DEVMETHOD(bus_write_ivar, nexus_write_ivar),
+
+ { 0, 0 }
+};
+
+static driver_t nexus_driver = {
+ "nexus",
+ nexus_methods,
+ sizeof(struct nexus_softc),
+};
+
+static devclass_t nexus_devclass;
+
+DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0);
+
+static int
+nexus_probe(device_t dev)
+{
+ phandle_t root;
+ phandle_t child, new_node, temp_node;
+ device_t cdev;
+ struct nexus_devinfo *dinfo;
+ struct nexus_softc *sc;
+ char *name, *type;
+
+ if ((root = OF_peer(0)) == -1)
+ panic("nexus_probe: OF_peer failed.");
+
+ child = root;
+ while (child != 0) {
+ OF_getprop_alloc(child, "name", 1, (void **)&name);
+ OF_getprop_alloc(child, "device_type", 1, (void **)&type);
+ cdev = device_add_child(dev, NULL, -1);
+ if (cdev != NULL) {
+ dinfo = malloc(sizeof(*dinfo), M_NEXUS, M_WAITOK);
+ dinfo->ndi_node = child;
+ dinfo->ndi_name = name;
+ dinfo->ndi_device_type = type;
+ device_set_ivars(cdev, dinfo);
+ } else
+ free(name, M_OFWPROP);
+
+next:
+ new_node = OF_child(child);
+ if (new_node == -1)
+ panic("nexus_probe: OF_child return -1");
+ if (new_node == 0)
+ new_node = OF_peer(child);
+ if (new_node == 0) {
+ temp_node = child;
+ while (new_node == 0) {
+ temp_node = OF_parent(temp_node);
+ if (temp_node == 0)
+ break;
+ new_node = OF_peer(temp_node);
+ }
+ }
+ child = new_node;
+ }
+ device_set_desc(dev, "OpenFirmware Nexus device");
+ return (0);
+}
+
+static void
+nexus_probe_nomatch(device_t dev, device_t child)
+{
+ char *name, *type;
+
+ if (BUS_READ_IVAR(dev, child, NEXUS_IVAR_NAME,
+ (uintptr_t *)&name) != 0 ||
+ BUS_READ_IVAR(dev, child, NEXUS_IVAR_DEVICE_TYPE,
+ (uintptr_t *)&type) != 0)
+ return;
+
+ if (type == NULL)
+ type = "(unknown)";
+#if 0
+ device_printf(dev, "<%s>, type %s (no driver attached)\n",
+ name, type);
+#endif
+}
+
+static int
+nexus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+ struct nexus_devinfo *dinfo;
+
+ 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;
+ default:
+ return (ENOENT);
+ }
+ return 0;
+}
+
+static int
+nexus_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
+{
+ struct nexus_devinfo *dinfo;
+
+ if ((dinfo = device_get_ivars(child)) == 0)
+ return (ENOENT);
+
+ switch (which) {
+ case NEXUS_IVAR_NODE:
+ case NEXUS_IVAR_NAME:
+ case NEXUS_IVAR_DEVICE_TYPE:
+ return (EINVAL);
+ default:
+ return (ENOENT);
+ }
+ return 0;
+}
diff --git a/sys/powerpc/include/nexusvar.h b/sys/powerpc/include/nexusvar.h
new file mode 100644
index 0000000..9cdeb63
--- /dev/null
+++ b/sys/powerpc/include/nexusvar.h
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 2001 by Thomas Moestl <tmm@FreeBSD.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _MACHINE_NEXUSVAR_H_
+#define _MACHINE_NEXUSVAR_H_
+
+enum nexus_ivars {
+ NEXUS_IVAR_NODE,
+ NEXUS_IVAR_NAME,
+ NEXUS_IVAR_DEVICE_TYPE,
+};
+
+/*
+ * Simplified accessors for nexus devices
+ * XXX: These should be made specializations of generic bus accessor macros
+ * instead of having multiple implementations around.
+ */
+#define NEXUS_ACCESSOR(var, ivar, type) \
+ __BUS_ACCESSOR(nexus, var, NEXUS, ivar, type)
+
+NEXUS_ACCESSOR(node, NODE, phandle_t)
+NEXUS_ACCESSOR(name, NAME, char *)
+NEXUS_ACCESSOR(device_type, DEVICE_TYPE, char *)
+
+#undef NEXUS_ACCESSOR
+
+#endif /* _MACHINE_NEXUSVAR_H_ */
diff --git a/sys/powerpc/powerpc/nexus.c b/sys/powerpc/powerpc/nexus.c
new file mode 100644
index 0000000..31f4f0e
--- /dev/null
+++ b/sys/powerpc/powerpc/nexus.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright 1998 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*-
+ * Copyright 2001 by Thomas Moestl <tmm@FreeBSD.org>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: FreeBSD: src/sys/i386/i386/nexus.c,v 1.43 2001/02/09
+ *
+ * $FreeBSD$
+ */
+
+#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 <dev/ofw/openfirm.h>
+
+#include <machine/bus.h>
+#include <machine/frame.h>
+#include <machine/nexusvar.h>
+#include <machine/resource.h>
+
+/*
+ * The nexus (which is a pseudo-bus actually) iterates over the nodes that
+ * exist in OpenFirmware and adds them as devices to this bus so that drivers
+ * can be attached to them.
+ *
+ * Maybe this code should get into dev/ofw to some extent, as some of it should
+ * work for all OpenFirmware based machines...
+ */
+
+static MALLOC_DEFINE(M_NEXUS, "nexus", "nexus device information");
+
+struct nexus_devinfo {
+ phandle_t ndi_node;
+ /* Some common properties. */
+ char *ndi_name;
+ char *ndi_device_type;
+};
+
+struct nexus_softc {
+};
+
+static int nexus_probe(device_t);
+static void nexus_probe_nomatch(device_t, device_t);
+static int nexus_read_ivar(device_t, device_t, int, uintptr_t *);
+static int nexus_write_ivar(device_t, device_t, int, uintptr_t);
+
+static device_method_t nexus_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, nexus_probe),
+ DEVMETHOD(device_attach, bus_generic_attach),
+ DEVMETHOD(device_detach, bus_generic_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+
+ /* Bus interface. Resource management is business of the children... */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_probe_nomatch, nexus_probe_nomatch),
+ DEVMETHOD(bus_read_ivar, nexus_read_ivar),
+ DEVMETHOD(bus_write_ivar, nexus_write_ivar),
+
+ { 0, 0 }
+};
+
+static driver_t nexus_driver = {
+ "nexus",
+ nexus_methods,
+ sizeof(struct nexus_softc),
+};
+
+static devclass_t nexus_devclass;
+
+DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0);
+
+static int
+nexus_probe(device_t dev)
+{
+ phandle_t root;
+ phandle_t child, new_node, temp_node;
+ device_t cdev;
+ struct nexus_devinfo *dinfo;
+ struct nexus_softc *sc;
+ char *name, *type;
+
+ if ((root = OF_peer(0)) == -1)
+ panic("nexus_probe: OF_peer failed.");
+
+ child = root;
+ while (child != 0) {
+ OF_getprop_alloc(child, "name", 1, (void **)&name);
+ OF_getprop_alloc(child, "device_type", 1, (void **)&type);
+ cdev = device_add_child(dev, NULL, -1);
+ if (cdev != NULL) {
+ dinfo = malloc(sizeof(*dinfo), M_NEXUS, M_WAITOK);
+ dinfo->ndi_node = child;
+ dinfo->ndi_name = name;
+ dinfo->ndi_device_type = type;
+ device_set_ivars(cdev, dinfo);
+ } else
+ free(name, M_OFWPROP);
+
+next:
+ new_node = OF_child(child);
+ if (new_node == -1)
+ panic("nexus_probe: OF_child return -1");
+ if (new_node == 0)
+ new_node = OF_peer(child);
+ if (new_node == 0) {
+ temp_node = child;
+ while (new_node == 0) {
+ temp_node = OF_parent(temp_node);
+ if (temp_node == 0)
+ break;
+ new_node = OF_peer(temp_node);
+ }
+ }
+ child = new_node;
+ }
+ device_set_desc(dev, "OpenFirmware Nexus device");
+ return (0);
+}
+
+static void
+nexus_probe_nomatch(device_t dev, device_t child)
+{
+ char *name, *type;
+
+ if (BUS_READ_IVAR(dev, child, NEXUS_IVAR_NAME,
+ (uintptr_t *)&name) != 0 ||
+ BUS_READ_IVAR(dev, child, NEXUS_IVAR_DEVICE_TYPE,
+ (uintptr_t *)&type) != 0)
+ return;
+
+ if (type == NULL)
+ type = "(unknown)";
+#if 0
+ device_printf(dev, "<%s>, type %s (no driver attached)\n",
+ name, type);
+#endif
+}
+
+static int
+nexus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+ struct nexus_devinfo *dinfo;
+
+ 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;
+ default:
+ return (ENOENT);
+ }
+ return 0;
+}
+
+static int
+nexus_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
+{
+ struct nexus_devinfo *dinfo;
+
+ if ((dinfo = device_get_ivars(child)) == 0)
+ return (ENOENT);
+
+ switch (which) {
+ case NEXUS_IVAR_NODE:
+ case NEXUS_IVAR_NAME:
+ case NEXUS_IVAR_DEVICE_TYPE:
+ return (EINVAL);
+ default:
+ return (ENOENT);
+ }
+ return 0;
+}
OpenPOWER on IntegriCloud