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

Cache object: fb301e1271142285fd30314695169cda


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