Index: dev/ofw/openfirmio.c =================================================================== --- dev/ofw/openfirmio.c (revision 186200) +++ dev/ofw/openfirmio.c (working copy) @@ -221,7 +221,7 @@ if (error) break; } - ok = OF_nextprop(node, name, newname); + ok = OF_nextprop(node, name, newname, sizeof(newname)); if (ok == 0) { error = ENOENT; break; Index: dev/ofw/ofwvar.h =================================================================== --- dev/ofw/ofwvar.h (revision 0) +++ dev/ofw/ofwvar.h (revision 0) @@ -0,0 +1,89 @@ +/*- + * Copyright (c) 2005 Peter Grehan + * Copyright (c) 2008 Nathan Whitehorn + * 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. + * + * $FreeBSD$ + */ + +#ifndef _OFW_OFWVAR_H_ +#define _OFW_OFWVAR_H_ + +/* + * An Open Firmware client implementation is declared with a kernel object and + * an associated method table, similar to a device driver. + * + * e.g. + * + * static ofw_method_t fdt_methods[] = { + * OFWMETHOD(ofw_init, fdt_init), + * OFWMETHOD(ofw_finddevice, fdt_finddevice), + * ... + * OFWMETHOD(ofw_nextprop, fdt_nextprop), + * { 0, 0 } + * }; + * + * static ofw_def_t ofw_fdt = { + * "ofw_fdt", + * fdt_methods, + * sizeof(fdt_softc), // or 0 if no softc + * }; + * + * OFW_DEF(ofw_fdt); + */ + +#include + +struct ofw_kobj { + /* + * An OFW instance is a kernel object + */ + KOBJ_FIELDS; + + /* + * Utility elements that an instance may use + */ + struct mtx ofw_mtx; /* available for instance use */ + void *ofw_iptr; /* instance data pointer */ + + /* + * Opaque data that can be overlaid with an instance-private + * structure. OFW code can test that this is large enough at + * compile time with a sizeof() test againt it's softc. There + * is also a run-time test when the MMU kernel object is + * registered. + */ +#define OFW_OPAQUESZ 64 + u_int ofw_opaque[OFW_OPAQUESZ]; +}; + +typedef struct ofw_kobj *ofw_t; +typedef struct kobj_class ofw_def_t; +#define ofw_method_t kobj_method_t + +#define OFWMETHOD KOBJMETHOD + +#define OFW_DEF(name) DATA_SET(ofw_set, name) + +#endif /* _OFW_OFWVAR_H_ */ Property changes on: dev/ofw/ofwvar.h ___________________________________________________________________ Added: svn:keywords + FreeBSD=%H Index: dev/ofw/ofw_standard.c =================================================================== --- dev/ofw/ofw_standard.c (revision 186188) +++ dev/ofw/ofw_standard.c (working copy) @@ -64,37 +64,93 @@ #include #include +#include #include +#include +#include "ofw_if.h" -MALLOC_DEFINE(M_OFWPROP, "openfirm", "Open Firmware properties"); +static void ofw_std_init(ofw_t, void *openfirm); +static int ofw_std_test(ofw_t, const char *name); +static int ofw_std_interpret(ofw_t, const char *cmd, int nreturns, + unsigned long *returns); +static phandle_t ofw_std_peer(ofw_t, phandle_t node); +static phandle_t ofw_std_child(ofw_t, phandle_t node); +static phandle_t ofw_std_parent(ofw_t, phandle_t node); +static phandle_t ofw_std_instance_to_package(ofw_t, ihandle_t instance); +static ssize_t ofw_std_getproplen(ofw_t, phandle_t package, + const char *propname); +static ssize_t ofw_std_getprop(ofw_t, phandle_t package, const char *propname, + void *buf, size_t buflen); +static int ofw_std_nextprop(ofw_t, phandle_t package, const char *previous, + char *buf, size_t); +static int ofw_std_setprop(ofw_t, phandle_t package, char *propname, + void *buf, size_t len); +static ssize_t ofw_std_canon(ofw_t, const char *device, char *buf, size_t len); +static phandle_t ofw_std_finddevice(ofw_t, const char *device); +static ssize_t ofw_std_instance_to_path(ofw_t, ihandle_t instance, char *buf, + size_t len); +static ssize_t ofw_std_package_to_path(ofw_t, phandle_t package, char *buf, + size_t len); +static int ofw_std_call_method(ofw_t, ihandle_t instance, const char *method, + int nargs, int nreturns, unsigned long *args_and_returns); +static ihandle_t ofw_std_open(ofw_t, const char *device); +static void ofw_std_close(ofw_t, ihandle_t instance); +static ssize_t ofw_std_read(ofw_t, ihandle_t instance, void *addr, size_t len); +static ssize_t ofw_std_write(ofw_t, ihandle_t instance, const void *addr, + size_t len); +static int ofw_std_seek(ofw_t, ihandle_t instance, u_int64_t pos); +static caddr_t ofw_std_claim(ofw_t, void *virt, size_t size, u_int align); +static void ofw_std_release(ofw_t, void *virt, size_t size); +static void ofw_std_enter(ofw_t); +static void ofw_std_exit(ofw_t); -static ihandle_t stdout; +static ofw_method_t ofw_std_methods[] = { + OFWMETHOD(ofw_init, ofw_std_init), + OFWMETHOD(ofw_peer, ofw_std_peer), + OFWMETHOD(ofw_child, ofw_std_child), + OFWMETHOD(ofw_parent, ofw_std_parent), + OFWMETHOD(ofw_instance_to_package, ofw_std_instance_to_package), + OFWMETHOD(ofw_getproplen, ofw_std_getproplen), + OFWMETHOD(ofw_getprop, ofw_std_getprop), + OFWMETHOD(ofw_nextprop, ofw_std_nextprop), + OFWMETHOD(ofw_setprop, ofw_std_setprop), + OFWMETHOD(ofw_canon, ofw_std_canon), + OFWMETHOD(ofw_finddevice, ofw_std_finddevice), + OFWMETHOD(ofw_instance_to_path, ofw_std_instance_to_path), + OFWMETHOD(ofw_package_to_path, ofw_std_package_to_path), -/* Initialiser */ + OFWMETHOD(ofw_test, ofw_std_test), + OFWMETHOD(ofw_call_method, ofw_std_call_method), + OFWMETHOD(ofw_interpret, ofw_std_interpret), + OFWMETHOD(ofw_open, ofw_std_open), + OFWMETHOD(ofw_close, ofw_std_close), + OFWMETHOD(ofw_read, ofw_std_read), + OFWMETHOD(ofw_write, ofw_std_write), + OFWMETHOD(ofw_seek, ofw_std_seek), + OFWMETHOD(ofw_claim, ofw_std_claim), + OFWMETHOD(ofw_release, ofw_std_release), + OFWMETHOD(ofw_enter, ofw_std_enter), + OFWMETHOD(ofw_exit, ofw_std_exit), -void -OF_init(int (*openfirm)(void *)) -{ - phandle_t chosen; + { 0, 0 } +}; - set_openfirm_callback(openfirm); - if ((chosen = OF_finddevice("/chosen")) == -1) - OF_exit(); - if (OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) == -1) - OF_exit(); -} +static ofw_def_t ofw_std = { + OFW_STD_DIRECT, + ofw_std_methods, + 0 +}; +OFW_DEF(ofw_std); -void -OF_printf(const char *fmt, ...) -{ - va_list va; - char buf[1024]; +static int (*openfirmware)(void *); - va_start(va, fmt); - vsprintf(buf, fmt, va); - OF_write(stdout, buf, strlen(buf)); - va_end(va); +/* Initialiser */ + +static void +ofw_std_init(ofw_t ofw, void *openfirm) +{ + openfirmware = (int (*)(void *))openfirm; } /* @@ -102,8 +158,8 @@ */ /* Test to see if a service exists. */ -int -OF_test(char *name) +static int +ofw_std_test(ofw_t ofw, const char *name) { static struct { cell_t name; @@ -123,10 +179,10 @@ return (args.missing); } -int -OF_interpret(char *cmd, int nreturns, ...) +static int +ofw_std_interpret(ofw_t ofw, const char *cmd, int nreturns, + unsigned long *returns) { - va_list ap; static struct { cell_t name; cell_t nargs; @@ -137,50 +193,26 @@ 1, }; cell_t status; - int i = 0; + int i = 0, j = 0; - va_start(ap, nreturns); args.nreturns = ++nreturns; args.slot[i++] = (cell_t)cmd; - while (i < 1) - args.slot[i++] = va_arg(ap, cell_t); if (openfirmware(&args) == -1) { - va_end(ap); return (-1); } status = args.slot[i++]; while (i < 1 + nreturns) - *va_arg(ap, cell_t *) = args.slot[i++]; - va_end(ap); + returns[j] = args.slot[i++]; return (status); } -/* Return firmware millisecond count. */ -int -OF_milliseconds() -{ - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t ms; - } args = { - (cell_t)"milliseconds", - 0, - 1, - }; - - openfirmware(&args); - return (args.ms); -} - /* * Device tree functions */ /* Return the next sibling of this node or 0. */ -phandle_t -OF_peer(phandle_t node) +static phandle_t +ofw_std_peer(ofw_t ofw, phandle_t node) { static struct { cell_t name; @@ -201,8 +233,8 @@ } /* Return the first child of this node or 0. */ -phandle_t -OF_child(phandle_t node) +static phandle_t +ofw_std_child(ofw_t ofw, phandle_t node) { static struct { cell_t name; @@ -223,8 +255,8 @@ } /* Return the parent of this node or 0. */ -phandle_t -OF_parent(phandle_t node) +static phandle_t +ofw_std_parent(ofw_t ofw, phandle_t node) { static struct { cell_t name; @@ -245,8 +277,8 @@ } /* Return the package handle that corresponds to an instance handle. */ -phandle_t -OF_instance_to_package(ihandle_t instance) +static phandle_t +ofw_std_instance_to_package(ofw_t ofw, ihandle_t instance) { static struct { cell_t name; @@ -267,8 +299,8 @@ } /* Get the length of a property of a package. */ -int -OF_getproplen(phandle_t package, char *propname) +static ssize_t +ofw_std_getproplen(ofw_t ofw, phandle_t package, const char *propname) { static struct { cell_t name; @@ -291,8 +323,9 @@ } /* Get the value of a property of a package. */ -int -OF_getprop(phandle_t package, char *propname, void *buf, int buflen) +static ssize_t +ofw_std_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf, + size_t buflen) { static struct { cell_t name; @@ -318,33 +351,10 @@ return (args.size); } -/* - * Store the value of a property of a package into newly allocated memory - * (using the M_OFWPROP malloc pool and M_WAITOK). elsz is the size of a - * single element, the number of elements is return in number. - */ -int -OF_getprop_alloc(phandle_t package, char *propname, int elsz, void **buf) -{ - int len; - - *buf = NULL; - if ((len = OF_getproplen(package, propname)) == -1 || - len % elsz != 0) - return (-1); - - *buf = malloc(len, M_OFWPROP, M_WAITOK); - if (OF_getprop(package, propname, *buf, len) == -1) { - free(*buf, M_OFWPROP); - *buf = NULL; - return (-1); - } - return (len / elsz); -} - /* Get the next property of a package. */ -int -OF_nextprop(phandle_t package, char *previous, char *buf) +static int +ofw_std_nextprop(ofw_t ofw, phandle_t package, const char *previous, char *buf, + size_t size) { static struct { cell_t name; @@ -370,8 +380,9 @@ /* Set the value of a property of a package. */ /* XXX Has a bug on FirePower */ -int -OF_setprop(phandle_t package, char *propname, void *buf, int len) +static int +ofw_std_setprop(ofw_t ofw, phandle_t package, char *propname, void *buf, + size_t len) { static struct { cell_t name; @@ -398,8 +409,8 @@ } /* Convert a device specifier to a fully qualified pathname. */ -int -OF_canon(const char *device, char *buf, int len) +static ssize_t +ofw_std_canon(ofw_t ofw, const char *device, char *buf, size_t len) { static struct { cell_t name; @@ -424,8 +435,8 @@ } /* Return a package handle for the specified device. */ -phandle_t -OF_finddevice(const char *device) +static phandle_t +ofw_std_finddevice(ofw_t ofw, const char *device) { static struct { cell_t name; @@ -446,8 +457,8 @@ } /* Return the fully qualified pathname corresponding to an instance. */ -int -OF_instance_to_path(ihandle_t instance, char *buf, int len) +static ssize_t +ofw_std_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len) { static struct { cell_t name; @@ -472,8 +483,8 @@ } /* Return the fully qualified pathname corresponding to a package. */ -int -OF_package_to_path(phandle_t package, char *buf, int len) +static ssize_t +ofw_std_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len) { static struct { cell_t name; @@ -498,10 +509,10 @@ } /* Call the method in the scope of a given instance. */ -int -OF_call_method(char *method, ihandle_t instance, int nargs, int nreturns, ...) +static int +ofw_std_call_method(ofw_t ofw, ihandle_t instance, const char *method, + int nargs, int nreturns, unsigned long *args_and_returns) { - va_list ap; static struct { cell_t name; cell_t nargs; @@ -515,6 +526,7 @@ 1, }; cell_t *cp; + unsigned long *ap; int n; if (nargs > 6) @@ -523,16 +535,16 @@ args.nreturns = nreturns + 1; args.method = (cell_t)method; args.instance = instance; - va_start(ap, nreturns); + + ap = args_and_returns; for (cp = args.args_n_results + (n = nargs); --n >= 0;) - *--cp = va_arg(ap, cell_t); + *--cp = *(ap++); if (openfirmware(&args) == -1) return (-1); if (args.args_n_results[nargs]) return (args.args_n_results[nargs]); for (cp = args.args_n_results + nargs + (n = args.nreturns); --n > 0;) - *va_arg(ap, cell_t *) = *--cp; - va_end(ap); + *(ap++) = *--cp; return (0); } @@ -541,8 +553,8 @@ */ /* Open an instance for a device. */ -ihandle_t -OF_open(char *device) +static ihandle_t +ofw_std_open(ofw_t ofw, const char *device) { static struct { cell_t name; @@ -564,8 +576,8 @@ } /* Close an instance. */ -void -OF_close(ihandle_t instance) +static void +ofw_std_close(ofw_t ofw, ihandle_t instance) { static struct { cell_t name; @@ -582,8 +594,8 @@ } /* Read from an instance. */ -int -OF_read(ihandle_t instance, void *addr, int len) +static ssize_t +ofw_std_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len) { static struct { cell_t name; @@ -609,8 +621,8 @@ } /* Write to an instance. */ -int -OF_write(ihandle_t instance, void *addr, int len) +static ssize_t +ofw_std_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len) { static struct { cell_t name; @@ -635,8 +647,8 @@ } /* Seek to a position. */ -int -OF_seek(ihandle_t instance, u_int64_t pos) +static int +ofw_std_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos) { static struct { cell_t name; @@ -665,8 +677,8 @@ */ /* Claim an area of memory. */ -void * -OF_claim(void *virt, u_int size, u_int align) +static caddr_t +ofw_std_claim(ofw_t ofw, void *virt, size_t size, u_int align) { static struct { cell_t name; @@ -691,8 +703,8 @@ } /* Release an area of memory. */ -void -OF_release(void *virt, u_int size) +static void +ofw_std_release(ofw_t ofw, void *virt, size_t size) { static struct { cell_t name; @@ -714,29 +726,9 @@ * Control transfer functions */ -/* Reset the system and call "boot ". */ -void -OF_boot(char *bootspec) -{ - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t bootspec; - } args = { - (cell_t)"boot", - 1, - }; - - args.bootspec = (cell_t)bootspec; - openfirmware(&args); - for (;;) /* just in case */ - ; -} - /* Suspend and drop back to the Open Firmware interface. */ -void -OF_enter() +static void +ofw_std_enter(ofw_t ofw) { static struct { cell_t name; @@ -751,8 +743,8 @@ } /* Shut down and drop back to the Open Firmware interface. */ -void -OF_exit() +static void +ofw_std_exit(ofw_t ofw) { static struct { cell_t name; @@ -767,44 +759,3 @@ ; } -/* Free bytes starting at , then call with . */ -#if 0 -void -OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len) -{ - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t virt; - cell_t size; - cell_t entry; - cell_t arg; - cell_t len; - } args = { - (cell_t)"chain", - 5, - }; - - args.virt = (cell_t)virt; - args.size = size; - args.entry = (cell_t)entry; - args.arg = (cell_t)arg; - args.len = len; - openfirmware(&args); -} -#else -void -OF_chain(void *virt, u_int size, - void (*entry)(void *, u_int, void *, void *, u_int), void *arg, u_int len) -{ - /* - * This is a REALLY dirty hack till the firmware gets this going - */ -#if 0 - if (size > 0) - OF_release(virt, size); -#endif - entry(0, 0, openfirmware, arg, len); -} -#endif Index: dev/ofw/openfirm.c =================================================================== --- dev/ofw/openfirm.c (revision 186200) +++ dev/ofw/openfirm.c (working copy) @@ -66,23 +66,70 @@ #include #include +#include +#include "ofw_if.h" + MALLOC_DEFINE(M_OFWPROP, "openfirm", "Open Firmware properties"); static ihandle_t stdout; +static ofw_def_t *ofw_def_impl; +static ofw_t ofw_obj; +static struct ofw_kobj ofw_kernel_obj; +static struct kobj_ops ofw_kernel_kops; + +/* + * OFW install routines. Highest priority wins, equal priority also + * overrides allowing last-set to win. + */ +SET_DECLARE(ofw_set, ofw_def_t); + +boolean_t +OF_install(char *name, int prio) +{ + ofw_def_t **ofwpp, *ofwp; + static int curr_prio = 0; + + /* + * Try and locate the OFW kobj corresponding to the name + */ + SET_FOREACH(ofwpp, ofw_set) { + ofwp = *ofwpp; + + if (ofwp->name && + !strcmp(ofwp->name, name) && + prio >= curr_prio) { + curr_prio = prio; + ofw_def_impl = ofwp; + return (TRUE); + } + } + + return (FALSE); +} + /* Initialiser */ void -OF_init(int (*openfirm)(void *)) +OF_init(void *cookie) { phandle_t chosen; - set_openfirm_callback(openfirm); + ofw_obj = &ofw_kernel_obj; + /* + * Take care of compiling the selected class, and + * then statically initialise the OFW object + */ + kobj_class_compile_static(ofw_def_impl, &ofw_kernel_kops); + kobj_init((kobj_t)ofw_obj, ofw_def_impl); + + OFW_INIT(ofw_obj, cookie); + if ((chosen = OF_finddevice("/chosen")) == -1) OF_exit(); if (OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) == -1) - OF_exit(); + stdout = -1; } void @@ -103,77 +150,29 @@ /* Test to see if a service exists. */ int -OF_test(char *name) +OF_test(const char *name) { - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t service; - cell_t missing; - } args = { - (cell_t)"test", - 1, - 1, - }; - - args.service = (cell_t)name; - if (openfirmware(&args) == -1) - return (-1); - return (args.missing); + return (OFW_TEST(ofw_obj,name)); } int -OF_interpret(char *cmd, int nreturns, ...) +OF_interpret(const char *cmd, int nreturns, ...) { va_list ap; - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t slot[16]; - } args = { - (cell_t)"interpret", - 1, - }; - cell_t status; + unsigned long slots[16]; int i = 0; + int status; + status = OFW_INTERPRET(ofw_obj,cmd,nreturns,slots); + va_start(ap, nreturns); - args.nreturns = ++nreturns; - args.slot[i++] = (cell_t)cmd; - while (i < 1) - args.slot[i++] = va_arg(ap, cell_t); - if (openfirmware(&args) == -1) { - va_end(ap); - return (-1); - } - status = args.slot[i++]; while (i < 1 + nreturns) - *va_arg(ap, cell_t *) = args.slot[i++]; + *va_arg(ap, cell_t *) = slots[i++]; va_end(ap); + return (status); } -/* Return firmware millisecond count. */ -int -OF_milliseconds() -{ - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t ms; - } args = { - (cell_t)"milliseconds", - 0, - 1, - }; - - openfirmware(&args); - return (args.ms); -} - /* * Device tree functions */ @@ -182,140 +181,42 @@ phandle_t OF_peer(phandle_t node) { - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t node; - cell_t next; - } args = { - (cell_t)"peer", - 1, - 1, - }; - - args.node = node; - if (openfirmware(&args) == -1) - return (-1); - return (args.next); + return (OFW_PEER(ofw_obj,node)); } /* Return the first child of this node or 0. */ phandle_t OF_child(phandle_t node) { - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t node; - cell_t child; - } args = { - (cell_t)"child", - 1, - 1, - }; - - args.node = node; - if (openfirmware(&args) == -1) - return (-1); - return (args.child); + return (OFW_CHILD(ofw_obj,node)); } /* Return the parent of this node or 0. */ phandle_t OF_parent(phandle_t node) { - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t node; - cell_t parent; - } args = { - (cell_t)"parent", - 1, - 1, - }; - - args.node = node; - if (openfirmware(&args) == -1) - return (-1); - return (args.parent); + return (OFW_PARENT(ofw_obj,node)); } /* Return the package handle that corresponds to an instance handle. */ phandle_t OF_instance_to_package(ihandle_t instance) { - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t instance; - cell_t package; - } args = { - (cell_t)"instance-to-package", - 1, - 1, - }; - - args.instance = instance; - if (openfirmware(&args) == -1) - return (-1); - return (args.package); + return (OFW_INSTANCE_TO_PACKAGE(ofw_obj,instance)); } /* Get the length of a property of a package. */ -int -OF_getproplen(phandle_t package, char *propname) +ssize_t +OF_getproplen(phandle_t package, const char *propname) { - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t package; - cell_t propname; - cell_t proplen; - } args = { - (cell_t)"getproplen", - 2, - 1, - }; - - args.package = package; - args.propname = (cell_t)propname; - if (openfirmware(&args) == -1) - return (-1); - return (args.proplen); + return (OFW_GETPROPLEN(ofw_obj,package,propname)); } /* Get the value of a property of a package. */ -int -OF_getprop(phandle_t package, char *propname, void *buf, int buflen) +ssize_t +OF_getprop(phandle_t package, const char *propname, void *buf, size_t buflen) { - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t package; - cell_t propname; - cell_t buf; - cell_t buflen; - cell_t size; - } args = { - (cell_t)"getprop", - 4, - 1, - }; - - args.package = package; - args.propname = (cell_t)propname; - args.buf = (cell_t)buf; - args.buflen = buflen; - if (openfirmware(&args) == -1) - return (-1); - return (args.size); + return (OFW_GETPROP(ofw_obj,package,propname,buf,buflen)); } /* @@ -323,8 +224,8 @@ * (using the M_OFWPROP malloc pool and M_WAITOK). elsz is the size of a * single element, the number of elements is return in number. */ -int -OF_getprop_alloc(phandle_t package, char *propname, int elsz, void **buf) +ssize_t +OF_getprop_alloc(phandle_t package, const char *propname, int elsz, void **buf) { int len; @@ -344,194 +245,69 @@ /* Get the next property of a package. */ int -OF_nextprop(phandle_t package, char *previous, char *buf) +OF_nextprop(phandle_t package, const char *previous, char *buf, size_t size) { - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t package; - cell_t previous; - cell_t buf; - cell_t flag; - } args = { - (cell_t)"nextprop", - 3, - 1, - }; - - args.package = package; - args.previous = (cell_t)previous; - args.buf = (cell_t)buf; - if (openfirmware(&args) == -1) - return (-1); - return (args.flag); + return (OFW_NEXTPROP(ofw_obj,package,previous,buf,size)); } /* Set the value of a property of a package. */ -/* XXX Has a bug on FirePower */ int -OF_setprop(phandle_t package, char *propname, void *buf, int len) +OF_setprop(phandle_t package, const char *propname, const void *buf, size_t len) { - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t package; - cell_t propname; - cell_t buf; - cell_t len; - cell_t size; - } args = { - (cell_t)"setprop", - 4, - 1, - }; - - args.package = package; - args.propname = (cell_t)propname; - args.buf = (cell_t)buf; - args.len = len; - if (openfirmware(&args) == -1) - return (-1); - return (args.size); + return (OFW_SETPROP(ofw_obj,package,propname,buf,len)); } /* Convert a device specifier to a fully qualified pathname. */ -int -OF_canon(const char *device, char *buf, int len) +ssize_t +OF_canon(const char *device, char *buf, size_t len) { - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t device; - cell_t buf; - cell_t len; - cell_t size; - } args = { - (cell_t)"canon", - 3, - 1, - }; - - args.device = (cell_t)device; - args.buf = (cell_t)buf; - args.len = len; - if (openfirmware(&args) == -1) - return (-1); - return (args.size); + return (OFW_CANON(ofw_obj,device,buf,len)); } /* Return a package handle for the specified device. */ phandle_t OF_finddevice(const char *device) { - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t device; - cell_t package; - } args = { - (cell_t)"finddevice", - 1, - 1, - }; - - args.device = (cell_t)device; - if (openfirmware(&args) == -1) - return (-1); - return (args.package); + return (OFW_FINDDEVICE(ofw_obj,device)); } /* Return the fully qualified pathname corresponding to an instance. */ -int -OF_instance_to_path(ihandle_t instance, char *buf, int len) +ssize_t +OF_instance_to_path(ihandle_t instance, char *buf, size_t len) { - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t instance; - cell_t buf; - cell_t len; - cell_t size; - } args = { - (cell_t)"instance-to-path", - 3, - 1, - }; - - args.instance = instance; - args.buf = (cell_t)buf; - args.len = len; - if (openfirmware(&args) == -1) - return (-1); - return (args.size); + return (OFW_INSTANCE_TO_PATH(ofw_obj,instance,buf,len)); } /* Return the fully qualified pathname corresponding to a package. */ -int -OF_package_to_path(phandle_t package, char *buf, int len) +ssize_t +OF_package_to_path(phandle_t package, char *buf, size_t len) { - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t package; - cell_t buf; - cell_t len; - cell_t size; - } args = { - (cell_t)"package-to-path", - 3, - 1, - }; - - args.package = package; - args.buf = (cell_t)buf; - args.len = len; - if (openfirmware(&args) == -1) - return (-1); - return (args.size); + return (OFW_PACKAGE_TO_PATH(ofw_obj,package,buf,len)); } /* Call the method in the scope of a given instance. */ int -OF_call_method(char *method, ihandle_t instance, int nargs, int nreturns, ...) +OF_call_method(const char *method, ihandle_t instance, int nargs, int nreturns, + ...) { va_list ap; - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t method; - cell_t instance; - cell_t args_n_results[12]; - } args = { - (cell_t)"call-method", - 2, - 1, - }; - cell_t *cp; - int n; + unsigned long args_n_results[12]; + int n, status; if (nargs > 6) return (-1); - args.nargs = nargs + 2; - args.nreturns = nreturns + 1; - args.method = (cell_t)method; - args.instance = instance; va_start(ap, nreturns); - for (cp = args.args_n_results + (n = nargs); --n >= 0;) - *--cp = va_arg(ap, cell_t); - if (openfirmware(&args) == -1) - return (-1); - if (args.args_n_results[nargs]) - return (args.args_n_results[nargs]); - for (cp = args.args_n_results + nargs + (n = args.nreturns); --n > 0;) - *va_arg(ap, cell_t *) = *--cp; + for (n = 0; n < nargs; n++) + args_n_results[n] = va_arg(ap, unsigned long); + + status = OFW_CALL_METHOD(ofw_obj, instance, method, nargs, nreturns, + args_n_results); + + if (status != 0) + return (status); + + for (; n < nargs + nreturns; n++) + *va_arg(ap, unsigned long *) = args_n_results[n]; va_end(ap); return (0); } @@ -542,122 +318,37 @@ /* Open an instance for a device. */ ihandle_t -OF_open(char *device) +OF_open(const char *device) { - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t device; - cell_t instance; - } args = { - (cell_t)"open", - 1, - 1, - }; - - args.device = (cell_t)device; - if (openfirmware(&args) == -1 || args.instance == 0) { - return (-1); - } - return (args.instance); + return (OFW_OPEN(ofw_obj, device)); } /* Close an instance. */ void OF_close(ihandle_t instance) { - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t instance; - } args = { - (cell_t)"close", - 1, - }; - - args.instance = instance; - openfirmware(&args); + OFW_CLOSE(ofw_obj, instance); } /* Read from an instance. */ -int -OF_read(ihandle_t instance, void *addr, int len) +ssize_t +OF_read(ihandle_t instance, void *addr, size_t len) { - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t instance; - cell_t addr; - cell_t len; - cell_t actual; - } args = { - (cell_t)"read", - 3, - 1, - }; - - args.instance = instance; - args.addr = (cell_t)addr; - args.len = len; - if (openfirmware(&args) == -1) - return (-1); - - return (args.actual); + return (OFW_READ(ofw_obj, instance, addr, len)); } /* Write to an instance. */ -int -OF_write(ihandle_t instance, void *addr, int len) +ssize_t +OF_write(ihandle_t instance, const void *addr, size_t len) { - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t instance; - cell_t addr; - cell_t len; - cell_t actual; - } args = { - (cell_t)"write", - 3, - 1, - }; - - args.instance = instance; - args.addr = (cell_t)addr; - args.len = len; - if (openfirmware(&args) == -1) - return (-1); - return (args.actual); + return (OFW_WRITE(ofw_obj, instance, addr, len)); } /* Seek to a position. */ int -OF_seek(ihandle_t instance, u_int64_t pos) +OF_seek(ihandle_t instance, uint64_t pos) { - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t instance; - cell_t poshi; - cell_t poslo; - cell_t status; - } args = { - (cell_t)"seek", - 3, - 1, - }; - - args.instance = instance; - args.poshi = pos >> 32; - args.poslo = pos; - if (openfirmware(&args) == -1) - return (-1); - return (args.status); + return (OFW_SEEK(ofw_obj, instance, pos)); } /* @@ -666,145 +357,37 @@ /* Claim an area of memory. */ void * -OF_claim(void *virt, u_int size, u_int align) +OF_claim(void *virt, size_t size, u_int align) { - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t virt; - cell_t size; - cell_t align; - cell_t baseaddr; - } args = { - (cell_t)"claim", - 3, - 1, - }; - - args.virt = (cell_t)virt; - args.size = size; - args.align = align; - if (openfirmware(&args) == -1) - return ((void *)-1); - return ((void *)args.baseaddr); + return (OFW_CLAIM(ofw_obj, virt, size, align)); } /* Release an area of memory. */ void -OF_release(void *virt, u_int size) +OF_release(void *virt, size_t size) { - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t virt; - cell_t size; - } args = { - (cell_t)"release", - 2, - }; - - args.virt = (cell_t)virt; - args.size = size; - openfirmware(&args); + OFW_RELEASE(ofw_obj, virt, size); } /* * Control transfer functions */ -/* Reset the system and call "boot ". */ -void -OF_boot(char *bootspec) -{ - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t bootspec; - } args = { - (cell_t)"boot", - 1, - }; - - args.bootspec = (cell_t)bootspec; - openfirmware(&args); - for (;;) /* just in case */ - ; -} - /* Suspend and drop back to the Open Firmware interface. */ void OF_enter() { - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - } args = { - (cell_t)"enter", - }; - - openfirmware(&args); - /* We may come back. */ + OFW_ENTER(ofw_obj); } /* Shut down and drop back to the Open Firmware interface. */ void OF_exit() { - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - } args = { - (cell_t)"exit", - }; + /* Should not return */ + OFW_EXIT(ofw_obj); - openfirmware(&args); for (;;) /* just in case */ ; } -/* Free bytes starting at , then call with . */ -#if 0 -void -OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len) -{ - static struct { - cell_t name; - cell_t nargs; - cell_t nreturns; - cell_t virt; - cell_t size; - cell_t entry; - cell_t arg; - cell_t len; - } args = { - (cell_t)"chain", - 5, - }; - - args.virt = (cell_t)virt; - args.size = size; - args.entry = (cell_t)entry; - args.arg = (cell_t)arg; - args.len = len; - openfirmware(&args); -} -#else -void -OF_chain(void *virt, u_int size, - void (*entry)(void *, u_int, void *, void *, u_int), void *arg, u_int len) -{ - /* - * This is a REALLY dirty hack till the firmware gets this going - */ -#if 0 - if (size > 0) - OF_release(virt, size); -#endif - entry(0, 0, openfirmware, arg, len); -} -#endif Index: dev/ofw/ofw_if.m =================================================================== --- dev/ofw/ofw_if.m (revision 0) +++ dev/ofw/ofw_if.m (revision 0) @@ -0,0 +1,357 @@ +#- +# Copyright (c) 2008 Nathan Whitehorn +# 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. +# +# $FreeBSD$ +# + +#include +#include + +/** + * @defgroup OFW ofw - KObj methods for Open Firmware RTAS implementations + * @brief A set of methods to implement the Open Firmware client side interface. + *@{ + */ + +INTERFACE ofw; + +/** + * @brief Initialize OFW client interface + * + * @param _cookie A handle to the client interface, generally the OF + * callback routine. + */ +METHOD void init { + ofw_t _ofw; + void *_cookie; +}; + +/** + * @brief Return next sibling of node + * + * @param _node Selected node + */ +METHOD phandle_t peer { + ofw_t _ofw; + phandle_t _node; +}; + +/** + * @brief Return parent of node + * + * @param _node Selected node + */ +METHOD phandle_t parent { + ofw_t _ofw; + phandle_t _node; +}; + +/** + * @brief Return first child of node + * + * @param _node Selected node + */ +METHOD phandle_t child { + ofw_t _ofw; + phandle_t _node; +}; + +/** + * @brief Return package corresponding to instance + * + * @param _handle Selected instance + */ +METHOD phandle_t instance_to_package { + ofw_t _ofw; + ihandle_t _handle; +}; + +/** + * @brief Return length of node property + * + * @param _node Selected node + * @param _prop Property name + */ +METHOD ssize_t getproplen { + ofw_t _ofw; + phandle_t _node; + const char *_prop; +}; + +/** + * @brief Read node property + * + * @param _node Selected node + * @param _prop Property name + * @param _buf Pointer to buffer + * @param _size Size of buffer + */ +METHOD ssize_t getprop { + ofw_t _ofw; + phandle_t _node; + const char *_prop; + void *_buf; + size_t _size; +}; + +/** + * @brief Get next property name + * + * @param _node Selected node + * @param _prop Current property name + * @param _buf Buffer for next property name + * @param _size Size of buffer + */ +METHOD int nextprop { + ofw_t _ofw; + phandle_t _node; + const char *_prop; + char *_buf; + size_t _size; +}; + +/** + * @brief Set property + * + * @param _node Selected node + * @param _prop Property name + * @param _buf Value to set + * @param _size Size of buffer + */ +METHOD int setprop { + ofw_t _ofw; + phandle_t _node; + const char *_prop; + const void *_buf; + size_t _size; +}; + +/** + * @brief Canonicalize path + * + * @param _path Path to canonicalize + * @param _buf Buffer for canonicalized path + * @param _size Size of buffer + */ +METHOD ssize_t canon { + ofw_t _ofw; + const char *_path; + char *_buf; + size_t _size; +}; + +/** + * @brief Return phandle for named device + * + * @param _path Device path + */ +METHOD phandle_t finddevice { + ofw_t _ofw; + const char *_path; +}; + +/** + * @brief Return path for node instance + * + * @param _handle Instance handle + * @param _path Buffer for path + * @param _size Size of buffer + */ +METHOD ssize_t instance_to_path { + ofw_t _ofw; + ihandle_t _handle; + char *_path; + size_t _size; +}; + +/** + * @brief Return path for node + * + * @param _node Package node + * @param _path Buffer for path + * @param _size Size of buffer + */ +METHOD ssize_t package_to_path { + ofw_t _ofw; + phandle_t _node; + char *_path; + size_t _size; +}; + + +# Methods for OF method calls (optional) + +/** + * @brief Test to see if a service exists. + * + * @param _name name of the service + */ +METHOD int test { + ofw_t _ofw; + const char *_name; +}; + +/** + * @brief Call method belonging to an instance handle + * + * @param _instance Instance handle + * @param _method Method name + * @param _nargs Number of arguments + * @param _nreturns Number of return values + * @param _args_and_returns Values for arguments, followed by returns + */ + +METHOD int call_method { + ofw_t _ofw; + ihandle_t _instance; + const char *_method; + int _nargs; + int _nreturns; + + unsigned long *_args_and_returns; +}; + +/** + * @brief Interpret a forth command + * + * @param _cmd Command + * @param _nreturns Number of return values + * @param _returns Values for returns + */ + +METHOD int interpret { + ofw_t _ofw; + const char *_cmd; + int _nreturns; + unsigned long *_returns; +}; + +# Device I/O Functions (optional) + +/** + * @brief Open node, returning instance handle + * + * @param _path Path to node + */ +METHOD ihandle_t open { + ofw_t _ofw; + const char *_path; +} + +/** + * @brief Close node instance + * + * @param _instance Instance to close + */ +METHOD void close { + ofw_t _ofw; + ihandle_t _instance; +} + +/** + * @brief Read from device + * + * @param _instance Device instance + * @param _buf Buffer to read to + * @param _size Size of buffer + */ +METHOD ssize_t read { + ofw_t _ofw; + ihandle_t _instance; + void *_buf; + size_t size; +} + +/** + * @brief Write to device + * + * @param _instance Device instance + * @param _buf Buffer to write from + * @param _size Size of buffer + */ +METHOD ssize_t write { + ofw_t _ofw; + ihandle_t _instance; + const void *_buf; + size_t size; +} + +/** + * @brief Seek device + * + * @param _instance Device instance + * @param _off Offset to which to seek + */ +METHOD int seek { + ofw_t _ofw; + ihandle_t _instance; + uint64_t _off; +} + +# Open Firmware memory management + +/** + * @brief Claim virtual memory + * + * @param _addr Requested memory location (NULL for first available) + * @param _size Requested size in bytes + * @param _align Requested alignment + */ +METHOD caddr_t claim { + ofw_t _ofw; + void *_addr; + size_t _size; + u_int _align; +} + +/** + * @brief Release virtual memory + * + * @param _addr Memory location + * @param _size Size in bytes + */ +METHOD void release { + ofw_t _ofw; + void *_addr; + size_t _size; +}; + +# Commands for returning control to the firmware + +/** + * @brief Temporarily return control to firmware + */ +METHOD void enter { + ofw_t _ofw; +}; + +/** + * @brief Halt and return control to firmware + */ +METHOD void exit { + ofw_t _ofw; +}; + + Property changes on: dev/ofw/ofw_if.m ___________________________________________________________________ Added: svn:keywords + FreeBSD=%H Index: dev/ofw/openfirm.h =================================================================== --- dev/ofw/openfirm.h (revision 186200) +++ dev/ofw/openfirm.h (working copy) @@ -60,84 +60,82 @@ #ifndef _OPENFIRM_H_ #define _OPENFIRM_H_ +#include + /* * Prototypes for Open Firmware Interface Routines */ -typedef unsigned long cell_t; +typedef uint32_t ihandle_t; +typedef uint32_t phandle_t; +typedef uint32_t pcell_t; -typedef unsigned int ihandle_t; -typedef unsigned int phandle_t; - #ifdef _KERNEL -#include -#include #include +#include + MALLOC_DECLARE(M_OFWPROP); /* - * Other than in Open Firmware calls, the size of a bus cell seems to be - * always the same. + * Open Firmware interface initialization. OF_install installs the named + * interface as the Open Firmware access mechanism, OF_init initializes it. */ -typedef u_int32_t pcell_t; -/* - * Stuff that is used by the Open Firmware code. - */ -void set_openfirm_callback(int (*)(void *)); -int openfirmware(void *); +boolean_t OF_install(char *name, int prio); +void OF_init(void *cookie); /* - * This isn't actually an Open Firmware function, but it seemed like the right - * place for it to go. + * Known Open Firmware interface names */ -void OF_init(int (*openfirm)(void *)); +#define OFW_STD_DIRECT "ofw_std" /* Standard OF interface */ +#define OFW_STD_REAL "ofw_real" /* Real-mode OF interface */ +#define OFW_FDT "ofw_fdt" /* Flattened Device Tree */ + /* Generic functions */ -int OF_test(char *); +int OF_test(const char *); void OF_printf(const char *, ...); /* Device tree functions */ -phandle_t OF_peer(phandle_t); -phandle_t OF_child(phandle_t); -phandle_t OF_parent(phandle_t); -phandle_t OF_instance_to_package(ihandle_t); -int OF_getproplen(phandle_t, char *); -int OF_getprop(phandle_t, char *, void *, int); -int OF_getprop_alloc(phandle_t package, char *propname, int elsz, - void **buf); -int OF_nextprop(phandle_t, char *, char *); -int OF_setprop(phandle_t, char *, void *, int); -int OF_canon(const char *, char *, int); -phandle_t OF_finddevice(const char *); -int OF_instance_to_path(ihandle_t, char *, int); -int OF_package_to_path(phandle_t, char *, int); -int OF_call_method(char *, ihandle_t, int, int, ...); +phandle_t OF_peer(phandle_t node); +phandle_t OF_child(phandle_t node); +phandle_t OF_parent(phandle_t node); +ssize_t OF_getproplen(phandle_t node, const char *propname); +ssize_t OF_getprop(phandle_t node, const char *propname, void *buf, + size_t len); +ssize_t OF_getprop_alloc(phandle_t node, const char *propname, + int elsz, void **buf); +int OF_nextprop(phandle_t node, const char *propname, char *buf, + size_t len); +int OF_setprop(phandle_t node, const char *name, const void *buf, + size_t len); +ssize_t OF_canon(const char *path, char *buf, size_t len); +phandle_t OF_finddevice(const char *path); +ssize_t OF_package_to_path(phandle_t node, char *buf, size_t len); /* Device I/O functions */ -ihandle_t OF_open(char *); -void OF_close(ihandle_t); -int OF_read(ihandle_t, void *, int); -int OF_write(ihandle_t, void *, int); -int OF_seek(ihandle_t, u_quad_t); +ihandle_t OF_open(const char *path); +void OF_close(ihandle_t instance); +ssize_t OF_read(ihandle_t instance, void *buf, size_t len); +ssize_t OF_write(ihandle_t instance, const void *buf, size_t len); +int OF_seek(ihandle_t instance, uint64_t where); +phandle_t OF_instance_to_package(ihandle_t instance); +ssize_t OF_instance_to_path(ihandle_t instance, char *buf, size_t len); +int OF_call_method(const char *method, ihandle_t instance, + int nargs, int nreturns, ...); + /* Memory functions */ -void *OF_claim(void *, u_int, u_int); -void OF_release(void *, u_int); +void *OF_claim(void *virtrequest, size_t size, u_int align); +void OF_release(void *virt, size_t size); /* Control transfer functions */ -void OF_boot(char *); void OF_enter(void); void OF_exit(void) __attribute__((noreturn)); -void OF_chain(void *, u_int, - void (*)(void *, u_int, void *, void *, u_int), void *, u_int); /* User interface functions */ -int OF_interpret(char *, int, ...); +int OF_interpret(const char *cmd, int nreturns, ...); -/* Time function */ -int OF_milliseconds(void); - #endif /* _KERNEL */ #endif /* _OPENFIRM_H_ */ Index: dev/ofw/openpromio.c =================================================================== --- dev/ofw/openpromio.c (revision 186200) +++ dev/ofw/openpromio.c (working copy) @@ -174,7 +174,7 @@ error = OF_getprop(node, prop, buf, proplen); break; case OPROMNXTPROP: - error = OF_nextprop(node, prop, buf); + error = OF_nextprop(node, prop, buf, OPROMMAXPARAM); proplen = strlen(buf); break; } Index: sparc64/sparc64/vm_machdep.c =================================================================== --- sparc64/sparc64/vm_machdep.c (revision 186200) +++ sparc64/sparc64/vm_machdep.c (working copy) @@ -334,7 +334,7 @@ bspec[sizeof(bspec) - 1] = '\0'; } - openfirmware_exit(&args); + ofw_exit(&args); } /* Index: sparc64/sparc64/mp_machdep.c =================================================================== --- sparc64/sparc64/mp_machdep.c (revision 186200) +++ sparc64/sparc64/mp_machdep.c (working copy) @@ -221,7 +221,7 @@ args.cpu = cpu; args.func = (cell_t)func; args.arg = (cell_t)arg; - openfirmware(&args); + ofw_entry(&args); } /* @@ -238,7 +238,7 @@ (cell_t)SUNW_STOPSELF, }; - openfirmware_exit(&args); + ofw_exit(&args); panic("%s: failed.", __func__); } Index: sparc64/sparc64/machdep.c =================================================================== --- sparc64/sparc64/machdep.c (revision 186200) +++ sparc64/sparc64/machdep.c (working copy) @@ -276,9 +276,10 @@ tick_stop(); /* - * Initialize Open Firmware (needed for console). + * Set up Open Firmware entry points */ - OF_init(vec); + ofw_tba = rdpr(tba); + ofw_vec = (u_long)vec; /* * Parse metadata if present and fetch parameters. Must be before the @@ -301,6 +302,12 @@ init_param1(); /* + * Initialize Open Firmware (needed for console). + */ + OF_install(OFW_STD_DIRECT, 0); + OF_init(ofw_entry); + + /* * Prime our per-CPU data page for use. Note, we are using it for * our stack, so don't pass the real size (PAGE_SIZE) to pcpu_init * or it'll zero it out from under us. @@ -481,14 +488,6 @@ } void -set_openfirm_callback(ofw_vec_t *vec) -{ - - ofw_tba = rdpr(tba); - ofw_vec = (u_long)vec; -} - -void sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) { struct trapframe *tf; @@ -725,7 +724,7 @@ #ifdef SMP cpu_mp_shutdown(); #endif - openfirmware_exit(args); + ofw_exit(args); } /* Get current clock frequency for the given CPU ID. */ Index: sparc64/sparc64/trap.c =================================================================== --- sparc64/sparc64/trap.c (revision 186200) +++ sparc64/sparc64/trap.c (working copy) @@ -71,6 +71,7 @@ #include #include +#include #include #include @@ -248,7 +249,7 @@ }; args.tba_addr = (cell_t)tba_addr; - openfirmware(&args); + ofw_entry(&args); } void Index: sparc64/sparc64/support.S =================================================================== --- sparc64/sparc64/support.S (revision 186200) +++ sparc64/sparc64/support.S (working copy) @@ -745,9 +745,9 @@ END(setjmp) /* - * void openfirmware(cell_t args[]) + * void ofw_entry(cell_t args[]) */ -ENTRY(openfirmware) +ENTRY(ofw_entry) save %sp, -CCFSZ, %sp SET(ofw_vec, %l7, %l6) ldx [%l6], %l6 @@ -758,12 +758,12 @@ wrpr %l7, 0, %pil ret restore %o0, %g0, %o0 -END(openfirmware) +END(ofw_entry) /* - * void openfirmware_exit(cell_t args[]) + * void ofw_exit(cell_t args[]) */ -ENTRY(openfirmware_exit) +ENTRY(ofw_exit) save %sp, -CCFSZ, %sp flushw wrpr %g0, PIL_TICK, %pil @@ -783,7 +783,7 @@ call %l6 mov %i0, %o0 ! never to return -END(openfirmware_exit) +END(ofw_exit) #ifdef GPROF Index: sparc64/include/ofw_machdep.h =================================================================== --- sparc64/include/ofw_machdep.h (revision 186200) +++ sparc64/include/ofw_machdep.h (working copy) @@ -29,10 +29,15 @@ #define _MACHINE_OFW_MACHDEP_H_ #include +#include +#include +typedef uint64_t cell_t; + int OF_decode_addr(phandle_t, int, int *, bus_addr_t *); void OF_getetheraddr(device_t, u_char *); void cpu_shutdown(void *); -void openfirmware_exit(void *); +int ofw_entry(void *); +void ofw_exit(void *); #endif /* _MACHINE_OFW_MACHDEP_H_ */ Index: sun4v/sun4v/mp_machdep.c =================================================================== --- sun4v/sun4v/mp_machdep.c (revision 186200) +++ sun4v/sun4v/mp_machdep.c (working copy) @@ -272,7 +272,7 @@ args.cpuid = cpuid; args.func = (cell_t)func; args.arg = (cell_t)arg; - openfirmware(&args); + ofw_entry(&args); return (int)args.result; } Index: sun4v/sun4v/machdep.c =================================================================== --- sun4v/sun4v/machdep.c (revision 186200) +++ sun4v/sun4v/machdep.c (working copy) @@ -310,18 +310,18 @@ end = 0; kmdp = NULL; - /* - * Initialize Open Firmware (needed for console). - */ - OF_init(vec); - - /* * XXX */ bootverbose = 1; /* + * Set up Open Firmware entry points + */ + ofw_tba = rdpr(tba); + ofw_vec = (u_long)vec; + + /* * Parse metadata if present and fetch parameters. Must be before the * console is inited so cninit gets the right value of boothowto. */ @@ -344,6 +344,12 @@ init_param1(); + /* + * Initialize Open Firmware (needed for console). + */ + OF_install(OFW_STD_DIRECT, 0); + OF_init(ofw_entry); + root = OF_peer(0); for (child = OF_child(root); child != 0; child = OF_peer(child)) { OF_getprop(child, "device_type", type, sizeof(type)); @@ -516,13 +522,6 @@ } void -set_openfirm_callback(ofw_vec_t *vec) -{ - ofw_tba = rdpr(tba); - ofw_vec = (u_long)vec; -} - -void sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) { struct trapframe *tf; Index: sun4v/sun4v/trap.c =================================================================== --- sun4v/sun4v/trap.c (revision 186200) +++ sun4v/sun4v/trap.c (working copy) @@ -261,7 +261,7 @@ args.tba_addr = (cell_t)tba_addr; args.mmfsa_ra = mmfsa_ra; - openfirmware(&args); + ofw_entry(&args); } void Index: sun4v/sun4v/support.S =================================================================== --- sun4v/sun4v/support.S (revision 186200) +++ sun4v/sun4v/support.S (working copy) @@ -622,9 +622,9 @@ END(setjmp) /* - * void openfirmware(cell_t args[]) + * void ofw_entry(cell_t args[]) */ -ENTRY(openfirmware) +ENTRY(ofw_entry) save %sp, -CCFSZ, %sp SET(ofw_vec, %l7, %l6) ldx [%l6], %l6 @@ -635,14 +635,14 @@ wrpr %l7, 0, %pil ret restore %o0, %g0, %o0 -END(openfirmware) +END(ofw_entry) #ifdef notyet /* SUN4V_FIXME - uses a now illegal ASI */ /* * void ofw_exit(cell_t args[]) */ -ENTRY(openfirmware_exit) +ENTRY(ofw_exit) save %sp, -CCFSZ, %sp flushw wrpr %g0, PIL_TICK, %pil @@ -661,7 +661,7 @@ call %l6 mov %i0, %o0 ! never to return -END(openfirmware_exit) +END(ofw_exit) #endif ENTRY(set_mmfsa_scratchpad) Index: powerpc/booke/machdep.c =================================================================== --- powerpc/booke/machdep.c (revision 186200) +++ powerpc/booke/machdep.c (working copy) @@ -427,7 +427,6 @@ if (boothowto & RB_KDB) kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); #endif - kobj_machdep_init(); /* Initialise virtual memory. */ pmap_mmu_install(MMU_TYPE_BOOKE, 0); Index: powerpc/powerpc/pmap_dispatch.c =================================================================== --- powerpc/powerpc/pmap_dispatch.c (revision 186200) +++ powerpc/powerpc/pmap_dispatch.c (working copy) @@ -37,9 +37,8 @@ * the highest priority call will be installed as the default * MMU handler when pmap_bootstrap() is called. * - * It is required that kobj_machdep_init() be called before - * pmap_bootstrap() to allow the kobj subsystem to initialise. This - * in turn requires that mutex_init() has been called. + * It is required that mutex_init() be called before pmap_bootstrap(), + * as the PMAP layer makes extensive use of mutexes. */ #include Index: powerpc/include/ofw_machdep.h =================================================================== --- powerpc/include/ofw_machdep.h (revision 186200) +++ powerpc/include/ofw_machdep.h (working copy) @@ -28,9 +28,18 @@ #ifndef _MACHINE_OFW_MACHDEP_H_ #define _MACHINE_OFW_MACHDEP_H_ +#include +#include +#include #include +#include +typedef uint32_t cell_t; + int OF_decode_addr(phandle_t, int, bus_space_tag_t *, bus_space_handle_t *); void OF_getetheraddr(device_t dev, u_char *addr); +void OF_initial_setup(void *fdt_ptr, void *junk, int (*openfirm)(void *)); +boolean_t OF_bootstrap(void); + #endif /* _MACHINE_OFW_MACHDEP_H_ */ Index: powerpc/aim/machdep.c =================================================================== --- powerpc/aim/machdep.c (revision 186200) +++ powerpc/aim/machdep.c (working copy) @@ -291,9 +291,19 @@ __asm __volatile("mtsprg 0, %0" :: "r"(pc)); + /* + * Init mutexes, which we use heavily in PMAP + */ + mutex_init(); /* + * Install the OF client interface + */ + + OF_bootstrap(); + + /* * Initialize the console before printing anything. */ cninit(); @@ -307,8 +317,6 @@ kdb_init(); - kobj_machdep_init(); - /* * XXX: Initialize the interrupt tables. * Disable translation in case the vector area Index: powerpc/aim/locore.S =================================================================== --- powerpc/aim/locore.S (revision 186200) +++ powerpc/aim/locore.S (working copy) @@ -129,14 +129,6 @@ .text .globl __start __start: -#ifdef FIRMWORKSBUGS - mfmsr 0 - andi. 0,0,PSL_IR|PSL_DR - beq 1f - - bl ofwr_init -1: -#endif li 8,0 li 9,0x100 mtctr 9 @@ -154,7 +146,6 @@ lis 8,openfirmware_entry@ha stw 5,openfirmware_entry@l(8) /* save client interface handler */ - mr 3,5 lis 1,(tmpstk+TMPSTKSZ-16)@ha addi 1,1,(tmpstk+TMPSTKSZ-16)@l @@ -172,7 +163,7 @@ mfsprg3 0 stw 0,16(9) /* ofmsr[4] = sprg3 */ - bl OF_init + bl OF_initial_setup lis 4,end@ha addi 4,4,end@l Index: powerpc/aim/ofw_machdep.c =================================================================== --- powerpc/aim/ofw_machdep.c (revision 186200) +++ powerpc/aim/ofw_machdep.c (working copy) @@ -65,7 +65,11 @@ extern register_t ofmsr[5]; extern struct pmap ofw_pmap; static int (*ofwcall)(void *); +static void *fdt; +int ofw_real_mode; +static int openfirmware(void *args); + /* * Saved SPRG0-3 from OpenFirmware. Will be restored prior to the callback. */ @@ -192,13 +196,45 @@ } void -set_openfirm_callback(int (*openfirm)(void *)) +OF_initial_setup(void *fdt_ptr, void *junk, int (*openfirm)(void *)) { + if (ofmsr[0] & PSL_DR) + ofw_real_mode = 0; + else + ofw_real_mode = 1; ofwcall = openfirm; + fdt = fdt_ptr; } -int +boolean_t +OF_bootstrap() +{ + boolean_t status = FALSE; + + if (ofwcall != NULL) { + if (ofw_real_mode) + status = OF_install(OFW_STD_REAL, 0); + else + status = OF_install(OFW_STD_DIRECT, 0); + + if (status != TRUE) + return status; + + OF_init(openfirmware); + } else { + status = OF_install(OFW_FDT, 0); + + if (status != TRUE) + return status; + + OF_init(fdt); + } + + return (status); +} + +static int openfirmware(void *args) { long oldmsr; @@ -206,6 +242,9 @@ u_int srsave[16]; u_int i; + if (pmap_bootstrapped && ofw_real_mode) + args = (void *)pmap_kextract((vm_offset_t)args); + __asm __volatile( "\t" "sync\n\t" "mfmsr %0\n\t" @@ -217,7 +256,7 @@ ofw_sprg_prepare(); - if (pmap_bootstrapped) { + if (pmap_bootstrapped && !ofw_real_mode) { /* * Swap the kernel's address space with Open Firmware's */ @@ -236,7 +275,7 @@ result = ofwcall(args); - if (pmap_bootstrapped) { + if (pmap_bootstrapped && !ofw_real_mode) { /* * Restore the kernel's addr space. The isync() doesn;t * work outside the loop unless mtsrin() is open-coded Index: conf/files.powerpc =================================================================== --- conf/files.powerpc (revision 186200) +++ conf/files.powerpc (working copy) @@ -30,9 +30,11 @@ dev/ofw/openfirm.c optional aim dev/ofw/openfirmio.c optional aim dev/ofw/ofw_bus_if.m optional aim +dev/ofw/ofw_if.m optional aim dev/ofw/ofw_bus_subr.c optional aim dev/ofw/ofw_console.c optional aim dev/ofw/ofw_disk.c optional ofwd aim +dev/ofw/ofw_standard.c optional aim dev/powermac_nvram/powermac_nvram.c optional powermac_nvram powermac dev/quicc/quicc_bfe_ocp.c optional quicc mpc85xx dev/scc/scc_bfe_macio.c optional scc powermac Index: conf/files.sparc64 =================================================================== --- conf/files.sparc64 (revision 186200) +++ conf/files.sparc64 (working copy) @@ -42,8 +42,10 @@ dev/le/if_le_lebuffer.c optional le sbus dev/le/if_le_ledma.c optional le sbus dev/le/lebuffer_sbus.c optional le sbus +dev/ofw/ofw_if.m standard dev/ofw/ofw_bus_if.m standard dev/ofw/ofw_bus_subr.c standard +dev/ofw/ofw_standard.c standard dev/ofw/ofw_console.c optional ofw_console dev/ofw/openfirm.c standard dev/ofw/openfirmio.c standard Index: conf/files.sun4v =================================================================== --- conf/files.sun4v (revision 186200) +++ conf/files.sun4v (working copy) @@ -21,8 +21,10 @@ crypto/blowfish/bf_enc.c optional crypto | ipsec crypto/des/des_enc.c optional crypto | ipsec | netsmb dev/ofw/ofw_bus_if.m standard +dev/ofw/ofw_if.m standard dev/ofw/ofw_bus_subr.c standard dev/ofw/ofw_console.c optional ofw_console +dev/ofw/ofw_standard.c standard dev/ofw/openfirm.c standard dev/ofw/openfirmio.c standard dev/ofw/openpromio.c standard Index: kern/subr_kobj.c =================================================================== --- kern/subr_kobj.c (revision 186200) +++ kern/subr_kobj.c (working copy) @@ -60,6 +60,19 @@ static int kobj_mutex_inited; static int kobj_next_id = 1; +/* + * In the event that kobj_mtx has not been initialized yet, + * we will ignore it, and run without locks in order to support + * use of KOBJ before mutexes are available. This early in the boot + * process, everything is single threaded and so races should not + * happen. This is used to provide the PMAP layer on PowerPC, as well + * as board support. + */ + +#define KOBJ_LOCK() if (kobj_mutex_inited) mtx_lock(&kobj_mtx); +#define KOBJ_UNLOCK() if (kobj_mutex_inited) mtx_unlock(&kobj_mtx); +#define KOBJ_ASSERT(what) if (kobj_mutex_inited) mtx_assert(&kobj_mtx,what); + SYSCTL_UINT(_kern, OID_AUTO, kobj_methodcount, CTLFLAG_RD, &kobj_next_id, 0, ""); @@ -74,12 +87,6 @@ SYSINIT(kobj, SI_SUB_LOCK, SI_ORDER_ANY, kobj_init_mutex, NULL); -void -kobj_machdep_init(void) -{ - kobj_init_mutex(NULL); -} - /* * This method structure is used to initialise new caches. Since the * desc pointer is NULL, it is guaranteed never to match any read @@ -99,8 +106,8 @@ static void kobj_register_method(struct kobjop_desc *desc) { + KOBJ_ASSERT(MA_OWNED); - mtx_assert(&kobj_mtx, MA_OWNED); if (desc->id == 0) { desc->id = kobj_next_id++; } @@ -117,7 +124,7 @@ kobj_method_t *m; int i; - mtx_assert(&kobj_mtx, MA_OWNED); + KOBJ_ASSERT(MA_OWNED); /* * Don't do anything if we are already compiled. @@ -145,7 +152,7 @@ { kobj_ops_t ops; - mtx_assert(&kobj_mtx, MA_NOTOWNED); + KOBJ_ASSERT(MA_NOTOWNED); /* * Allocate space for the compiled ops table. @@ -154,7 +161,7 @@ if (!ops) panic("kobj_compile_methods: out of memory"); - mtx_lock(&kobj_mtx); + KOBJ_LOCK(); /* * We may have lost a race for kobj_class_compile here - check @@ -162,28 +169,30 @@ * class. */ if (cls->ops) { - mtx_unlock(&kobj_mtx); + KOBJ_UNLOCK(); free(ops, M_KOBJ); return; } kobj_class_compile_common(cls, ops); - mtx_unlock(&kobj_mtx); + KOBJ_UNLOCK(); } void kobj_class_compile_static(kobj_class_t cls, kobj_ops_t ops) { - mtx_assert(&kobj_mtx, MA_NOTOWNED); + KOBJ_ASSERT(MA_NOTOWNED); /* * Increment refs to make sure that the ops table is not freed. */ - mtx_lock(&kobj_mtx); + KOBJ_LOCK(); + cls->refs++; kobj_class_compile_common(cls, ops); - mtx_unlock(&kobj_mtx); + + KOBJ_UNLOCK(); } static kobj_method_t* @@ -254,8 +263,8 @@ kobj_method_t *m; void* ops = 0; - mtx_assert(&kobj_mtx, MA_NOTOWNED); - mtx_lock(&kobj_mtx); + KOBJ_ASSERT(MA_NOTOWNED); + KOBJ_LOCK(); /* * Protect against a race between kobj_create and @@ -275,7 +284,7 @@ cls->ops = 0; } - mtx_unlock(&kobj_mtx); + KOBJ_UNLOCK(); if (ops) free(ops, M_KOBJ); @@ -302,9 +311,9 @@ void kobj_init(kobj_t obj, kobj_class_t cls) { - mtx_assert(&kobj_mtx, MA_NOTOWNED); + KOBJ_ASSERT(MA_NOTOWNED); retry: - mtx_lock(&kobj_mtx); + KOBJ_LOCK(); /* * Consider compiling the class' method table. @@ -315,7 +324,7 @@ * because of the call to malloc - we drop the lock * and re-try. */ - mtx_unlock(&kobj_mtx); + KOBJ_UNLOCK(); kobj_class_compile(cls); goto retry; } @@ -323,7 +332,7 @@ obj->ops = cls->ops; cls->refs++; - mtx_unlock(&kobj_mtx); + KOBJ_UNLOCK(); } void @@ -337,11 +346,11 @@ * after its last instance is deleted. As an optimisation, we * should defer this for a short while to avoid thrashing. */ - mtx_assert(&kobj_mtx, MA_NOTOWNED); - mtx_lock(&kobj_mtx); + KOBJ_ASSERT(MA_NOTOWNED); + KOBJ_LOCK(); cls->refs--; refs = cls->refs; - mtx_unlock(&kobj_mtx); + KOBJ_UNLOCK(); if (!refs) kobj_class_free(cls); Index: sys/kobj.h =================================================================== --- sys/kobj.h (revision 186200) +++ sys/kobj.h (working copy) @@ -246,9 +246,4 @@ */ int kobj_error_method(void); -/* - * Machine-dependent initialisation call for boot-time kobj clients - */ -void kobj_machdep_init(void); - #endif /* !_SYS_KOBJ_H_ */