xref: /onnv-gate/usr/src/lib/fm/topo/modules/i86pc/x86pi/x86pi.c (revision 13017:cce6a2186e4e)
110942STom.Pothier@Sun.COM /*
210942STom.Pothier@Sun.COM  * CDDL HEADER START
310942STom.Pothier@Sun.COM  *
410942STom.Pothier@Sun.COM  * The contents of this file are subject to the terms of the
510942STom.Pothier@Sun.COM  * Common Development and Distribution License (the "License").
610942STom.Pothier@Sun.COM  * You may not use this file except in compliance with the License.
710942STom.Pothier@Sun.COM  *
810942STom.Pothier@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910942STom.Pothier@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1010942STom.Pothier@Sun.COM  * See the License for the specific language governing permissions
1110942STom.Pothier@Sun.COM  * and limitations under the License.
1210942STom.Pothier@Sun.COM  *
1310942STom.Pothier@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1410942STom.Pothier@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510942STom.Pothier@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1610942STom.Pothier@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1710942STom.Pothier@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1810942STom.Pothier@Sun.COM  *
1910942STom.Pothier@Sun.COM  * CDDL HEADER END
2010942STom.Pothier@Sun.COM  */
2110942STom.Pothier@Sun.COM 
2210942STom.Pothier@Sun.COM /*
2312355SSean.Ye@Sun.COM  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2410942STom.Pothier@Sun.COM  */
2510942STom.Pothier@Sun.COM 
2610942STom.Pothier@Sun.COM /*
2710942STom.Pothier@Sun.COM  * x86 Generic FMA Topology Enumerator
2810942STom.Pothier@Sun.COM  */
2910942STom.Pothier@Sun.COM 
3010942STom.Pothier@Sun.COM 
3110942STom.Pothier@Sun.COM #include <fcntl.h>
3210942STom.Pothier@Sun.COM #include <unistd.h>
3310942STom.Pothier@Sun.COM #include <sys/types.h>
3410942STom.Pothier@Sun.COM #include <strings.h>
3510942STom.Pothier@Sun.COM #include <sys/fcntl.h>
3610942STom.Pothier@Sun.COM #include <fm/topo_mod.h>
3710942STom.Pothier@Sun.COM #include <fm/topo_hc.h>
3810942STom.Pothier@Sun.COM #include <sys/systeminfo.h>
3910942STom.Pothier@Sun.COM #include <sys/smbios.h>
4010942STom.Pothier@Sun.COM #include <sys/smbios_impl.h>
4110942STom.Pothier@Sun.COM #include <sys/fm/protocol.h>
4210942STom.Pothier@Sun.COM #include <x86pi_impl.h>
4310942STom.Pothier@Sun.COM 
4410942STom.Pothier@Sun.COM 
4510942STom.Pothier@Sun.COM static int x86pi_enum_start(topo_mod_t *, x86pi_enum_t *);
4612832STrang.Do@Sun.COM static int x86pi_enum_gentopo(topo_mod_t *, tnode_t *);
4710942STom.Pothier@Sun.COM 
4810942STom.Pothier@Sun.COM /*
4910942STom.Pothier@Sun.COM  * Entry point called by libtopo when enumeration is required
5010942STom.Pothier@Sun.COM  */
5110942STom.Pothier@Sun.COM static topo_enum_f x86pi_enum;	/* libtopo enumeration entry point */
5210942STom.Pothier@Sun.COM 
5310942STom.Pothier@Sun.COM /*
54*13017STom.Pothier@Sun.COM  * Top level chassis node in a multiple chassis system; or the chassis
55*13017STom.Pothier@Sun.COM  * node in a single chassis system.
56*13017STom.Pothier@Sun.COM  */
57*13017STom.Pothier@Sun.COM static tnode_t *motherchassis_node = NULL;
58*13017STom.Pothier@Sun.COM 
59*13017STom.Pothier@Sun.COM 
60*13017STom.Pothier@Sun.COM /*
6110942STom.Pothier@Sun.COM  * Declare the operations vector and information structure used during
6210942STom.Pothier@Sun.COM  * module registration
6310942STom.Pothier@Sun.COM  */
6410942STom.Pothier@Sun.COM static topo_modops_t x86pi_ops =
6510942STom.Pothier@Sun.COM 	{ x86pi_enum, NULL };
6610942STom.Pothier@Sun.COM 
6710942STom.Pothier@Sun.COM static topo_modinfo_t	x86pi_modinfo =
6810942STom.Pothier@Sun.COM 	{ X86PI_DESC, X86PI_SCHEME, X86PI_VERSION, &x86pi_ops };
6910942STom.Pothier@Sun.COM 
7010942STom.Pothier@Sun.COM /*
7110942STom.Pothier@Sun.COM  * Used to pass SMBIOS' FM compatibility to the
7210942STom.Pothier@Sun.COM  * chip enumerator
7310942STom.Pothier@Sun.COM  */
7410942STom.Pothier@Sun.COM int x86pi_smbios = 0;
7510942STom.Pothier@Sun.COM 
7610942STom.Pothier@Sun.COM /*
7710942STom.Pothier@Sun.COM  * Called by libtopo when the topo module is loaded.
7810942STom.Pothier@Sun.COM  */
7910942STom.Pothier@Sun.COM int
_topo_init(topo_mod_t * mod,topo_version_t version)8010942STom.Pothier@Sun.COM _topo_init(topo_mod_t *mod, topo_version_t version)
8110942STom.Pothier@Sun.COM {
8210942STom.Pothier@Sun.COM 	int	result;
8310942STom.Pothier@Sun.COM 	char	isa[MAXNAMELEN];
8410942STom.Pothier@Sun.COM 
8510942STom.Pothier@Sun.COM 	if (getenv("TOPOX86PIDBG") != NULL) {
8610942STom.Pothier@Sun.COM 		/* Debugging is requested for this module */
8710942STom.Pothier@Sun.COM 		topo_mod_setdebug(mod);
8810942STom.Pothier@Sun.COM 	}
8910942STom.Pothier@Sun.COM 	topo_mod_dprintf(mod, "module initializing.\n");
9010942STom.Pothier@Sun.COM 
9110942STom.Pothier@Sun.COM 	if (version != TOPO_VERSION) {
9210983STom.Pothier@Sun.COM 		(void) topo_mod_seterrno(mod, EMOD_VER_NEW);
9310942STom.Pothier@Sun.COM 		topo_mod_dprintf(mod, "incompatible topo version %d\n",
9410942STom.Pothier@Sun.COM 		    version);
9510942STom.Pothier@Sun.COM 		return (-1);
9610942STom.Pothier@Sun.COM 	}
9710942STom.Pothier@Sun.COM 
9810942STom.Pothier@Sun.COM 	/* Verify that this is a i86pc architecture machine */
9910942STom.Pothier@Sun.COM 	(void) sysinfo(SI_MACHINE, isa, MAXNAMELEN);
10010942STom.Pothier@Sun.COM 	if (strncmp(isa, "i86pc", MAXNAMELEN) != 0) {
10110942STom.Pothier@Sun.COM 		topo_mod_dprintf(mod, "not i86pc architecture: %s\n", isa);
10210942STom.Pothier@Sun.COM 		return (-1);
10310942STom.Pothier@Sun.COM 	}
10410942STom.Pothier@Sun.COM 
10510942STom.Pothier@Sun.COM 	result = topo_mod_register(mod, &x86pi_modinfo, TOPO_VERSION);
10610942STom.Pothier@Sun.COM 	if (result < 0) {
10710942STom.Pothier@Sun.COM 		topo_mod_dprintf(mod, "registration failed: %s\n",
10810942STom.Pothier@Sun.COM 		    topo_mod_errmsg(mod));
10910942STom.Pothier@Sun.COM 		/* module errno already set */
11010942STom.Pothier@Sun.COM 		return (-1);
11110942STom.Pothier@Sun.COM 	}
11210942STom.Pothier@Sun.COM 	topo_mod_dprintf(mod, "module ready.\n");
11310942STom.Pothier@Sun.COM 	return (0);
11410942STom.Pothier@Sun.COM }
11510942STom.Pothier@Sun.COM 
11610942STom.Pothier@Sun.COM 
11710942STom.Pothier@Sun.COM /*
11810942STom.Pothier@Sun.COM  * Clean up any data used by the module before it is unloaded.
11910942STom.Pothier@Sun.COM  */
12010942STom.Pothier@Sun.COM void
_topo_fini(topo_mod_t * mod)12110942STom.Pothier@Sun.COM _topo_fini(topo_mod_t *mod)
12210942STom.Pothier@Sun.COM {
12310942STom.Pothier@Sun.COM 	topo_mod_dprintf(mod, "module finishing.\n");
12410942STom.Pothier@Sun.COM 
12510942STom.Pothier@Sun.COM 	/* Unregister from libtopo */
12610942STom.Pothier@Sun.COM 	topo_mod_unregister(mod);
12710942STom.Pothier@Sun.COM }
12810942STom.Pothier@Sun.COM 
12910942STom.Pothier@Sun.COM 
13010942STom.Pothier@Sun.COM /*
13110942STom.Pothier@Sun.COM  * Enumeration entry point for the x86 Generic topology enumerator
13210942STom.Pothier@Sun.COM  */
13310942STom.Pothier@Sun.COM /* ARGSUSED */
13410942STom.Pothier@Sun.COM static int
x86pi_enum(topo_mod_t * mod,tnode_t * t_parent,const char * name,topo_instance_t min,topo_instance_t max,void * pi_private,void * data)13510942STom.Pothier@Sun.COM x86pi_enum(topo_mod_t *mod, tnode_t *t_parent, const char *name,
13610942STom.Pothier@Sun.COM     topo_instance_t min, topo_instance_t max, void *pi_private, void *data)
13710942STom.Pothier@Sun.COM {
13810942STom.Pothier@Sun.COM 	int		result;
13910942STom.Pothier@Sun.COM 	hrtime_t	starttime;
14010942STom.Pothier@Sun.COM 	x86pi_enum_t	x86pi;
14110942STom.Pothier@Sun.COM 
14210942STom.Pothier@Sun.COM 	/* Begin enumeration */
14310942STom.Pothier@Sun.COM 	starttime = gethrtime();
14410942STom.Pothier@Sun.COM 	topo_mod_dprintf(mod, "enumeration starting.\n");
14510942STom.Pothier@Sun.COM 
14610942STom.Pothier@Sun.COM 	/*
14710942STom.Pothier@Sun.COM 	 * Let's do some enumeration.
14810942STom.Pothier@Sun.COM 	 */
14910942STom.Pothier@Sun.COM 	bzero(&x86pi, sizeof (x86pi_enum_t));
15010942STom.Pothier@Sun.COM 	x86pi.t_parent = t_parent;
15110942STom.Pothier@Sun.COM 	result = x86pi_enum_start(mod, &x86pi);
15210942STom.Pothier@Sun.COM 	if (result != 0) {
15310942STom.Pothier@Sun.COM 		topo_mod_dprintf(mod, "Enumeration failed.\n");
15410942STom.Pothier@Sun.COM 		return (-1);
15510942STom.Pothier@Sun.COM 	}
15610942STom.Pothier@Sun.COM 
15710942STom.Pothier@Sun.COM 	/* Complete enumeration */
15810942STom.Pothier@Sun.COM 	topo_mod_dprintf(mod, "enumeration complete in %lld ms.\n",
15910942STom.Pothier@Sun.COM 	    ((gethrtime() - starttime)/MICROSEC));
16010942STom.Pothier@Sun.COM 
16110942STom.Pothier@Sun.COM 	/* All done */
16210942STom.Pothier@Sun.COM 	return (result);
16310942STom.Pothier@Sun.COM }
16410942STom.Pothier@Sun.COM 
16510942STom.Pothier@Sun.COM static int
x86pi_enum_start(topo_mod_t * mod,x86pi_enum_t * x86pi)16610942STom.Pothier@Sun.COM x86pi_enum_start(topo_mod_t *mod, x86pi_enum_t *x86pi)
16710942STom.Pothier@Sun.COM {
16810942STom.Pothier@Sun.COM 	int		rv;
16910942STom.Pothier@Sun.COM 	int		complvl = 0;
17010942STom.Pothier@Sun.COM 	smbios_hdl_t	*shp;
17110942STom.Pothier@Sun.COM 	char		*f = "x86pi_enum_start";
17210942STom.Pothier@Sun.COM 
17310942STom.Pothier@Sun.COM 	/*
17410942STom.Pothier@Sun.COM 	 * Verify BIOS compliance.
17510942STom.Pothier@Sun.COM 	 */
17610942STom.Pothier@Sun.COM 	shp = x86pi_smb_open(mod);
17710942STom.Pothier@Sun.COM 	if (shp == NULL) {
17810942STom.Pothier@Sun.COM 		topo_mod_dprintf(mod, "%s: failed to open SMBIOS\n", f);
17910942STom.Pothier@Sun.COM 		complvl = X86PI_NONE;
18010942STom.Pothier@Sun.COM 	} else {
18112832STrang.Do@Sun.COM 		complvl = x86pi_check_comp(mod);
18210942STom.Pothier@Sun.COM 	}
18310942STom.Pothier@Sun.COM 
18410942STom.Pothier@Sun.COM 	topo_mod_dprintf(mod, "%s: SMBIOS x86pi compliance: %s\n", f,
18510942STom.Pothier@Sun.COM 	    complvl == X86PI_FULL ? "FULL" : "NONE");
18610942STom.Pothier@Sun.COM 
18710942STom.Pothier@Sun.COM 	if (complvl == X86PI_NONE) {
18810942STom.Pothier@Sun.COM 		/* fall back to legacy enumeration */
18910942STom.Pothier@Sun.COM 		topo_mod_dprintf(mod,
19010942STom.Pothier@Sun.COM 		    "%s: Calling legacy enumeration\n", f);
19110942STom.Pothier@Sun.COM 
19210942STom.Pothier@Sun.COM 		return (topo_mod_enummap(mod, x86pi->t_parent,
19310942STom.Pothier@Sun.COM 		    "i86pc-legacy", FM_FMRI_SCHEME_HC));
19410942STom.Pothier@Sun.COM 	}
19510942STom.Pothier@Sun.COM 
19610942STom.Pothier@Sun.COM 	x86pi->priv = (void *)shp;
19710942STom.Pothier@Sun.COM 	x86pi_smbios = complvl;
19810942STom.Pothier@Sun.COM 
19910942STom.Pothier@Sun.COM 	if (x86pi_hbr_enum_init(mod) < 0) {
20010942STom.Pothier@Sun.COM 		topo_mod_dprintf(mod, "%s: x86pi_hbr_enum_init() failed.\n", f);
20110942STom.Pothier@Sun.COM 		return (-1);
20210942STom.Pothier@Sun.COM 	}
20310942STom.Pothier@Sun.COM 
20410942STom.Pothier@Sun.COM 	/*
20510942STom.Pothier@Sun.COM 	 * Create the topology.
20610942STom.Pothier@Sun.COM 	 */
20710942STom.Pothier@Sun.COM 	fac_done = 0;
20812832STrang.Do@Sun.COM 	rv = x86pi_enum_gentopo(mod, x86pi->t_parent);
20912355SSean.Ye@Sun.COM 
21012355SSean.Ye@Sun.COM 	x86pi_hbr_enum_fini(mod);
21112355SSean.Ye@Sun.COM 
21210942STom.Pothier@Sun.COM 	if (rv != 0) {
21310942STom.Pothier@Sun.COM 		return (-1);
21410942STom.Pothier@Sun.COM 	}
21510942STom.Pothier@Sun.COM 	x86pi->mod = mod;
21610942STom.Pothier@Sun.COM 
21710942STom.Pothier@Sun.COM 	if (fac_done == 0) {
218*13017STom.Pothier@Sun.COM 		(void) topo_mod_enummap(mod, motherchassis_node, "chassis",
21910942STom.Pothier@Sun.COM 		    FM_FMRI_SCHEME_HC);
220*13017STom.Pothier@Sun.COM 		(void) topo_mod_enummap(mod, motherchassis_node, "fan",
22110942STom.Pothier@Sun.COM 		    FM_FMRI_SCHEME_HC);
222*13017STom.Pothier@Sun.COM 		(void) topo_mod_enummap(mod, motherchassis_node, "psu",
22310942STom.Pothier@Sun.COM 		    FM_FMRI_SCHEME_HC);
22410942STom.Pothier@Sun.COM 	}
22510942STom.Pothier@Sun.COM 
22610942STom.Pothier@Sun.COM 	/* All done */
22710942STom.Pothier@Sun.COM 	topo_mod_dprintf(mod, "%s: done.\n", f);
22810942STom.Pothier@Sun.COM 	return (rv);
22910942STom.Pothier@Sun.COM }
23010942STom.Pothier@Sun.COM 
23110942STom.Pothier@Sun.COM /*
23210942STom.Pothier@Sun.COM  * Create the i86pc topology
23310942STom.Pothier@Sun.COM  *
23410942STom.Pothier@Sun.COM  * If either Type 2 or Type 3 structures have contained elements/handles,
23510942STom.Pothier@Sun.COM  * walk them creating the topo.
23610942STom.Pothier@Sun.COM  *
23710942STom.Pothier@Sun.COM  * If there are no contained elements/handles, build this topo:
23810942STom.Pothier@Sun.COM  *
23910942STom.Pothier@Sun.COM  *    Main Chassis
24010942STom.Pothier@Sun.COM  *      Motherboard
24110942STom.Pothier@Sun.COM  *        CMP Chip/Core/Strands
24210942STom.Pothier@Sun.COM  *          Memory Controllers/Memory Devices (DIMMs)
24310942STom.Pothier@Sun.COM  *        PCIE HostBrige
24410942STom.Pothier@Sun.COM  *          PCIE Root Complex
24510942STom.Pothier@Sun.COM  *
24610942STom.Pothier@Sun.COM  */
24710942STom.Pothier@Sun.COM static int
x86pi_enum_gentopo(topo_mod_t * mod,tnode_t * t_parent)24812832STrang.Do@Sun.COM x86pi_enum_gentopo(topo_mod_t *mod, tnode_t *t_parent)
24910942STom.Pothier@Sun.COM {
25010942STom.Pothier@Sun.COM 	int		rv;
25110942STom.Pothier@Sun.COM 	int		nch, nbb, ncmp, i;
25210942STom.Pothier@Sun.COM 	int		ch_smbid, bb_smbid;
25310942STom.Pothier@Sun.COM 	tnode_t		*chassis_node = NULL;
25410942STom.Pothier@Sun.COM 	tnode_t		*basebd_node = NULL;
25510942STom.Pothier@Sun.COM 	smbs_cnt_t	*smbc;
25610942STom.Pothier@Sun.COM 	tnode_t		*pnode = NULL;
25710942STom.Pothier@Sun.COM 	id_t		psmbid;
25810942STom.Pothier@Sun.COM 	int		notvisited;
25910942STom.Pothier@Sun.COM 	int		bb_count, ch_count;
26010942STom.Pothier@Sun.COM 	int		min, max;
26110942STom.Pothier@Sun.COM 	int		ch_inst = 0;
26211859STom.Pothier@Sun.COM 	int		disk_inst = 0;
26310942STom.Pothier@Sun.COM 	topo_instance_t	 hbri = 0, rci = 0;
26410942STom.Pothier@Sun.COM 	smbios_pciexrc_t hbr;
26511859STom.Pothier@Sun.COM 	smbios_port_ext_t export;
26610942STom.Pothier@Sun.COM 	char		*f = "x86pi_enum_gentopo";
26712832STrang.Do@Sun.COM 	smbios_hdl_t 	*shp;
26812832STrang.Do@Sun.COM 
26912832STrang.Do@Sun.COM 	shp = topo_mod_smbios(mod);
27012832STrang.Do@Sun.COM 	if (shp == NULL) {
27112832STrang.Do@Sun.COM 		topo_mod_dprintf(mod, "%s: failed to load SMBIOS\n", f);
27212832STrang.Do@Sun.COM 		return (-1);
27312832STrang.Do@Sun.COM 	}
27410942STom.Pothier@Sun.COM 
27510942STom.Pothier@Sun.COM 	if (t_parent == NULL) {
27610942STom.Pothier@Sun.COM 		topo_mod_dprintf(mod, "%s: NULL parent\n", f);
27710942STom.Pothier@Sun.COM 		return (-1);
27810942STom.Pothier@Sun.COM 	}
27910942STom.Pothier@Sun.COM 
28010942STom.Pothier@Sun.COM 	/*
28110942STom.Pothier@Sun.COM 	 * "Chassis'"
28210942STom.Pothier@Sun.COM 	 */
28310942STom.Pothier@Sun.COM 	/* Type 3 structs */
28410942STom.Pothier@Sun.COM 	stypes[SMB_TYPE_CHASSIS].type = SMB_TYPE_CHASSIS;
28512832STrang.Do@Sun.COM 	x86pi_smb_strcnt(mod, &stypes[SMB_TYPE_CHASSIS]);
28610942STom.Pothier@Sun.COM 
28710942STom.Pothier@Sun.COM 	ch_count = stypes[SMB_TYPE_CHASSIS].count;
28810942STom.Pothier@Sun.COM 
28910942STom.Pothier@Sun.COM 	for (nch = 0; nch < ch_count; nch++) {
29010942STom.Pothier@Sun.COM 		topo_mod_dprintf(mod, "%s: found %d chassis\n", f,
29110942STom.Pothier@Sun.COM 		    stypes[SMB_TYPE_CHASSIS].count);
29210942STom.Pothier@Sun.COM 
29310942STom.Pothier@Sun.COM 		ch_smbid = stypes[SMB_TYPE_CHASSIS].ids[nch].id;
29410942STom.Pothier@Sun.COM 
29510942STom.Pothier@Sun.COM 		/*
29610942STom.Pothier@Sun.COM 		 * Expect SMBIOS to set the first Chassis Structure to be the
29710942STom.Pothier@Sun.COM 		 * parent/mother of all chassis
29810942STom.Pothier@Sun.COM 		 */
29910942STom.Pothier@Sun.COM 		if (nch == 0)
30010942STom.Pothier@Sun.COM 			motherchassis_node = chassis_node =
30112832STrang.Do@Sun.COM 			    x86pi_gen_chassis(mod, t_parent, ch_smbid,
30212832STrang.Do@Sun.COM 			    ch_inst++);
30310942STom.Pothier@Sun.COM 		else {
30410942STom.Pothier@Sun.COM 			if (motherchassis_node != NULL)
30510942STom.Pothier@Sun.COM 				chassis_node = x86pi_gen_chassis(mod,
30612832STrang.Do@Sun.COM 				    motherchassis_node, ch_smbid, ch_inst++);
30710942STom.Pothier@Sun.COM 			else
30810942STom.Pothier@Sun.COM 				chassis_node = x86pi_gen_chassis(mod,
30912832STrang.Do@Sun.COM 				    t_parent, ch_smbid, ch_inst++);
31010942STom.Pothier@Sun.COM 		}
31110942STom.Pothier@Sun.COM 
31210942STom.Pothier@Sun.COM 		if (chassis_node == NULL) {
31310942STom.Pothier@Sun.COM 			topo_mod_dprintf(mod,
31410942STom.Pothier@Sun.COM 			    "%s: Failed to create chassis %d\n", f, nch);
31510942STom.Pothier@Sun.COM 			continue;
31610942STom.Pothier@Sun.COM 		}
31710942STom.Pothier@Sun.COM 		stypes[SMB_TYPE_CHASSIS].ids[nch].node = chassis_node;
31811859STom.Pothier@Sun.COM 
31911859STom.Pothier@Sun.COM 		/* count SMBIOS extended port connector structures */
32011859STom.Pothier@Sun.COM 		smbc = &stypes[SUN_OEM_EXT_PORT];
32111859STom.Pothier@Sun.COM 		smbc->type = SUN_OEM_EXT_PORT;
32212832STrang.Do@Sun.COM 		x86pi_smb_strcnt(mod, smbc);
32311859STom.Pothier@Sun.COM 
32412815SVuong.Nguyen@Sun.COM 		/*
32512815SVuong.Nguyen@Sun.COM 		 * enumerate direct attached SATA disks if we found a
32612815SVuong.Nguyen@Sun.COM 		 * SUN_OEM_EXT_PORT record.
32712815SVuong.Nguyen@Sun.COM 		 */
32812815SVuong.Nguyen@Sun.COM 		if (smbc->count > 0) {
32912815SVuong.Nguyen@Sun.COM 			rv = topo_node_range_create(mod, chassis_node, BAY, 0,
33012815SVuong.Nguyen@Sun.COM 			    smbc->count + 1);
33112815SVuong.Nguyen@Sun.COM 			if (rv != 0) {
33212815SVuong.Nguyen@Sun.COM 				topo_mod_dprintf(mod,
33312815SVuong.Nguyen@Sun.COM 				    "%s: Failed to create %s range: %s\n",
33412815SVuong.Nguyen@Sun.COM 				    f, BAY, topo_mod_errmsg(mod));
33512815SVuong.Nguyen@Sun.COM 				continue;
33612815SVuong.Nguyen@Sun.COM 			}
33712815SVuong.Nguyen@Sun.COM 		} else {
33811859STom.Pothier@Sun.COM 			topo_mod_dprintf(mod,
33912815SVuong.Nguyen@Sun.COM 			    "Skipping disk bay enumeration\n");
34011859STom.Pothier@Sun.COM 		}
34111859STom.Pothier@Sun.COM 
34211859STom.Pothier@Sun.COM 		for (i = 0; i < smbc->count; i++) {
34311859STom.Pothier@Sun.COM 			if (smbios_info_extport(shp, smbc->ids[i].id,
34411859STom.Pothier@Sun.COM 			    &export) != 0) {
34511859STom.Pothier@Sun.COM 				topo_mod_dprintf(mod,
34611859STom.Pothier@Sun.COM 				    "smbios_info_export failed: id = %d\n",
34711859STom.Pothier@Sun.COM 				    (int)smbc->ids[i].id);
34811859STom.Pothier@Sun.COM 				continue;
34911859STom.Pothier@Sun.COM 			}
35011859STom.Pothier@Sun.COM 			if (export.smbporte_chassis != ch_smbid)
35111859STom.Pothier@Sun.COM 				continue;
35211859STom.Pothier@Sun.COM 
35311859STom.Pothier@Sun.COM 			/*
35411859STom.Pothier@Sun.COM 			 * x86pi_gen_bay:
35511859STom.Pothier@Sun.COM 			 *   create "bay" node
35611859STom.Pothier@Sun.COM 			 *   call "disk" enum passing in "bay" node
35711859STom.Pothier@Sun.COM 			 */
35812832STrang.Do@Sun.COM 			rv = x86pi_gen_bay(mod, chassis_node, &export,
35912832STrang.Do@Sun.COM 			    disk_inst);
36011859STom.Pothier@Sun.COM 			if (rv != 0)
36111859STom.Pothier@Sun.COM 				topo_mod_dprintf(mod,
36211859STom.Pothier@Sun.COM 				    "Failed to create disk %d\n", i);
36311859STom.Pothier@Sun.COM 			disk_inst++;
36411859STom.Pothier@Sun.COM 		}
36510942STom.Pothier@Sun.COM 	}
36610942STom.Pothier@Sun.COM 
36710942STom.Pothier@Sun.COM 	/*
36810942STom.Pothier@Sun.COM 	 * "Base Board"
36910942STom.Pothier@Sun.COM 	 */
37010942STom.Pothier@Sun.COM 	/* Type 2 structs */
37110942STom.Pothier@Sun.COM 	stypes[SMB_TYPE_BASEBOARD].type = SMB_TYPE_BASEBOARD;
37212832STrang.Do@Sun.COM 	x86pi_smb_strcnt(mod, &stypes[SMB_TYPE_BASEBOARD]);
37310942STom.Pothier@Sun.COM 	bb_count = notvisited = stypes[SMB_TYPE_BASEBOARD].count;
37410942STom.Pothier@Sun.COM 
37510942STom.Pothier@Sun.COM 	for (nbb = 0; nbb < bb_count; nbb++) {
37610942STom.Pothier@Sun.COM 		stypes[SMB_TYPE_BASEBOARD].ids[nbb].visited = 0;
37710942STom.Pothier@Sun.COM 		stypes[SMB_TYPE_BASEBOARD].ids[nbb].con_by_id = 0;
37810942STom.Pothier@Sun.COM 		stypes[SMB_TYPE_BASEBOARD].ids[nbb].node = NULL;
37910942STom.Pothier@Sun.COM 	}
38012832STrang.Do@Sun.COM 	(void) x86pi_bb_contains(mod);
38110942STom.Pothier@Sun.COM 
38210942STom.Pothier@Sun.COM 	min = 0;
38310942STom.Pothier@Sun.COM 	nbb = 0;
38410942STom.Pothier@Sun.COM 	do {
38510942STom.Pothier@Sun.COM 		/*
38610942STom.Pothier@Sun.COM 		 * We have reached end of the array due to the
38710942STom.Pothier@Sun.COM 		 * parent-child relationship, without visiting all
38810942STom.Pothier@Sun.COM 		 * baseboards! so re-iterate..
38910942STom.Pothier@Sun.COM 		 * (or)
39010942STom.Pothier@Sun.COM 		 * All baseboards are visited and their contained
39110942STom.Pothier@Sun.COM 		 * processors are enumerated
39210942STom.Pothier@Sun.COM 		 * (and/or)
39310942STom.Pothier@Sun.COM 		 * More baseboards pending a visit
39410942STom.Pothier@Sun.COM 		 */
39510942STom.Pothier@Sun.COM 		if (nbb > bb_count && notvisited)
39610942STom.Pothier@Sun.COM 			nbb = 0;
39710942STom.Pothier@Sun.COM 		else if (nbb > bb_count && !notvisited)
39810942STom.Pothier@Sun.COM 			break;
39910942STom.Pothier@Sun.COM 		if (stypes[SMB_TYPE_BASEBOARD].ids[nbb].visited ==
40010942STom.Pothier@Sun.COM 		    X86PI_VISITED) {
40110942STom.Pothier@Sun.COM 			nbb++;
40210942STom.Pothier@Sun.COM 			continue;
40310942STom.Pothier@Sun.COM 		}
40410942STom.Pothier@Sun.COM 
40510942STom.Pothier@Sun.COM 		/*
40610942STom.Pothier@Sun.COM 		 * Get the Top-most Parent Baseboard, irrespective
40710942STom.Pothier@Sun.COM 		 * of its index in the array of Type-2s
40810942STom.Pothier@Sun.COM 		 * If this Baseboard has no Baseboard parents
40910942STom.Pothier@Sun.COM 		 * place it under the chassis that contains it
41010942STom.Pothier@Sun.COM 		 */
41112832STrang.Do@Sun.COM 		bb_smbid = x86pi_bb_topparent(mod, nbb, &pnode, &psmbid);
41210942STom.Pothier@Sun.COM 		if (bb_smbid == -1 || pnode == NULL) {
41310942STom.Pothier@Sun.COM 			topo_mod_dprintf(mod,
41410942STom.Pothier@Sun.COM 			    "Failed to get BaseBoard node (%d): parent\n",
41510942STom.Pothier@Sun.COM 			    nbb);
41610942STom.Pothier@Sun.COM 			return (-1);
41710942STom.Pothier@Sun.COM 		}
41810942STom.Pothier@Sun.COM 
41910942STom.Pothier@Sun.COM 		if (stypes[SMB_TYPE_BASEBOARD].ids[nbb].id != bb_smbid) {
42010942STom.Pothier@Sun.COM 			for (int i = 0; i < bb_count; i++) {
42110942STom.Pothier@Sun.COM 				if (bb_smbid ==
42210942STom.Pothier@Sun.COM 				    stypes[SMB_TYPE_BASEBOARD].ids[i].id) {
42310942STom.Pothier@Sun.COM 					stypes[SMB_TYPE_BASEBOARD].ids[i].\
42410942STom.Pothier@Sun.COM 					    visited = 1;
42510942STom.Pothier@Sun.COM 					notvisited--;
42610942STom.Pothier@Sun.COM 					break;
42710942STom.Pothier@Sun.COM 				}
42810942STom.Pothier@Sun.COM 			}
42910942STom.Pothier@Sun.COM 		} else {
43010942STom.Pothier@Sun.COM 			stypes[SMB_TYPE_BASEBOARD].ids[nbb].visited = 1;
43110942STom.Pothier@Sun.COM 			notvisited--;
43210942STom.Pothier@Sun.COM 		}
43310942STom.Pothier@Sun.COM 
43412832STrang.Do@Sun.COM 		basebd_node = x86pi_gen_bboard(mod, pnode, bb_smbid,
43512832STrang.Do@Sun.COM 		    nbb, psmbid);
43610942STom.Pothier@Sun.COM 		if (basebd_node == NULL) {
43710942STom.Pothier@Sun.COM 			topo_mod_dprintf(mod,
43810942STom.Pothier@Sun.COM 			    "Failed to create BaseBoard node (%d)\n", nbb);
43910942STom.Pothier@Sun.COM 			nbb++;
44010942STom.Pothier@Sun.COM 			continue;
44110942STom.Pothier@Sun.COM 		}
44210942STom.Pothier@Sun.COM 
44310942STom.Pothier@Sun.COM 		stypes[SMB_TYPE_BASEBOARD].ids[nbb].node = basebd_node;
44410942STom.Pothier@Sun.COM 		/*
44510942STom.Pothier@Sun.COM 		 * Look for contained handles here and if there are
44610942STom.Pothier@Sun.COM 		 * make sure the chip handle below is part of it.
44710942STom.Pothier@Sun.COM 		 */
44812832STrang.Do@Sun.COM 		ncmp = x86pi_bb_getchips(mod, nbb, bb_count);
44910942STom.Pothier@Sun.COM 		if (ncmp > 0) {
45010942STom.Pothier@Sun.COM 			max = min + ncmp - 1;
45110942STom.Pothier@Sun.COM 			/* make sure the chip enum is loaded */
45210942STom.Pothier@Sun.COM 			topo_mod_dprintf(mod, "%s: loading chip enum\n", f);
45310942STom.Pothier@Sun.COM 
45410942STom.Pothier@Sun.COM 			if (topo_mod_load(mod, CHIP, TOPO_VERSION) == NULL) {
45510942STom.Pothier@Sun.COM 				topo_mod_dprintf(mod,
45610942STom.Pothier@Sun.COM 				    "%s: Failed to load %s module: %s\n", f,
45710942STom.Pothier@Sun.COM 				    CHIP, topo_strerror(topo_mod_errno(mod)));
45810942STom.Pothier@Sun.COM 			} else {
45910942STom.Pothier@Sun.COM 				/* create node range */
46010942STom.Pothier@Sun.COM 				topo_mod_dprintf(mod,
46110942STom.Pothier@Sun.COM 				    "%s: chip range %d to %d\n",
46210942STom.Pothier@Sun.COM 				    f, min, max);
46310942STom.Pothier@Sun.COM 				rv = topo_node_range_create(mod, basebd_node,
46410942STom.Pothier@Sun.COM 				    CHIP, min, max);
46510942STom.Pothier@Sun.COM 				if (rv != 0) {
46610942STom.Pothier@Sun.COM 					topo_mod_dprintf(mod,
46710942STom.Pothier@Sun.COM 					    "%s: Failed to create node range: "
46810942STom.Pothier@Sun.COM 					    "%s\n", f,
46910942STom.Pothier@Sun.COM 					    topo_strerror(topo_mod_errno(mod)));
47010942STom.Pothier@Sun.COM 				} else {
47110942STom.Pothier@Sun.COM 					/* call the chip enumerator */
47210942STom.Pothier@Sun.COM 					topo_mod_dprintf(mod, "%s: calling"
47310942STom.Pothier@Sun.COM 					    " chip enum\n", f);
47410942STom.Pothier@Sun.COM 					rv =
47510942STom.Pothier@Sun.COM 					    topo_mod_enumerate(mod, basebd_node,
47610942STom.Pothier@Sun.COM 					    CHIP, CHIP, min, max,
47710942STom.Pothier@Sun.COM 					    &x86pi_smbios);
47810942STom.Pothier@Sun.COM 					min = max + 1;
47910942STom.Pothier@Sun.COM 					if (rv != 0)
48010942STom.Pothier@Sun.COM 						topo_mod_dprintf(mod, "%s:%s"
48110942STom.Pothier@Sun.COM 						    "enumeration failed: \n",
48210942STom.Pothier@Sun.COM 						    f, CHIP);
48310942STom.Pothier@Sun.COM 				}
48410942STom.Pothier@Sun.COM 			}
48510942STom.Pothier@Sun.COM 		}
48610942STom.Pothier@Sun.COM 
48710942STom.Pothier@Sun.COM 		/* enumerate the hostbridge node */
48810942STom.Pothier@Sun.COM 		rv = topo_node_range_create(mod, basebd_node, HOSTBRIDGE,
48910942STom.Pothier@Sun.COM 		    0, 255);
49010942STom.Pothier@Sun.COM 		if (rv != 0) {
49110942STom.Pothier@Sun.COM 			topo_mod_dprintf(mod,
49210942STom.Pothier@Sun.COM 			    "%s: Failed to create %s range: %s\n",
49310942STom.Pothier@Sun.COM 			    f, HOSTBRIDGE, topo_mod_errmsg(mod));
49410942STom.Pothier@Sun.COM 			continue;
49510942STom.Pothier@Sun.COM 		}
49610942STom.Pothier@Sun.COM 
49710942STom.Pothier@Sun.COM 		smbc = &stypes[SUN_OEM_PCIEXRC];
49810942STom.Pothier@Sun.COM 		smbc->type = SUN_OEM_PCIEXRC;
49912832STrang.Do@Sun.COM 		x86pi_smb_strcnt(mod, smbc);
50010942STom.Pothier@Sun.COM 		for (i = 0; i < smbc->count; i++) {
50110942STom.Pothier@Sun.COM 			if (smbios_info_pciexrc(shp, smbc->ids[i].id,
50210942STom.Pothier@Sun.COM 			    &hbr) != 0) {
50310942STom.Pothier@Sun.COM 				topo_mod_dprintf(mod,
50410942STom.Pothier@Sun.COM 				    "smbios_info_pciexrc failed: "
50510942STom.Pothier@Sun.COM 				    "id = %d\n", (int)smbc->ids[i].id);
50610942STom.Pothier@Sun.COM 				continue;
50710942STom.Pothier@Sun.COM 			}
50810942STom.Pothier@Sun.COM 
50910942STom.Pothier@Sun.COM 			if (hbr.smbpcie_bb != bb_smbid)
51010942STom.Pothier@Sun.COM 				continue;
51112832STrang.Do@Sun.COM 			rv = x86pi_gen_hbr(mod, basebd_node,
51210942STom.Pothier@Sun.COM 			    smbc->ids[i].id, hbri, &rci);
51310942STom.Pothier@Sun.COM 			if (rv != 0)
51410942STom.Pothier@Sun.COM 				topo_mod_dprintf(mod,
51510942STom.Pothier@Sun.COM 				    "couldn't create hostbridge=%d\n", hbri);
51610942STom.Pothier@Sun.COM 			hbri++;
51710942STom.Pothier@Sun.COM 		}
51810942STom.Pothier@Sun.COM 		nbb++;
51910942STom.Pothier@Sun.COM 
52010942STom.Pothier@Sun.COM 	} while (notvisited);
52110942STom.Pothier@Sun.COM 
52210942STom.Pothier@Sun.COM 	return (0);
52310942STom.Pothier@Sun.COM }
524