0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston/*
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * CDDL HEADER START
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston *
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * The contents of this file are subject to the terms of the
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * Common Development and Distribution License (the "License").
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * You may not use this file except in compliance with the License.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston *
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * or http://www.opensolaris.org/os/licensing.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * See the License for the specific language governing permissions
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * and limitations under the License.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston *
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * When distributing Covered Code, include this CDDL HEADER in each
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * If applicable, add the following below this CDDL HEADER, with the
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * fields enclosed by brackets "[]" replaced with your own identifying
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * information: Portions Copyright [yyyy] [name of copyright owner]
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston *
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * CDDL HEADER END
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston/*
186d582bd9dbcd38e0aeea49036d47d3426a3536Surya Prakki * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * Use is subject to license terms.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston#include <string.h>
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston#include <strings.h>
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston#include <libdevinfo.h>
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston#include <fm/topo_mod.h>
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi#include <fm/topo_hc.h>
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston#include <sys/fm/protocol.h>
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston#include "opl_topo.h"
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0eb822a1c0c2bea495647510b75f77f0e57633ebcindistatic const topo_pgroup_info_t io_pgroup =
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi { TOPO_PGROUP_IO, TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
0eb822a1c0c2bea495647510b75f77f0e57633ebcindistatic const topo_pgroup_info_t pci_pgroup =
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi { TOPO_PGROUP_PCI, TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
23a276b1252962c987a613be470dde26561247b8hueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston/*
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * Check the root complex device node for a slot-names property.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chuestonconst char *
0eb822a1c0c2bea495647510b75f77f0e57633ebcindiopl_get_slot_name(topo_mod_t *mod, di_node_t n)
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston{
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi di_prom_handle_t ptp = DI_PROM_HANDLE_NIL;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston di_prom_prop_t pp = DI_PROM_PROP_NIL;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston uchar_t *buf;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if ((ptp = topo_mod_prominfo(mod)) == DI_PROM_PROP_NIL)
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi return (NULL);
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi for (pp = di_prom_prop_next(ptp, n, pp);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston pp != DI_PROM_PROP_NIL;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi pp = di_prom_prop_next(ptp, n, pp)) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (strcmp(di_prom_prop_name(pp), OPL_SLOT_NAMES) == 0) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (di_prom_prop_data(pp, &buf) <= sizeof (uint32_t))
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston continue;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return ((const char *)&buf[4]);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (NULL);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston}
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chuestonstatic tnode_t *
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chuestonopl_node_create(topo_mod_t *mp, tnode_t *parent, const char *name, int inst,
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston void *priv)
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston{
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston tnode_t *node;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston nvlist_t *fmri;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi nvlist_t *auth = topo_mod_auth(mp, parent);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (parent == NULL || inst < 0) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (NULL);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* Create FMRI */
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if ((fmri = topo_mod_hcfmri(mp, parent, FM_HC_SCHEME_VERSION, name,
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi inst, NULL, auth, NULL, NULL, NULL)) == NULL) {
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi topo_mod_dprintf(mp, "create of tnode for %s failed: %s",
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston name, topo_strerror(topo_mod_errno(mp)));
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi nvlist_free(auth);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (NULL);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi nvlist_free(auth);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* Create and bind node */
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi node = topo_node_bind(mp, parent, name, inst, fmri);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (node == NULL) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston nvlist_free(fmri);
23a276b1252962c987a613be470dde26561247b8hueston topo_mod_dprintf(mp, "unable to bind root complex: %s\n",
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston topo_strerror(topo_mod_errno(mp)));
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (NULL); /* mod_errno already set */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston nvlist_free(fmri);
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi topo_node_setspecific(node, priv);
23a276b1252962c987a613be470dde26561247b8hueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (node);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston}
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston/*
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * Create a root complex node.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chuestonstatic tnode_t *
0eb822a1c0c2bea495647510b75f77f0e57633ebcindiopl_rc_node_create(topo_mod_t *mp, tnode_t *parent, di_node_t dnode, int inst)
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston{
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston int err;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston tnode_t *rcn;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston const char *slot_name;
23a276b1252962c987a613be470dde26561247b8hueston char *dnpath;
9dd0f810214fdc8e1af881a9a5c4b6927629ff9ecindi nvlist_t *mod;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi rcn = opl_node_create(mp, parent, PCIEX_ROOT, inst, (void *)dnode);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (rcn == NULL) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (NULL);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /*
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * If this root complex connects to a slot, it will have a
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * slot-names property.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston */
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi slot_name = opl_get_slot_name(mp, dnode);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (slot_name) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston char fru_str[64];
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston nvlist_t *fru_fmri;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* Add FRU fmri */
92ba710950bf6ee35de67e1e0b7f20ec9e528106eschrock (void) snprintf(fru_str, sizeof (fru_str), "hc:///component=%s",
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston slot_name);
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if (topo_mod_str2nvl(mp, fru_str, &fru_fmri) == 0) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston (void) topo_node_fru_set(rcn, fru_fmri, 0, &err);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston nvlist_free(fru_fmri);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* Add label */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston (void) topo_node_label_set(rcn, (char *)slot_name, &err);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston } else {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* Inherit parent FRU's label */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston (void) topo_node_fru_set(rcn, NULL, 0, &err);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston (void) topo_node_label_set(rcn, NULL, &err);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
23a276b1252962c987a613be470dde26561247b8hueston
23a276b1252962c987a613be470dde26561247b8hueston /*
23a276b1252962c987a613be470dde26561247b8hueston * Set ASRU to be the dev-scheme ASRU
23a276b1252962c987a613be470dde26561247b8hueston */
23a276b1252962c987a613be470dde26561247b8hueston if ((dnpath = di_devfs_path(dnode)) != NULL) {
23a276b1252962c987a613be470dde26561247b8hueston nvlist_t *fmri;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi fmri = topo_mod_devfmri(mp, FM_DEV_SCHEME_VERSION,
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi dnpath, NULL);
23a276b1252962c987a613be470dde26561247b8hueston if (fmri == NULL) {
23a276b1252962c987a613be470dde26561247b8hueston topo_mod_dprintf(mp,
23a276b1252962c987a613be470dde26561247b8hueston "dev:///%s fmri creation failed.\n",
23a276b1252962c987a613be470dde26561247b8hueston dnpath);
186d582bd9dbcd38e0aeea49036d47d3426a3536Surya Prakki (void) topo_mod_seterrno(mp, err);
23a276b1252962c987a613be470dde26561247b8hueston di_devfs_path_free(dnpath);
23a276b1252962c987a613be470dde26561247b8hueston return (NULL);
23a276b1252962c987a613be470dde26561247b8hueston }
23a276b1252962c987a613be470dde26561247b8hueston if (topo_node_asru_set(rcn, fmri, 0, &err) < 0) {
23a276b1252962c987a613be470dde26561247b8hueston topo_mod_dprintf(mp, "topo_node_asru_set failed\n");
186d582bd9dbcd38e0aeea49036d47d3426a3536Surya Prakki (void) topo_mod_seterrno(mp, err);
23a276b1252962c987a613be470dde26561247b8hueston nvlist_free(fmri);
23a276b1252962c987a613be470dde26561247b8hueston di_devfs_path_free(dnpath);
23a276b1252962c987a613be470dde26561247b8hueston return (NULL);
23a276b1252962c987a613be470dde26561247b8hueston }
23a276b1252962c987a613be470dde26561247b8hueston nvlist_free(fmri);
23a276b1252962c987a613be470dde26561247b8hueston } else {
23a276b1252962c987a613be470dde26561247b8hueston topo_mod_dprintf(mp, "NULL di_devfs_path.\n");
23a276b1252962c987a613be470dde26561247b8hueston }
23a276b1252962c987a613be470dde26561247b8hueston
23a276b1252962c987a613be470dde26561247b8hueston /*
23a276b1252962c987a613be470dde26561247b8hueston * Set pciexrc properties for root complex nodes
23a276b1252962c987a613be470dde26561247b8hueston */
23a276b1252962c987a613be470dde26561247b8hueston
23a276b1252962c987a613be470dde26561247b8hueston /* Add the io and pci property groups */
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if (topo_pgroup_create(rcn, &io_pgroup, &err) < 0) {
23a276b1252962c987a613be470dde26561247b8hueston topo_mod_dprintf(mp, "topo_pgroup_create failed\n");
23a276b1252962c987a613be470dde26561247b8hueston di_devfs_path_free(dnpath);
186d582bd9dbcd38e0aeea49036d47d3426a3536Surya Prakki (void) topo_mod_seterrno(mp, err);
23a276b1252962c987a613be470dde26561247b8hueston return (NULL);
23a276b1252962c987a613be470dde26561247b8hueston }
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if (topo_pgroup_create(rcn, &pci_pgroup, &err) < 0) {
23a276b1252962c987a613be470dde26561247b8hueston topo_mod_dprintf(mp, "topo_pgroup_create failed\n");
23a276b1252962c987a613be470dde26561247b8hueston di_devfs_path_free(dnpath);
186d582bd9dbcd38e0aeea49036d47d3426a3536Surya Prakki (void) topo_mod_seterrno(mp, err);
23a276b1252962c987a613be470dde26561247b8hueston return (NULL);
23a276b1252962c987a613be470dde26561247b8hueston }
23a276b1252962c987a613be470dde26561247b8hueston /* Add the devfs path property */
23a276b1252962c987a613be470dde26561247b8hueston if (dnpath) {
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if (topo_prop_set_string(rcn, TOPO_PGROUP_IO, TOPO_IO_DEV,
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi TOPO_PROP_IMMUTABLE, dnpath, &err) != 0) {
23a276b1252962c987a613be470dde26561247b8hueston topo_mod_dprintf(mp, "Failed to set DEV property\n");
23a276b1252962c987a613be470dde26561247b8hueston di_devfs_path_free(dnpath);
186d582bd9dbcd38e0aeea49036d47d3426a3536Surya Prakki (void) topo_mod_seterrno(mp, err);
23a276b1252962c987a613be470dde26561247b8hueston }
23a276b1252962c987a613be470dde26561247b8hueston di_devfs_path_free(dnpath);
23a276b1252962c987a613be470dde26561247b8hueston }
23a276b1252962c987a613be470dde26561247b8hueston /* Oberon device type is always "pciex" */
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if (topo_prop_set_string(rcn, TOPO_PGROUP_IO, TOPO_IO_DEVTYPE,
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi TOPO_PROP_IMMUTABLE, OPL_PX_DEVTYPE, &err) != 0) {
23a276b1252962c987a613be470dde26561247b8hueston topo_mod_dprintf(mp, "Failed to set DEVTYPE property\n");
23a276b1252962c987a613be470dde26561247b8hueston }
23a276b1252962c987a613be470dde26561247b8hueston /* Oberon driver is always "px" */
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if (topo_prop_set_string(rcn, TOPO_PGROUP_IO, TOPO_IO_DRIVER,
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi TOPO_PROP_IMMUTABLE, OPL_PX_DRV, &err) != 0) {
23a276b1252962c987a613be470dde26561247b8hueston topo_mod_dprintf(mp, "Failed to set DRIVER property\n");
23a276b1252962c987a613be470dde26561247b8hueston }
9dd0f810214fdc8e1af881a9a5c4b6927629ff9ecindi if ((mod = topo_mod_modfmri(mp, FM_MOD_SCHEME_VERSION, OPL_PX_DRV))
9dd0f810214fdc8e1af881a9a5c4b6927629ff9ecindi == NULL || topo_prop_set_fmri(rcn, TOPO_PGROUP_IO,
9dd0f810214fdc8e1af881a9a5c4b6927629ff9ecindi TOPO_IO_MODULE, TOPO_PROP_IMMUTABLE, mod, &err) != 0) {
9dd0f810214fdc8e1af881a9a5c4b6927629ff9ecindi topo_mod_dprintf(mp, "Failed to set MODULE property\n");
9dd0f810214fdc8e1af881a9a5c4b6927629ff9ecindi }
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(mod);
9dd0f810214fdc8e1af881a9a5c4b6927629ff9ecindi
23a276b1252962c987a613be470dde26561247b8hueston /* This is a PCIEX Root Complex */
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if (topo_prop_set_string(rcn, TOPO_PGROUP_PCI, TOPO_PCI_EXCAP,
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi TOPO_PROP_IMMUTABLE, PCIEX_ROOT, &err) != 0) {
23a276b1252962c987a613be470dde26561247b8hueston topo_mod_dprintf(mp, "Failed to set EXCAP property\n");
23a276b1252962c987a613be470dde26561247b8hueston }
23a276b1252962c987a613be470dde26561247b8hueston /* BDF of Oberon root complex is constant */
23a276b1252962c987a613be470dde26561247b8hueston if (topo_prop_set_string(rcn, TOPO_PGROUP_PCI,
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi TOPO_PCI_BDF, TOPO_PROP_IMMUTABLE, OPL_PX_BDF, &err) != 0) {
23a276b1252962c987a613be470dde26561247b8hueston topo_mod_dprintf(mp, "Failed to set EXCAP property\n");
23a276b1252962c987a613be470dde26561247b8hueston }
23a276b1252962c987a613be470dde26561247b8hueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* Make room for children */
186d582bd9dbcd38e0aeea49036d47d3426a3536Surya Prakki (void) topo_node_range_create(mp, rcn, PCIEX_BUS, 0, OPL_BUS_MAX);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (rcn);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston}
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston/*
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * Create a hostbridge node.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chuestonstatic tnode_t *
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chuestonopl_hb_node_create(topo_mod_t *mp, tnode_t *parent, int inst)
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston{
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston int err;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston tnode_t *hbn;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston hbn = opl_node_create(mp, parent, HOSTBRIDGE, inst, NULL);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (hbn == NULL) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (NULL);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* Inherit parent FRU's label */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston (void) topo_node_fru_set(hbn, NULL, 0, &err);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston (void) topo_node_label_set(hbn, NULL, &err);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* Make room for children */
186d582bd9dbcd38e0aeea49036d47d3426a3536Surya Prakki (void) topo_node_range_create(mp, hbn, PCIEX_ROOT, 0, OPL_RC_MAX);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (hbn);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston}
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston/*
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * opl_hb_enum gets the ioboard instance passed in, and determines the
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * hostbridge and root complex instances numbers based on the bus addresses.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chuestonint
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chuestonopl_hb_enum(topo_mod_t *mp, const ioboard_contents_t *iob, tnode_t *ion,
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi int brd)
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston{
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston int hb;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston int rc;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston di_node_t p;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston tnode_t *hbnode;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston tnode_t *rcnode;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston topo_mod_t *pcimod;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* Load the pcibus module. We'll need it later. */
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi pcimod = topo_mod_load(mp, PCI_BUS, PCI_BUS_VERS);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (pcimod == NULL) {
23a276b1252962c987a613be470dde26561247b8hueston topo_mod_dprintf(mp, "can't load pcibus module: %s\n",
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston topo_strerror(topo_mod_errno(mp)));
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (-1);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* For each hostbridge on an ioboard... */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston for (hb = 0; hb < OPL_HB_MAX; hb++) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston hbnode = NULL;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* For each root complex in a hostbridge... */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston for (rc = 0; rc < OPL_RC_MAX; rc++) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston p = iob->rcs[hb][rc];
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* If no root complex, continue */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (p == DI_NODE_NIL) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston continue;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* The root complex exists! */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston topo_mod_dprintf(mp, "declaring "
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston "/chassis=0/ioboard=%d/hostbridge=%d/pciexrc=%d\n",
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston brd, hb, rc);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /*
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * If we haven't created a hostbridge node yet, do it
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * now.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (hbnode == NULL) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston hbnode = opl_hb_node_create(mp, ion, hb);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (hbnode == NULL) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston topo_mod_dprintf(mp,
23a276b1252962c987a613be470dde26561247b8hueston "unable to create hbnode: %s\n",
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston topo_strerror(topo_mod_errno(mp)));
724365f7556fc4201fdb11766ebc6bd918523130sethg topo_mod_unload(pcimod);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (-1);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* Create the root complex node */
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi rcnode = opl_rc_node_create(mp, hbnode, p, rc);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (rcnode == NULL) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston topo_mod_dprintf(mp,
23a276b1252962c987a613be470dde26561247b8hueston "unable to create rcnode: %s\n",
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston topo_strerror(topo_mod_errno(mp)));
724365f7556fc4201fdb11766ebc6bd918523130sethg topo_mod_unload(pcimod);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (-1);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* Enumerate pcibus nodes under the root complex */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (topo_mod_enumerate(pcimod, rcnode,
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi PCI_BUS, PCIEX_BUS, 0, 255, NULL) != 0) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston topo_mod_dprintf(mp,
23a276b1252962c987a613be470dde26561247b8hueston "error enumerating pcibus: %s\n",
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston topo_strerror(topo_mod_errno(mp)));
724365f7556fc4201fdb11766ebc6bd918523130sethg topo_mod_unload(pcimod);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (-1);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
724365f7556fc4201fdb11766ebc6bd918523130sethg topo_mod_unload(pcimod);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (0);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston}