The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/powerpc/ofw/ofw_real.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 8583c0b550ae651ff9c264b268e1e8d4


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.