1 /* $NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $ */
4 * SPDX-License-Identifier: BSD-4-Clause AND BSD-2-Clause-FreeBSD
6 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
7 * Copyright (C) 1995, 1996 TooLs GmbH.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by TooLs GmbH.
21 * 4. The name of TooLs GmbH may not be used to endorse or promote products
22 * derived from this software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
30 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
33 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 * Copyright (C) 2000 Benno Rice.
37 * All rights reserved.
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
48 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
49 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
50 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
51 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
52 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
53 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
54 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
55 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
56 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
57 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60 #include <sys/cdefs.h>
61 __FBSDID("$FreeBSD$");
63 #include <sys/param.h>
64 #include <sys/kernel.h>
65 #include <sys/malloc.h>
66 #include <sys/systm.h>
68 #include <machine/stdarg.h>
70 #include <dev/ofw/ofwvar.h>
71 #include <dev/ofw/openfirm.h>
75 static int ofw_std_init(ofw_t ofw, void *openfirm);
76 static int ofw_std_test(ofw_t ofw, const char *name);
77 static int ofw_std_interpret(ofw_t ofw, const char *cmd, int nreturns,
79 static phandle_t ofw_std_peer(ofw_t ofw, phandle_t node);
80 static phandle_t ofw_std_child(ofw_t ofw, phandle_t node);
81 static phandle_t ofw_std_parent(ofw_t ofw, phandle_t node);
82 static phandle_t ofw_std_instance_to_package(ofw_t ofw, ihandle_t instance);
83 static ssize_t ofw_std_getproplen(ofw_t ofw, phandle_t package,
84 const char *propname);
85 static ssize_t ofw_std_getprop(ofw_t ofw, phandle_t package,
86 const char *propname, void *buf, size_t buflen);
87 static int ofw_std_nextprop(ofw_t ofw, phandle_t package, const char *previous,
89 static int ofw_std_setprop(ofw_t ofw, phandle_t package, const char *propname,
90 const void *buf, size_t len);
91 static ssize_t ofw_std_canon(ofw_t ofw, const char *device, char *buf,
93 static phandle_t ofw_std_finddevice(ofw_t ofw, const char *device);
94 static ssize_t ofw_std_instance_to_path(ofw_t ofw, ihandle_t instance,
95 char *buf, size_t len);
96 static ssize_t ofw_std_package_to_path(ofw_t ofw, phandle_t package, char *buf,
98 static int ofw_std_call_method(ofw_t ofw, ihandle_t instance,
99 const char *method, int nargs, int nreturns, cell_t *args_and_returns);
100 static ihandle_t ofw_std_open(ofw_t ofw, const char *device);
101 static void ofw_std_close(ofw_t ofw, ihandle_t instance);
102 static ssize_t ofw_std_read(ofw_t ofw, ihandle_t instance, void *addr,
104 static ssize_t ofw_std_write(ofw_t ofw, ihandle_t instance, const void *addr,
106 static int ofw_std_seek(ofw_t ofw, ihandle_t instance, uint64_t pos);
107 static caddr_t ofw_std_claim(ofw_t ofw, void *virt, size_t size, u_int align);
108 static void ofw_std_release(ofw_t ofw, void *virt, size_t size);
109 static void ofw_std_enter(ofw_t ofw);
110 static void ofw_std_exit(ofw_t ofw);
112 static ofw_method_t ofw_std_methods[] = {
113 OFWMETHOD(ofw_init, ofw_std_init),
114 OFWMETHOD(ofw_peer, ofw_std_peer),
115 OFWMETHOD(ofw_child, ofw_std_child),
116 OFWMETHOD(ofw_parent, ofw_std_parent),
117 OFWMETHOD(ofw_instance_to_package, ofw_std_instance_to_package),
118 OFWMETHOD(ofw_getproplen, ofw_std_getproplen),
119 OFWMETHOD(ofw_getprop, ofw_std_getprop),
120 OFWMETHOD(ofw_nextprop, ofw_std_nextprop),
121 OFWMETHOD(ofw_setprop, ofw_std_setprop),
122 OFWMETHOD(ofw_canon, ofw_std_canon),
123 OFWMETHOD(ofw_finddevice, ofw_std_finddevice),
124 OFWMETHOD(ofw_instance_to_path, ofw_std_instance_to_path),
125 OFWMETHOD(ofw_package_to_path, ofw_std_package_to_path),
127 OFWMETHOD(ofw_test, ofw_std_test),
128 OFWMETHOD(ofw_call_method, ofw_std_call_method),
129 OFWMETHOD(ofw_interpret, ofw_std_interpret),
130 OFWMETHOD(ofw_open, ofw_std_open),
131 OFWMETHOD(ofw_close, ofw_std_close),
132 OFWMETHOD(ofw_read, ofw_std_read),
133 OFWMETHOD(ofw_write, ofw_std_write),
134 OFWMETHOD(ofw_seek, ofw_std_seek),
135 OFWMETHOD(ofw_claim, ofw_std_claim),
136 OFWMETHOD(ofw_release, ofw_std_release),
137 OFWMETHOD(ofw_enter, ofw_std_enter),
138 OFWMETHOD(ofw_exit, ofw_std_exit),
143 static ofw_def_t ofw_std = {
150 static int (*openfirmware)(void *);
155 ofw_std_init(ofw_t ofw, void *openfirm)
158 openfirmware = (int (*)(void *))openfirm;
166 /* Test to see if a service exists. */
168 ofw_std_test(ofw_t ofw, const char *name)
182 args.service = (cell_t)name;
183 if (openfirmware(&args) == -1)
185 return (args.missing);
189 ofw_std_interpret(ofw_t ofw, const char *cmd, int nreturns, cell_t *returns)
203 args.nreturns = ++nreturns;
204 args.slot[i++] = (cell_t)cmd;
205 if (openfirmware(&args) == -1)
207 status = args.slot[i++];
208 while (i < 1 + nreturns)
209 returns[j++] = args.slot[i++];
214 * Device tree functions
217 /* Return the next sibling of this node or 0. */
219 ofw_std_peer(ofw_t ofw, phandle_t node)
234 if (openfirmware(&args) == -1)
239 /* Return the first child of this node or 0. */
241 ofw_std_child(ofw_t ofw, phandle_t node)
256 if (openfirmware(&args) == -1)
261 /* Return the parent of this node or 0. */
263 ofw_std_parent(ofw_t ofw, phandle_t node)
278 if (openfirmware(&args) == -1)
280 return (args.parent);
283 /* Return the package handle that corresponds to an instance handle. */
285 ofw_std_instance_to_package(ofw_t ofw, ihandle_t instance)
294 (cell_t)"instance-to-package",
299 args.instance = instance;
300 if (openfirmware(&args) == -1)
302 return (args.package);
305 /* Get the length of a property of a package. */
307 ofw_std_getproplen(ofw_t ofw, phandle_t package, const char *propname)
317 (cell_t)"getproplen",
322 args.package = package;
323 args.propname = (cell_t)propname;
324 if (openfirmware(&args) == -1)
326 return (args.proplen);
329 /* Get the value of a property of a package. */
331 ofw_std_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf,
349 args.package = package;
350 args.propname = (cell_t)propname;
351 args.buf = (cell_t)buf;
352 args.buflen = buflen;
353 if (openfirmware(&args) == -1)
358 /* Get the next property of a package. */
360 ofw_std_nextprop(ofw_t ofw, phandle_t package, const char *previous, char *buf,
377 args.package = package;
378 args.previous = (cell_t)previous;
379 args.buf = (cell_t)buf;
380 if (openfirmware(&args) == -1)
385 /* Set the value of a property of a package. */
386 /* XXX Has a bug on FirePower */
388 ofw_std_setprop(ofw_t ofw, phandle_t package, const char *propname,
389 const void *buf, size_t len)
406 args.package = package;
407 args.propname = (cell_t)propname;
408 args.buf = (cell_t)buf;
410 if (openfirmware(&args) == -1)
415 /* Convert a device specifier to a fully qualified pathname. */
417 ofw_std_canon(ofw_t ofw, const char *device, char *buf, size_t len)
433 args.device = (cell_t)device;
434 args.buf = (cell_t)buf;
436 if (openfirmware(&args) == -1)
441 /* Return a package handle for the specified device. */
443 ofw_std_finddevice(ofw_t ofw, const char *device)
452 (cell_t)"finddevice",
457 args.device = (cell_t)device;
458 if (openfirmware(&args) == -1)
460 return (args.package);
463 /* Return the fully qualified pathname corresponding to an instance. */
465 ofw_std_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len)
476 (cell_t)"instance-to-path",
481 args.instance = instance;
482 args.buf = (cell_t)buf;
484 if (openfirmware(&args) == -1)
489 /* Return the fully qualified pathname corresponding to a package. */
491 ofw_std_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len)
502 (cell_t)"package-to-path",
507 args.package = package;
508 args.buf = (cell_t)buf;
510 if (openfirmware(&args) == -1)
515 /* Call the method in the scope of a given instance. */
517 ofw_std_call_method(ofw_t ofw, ihandle_t instance, const char *method,
518 int nargs, int nreturns, cell_t *args_and_returns)
526 cell_t args_n_results[12];
528 (cell_t)"call-method",
537 args.nargs = nargs + 2;
538 args.nreturns = nreturns + 1;
539 args.method = (cell_t)method;
540 args.instance = instance;
542 ap = args_and_returns;
543 for (cp = args.args_n_results + (n = nargs); --n >= 0;)
545 if (openfirmware(&args) == -1)
547 if (args.args_n_results[nargs])
548 return (args.args_n_results[nargs]);
549 for (cp = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
555 * Device I/O functions
558 /* Open an instance for a device. */
560 ofw_std_open(ofw_t ofw, const char *device)
574 args.device = (cell_t)device;
575 if (openfirmware(&args) == -1 || args.instance == 0)
577 return (args.instance);
580 /* Close an instance. */
582 ofw_std_close(ofw_t ofw, ihandle_t instance)
595 args.instance = instance;
599 /* Read from an instance. */
601 ofw_std_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len)
617 args.instance = instance;
618 args.addr = (cell_t)addr;
620 if (openfirmware(&args) == -1)
623 return (args.actual);
626 /* Write to an instance. */
628 ofw_std_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len)
644 args.instance = instance;
645 args.addr = (cell_t)addr;
647 if (openfirmware(&args) == -1)
649 return (args.actual);
652 /* Seek to a position. */
654 ofw_std_seek(ofw_t ofw, ihandle_t instance, uint64_t pos)
670 args.instance = instance;
671 args.poshi = pos >> 32;
673 if (openfirmware(&args) == -1)
675 return (args.status);
682 /* Claim an area of memory. */
684 ofw_std_claim(ofw_t ofw, void *virt, size_t size, u_int align)
700 args.virt = (cell_t)virt;
703 if (openfirmware(&args) == -1)
705 return ((void *)args.baseaddr);
708 /* Release an area of memory. */
710 ofw_std_release(ofw_t ofw, void *virt, size_t size)
724 args.virt = (cell_t)virt;
730 * Control transfer functions
733 /* Suspend and drop back to the Open Firmware interface. */
735 ofw_std_enter(ofw_t ofw)
748 /* We may come back. */
751 /* Shut down and drop back to the Open Firmware interface. */
753 ofw_std_exit(ofw_t ofw)
766 for (;;) /* just in case */