7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * CDDL HEADER START
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * The contents of this file are subject to the terms of the
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Common Development and Distribution License (the "License").
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * You may not use this file except in compliance with the License.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * or http://www.opensolaris.org/os/licensing.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * See the License for the specific language governing permissions
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * and limitations under the License.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * When distributing Covered Code, include this CDDL HEADER in each
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * If applicable, add the following below this CDDL HEADER, with the
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * fields enclosed by brackets "[]" replaced with your own identifying
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * information: Portions Copyright [yyyy] [name of copyright owner]
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * CDDL HEADER END
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
12cc75c814f0c017004a9bbc96429911e008601bcindi * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Use is subject to license terms.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#pragma ident "%Z%%M% %I% %E% SMI"
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <string.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <fm/topo_mod.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <libdevinfo.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/param.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/systeminfo.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi#include <hb_sun4.h>
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi#include <util.h>
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi#include <hostbridge.h>
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi#include <pcibus.h>
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi#include <did.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindibusorrc_t *
0eb822a1c0c2bea495647510b75f77f0e57633ebcindibusorrc_new(topo_mod_t *mod, const char *bus_addr, di_node_t di)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi busorrc_t *pp;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi char *comma;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi char *bac;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi int e;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
724365f7556fc4201fdb11766ebc6bd918523130sethg if ((pp = topo_mod_zalloc(mod, sizeof (busorrc_t))) == NULL)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (NULL);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi pp->br_din = di;
724365f7556fc4201fdb11766ebc6bd918523130sethg bac = topo_mod_strdup(mod, bus_addr);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if ((comma = strchr(bac, ',')) != NULL)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *comma = '\0';
724365f7556fc4201fdb11766ebc6bd918523130sethg pp->br_ba_bc = strtonum(mod, bac, &e);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (e < 0) {
724365f7556fc4201fdb11766ebc6bd918523130sethg topo_mod_dprintf(mod,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "Trouble interpreting bus_addr before comma.\n");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (comma != NULL)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *comma = ',';
724365f7556fc4201fdb11766ebc6bd918523130sethg topo_mod_strfree(mod, bac);
724365f7556fc4201fdb11766ebc6bd918523130sethg topo_mod_free(mod, pp, sizeof (busorrc_t));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (NULL);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (comma == NULL) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi pp->br_ba_ac = 0;
724365f7556fc4201fdb11766ebc6bd918523130sethg topo_mod_strfree(mod, bac);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (pp);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
724365f7556fc4201fdb11766ebc6bd918523130sethg pp->br_ba_ac = strtonum(mod, comma + 1, &e);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (e < 0) {
724365f7556fc4201fdb11766ebc6bd918523130sethg topo_mod_dprintf(mod,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "Trouble interpreting bus_addr after comma.\n");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *comma = ',';
724365f7556fc4201fdb11766ebc6bd918523130sethg topo_mod_strfree(mod, bac);
724365f7556fc4201fdb11766ebc6bd918523130sethg topo_mod_free(mod, pp, sizeof (busorrc_t));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (NULL);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *comma = ',';
724365f7556fc4201fdb11766ebc6bd918523130sethg topo_mod_strfree(mod, bac);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (pp);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindivoid
0eb822a1c0c2bea495647510b75f77f0e57633ebcindibusorrc_insert(topo_mod_t *mod, busorrc_t **head, busorrc_t *new)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi busorrc_t *ppci, *pci;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
724365f7556fc4201fdb11766ebc6bd918523130sethg topo_mod_dprintf(mod,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "inserting (%x,%x)\n", new->br_ba_bc, new->br_ba_ac);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /* No entries yet? */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (*head == NULL) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *head = new;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi ppci = NULL;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi pci = *head;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi while (pci != NULL) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (new->br_ba_ac == pci->br_ba_ac)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (new->br_ba_bc < pci->br_ba_bc)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi break;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (new->br_ba_ac < pci->br_ba_ac)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi break;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi ppci = pci;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi pci = pci->br_nextbus;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (ppci == NULL) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi new->br_nextbus = pci;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi pci->br_prevbus = new;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *head = new;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi } else {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi new->br_nextbus = ppci->br_nextbus;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (new->br_nextbus != NULL)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi new->br_nextbus->br_prevbus = new;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi ppci->br_nextbus = new;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi new->br_prevbus = ppci;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiint
0eb822a1c0c2bea495647510b75f77f0e57633ebcindibusorrc_add(topo_mod_t *mod, busorrc_t **list, di_node_t n)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi busorrc_t *nb;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi char *ba;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
724365f7556fc4201fdb11766ebc6bd918523130sethg topo_mod_dprintf(mod, "busorrc_add\n");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi ba = di_bus_addr(n);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (ba == NULL ||
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi (nb = busorrc_new(mod, ba, n)) == NULL) {
724365f7556fc4201fdb11766ebc6bd918523130sethg topo_mod_dprintf(mod, "busorrc_new() failed.\n");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (-1);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi busorrc_insert(mod, list, nb);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (0);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindivoid
0eb822a1c0c2bea495647510b75f77f0e57633ebcindibusorrc_free(topo_mod_t *mod, busorrc_t *pb)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (pb == NULL)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return;
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi busorrc_free(mod, pb->br_nextbus);
724365f7556fc4201fdb11766ebc6bd918523130sethg topo_mod_free(mod, pb, sizeof (busorrc_t));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecinditnode_t *
0eb822a1c0c2bea495647510b75f77f0e57633ebcindihb_process(topo_mod_t *mod, tnode_t *ptn, topo_instance_t hbi,
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi topo_instance_t bi, di_node_t bn, did_t *hbdid)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi tnode_t *hb;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if ((hb = pcihostbridge_declare(mod, ptn, bn, hbi)) == NULL)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (NULL);
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if (topo_mod_enumerate(mod, hb, PCI_BUS, PCI_BUS, bi, bi, hbdid) == 0)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (hb);
12cc75c814f0c017004a9bbc96429911e008601bcindi
12cc75c814f0c017004a9bbc96429911e008601bcindi topo_node_unbind(hb);
12cc75c814f0c017004a9bbc96429911e008601bcindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (NULL);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecinditnode_t *
0eb822a1c0c2bea495647510b75f77f0e57633ebcindirc_process(topo_mod_t *mod, tnode_t *ptn, topo_instance_t rci, di_node_t bn)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi tnode_t *rc;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if ((rc = pciexrc_declare(mod, ptn, bn, rci)) == NULL)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (NULL);
724365f7556fc4201fdb11766ebc6bd918523130sethg if (topo_mod_enumerate(mod,
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi rc, PCI_BUS, PCIEX_BUS, 0, MAX_HB_BUSES, NULL) == 0)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (rc);
12cc75c814f0c017004a9bbc96429911e008601bcindi
12cc75c814f0c017004a9bbc96429911e008601bcindi topo_node_unbind(rc);
12cc75c814f0c017004a9bbc96429911e008601bcindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (NULL);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * declare_exbuses() assumes the elements in the provided busorrc list
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * are sorted thusly:
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * (Hostbridge #0, Root Complex #0, ExBus #0)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * (Hostbridge #0, Root Complex #0, ExBus #1)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * ...
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * (Hostbridge #0, Root Complex #0, ExBus #(buses/rc))
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * (Hostbridge #0, Root Complex #1, ExBus #0)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * ...
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * (Hostbridge #0, Root Complex #1, ExBus #(buses/rc))
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * ...
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * ...
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * (Hostbridge #0, Root Complex #(rcs/hostbridge), ExBus #(buses/rc))
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * (Hostbridge #1, Root Complex #0, ExBus #0)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * ...
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * ...
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * ...
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * ...
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * (Hostbridge #nhb, Root Complex #(rcs/hostbridge), ExBus #(buses/rc))
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiint
0eb822a1c0c2bea495647510b75f77f0e57633ebcindideclare_exbuses(topo_mod_t *mod, busorrc_t *list, tnode_t *ptn, int nhb,
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi int nrc)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
12cc75c814f0c017004a9bbc96429911e008601bcindi int err = 0;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi tnode_t **rcs;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi tnode_t **hb;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi busorrc_t *p;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi int br, rc;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Allocate an array to point at the hostbridge tnode_t pointers.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
724365f7556fc4201fdb11766ebc6bd918523130sethg if ((hb = topo_mod_zalloc(mod, nhb * sizeof (tnode_t *))) == NULL)
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi return (topo_mod_seterrno(mod, EMOD_NOMEM));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Allocate an array to point at the root complex tnode_t pointers.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
12cc75c814f0c017004a9bbc96429911e008601bcindi if ((rcs = topo_mod_zalloc(mod, nrc * sizeof (tnode_t *))) == NULL) {
12cc75c814f0c017004a9bbc96429911e008601bcindi topo_mod_free(mod, hb, nhb * sizeof (tnode_t *));
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi return (topo_mod_seterrno(mod, EMOD_NOMEM));
12cc75c814f0c017004a9bbc96429911e008601bcindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi br = rc = 0;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi for (p = list; p != NULL; p = p->br_nextbus) {
724365f7556fc4201fdb11766ebc6bd918523130sethg topo_mod_dprintf(mod,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "declaring (%x,%x)\n", p->br_ba_bc, p->br_ba_ac);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
12cc75c814f0c017004a9bbc96429911e008601bcindi if (did_create(mod, p->br_din, 0, br, rc, rc) == NULL) {
12cc75c814f0c017004a9bbc96429911e008601bcindi err = -1;
12cc75c814f0c017004a9bbc96429911e008601bcindi break;
12cc75c814f0c017004a9bbc96429911e008601bcindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (hb[br] == NULL) {
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi hb[br] = pciexhostbridge_declare(mod, ptn, p->br_din,
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi br);
12cc75c814f0c017004a9bbc96429911e008601bcindi if (hb[br] == NULL) {
12cc75c814f0c017004a9bbc96429911e008601bcindi err = -1;
12cc75c814f0c017004a9bbc96429911e008601bcindi break;
12cc75c814f0c017004a9bbc96429911e008601bcindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (rcs[rc] == NULL) {
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi rcs[rc] = rc_process(mod, hb[br], rc, p->br_din);
12cc75c814f0c017004a9bbc96429911e008601bcindi if (rcs[rc] == NULL) {
12cc75c814f0c017004a9bbc96429911e008601bcindi err = -1;
12cc75c814f0c017004a9bbc96429911e008601bcindi break;
12cc75c814f0c017004a9bbc96429911e008601bcindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi } else {
724365f7556fc4201fdb11766ebc6bd918523130sethg if (topo_mod_enumerate(mod,
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi rcs[rc], PCI_BUS, PCIEX_BUS, 0, MAX_HB_BUSES,
12cc75c814f0c017004a9bbc96429911e008601bcindi NULL) < 0) {
12cc75c814f0c017004a9bbc96429911e008601bcindi err = -1;
12cc75c814f0c017004a9bbc96429911e008601bcindi break;
12cc75c814f0c017004a9bbc96429911e008601bcindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi rc++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (rc == nrc) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi rc = 0;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi br++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (br == nhb)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi br = 0;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
12cc75c814f0c017004a9bbc96429911e008601bcindi
12cc75c814f0c017004a9bbc96429911e008601bcindi if (err != 0) {
12cc75c814f0c017004a9bbc96429911e008601bcindi int i;
12cc75c814f0c017004a9bbc96429911e008601bcindi
12cc75c814f0c017004a9bbc96429911e008601bcindi for (i = 0; i < nhb; ++i)
12cc75c814f0c017004a9bbc96429911e008601bcindi topo_node_unbind(hb[br]);
12cc75c814f0c017004a9bbc96429911e008601bcindi for (i = 0; i < nrc; ++i)
12cc75c814f0c017004a9bbc96429911e008601bcindi topo_node_unbind(rcs[rc]);
12cc75c814f0c017004a9bbc96429911e008601bcindi }
12cc75c814f0c017004a9bbc96429911e008601bcindi
724365f7556fc4201fdb11766ebc6bd918523130sethg topo_mod_free(mod, rcs, nrc * sizeof (tnode_t *));
724365f7556fc4201fdb11766ebc6bd918523130sethg topo_mod_free(mod, hb, nhb * sizeof (tnode_t *));
12cc75c814f0c017004a9bbc96429911e008601bcindi
12cc75c814f0c017004a9bbc96429911e008601bcindi return (err);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * declare_buses() assumes the elements in the provided busorrc list
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * are sorted thusly:
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * (Hostbridge #0, Bus #0)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * (Hostbridge #1, Bus #0)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * ...
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * (Hostbridge #nhb, Bus #0)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * (Hostbridge #0, Bus #1)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * ...
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * ...
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * (Hostbridge #nhb, Bus #(buses/hostbridge))
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiint
0eb822a1c0c2bea495647510b75f77f0e57633ebcindideclare_buses(topo_mod_t *mod, busorrc_t *list, tnode_t *ptn, int nhb)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
12cc75c814f0c017004a9bbc96429911e008601bcindi int err = 0;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi busorrc_t *p;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi tnode_t **hb;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi did_t *link;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi int br, bus;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Allocate an array to point at the hostbridge tnode_t pointers.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
724365f7556fc4201fdb11766ebc6bd918523130sethg if ((hb = topo_mod_zalloc(mod, nhb * sizeof (tnode_t *))) == NULL)
724365f7556fc4201fdb11766ebc6bd918523130sethg return (topo_mod_seterrno(mod, EMOD_NOMEM));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi br = bus = 0;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi for (p = list; p != NULL; p = p->br_nextbus) {
724365f7556fc4201fdb11766ebc6bd918523130sethg topo_mod_dprintf(mod,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "declaring (%x,%x)\n", p->br_ba_bc, p->br_ba_ac);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if ((link =
12cc75c814f0c017004a9bbc96429911e008601bcindi did_create(mod, p->br_din, 0, br, NO_RC, bus)) == NULL) {
12cc75c814f0c017004a9bbc96429911e008601bcindi err = -1;
12cc75c814f0c017004a9bbc96429911e008601bcindi break;
12cc75c814f0c017004a9bbc96429911e008601bcindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (hb[br] == NULL) {
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi hb[br] = hb_process(mod, ptn, br, bus, p->br_din, link);
12cc75c814f0c017004a9bbc96429911e008601bcindi if (hb[br] == NULL) {
12cc75c814f0c017004a9bbc96429911e008601bcindi err = -1;
12cc75c814f0c017004a9bbc96429911e008601bcindi break;
12cc75c814f0c017004a9bbc96429911e008601bcindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi } else {
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi did_link_set(mod, hb[br], link);
724365f7556fc4201fdb11766ebc6bd918523130sethg if (topo_mod_enumerate(mod,
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi hb[br], PCI_BUS, PCI_BUS, bus, bus, link) < 0) {
12cc75c814f0c017004a9bbc96429911e008601bcindi err = -1;
12cc75c814f0c017004a9bbc96429911e008601bcindi break;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi br++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (br == nhb) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi br = 0;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi bus++;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
12cc75c814f0c017004a9bbc96429911e008601bcindi
12cc75c814f0c017004a9bbc96429911e008601bcindi if (err != 0) {
12cc75c814f0c017004a9bbc96429911e008601bcindi int i;
12cc75c814f0c017004a9bbc96429911e008601bcindi
12cc75c814f0c017004a9bbc96429911e008601bcindi for (i = 0; i < nhb; ++i)
12cc75c814f0c017004a9bbc96429911e008601bcindi topo_node_unbind(hb[br]);
12cc75c814f0c017004a9bbc96429911e008601bcindi }
12cc75c814f0c017004a9bbc96429911e008601bcindi
724365f7556fc4201fdb11766ebc6bd918523130sethg topo_mod_free(mod, hb, nhb * sizeof (tnode_t *));
12cc75c814f0c017004a9bbc96429911e008601bcindi return (err);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}