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

Cache object: 52dfce3a74c88e2c8b2b0abbea643d13


[ 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.