11414Scindi /*
21414Scindi * CDDL HEADER START
31414Scindi *
41414Scindi * The contents of this file are subject to the terms of the
51414Scindi * Common Development and Distribution License (the "License").
61414Scindi * You may not use this file except in compliance with the License.
71414Scindi *
81414Scindi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91414Scindi * or http://www.opensolaris.org/os/licensing.
101414Scindi * See the License for the specific language governing permissions
111414Scindi * and limitations under the License.
121414Scindi *
131414Scindi * When distributing Covered Code, include this CDDL HEADER in each
141414Scindi * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151414Scindi * If applicable, add the following below this CDDL HEADER, with the
161414Scindi * fields enclosed by brackets "[]" replaced with your own identifying
171414Scindi * information: Portions Copyright [yyyy] [name of copyright owner]
181414Scindi *
191414Scindi * CDDL HEADER END
201414Scindi */
211414Scindi
221414Scindi /*
23*10187SKrishna.Elango@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
241414Scindi * Use is subject to license terms.
251414Scindi */
261414Scindi
271414Scindi #include <fm/topo_mod.h>
283062Scindi #include <fm/topo_hc.h>
291414Scindi #include <libdevinfo.h>
301865Sdilpreet #include <strings.h>
313062Scindi #include <pcibus.h>
323062Scindi #include <hostbridge.h>
333062Scindi #include <did.h>
343062Scindi #include <util.h>
351414Scindi
361414Scindi static int
hb_process(topo_mod_t * mod,tnode_t * ptn,topo_instance_t hbi,di_node_t bn)373062Scindi hb_process(topo_mod_t *mod, tnode_t *ptn, topo_instance_t hbi, di_node_t bn)
381414Scindi {
391414Scindi tnode_t *hb;
403062Scindi did_t *hbdid;
411414Scindi
423062Scindi if ((hbdid = did_create(mod, bn, 0, hbi, NO_RC, TRUST_BDF)) == NULL)
431414Scindi return (-1);
443062Scindi if ((hb = pcihostbridge_declare(mod, ptn, bn, hbi)) == NULL)
451414Scindi return (-1);
464328Scindi if (topo_mod_enumerate(mod,
474328Scindi hb, PCI_BUS, PCI_BUS, 0, MAX_HB_BUSES, (void *)hbdid) < 0) {
484328Scindi topo_node_unbind(hb);
494328Scindi return (-1);
504328Scindi }
514328Scindi
524328Scindi return (0);
531414Scindi }
541414Scindi
551414Scindi static int
rc_process(topo_mod_t * mod,tnode_t * ptn,topo_instance_t hbi,di_node_t bn)563062Scindi rc_process(topo_mod_t *mod, tnode_t *ptn, topo_instance_t hbi, di_node_t bn)
571414Scindi {
581414Scindi tnode_t *hb;
591414Scindi tnode_t *rc;
603062Scindi did_t *hbdid;
611414Scindi
623062Scindi if ((hbdid = did_create(mod, bn, 0, hbi, hbi, TRUST_BDF)) == NULL)
631414Scindi return (-1);
643062Scindi if ((hb = pciexhostbridge_declare(mod, ptn, bn, hbi)) == NULL)
651414Scindi return (-1);
663062Scindi if ((rc = pciexrc_declare(mod, hb, bn, hbi)) == NULL)
672027Ssethg return (-1);
684328Scindi if (topo_mod_enumerate(mod,
694328Scindi rc, PCI_BUS, PCIEX_BUS, 0, MAX_HB_BUSES, (void *)hbdid) < 0) {
704328Scindi topo_node_unbind(hb);
714328Scindi topo_node_unbind(rc);
724328Scindi return (-1);
734328Scindi }
744328Scindi
754328Scindi return (0);
761414Scindi }
771414Scindi
781414Scindi
791414Scindi int
pci_hostbridges_find(topo_mod_t * mod,tnode_t * ptn)803062Scindi pci_hostbridges_find(topo_mod_t *mod, tnode_t *ptn)
811414Scindi {
821414Scindi di_node_t devtree;
833062Scindi di_node_t pnode, cnode;
841414Scindi int hbcnt = 0;
851414Scindi
861414Scindi /* Scan for buses, top-level devinfo nodes with the right driver */
873062Scindi devtree = topo_mod_devinfo(mod);
881414Scindi if (devtree == DI_NODE_NIL) {
892027Ssethg topo_mod_dprintf(mod, "devinfo init failed.");
901414Scindi topo_node_range_destroy(ptn, HOSTBRIDGE);
911414Scindi return (0);
921414Scindi }
931414Scindi
941865Sdilpreet pnode = di_drv_first_node(PCI, devtree);
951865Sdilpreet while (pnode != DI_NODE_NIL) {
964328Scindi if (hb_process(mod, ptn, hbcnt, pnode) < 0) {
974328Scindi if (hbcnt == 0)
984328Scindi topo_node_range_destroy(ptn, HOSTBRIDGE);
992027Ssethg return (topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM));
1001414Scindi }
1014328Scindi hbcnt++;
1021865Sdilpreet pnode = di_drv_next_node(pnode);
1031414Scindi }
1041414Scindi
1051414Scindi pnode = di_drv_first_node(NPE, devtree);
1061414Scindi while (pnode != DI_NODE_NIL) {
1071865Sdilpreet for (cnode = di_child_node(pnode); cnode != DI_NODE_NIL;
1081865Sdilpreet cnode = di_sibling_node(cnode)) {
1091865Sdilpreet if (di_driver_name(cnode) == NULL)
1101865Sdilpreet continue;
1111865Sdilpreet if (strcmp(di_driver_name(cnode), PCI_PCI) == 0) {
1124328Scindi if (hb_process(mod, ptn, hbcnt, cnode) < 0) {
1134328Scindi if (hbcnt == 0)
1144328Scindi topo_node_range_destroy(ptn,
1154328Scindi HOSTBRIDGE);
1162027Ssethg return (topo_mod_seterrno(mod,
1171865Sdilpreet EMOD_PARTIAL_ENUM));
1181865Sdilpreet }
1194328Scindi hbcnt++;
1201865Sdilpreet }
121*10187SKrishna.Elango@Sun.COM if (strcmp(di_driver_name(cnode), PCIEB) == 0) {
1224328Scindi if (rc_process(mod, ptn, hbcnt, cnode) < 0) {
1234328Scindi if (hbcnt == 0)
1244328Scindi topo_node_range_destroy(ptn,
1254328Scindi HOSTBRIDGE);
1262027Ssethg return (topo_mod_seterrno(mod,
1271865Sdilpreet EMOD_PARTIAL_ENUM));
1281865Sdilpreet }
1294328Scindi hbcnt++;
1301865Sdilpreet }
1311414Scindi }
1321414Scindi pnode = di_drv_next_node(pnode);
1331414Scindi }
1341414Scindi return (0);
1351414Scindi }
1361414Scindi
1371414Scindi /*ARGSUSED*/
1381414Scindi int
platform_hb_enum(topo_mod_t * mod,tnode_t * parent,const char * name,topo_instance_t imin,topo_instance_t imax)1393062Scindi platform_hb_enum(topo_mod_t *mod, tnode_t *parent, const char *name,
1403062Scindi topo_instance_t imin, topo_instance_t imax)
1411414Scindi {
1423062Scindi return (pci_hostbridges_find(mod, parent));
1431414Scindi }
1441414Scindi
1451414Scindi /*ARGSUSED*/
1461414Scindi int
platform_hb_label(topo_mod_t * mod,tnode_t * node,nvlist_t * in,nvlist_t ** out)1473062Scindi platform_hb_label(topo_mod_t *mod, tnode_t *node, nvlist_t *in, nvlist_t **out)
1481414Scindi {
1492027Ssethg return (labelmethod_inherit(mod, node, in, out));
1501414Scindi }
151