Changeset View
Changeset View
Standalone View
Standalone View
stand/libofw/openfirm.c
| Show First 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | |||||
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
| * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||||
| * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| */ | */ | ||||
| #include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
| __FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
| #include <sys/endian.h> | |||||
| #include <machine/stdarg.h> | #include <machine/stdarg.h> | ||||
| #include <stand.h> | #include <stand.h> | ||||
| #include "openfirm.h" | #include "openfirm.h" | ||||
| int (*openfirmware)(void *); | int (*openfirmware)(void *); | ||||
| phandle_t chosen; | phandle_t chosen; | ||||
| ihandle_t mmu; | ihandle_t mmu; | ||||
| ihandle_t memory; | ihandle_t memory; | ||||
| int real_mode = 0; | int real_mode = 0; | ||||
| #define IN(x) htobe32((cell_t)x) | |||||
| #define OUT(x) be32toh(x) | |||||
| #define SETUP(a, b, c, d) \ | |||||
| a.name = IN( (b) ); \ | |||||
| a.nargs = IN( (c) ); \ | |||||
| a.nreturns = IN( (d) ); | |||||
| /* Initialiser */ | /* Initialiser */ | ||||
| void | void | ||||
| OF_init(int (*openfirm)(void *)) | OF_init(int (*openfirm)(void *)) | ||||
| { | { | ||||
| phandle_t options; | phandle_t options; | ||||
| char mode[sizeof("true")]; | char mode[sizeof("true")]; | ||||
| Show All 30 Lines | |||||
| OF_test(char *name) | OF_test(char *name) | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| cell_t service; | cell_t service; | ||||
| cell_t missing; | cell_t missing; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"test", | SETUP(args, "test", 1, 1); | ||||
| 1, | |||||
| 1, | |||||
| }; | |||||
| args.service = (cell_t)name; | args.service = IN(name); | ||||
| if (openfirmware(&args) == -1) | if (openfirmware(&args) == -1) | ||||
| return (-1); | return (-1); | ||||
| return (args.missing); | return (OUT(args.missing)); | ||||
| } | } | ||||
| /* Return firmware millisecond count. */ | /* Return firmware millisecond count. */ | ||||
| int | int | ||||
| OF_milliseconds() | OF_milliseconds() | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| cell_t ms; | cell_t ms; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"milliseconds", | SETUP(args, "milliseconds", 0, 1); | ||||
| 0, | |||||
| 1, | |||||
| }; | |||||
| openfirmware(&args); | openfirmware(&args); | ||||
| return (args.ms); | return (OUT(args.ms)); | ||||
| } | } | ||||
| /* | /* | ||||
| * Device tree functions | * Device tree functions | ||||
| */ | */ | ||||
| /* Return the next sibling of this node or 0. */ | /* Return the next sibling of this node or 0. */ | ||||
| phandle_t | phandle_t | ||||
| OF_peer(phandle_t node) | OF_peer(phandle_t node) | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| cell_t node; | cell_t node; | ||||
| cell_t next; | cell_t next; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"peer", | SETUP(args, "peer", 1, 1); | ||||
| 1, | |||||
| 1, | |||||
| }; | |||||
| args.node = node; | args.node = node; | ||||
| if (openfirmware(&args) == -1) | if (openfirmware(&args) == -1) | ||||
| return (-1); | return (-1); | ||||
| return (args.next); | return (args.next); | ||||
| } | } | ||||
| /* Return the first child of this node or 0. */ | /* Return the first child of this node or 0. */ | ||||
| phandle_t | phandle_t | ||||
| OF_child(phandle_t node) | OF_child(phandle_t node) | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| cell_t node; | cell_t node; | ||||
| cell_t child; | cell_t child; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"child", | SETUP(args, "child", 1, 1); | ||||
| 1, | |||||
| 1, | |||||
| }; | |||||
| args.node = node; | args.node = node; | ||||
| if (openfirmware(&args) == -1) | if (openfirmware(&args) == -1) | ||||
| return (-1); | return (-1); | ||||
| return (args.child); | return (args.child); | ||||
| } | } | ||||
| /* Return the parent of this node or 0. */ | /* Return the parent of this node or 0. */ | ||||
| phandle_t | phandle_t | ||||
| OF_parent(phandle_t node) | OF_parent(phandle_t node) | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| cell_t node; | cell_t node; | ||||
| cell_t parent; | cell_t parent; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"parent", | SETUP(args, "parent", 1, 1); | ||||
| 1, | |||||
| 1, | |||||
| }; | |||||
| args.node = node; | args.node = node; | ||||
| if (openfirmware(&args) == -1) | if (openfirmware(&args) == -1) | ||||
| return (-1); | return (-1); | ||||
| return (args.parent); | return (args.parent); | ||||
| } | } | ||||
| /* Return the package handle that corresponds to an instance handle. */ | /* Return the package handle that corresponds to an instance handle. */ | ||||
| phandle_t | phandle_t | ||||
| OF_instance_to_package(ihandle_t instance) | OF_instance_to_package(ihandle_t instance) | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| cell_t instance; | cell_t instance; | ||||
| cell_t package; | cell_t package; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"instance-to-package", | SETUP(args, "instance-to-package", 1, 1); | ||||
| 1, | |||||
| 1, | |||||
| }; | |||||
| args.instance = instance; | args.instance = instance; | ||||
| if (openfirmware(&args) == -1) | if (openfirmware(&args) == -1) | ||||
| return (-1); | return (-1); | ||||
| return (args.package); | return (args.package); | ||||
| } | } | ||||
| /* Get the length of a property of a package. */ | /* Get the length of a property of a package. */ | ||||
| int | int | ||||
| OF_getproplen(phandle_t package, const char *propname) | OF_getproplen(phandle_t package, const char *propname) | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| cell_t package; | cell_t package; | ||||
| cell_t propname; | cell_t propname; | ||||
| cell_t proplen; | cell_t proplen; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"getproplen", | SETUP(args, "getproplen", 2, 1); | ||||
| 2, | |||||
| 1, | |||||
| }; | |||||
| args.package = package; | args.package = package; | ||||
| args.propname = (cell_t)propname; | args.propname = IN(propname); | ||||
| if (openfirmware(&args) == -1) | if (openfirmware(&args) == -1) | ||||
| return (-1); | return (-1); | ||||
| return (args.proplen); | return (OUT(args.proplen)); | ||||
| } | } | ||||
| /* Get the value of a property of a package. */ | /* Get the value of a property of a package. */ | ||||
| int | int | ||||
| OF_getprop(phandle_t package, const char *propname, void *buf, int buflen) | OF_getprop(phandle_t package, const char *propname, void *buf, int buflen) | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| cell_t package; | cell_t package; | ||||
| cell_t propname; | cell_t propname; | ||||
| cell_t buf; | cell_t buf; | ||||
| cell_t buflen; | cell_t buflen; | ||||
| cell_t size; | cell_t size; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"getprop", | SETUP(args, "getprop", 4, 1); | ||||
| 4, | |||||
| 1, | |||||
| }; | |||||
| args.package = package; | args.package = package; | ||||
| args.propname = (cell_t)propname; | args.propname = IN(propname); | ||||
| args.buf = (cell_t)buf; | args.buf = IN(buf); | ||||
| args.buflen = buflen; | args.buflen = IN(buflen); | ||||
| if (openfirmware(&args) == -1) | if (openfirmware(&args) == -1) | ||||
| return (-1); | return (-1); | ||||
| return (args.size); | return (OUT(args.size)); | ||||
| } | } | ||||
| /* Decode a binary property from a package. */ | |||||
| int | |||||
| OF_getencprop(phandle_t package, const char *propname, cell_t *buf, int buflen) | |||||
| { | |||||
| int retval, i; | |||||
| retval = OF_getprop(package, propname, buf, buflen); | |||||
| if (retval == -1) | |||||
| return (retval); | |||||
| for (i = 0; i < buflen/4; i++) | |||||
| buf[i] = be32toh((uint32_t)buf[i]); | |||||
| return (retval); | |||||
| } | |||||
| /* Get the next property of a package. */ | /* Get the next property of a package. */ | ||||
| int | int | ||||
| OF_nextprop(phandle_t package, const char *previous, char *buf) | OF_nextprop(phandle_t package, const char *previous, char *buf) | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| cell_t package; | cell_t package; | ||||
| cell_t previous; | cell_t previous; | ||||
| cell_t buf; | cell_t buf; | ||||
| cell_t flag; | cell_t flag; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"nextprop", | SETUP(args, "nextprop", 3, 1); | ||||
| 3, | |||||
| 1, | |||||
| }; | |||||
| args.package = package; | args.package = package; | ||||
| args.previous = (cell_t)previous; | args.previous = IN(previous); | ||||
| args.buf = (cell_t)buf; | args.buf = IN(buf); | ||||
| if (openfirmware(&args) == -1) | if (openfirmware(&args) == -1) | ||||
| return (-1); | return (-1); | ||||
| return (args.flag); | return (OUT(args.flag)); | ||||
| } | } | ||||
| /* Set the value of a property of a package. */ | /* Set the value of a property of a package. */ | ||||
| /* XXX Has a bug on FirePower */ | /* XXX Has a bug on FirePower */ | ||||
| int | int | ||||
| OF_setprop(phandle_t package, const char *propname, void *buf, int len) | OF_setprop(phandle_t package, const char *propname, void *buf, int len) | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| cell_t package; | cell_t package; | ||||
| cell_t propname; | cell_t propname; | ||||
| cell_t buf; | cell_t buf; | ||||
| cell_t len; | cell_t len; | ||||
| cell_t size; | cell_t size; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"setprop", | SETUP(args, "setprop", 4, 1); | ||||
| 4, | |||||
| 1, | |||||
| }; | |||||
| args.package = package; | args.package = package; | ||||
| args.propname = (cell_t)propname; | args.propname = IN(propname); | ||||
| args.buf = (cell_t)buf; | args.buf = IN(buf); | ||||
| args.len = len; | args.len = IN(len); | ||||
| if (openfirmware(&args) == -1) | if (openfirmware(&args) == -1) | ||||
| return (-1); | return (-1); | ||||
| return (args.size); | return (OUT(args.size)); | ||||
| } | } | ||||
| /* Convert a device specifier to a fully qualified pathname. */ | /* Convert a device specifier to a fully qualified pathname. */ | ||||
| int | int | ||||
| OF_canon(const char *device, char *buf, int len) | OF_canon(const char *device, char *buf, int len) | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| cell_t device; | cell_t device; | ||||
| cell_t buf; | cell_t buf; | ||||
| cell_t len; | cell_t len; | ||||
| cell_t size; | cell_t size; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"canon", | SETUP(args, "canon", 3, 1); | ||||
| 3, | |||||
| 1, | |||||
| }; | |||||
| args.device = (cell_t)device; | args.device = IN(device); | ||||
| args.buf = (cell_t)buf; | args.buf = IN(buf); | ||||
| args.len = len; | args.len = IN(len); | ||||
| if (openfirmware(&args) == -1) | if (openfirmware(&args) == -1) | ||||
| return (-1); | return (-1); | ||||
| return (args.size); | return (OUT(args.size)); | ||||
| } | } | ||||
| /* Return a package handle for the specified device. */ | /* Return a package handle for the specified device. */ | ||||
| phandle_t | phandle_t | ||||
| OF_finddevice(const char *device) | OF_finddevice(const char *device) | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| cell_t device; | cell_t device; | ||||
| cell_t package; | cell_t package; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"finddevice", | SETUP(args, "finddevice", 1, 1); | ||||
| 1, | |||||
| 1, | |||||
| }; | |||||
| args.device = (cell_t)device; | args.device = IN(device); | ||||
| if (openfirmware(&args) == -1) | if (openfirmware(&args) == -1) | ||||
| return (-1); | return (-1); | ||||
| return (args.package); | return (args.package); | ||||
| } | } | ||||
| /* Return the fully qualified pathname corresponding to an instance. */ | /* Return the fully qualified pathname corresponding to an instance. */ | ||||
| int | int | ||||
| OF_instance_to_path(ihandle_t instance, char *buf, int len) | OF_instance_to_path(ihandle_t instance, char *buf, int len) | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| cell_t instance; | cell_t instance; | ||||
| cell_t buf; | cell_t buf; | ||||
| cell_t len; | cell_t len; | ||||
| cell_t size; | cell_t size; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"instance-to-path", | SETUP(args, "instance-to-path", 3, 1); | ||||
| 3, | |||||
| 1, | |||||
| }; | |||||
| args.instance = instance; | args.instance = instance; | ||||
| args.buf = (cell_t)buf; | args.buf = IN(buf); | ||||
| args.len = len; | args.len = IN(len); | ||||
| if (openfirmware(&args) == -1) | if (openfirmware(&args) == -1) | ||||
| return (-1); | return (-1); | ||||
| return (args.size); | return (OUT(args.size)); | ||||
| } | } | ||||
| /* Return the fully qualified pathname corresponding to a package. */ | /* Return the fully qualified pathname corresponding to a package. */ | ||||
| int | int | ||||
| OF_package_to_path(phandle_t package, char *buf, int len) | OF_package_to_path(phandle_t package, char *buf, int len) | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| cell_t package; | cell_t package; | ||||
| cell_t buf; | cell_t buf; | ||||
| cell_t len; | cell_t len; | ||||
| cell_t size; | cell_t size; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"package-to-path", | SETUP(args, "package-to-path", 3, 1); | ||||
| 3, | |||||
| 1, | |||||
| }; | |||||
| args.package = package; | args.package = package; | ||||
| args.buf = (cell_t)buf; | args.buf = IN(buf); | ||||
| args.len = len; | args.len = IN(len); | ||||
| if (openfirmware(&args) == -1) | if (openfirmware(&args) == -1) | ||||
| return (-1); | return (-1); | ||||
| return (args.size); | return (OUT(args.size)); | ||||
| } | } | ||||
| /* Call the method in the scope of a given instance. */ | /* Call the method in the scope of a given instance. */ | ||||
| int | int | ||||
| OF_call_method(char *method, ihandle_t instance, int nargs, int nreturns, ...) | OF_call_method(char *method, ihandle_t instance, int nargs, int nreturns, ...) | ||||
| { | { | ||||
| va_list ap; | va_list ap; | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| cell_t method; | cell_t method; | ||||
| cell_t instance; | cell_t instance; | ||||
| cell_t args_n_results[12]; | cell_t args_n_results[12]; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"call-method", | SETUP(args, "call-method", nargs + 2, nreturns + 1); | ||||
| 2, | |||||
| 1, | |||||
| }; | |||||
| cell_t *cp; | cell_t *cp; | ||||
| int n; | int n; | ||||
| if (nargs > 6) | if (nargs > 6) | ||||
| return (-1); | return (-1); | ||||
| args.nargs = nargs + 2; | args.method = IN(method); | ||||
| args.nreturns = nreturns + 1; | |||||
| args.method = (cell_t)method; | |||||
| args.instance = instance; | args.instance = instance; | ||||
| va_start(ap, nreturns); | va_start(ap, nreturns); | ||||
| for (cp = (cell_t *)(args.args_n_results + (n = nargs)); --n >= 0;) | for (cp = (cell_t *)(args.args_n_results + (n = nargs)); --n >= 0;) | ||||
| *--cp = va_arg(ap, cell_t); | *--cp = IN(va_arg(ap, cell_t)); | ||||
| if (openfirmware(&args) == -1) | if (openfirmware(&args) == -1) | ||||
| return (-1); | return (-1); | ||||
| if (args.args_n_results[nargs]) | if (args.args_n_results[nargs]) | ||||
| return (args.args_n_results[nargs]); | return (OUT(args.args_n_results[nargs])); | ||||
| for (cp = (cell_t *)(args.args_n_results + nargs + (n = args.nreturns)); | /* XXX what if ihandles or phandles are returned */ | ||||
| --n > 0;) | for (cp = (cell_t *)(args.args_n_results + nargs + | ||||
| *va_arg(ap, cell_t *) = *--cp; | (n = be32toh(args.nreturns))); --n > 0;) | ||||
| *va_arg(ap, cell_t *) = OUT(*--cp); | |||||
| va_end(ap); | va_end(ap); | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| /* | /* | ||||
| * Device I/O functions | * Device I/O functions | ||||
| */ | */ | ||||
| /* Open an instance for a device. */ | /* Open an instance for a device. */ | ||||
| ihandle_t | ihandle_t | ||||
| OF_open(char *device) | OF_open(char *device) | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| cell_t device; | cell_t device; | ||||
| cell_t instance; | cell_t instance; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"open", | SETUP(args, "open", 1, 1); | ||||
| 1, | |||||
| 1, | |||||
| }; | |||||
| args.device = (cell_t)device; | args.device = IN(device); | ||||
| if (openfirmware(&args) == -1 || args.instance == 0) { | if (openfirmware(&args) == -1 || args.instance == 0) { | ||||
| return (-1); | return (-1); | ||||
| } | } | ||||
| return (args.instance); | return (args.instance); | ||||
| } | } | ||||
| /* Close an instance. */ | /* Close an instance. */ | ||||
| void | void | ||||
| OF_close(ihandle_t instance) | OF_close(ihandle_t instance) | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| cell_t instance; | cell_t instance; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"close", | SETUP(args, "close", 1, 0); | ||||
| 1, | |||||
| }; | |||||
| args.instance = instance; | args.instance = instance; | ||||
| openfirmware(&args); | openfirmware(&args); | ||||
| } | } | ||||
| /* Read from an instance. */ | /* Read from an instance. */ | ||||
| int | int | ||||
| OF_read(ihandle_t instance, void *addr, int len) | OF_read(ihandle_t instance, void *addr, int len) | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| cell_t instance; | cell_t instance; | ||||
| cell_t addr; | cell_t addr; | ||||
| cell_t len; | cell_t len; | ||||
| cell_t actual; | cell_t actual; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"read", | SETUP(args, "read", 3, 1); | ||||
| 3, | |||||
| 1, | |||||
| }; | |||||
| args.instance = instance; | args.instance = instance; | ||||
| args.addr = (cell_t)addr; | args.addr = IN(addr); | ||||
| args.len = len; | args.len = IN(len); | ||||
| #if defined(OPENFIRM_DEBUG) | #if defined(OPENFIRM_DEBUG) | ||||
| printf("OF_read: called with instance=%08x, addr=%p, len=%d\n", | printf("OF_read: called with instance=%08x, addr=%p, len=%d\n", | ||||
| args.instance, args.addr, args.len); | instance, addr, len); | ||||
| #endif | #endif | ||||
| if (openfirmware(&args) == -1) | if (openfirmware(&args) == -1) | ||||
| return (-1); | return (-1); | ||||
| #if defined(OPENFIRM_DEBUG) | #if defined(OPENFIRM_DEBUG) | ||||
| printf("OF_read: returning instance=%d, addr=%p, len=%d, actual=%d\n", | printf("OF_read: returning instance=%d, addr=%p, len=%d, actual=%d\n", | ||||
| args.instance, args.addr, args.len, args.actual); | args.instance, OUT(args.addr), OUT(args.len), OUT(args.actual)); | ||||
| #endif | #endif | ||||
| return (args.actual); | return (OUT(args.actual)); | ||||
| } | } | ||||
| /* Write to an instance. */ | /* Write to an instance. */ | ||||
| int | int | ||||
| OF_write(ihandle_t instance, void *addr, int len) | OF_write(ihandle_t instance, void *addr, int len) | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| cell_t instance; | cell_t instance; | ||||
| cell_t addr; | cell_t addr; | ||||
| cell_t len; | cell_t len; | ||||
| cell_t actual; | cell_t actual; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"write", | SETUP(args, "write", 3, 1); | ||||
| 3, | |||||
| 1, | |||||
| }; | |||||
| args.instance = instance; | args.instance = instance; | ||||
| args.addr = (cell_t)addr; | args.addr = IN(addr); | ||||
| args.len = len; | args.len = IN(len); | ||||
| if (openfirmware(&args) == -1) | if (openfirmware(&args) == -1) | ||||
| return (-1); | return (-1); | ||||
| return (args.actual); | return (OUT(args.actual)); | ||||
| } | } | ||||
| /* Seek to a position. */ | /* Seek to a position. */ | ||||
| int | int | ||||
| OF_seek(ihandle_t instance, uint64_t pos) | OF_seek(ihandle_t instance, uint64_t pos) | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| cell_t instance; | cell_t instance; | ||||
| cell_t poshi; | cell_t poshi; | ||||
| cell_t poslo; | cell_t poslo; | ||||
| cell_t status; | cell_t status; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"seek", | SETUP(args, "seek", 3, 1); | ||||
| 3, | |||||
| 1, | |||||
| }; | |||||
| args.instance = instance; | args.instance = instance; | ||||
| args.poshi = pos >> 32; | args.poshi = IN(((uint64_t)pos >> 32)); | ||||
| args.poslo = pos; | args.poslo = IN(pos); | ||||
| if (openfirmware(&args) == -1) | if (openfirmware(&args) == -1) | ||||
| return (-1); | return (-1); | ||||
| return (args.status); | return (OUT(args.status)); | ||||
| } | } | ||||
| /* Blocks. */ | /* Blocks. */ | ||||
| unsigned int | unsigned int | ||||
| OF_blocks(ihandle_t instance) | OF_blocks(ihandle_t instance) | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| cell_t instance; | cell_t instance; | ||||
| cell_t result; | cell_t result; | ||||
| cell_t blocks; | cell_t blocks; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"#blocks", | SETUP(args, "#blocks", 2, 1); | ||||
| 2, | |||||
| 1, | |||||
| }; | |||||
| args.instance = instance; | args.instance = instance; | ||||
| if (openfirmware(&args) == -1) | if (openfirmware(&args) == -1) | ||||
| return ((unsigned int)-1); | return ((unsigned int)-1); | ||||
| return (args.blocks); | return (OUT(args.blocks)); | ||||
| } | } | ||||
| /* Block size. */ | /* Block size. */ | ||||
| int | int | ||||
| OF_block_size(ihandle_t instance) | OF_block_size(ihandle_t instance) | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| cell_t instance; | cell_t instance; | ||||
| cell_t result; | cell_t result; | ||||
| cell_t size; | cell_t size; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"block-size", | SETUP(args, "block-size", 2, 1); | ||||
| 2, | |||||
| 1, | |||||
| }; | |||||
| args.instance = instance; | args.instance = instance; | ||||
| if (openfirmware(&args) == -1) | if (openfirmware(&args) == -1) | ||||
| return (512); | return (512); | ||||
| return (args.size); | return (OUT(args.size)); | ||||
| } | } | ||||
| /* | /* | ||||
| * Memory functions | * Memory functions | ||||
| */ | */ | ||||
| /* Claim an area of memory. */ | /* Claim an area of memory. */ | ||||
| void * | void * | ||||
| OF_claim(void *virt, u_int size, u_int align) | OF_claim(void *virt, u_int size, u_int align) | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| cell_t virt; | cell_t virt; | ||||
| cell_t size; | cell_t size; | ||||
| cell_t align; | cell_t align; | ||||
| cell_t baseaddr; | cell_t baseaddr; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"claim", | SETUP(args, "claim", 3, 1); | ||||
| 3, | |||||
| 1, | |||||
| }; | |||||
| args.virt = (cell_t)virt; | args.virt = IN(virt); | ||||
| args.size = size; | args.size = IN(size); | ||||
| args.align = align; | args.align = IN(align); | ||||
| if (openfirmware(&args) == -1) | if (openfirmware(&args) == -1) | ||||
| return ((void *)-1); | return ((void *)-1); | ||||
| return ((void *)args.baseaddr); | return ((void *)OUT(args.baseaddr)); | ||||
| } | } | ||||
| /* Release an area of memory. */ | /* Release an area of memory. */ | ||||
| void | void | ||||
| OF_release(void *virt, u_int size) | OF_release(void *virt, u_int size) | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| cell_t virt; | cell_t virt; | ||||
| cell_t size; | cell_t size; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"release", | SETUP(args, "release", 2, 0); | ||||
| 2, | |||||
| }; | |||||
| args.virt = (cell_t)virt; | args.virt = IN(virt); | ||||
| args.size = size; | args.size = IN(size); | ||||
| openfirmware(&args); | openfirmware(&args); | ||||
| } | } | ||||
| /* | /* | ||||
| * Control transfer functions | * Control transfer functions | ||||
| */ | */ | ||||
| /* Reset the system and call "boot <bootspec>". */ | /* Reset the system and call "boot <bootspec>". */ | ||||
| void | void | ||||
| OF_boot(char *bootspec) | OF_boot(char *bootspec) | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| cell_t bootspec; | cell_t bootspec; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"boot", | SETUP(args, "boot", 1, 0); | ||||
| 1, | |||||
| }; | |||||
| args.bootspec = (cell_t)bootspec; | args.bootspec = IN(bootspec); | ||||
| openfirmware(&args); | openfirmware(&args); | ||||
| for (;;) /* just in case */ | for (;;) /* just in case */ | ||||
| ; | ; | ||||
| } | } | ||||
| /* Suspend and drop back to the Open Firmware interface. */ | /* Suspend and drop back to the Open Firmware interface. */ | ||||
| void | void | ||||
| OF_enter() | OF_enter() | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"enter", | SETUP(args, "enter", 0, 0); | ||||
| }; | |||||
| openfirmware(&args); | openfirmware(&args); | ||||
| /* We may come back. */ | /* We may come back. */ | ||||
| } | } | ||||
| /* Shut down and drop back to the Open Firmware interface. */ | /* Shut down and drop back to the Open Firmware interface. */ | ||||
| void | void | ||||
| OF_exit() | OF_exit() | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"exit", | SETUP(args, "exit", 0, 0); | ||||
| }; | |||||
| openfirmware(&args); | openfirmware(&args); | ||||
| for (;;) /* just in case */ | for (;;) /* just in case */ | ||||
| ; | ; | ||||
| } | } | ||||
| void | void | ||||
| OF_quiesce() | OF_quiesce() | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"quiesce", | SETUP(args, "quiesce", 0, 0); | ||||
| }; | |||||
| openfirmware(&args); | openfirmware(&args); | ||||
| } | } | ||||
| /* Free <size> bytes starting at <virt>, then call <entry> with <arg>. */ | /* Free <size> bytes starting at <virt>, then call <entry> with <arg>. */ | ||||
| #if 0 | #if 0 | ||||
| void | void | ||||
| OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len) | OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len) | ||||
| { | { | ||||
| static struct { | static struct { | ||||
| cell_t name; | cell_t name; | ||||
| cell_t nargs; | cell_t nargs; | ||||
| cell_t nreturns; | cell_t nreturns; | ||||
| cell_t virt; | cell_t virt; | ||||
| cell_t size; | cell_t size; | ||||
| cell_t entry; | cell_t entry; | ||||
| cell_t arg; | cell_t arg; | ||||
| cell_t len; | cell_t len; | ||||
| } args = { | } args = {}; | ||||
| (cell_t)"chain", | SETUP(args, "chain", 5, 0); | ||||
| 5, | |||||
| }; | |||||
| args.virt = (cell_t)virt; | args.virt = IN(virt); | ||||
| args.size = size; | args.size = IN(size); | ||||
| args.entry = (cell_t)entry; | args.entry = IN(entry); | ||||
| args.arg = (cell_t)arg; | args.arg = IN(arg); | ||||
| args.len = len; | args.len = IN(len); | ||||
| openfirmware(&args); | openfirmware(&args); | ||||
| } | } | ||||
| #else | #else | ||||
| void | void | ||||
| OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len) | OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len) | ||||
| { | { | ||||
| /* | /* | ||||
| * This is a REALLY dirty hack till the firmware gets this going | * This is a REALLY dirty hack till the firmware gets this going | ||||
| */ | */ | ||||
| #if 0 | #if 0 | ||||
| if (size > 0) | if (size > 0) | ||||
| OF_release(virt, size); | OF_release(virt, size); | ||||
| #endif | #endif | ||||
| entry(0, 0, openfirmware, arg, len); | entry(0, 0, openfirmware, arg, len); | ||||
| } | } | ||||
| #endif | #endif | ||||