1 /* $NetBSD: openfirm.c,v 1.11 2021/02/07 13:59:36 martin Exp $ */
2
3 /*
4 * Copyright 1997
5 * Digital Equipment Corporation. All rights reserved.
6 *
7 * This software is furnished under license and may be used and
8 * copied only in accordance with the following terms and conditions.
9 * Subject to these conditions, you may download, copy, install,
10 * use, modify and distribute this software in source and/or binary
11 * form. No title or ownership is transferred hereby.
12 *
13 * 1) Any source code used, modified or distributed must reproduce
14 * and retain this copyright notice and list of conditions as
15 * they appear in the source file.
16 *
17 * 2) No right is granted to use any trade name, trademark, or logo of
18 * Digital Equipment Corporation. Neither the "Digital Equipment
19 * Corporation" name nor any trademark or logo of Digital Equipment
20 * Corporation may be used to endorse or promote products derived
21 * from this software without the prior written permission of
22 * Digital Equipment Corporation.
23 *
24 * 3) This software is provided "AS-IS" and any express or implied
25 * warranties, including but not limited to, any implied warranties
26 * of merchantability, fitness for a particular purpose, or
27 * non-infringement are disclaimed. In no event shall DIGITAL be
28 * liable for any damages whatsoever, and in particular, DIGITAL
29 * shall not be liable for special, indirect, consequential, or
30 * incidental damages or damages for lost profits, loss of
31 * revenue or loss of use, whether such damages arise in contract,
32 * negligence, tort, under statute, in equity, at law or otherwise,
33 * even if advised of the possibility of such damage.
34 */
35
36 /*
37 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
38 * Copyright (C) 1995, 1996 TooLs GmbH.
39 * All rights reserved.
40 *
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
43 * are met:
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. All advertising materials mentioning features or use of this software
50 * must display the following acknowledgement:
51 * This product includes software developed by TooLs GmbH.
52 * 4. The name of TooLs GmbH may not be used to endorse or promote products
53 * derived from this software without specific prior written permission.
54 *
55 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
56 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
57 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
58 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
59 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
60 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
61 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
62 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
63 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
64 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
65 */
66
67 #include <sys/cdefs.h>
68 __KERNEL_RCSID(0, "$NetBSD: openfirm.c,v 1.11 2021/02/07 13:59:36 martin Exp $");
69
70 #include <sys/param.h>
71
72 #include <dev/ofw/openfirm.h>
73
74
75 /*
76 * Wrapper routines for OFW client services.
77 *
78 * This code was adapted from the PowerPC version done by
79 * Wolfgang Solfrank. The main difference is that we don't
80 * do the silly "ofw_stack" dance to convert the OS's real-
81 * mode view of OFW to virtual-mode. We don't need to do
82 * that because our NetBSD port assumes virtual-mode OFW.
83 *
84 * We should work with Wolfgang to turn this into a MI file. -JJK
85 */
86
87
88 int
OF_peer(int phandle)89 OF_peer(int phandle)
90 {
91 static struct {
92 const char *name;
93 int nargs;
94 int nreturns;
95 int phandle;
96 int sibling;
97 } args = {
98 "peer",
99 1,
100 1,
101 };
102
103 args.phandle = phandle;
104 if (openfirmware(&args) == -1)
105 return 0;
106 return args.sibling;
107 }
108
109 int
OF_child(int phandle)110 OF_child(int phandle)
111 {
112 static struct {
113 const char *name;
114 int nargs;
115 int nreturns;
116 int phandle;
117 int child;
118 } args = {
119 "child",
120 1,
121 1,
122 };
123
124 args.phandle = phandle;
125 if (openfirmware(&args) == -1)
126 return 0;
127 return args.child;
128 }
129
130 int
OF_parent(int phandle)131 OF_parent(int phandle)
132 {
133 static struct {
134 const char *name;
135 int nargs;
136 int nreturns;
137 int phandle;
138 int parent;
139 } args = {
140 "parent",
141 1,
142 1,
143 };
144
145 args.phandle = phandle;
146 if (openfirmware(&args) == -1)
147 return 0;
148 return args.parent;
149 }
150
151 int
OF_instance_to_package(int ihandle)152 OF_instance_to_package(int ihandle)
153 {
154 static struct {
155 const char *name;
156 int nargs;
157 int nreturns;
158 int ihandle;
159 int phandle;
160 } args = {
161 "instance-to-package",
162 1,
163 1,
164 };
165
166 args.ihandle = ihandle;
167 if (openfirmware(&args) == -1)
168 return -1;
169 return args.phandle;
170 }
171
172 int
OF_nextprop(int handle,const char * prop,void * nextprop)173 OF_nextprop(int handle, const char *prop, void *nextprop)
174 {
175 static struct {
176 const char *name;
177 int nargs;
178 int nreturns;
179 int phandle;
180 const char *prop;
181 void *nextprop;
182 int flags;
183 } args = {
184 "nextprop",
185 3,
186 1,
187 };
188
189 args.phandle = handle;
190 args.prop = prop;
191 args.nextprop = nextprop;
192
193 if (openfirmware(&args) == -1)
194 return -1;
195 return args.flags;
196 }
197
198 int
OF_getprop(int handle,const char * prop,void * buf,int buflen)199 OF_getprop(int handle, const char *prop, void *buf, int buflen)
200 {
201 static struct {
202 const char *name;
203 int nargs;
204 int nreturns;
205 int phandle;
206 const char *prop;
207 void *buf;
208 int buflen;
209 int size;
210 } args = {
211 "getprop",
212 4,
213 1,
214 };
215
216 args.phandle = handle;
217 args.prop = prop;
218 args.buf = buf;
219 args.buflen = buflen;
220
221
222 if (openfirmware(&args) == -1)
223 return -1;
224 return args.size;
225 }
226
227 int
OF_setprop(int handle,const char * prop,const void * buf,int buflen)228 OF_setprop(int handle, const char *prop, const void *buf, int buflen)
229 {
230 static struct {
231 const char *name;
232 int nargs;
233 int nreturns;
234 int phandle;
235 const char *prop;
236 const void *buf;
237 int buflen;
238 int size;
239 } args = {
240 "setprop",
241 4,
242 1,
243 };
244
245 args.phandle = handle;
246 args.prop = prop;
247 args.buf = buf;
248 args.buflen = buflen;
249
250
251 if (openfirmware(&args) == -1)
252 return -1;
253 return args.size;
254 }
255
256 int
OF_getproplen(int handle,const char * prop)257 OF_getproplen(int handle, const char *prop)
258 {
259 static struct {
260 const char *name;
261 int nargs;
262 int nreturns;
263 int phandle;
264 const char *prop;
265 int size;
266 } args = {
267 "getproplen",
268 2,
269 1,
270 };
271
272 args.phandle = handle;
273 args.prop = prop;
274 if (openfirmware(&args) == -1)
275 return -1;
276 return args.size;
277 }
278
279 int
OF_finddevice(const char * name)280 OF_finddevice(const char *name)
281 {
282 static struct {
283 const char *name;
284 int nargs;
285 int nreturns;
286 const char *device;
287 int phandle;
288 } args = {
289 "finddevice",
290 1,
291 1,
292 };
293
294 args.device = name;
295 if (openfirmware(&args) == -1)
296 return -1;
297 return args.phandle;
298 }
299
300 int
OF_instance_to_path(int ihandle,char * buf,int buflen)301 OF_instance_to_path(int ihandle, char *buf, int buflen)
302 {
303 static struct {
304 const char *name;
305 int nargs;
306 int nreturns;
307 int ihandle;
308 char *buf;
309 int buflen;
310 int length;
311 } args = {
312 "instance-to-path",
313 3,
314 1,
315 };
316
317 args.ihandle = ihandle;
318 args.buf = buf;
319 args.buflen = buflen;
320 if (openfirmware(&args) < 0)
321 return -1;
322 return args.length;
323 }
324
325 int
OF_package_to_path(int phandle,char * buf,int buflen)326 OF_package_to_path(int phandle, char *buf, int buflen)
327 {
328 static struct {
329 const char *name;
330 int nargs;
331 int nreturns;
332 int phandle;
333 char *buf;
334 int buflen;
335 int length;
336 } args = {
337 "package-to-path",
338 3,
339 1,
340 };
341
342 args.phandle = phandle;
343 args.buf = buf;
344 args.buflen = buflen;
345 if (openfirmware(&args) < 0)
346 return -1;
347 return args.length;
348 }
349
350 int
351 #ifdef __STDC__
OF_call_method(const char * method,int ihandle,int nargs,int nreturns,...)352 OF_call_method(const char *method, int ihandle, int nargs, int nreturns, ...)
353 #else
354 OF_call_method(method, ihandle, nargs, nreturns, va_alist)
355 const char *method;
356 int ihandle;
357 int nargs;
358 int nreturns;
359 va_dcl
360 #endif
361 {
362 va_list ap;
363 static struct {
364 const char *name;
365 int nargs;
366 int nreturns;
367 const char *method;
368 int ihandle;
369 int args_n_results[12];
370 } args = {
371 "call-method",
372 2,
373 1,
374 };
375 int *ip, n;
376
377 if (nargs > 6)
378 return -1;
379 args.nargs = nargs + 2;
380 args.nreturns = nreturns + 1;
381 args.method = method;
382 args.ihandle = ihandle;
383 va_start(ap, nreturns);
384 for (ip = args.args_n_results + (n = nargs); --n >= 0;)
385 *--ip = va_arg(ap, int);
386 if (openfirmware(&args) == -1) {
387 va_end(ap);
388 return -1;
389 }
390 /*
391 {
392 int i, res;
393
394 printf("call_method(%s): ihandle = %x, nargs = %d, nreturns = %d -- ",
395 method, ihandle, nargs, nreturns);
396 res = openfirmware(&args);
397 printf("res = %x\n", res);
398 printf("\targs_n_results = ");
399 for (i = 0; i < nargs + nreturns + 1; i++)
400 printf("%x ", args.args_n_results[i]);
401 printf("\n");
402 if (res == -1) return -1;
403 }
404 */
405 if (args.args_n_results[nargs]) {
406 va_end(ap);
407 return args.args_n_results[nargs];
408 }
409 for (ip = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
410 *va_arg(ap, int *) = *--ip;
411 va_end(ap);
412 return 0;
413 }
414
415 int
416 #ifdef __STDC__
OF_call_method_1(const char * method,int ihandle,int nargs,...)417 OF_call_method_1(const char *method, int ihandle, int nargs, ...)
418 #else
419 OF_call_method_1(method, ihandle, nargs, va_alist)
420 const char *method;
421 int ihandle;
422 int nargs;
423 va_dcl
424 #endif
425 {
426 va_list ap;
427 static struct {
428 const char *name;
429 int nargs;
430 int nreturns;
431 const char *method;
432 int ihandle;
433 int args_n_results[8];
434 } args = {
435 "call-method",
436 2,
437 2,
438 };
439 int *ip, n;
440
441 if (nargs > 6)
442 return -1;
443 args.nargs = nargs + 2;
444 args.method = method;
445 args.ihandle = ihandle;
446 va_start(ap, nargs);
447 for (ip = args.args_n_results + (n = nargs); --n >= 0;)
448 *--ip = va_arg(ap, int);
449 va_end(ap);
450 if (openfirmware(&args) == -1)
451 return -1;
452 /*
453 {
454 int i, res;
455
456 printf("call_method_1(%s): ihandle = %x, nargs = %d -- ",
457 method, ihandle, nargs);
458 res = openfirmware(&args);
459 printf("res = %x\n", res);
460 printf("\targs_n_results = ");
461 for (i = 0; i < nargs + 2; i++)
462 printf("%x ", args.args_n_results[i]);
463 printf("\n");
464 if (res == -1) return -1;
465 }
466 */
467 if (args.args_n_results[nargs])
468 return -1;
469 return args.args_n_results[nargs + 1];
470 }
471
472 int
OF_open(const char * dname)473 OF_open(const char *dname)
474 {
475 static struct {
476 const char *name;
477 int nargs;
478 int nreturns;
479 const char *dname;
480 int handle;
481 } args = {
482 "open",
483 1,
484 1,
485 };
486
487 args.dname = dname;
488 if (openfirmware(&args) == -1)
489 return -1;
490 return args.handle;
491 }
492
493 void
OF_close(int handle)494 OF_close(int handle)
495 {
496 static struct {
497 const char *name;
498 int nargs;
499 int nreturns;
500 int handle;
501 } args = {
502 "close",
503 1,
504 0,
505 };
506
507 args.handle = handle;
508 openfirmware(&args);
509 }
510
511 int
OF_read(int handle,void * addr,int len)512 OF_read(int handle, void *addr, int len)
513 {
514 static struct {
515 const char *name;
516 int nargs;
517 int nreturns;
518 int ihandle;
519 void *addr;
520 int len;
521 int actual;
522 } args = {
523 "read",
524 3,
525 1,
526 };
527
528 args.ihandle = handle;
529 args.addr = addr;
530 args.len = len;
531 if (openfirmware(&args) == -1)
532 return -1;
533 return args.actual;
534 }
535
536 int
OF_write(int handle,const void * addr,int len)537 OF_write(int handle, const void *addr, int len)
538 {
539 static struct {
540 const char *name;
541 int nargs;
542 int nreturns;
543 int ihandle;
544 const void *addr;
545 int len;
546 int actual;
547 } args = {
548 "write",
549 3,
550 1,
551 };
552
553 args.ihandle = handle;
554 args.addr = addr;
555 args.len = len;
556 if (openfirmware(&args) == -1)
557 return -1;
558 return args.actual;
559 }
560
561 int
OF_seek(int handle,u_quad_t pos)562 OF_seek(int handle, u_quad_t pos)
563 {
564 static struct {
565 const char *name;
566 int nargs;
567 int nreturns;
568 int handle;
569 int poshi;
570 int poslo;
571 int status;
572 } args = {
573 "seek",
574 3,
575 1,
576 };
577
578 args.handle = handle;
579 args.poshi = (int)(pos >> 32);
580 args.poslo = (int)pos;
581 if (openfirmware(&args) == -1)
582 return -1;
583 return args.status;
584 }
585
586 void *
OF_claim(void * virt,u_int size,u_int align)587 OF_claim(void *virt, u_int size, u_int align)
588 {
589 static struct {
590 const char *name;
591 int nargs;
592 int nreturns;
593 void *virt;
594 u_int size;
595 u_int align;
596 void *baseaddr;
597 } args = {
598 "claim",
599 3,
600 1,
601 };
602
603 args.virt = virt;
604 args.size = size;
605 args.align = align;
606 if (openfirmware(&args) == -1)
607 return (void *)-1;
608 return args.baseaddr;
609 }
610
611 void
OF_release(void * virt,u_int size)612 OF_release(void *virt, u_int size)
613 {
614 static struct {
615 const char *name;
616 int nargs;
617 int nreturns;
618 void *virt;
619 u_int size;
620 } args = {
621 "release",
622 2,
623 0,
624 };
625
626 args.virt = virt;
627 args.size = size;
628 openfirmware(&args);
629 }
630
631 int
OF_milliseconds(void)632 OF_milliseconds(void)
633 {
634 static struct {
635 const char *name;
636 int nargs;
637 int nreturns;
638 int ms;
639 } args = {
640 "milliseconds",
641 0,
642 1,
643 };
644
645 openfirmware(&args);
646 return args.ms;
647 }
648
649 void
OF_boot(const char * btspec)650 OF_boot(const char *btspec)
651 {
652 static struct {
653 const char *name;
654 int nargs;
655 int nreturns;
656 const char *bootspec;
657 } args = {
658 "boot",
659 1,
660 0,
661 };
662
663 args.bootspec = btspec;
664 openfirmware(&args);
665 while (1); /* just in case */
666 }
667
668 void
OF_enter(void)669 OF_enter(void)
670 {
671 static struct {
672 const char *name;
673 int nargs;
674 int nreturns;
675 } args = {
676 "enter",
677 0,
678 0,
679 };
680
681 openfirmware(&args);
682 }
683
684 void
OF_exit(void)685 OF_exit(void)
686 {
687 static struct {
688 const char *name;
689 int nargs;
690 int nreturns;
691 } args = {
692 "exit",
693 0,
694 0,
695 };
696
697 openfirmware(&args);
698 while (1); /* just in case */
699 }
700
701 typedef void (*of_callback_t)(void *);
702
703 of_callback_t
OF_set_callback(of_callback_t newfunc)704 OF_set_callback(of_callback_t newfunc)
705 {
706 static struct {
707 const char *name;
708 int nargs;
709 int nreturns;
710 of_callback_t newfunc;
711 of_callback_t oldfunc;
712 } args = {
713 "set-callback",
714 1,
715 1,
716 };
717
718 args.newfunc = newfunc;
719 if (openfirmware(&args) == -1)
720 return 0;
721 return args.oldfunc;
722 }
723