fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro/*
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * CDDL HEADER START
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro *
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * The contents of this file are subject to the terms of the
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * Common Development and Distribution License (the "License").
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * You may not use this file except in compliance with the License.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro *
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * or http://www.opensolaris.org/os/licensing.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * See the License for the specific language governing permissions
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * and limitations under the License.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro *
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * When distributing Covered Code, include this CDDL HEADER in each
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * If applicable, add the following below this CDDL HEADER, with the
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * fields enclosed by brackets "[]" replaced with your own identifying
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * information: Portions Copyright [yyyy] [name of copyright owner]
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro *
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * CDDL HEADER END
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro/*
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * Use is subject to license terms.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#include <stdio.h>
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#include <string.h>
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#include <stdlib.h>
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#include <unistd.h>
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#include <sys/types.h>
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#include <alloca.h>
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#include <sys/stat.h>
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#include <malloc.h>
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#include <fcntl.h>
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#include <syslog.h>
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#include <string.h>
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#include <errno.h>
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#include <sys/mdesc.h>
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#include <sys/mdesc_impl.h>
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#include <libdevinfo.h>
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#include "ldma.h"
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#include "mdesc_mutable.h"
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic int get_devinfo(uint8_t **mdpp, size_t *size);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic boolean_t is_root_complex(di_prom_handle_t ph, di_node_t di);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic md_node_t *link_device_node(mmd_t *mdp,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro di_prom_handle_t ph, di_node_t di, md_node_t *node, char *path);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic int create_children(mmd_t *mdp,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro di_prom_handle_t ph, md_node_t *node, di_node_t parent);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic int create_peers(mmd_t *mdp,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro di_prom_handle_t ph, md_node_t *node, di_node_t dev);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic int device_tree_to_md(mmd_t *mdp, md_node_t *top);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#define PCIEX "pciex"
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#define LDMA_MODULE LDMA_NAME_DIO
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro/* System Info version supported (only version 1.0) */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic ds_ver_t ldma_dio_vers[] = { {1, 0} };
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#define LDMA_DIO_NVERS (sizeof (ldma_dio_vers) / sizeof (ds_ver_t))
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#define LDMA_DIO_NHANDLERS (sizeof (ldma_dio_handlers) / \
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro sizeof (ldma_msg_handler_t))
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic ldm_msg_func_t ldma_dio_pcidev_info_handler;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic ldma_msg_handler_t ldma_dio_handlers[] = {
82629e3015252bf18319ba3815c773df23e21436Mike Christensen {MSGDIO_PCIDEV_INFO, LDMA_MSGFLG_ACCESS_CONTROL,
82629e3015252bf18319ba3815c773df23e21436Mike Christensen ldma_dio_pcidev_info_handler },
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro};
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloroldma_agent_info_t ldma_dio_info = {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro LDMA_NAME_DIO,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro ldma_dio_vers, LDMA_DIO_NVERS,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro ldma_dio_handlers, LDMA_DIO_NHANDLERS
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro};
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro/* ARGSUSED */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic ldma_request_status_t
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloroldma_dio_pcidev_info_handler(ds_ver_t *ver, ldma_message_header_t *request,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro size_t request_dlen, ldma_message_header_t **replyp, size_t *reply_dlenp)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro{
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro ldma_message_header_t *reply;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro char *data;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro uint8_t *md_bufp = NULL;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro size_t md_size;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro int rv;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro LDMA_DBG("%s: PCI device info request", __func__);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro rv = get_devinfo(&md_bufp, &md_size);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (rv != 0) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro LDMA_ERR("Failed to generate devinfo MD");
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (LDMA_REQ_FAILED);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro reply = ldma_alloc_result_msg(request, md_size);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (reply == NULL) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro LDMA_ERR("Memory allocation failure");
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro free(md_bufp);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (LDMA_REQ_FAILED);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro reply->msg_info = md_size;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro data = LDMA_HDR2DATA(reply);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro (void) memcpy(data, md_bufp, md_size);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro *replyp = reply;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro *reply_dlenp = md_size;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro free(md_bufp);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro LDMA_DBG("%s: sending PCI device info", __func__);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (LDMA_REQ_COMPLETED);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro}
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic boolean_t
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorois_root_complex(di_prom_handle_t ph, di_node_t di)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro{
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro int len;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro char *type;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro len = di_prom_prop_lookup_strings(ph, di, "device_type", &type);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if ((len == 0) || (type == NULL))
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (B_FALSE);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (strcmp(type, PCIEX) != 0)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (B_FALSE);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro /*
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * A root complex node is directly under the root node. So, if
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * 'di' is not the root node, and its parent has no parent,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * then 'di' represents a root complex node.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return ((di_parent_node(di) != DI_NODE_NIL) &&
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro (di_parent_node(di_parent_node(di)) == DI_NODE_NIL));
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro}
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro/*
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * String properties in the prom can contain multiple null-terminated
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * strings which are concatenated together. We must represent them in
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * an MD as a data property. This function retrieves such a property
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * and adds it to the MD. If the 'alt_name' PROM property exists then
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * the MD property is created with the value of the PROM 'alt_name'
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * property, otherwise it is created with the value of the PROM 'name'
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * property.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic int
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloroadd_prom_string_prop(di_prom_handle_t ph,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro mmd_t *mdp, md_node_t *np, di_node_t di, char *name, char *alt_name)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro{
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro int count;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro char *pp_data = NULL;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro char *str;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro int rv = 0;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (alt_name != NULL) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro count = di_prom_prop_lookup_strings(ph, di, alt_name, &pp_data);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (pp_data == NULL) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro count = di_prom_prop_lookup_strings(ph, di, name, &pp_data);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (count > 0 && pp_data != NULL) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro for (str = pp_data; count > 0; str += strlen(str) + 1)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro count--;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro rv = md_add_data_property(mdp,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro np, name, str - pp_data, (uint8_t *)pp_data);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (rv);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro}
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro/*
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * Add an int property 'name' to an MD from an existing PROM property. If
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * the 'alt_name' PROM property exists then the MD property is created with
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * the value of the PROM 'alt_name' property, otherwise it is created with
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * the value of the PROM 'name' property.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic int
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloroadd_prom_int_prop(di_prom_handle_t ph,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro mmd_t *mdp, md_node_t *np, di_node_t di, char *name, char *alt_name)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro{
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro int count;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro int rv = 0;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro int *pp_data = NULL;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (alt_name != NULL) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro count = di_prom_prop_lookup_ints(ph, di, alt_name, &pp_data);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (pp_data == NULL) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro count = di_prom_prop_lookup_ints(ph, di, name, &pp_data);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro /*
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * Note: We know that the properties of interest contain a
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * a single int.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (count > 0 && pp_data != NULL) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro ASSERT(count == 1);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro rv = md_add_value_property(mdp, np, name, *pp_data);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (rv);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro}
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic md_node_t *
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorolink_device_node(mmd_t *mdp,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro di_prom_handle_t ph, di_node_t di, md_node_t *node, char *path)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro{
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro md_node_t *np;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro np = md_link_new_node(mdp, "iodevice", node, "fwd", "back");
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (np == NULL)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (NULL);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro /* Add the properties from the devinfo node. */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (md_add_string_property(mdp, np, "dev_path", path) != 0)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro goto fail;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro /* Add the required properties for this node. */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (add_prom_string_prop(ph, mdp, np, di, "device_type", NULL) != 0)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro goto fail;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (add_prom_string_prop(ph, mdp, np, di, "compatible", NULL) != 0)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro goto fail;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (add_prom_int_prop(ph,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro mdp, np, di, "device-id", "real-device-id") != 0)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro goto fail;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (add_prom_int_prop(ph,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro mdp, np, di, "vendor-id", "real-vendor-id") != 0)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro goto fail;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (add_prom_int_prop(ph,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro mdp, np, di, "class-code", "real-class-code") != 0)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro goto fail;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (np);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorofail:
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro md_free_node(mdp, np);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (NULL);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro}
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic int
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorocreate_children(mmd_t *mdp,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro di_prom_handle_t ph, md_node_t *md_parent, di_node_t di_parent)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro{
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro md_node_t *md_node;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro md_node_t *md_child;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro di_node_t di_child;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro char *path;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro int rv;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro path = di_devfs_path(di_parent);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (path == NULL)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (EIO);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro md_node = link_device_node(mdp, ph, di_parent, md_parent, path);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro di_devfs_path_free(path);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (md_node == NULL) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (ENOMEM);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro while ((di_child = di_child_node(di_parent)) != DI_NODE_NIL) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro path = di_devfs_path(di_child);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (path != NULL) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro md_child = link_device_node(mdp,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro ph, di_child, md_node, path);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro di_devfs_path_free(path);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (md_child == NULL) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (ENOMEM);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro rv = create_peers(mdp, ph, md_node, di_child);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (rv != 0)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (rv);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro md_node = md_child;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro di_parent = di_child;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (0);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro}
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic int
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorocreate_peers(mmd_t *mdp, di_prom_handle_t ph, md_node_t *node, di_node_t dev)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro{
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro di_node_t di_peer;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro int rv;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro while ((di_peer = di_sibling_node(dev)) != DI_NODE_NIL) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro rv = create_children(mdp, ph, node, di_peer);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (rv != 0)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (rv);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro dev = di_peer;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (0);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro}
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic int
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorodevice_tree_to_md(mmd_t *mdp, md_node_t *top)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro{
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro di_node_t node;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro di_node_t root;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro di_prom_handle_t ph;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro int rv = 0;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro root = di_init("/", DINFOSUBTREE | DINFOPROP);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (root == DI_NODE_NIL) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro LDMA_ERR("di_init cannot find device tree root node.");
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (errno);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro ph = di_prom_init();
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (ph == DI_PROM_HANDLE_NIL) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro LDMA_ERR("di_prom_init failed.");
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro di_fini(root);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (errno);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro node = di_child_node(root);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro while (node != NULL) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (is_root_complex(ph, node)) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro rv = create_children(mdp, ph, top, node);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (rv != 0)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro break;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro node = di_sibling_node(node);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro di_prom_fini(ph);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro di_fini(root);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (rv);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro}
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic int
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloroget_devinfo(uint8_t **mdpp, size_t *size)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro{
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro mmd_t *mdp;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro md_node_t *rootp;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro size_t md_size;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro uint8_t *md_bufp;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro mdp = md_new_md();
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (mdp == NULL) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (ENOMEM);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro rootp = md_new_node(mdp, "root");
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (rootp == NULL) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro md_destroy(mdp);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (ENOMEM);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (device_tree_to_md(mdp, rootp) != 0) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro md_destroy(mdp);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (ENOMEM);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro md_size = (int)md_gen_bin(mdp, &md_bufp);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (md_size == 0) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro md_destroy(mdp);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (EIO);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro *mdpp = md_bufp;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro *size = md_size;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro md_destroy(mdp);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (0);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro}