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/endian.h>
60 #include <machine/stdarg.h>
66 int (*openfirmware)(void *);
73 #define IN(x) htobe32((cell_t)x)
74 #define OUT(x) be32toh(x)
75 #define SETUP(a, b, c, d) \
77 a.nargs = IN( (c) ); \
78 a.nreturns = IN( (d) );
83 OF_init(int (*openfirm)(void *))
86 char mode[sizeof("true")];
88 openfirmware = openfirm;
90 if ((chosen = OF_finddevice("/chosen")) == -1)
92 if (OF_getprop(chosen, "memory", &memory, sizeof(memory)) == -1) {
93 memory = OF_open("/memory");
95 memory = OF_open("/memory@0");
99 if (OF_getprop(chosen, "mmu", &mmu, sizeof(mmu)) == -1)
103 * Check if we run in real mode. If so, we do not need to map
106 options = OF_finddevice("/options");
107 if (OF_getprop(options, "real-mode?", mode, sizeof(mode)) > 0 &&
108 strcmp(mode, "true") == 0)
116 /* Test to see if a service exists. */
127 SETUP(args, "test", 1, 1);
129 args.service = IN(name);
130 if (openfirmware(&args) == -1)
132 return (OUT(args.missing));
135 /* Return firmware millisecond count. */
137 OF_milliseconds(void)
145 SETUP(args, "milliseconds", 0, 1);
148 return (OUT(args.ms));
152 * Device tree functions
155 /* Return the next sibling of this node or 0. */
157 OF_peer(phandle_t node)
166 SETUP(args, "peer", 1, 1);
169 if (openfirmware(&args) == -1)
174 /* Return the first child of this node or 0. */
176 OF_child(phandle_t node)
185 SETUP(args, "child", 1, 1);
188 if (openfirmware(&args) == -1)
193 /* Return the parent of this node or 0. */
195 OF_parent(phandle_t node)
204 SETUP(args, "parent", 1, 1);
207 if (openfirmware(&args) == -1)
209 return (args.parent);
212 /* Return the package handle that corresponds to an instance handle. */
214 OF_instance_to_package(ihandle_t instance)
223 SETUP(args, "instance-to-package", 1, 1);
225 args.instance = instance;
226 if (openfirmware(&args) == -1)
228 return (args.package);
231 /* Get the length of a property of a package. */
233 OF_getproplen(phandle_t package, const char *propname)
243 SETUP(args, "getproplen", 2, 1);
245 args.package = package;
246 args.propname = IN(propname);
247 if (openfirmware(&args) == -1)
249 return (OUT(args.proplen));
252 /* Get the value of a property of a package. */
254 OF_getprop(phandle_t package, const char *propname, void *buf, int buflen)
266 SETUP(args, "getprop", 4, 1);
268 args.package = package;
269 args.propname = IN(propname);
271 args.buflen = IN(buflen);
272 if (openfirmware(&args) == -1)
274 return (OUT(args.size));
277 /* Decode a binary property from a package. */
279 OF_getencprop(phandle_t package, const char *propname, cell_t *buf, int buflen)
282 retval = OF_getprop(package, propname, buf, buflen);
286 for (i = 0; i < buflen/4; i++)
287 buf[i] = be32toh((uint32_t)buf[i]);
292 /* Get the next property of a package. */
294 OF_nextprop(phandle_t package, const char *previous, char *buf)
305 SETUP(args, "nextprop", 3, 1);
307 args.package = package;
308 args.previous = IN(previous);
310 if (openfirmware(&args) == -1)
312 return (OUT(args.flag));
315 /* Set the value of a property of a package. */
316 /* XXX Has a bug on FirePower */
318 OF_setprop(phandle_t package, const char *propname, void *buf, int len)
330 SETUP(args, "setprop", 4, 1);
332 args.package = package;
333 args.propname = IN(propname);
336 if (openfirmware(&args) == -1)
338 return (OUT(args.size));
341 /* Convert a device specifier to a fully qualified pathname. */
343 OF_canon(const char *device, char *buf, int len)
354 SETUP(args, "canon", 3, 1);
356 args.device = IN(device);
359 if (openfirmware(&args) == -1)
361 return (OUT(args.size));
364 /* Return a package handle for the specified device. */
366 OF_finddevice(const char *device)
375 SETUP(args, "finddevice", 1, 1);
377 args.device = IN(device);
378 if (openfirmware(&args) == -1)
380 return (args.package);
383 /* Return the fully qualified pathname corresponding to an instance. */
385 OF_instance_to_path(ihandle_t instance, char *buf, int len)
396 SETUP(args, "instance-to-path", 3, 1);
398 args.instance = instance;
401 if (openfirmware(&args) == -1)
403 return (OUT(args.size));
406 /* Return the fully qualified pathname corresponding to a package. */
408 OF_package_to_path(phandle_t package, char *buf, int len)
419 SETUP(args, "package-to-path", 3, 1);
421 args.package = package;
424 if (openfirmware(&args) == -1)
426 return (OUT(args.size));
429 /* Call the method in the scope of a given instance. */
431 OF_call_method(char *method, ihandle_t instance, int nargs, int nreturns, ...)
440 cell_t args_n_results[12];
442 SETUP(args, "call-method", nargs + 2, nreturns + 1);
448 args.method = IN(method);
449 args.instance = instance;
450 va_start(ap, nreturns);
451 for (cp = (cell_t *)(args.args_n_results + (n = nargs)); --n >= 0;)
452 *--cp = IN(va_arg(ap, cell_t));
453 if (openfirmware(&args) == -1)
455 if (args.args_n_results[nargs])
456 return (OUT(args.args_n_results[nargs]));
457 /* XXX what if ihandles or phandles are returned */
458 for (cp = (cell_t *)(args.args_n_results + nargs +
459 (n = be32toh(args.nreturns))); --n > 0;)
460 *va_arg(ap, cell_t *) = OUT(*--cp);
466 * Device I/O functions
469 /* Open an instance for a device. */
471 OF_open(char *device)
480 SETUP(args, "open", 1, 1);
482 args.device = IN(device);
483 if (openfirmware(&args) == -1 || args.instance == 0) {
486 return (args.instance);
489 /* Close an instance. */
491 OF_close(ihandle_t instance)
499 SETUP(args, "close", 1, 0);
501 args.instance = instance;
505 /* Read from an instance. */
507 OF_read(ihandle_t instance, void *addr, int len)
518 SETUP(args, "read", 3, 1);
520 args.instance = instance;
521 args.addr = IN(addr);
524 #if defined(OPENFIRM_DEBUG)
525 printf("OF_read: called with instance=%08x, addr=%p, len=%d\n",
526 instance, addr, len);
529 if (openfirmware(&args) == -1)
532 #if defined(OPENFIRM_DEBUG)
533 printf("OF_read: returning instance=%d, addr=%p, len=%d, actual=%d\n",
534 args.instance, OUT(args.addr), OUT(args.len), OUT(args.actual));
537 return (OUT(args.actual));
540 /* Write to an instance. */
542 OF_write(ihandle_t instance, void *addr, int len)
553 SETUP(args, "write", 3, 1);
555 args.instance = instance;
556 args.addr = IN(addr);
558 if (openfirmware(&args) == -1)
560 return (OUT(args.actual));
563 /* Seek to a position. */
565 OF_seek(ihandle_t instance, uint64_t pos)
576 SETUP(args, "seek", 3, 1);
578 args.instance = instance;
579 args.poshi = IN(((uint64_t)pos >> 32));
580 args.poslo = IN(pos);
581 if (openfirmware(&args) == -1)
583 return (OUT(args.status));
588 OF_blocks(ihandle_t instance)
598 SETUP(args, "#blocks", 2, 1);
600 args.instance = instance;
601 if (openfirmware(&args) == -1)
602 return ((unsigned int)-1);
603 return (OUT(args.blocks));
608 OF_block_size(ihandle_t instance)
618 SETUP(args, "block-size", 2, 1);
620 args.instance = instance;
621 if (openfirmware(&args) == -1)
623 return (OUT(args.size));
630 /* Claim an area of memory. */
632 OF_claim(void *virt, u_int size, u_int align)
643 SETUP(args, "claim", 3, 1);
645 args.virt = IN(virt);
646 args.size = IN(size);
647 args.align = IN(align);
648 if (openfirmware(&args) == -1)
650 return ((void *)OUT(args.baseaddr));
653 /* Release an area of memory. */
655 OF_release(void *virt, u_int size)
664 SETUP(args, "release", 2, 0);
666 args.virt = IN(virt);
667 args.size = IN(size);
672 * Control transfer functions
675 /* Reset the system and call "boot <bootspec>". */
677 OF_boot(char *bootspec)
685 SETUP(args, "boot", 1, 0);
687 args.bootspec = IN(bootspec);
689 for (;;) /* just in case */
693 /* Suspend and drop back to the Open Firmware interface. */
702 SETUP(args, "enter", 0, 0);
705 /* We may come back. */
708 /* Shut down and drop back to the Open Firmware interface. */
717 SETUP(args, "exit", 0, 0);
720 for (;;) /* just in case */
732 SETUP(args, "quiesce", 0, 0);
737 /* Free <size> bytes starting at <virt>, then call <entry> with <arg>. */
740 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
752 SETUP(args, "chain", 5, 0);
754 args.virt = IN(virt);
755 args.size = IN(size);
756 args.entry = IN(entry);
763 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
766 * This is a REALLY dirty hack till the firmware gets this going
770 OF_release(virt, size);
772 ((int (*)(u_long, u_long, u_long, void *, u_long))entry)
773 (0, 0, (u_long)openfirmware, arg, len);