1 /* $NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $ */
2
3 /*-
4 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
5 * Copyright (C) 1995, 1996 TooLs GmbH.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
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.
21 *
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.
32 */
33 /*-
34 * Copyright (C) 2000 Benno Rice.
35 * All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
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.
45 *
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.
56 */
57
58 #include <sys/cdefs.h>
59 __FBSDID("$FreeBSD$");
60
61 #include <machine/stdarg.h>
62
63 #include <stand.h>
64
65 #include "openfirm.h"
66
67 int (*openfirmware)(void *);
68
69 phandle_t chosen;
70 ihandle_t mmu;
71 ihandle_t memory;
72 int real_mode = 0;
73
74 /* Initialiser */
75
76 void
OF_init(int (* openfirm)(void *))77 OF_init(int (*openfirm)(void *))
78 {
79 phandle_t options;
80 char mode[sizeof("true")];
81
82 openfirmware = openfirm;
83
84 if ((chosen = OF_finddevice("/chosen")) == -1)
85 OF_exit();
86 if (OF_getprop(chosen, "memory", &memory, sizeof(memory)) == -1) {
87 memory = OF_open("/memory");
88 if (memory == -1)
89 memory = OF_open("/memory@0");
90 if (memory == -1)
91 OF_exit();
92 }
93 if (OF_getprop(chosen, "mmu", &mmu, sizeof(mmu)) == -1)
94 OF_exit();
95
96 /*
97 * Check if we run in real mode. If so, we do not need to map
98 * memory later on.
99 */
100 options = OF_finddevice("/options");
101 if (OF_getprop(options, "real-mode?", mode, sizeof(mode)) > 0 &&
102 strcmp(mode, "true") == 0)
103 real_mode = 1;
104 }
105
106 /*
107 * Generic functions
108 */
109
110 /* Test to see if a service exists. */
111 int
OF_test(char * name)112 OF_test(char *name)
113 {
114 static struct {
115 cell_t name;
116 cell_t nargs;
117 cell_t nreturns;
118 cell_t service;
119 cell_t missing;
120 } args = {
121 (cell_t)"test",
122 1,
123 1,
124 };
125
126 args.service = (cell_t)name;
127 if (openfirmware(&args) == -1)
128 return (-1);
129 return (args.missing);
130 }
131
132 /* Return firmware millisecond count. */
133 int
OF_milliseconds()134 OF_milliseconds()
135 {
136 static struct {
137 cell_t name;
138 cell_t nargs;
139 cell_t nreturns;
140 cell_t ms;
141 } args = {
142 (cell_t)"milliseconds",
143 0,
144 1,
145 };
146
147 openfirmware(&args);
148 return (args.ms);
149 }
150
151 /*
152 * Device tree functions
153 */
154
155 /* Return the next sibling of this node or 0. */
156 phandle_t
OF_peer(phandle_t node)157 OF_peer(phandle_t node)
158 {
159 static struct {
160 cell_t name;
161 cell_t nargs;
162 cell_t nreturns;
163 cell_t node;
164 cell_t next;
165 } args = {
166 (cell_t)"peer",
167 1,
168 1,
169 };
170
171 args.node = node;
172 if (openfirmware(&args) == -1)
173 return (-1);
174 return (args.next);
175 }
176
177 /* Return the first child of this node or 0. */
178 phandle_t
OF_child(phandle_t node)179 OF_child(phandle_t node)
180 {
181 static struct {
182 cell_t name;
183 cell_t nargs;
184 cell_t nreturns;
185 cell_t node;
186 cell_t child;
187 } args = {
188 (cell_t)"child",
189 1,
190 1,
191 };
192
193 args.node = node;
194 if (openfirmware(&args) == -1)
195 return (-1);
196 return (args.child);
197 }
198
199 /* Return the parent of this node or 0. */
200 phandle_t
OF_parent(phandle_t node)201 OF_parent(phandle_t node)
202 {
203 static struct {
204 cell_t name;
205 cell_t nargs;
206 cell_t nreturns;
207 cell_t node;
208 cell_t parent;
209 } args = {
210 (cell_t)"parent",
211 1,
212 1,
213 };
214
215 args.node = node;
216 if (openfirmware(&args) == -1)
217 return (-1);
218 return (args.parent);
219 }
220
221 /* Return the package handle that corresponds to an instance handle. */
222 phandle_t
OF_instance_to_package(ihandle_t instance)223 OF_instance_to_package(ihandle_t instance)
224 {
225 static struct {
226 cell_t name;
227 cell_t nargs;
228 cell_t nreturns;
229 cell_t instance;
230 cell_t package;
231 } args = {
232 (cell_t)"instance-to-package",
233 1,
234 1,
235 };
236
237 args.instance = instance;
238 if (openfirmware(&args) == -1)
239 return (-1);
240 return (args.package);
241 }
242
243 /* Get the length of a property of a package. */
244 int
OF_getproplen(phandle_t package,char * propname)245 OF_getproplen(phandle_t package, char *propname)
246 {
247 static struct {
248 cell_t name;
249 cell_t nargs;
250 cell_t nreturns;
251 cell_t package;
252 cell_t propname;
253 cell_t proplen;
254 } args = {
255 (cell_t)"getproplen",
256 2,
257 1,
258 };
259
260 args.package = package;
261 args.propname = (cell_t)propname;
262 if (openfirmware(&args) == -1)
263 return (-1);
264 return (args.proplen);
265 }
266
267 /* Get the value of a property of a package. */
268 int
OF_getprop(phandle_t package,char * propname,void * buf,int buflen)269 OF_getprop(phandle_t package, char *propname, void *buf, int buflen)
270 {
271 static struct {
272 cell_t name;
273 cell_t nargs;
274 cell_t nreturns;
275 cell_t package;
276 cell_t propname;
277 cell_t buf;
278 cell_t buflen;
279 cell_t size;
280 } args = {
281 (cell_t)"getprop",
282 4,
283 1,
284 };
285
286 args.package = package;
287 args.propname = (cell_t)propname;
288 args.buf = (cell_t)buf;
289 args.buflen = buflen;
290 if (openfirmware(&args) == -1)
291 return (-1);
292 return (args.size);
293 }
294
295 /* Get the next property of a package. */
296 int
OF_nextprop(phandle_t package,char * previous,char * buf)297 OF_nextprop(phandle_t package, char *previous, char *buf)
298 {
299 static struct {
300 cell_t name;
301 cell_t nargs;
302 cell_t nreturns;
303 cell_t package;
304 cell_t previous;
305 cell_t buf;
306 cell_t flag;
307 } args = {
308 (cell_t)"nextprop",
309 3,
310 1,
311 };
312
313 args.package = package;
314 args.previous = (cell_t)previous;
315 args.buf = (cell_t)buf;
316 if (openfirmware(&args) == -1)
317 return (-1);
318 return (args.flag);
319 }
320
321 /* Set the value of a property of a package. */
322 /* XXX Has a bug on FirePower */
323 int
OF_setprop(phandle_t package,char * propname,void * buf,int len)324 OF_setprop(phandle_t package, char *propname, void *buf, int len)
325 {
326 static struct {
327 cell_t name;
328 cell_t nargs;
329 cell_t nreturns;
330 cell_t package;
331 cell_t propname;
332 cell_t buf;
333 cell_t len;
334 cell_t size;
335 } args = {
336 (cell_t)"setprop",
337 4,
338 1,
339 };
340
341 args.package = package;
342 args.propname = (cell_t)propname;
343 args.buf = (cell_t)buf;
344 args.len = len;
345 if (openfirmware(&args) == -1)
346 return (-1);
347 return (args.size);
348 }
349
350 /* Convert a device specifier to a fully qualified pathname. */
351 int
OF_canon(const char * device,char * buf,int len)352 OF_canon(const char *device, char *buf, int len)
353 {
354 static struct {
355 cell_t name;
356 cell_t nargs;
357 cell_t nreturns;
358 cell_t device;
359 cell_t buf;
360 cell_t len;
361 cell_t size;
362 } args = {
363 (cell_t)"canon",
364 3,
365 1,
366 };
367
368 args.device = (cell_t)device;
369 args.buf = (cell_t)buf;
370 args.len = len;
371 if (openfirmware(&args) == -1)
372 return (-1);
373 return (args.size);
374 }
375
376 /* Return a package handle for the specified device. */
377 phandle_t
OF_finddevice(const char * device)378 OF_finddevice(const char *device)
379 {
380 static struct {
381 cell_t name;
382 cell_t nargs;
383 cell_t nreturns;
384 cell_t device;
385 cell_t package;
386 } args = {
387 (cell_t)"finddevice",
388 1,
389 1,
390 };
391
392 args.device = (cell_t)device;
393 if (openfirmware(&args) == -1)
394 return (-1);
395 return (args.package);
396 }
397
398 /* Return the fully qualified pathname corresponding to an instance. */
399 int
OF_instance_to_path(ihandle_t instance,char * buf,int len)400 OF_instance_to_path(ihandle_t instance, char *buf, int len)
401 {
402 static struct {
403 cell_t name;
404 cell_t nargs;
405 cell_t nreturns;
406 cell_t instance;
407 cell_t buf;
408 cell_t len;
409 cell_t size;
410 } args = {
411 (cell_t)"instance-to-path",
412 3,
413 1,
414 };
415
416 args.instance = instance;
417 args.buf = (cell_t)buf;
418 args.len = len;
419 if (openfirmware(&args) == -1)
420 return (-1);
421 return (args.size);
422 }
423
424 /* Return the fully qualified pathname corresponding to a package. */
425 int
OF_package_to_path(phandle_t package,char * buf,int len)426 OF_package_to_path(phandle_t package, char *buf, int len)
427 {
428 static struct {
429 cell_t name;
430 cell_t nargs;
431 cell_t nreturns;
432 cell_t package;
433 cell_t buf;
434 cell_t len;
435 cell_t size;
436 } args = {
437 (cell_t)"package-to-path",
438 3,
439 1,
440 };
441
442 args.package = package;
443 args.buf = (cell_t)buf;
444 args.len = len;
445 if (openfirmware(&args) == -1)
446 return (-1);
447 return (args.size);
448 }
449
450 /* Call the method in the scope of a given instance. */
451 int
OF_call_method(char * method,ihandle_t instance,int nargs,int nreturns,...)452 OF_call_method(char *method, ihandle_t instance, int nargs, int nreturns, ...)
453 {
454 va_list ap;
455 static struct {
456 cell_t name;
457 cell_t nargs;
458 cell_t nreturns;
459 cell_t method;
460 cell_t instance;
461 cell_t args_n_results[12];
462 } args = {
463 (cell_t)"call-method",
464 2,
465 1,
466 };
467 cell_t *cp;
468 int n;
469
470 if (nargs > 6)
471 return (-1);
472 args.nargs = nargs + 2;
473 args.nreturns = nreturns + 1;
474 args.method = (cell_t)method;
475 args.instance = instance;
476 va_start(ap, nreturns);
477 for (cp = (cell_t *)(args.args_n_results + (n = nargs)); --n >= 0;)
478 *--cp = va_arg(ap, cell_t);
479 if (openfirmware(&args) == -1)
480 return (-1);
481 if (args.args_n_results[nargs])
482 return (args.args_n_results[nargs]);
483 for (cp = (cell_t *)(args.args_n_results + nargs + (n = args.nreturns));
484 --n > 0;)
485 *va_arg(ap, cell_t *) = *--cp;
486 va_end(ap);
487 return (0);
488 }
489
490 /*
491 * Device I/O functions
492 */
493
494 /* Open an instance for a device. */
495 ihandle_t
OF_open(char * device)496 OF_open(char *device)
497 {
498 static struct {
499 cell_t name;
500 cell_t nargs;
501 cell_t nreturns;
502 cell_t device;
503 cell_t instance;
504 } args = {
505 (cell_t)"open",
506 1,
507 1,
508 };
509
510 args.device = (cell_t)device;
511 if (openfirmware(&args) == -1 || args.instance == 0) {
512 return (-1);
513 }
514 return (args.instance);
515 }
516
517 /* Close an instance. */
518 void
OF_close(ihandle_t instance)519 OF_close(ihandle_t instance)
520 {
521 static struct {
522 cell_t name;
523 cell_t nargs;
524 cell_t nreturns;
525 cell_t instance;
526 } args = {
527 (cell_t)"close",
528 1,
529 };
530
531 args.instance = instance;
532 openfirmware(&args);
533 }
534
535 /* Read from an instance. */
536 int
OF_read(ihandle_t instance,void * addr,int len)537 OF_read(ihandle_t instance, void *addr, int len)
538 {
539 static struct {
540 cell_t name;
541 cell_t nargs;
542 cell_t nreturns;
543 cell_t instance;
544 cell_t addr;
545 cell_t len;
546 cell_t actual;
547 } args = {
548 (cell_t)"read",
549 3,
550 1,
551 };
552
553 args.instance = instance;
554 args.addr = (cell_t)addr;
555 args.len = len;
556
557 #if defined(OPENFIRM_DEBUG)
558 printf("OF_read: called with instance=%08x, addr=%p, len=%d\n",
559 args.instance, args.addr, args.len);
560 #endif
561
562 if (openfirmware(&args) == -1)
563 return (-1);
564
565 #if defined(OPENFIRM_DEBUG)
566 printf("OF_read: returning instance=%d, addr=%p, len=%d, actual=%d\n",
567 args.instance, args.addr, args.len, args.actual);
568 #endif
569
570 return (args.actual);
571 }
572
573 /* Write to an instance. */
574 int
OF_write(ihandle_t instance,void * addr,int len)575 OF_write(ihandle_t instance, void *addr, int len)
576 {
577 static struct {
578 cell_t name;
579 cell_t nargs;
580 cell_t nreturns;
581 cell_t instance;
582 cell_t addr;
583 cell_t len;
584 cell_t actual;
585 } args = {
586 (cell_t)"write",
587 3,
588 1,
589 };
590
591 args.instance = instance;
592 args.addr = (cell_t)addr;
593 args.len = len;
594 if (openfirmware(&args) == -1)
595 return (-1);
596 return (args.actual);
597 }
598
599 /* Seek to a position. */
600 int
OF_seek(ihandle_t instance,u_int64_t pos)601 OF_seek(ihandle_t instance, u_int64_t pos)
602 {
603 static struct {
604 cell_t name;
605 cell_t nargs;
606 cell_t nreturns;
607 cell_t instance;
608 cell_t poshi;
609 cell_t poslo;
610 cell_t status;
611 } args = {
612 (cell_t)"seek",
613 3,
614 1,
615 };
616
617 args.instance = instance;
618 args.poshi = pos >> 32;
619 args.poslo = pos;
620 if (openfirmware(&args) == -1)
621 return (-1);
622 return (args.status);
623 }
624
625 /*
626 * Memory functions
627 */
628
629 /* Claim an area of memory. */
630 void *
OF_claim(void * virt,u_int size,u_int align)631 OF_claim(void *virt, u_int size, u_int align)
632 {
633 static struct {
634 cell_t name;
635 cell_t nargs;
636 cell_t nreturns;
637 cell_t virt;
638 cell_t size;
639 cell_t align;
640 cell_t baseaddr;
641 } args = {
642 (cell_t)"claim",
643 3,
644 1,
645 };
646
647 args.virt = (cell_t)virt;
648 args.size = size;
649 args.align = align;
650 if (openfirmware(&args) == -1)
651 return ((void *)-1);
652 return ((void *)args.baseaddr);
653 }
654
655 /* Release an area of memory. */
656 void
OF_release(void * virt,u_int size)657 OF_release(void *virt, u_int size)
658 {
659 static struct {
660 cell_t name;
661 cell_t nargs;
662 cell_t nreturns;
663 cell_t virt;
664 cell_t size;
665 } args = {
666 (cell_t)"release",
667 2,
668 };
669
670 args.virt = (cell_t)virt;
671 args.size = size;
672 openfirmware(&args);
673 }
674
675 /*
676 * Control transfer functions
677 */
678
679 /* Reset the system and call "boot <bootspec>". */
680 void
OF_boot(char * bootspec)681 OF_boot(char *bootspec)
682 {
683 static struct {
684 cell_t name;
685 cell_t nargs;
686 cell_t nreturns;
687 cell_t bootspec;
688 } args = {
689 (cell_t)"boot",
690 1,
691 };
692
693 args.bootspec = (cell_t)bootspec;
694 openfirmware(&args);
695 for (;;) /* just in case */
696 ;
697 }
698
699 /* Suspend and drop back to the Open Firmware interface. */
700 void
OF_enter()701 OF_enter()
702 {
703 static struct {
704 cell_t name;
705 cell_t nargs;
706 cell_t nreturns;
707 } args = {
708 (cell_t)"enter",
709 };
710
711 openfirmware(&args);
712 /* We may come back. */
713 }
714
715 /* Shut down and drop back to the Open Firmware interface. */
716 void
OF_exit()717 OF_exit()
718 {
719 static struct {
720 cell_t name;
721 cell_t nargs;
722 cell_t nreturns;
723 } args = {
724 (cell_t)"exit",
725 };
726
727 openfirmware(&args);
728 for (;;) /* just in case */
729 ;
730 }
731
732 void
OF_quiesce()733 OF_quiesce()
734 {
735 static struct {
736 cell_t name;
737 cell_t nargs;
738 cell_t nreturns;
739 } args = {
740 (cell_t)"quiesce",
741 };
742
743 openfirmware(&args);
744 }
745
746 /* Free <size> bytes starting at <virt>, then call <entry> with <arg>. */
747 #if 0
748 void
749 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
750 {
751 static struct {
752 cell_t name;
753 cell_t nargs;
754 cell_t nreturns;
755 cell_t virt;
756 cell_t size;
757 cell_t entry;
758 cell_t arg;
759 cell_t len;
760 } args = {
761 (cell_t)"chain",
762 5,
763 };
764
765 args.virt = (cell_t)virt;
766 args.size = size;
767 args.entry = (cell_t)entry;
768 args.arg = (cell_t)arg;
769 args.len = len;
770 openfirmware(&args);
771 }
772 #else
773 void
OF_chain(void * virt,u_int size,void (* entry)(),void * arg,u_int len)774 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
775 {
776 /*
777 * This is a REALLY dirty hack till the firmware gets this going
778 */
779 #if 0
780 if (size > 0)
781 OF_release(virt, size);
782 #endif
783 entry(0, 0, openfirmware, arg, len);
784 }
785 #endif
786