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
);