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/ofw_graph.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 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2019 Emmanuel Vadot <manu@FreeBSD.org>
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions, and the following disclaimer,
   11  *    without modification, immediately at the beginning of the file.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in
   14  *    the documentation and/or other materials provided with the
   15  *    distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  * $FreeBSD$
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD$");
   34 
   35 #include "opt_platform.h"
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/bus.h>
   39 #include <sys/errno.h>
   40 
   41 #include <dev/ofw/ofw_bus.h>
   42 #include <dev/ofw/ofw_bus_subr.h>
   43 #include <dev/ofw/ofw_graph.h>
   44 #include <dev/ofw/openfirm.h>
   45 
   46 #include "ofw_bus_if.h"
   47 
   48 #define PORT_MAX_NAME   8
   49 
   50 phandle_t
   51 ofw_graph_get_port_by_idx(phandle_t node, uint32_t idx)
   52 {
   53         phandle_t ports, child;
   54         uint32_t reg;
   55         char portnode[PORT_MAX_NAME];
   56 
   57         /* First try to find a port@<idx> node */
   58         snprintf(portnode, sizeof(portnode), "port@%d", idx);
   59         child = ofw_bus_find_child(node, portnode);
   60         if (child != 0)
   61                 return (child);
   62 
   63         /* Now check for 'port' without explicit index. */
   64         if (idx == 0) {
   65                 snprintf(portnode, sizeof(portnode), "port");
   66                 child = ofw_bus_find_child(node, portnode);
   67                 if (child != 0)
   68                         return (child);
   69         }
   70 
   71         /* Next try to look under ports */
   72         ports = ofw_bus_find_child(node, "ports");
   73         if (ports == 0)
   74                 return (0);
   75 
   76         for (child = OF_child(ports); child != 0; child = OF_peer(child)) {
   77                 if (OF_getencprop(child, "reg", &reg, sizeof(uint32_t)) <= 0 ||
   78                     reg != idx)
   79                         continue;
   80 
   81                 return (child);
   82         }
   83 
   84         return (0);
   85 }
   86 
   87 size_t
   88 ofw_graph_port_get_num_endpoints(phandle_t port)
   89 {
   90         phandle_t child;
   91         char *name;
   92         size_t num = 0;
   93         int ret;
   94 
   95         for (num = 0, child = OF_child(port); child != 0;
   96              child = OF_peer(child)) {
   97                 ret = OF_getprop_alloc(child, "name", (void **)&name);
   98                 if (ret == -1)
   99                         continue;
  100                 if (strcmp(name, "endpoint") == 0)
  101                         num++;
  102                 else if (strncmp(name, "endpoint@", 9) == 0)
  103                         num++;
  104                 free(name, M_OFWPROP);
  105         }
  106 
  107         return (num);
  108 }
  109 
  110 phandle_t
  111 ofw_graph_get_endpoint_by_idx(phandle_t port, uint32_t idx)
  112 {
  113         phandle_t endpoint, child;
  114         uint32_t reg;
  115 
  116         /* First test if we have only one endpoint */
  117         endpoint = ofw_bus_find_child(port, "endpoint");
  118         if (endpoint != 0)
  119                 return (endpoint);
  120 
  121         /* Then test all childs based on the reg property */
  122         for (child = OF_child(port); child != 0; child = OF_peer(child)) {
  123                 if (OF_getencprop(child, "reg", &reg, sizeof(uint32_t)) <= 0 ||
  124                     reg != idx)
  125                         continue;
  126 
  127                 return (child);
  128         }
  129 
  130         return (0);
  131 }
  132 
  133 phandle_t
  134 ofw_graph_get_remote_endpoint(phandle_t endpoint)
  135 {
  136         phandle_t remote;
  137 
  138         if (OF_getencprop(endpoint, "remote-endpoint", &remote,
  139               sizeof(phandle_t)) <= 0)
  140                 return (0);
  141 
  142         return (remote);
  143 }
  144 
  145 phandle_t
  146 ofw_graph_get_remote_parent(phandle_t remote)
  147 {
  148         phandle_t node;
  149         char *name;
  150         int ret;
  151 
  152         /* get the endpoint node */
  153         node = OF_node_from_xref(remote);
  154 
  155         /* go to the port@X node */
  156         node = OF_parent(node);
  157         /* go to the ports node or parent */
  158         node = OF_parent(node);
  159 
  160         /* if the node name is 'ports' we need to go up one last time */
  161         ret = OF_getprop_alloc(node, "name", (void **)&name);
  162         if (ret == -1) {
  163                 printf("%s: Node %x don't have a name, abort\n", __func__, node);
  164                 node = 0;
  165                 goto end;
  166         }
  167         if (strcmp("ports", name) == 0)
  168                 node = OF_parent(node);
  169 
  170 end:
  171         free(name, M_OFWPROP);
  172         return (node);
  173 }
  174 
  175 device_t
  176 ofw_graph_get_device_by_port_ep(phandle_t node, uint32_t port_id, uint32_t ep_id)
  177 {
  178         phandle_t outport, port, endpoint, remote;
  179 
  180         port = ofw_graph_get_port_by_idx(node, port_id);
  181         if (port == 0)
  182                 return (NULL);
  183         endpoint = ofw_graph_get_endpoint_by_idx(port, ep_id);
  184         if (endpoint == 0)
  185                 return NULL;
  186         remote = ofw_graph_get_remote_endpoint(endpoint);
  187         if (remote == 0)
  188                 return (NULL);
  189         outport = ofw_graph_get_remote_parent(remote);
  190         if (outport == 0)
  191                 return (NULL);
  192 
  193         return (OF_device_from_xref(OF_xref_from_node(outport)));
  194 }

Cache object: 93609772d64f2944f229e7a06f4a8390


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