opl_hostbridge.c revision 724365f7556fc4201fdb11766ebc6bd918523130
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/*
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * Use is subject to license terms.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston#pragma ident "%Z%%M% %I% %E% SMI"
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston#include <string.h>
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston#include <strings.h>
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston#include <libdevinfo.h>
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston#include <fm/topo_mod.h>
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston#include <sys/fm/protocol.h>
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston#include "opl_topo.h"
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston/*
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * Check the root complex device node for a slot-names property.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chuestonconst char *
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chuestonopl_get_slot_name(di_node_t n)
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston{
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston di_prom_prop_t pp = DI_PROM_PROP_NIL;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston uchar_t *buf;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston for (pp = di_prom_prop_next(opl_promtree, n, pp);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston pp != DI_PROM_PROP_NIL;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston pp = di_prom_prop_next(opl_promtree, 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 int err;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston tnode_t *node;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston nvlist_t *fmri;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston nvlist_t *args = NULL;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston nvlist_t *pfmri = NULL;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston topo_hdl_t *thp = topo_mod_handle(mp);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (parent == NULL || inst < 0) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (NULL);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* Get parent FMRI */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston (void) topo_node_resource(parent, &pfmri, &err);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (pfmri != NULL) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (topo_mod_nvalloc(mp, &args, NV_UNIQUE_NAME) != 0 ||
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston nvlist_add_nvlist(args, TOPO_METH_FMRI_ARG_PARENT, pfmri)
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston != 0) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston nvlist_free(pfmri);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston nvlist_free(args);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston (void) topo_mod_seterrno(mp, EMOD_FMRI_NVL);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (NULL);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston nvlist_free(pfmri);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* Create FMRI */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if ((fmri = topo_fmri_create(thp, FM_FMRI_SCHEME_HC, name, inst,
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston args, &err)) == NULL) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston topo_mod_dprintf(mp, "create of tnode for %s failed: %s",
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston name, topo_strerror(topo_mod_errno(mp)));
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston (void) topo_mod_seterrno(mp, err);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston nvlist_free(args);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (NULL);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston nvlist_free(args);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* Create and bind node */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston node = topo_node_bind(mp, parent, name, inst, fmri, priv);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (node == NULL) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston nvlist_free(fmri);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston topo_mod_dprintf(mp, "unable to bind root complex",
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston topo_strerror(topo_mod_errno(mp)));
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (NULL); /* mod_errno already set */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston nvlist_free(fmri);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston return (node);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston}
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston/*
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston * Create a root complex node.
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chuestonstatic tnode_t *
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chuestonopl_rc_node_create(topo_mod_t *mp, tnode_t *parent, di_node_t dnode, int inst,
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston void *priv)
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston{
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston int err;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston tnode_t *rcn;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston topo_hdl_t *thp = topo_mod_handle(mp);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston const char *slot_name;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston rcn = opl_node_create(mp, parent, PCIEXRC, inst, priv);
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 */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston slot_name = opl_get_slot_name(dnode);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (slot_name) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston char fru_str[64];
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston nvlist_t *fru_fmri;
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* Add FRU fmri */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston snprintf(fru_str, sizeof (fru_str), "hc:///component=%s",
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston slot_name);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (topo_fmri_str2nvl(thp, fru_str, &fru_fmri, &err) == 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 }
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston /* Make room for children */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston 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 */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston topo_node_range_create(mp, hbn, PCIEXRC, 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,
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston 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. */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston pcimod = topo_mod_load(mp, PCI_MOD_PATH);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (pcimod == NULL) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston topo_mod_dprintf(mp, "can't load pcibus module",
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,
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston "unable to create hbnode: %s",
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 */
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston rcnode = opl_rc_node_create(mp, hbnode, p, rc, p);
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston if (rcnode == NULL) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston topo_mod_dprintf(mp,
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston "unable to create rcnode: %s",
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,
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston PCI_BUS, PCIEX_BUS, 0, 255) != 0) {
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston topo_mod_dprintf(mp,
0b6016e6ff70af39f99c9cc28e0c2207c8f5413chueston "error enumerating pcibus",
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}