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.
60 #include <sys/param.h>
61 #include <sys/kernel.h>
62 #include <sys/malloc.h>
63 #include <sys/systm.h>
65 #include <machine/stdarg.h>
67 #include <dev/ofw/openfirm.h>
69 MALLOC_DEFINE(M_OFWPROP, "openfirm", "OpenFirmware properties");
71 static ihandle_t stdin;
72 static ihandle_t stdout;
76 void ofbcopy(const void *, void *, size_t);
81 OF_init(int (*openfirm)(void *))
85 set_openfirm_callback(openfirm);
86 if ((chosen = OF_finddevice("/chosen")) == -1)
88 OF_getprop(chosen, "stdin", &stdin, sizeof(stdin));
89 OF_getprop(chosen, "stdout", &stdout, sizeof(stdout));
93 OF_printf(const char *fmt, ...)
99 vsprintf(buf, fmt, va);
100 OF_write(stdout, buf, strlen(buf));
108 /* Test to see if a service exists. */
124 args.service = (cell_t)name;
125 if (openfirmware(&args) == -1)
130 /* Return firmware millisecond count. */
140 (cell_t)"milliseconds",
150 * Device tree functions
153 /* Return the next sibling of this node or 0. */
155 OF_peer(phandle_t node)
169 args.node = (cell_t)node;
170 if (openfirmware(&args) == -1)
175 /* Return the first child of this node or 0. */
177 OF_child(phandle_t node)
191 args.node = (cell_t)node;
192 if (openfirmware(&args) == -1)
197 /* Return the parent of this node or 0. */
199 OF_parent(phandle_t node)
213 args.node = (cell_t)node;
214 if (openfirmware(&args) == -1)
219 /* Return the package handle that corresponds to an instance handle. */
221 OF_instance_to_package(ihandle_t instance)
230 (cell_t)"instance-to-package",
235 args.instance = (cell_t)instance;
236 if (openfirmware(&args) == -1)
241 /* Get the length of a property of a package. */
243 OF_getproplen(phandle_t package, char *propname)
253 (cell_t)"getproplen",
258 args.package = (cell_t)package;
259 args.propname = (cell_t)propname;
260 if (openfirmware(&args) == -1)
265 /* Get the value of a property of a package. */
267 OF_getprop(phandle_t package, char *propname, void *buf, int buflen)
284 args.package = (cell_t)package;
285 args.propname = (cell_t)propname;
286 args.buf = (cell_t)buf;
287 args.buflen = (cell_t)buflen;
288 if (openfirmware(&args) == -1)
294 * Store the value of a property of a package into newly allocated memory (using
295 * the M_OFWPROP malloc pool and M_WAITOK). elsz is the size of a single element,
296 * the number of elements is return in number.
299 OF_getprop_alloc(phandle_t package, char *propname, int elsz, void **buf)
304 if ((len = OF_getproplen(package, propname)) == -1 ||
308 *buf = malloc(len, M_OFWPROP, M_WAITOK);
309 if (OF_getprop(package, propname, *buf, len) == -1) {
310 free(*buf, M_OFWPROP);
317 /* Get the next property of a package. */
319 OF_nextprop(phandle_t package, char *previous, char *buf)
335 args.package = (cell_t)package;
336 args.previous = (cell_t)previous;
337 args.buf = (cell_t)buf;
338 if (openfirmware(&args) == -1)
343 /* Set the value of a property of a package. */
344 /* XXX Has a bug on FirePower */
346 OF_setprop(phandle_t package, char *propname, void *buf, int len)
363 args.package = (cell_t)package;
364 args.propname = (cell_t)propname;
365 args.buf = (cell_t)buf;
366 args.len = (cell_t)len;
367 if (openfirmware(&args) == -1)
372 /* Convert a device specifier to a fully qualified pathname. */
374 OF_canon(const char *device, char *buf, int len)
390 args.device = (cell_t)device;
391 args.buf = (cell_t)buf;
392 args.len = (cell_t)len;
393 if (openfirmware(&args) == -1)
398 /* Return a package handle for the specified device. */
400 OF_finddevice(const char *device)
409 (cell_t)"finddevice",
414 args.device = (cell_t)device;
415 if (openfirmware(&args) == -1)
420 /* Return the fully qualified pathname corresponding to an instance. */
422 OF_instance_to_path(ihandle_t instance, char *buf, int len)
433 (cell_t)"instance-to-path",
438 args.instance = (cell_t)instance;
439 args.buf = (cell_t)buf;
440 args.len = (cell_t)len;
441 if (openfirmware(&args) == -1)
446 /* Return the fully qualified pathname corresponding to a package. */
448 OF_package_to_path(phandle_t package, char *buf, int len)
459 (cell_t)"package-to-path",
464 args.package = (cell_t)package;
465 args.buf = (cell_t)buf;
466 args.len = (cell_t)len;
467 if (openfirmware(&args) == -1)
472 /* Call the method in the scope of a given instance. */
474 OF_call_method(char *method, ihandle_t instance, int nargs, int nreturns, ...)
483 cell_t args_n_results[12];
485 (cell_t)"call-method",
494 args.nargs = (cell_t)nargs + 2;
495 args.nreturns = (cell_t)nreturns + 1;
496 args.method = (cell_t)method;
497 args.instance = (cell_t)instance;
498 va_start(ap, nreturns);
499 for (ip = args.args_n_results + (n = (cell_t)nargs); --n >= 0;)
500 *--ip = va_arg(ap, cell_t);
502 if (openfirmware(&args) == -1)
504 if (args.args_n_results[nargs])
505 return args.args_n_results[nargs];
506 for (ip = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
507 *va_arg(ap, cell_t *) = *--ip;
513 * Device I/O functions.
516 /* Open an instance for a device. */
518 OF_open(char *device)
532 args.device = (cell_t)device;
533 if (openfirmware(&args) == -1 || args.instance == 0) {
536 return args.instance;
539 /* Close an instance. */
541 OF_close(ihandle_t instance)
554 args.instance = (cell_t)instance;
558 /* Read from an instance. */
560 OF_read(ihandle_t instance, void *addr, int len)
576 args.instance = (cell_t)instance;
577 args.addr = (cell_t)addr;
578 args.len = (cell_t)len;
579 if (openfirmware(&args) == -1)
585 /* Write to an instance. */
587 OF_write(ihandle_t instance, void *addr, int len)
603 args.instance = (cell_t)instance;
604 args.addr = (cell_t)addr;
605 args.len = (cell_t)len;
606 if (openfirmware(&args) == -1)
611 /* Seek to a position. */
613 OF_seek(ihandle_t instance, u_int64_t pos)
629 args.instance = (cell_t)instance;
630 args.poshi = (cell_t)(pos >> 32);
631 args.poslo = (cell_t)pos;
632 if (openfirmware(&args) == -1)
641 /* Claim an area of memory. */
643 OF_claim(void *virt, u_int size, u_int align)
659 args.virt = (cell_t)virt;
660 args.size = (cell_t)size;
661 args.align = (cell_t)align;
662 if (openfirmware(&args) == -1)
664 return (void *)args.baseaddr;
667 /* Release an area of memory. */
669 OF_release(void *virt, u_int size)
683 args.virt = (cell_t)virt;
684 args.size = (cell_t)size;
689 * Control transfer functions.
692 /* Reset the system and call "boot <bootspec>". */
694 OF_boot(char *bootspec)
707 args.bootspec = (cell_t)bootspec;
709 for (;;); /* just in case */
712 /* Suspend and drop back to the OpenFirmware interface. */
727 return; /* We may come back. */
730 /* Shut down and drop back to the OpenFirmware interface. */
745 for (;;); /* just in case */
748 /* Free <size> bytes starting at <virt>, then call <entry> with <arg>. */
751 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
768 args.virt = (cell_t)virt;
769 args.size = (cell_t)size;
770 args.entry = (cell_t)entry;
771 args.arg = (cell_t)arg;
772 args.len = (cell_t)len;
777 OF_chain(void *virt, u_int size,
778 void (*entry)(void *, u_int, void *, void *, u_int), void *arg, u_int len)
781 * This is a REALLY dirty hack till the firmware gets this going
784 OF_release(virt, size);
786 entry(0, 0, openfirmware, arg, len);
791 ofbcopy(const void *src, void *dst, size_t len)
793 const char *sp = src;