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/dev/ofw/openfirm.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  * SPDX-License-Identifier: BSD-4-Clause
    5  *
    6  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
    7  * Copyright (C) 1995, 1996 TooLs GmbH.
    8  * All rights reserved.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by TooLs GmbH.
   21  * 4. The name of TooLs GmbH may not be used to endorse or promote products
   22  *    derived from this software without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
   25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   26  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   27  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   29  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   30  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   31  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   32  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   33  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   34  */
   35 /*-
   36  * Copyright (C) 2000 Benno Rice.
   37  * All rights reserved.
   38  *
   39  * Redistribution and use in source and binary forms, with or without
   40  * modification, are permitted provided that the following conditions
   41  * are met:
   42  * 1. Redistributions of source code must retain the above copyright
   43  *    notice, this list of conditions and the following disclaimer.
   44  * 2. Redistributions in binary form must reproduce the above copyright
   45  *    notice, this list of conditions and the following disclaimer in the
   46  *    documentation and/or other materials provided with the distribution.
   47  *
   48  * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
   49  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   50  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   51  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   52  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   53  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   54  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   55  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   56  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   57  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   58  */
   59 
   60 #include <sys/cdefs.h>
   61 __FBSDID("$FreeBSD$");
   62 
   63 #include "opt_platform.h"
   64 
   65 #include <sys/param.h>
   66 #include <sys/kernel.h>
   67 #include <sys/lock.h>
   68 #include <sys/malloc.h>
   69 #include <sys/mutex.h>
   70 #include <sys/queue.h>
   71 #include <sys/systm.h>
   72 #include <sys/endian.h>
   73 
   74 #include <machine/stdarg.h>
   75 
   76 #include <dev/ofw/ofwvar.h>
   77 #include <dev/ofw/openfirm.h>
   78 
   79 #include "ofw_if.h"
   80 
   81 static void OF_putchar(int c, void *arg);
   82 
   83 MALLOC_DEFINE(M_OFWPROP, "openfirm", "Open Firmware properties");
   84 
   85 static ihandle_t stdout;
   86 
   87 static ofw_def_t        *ofw_def_impl = NULL;
   88 static ofw_t            ofw_obj;
   89 static struct ofw_kobj  ofw_kernel_obj;
   90 static struct kobj_ops  ofw_kernel_kops;
   91 
   92 struct xrefinfo {
   93         phandle_t       xref;
   94         phandle_t       node;
   95         device_t        dev;
   96         SLIST_ENTRY(xrefinfo) next_entry;
   97 };
   98 
   99 static SLIST_HEAD(, xrefinfo) xreflist = SLIST_HEAD_INITIALIZER(xreflist);
  100 static struct mtx xreflist_lock;
  101 static boolean_t xref_init_done;
  102 
  103 #define FIND_BY_XREF    0
  104 #define FIND_BY_NODE    1
  105 #define FIND_BY_DEV     2
  106 
  107 /*
  108  * xref-phandle-device lookup helper routines.
  109  *
  110  * As soon as we are able to use malloc(), walk the node tree and build a list
  111  * of info that cross-references node handles, xref handles, and device_t
  112  * instances.  This list exists primarily to allow association of a device_t
  113  * with an xref handle, but it is also used to speed up translation between xref
  114  * and node handles.  Before malloc() is available we have to recursively search
  115  * the node tree each time we want to translate between a node and xref handle.
  116  * Afterwards we can do the translations by searching this much shorter list.
  117  */
  118 static void
  119 xrefinfo_create(phandle_t node)
  120 {
  121         struct xrefinfo * xi;
  122         phandle_t child, xref;
  123 
  124         /*
  125          * Recursively descend from parent, looking for nodes with a property
  126          * named either "phandle", "ibm,phandle", or "linux,phandle".  For each
  127          * such node found create an entry in the xreflist.
  128          */
  129         for (child = OF_child(node); child != 0; child = OF_peer(child)) {
  130                 xrefinfo_create(child);
  131                 if (OF_getencprop(child, "phandle", &xref, sizeof(xref)) ==
  132                     -1 && OF_getencprop(child, "ibm,phandle", &xref,
  133                     sizeof(xref)) == -1 && OF_getencprop(child,
  134                     "linux,phandle", &xref, sizeof(xref)) == -1)
  135                         continue;
  136                 xi = malloc(sizeof(*xi), M_OFWPROP, M_WAITOK | M_ZERO);
  137                 xi->node = child;
  138                 xi->xref = xref;
  139                 SLIST_INSERT_HEAD(&xreflist, xi, next_entry);
  140         }
  141 }
  142 
  143 static void
  144 xrefinfo_init(void *unsed)
  145 {
  146 
  147         /*
  148          * There is no locking during this init because it runs much earlier
  149          * than any of the clients/consumers of the xref list data, but we do
  150          * initialize the mutex that will be used for access later.
  151          */
  152         mtx_init(&xreflist_lock, "OF xreflist lock", NULL, MTX_DEF);
  153         xrefinfo_create(OF_peer(0));
  154         xref_init_done = true;
  155 }
  156 SYSINIT(xrefinfo, SI_SUB_KMEM, SI_ORDER_ANY, xrefinfo_init, NULL);
  157 
  158 static struct xrefinfo *
  159 xrefinfo_find(uintptr_t key, int find_by)
  160 {
  161         struct xrefinfo *rv, *xi;
  162 
  163         rv = NULL;
  164         mtx_lock(&xreflist_lock);
  165         SLIST_FOREACH(xi, &xreflist, next_entry) {
  166                 if ((find_by == FIND_BY_XREF && (phandle_t)key == xi->xref) ||
  167                     (find_by == FIND_BY_NODE && (phandle_t)key == xi->node) ||
  168                     (find_by == FIND_BY_DEV && key == (uintptr_t)xi->dev)) {
  169                         rv = xi;
  170                         break;
  171                 }
  172         }
  173         mtx_unlock(&xreflist_lock);
  174         return (rv);
  175 }
  176 
  177 static struct xrefinfo *
  178 xrefinfo_add(phandle_t node, phandle_t xref, device_t dev)
  179 {
  180         struct xrefinfo *xi;
  181 
  182         xi = malloc(sizeof(*xi), M_OFWPROP, M_WAITOK);
  183         xi->node = node;
  184         xi->xref = xref;
  185         xi->dev  = dev;
  186         mtx_lock(&xreflist_lock);
  187         SLIST_INSERT_HEAD(&xreflist, xi, next_entry);
  188         mtx_unlock(&xreflist_lock);
  189         return (xi);
  190 }
  191 
  192 /*
  193  * OFW install routines.  Highest priority wins, equal priority also
  194  * overrides allowing last-set to win.
  195  */
  196 SET_DECLARE(ofw_set, ofw_def_t);
  197 
  198 boolean_t
  199 OF_install(char *name, int prio)
  200 {
  201         ofw_def_t *ofwp, **ofwpp;
  202         static int curr_prio = 0;
  203 
  204         /* Allow OF layer to be uninstalled */
  205         if (name == NULL) {
  206                 ofw_def_impl = NULL;
  207                 return (FALSE);
  208         }
  209 
  210         /*
  211          * Try and locate the OFW kobj corresponding to the name.
  212          */
  213         SET_FOREACH(ofwpp, ofw_set) {
  214                 ofwp = *ofwpp;
  215 
  216                 if (ofwp->name &&
  217                     !strcmp(ofwp->name, name) &&
  218                     prio >= curr_prio) {
  219                         curr_prio = prio;
  220                         ofw_def_impl = ofwp;
  221                         return (TRUE);
  222                 }
  223         }
  224 
  225         return (FALSE);
  226 }
  227 
  228 /* Initializer */
  229 int
  230 OF_init(void *cookie)
  231 {
  232         phandle_t chosen;
  233         int rv;
  234 
  235         if (ofw_def_impl == NULL)
  236                 return (-1);
  237 
  238         ofw_obj = &ofw_kernel_obj;
  239         /*
  240          * Take care of compiling the selected class, and
  241          * then statically initialize the OFW object.
  242          */
  243         kobj_class_compile_static(ofw_def_impl, &ofw_kernel_kops);
  244         kobj_init_static((kobj_t)ofw_obj, ofw_def_impl);
  245 
  246         rv = OFW_INIT(ofw_obj, cookie);
  247 
  248         if ((chosen = OF_finddevice("/chosen")) != -1)
  249                 if (OF_getencprop(chosen, "stdout", &stdout,
  250                     sizeof(stdout)) == -1)
  251                         stdout = -1;
  252 
  253         return (rv);
  254 }
  255 
  256 static void
  257 OF_putchar(int c, void *arg __unused)
  258 {
  259         char cbuf;
  260 
  261         if (c == '\n') {
  262                 cbuf = '\r';
  263                 OF_write(stdout, &cbuf, 1);
  264         }
  265 
  266         cbuf = c;
  267         OF_write(stdout, &cbuf, 1);
  268 }
  269 
  270 void
  271 OF_printf(const char *fmt, ...)
  272 {
  273         va_list va;
  274 
  275         va_start(va, fmt);
  276         (void)kvprintf(fmt, OF_putchar, NULL, 10, va);
  277         va_end(va);
  278 }
  279 
  280 /*
  281  * Generic functions
  282  */
  283 
  284 /* Test to see if a service exists. */
  285 int
  286 OF_test(const char *name)
  287 {
  288 
  289         if (ofw_def_impl == NULL)
  290                 return (-1);
  291 
  292         return (OFW_TEST(ofw_obj, name));
  293 }
  294 
  295 int
  296 OF_interpret(const char *cmd, int nreturns, ...)
  297 {
  298         va_list ap;
  299         cell_t slots[16];
  300         int i = 0;
  301         int status;
  302 
  303         if (ofw_def_impl == NULL)
  304                 return (-1);
  305 
  306         status = OFW_INTERPRET(ofw_obj, cmd, nreturns, slots);
  307         if (status == -1)
  308                 return (status);
  309 
  310         va_start(ap, nreturns);
  311         while (i < nreturns)
  312                 *va_arg(ap, cell_t *) = slots[i++];
  313         va_end(ap);
  314 
  315         return (status);
  316 }
  317 
  318 /*
  319  * Device tree functions
  320  */
  321 
  322 /* Return the next sibling of this node or 0. */
  323 phandle_t
  324 OF_peer(phandle_t node)
  325 {
  326 
  327         if (ofw_def_impl == NULL)
  328                 return (0);
  329 
  330         return (OFW_PEER(ofw_obj, node));
  331 }
  332 
  333 /* Return the first child of this node or 0. */
  334 phandle_t
  335 OF_child(phandle_t node)
  336 {
  337 
  338         if (ofw_def_impl == NULL)
  339                 return (0);
  340 
  341         return (OFW_CHILD(ofw_obj, node));
  342 }
  343 
  344 /* Return the parent of this node or 0. */
  345 phandle_t
  346 OF_parent(phandle_t node)
  347 {
  348 
  349         if (ofw_def_impl == NULL)
  350                 return (0);
  351 
  352         return (OFW_PARENT(ofw_obj, node));
  353 }
  354 
  355 /* Return the package handle that corresponds to an instance handle. */
  356 phandle_t
  357 OF_instance_to_package(ihandle_t instance)
  358 {
  359 
  360         if (ofw_def_impl == NULL)
  361                 return (-1);
  362 
  363         return (OFW_INSTANCE_TO_PACKAGE(ofw_obj, instance));
  364 }
  365 
  366 /* Get the length of a property of a package. */
  367 ssize_t
  368 OF_getproplen(phandle_t package, const char *propname)
  369 {
  370 
  371         if (ofw_def_impl == NULL)
  372                 return (-1);
  373 
  374         return (OFW_GETPROPLEN(ofw_obj, package, propname));
  375 }
  376 
  377 /* Check existence of a property of a package. */
  378 int
  379 OF_hasprop(phandle_t package, const char *propname)
  380 {
  381 
  382         return (OF_getproplen(package, propname) >= 0 ? 1 : 0);
  383 }
  384 
  385 /* Get the value of a property of a package. */
  386 ssize_t
  387 OF_getprop(phandle_t package, const char *propname, void *buf, size_t buflen)
  388 {
  389 
  390         if (ofw_def_impl == NULL)
  391                 return (-1);
  392 
  393         return (OFW_GETPROP(ofw_obj, package, propname, buf, buflen));
  394 }
  395 
  396 ssize_t
  397 OF_getencprop(phandle_t node, const char *propname, pcell_t *buf, size_t len)
  398 {
  399         ssize_t retval;
  400         int i;
  401 
  402         KASSERT(len % 4 == 0, ("Need a multiple of 4 bytes"));
  403 
  404         retval = OF_getprop(node, propname, buf, len);
  405         if (retval <= 0)
  406                 return (retval);
  407 
  408         for (i = 0; i < len/4; i++)
  409                 buf[i] = be32toh(buf[i]);
  410 
  411         return (retval);
  412 }
  413 
  414 /*
  415  * Recursively search the node and its parent for the given property, working
  416  * downward from the node to the device tree root.  Returns the value of the
  417  * first match.
  418  */
  419 ssize_t
  420 OF_searchprop(phandle_t node, const char *propname, void *buf, size_t len)
  421 {
  422         ssize_t rv;
  423 
  424         for (; node != 0; node = OF_parent(node))
  425                 if ((rv = OF_getprop(node, propname, buf, len)) != -1)
  426                         return (rv);
  427         return (-1);
  428 }
  429 
  430 ssize_t
  431 OF_searchencprop(phandle_t node, const char *propname, pcell_t *buf, size_t len)
  432 {
  433         ssize_t rv;
  434 
  435         for (; node != 0; node = OF_parent(node))
  436                 if ((rv = OF_getencprop(node, propname, buf, len)) != -1)
  437                         return (rv);
  438         return (-1);
  439 }
  440 
  441 /*
  442  * Store the value of a property of a package into newly allocated memory
  443  * (using the M_OFWPROP malloc pool and M_WAITOK).
  444  */
  445 ssize_t
  446 OF_getprop_alloc(phandle_t package, const char *propname, void **buf)
  447 {
  448         int len;
  449 
  450         *buf = NULL;
  451         if ((len = OF_getproplen(package, propname)) == -1)
  452                 return (-1);
  453 
  454         if (len > 0) {
  455                 *buf = malloc(len, M_OFWPROP, M_WAITOK);
  456                 if (OF_getprop(package, propname, *buf, len) == -1) {
  457                         free(*buf, M_OFWPROP);
  458                         *buf = NULL;
  459                         return (-1);
  460                 }
  461         }
  462         return (len);
  463 }
  464 
  465 /*
  466  * Store the value of a property of a package into newly allocated memory
  467  * (using the M_OFWPROP malloc pool and M_WAITOK).  elsz is the size of a
  468  * single element, the number of elements is return in number.
  469  */
  470 ssize_t
  471 OF_getprop_alloc_multi(phandle_t package, const char *propname, int elsz, void **buf)
  472 {
  473         int len;
  474 
  475         *buf = NULL;
  476         if ((len = OF_getproplen(package, propname)) == -1 ||
  477             len % elsz != 0)
  478                 return (-1);
  479 
  480         if (len > 0) {
  481                 *buf = malloc(len, M_OFWPROP, M_WAITOK);
  482                 if (OF_getprop(package, propname, *buf, len) == -1) {
  483                         free(*buf, M_OFWPROP);
  484                         *buf = NULL;
  485                         return (-1);
  486                 }
  487         }
  488         return (len / elsz);
  489 }
  490 
  491 ssize_t
  492 OF_getencprop_alloc(phandle_t package, const char *name, void **buf)
  493 {
  494         ssize_t ret;
  495 
  496         ret = OF_getencprop_alloc_multi(package, name, sizeof(pcell_t),
  497             buf);
  498         if (ret < 0)
  499                 return (ret);
  500         else
  501                 return (ret * sizeof(pcell_t));
  502 }
  503 
  504 ssize_t
  505 OF_getencprop_alloc_multi(phandle_t package, const char *name, int elsz,
  506     void **buf)
  507 {
  508         ssize_t retval;
  509         pcell_t *cell;
  510         int i;
  511 
  512         retval = OF_getprop_alloc_multi(package, name, elsz, buf);
  513         if (retval == -1)
  514                 return (-1);
  515 
  516         cell = *buf;
  517         for (i = 0; i < retval * elsz / 4; i++)
  518                 cell[i] = be32toh(cell[i]);
  519 
  520         return (retval);
  521 }
  522 
  523 /* Free buffer allocated by OF_getencprop_alloc or OF_getprop_alloc */
  524 void OF_prop_free(void *buf)
  525 {
  526 
  527         free(buf, M_OFWPROP);
  528 }
  529 
  530 /* Get the next property of a package. */
  531 int
  532 OF_nextprop(phandle_t package, const char *previous, char *buf, size_t size)
  533 {
  534 
  535         if (ofw_def_impl == NULL)
  536                 return (-1);
  537 
  538         return (OFW_NEXTPROP(ofw_obj, package, previous, buf, size));
  539 }
  540 
  541 /* Set the value of a property of a package. */
  542 int
  543 OF_setprop(phandle_t package, const char *propname, const void *buf, size_t len)
  544 {
  545 
  546         if (ofw_def_impl == NULL)
  547                 return (-1);
  548 
  549         return (OFW_SETPROP(ofw_obj, package, propname, buf,len));
  550 }
  551 
  552 /* Convert a device specifier to a fully qualified pathname. */
  553 ssize_t
  554 OF_canon(const char *device, char *buf, size_t len)
  555 {
  556 
  557         if (ofw_def_impl == NULL)
  558                 return (-1);
  559 
  560         return (OFW_CANON(ofw_obj, device, buf, len));
  561 }
  562 
  563 /* Return a package handle for the specified device. */
  564 phandle_t
  565 OF_finddevice(const char *device)
  566 {
  567 
  568         if (ofw_def_impl == NULL)
  569                 return (-1);
  570 
  571         return (OFW_FINDDEVICE(ofw_obj, device));
  572 }
  573 
  574 /* Return the fully qualified pathname corresponding to an instance. */
  575 ssize_t
  576 OF_instance_to_path(ihandle_t instance, char *buf, size_t len)
  577 {
  578 
  579         if (ofw_def_impl == NULL)
  580                 return (-1);
  581 
  582         return (OFW_INSTANCE_TO_PATH(ofw_obj, instance, buf, len));
  583 }
  584 
  585 /* Return the fully qualified pathname corresponding to a package. */
  586 ssize_t
  587 OF_package_to_path(phandle_t package, char *buf, size_t len)
  588 {
  589 
  590         if (ofw_def_impl == NULL)
  591                 return (-1);
  592 
  593         return (OFW_PACKAGE_TO_PATH(ofw_obj, package, buf, len));
  594 }
  595 
  596 /* Look up effective phandle (see FDT/PAPR spec) */
  597 static phandle_t
  598 OF_child_xref_phandle(phandle_t parent, phandle_t xref)
  599 {
  600         phandle_t child, rxref;
  601 
  602         /*
  603          * Recursively descend from parent, looking for a node with a property
  604          * named either "phandle", "ibm,phandle", or "linux,phandle" that
  605          * matches the xref we are looking for.
  606          */
  607 
  608         for (child = OF_child(parent); child != 0; child = OF_peer(child)) {
  609                 rxref = OF_child_xref_phandle(child, xref);
  610                 if (rxref != -1)
  611                         return (rxref);
  612 
  613                 if (OF_getencprop(child, "phandle", &rxref, sizeof(rxref)) ==
  614                     -1 && OF_getencprop(child, "ibm,phandle", &rxref,
  615                     sizeof(rxref)) == -1 && OF_getencprop(child,
  616                     "linux,phandle", &rxref, sizeof(rxref)) == -1)
  617                         continue;
  618 
  619                 if (rxref == xref)
  620                         return (child);
  621         }
  622 
  623         return (-1);
  624 }
  625 
  626 phandle_t
  627 OF_node_from_xref(phandle_t xref)
  628 {
  629         struct xrefinfo *xi;
  630         phandle_t node;
  631 
  632         if (xref_init_done) {
  633                 if ((xi = xrefinfo_find(xref, FIND_BY_XREF)) == NULL)
  634                         return (xref);
  635                 return (xi->node);
  636         }
  637 
  638         if ((node = OF_child_xref_phandle(OF_peer(0), xref)) == -1)
  639                 return (xref);
  640         return (node);
  641 }
  642 
  643 phandle_t
  644 OF_xref_from_node(phandle_t node)
  645 {
  646         struct xrefinfo *xi;
  647         phandle_t xref;
  648 
  649         if (xref_init_done) {
  650                 if ((xi = xrefinfo_find(node, FIND_BY_NODE)) == NULL)
  651                         return (node);
  652                 return (xi->xref);
  653         }
  654 
  655         if (OF_getencprop(node, "phandle", &xref, sizeof(xref)) == -1 &&
  656             OF_getencprop(node, "ibm,phandle", &xref, sizeof(xref)) == -1 &&
  657             OF_getencprop(node, "linux,phandle", &xref, sizeof(xref)) == -1)
  658                 return (node);
  659         return (xref);
  660 }
  661 
  662 device_t
  663 OF_device_from_xref(phandle_t xref)
  664 {
  665         struct xrefinfo *xi;
  666 
  667         if (xref_init_done) {
  668                 if ((xi = xrefinfo_find(xref, FIND_BY_XREF)) == NULL)
  669                         return (NULL);
  670                 return (xi->dev);
  671         }
  672         panic("Attempt to find device before xreflist_init");
  673 }
  674 
  675 phandle_t
  676 OF_xref_from_device(device_t dev)
  677 {
  678         struct xrefinfo *xi;
  679 
  680         if (xref_init_done) {
  681                 if ((xi = xrefinfo_find((uintptr_t)dev, FIND_BY_DEV)) == NULL)
  682                         return (0);
  683                 return (xi->xref);
  684         }
  685         panic("Attempt to find xref before xreflist_init");
  686 }
  687 
  688 int
  689 OF_device_register_xref(phandle_t xref, device_t dev)
  690 {
  691         struct xrefinfo *xi;
  692 
  693         /*
  694          * If the given xref handle doesn't already exist in the list then we
  695          * add a list entry.  In theory this can only happen on a system where
  696          * nodes don't contain phandle properties and xref and node handles are
  697          * synonymous, so the xref handle is added as the node handle as well.
  698          */
  699         if (xref_init_done) {
  700                 if ((xi = xrefinfo_find(xref, FIND_BY_XREF)) == NULL)
  701                         xrefinfo_add(xref, xref, dev);
  702                 else 
  703                         xi->dev = dev;
  704                 return (0);
  705         }
  706         panic("Attempt to register device before xreflist_init");
  707 }
  708 
  709 /*  Call the method in the scope of a given instance. */
  710 int
  711 OF_call_method(const char *method, ihandle_t instance, int nargs, int nreturns,
  712     ...)
  713 {
  714         va_list ap;
  715         cell_t args_n_results[12];
  716         int n, status;
  717 
  718         if (nargs > 6 || ofw_def_impl == NULL)
  719                 return (-1);
  720         va_start(ap, nreturns);
  721         for (n = 0; n < nargs; n++)
  722                 args_n_results[n] = va_arg(ap, cell_t);
  723 
  724         status = OFW_CALL_METHOD(ofw_obj, instance, method, nargs, nreturns,
  725             args_n_results);
  726         if (status != 0)
  727                 return (status);
  728 
  729         for (; n < nargs + nreturns; n++)
  730                 *va_arg(ap, cell_t *) = args_n_results[n];
  731         va_end(ap);
  732         return (0);
  733 }
  734 
  735 /*
  736  * Device I/O functions
  737  */
  738 
  739 /* Open an instance for a device. */
  740 ihandle_t
  741 OF_open(const char *device)
  742 {
  743 
  744         if (ofw_def_impl == NULL)
  745                 return (0);
  746 
  747         return (OFW_OPEN(ofw_obj, device));
  748 }
  749 
  750 /* Close an instance. */
  751 void
  752 OF_close(ihandle_t instance)
  753 {
  754 
  755         if (ofw_def_impl == NULL)
  756                 return;
  757 
  758         OFW_CLOSE(ofw_obj, instance);
  759 }
  760 
  761 /* Read from an instance. */
  762 ssize_t
  763 OF_read(ihandle_t instance, void *addr, size_t len)
  764 {
  765 
  766         if (ofw_def_impl == NULL)
  767                 return (-1);
  768 
  769         return (OFW_READ(ofw_obj, instance, addr, len));
  770 }
  771 
  772 /* Write to an instance. */
  773 ssize_t
  774 OF_write(ihandle_t instance, const void *addr, size_t len)
  775 {
  776 
  777         if (ofw_def_impl == NULL)
  778                 return (-1);
  779 
  780         return (OFW_WRITE(ofw_obj, instance, addr, len));
  781 }
  782 
  783 /* Seek to a position. */
  784 int
  785 OF_seek(ihandle_t instance, uint64_t pos)
  786 {
  787 
  788         if (ofw_def_impl == NULL)
  789                 return (-1);
  790 
  791         return (OFW_SEEK(ofw_obj, instance, pos));
  792 }
  793 
  794 /*
  795  * Memory functions
  796  */
  797 
  798 /* Claim an area of memory. */
  799 void *
  800 OF_claim(void *virt, size_t size, u_int align)
  801 {
  802 
  803         if (ofw_def_impl == NULL)
  804                 return ((void *)-1);
  805 
  806         return (OFW_CLAIM(ofw_obj, virt, size, align));
  807 }
  808 
  809 /* Release an area of memory. */
  810 void
  811 OF_release(void *virt, size_t size)
  812 {
  813 
  814         if (ofw_def_impl == NULL)
  815                 return;
  816 
  817         OFW_RELEASE(ofw_obj, virt, size);
  818 }
  819 
  820 /*
  821  * Control transfer functions
  822  */
  823 
  824 /* Suspend and drop back to the Open Firmware interface. */
  825 void
  826 OF_enter(void)
  827 {
  828 
  829         if (ofw_def_impl == NULL)
  830                 return;
  831 
  832         OFW_ENTER(ofw_obj);
  833 }
  834 
  835 /* Shut down and drop back to the Open Firmware interface. */
  836 void
  837 OF_exit(void)
  838 {
  839 
  840         if (ofw_def_impl == NULL)
  841                 panic("OF_exit: Open Firmware not available");
  842 
  843         /* Should not return */
  844         OFW_EXIT(ofw_obj);
  845 
  846         for (;;)                        /* just in case */
  847                 ;
  848 }

Cache object: 72463f9b94b9d7726e45d0d33b245efa


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