]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/powerpc/ofw/ofw_real.c
Move the powerpc64 direct map base address from zero to high memory. This
[FreeBSD/FreeBSD.git] / sys / powerpc / ofw / ofw_real.c
1 /*      $NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $        */
2
3 /*-
4  * SPDX-License-Identifier:BSD-4-Clause AND BSD-2-Clause-FreeBSD
5  *
6  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
7  * Copyright (C) 1995, 1996 TooLs GmbH.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *      This product includes software developed by TooLs GmbH.
21  * 4. The name of TooLs GmbH may not be used to endorse or promote products
22  *    derived from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
30  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
33  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 /*-
36  * Copyright (C) 2000 Benno Rice.
37  * All rights reserved.
38  *
39  * Redistribution and use in source and binary forms, with or without
40  * modification, are permitted provided that the following conditions
41  * are met:
42  * 1. Redistributions of source code must retain the above copyright
43  *    notice, this list of conditions and the following disclaimer.
44  * 2. Redistributions in binary form must reproduce the above copyright
45  *    notice, this list of conditions and the following disclaimer in the
46  *    documentation and/or other materials provided with the distribution.
47  *
48  * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
49  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
50  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
51  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
52  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
53  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
54  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
55  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
56  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
57  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
58  */
59
60 #include <sys/cdefs.h>
61 __FBSDID("$FreeBSD$");
62
63 #include <sys/param.h>
64 #include <sys/kernel.h>
65 #include <sys/lock.h>
66 #include <sys/mutex.h>
67 #include <sys/systm.h>
68
69 #include <vm/vm.h>
70 #include <vm/vm_page.h>
71 #include <vm/pmap.h>
72
73 #include <machine/bus.h>
74 #include <machine/md_var.h>
75 #include <machine/ofw_machdep.h>
76 #include <machine/stdarg.h>
77
78 #include <dev/ofw/openfirm.h>
79 #include <dev/ofw/ofwvar.h>
80 #include "ofw_if.h"
81
82 static int ofw_real_init(ofw_t, void *openfirm);
83 static int ofw_real_test(ofw_t, const char *name);
84 static phandle_t ofw_real_peer(ofw_t, phandle_t node);
85 static phandle_t ofw_real_child(ofw_t, phandle_t node);
86 static phandle_t ofw_real_parent(ofw_t, phandle_t node);
87 static phandle_t ofw_real_instance_to_package(ofw_t, ihandle_t instance);
88 static ssize_t ofw_real_getproplen(ofw_t, phandle_t package, 
89     const char *propname);
90 static ssize_t ofw_real_getprop(ofw_t, phandle_t package, const char *propname, 
91     void *buf, size_t buflen);
92 static int ofw_real_nextprop(ofw_t, phandle_t package, const char *previous, 
93     char *buf, size_t);
94 static int ofw_real_setprop(ofw_t, phandle_t package, const char *propname,
95     const void *buf, size_t len);
96 static ssize_t ofw_real_canon(ofw_t, const char *device, char *buf, size_t len);
97 static phandle_t ofw_real_finddevice(ofw_t, const char *device);
98 static ssize_t ofw_real_instance_to_path(ofw_t, ihandle_t instance, char *buf, 
99     size_t len);
100 static ssize_t ofw_real_package_to_path(ofw_t, phandle_t package, char *buf, 
101     size_t len);
102 static int ofw_real_call_method(ofw_t, ihandle_t instance, const char *method, 
103     int nargs, int nreturns, cell_t *args_and_returns);
104 static int ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns,
105     cell_t *returns);
106 static ihandle_t ofw_real_open(ofw_t, const char *device);
107 static void ofw_real_close(ofw_t, ihandle_t instance);
108 static ssize_t ofw_real_read(ofw_t, ihandle_t instance, void *addr, size_t len);
109 static ssize_t ofw_real_write(ofw_t, ihandle_t instance, const void *addr, 
110     size_t len);
111 static int ofw_real_seek(ofw_t, ihandle_t instance, u_int64_t pos);
112 static caddr_t ofw_real_claim(ofw_t, void *virt, size_t size, u_int align);
113 static void ofw_real_release(ofw_t, void *virt, size_t size);
114 static void ofw_real_enter(ofw_t);
115 static void ofw_real_exit(ofw_t);
116
117 static ofw_method_t ofw_real_methods[] = {
118         OFWMETHOD(ofw_init,                     ofw_real_init),
119         OFWMETHOD(ofw_peer,                     ofw_real_peer),
120         OFWMETHOD(ofw_child,                    ofw_real_child),
121         OFWMETHOD(ofw_parent,                   ofw_real_parent),
122         OFWMETHOD(ofw_instance_to_package,      ofw_real_instance_to_package),
123         OFWMETHOD(ofw_getproplen,               ofw_real_getproplen),
124         OFWMETHOD(ofw_getprop,                  ofw_real_getprop),
125         OFWMETHOD(ofw_nextprop,                 ofw_real_nextprop),
126         OFWMETHOD(ofw_setprop,                  ofw_real_setprop),
127         OFWMETHOD(ofw_canon,                    ofw_real_canon),
128         OFWMETHOD(ofw_finddevice,               ofw_real_finddevice),
129         OFWMETHOD(ofw_instance_to_path,         ofw_real_instance_to_path),
130         OFWMETHOD(ofw_package_to_path,          ofw_real_package_to_path),
131
132         OFWMETHOD(ofw_test,                     ofw_real_test),
133         OFWMETHOD(ofw_call_method,              ofw_real_call_method),
134         OFWMETHOD(ofw_interpret,                ofw_real_interpret),
135         OFWMETHOD(ofw_open,                     ofw_real_open),
136         OFWMETHOD(ofw_close,                    ofw_real_close),
137         OFWMETHOD(ofw_read,                     ofw_real_read),
138         OFWMETHOD(ofw_write,                    ofw_real_write),
139         OFWMETHOD(ofw_seek,                     ofw_real_seek),
140         OFWMETHOD(ofw_claim,                    ofw_real_claim),
141         OFWMETHOD(ofw_release,                  ofw_real_release),
142         OFWMETHOD(ofw_enter,                    ofw_real_enter),
143         OFWMETHOD(ofw_exit,                     ofw_real_exit),
144
145         { 0, 0 }
146 };
147
148 static ofw_def_t ofw_real = {
149         OFW_STD_REAL,
150         ofw_real_methods,
151         0
152 };
153 OFW_DEF(ofw_real);
154
155 static ofw_def_t ofw_32bit = {
156         OFW_STD_32BIT,
157         ofw_real_methods,
158         0
159 };
160 OFW_DEF(ofw_32bit);
161
162 static MALLOC_DEFINE(M_OFWREAL, "ofwreal",
163     "Open Firmware Real Mode Bounce Page");
164
165 static int (*openfirmware)(void *);
166
167 static vm_offset_t      of_bounce_phys;
168 static caddr_t          of_bounce_virt;
169 static off_t            of_bounce_offset;
170 static size_t           of_bounce_size;
171 static struct mtx       of_bounce_mtx;
172
173 extern int              ofw_real_mode;
174
175 /*
176  * After the VM is up, allocate a wired, low memory bounce page.
177  */
178
179 static void ofw_real_bounce_alloc(void *);
180
181 SYSINIT(ofw_real_bounce_alloc, SI_SUB_KMEM, SI_ORDER_ANY, 
182     ofw_real_bounce_alloc, NULL);
183
184 static void
185 ofw_real_start(void)
186 {
187         mtx_lock(&of_bounce_mtx);
188         of_bounce_offset = 0;
189 }
190         
191 static void
192 ofw_real_stop(void)
193 {
194         mtx_unlock(&of_bounce_mtx);
195 }
196
197 static void
198 ofw_real_bounce_alloc(void *junk)
199 {
200         /*
201          * Check that ofw_real is actually in use before allocating wads 
202          * of memory. Do this by checking if our mutex has been set up.
203          */
204         if (!mtx_initialized(&of_bounce_mtx))
205                 return;
206
207         /*
208          * Allocate a page of contiguous, wired physical memory that can
209          * fit into a 32-bit address space and accessed from real mode.
210          */
211
212         mtx_lock(&of_bounce_mtx);
213
214         of_bounce_virt = contigmalloc(4 * PAGE_SIZE, M_OFWREAL, 0, 0,
215             ulmin(platform_real_maxaddr(), BUS_SPACE_MAXADDR_32BIT), PAGE_SIZE,
216             4 * PAGE_SIZE);
217
218         of_bounce_phys = vtophys(of_bounce_virt);
219         of_bounce_size = 4 * PAGE_SIZE;
220
221         /*
222          * For virtual-mode OF, direct map this physical address so that
223          * we have a 32-bit virtual address to give OF.
224          */
225
226         if (!ofw_real_mode && (!hw_direct_map || DMAP_BASE_ADDRESS != 0)) 
227                 pmap_kenter(of_bounce_phys, of_bounce_phys);
228
229         mtx_unlock(&of_bounce_mtx);
230 }
231
232 static cell_t
233 ofw_real_map(const void *buf, size_t len)
234 {
235         static char emergency_buffer[255];
236         cell_t phys;
237
238         mtx_assert(&of_bounce_mtx, MA_OWNED);
239
240         if (of_bounce_virt == NULL) {
241                 /*
242                  * If we haven't set up the MMU, then buf is guaranteed
243                  * to be accessible to OF, because the only memory we
244                  * can use right now is memory mapped by firmware.
245                  */
246                 if (!pmap_bootstrapped)
247                         return (cell_t)((uintptr_t)buf & ~DMAP_BASE_ADDRESS);
248
249                 /*
250                  * XXX: It is possible for us to get called before the VM has
251                  * come online, but after the MMU is up. We don't have the
252                  * bounce buffer yet, but can no longer presume a 1:1 mapping.
253                  * Copy into the emergency buffer, and reset at the end.
254                  */
255                 of_bounce_virt = emergency_buffer;
256                 of_bounce_phys = (vm_offset_t)of_bounce_virt &
257                     ~DMAP_BASE_ADDRESS;
258                 of_bounce_size = sizeof(emergency_buffer);
259         }
260
261         /*
262          * Make sure the bounce page offset satisfies any reasonable
263          * alignment constraint.
264          */
265         of_bounce_offset += sizeof(register_t) -
266             (of_bounce_offset % sizeof(register_t));
267
268         if (of_bounce_offset + len > of_bounce_size) {
269                 panic("Oversize Open Firmware call!");
270                 return 0;
271         }
272
273         if (buf != NULL)
274                 memcpy(of_bounce_virt + of_bounce_offset, buf, len);
275         else
276                 return (0);
277
278         phys = of_bounce_phys + of_bounce_offset;
279
280         of_bounce_offset += len;
281
282         return (phys);
283 }
284
285 static void
286 ofw_real_unmap(cell_t physaddr, void *buf, size_t len)
287 {
288         mtx_assert(&of_bounce_mtx, MA_OWNED);
289
290         if (of_bounce_virt == NULL)
291                 return;
292
293         if (physaddr == 0)
294                 return;
295
296         memcpy(buf,of_bounce_virt + (physaddr - of_bounce_phys),len);
297 }
298
299 /* Initialiser */
300
301 static int
302 ofw_real_init(ofw_t ofw, void *openfirm)
303 {
304         openfirmware = (int (*)(void *))openfirm;
305
306         mtx_init(&of_bounce_mtx, "OF Bounce Page", NULL, MTX_DEF);
307         of_bounce_virt = NULL;
308         return (0);
309 }
310
311 /*
312  * Generic functions
313  */
314
315 /* Test to see if a service exists. */
316 static int
317 ofw_real_test(ofw_t ofw, const char *name)
318 {
319         vm_offset_t argsptr;
320         struct {
321                 cell_t name;
322                 cell_t nargs;
323                 cell_t nreturns;
324                 cell_t service;
325                 cell_t missing;
326         } args;
327
328         args.name = (cell_t)(uintptr_t)"test";
329         args.nargs = 1;
330         args.nreturns = 1;
331
332         ofw_real_start();
333
334         args.service = ofw_real_map(name, strlen(name) + 1);
335         argsptr = ofw_real_map(&args, sizeof(args));
336         if (args.service == 0 || openfirmware((void *)argsptr) == -1) {
337                 ofw_real_stop();
338                 return (-1);
339         }
340         ofw_real_unmap(argsptr, &args, sizeof(args));
341         ofw_real_stop();
342         return (args.missing);
343 }
344
345 /*
346  * Device tree functions
347  */
348
349 /* Return the next sibling of this node or 0. */
350 static phandle_t
351 ofw_real_peer(ofw_t ofw, phandle_t node)
352 {
353         vm_offset_t argsptr;
354         struct {
355                 cell_t name;
356                 cell_t nargs;
357                 cell_t nreturns;
358                 cell_t node;
359                 cell_t next;
360         } args;
361
362         args.name = (cell_t)(uintptr_t)"peer";
363         args.nargs = 1;
364         args.nreturns = 1;
365
366         args.node = node;
367         ofw_real_start();
368         argsptr = ofw_real_map(&args, sizeof(args));
369         if (openfirmware((void *)argsptr) == -1) {
370                 ofw_real_stop();
371                 return (0);
372         }
373         ofw_real_unmap(argsptr, &args, sizeof(args));
374         ofw_real_stop();
375         return (args.next);
376 }
377
378 /* Return the first child of this node or 0. */
379 static phandle_t
380 ofw_real_child(ofw_t ofw, phandle_t node)
381 {
382         vm_offset_t argsptr;
383         struct {
384                 cell_t name;
385                 cell_t nargs;
386                 cell_t nreturns;
387                 cell_t node;
388                 cell_t child;
389         } args;
390
391         args.name = (cell_t)(uintptr_t)"child";
392         args.nargs = 1;
393         args.nreturns = 1;
394
395         args.node = node;
396         ofw_real_start();
397         argsptr = ofw_real_map(&args, sizeof(args));
398         if (openfirmware((void *)argsptr) == -1) {
399                 ofw_real_stop();
400                 return (0);
401         }
402         ofw_real_unmap(argsptr, &args, sizeof(args));
403         ofw_real_stop();
404         return (args.child);
405 }
406
407 /* Return the parent of this node or 0. */
408 static phandle_t
409 ofw_real_parent(ofw_t ofw, phandle_t node)
410 {
411         vm_offset_t argsptr;
412         struct {
413                 cell_t name;
414                 cell_t nargs;
415                 cell_t nreturns;
416                 cell_t node;
417                 cell_t parent;
418         } args;
419
420         args.name = (cell_t)(uintptr_t)"parent";
421         args.nargs = 1;
422         args.nreturns = 1;
423
424         args.node = node;
425         ofw_real_start();
426         argsptr = ofw_real_map(&args, sizeof(args));
427         if (openfirmware((void *)argsptr) == -1) {
428                 ofw_real_stop();
429                 return (0);
430         }
431         ofw_real_unmap(argsptr, &args, sizeof(args));
432         ofw_real_stop();
433         return (args.parent);
434 }
435
436 /* Return the package handle that corresponds to an instance handle. */
437 static phandle_t
438 ofw_real_instance_to_package(ofw_t ofw, ihandle_t instance)
439 {
440         vm_offset_t argsptr;
441         struct {
442                 cell_t name;
443                 cell_t nargs;
444                 cell_t nreturns;
445                 cell_t instance;
446                 cell_t package;
447         } args;
448
449         args.name = (cell_t)(uintptr_t)"instance-to-package";
450         args.nargs = 1;
451         args.nreturns = 1;
452
453         args.instance = instance;
454         ofw_real_start();
455         argsptr = ofw_real_map(&args, sizeof(args));
456         if (openfirmware((void *)argsptr) == -1) {
457                 ofw_real_stop();
458                 return (-1);
459         }
460         ofw_real_unmap(argsptr, &args, sizeof(args));
461         ofw_real_stop();
462         return (args.package);
463 }
464
465 /* Get the length of a property of a package. */
466 static ssize_t
467 ofw_real_getproplen(ofw_t ofw, phandle_t package, const char *propname)
468 {
469         vm_offset_t argsptr;
470         struct {
471                 cell_t name;
472                 cell_t nargs;
473                 cell_t nreturns;
474                 cell_t package;
475                 cell_t propname;
476                 int32_t proplen;
477         } args;
478
479         args.name = (cell_t)(uintptr_t)"getproplen";
480         args.nargs = 2;
481         args.nreturns = 1;
482
483         ofw_real_start();
484
485         args.package = package;
486         args.propname = ofw_real_map(propname, strlen(propname) + 1);
487         argsptr = ofw_real_map(&args, sizeof(args));
488         if (args.propname == 0 || openfirmware((void *)argsptr) == -1) {
489                 ofw_real_stop();
490                 return (-1);
491         }
492         ofw_real_unmap(argsptr, &args, sizeof(args));
493         ofw_real_stop();
494         return (args.proplen);
495 }
496
497 /* Get the value of a property of a package. */
498 static ssize_t
499 ofw_real_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf, 
500     size_t buflen)
501 {
502         vm_offset_t argsptr;
503         struct {
504                 cell_t name;
505                 cell_t nargs;
506                 cell_t nreturns;
507                 cell_t package;
508                 cell_t propname;
509                 cell_t buf;
510                 cell_t buflen;
511                 int32_t size;
512         } args;
513
514         args.name = (cell_t)(uintptr_t)"getprop";
515         args.nargs = 4;
516         args.nreturns = 1;
517
518         ofw_real_start();
519
520         args.package = package;
521         args.propname = ofw_real_map(propname, strlen(propname) + 1);
522         args.buf = ofw_real_map(buf, buflen);
523         args.buflen = buflen;
524         argsptr = ofw_real_map(&args, sizeof(args));
525         if (args.propname == 0 || args.buf == 0 ||
526             openfirmware((void *)argsptr) == -1) {
527                 ofw_real_stop();
528                 return (-1);
529         }
530         ofw_real_unmap(argsptr, &args, sizeof(args));
531         ofw_real_unmap(args.buf, buf, buflen);
532
533         ofw_real_stop();
534         return (args.size);
535 }
536
537 /* Get the next property of a package. */
538 static int
539 ofw_real_nextprop(ofw_t ofw, phandle_t package, const char *previous, 
540     char *buf, size_t size)
541 {
542         vm_offset_t argsptr;
543         struct {
544                 cell_t name;
545                 cell_t nargs;
546                 cell_t nreturns;
547                 cell_t package;
548                 cell_t previous;
549                 cell_t buf;
550                 cell_t flag;
551         } args;
552
553         args.name = (cell_t)(uintptr_t)"nextprop";
554         args.nargs = 3;
555         args.nreturns = 1;
556
557         ofw_real_start();
558
559         args.package = package;
560         args.previous = ofw_real_map(previous, (previous != NULL) ? (strlen(previous) + 1) : 0);
561         args.buf = ofw_real_map(buf, size);
562         argsptr = ofw_real_map(&args, sizeof(args));
563         if (args.buf == 0 || openfirmware((void *)argsptr) == -1) {
564                 ofw_real_stop();
565                 return (-1);
566         }
567         ofw_real_unmap(argsptr, &args, sizeof(args));
568         ofw_real_unmap(args.buf, buf, size);
569
570         ofw_real_stop();
571         return (args.flag);
572 }
573
574 /* Set the value of a property of a package. */
575 /* XXX Has a bug on FirePower */
576 static int
577 ofw_real_setprop(ofw_t ofw, phandle_t package, const char *propname,
578     const void *buf, size_t len)
579 {
580         vm_offset_t argsptr;
581         struct {
582                 cell_t name;
583                 cell_t nargs;
584                 cell_t nreturns;
585                 cell_t package;
586                 cell_t propname;
587                 cell_t buf;
588                 cell_t len;
589                 cell_t size;
590         } args;
591
592         args.name = (cell_t)(uintptr_t)"setprop";
593         args.nargs = 4;
594         args.nreturns = 1;
595
596         ofw_real_start();
597
598         args.package = package;
599         args.propname = ofw_real_map(propname, strlen(propname) + 1);
600         args.buf = ofw_real_map(buf, len);
601         args.len = len;
602         argsptr = ofw_real_map(&args, sizeof(args));
603         if (args.propname == 0 || args.buf == 0 ||
604             openfirmware((void *)argsptr) == -1) {
605                 ofw_real_stop();
606                 return (-1);
607         }
608         ofw_real_unmap(argsptr, &args, sizeof(args));
609         ofw_real_stop();
610         return (args.size);
611 }
612
613 /* Convert a device specifier to a fully qualified pathname. */
614 static ssize_t
615 ofw_real_canon(ofw_t ofw, const char *device, char *buf, size_t len)
616 {
617         vm_offset_t argsptr;
618         struct {
619                 cell_t name;
620                 cell_t nargs;
621                 cell_t nreturns;
622                 cell_t device;
623                 cell_t buf;
624                 cell_t len;
625                 int32_t size;
626         } args;
627
628         args.name = (cell_t)(uintptr_t)"canon";
629         args.nargs = 3;
630         args.nreturns = 1;
631
632         ofw_real_start();
633
634         args.device = ofw_real_map(device, strlen(device) + 1);
635         args.buf = ofw_real_map(buf, len);
636         args.len = len;
637         argsptr = ofw_real_map(&args, sizeof(args));
638         if (args.device == 0 || args.buf == 0 ||
639             openfirmware((void *)argsptr) == -1) {
640                 ofw_real_stop();
641                 return (-1);
642         }
643         ofw_real_unmap(argsptr, &args, sizeof(args));
644         ofw_real_unmap(args.buf, buf, len);
645
646         ofw_real_stop();
647         return (args.size);
648 }
649
650 /* Return a package handle for the specified device. */
651 static phandle_t
652 ofw_real_finddevice(ofw_t ofw, const char *device)
653 {
654         vm_offset_t argsptr;
655         struct {
656                 cell_t name;
657                 cell_t nargs;
658                 cell_t nreturns;
659                 cell_t device;
660                 cell_t package;
661         } args;
662
663         args.name = (cell_t)(uintptr_t)"finddevice";
664         args.nargs = 1;
665         args.nreturns = 1;
666
667         ofw_real_start();
668
669         args.device = ofw_real_map(device, strlen(device) + 1);
670         argsptr = ofw_real_map(&args, sizeof(args));
671         if (args.device == 0 ||
672             openfirmware((void *)argsptr) == -1) {
673                 ofw_real_stop();
674                 return (-1);
675         }
676         ofw_real_unmap(argsptr, &args, sizeof(args));
677         ofw_real_stop();
678         return (args.package);
679 }
680
681 /* Return the fully qualified pathname corresponding to an instance. */
682 static ssize_t
683 ofw_real_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len)
684 {
685         vm_offset_t argsptr;
686         struct {
687                 cell_t name;
688                 cell_t nargs;
689                 cell_t nreturns;
690                 cell_t instance;
691                 cell_t buf;
692                 cell_t len;
693                 int32_t size;
694         } args;
695
696         args.name = (cell_t)(uintptr_t)"instance-to-path";
697         args.nargs = 3;
698         args.nreturns = 1;
699
700         ofw_real_start();
701
702         args.instance = instance;
703         args.buf = ofw_real_map(buf, len);
704         args.len = len;
705         argsptr = ofw_real_map(&args, sizeof(args));
706         if (args.buf == 0 ||
707             openfirmware((void *)argsptr) == -1) {
708                 ofw_real_stop();
709                 return (-1);
710         }
711         ofw_real_unmap(argsptr, &args, sizeof(args));
712         ofw_real_unmap(args.buf, buf, len);
713
714         ofw_real_stop();
715         return (args.size);
716 }
717
718 /* Return the fully qualified pathname corresponding to a package. */
719 static ssize_t
720 ofw_real_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len)
721 {
722         vm_offset_t argsptr;
723         struct {
724                 cell_t name;
725                 cell_t nargs;
726                 cell_t nreturns;
727                 cell_t package;
728                 cell_t buf;
729                 cell_t len;
730                 int32_t size;
731         } args;
732
733         args.name = (cell_t)(uintptr_t)"package-to-path";
734         args.nargs = 3;
735         args.nreturns = 1;
736
737         ofw_real_start();
738
739         args.package = package;
740         args.buf = ofw_real_map(buf, len);
741         args.len = len;
742         argsptr = ofw_real_map(&args, sizeof(args));
743         if (args.buf == 0 ||
744             openfirmware((void *)argsptr) == -1) {
745                 ofw_real_stop();
746                 return (-1);
747         }
748         ofw_real_unmap(argsptr, &args, sizeof(args));
749         ofw_real_unmap(args.buf, buf, len);
750
751         ofw_real_stop();
752         return (args.size);
753 }
754
755 /*  Call the method in the scope of a given instance. */
756 static int
757 ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method, 
758     int nargs, int nreturns, cell_t *args_and_returns)
759 {
760         vm_offset_t argsptr;
761         struct {
762                 cell_t name;
763                 cell_t nargs;
764                 cell_t nreturns;
765                 cell_t method;
766                 cell_t instance;
767                 cell_t args_n_results[12];
768         } args;
769         cell_t *ap, *cp;
770         int n;
771
772         args.name = (cell_t)(uintptr_t)"call-method";
773         args.nargs = 2;
774         args.nreturns = 1;
775
776         if (nargs > 6)
777                 return (-1);
778
779         ofw_real_start();
780         args.nargs = nargs + 2;
781         args.nreturns = nreturns + 1;
782         args.method = ofw_real_map(method, strlen(method) + 1);
783         args.instance = instance;
784
785         ap = args_and_returns;
786         for (cp = args.args_n_results + (n = nargs); --n >= 0;)
787                 *--cp = *(ap++);
788         argsptr = ofw_real_map(&args, sizeof(args));
789         if (args.method == 0 ||
790             openfirmware((void *)argsptr) == -1) {
791                 ofw_real_stop();
792                 return (-1);
793         }
794         ofw_real_unmap(argsptr, &args, sizeof(args));
795         ofw_real_stop();
796         if (args.args_n_results[nargs])
797                 return (args.args_n_results[nargs]);
798         for (cp = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
799                 *(ap++) = *--cp;
800         return (0);
801 }
802
803 static int
804 ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns, cell_t *returns)
805 {
806         vm_offset_t argsptr;
807         struct {
808                 cell_t name;
809                 cell_t nargs;
810                 cell_t nreturns;
811                 cell_t slot[16];
812         } args;
813         cell_t status;
814         int i = 0, j = 0;
815
816         args.name = (cell_t)(uintptr_t)"interpret";
817         args.nargs = 1;
818
819         ofw_real_start();
820         args.nreturns = ++nreturns;
821         args.slot[i++] = ofw_real_map(cmd, strlen(cmd) + 1);
822         argsptr = ofw_real_map(&args, sizeof(args));
823         if (openfirmware((void *)argsptr) == -1) {
824                 ofw_real_stop();
825                 return (-1);
826         }
827         ofw_real_unmap(argsptr, &args, sizeof(args));
828         ofw_real_stop();
829         status = args.slot[i++];
830         while (i < 1 + nreturns)
831                 returns[j++] = args.slot[i++];
832         return (status);
833 }
834
835 /*
836  * Device I/O functions
837  */
838
839 /* Open an instance for a device. */
840 static ihandle_t
841 ofw_real_open(ofw_t ofw, const char *device)
842 {
843         vm_offset_t argsptr;
844         struct {
845                 cell_t name;
846                 cell_t nargs;
847                 cell_t nreturns;
848                 cell_t device;
849                 cell_t instance;
850         } args;
851
852         args.name = (cell_t)(uintptr_t)"open";
853         args.nargs = 1;
854         args.nreturns = 1;
855
856         ofw_real_start();
857
858         args.device = ofw_real_map(device, strlen(device) + 1);
859         argsptr = ofw_real_map(&args, sizeof(args));
860         if (args.device == 0 || openfirmware((void *)argsptr) == -1 
861             || args.instance == 0) {
862                 ofw_real_stop();
863                 return (-1);
864         }
865         ofw_real_unmap(argsptr, &args, sizeof(args));
866         ofw_real_stop();
867         return (args.instance);
868 }
869
870 /* Close an instance. */
871 static void
872 ofw_real_close(ofw_t ofw, ihandle_t instance)
873 {
874         vm_offset_t argsptr;
875         struct {
876                 cell_t name;
877                 cell_t nargs;
878                 cell_t nreturns;
879                 cell_t instance;
880         } args;
881
882         args.name = (cell_t)(uintptr_t)"close";
883         args.nargs = 1;
884         args.nreturns = 0;
885         args.instance = instance;
886         ofw_real_start();
887         argsptr = ofw_real_map(&args, sizeof(args));
888         openfirmware((void *)argsptr);
889         ofw_real_stop();
890 }
891
892 /* Read from an instance. */
893 static ssize_t
894 ofw_real_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len)
895 {
896         vm_offset_t argsptr;
897         struct {
898                 cell_t name;
899                 cell_t nargs;
900                 cell_t nreturns;
901                 cell_t instance;
902                 cell_t addr;
903                 cell_t len;
904                 int32_t actual;
905         } args;
906
907         args.name = (cell_t)(uintptr_t)"read";
908         args.nargs = 3;
909         args.nreturns = 1;
910
911         ofw_real_start();
912
913         args.instance = instance;
914         args.addr = ofw_real_map(addr, len);
915         args.len = len;
916         argsptr = ofw_real_map(&args, sizeof(args));
917         if (args.addr == 0 || openfirmware((void *)argsptr) == -1) {
918                 ofw_real_stop();
919                 return (-1);
920         }
921         ofw_real_unmap(argsptr, &args, sizeof(args));
922         ofw_real_unmap(args.addr, addr, len);
923
924         ofw_real_stop();
925         return (args.actual);
926 }
927
928 /* Write to an instance. */
929 static ssize_t
930 ofw_real_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len)
931 {
932         vm_offset_t argsptr;
933         struct {
934                 cell_t name;
935                 cell_t nargs;
936                 cell_t nreturns;
937                 cell_t instance;
938                 cell_t addr;
939                 cell_t len;
940                 int32_t actual;
941         } args;
942
943         args.name = (cell_t)(uintptr_t)"write";
944         args.nargs = 3;
945         args.nreturns = 1;
946
947         ofw_real_start();
948
949         args.instance = instance;
950         args.addr = ofw_real_map(addr, len);
951         args.len = len;
952         argsptr = ofw_real_map(&args, sizeof(args));
953         if (args.addr == 0 || openfirmware((void *)argsptr) == -1) {
954                 ofw_real_stop();
955                 return (-1);
956         }
957         ofw_real_unmap(argsptr, &args, sizeof(args));
958         ofw_real_stop();
959         return (args.actual);
960 }
961
962 /* Seek to a position. */
963 static int
964 ofw_real_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos)
965 {
966         vm_offset_t argsptr;
967         struct {
968                 cell_t name;
969                 cell_t nargs;
970                 cell_t nreturns;
971                 cell_t instance;
972                 cell_t poshi;
973                 cell_t poslo;
974                 cell_t status;
975         } args;
976
977         args.name = (cell_t)(uintptr_t)"seek";
978         args.nargs = 3;
979         args.nreturns = 1;
980
981         args.instance = instance;
982         args.poshi = pos >> 32;
983         args.poslo = pos;
984         ofw_real_start();
985         argsptr = ofw_real_map(&args, sizeof(args));
986         if (openfirmware((void *)argsptr) == -1) {
987                 ofw_real_stop();
988                 return (-1);
989         }
990         ofw_real_unmap(argsptr, &args, sizeof(args));
991         ofw_real_stop();
992         return (args.status);
993 }
994
995 /*
996  * Memory functions
997  */
998
999 /* Claim an area of memory. */
1000 static caddr_t
1001 ofw_real_claim(ofw_t ofw, void *virt, size_t size, u_int align)
1002 {
1003         vm_offset_t argsptr;
1004         struct {
1005                 cell_t name;
1006                 cell_t nargs;
1007                 cell_t nreturns;
1008                 cell_t virt;
1009                 cell_t size;
1010                 cell_t align;
1011                 cell_t baseaddr;
1012         } args;
1013
1014         args.name = (cell_t)(uintptr_t)"claim";
1015         args.nargs = 3;
1016         args.nreturns = 1;
1017
1018         args.virt = (cell_t)(uintptr_t)virt;
1019         args.size = size;
1020         args.align = align;
1021         ofw_real_start();
1022         argsptr = ofw_real_map(&args, sizeof(args));
1023         if (openfirmware((void *)argsptr) == -1) {
1024                 ofw_real_stop();
1025                 return ((void *)-1);
1026         }
1027         ofw_real_unmap(argsptr, &args, sizeof(args));
1028         ofw_real_stop();
1029         return ((void *)(uintptr_t)args.baseaddr);
1030 }
1031
1032 /* Release an area of memory. */
1033 static void
1034 ofw_real_release(ofw_t ofw, void *virt, size_t size)
1035 {
1036         vm_offset_t argsptr;
1037         struct {
1038                 cell_t name;
1039                 cell_t nargs;
1040                 cell_t nreturns;
1041                 cell_t virt;
1042                 cell_t size;
1043         } args;
1044
1045         args.name = (cell_t)(uintptr_t)"release";
1046         args.nargs = 2;
1047         args.nreturns = 0;
1048
1049         args.virt = (cell_t)(uintptr_t)virt;
1050         args.size = size;
1051         ofw_real_start();
1052         argsptr = ofw_real_map(&args, sizeof(args));
1053         openfirmware((void *)argsptr);
1054         ofw_real_stop();
1055 }
1056
1057 /*
1058  * Control transfer functions
1059  */
1060
1061 /* Suspend and drop back to the Open Firmware interface. */
1062 static void
1063 ofw_real_enter(ofw_t ofw)
1064 {
1065         vm_offset_t argsptr;
1066         struct {
1067                 cell_t name;
1068                 cell_t nargs;
1069                 cell_t nreturns;
1070         } args;
1071
1072         args.name = (cell_t)(uintptr_t)"enter";
1073         args.nargs = 0;
1074         args.nreturns = 0;
1075
1076         ofw_real_start();
1077         argsptr = ofw_real_map(&args, sizeof(args));
1078         openfirmware((void *)argsptr);
1079         /* We may come back. */
1080         ofw_real_stop();
1081 }
1082
1083 /* Shut down and drop back to the Open Firmware interface. */
1084 static void
1085 ofw_real_exit(ofw_t ofw)
1086 {
1087         vm_offset_t argsptr;
1088         struct {
1089                 cell_t name;
1090                 cell_t nargs;
1091                 cell_t nreturns;
1092         } args;
1093
1094         args.name = (cell_t)(uintptr_t)"exit";
1095         args.nargs = 0;
1096         args.nreturns = 0;
1097
1098         ofw_real_start();
1099         argsptr = ofw_real_map(&args, sizeof(args));
1100         openfirmware((void *)argsptr);
1101         for (;;)                        /* just in case */
1102                 ;
1103         ofw_real_stop();
1104 }
1105