Deleted Added
sdiff udiff text old ( 208172 ) new ( 208614 )
full compact
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: head/sys/powerpc/ofw/ofw_real.c 208172 2010-05-16 22:01:43Z nwhitehorn $");
60
61#include <sys/param.h>
62#include <sys/kernel.h>
63#include <sys/lock.h>
64#include <sys/mutex.h>
65#include <sys/systm.h>
66
67#include <vm/vm.h>
68#include <vm/pmap.h>
69
70#include <machine/stdarg.h>
71#include <machine/bus.h>
72#include <machine/pmap.h>
73#include <machine/ofw_machdep.h>
74
75#include <dev/ofw/openfirm.h>
76#include <dev/ofw/ofwvar.h>
77#include "ofw_if.h"
78
79static void ofw_real_init(ofw_t, void *openfirm);
80static int ofw_real_test(ofw_t, const char *name);
81static phandle_t ofw_real_peer(ofw_t, phandle_t node);
82static phandle_t ofw_real_child(ofw_t, phandle_t node);
83static phandle_t ofw_real_parent(ofw_t, phandle_t node);
84static phandle_t ofw_real_instance_to_package(ofw_t, ihandle_t instance);
85static ssize_t ofw_real_getproplen(ofw_t, phandle_t package,
86 const char *propname);
87static ssize_t ofw_real_getprop(ofw_t, phandle_t package, const char *propname,
88 void *buf, size_t buflen);
89static int ofw_real_nextprop(ofw_t, phandle_t package, const char *previous,
90 char *buf, size_t);
91static int ofw_real_setprop(ofw_t, phandle_t package, const char *propname,
92 const void *buf, size_t len);
93static ssize_t ofw_real_canon(ofw_t, const char *device, char *buf, size_t len);
94static phandle_t ofw_real_finddevice(ofw_t, const char *device);
95static ssize_t ofw_real_instance_to_path(ofw_t, ihandle_t instance, char *buf,
96 size_t len);
97static ssize_t ofw_real_package_to_path(ofw_t, phandle_t package, char *buf,
98 size_t len);
99static int ofw_real_call_method(ofw_t, ihandle_t instance, const char *method,
100 int nargs, int nreturns, unsigned long *args_and_returns);
101static ihandle_t ofw_real_open(ofw_t, const char *device);
102static void ofw_real_close(ofw_t, ihandle_t instance);
103static ssize_t ofw_real_read(ofw_t, ihandle_t instance, void *addr, size_t len);
104static ssize_t ofw_real_write(ofw_t, ihandle_t instance, const void *addr,
105 size_t len);
106static int ofw_real_seek(ofw_t, ihandle_t instance, u_int64_t pos);
107static caddr_t ofw_real_claim(ofw_t, void *virt, size_t size, u_int align);
108static void ofw_real_release(ofw_t, void *virt, size_t size);
109static void ofw_real_enter(ofw_t);
110static void ofw_real_exit(ofw_t);
111
112static ofw_method_t ofw_real_methods[] = {
113 OFWMETHOD(ofw_init, ofw_real_init),
114 OFWMETHOD(ofw_peer, ofw_real_peer),
115 OFWMETHOD(ofw_child, ofw_real_child),
116 OFWMETHOD(ofw_parent, ofw_real_parent),
117 OFWMETHOD(ofw_instance_to_package, ofw_real_instance_to_package),
118 OFWMETHOD(ofw_getproplen, ofw_real_getproplen),
119 OFWMETHOD(ofw_getprop, ofw_real_getprop),
120 OFWMETHOD(ofw_nextprop, ofw_real_nextprop),
121 OFWMETHOD(ofw_setprop, ofw_real_setprop),
122 OFWMETHOD(ofw_canon, ofw_real_canon),
123 OFWMETHOD(ofw_finddevice, ofw_real_finddevice),
124 OFWMETHOD(ofw_instance_to_path, ofw_real_instance_to_path),
125 OFWMETHOD(ofw_package_to_path, ofw_real_package_to_path),
126
127 OFWMETHOD(ofw_test, ofw_real_test),
128 OFWMETHOD(ofw_call_method, ofw_real_call_method),
129 OFWMETHOD(ofw_open, ofw_real_open),
130 OFWMETHOD(ofw_close, ofw_real_close),
131 OFWMETHOD(ofw_read, ofw_real_read),
132 OFWMETHOD(ofw_write, ofw_real_write),
133 OFWMETHOD(ofw_seek, ofw_real_seek),
134 OFWMETHOD(ofw_claim, ofw_real_claim),
135 OFWMETHOD(ofw_release, ofw_real_release),
136 OFWMETHOD(ofw_enter, ofw_real_enter),
137 OFWMETHOD(ofw_exit, ofw_real_exit),
138
139 { 0, 0 }
140};
141
142static ofw_def_t ofw_real = {
143 OFW_STD_REAL,
144 ofw_real_methods,
145 0
146};
147OFW_DEF(ofw_real);
148
149MALLOC_DEFINE(M_OFWREAL, "ofwreal", "Open Firmware Real Mode Bounce Page");
150
151static int (*openfirmware)(void *);
152
153static vm_offset_t of_bounce_phys;
154static caddr_t of_bounce_virt;
155static off_t of_bounce_offset;
156static size_t of_bounce_size;
157static struct mtx of_bounce_mtx;
158
159/*
160 * After the VM is up, allocate a wired, low memory bounce page.
161 */
162
163static void ofw_real_bounce_alloc(void *);
164
165SYSINIT(ofw_real_bounce_alloc, SI_SUB_VM, SI_ORDER_ANY,
166 ofw_real_bounce_alloc, NULL);
167
168static void
169ofw_real_start(void)
170{
171 mtx_lock(&of_bounce_mtx);
172 of_bounce_offset = 0;
173}
174
175static void
176ofw_real_stop(void)
177{
178 mtx_unlock(&of_bounce_mtx);
179}
180
181static void
182ofw_real_bounce_alloc(void *junk)
183{
184 /*
185 * Check that ofw_real is actually in use before allocating wads
186 * of memory. Do this by checking if our mutex has been set up.
187 */
188 if (!mtx_initialized(&of_bounce_mtx))
189 return;
190
191 /*
192 * Allocate a page of contiguous, wired physical memory that can
193 * fit into a 32-bit address space.
194 */
195
196 mtx_lock(&of_bounce_mtx);
197
198 of_bounce_virt = contigmalloc(PAGE_SIZE, M_OFWREAL, 0,
199 0, BUS_SPACE_MAXADDR_32BIT, PAGE_SIZE, PAGE_SIZE);
200 of_bounce_phys = vtophys(of_bounce_virt);
201 of_bounce_size = PAGE_SIZE;
202
203 mtx_unlock(&of_bounce_mtx);
204}
205
206static cell_t
207ofw_real_map(const void *buf, size_t len)
208{
209 cell_t phys;
210
211 mtx_assert(&of_bounce_mtx, MA_OWNED);
212
213 if (of_bounce_virt == NULL) {
214 if (!pmap_bootstrapped)
215 return (cell_t)buf;
216
217 /*
218 * XXX: It is possible for us to get called before the VM has
219 * come online, but after the MMU is up. We don't have the
220 * bounce buffer yet, but can no longer presume a 1:1 mapping.
221 * Grab the physical address of the buffer, and hope it is
222 * in range if this happens.
223 */
224 return (cell_t)vtophys(buf);
225 }
226
227 /*
228 * Make sure the bounce page offset satisfies any reasonable
229 * alignment constraint.
230 */
231 of_bounce_offset += of_bounce_offset % sizeof(register_t);
232
233 if (of_bounce_offset + len > of_bounce_size) {
234 panic("Oversize Open Firmware call!");
235 return 0;
236 }
237
238 memcpy(of_bounce_virt + of_bounce_offset, buf, len);
239 phys = of_bounce_phys + of_bounce_offset;
240
241 of_bounce_offset += len;
242
243 return phys;
244}
245
246static void
247ofw_real_unmap(cell_t physaddr, void *buf, size_t len)
248{
249 mtx_assert(&of_bounce_mtx, MA_OWNED);
250
251 if (of_bounce_virt == NULL)
252 return;
253
254 memcpy(buf,of_bounce_virt + (physaddr - of_bounce_phys),len);
255}
256
257/* Initialiser */
258
259static void
260ofw_real_init(ofw_t ofw, void *openfirm)
261{
262 openfirmware = (int (*)(void *))openfirm;
263
264 mtx_init(&of_bounce_mtx, "OF Bounce Page", MTX_DEF, 0);
265 of_bounce_virt = NULL;
266}
267
268/*
269 * Generic functions
270 */
271
272/* Test to see if a service exists. */
273static int
274ofw_real_test(ofw_t ofw, const char *name)
275{
276 struct {
277 cell_t name;
278 cell_t nargs;
279 cell_t nreturns;
280 cell_t service;
281 cell_t missing;
282 } args = {
283 (cell_t)"test",
284 1,
285 1,
286 };
287
288 ofw_real_start();
289
290 args.service = ofw_real_map(name, strlen(name) + 1);
291 if (args.service == 0 || openfirmware(&args) == -1) {
292 ofw_real_stop();
293 return (-1);
294 }
295 ofw_real_stop();
296 return (args.missing);
297}
298
299/*
300 * Device tree functions
301 */
302
303/* Return the next sibling of this node or 0. */
304static phandle_t
305ofw_real_peer(ofw_t ofw, phandle_t node)
306{
307 struct {
308 cell_t name;
309 cell_t nargs;
310 cell_t nreturns;
311 cell_t node;
312 cell_t next;
313 } args = {
314 (cell_t)"peer",
315 1,
316 1,
317 };
318
319 args.node = node;
320 if (openfirmware(&args) == -1)
321 return (-1);
322 return (args.next);
323}
324
325/* Return the first child of this node or 0. */
326static phandle_t
327ofw_real_child(ofw_t ofw, phandle_t node)
328{
329 struct {
330 cell_t name;
331 cell_t nargs;
332 cell_t nreturns;
333 cell_t node;
334 cell_t child;
335 } args = {
336 (cell_t)"child",
337 1,
338 1,
339 };
340
341 args.node = node;
342 if (openfirmware(&args) == -1)
343 return (-1);
344 return (args.child);
345}
346
347/* Return the parent of this node or 0. */
348static phandle_t
349ofw_real_parent(ofw_t ofw, phandle_t node)
350{
351 struct {
352 cell_t name;
353 cell_t nargs;
354 cell_t nreturns;
355 cell_t node;
356 cell_t parent;
357 } args = {
358 (cell_t)"parent",
359 1,
360 1,
361 };
362
363 args.node = node;
364 if (openfirmware(&args) == -1)
365 return (-1);
366 return (args.parent);
367}
368
369/* Return the package handle that corresponds to an instance handle. */
370static phandle_t
371ofw_real_instance_to_package(ofw_t ofw, ihandle_t instance)
372{
373 struct {
374 cell_t name;
375 cell_t nargs;
376 cell_t nreturns;
377 cell_t instance;
378 cell_t package;
379 } args = {
380 (cell_t)"instance-to-package",
381 1,
382 1,
383 };
384
385 args.instance = instance;
386 if (openfirmware(&args) == -1)
387 return (-1);
388 return (args.package);
389}
390
391/* Get the length of a property of a package. */
392static ssize_t
393ofw_real_getproplen(ofw_t ofw, phandle_t package, const char *propname)
394{
395 struct {
396 cell_t name;
397 cell_t nargs;
398 cell_t nreturns;
399 cell_t package;
400 cell_t propname;
401 cell_t proplen;
402 } args = {
403 (cell_t)"getproplen",
404 2,
405 1,
406 };
407
408 ofw_real_start();
409
410 args.package = package;
411 args.propname = ofw_real_map(propname, strlen(propname) + 1);
412 if (args.propname == 0 || openfirmware(&args) == -1) {
413 ofw_real_stop();
414 return (-1);
415 }
416 ofw_real_stop();
417 return (args.proplen);
418}
419
420/* Get the value of a property of a package. */
421static ssize_t
422ofw_real_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf,
423 size_t buflen)
424{
425 struct {
426 cell_t name;
427 cell_t nargs;
428 cell_t nreturns;
429 cell_t package;
430 cell_t propname;
431 cell_t buf;
432 cell_t buflen;
433 cell_t size;
434 } args = {
435 (cell_t)"getprop",
436 4,
437 1,
438 };
439
440 ofw_real_start();
441
442 args.package = package;
443 args.propname = ofw_real_map(propname, strlen(propname) + 1);
444 args.buf = ofw_real_map(buf, buflen);
445 args.buflen = buflen;
446 if (args.propname == 0 || args.buf == 0 || openfirmware(&args) == -1) {
447 ofw_real_stop();
448 return (-1);
449 }
450 ofw_real_unmap(args.buf, buf, buflen);
451
452 ofw_real_stop();
453 return (args.size);
454}
455
456/* Get the next property of a package. */
457static int
458ofw_real_nextprop(ofw_t ofw, phandle_t package, const char *previous,
459 char *buf, size_t size)
460{
461 struct {
462 cell_t name;
463 cell_t nargs;
464 cell_t nreturns;
465 cell_t package;
466 cell_t previous;
467 cell_t buf;
468 cell_t flag;
469 } args = {
470 (cell_t)"nextprop",
471 3,
472 1,
473 };
474
475 ofw_real_start();
476
477 args.package = package;
478 args.previous = ofw_real_map(previous, strlen(previous) + 1);
479 args.buf = ofw_real_map(buf, size);
480 if (args.previous == 0 || args.buf == 0 || openfirmware(&args) == -1) {
481 ofw_real_stop();
482 return (-1);
483 }
484 ofw_real_unmap(args.buf, buf, size);
485
486 ofw_real_stop();
487 return (args.flag);
488}
489
490/* Set the value of a property of a package. */
491/* XXX Has a bug on FirePower */
492static int
493ofw_real_setprop(ofw_t ofw, phandle_t package, const char *propname,
494 const void *buf, size_t len)
495{
496 struct {
497 cell_t name;
498 cell_t nargs;
499 cell_t nreturns;
500 cell_t package;
501 cell_t propname;
502 cell_t buf;
503 cell_t len;
504 cell_t size;
505 } args = {
506 (cell_t)"setprop",
507 4,
508 1,
509 };
510
511 ofw_real_start();
512
513 args.package = package;
514 args.propname = ofw_real_map(propname, strlen(propname) + 1);
515 args.buf = ofw_real_map(buf, len);
516 args.len = len;
517 if (args.propname == 0 || args.buf == 0 || openfirmware(&args) == -1) {
518 ofw_real_stop();
519 return (-1);
520 }
521 ofw_real_stop();
522 return (args.size);
523}
524
525/* Convert a device specifier to a fully qualified pathname. */
526static ssize_t
527ofw_real_canon(ofw_t ofw, const char *device, char *buf, size_t len)
528{
529 struct {
530 cell_t name;
531 cell_t nargs;
532 cell_t nreturns;
533 cell_t device;
534 cell_t buf;
535 cell_t len;
536 cell_t size;
537 } args = {
538 (cell_t)"canon",
539 3,
540 1,
541 };
542
543 ofw_real_start();
544
545 args.device = ofw_real_map(device, strlen(device) + 1);
546 args.buf = ofw_real_map(buf, len);
547 args.len = len;
548 if (args.device == 0 || args.buf == 0 || openfirmware(&args) == -1) {
549 ofw_real_stop();
550 return (-1);
551 }
552 ofw_real_unmap(args.buf, buf, len);
553
554 ofw_real_stop();
555 return (args.size);
556}
557
558/* Return a package handle for the specified device. */
559static phandle_t
560ofw_real_finddevice(ofw_t ofw, const char *device)
561{
562 struct {
563 cell_t name;
564 cell_t nargs;
565 cell_t nreturns;
566 cell_t device;
567 cell_t package;
568 } args = {
569 (cell_t)"finddevice",
570 1,
571 1,
572 };
573
574 ofw_real_start();
575
576 args.device = ofw_real_map(device, strlen(device) + 1);
577 if (args.device == 0 || openfirmware(&args) == -1) {
578 ofw_real_stop();
579 return (-1);
580 }
581 ofw_real_stop();
582 return (args.package);
583}
584
585/* Return the fully qualified pathname corresponding to an instance. */
586static ssize_t
587ofw_real_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len)
588{
589 struct {
590 cell_t name;
591 cell_t nargs;
592 cell_t nreturns;
593 cell_t instance;
594 cell_t buf;
595 cell_t len;
596 cell_t size;
597 } args = {
598 (cell_t)"instance-to-path",
599 3,
600 1,
601 };
602
603 ofw_real_start();
604
605 args.instance = instance;
606 args.buf = ofw_real_map(buf, len);
607 args.len = len;
608 if (args.buf == 0 || openfirmware(&args) == -1) {
609 ofw_real_stop();
610 return (-1);
611 }
612 ofw_real_unmap(args.buf, buf, len);
613
614 ofw_real_stop();
615 return (args.size);
616}
617
618/* Return the fully qualified pathname corresponding to a package. */
619static ssize_t
620ofw_real_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len)
621{
622 struct {
623 cell_t name;
624 cell_t nargs;
625 cell_t nreturns;
626 cell_t package;
627 cell_t buf;
628 cell_t len;
629 cell_t size;
630 } args = {
631 (cell_t)"package-to-path",
632 3,
633 1,
634 };
635
636 ofw_real_start();
637
638 args.package = package;
639 args.buf = ofw_real_map(buf, len);
640 args.len = len;
641 if (args.buf == 0 || openfirmware(&args) == -1) {
642 ofw_real_stop();
643 return (-1);
644 }
645 ofw_real_unmap(args.buf, buf, len);
646
647 ofw_real_stop();
648 return (args.size);
649}
650
651/* Call the method in the scope of a given instance. */
652static int
653ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method,
654 int nargs, int nreturns, unsigned long *args_and_returns)
655{
656 struct {
657 cell_t name;
658 cell_t nargs;
659 cell_t nreturns;
660 cell_t method;
661 cell_t instance;
662 cell_t args_n_results[12];
663 } args = {
664 (cell_t)"call-method",
665 2,
666 1,
667 };
668 cell_t *cp;
669 unsigned long *ap;
670 int n;
671
672 if (nargs > 6)
673 return (-1);
674
675 ofw_real_start();
676 args.nargs = nargs + 2;
677 args.nreturns = nreturns + 1;
678 args.method = ofw_real_map(method, strlen(method) + 1);
679 args.instance = instance;
680
681 ap = args_and_returns;
682 for (cp = args.args_n_results + (n = nargs); --n >= 0;)
683 *--cp = *(ap++);
684 if (args.method == 0 || openfirmware(&args) == -1) {
685 ofw_real_stop();
686 return (-1);
687 }
688 ofw_real_stop();
689 if (args.args_n_results[nargs])
690 return (args.args_n_results[nargs]);
691 for (cp = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
692 *(ap++) = *--cp;
693 return (0);
694}
695
696/*
697 * Device I/O functions
698 */
699
700/* Open an instance for a device. */
701static ihandle_t
702ofw_real_open(ofw_t ofw, const char *device)
703{
704 struct {
705 cell_t name;
706 cell_t nargs;
707 cell_t nreturns;
708 cell_t device;
709 cell_t instance;
710 } args = {
711 (cell_t)"open",
712 1,
713 1,
714 };
715
716 ofw_real_start();
717
718 args.device = ofw_real_map(device, strlen(device) + 1);
719 if (args.device == 0 || openfirmware(&args) == -1
720 || args.instance == 0) {
721 ofw_real_stop();
722 return (-1);
723 }
724 ofw_real_stop();
725 return (args.instance);
726}
727
728/* Close an instance. */
729static void
730ofw_real_close(ofw_t ofw, ihandle_t instance)
731{
732 struct {
733 cell_t name;
734 cell_t nargs;
735 cell_t nreturns;
736 cell_t instance;
737 } args = {
738 (cell_t)"close",
739 1,
740 0,
741 };
742
743 args.instance = instance;
744 openfirmware(&args);
745}
746
747/* Read from an instance. */
748static ssize_t
749ofw_real_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len)
750{
751 struct {
752 cell_t name;
753 cell_t nargs;
754 cell_t nreturns;
755 cell_t instance;
756 cell_t addr;
757 cell_t len;
758 cell_t actual;
759 } args = {
760 (cell_t)"read",
761 3,
762 1,
763 };
764
765 ofw_real_start();
766
767 args.instance = instance;
768 args.addr = ofw_real_map(addr, len);
769 args.len = len;
770 if (args.addr == 0 || openfirmware(&args) == -1) {
771 ofw_real_stop();
772 return (-1);
773 }
774 ofw_real_unmap(args.addr, addr, len);
775
776 ofw_real_stop();
777 return (args.actual);
778}
779
780/* Write to an instance. */
781static ssize_t
782ofw_real_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len)
783{
784 struct {
785 cell_t name;
786 cell_t nargs;
787 cell_t nreturns;
788 cell_t instance;
789 cell_t addr;
790 cell_t len;
791 cell_t actual;
792 } args = {
793 (cell_t)"write",
794 3,
795 1,
796 };
797
798 ofw_real_start();
799
800 args.instance = instance;
801 args.addr = ofw_real_map(addr, len);
802 args.len = len;
803 if (args.addr == 0 || openfirmware(&args) == -1) {
804 ofw_real_stop();
805 return (-1);
806 }
807 ofw_real_stop();
808 return (args.actual);
809}
810
811/* Seek to a position. */
812static int
813ofw_real_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos)
814{
815 struct {
816 cell_t name;
817 cell_t nargs;
818 cell_t nreturns;
819 cell_t instance;
820 cell_t poshi;
821 cell_t poslo;
822 cell_t status;
823 } args = {
824 (cell_t)"seek",
825 3,
826 1,
827 };
828
829 args.instance = instance;
830 args.poshi = pos >> 32;
831 args.poslo = pos;
832 if (openfirmware(&args) == -1)
833 return (-1);
834 return (args.status);
835}
836
837/*
838 * Memory functions
839 */
840
841/* Claim an area of memory. */
842static caddr_t
843ofw_real_claim(ofw_t ofw, void *virt, size_t size, u_int align)
844{
845 struct {
846 cell_t name;
847 cell_t nargs;
848 cell_t nreturns;
849 cell_t virt;
850 cell_t size;
851 cell_t align;
852 cell_t baseaddr;
853 } args = {
854 (cell_t)"claim",
855 3,
856 1,
857 };
858
859 args.virt = (cell_t)virt;
860 args.size = size;
861 args.align = align;
862 if (openfirmware(&args) == -1)
863 return ((void *)-1);
864 return ((void *)args.baseaddr);
865}
866
867/* Release an area of memory. */
868static void
869ofw_real_release(ofw_t ofw, void *virt, size_t size)
870{
871 struct {
872 cell_t name;
873 cell_t nargs;
874 cell_t nreturns;
875 cell_t virt;
876 cell_t size;
877 } args = {
878 (cell_t)"release",
879 2,
880 0,
881 };
882
883 args.virt = (cell_t)virt;
884 args.size = size;
885 openfirmware(&args);
886}
887
888/*
889 * Control transfer functions
890 */
891
892/* Suspend and drop back to the Open Firmware interface. */
893static void
894ofw_real_enter(ofw_t ofw)
895{
896 struct {
897 cell_t name;
898 cell_t nargs;
899 cell_t nreturns;
900 } args = {
901 (cell_t)"enter",
902 0,
903 0,
904 };
905
906 openfirmware(&args);
907 /* We may come back. */
908}
909
910/* Shut down and drop back to the Open Firmware interface. */
911static void
912ofw_real_exit(ofw_t ofw)
913{
914 struct {
915 cell_t name;
916 cell_t nargs;
917 cell_t nreturns;
918 } args = {
919 (cell_t)"exit",
920 0,
921 0,
922 };
923
924 openfirmware(&args);
925 for (;;) /* just in case */
926 ;
927}
928