1 /* $NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $ */
4 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
5 * Copyright (C) 1995, 1996 TooLs GmbH.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by TooLs GmbH.
19 * 4. The name of TooLs GmbH may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 * Copyright (C) 2000 Benno Rice.
35 * All rights reserved.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
46 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
47 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
51 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
52 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
53 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
54 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
55 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
58 #include <sys/cdefs.h>
59 __FBSDID("$FreeBSD$");
61 #include <sys/param.h>
62 #include <sys/kernel.h>
63 #include <sys/malloc.h>
64 #include <sys/systm.h>
66 #include <machine/stdarg.h>
68 #include <dev/ofw/ofwvar.h>
69 #include <dev/ofw/openfirm.h>
73 static int ofw_std_init(ofw_t ofw, void *openfirm);
74 static int ofw_std_test(ofw_t ofw, const char *name);
75 static int ofw_std_interpret(ofw_t ofw, const char *cmd, int nreturns,
77 static phandle_t ofw_std_peer(ofw_t ofw, phandle_t node);
78 static phandle_t ofw_std_child(ofw_t ofw, phandle_t node);
79 static phandle_t ofw_std_parent(ofw_t ofw, phandle_t node);
80 static phandle_t ofw_std_instance_to_package(ofw_t ofw, ihandle_t instance);
81 static ssize_t ofw_std_getproplen(ofw_t ofw, phandle_t package,
82 const char *propname);
83 static ssize_t ofw_std_getprop(ofw_t ofw, phandle_t package,
84 const char *propname, void *buf, size_t buflen);
85 static int ofw_std_nextprop(ofw_t ofw, phandle_t package, const char *previous,
87 static int ofw_std_setprop(ofw_t ofw, phandle_t package, const char *propname,
88 const void *buf, size_t len);
89 static ssize_t ofw_std_canon(ofw_t ofw, const char *device, char *buf,
91 static phandle_t ofw_std_finddevice(ofw_t ofw, const char *device);
92 static ssize_t ofw_std_instance_to_path(ofw_t ofw, ihandle_t instance,
93 char *buf, size_t len);
94 static ssize_t ofw_std_package_to_path(ofw_t ofw, phandle_t package, char *buf,
96 static int ofw_std_call_method(ofw_t ofw, ihandle_t instance,
97 const char *method, int nargs, int nreturns, cell_t *args_and_returns);
98 static ihandle_t ofw_std_open(ofw_t ofw, const char *device);
99 static void ofw_std_close(ofw_t ofw, ihandle_t instance);
100 static ssize_t ofw_std_read(ofw_t ofw, ihandle_t instance, void *addr,
102 static ssize_t ofw_std_write(ofw_t ofw, ihandle_t instance, const void *addr,
104 static int ofw_std_seek(ofw_t ofw, ihandle_t instance, uint64_t pos);
105 static caddr_t ofw_std_claim(ofw_t ofw, void *virt, size_t size, u_int align);
106 static void ofw_std_release(ofw_t ofw, void *virt, size_t size);
107 static void ofw_std_enter(ofw_t ofw);
108 static void ofw_std_exit(ofw_t ofw);
110 static ofw_method_t ofw_std_methods[] = {
111 OFWMETHOD(ofw_init, ofw_std_init),
112 OFWMETHOD(ofw_peer, ofw_std_peer),
113 OFWMETHOD(ofw_child, ofw_std_child),
114 OFWMETHOD(ofw_parent, ofw_std_parent),
115 OFWMETHOD(ofw_instance_to_package, ofw_std_instance_to_package),
116 OFWMETHOD(ofw_getproplen, ofw_std_getproplen),
117 OFWMETHOD(ofw_getprop, ofw_std_getprop),
118 OFWMETHOD(ofw_nextprop, ofw_std_nextprop),
119 OFWMETHOD(ofw_setprop, ofw_std_setprop),
120 OFWMETHOD(ofw_canon, ofw_std_canon),
121 OFWMETHOD(ofw_finddevice, ofw_std_finddevice),
122 OFWMETHOD(ofw_instance_to_path, ofw_std_instance_to_path),
123 OFWMETHOD(ofw_package_to_path, ofw_std_package_to_path),
125 OFWMETHOD(ofw_test, ofw_std_test),
126 OFWMETHOD(ofw_call_method, ofw_std_call_method),
127 OFWMETHOD(ofw_interpret, ofw_std_interpret),
128 OFWMETHOD(ofw_open, ofw_std_open),
129 OFWMETHOD(ofw_close, ofw_std_close),
130 OFWMETHOD(ofw_read, ofw_std_read),
131 OFWMETHOD(ofw_write, ofw_std_write),
132 OFWMETHOD(ofw_seek, ofw_std_seek),
133 OFWMETHOD(ofw_claim, ofw_std_claim),
134 OFWMETHOD(ofw_release, ofw_std_release),
135 OFWMETHOD(ofw_enter, ofw_std_enter),
136 OFWMETHOD(ofw_exit, ofw_std_exit),
141 static ofw_def_t ofw_std = {
148 static int (*openfirmware)(void *);
153 ofw_std_init(ofw_t ofw, void *openfirm)
156 openfirmware = (int (*)(void *))openfirm;
164 /* Test to see if a service exists. */
166 ofw_std_test(ofw_t ofw, const char *name)
180 args.service = (cell_t)name;
181 if (openfirmware(&args) == -1)
183 return (args.missing);
187 ofw_std_interpret(ofw_t ofw, const char *cmd, int nreturns, cell_t *returns)
201 args.nreturns = ++nreturns;
202 args.slot[i++] = (cell_t)cmd;
203 if (openfirmware(&args) == -1)
205 status = args.slot[i++];
206 while (i < 1 + nreturns)
207 returns[j++] = args.slot[i++];
212 * Device tree functions
215 /* Return the next sibling of this node or 0. */
217 ofw_std_peer(ofw_t ofw, phandle_t node)
232 if (openfirmware(&args) == -1)
237 /* Return the first child of this node or 0. */
239 ofw_std_child(ofw_t ofw, phandle_t node)
254 if (openfirmware(&args) == -1)
259 /* Return the parent of this node or 0. */
261 ofw_std_parent(ofw_t ofw, phandle_t node)
276 if (openfirmware(&args) == -1)
278 return (args.parent);
281 /* Return the package handle that corresponds to an instance handle. */
283 ofw_std_instance_to_package(ofw_t ofw, ihandle_t instance)
292 (cell_t)"instance-to-package",
297 args.instance = instance;
298 if (openfirmware(&args) == -1)
300 return (args.package);
303 /* Get the length of a property of a package. */
305 ofw_std_getproplen(ofw_t ofw, phandle_t package, const char *propname)
315 (cell_t)"getproplen",
320 args.package = package;
321 args.propname = (cell_t)propname;
322 if (openfirmware(&args) == -1)
324 return (args.proplen);
327 /* Get the value of a property of a package. */
329 ofw_std_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf,
347 args.package = package;
348 args.propname = (cell_t)propname;
349 args.buf = (cell_t)buf;
350 args.buflen = buflen;
351 if (openfirmware(&args) == -1)
356 /* Get the next property of a package. */
358 ofw_std_nextprop(ofw_t ofw, phandle_t package, const char *previous, char *buf,
375 args.package = package;
376 args.previous = (cell_t)previous;
377 args.buf = (cell_t)buf;
378 if (openfirmware(&args) == -1)
383 /* Set the value of a property of a package. */
384 /* XXX Has a bug on FirePower */
386 ofw_std_setprop(ofw_t ofw, phandle_t package, const char *propname,
387 const void *buf, size_t len)
404 args.package = package;
405 args.propname = (cell_t)propname;
406 args.buf = (cell_t)buf;
408 if (openfirmware(&args) == -1)
413 /* Convert a device specifier to a fully qualified pathname. */
415 ofw_std_canon(ofw_t ofw, const char *device, char *buf, size_t len)
431 args.device = (cell_t)device;
432 args.buf = (cell_t)buf;
434 if (openfirmware(&args) == -1)
439 /* Return a package handle for the specified device. */
441 ofw_std_finddevice(ofw_t ofw, const char *device)
450 (cell_t)"finddevice",
455 args.device = (cell_t)device;
456 if (openfirmware(&args) == -1)
458 return (args.package);
461 /* Return the fully qualified pathname corresponding to an instance. */
463 ofw_std_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len)
474 (cell_t)"instance-to-path",
479 args.instance = instance;
480 args.buf = (cell_t)buf;
482 if (openfirmware(&args) == -1)
487 /* Return the fully qualified pathname corresponding to a package. */
489 ofw_std_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len)
500 (cell_t)"package-to-path",
505 args.package = package;
506 args.buf = (cell_t)buf;
508 if (openfirmware(&args) == -1)
513 /* Call the method in the scope of a given instance. */
515 ofw_std_call_method(ofw_t ofw, ihandle_t instance, const char *method,
516 int nargs, int nreturns, cell_t *args_and_returns)
524 cell_t args_n_results[12];
526 (cell_t)"call-method",
535 args.nargs = nargs + 2;
536 args.nreturns = nreturns + 1;
537 args.method = (cell_t)method;
538 args.instance = instance;
540 ap = args_and_returns;
541 for (cp = args.args_n_results + (n = nargs); --n >= 0;)
543 if (openfirmware(&args) == -1)
545 if (args.args_n_results[nargs])
546 return (args.args_n_results[nargs]);
547 for (cp = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
553 * Device I/O functions
556 /* Open an instance for a device. */
558 ofw_std_open(ofw_t ofw, const char *device)
572 args.device = (cell_t)device;
573 if (openfirmware(&args) == -1 || args.instance == 0)
575 return (args.instance);
578 /* Close an instance. */
580 ofw_std_close(ofw_t ofw, ihandle_t instance)
593 args.instance = instance;
597 /* Read from an instance. */
599 ofw_std_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len)
615 args.instance = instance;
616 args.addr = (cell_t)addr;
618 if (openfirmware(&args) == -1)
621 return (args.actual);
624 /* Write to an instance. */
626 ofw_std_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len)
642 args.instance = instance;
643 args.addr = (cell_t)addr;
645 if (openfirmware(&args) == -1)
647 return (args.actual);
650 /* Seek to a position. */
652 ofw_std_seek(ofw_t ofw, ihandle_t instance, uint64_t pos)
668 args.instance = instance;
669 args.poshi = pos >> 32;
671 if (openfirmware(&args) == -1)
673 return (args.status);
680 /* Claim an area of memory. */
682 ofw_std_claim(ofw_t ofw, void *virt, size_t size, u_int align)
698 args.virt = (cell_t)virt;
701 if (openfirmware(&args) == -1)
703 return ((void *)args.baseaddr);
706 /* Release an area of memory. */
708 ofw_std_release(ofw_t ofw, void *virt, size_t size)
722 args.virt = (cell_t)virt;
728 * Control transfer functions
731 /* Suspend and drop back to the Open Firmware interface. */
733 ofw_std_enter(ofw_t ofw)
746 /* We may come back. */
749 /* Shut down and drop back to the Open Firmware interface. */
751 ofw_std_exit(ofw_t ofw)
764 for (;;) /* just in case */