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 <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
79 static void ofw_real_init(ofw_t, void *openfirm);
80 static int ofw_real_test(ofw_t, const char *name);
81 static phandle_t ofw_real_peer(ofw_t, phandle_t node);
82 static phandle_t ofw_real_child(ofw_t, phandle_t node);
83 static phandle_t ofw_real_parent(ofw_t, phandle_t node);
84 static phandle_t ofw_real_instance_to_package(ofw_t, ihandle_t instance);
85 static ssize_t ofw_real_getproplen(ofw_t, phandle_t package,
86 const char *propname);
87 static ssize_t ofw_real_getprop(ofw_t, phandle_t package, const char *propname,
88 void *buf, size_t buflen);
89 static int ofw_real_nextprop(ofw_t, phandle_t package, const char *previous,
90 char *buf, size_t);
91 static int ofw_real_setprop(ofw_t, phandle_t package, const char *propname,
92 const void *buf, size_t len);
93 static ssize_t ofw_real_canon(ofw_t, const char *device, char *buf, size_t len);
94 static phandle_t ofw_real_finddevice(ofw_t, const char *device);
95 static ssize_t ofw_real_instance_to_path(ofw_t, ihandle_t instance, char *buf,
96 size_t len);
97 static ssize_t ofw_real_package_to_path(ofw_t, phandle_t package, char *buf,
98 size_t len);
99 static int ofw_real_call_method(ofw_t, ihandle_t instance, const char *method,
100 int nargs, int nreturns, unsigned long *args_and_returns);
101 static ihandle_t ofw_real_open(ofw_t, const char *device);
102 static void ofw_real_close(ofw_t, ihandle_t instance);
103 static ssize_t ofw_real_read(ofw_t, ihandle_t instance, void *addr, size_t len);
104 static ssize_t ofw_real_write(ofw_t, ihandle_t instance, const void *addr,
105 size_t len);
106 static int ofw_real_seek(ofw_t, ihandle_t instance, u_int64_t pos);
107 static caddr_t ofw_real_claim(ofw_t, void *virt, size_t size, u_int align);
108 static void ofw_real_release(ofw_t, void *virt, size_t size);
109 static void ofw_real_enter(ofw_t);
110 static void ofw_real_exit(ofw_t);
111
112 static 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
142 static ofw_def_t ofw_real = {
143 OFW_STD_REAL,
144 ofw_real_methods,
145 0
146 };
147 OFW_DEF(ofw_real);
148
149 MALLOC_DEFINE(M_OFWREAL, "ofwreal", "Open Firmware Real Mode Bounce Page");
150
151 static int (*openfirmware)(void *);
152
153 static vm_offset_t of_bounce_phys;
154 static caddr_t of_bounce_virt;
155 static off_t of_bounce_offset;
156 static size_t of_bounce_size;
157 static struct mtx of_bounce_mtx;
158
159 /*
160 * After the VM is up, allocate a wired, low memory bounce page.
161 */
162
163 static void ofw_real_bounce_alloc(void *);
164
165 SYSINIT(ofw_real_bounce_alloc, SI_SUB_VM, SI_ORDER_ANY,
166 ofw_real_bounce_alloc, NULL);
167
168 static void
169 ofw_real_start(void)
170 {
171 mtx_lock(&of_bounce_mtx);
172 of_bounce_offset = 0;
173 }
174
175 static void
176 ofw_real_stop(void)
177 {
178 mtx_unlock(&of_bounce_mtx);
179 }
180
181 static void
182 ofw_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
206 static cell_t
207 ofw_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
246 static void
247 ofw_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
259 static void
260 ofw_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. */
273 static int
274 ofw_real_test(ofw_t ofw, const char *name)
275 {
276 static 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. */
304 static phandle_t
305 ofw_real_peer(ofw_t ofw, phandle_t node)
306 {
307 static 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. */
326 static phandle_t
327 ofw_real_child(ofw_t ofw, phandle_t node)
328 {
329 static 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. */
348 static phandle_t
349 ofw_real_parent(ofw_t ofw, phandle_t node)
350 {
351 static 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. */
370 static phandle_t
371 ofw_real_instance_to_package(ofw_t ofw, ihandle_t instance)
372 {
373 static 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. */
392 static ssize_t
393 ofw_real_getproplen(ofw_t ofw, phandle_t package, const char *propname)
394 {
395 static 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. */
421 static ssize_t
422 ofw_real_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf,
423 size_t buflen)
424 {
425 static 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. */
457 static int
458 ofw_real_nextprop(ofw_t ofw, phandle_t package, const char *previous,
459 char *buf, size_t size)
460 {
461 static 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 */
492 static int
493 ofw_real_setprop(ofw_t ofw, phandle_t package, const char *propname,
494 const void *buf, size_t len)
495 {
496 static 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. */
526 static ssize_t
527 ofw_real_canon(ofw_t ofw, const char *device, char *buf, size_t len)
528 {
529 static 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. */
559 static phandle_t
560 ofw_real_finddevice(ofw_t ofw, const char *device)
561 {
562 static 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. */
586 static ssize_t
587 ofw_real_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len)
588 {
589 static 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. */
619 static ssize_t
620 ofw_real_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len)
621 {
622 static 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. */
652 static int
653 ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method,
654 int nargs, int nreturns, unsigned long *args_and_returns)
655 {
656 static 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. */
701 static ihandle_t
702 ofw_real_open(ofw_t ofw, const char *device)
703 {
704 static 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. */
729 static void
730 ofw_real_close(ofw_t ofw, ihandle_t instance)
731 {
732 static 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 };
741
742 args.instance = instance;
743 openfirmware(&args);
744 }
745
746 /* Read from an instance. */
747 static ssize_t
748 ofw_real_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len)
749 {
750 static struct {
751 cell_t name;
752 cell_t nargs;
753 cell_t nreturns;
754 cell_t instance;
755 cell_t addr;
756 cell_t len;
757 cell_t actual;
758 } args = {
759 (cell_t)"read",
760 3,
761 1,
762 };
763
764 ofw_real_start();
765
766 args.instance = instance;
767 args.addr = ofw_real_map(addr, len);
768 args.len = len;
769 if (args.addr == 0 || openfirmware(&args) == -1) {
770 ofw_real_stop();
771 return (-1);
772 }
773 ofw_real_unmap(args.addr, addr, len);
774
775 ofw_real_stop();
776 return (args.actual);
777 }
778
779 /* Write to an instance. */
780 static ssize_t
781 ofw_real_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len)
782 {
783 static struct {
784 cell_t name;
785 cell_t nargs;
786 cell_t nreturns;
787 cell_t instance;
788 cell_t addr;
789 cell_t len;
790 cell_t actual;
791 } args = {
792 (cell_t)"write",
793 3,
794 1,
795 };
796
797 ofw_real_start();
798
799 args.instance = instance;
800 args.addr = ofw_real_map(addr, len);
801 args.len = len;
802 if (args.addr == 0 || openfirmware(&args) == -1) {
803 ofw_real_stop();
804 return (-1);
805 }
806 ofw_real_stop();
807 return (args.actual);
808 }
809
810 /* Seek to a position. */
811 static int
812 ofw_real_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos)
813 {
814 static struct {
815 cell_t name;
816 cell_t nargs;
817 cell_t nreturns;
818 cell_t instance;
819 cell_t poshi;
820 cell_t poslo;
821 cell_t status;
822 } args = {
823 (cell_t)"seek",
824 3,
825 1,
826 };
827
828 args.instance = instance;
829 args.poshi = pos >> 32;
830 args.poslo = pos;
831 if (openfirmware(&args) == -1)
832 return (-1);
833 return (args.status);
834 }
835
836 /*
837 * Memory functions
838 */
839
840 /* Claim an area of memory. */
841 static caddr_t
842 ofw_real_claim(ofw_t ofw, void *virt, size_t size, u_int align)
843 {
844 static struct {
845 cell_t name;
846 cell_t nargs;
847 cell_t nreturns;
848 cell_t virt;
849 cell_t size;
850 cell_t align;
851 cell_t baseaddr;
852 } args = {
853 (cell_t)"claim",
854 3,
855 1,
856 };
857
858 args.virt = (cell_t)virt;
859 args.size = size;
860 args.align = align;
861 if (openfirmware(&args) == -1)
862 return ((void *)-1);
863 return ((void *)args.baseaddr);
864 }
865
866 /* Release an area of memory. */
867 static void
868 ofw_real_release(ofw_t ofw, void *virt, size_t size)
869 {
870 static struct {
871 cell_t name;
872 cell_t nargs;
873 cell_t nreturns;
874 cell_t virt;
875 cell_t size;
876 } args = {
877 (cell_t)"release",
878 2,
879 };
880
881 args.virt = (cell_t)virt;
882 args.size = size;
883 openfirmware(&args);
884 }
885
886 /*
887 * Control transfer functions
888 */
889
890 /* Suspend and drop back to the Open Firmware interface. */
891 static void
892 ofw_real_enter(ofw_t ofw)
893 {
894 static struct {
895 cell_t name;
896 cell_t nargs;
897 cell_t nreturns;
898 } args = {
899 (cell_t)"enter",
900 };
901
902 openfirmware(&args);
903 /* We may come back. */
904 }
905
906 /* Shut down and drop back to the Open Firmware interface. */
907 static void
908 ofw_real_exit(ofw_t ofw)
909 {
910 static struct {
911 cell_t name;
912 cell_t nargs;
913 cell_t nreturns;
914 } args = {
915 (cell_t)"exit",
916 };
917
918 openfirmware(&args);
919 for (;;) /* just in case */
920 ;
921 }
922
Cache object: fb301e1271142285fd30314695169cda
|