1074bb90dSTom Pothier /*
2074bb90dSTom Pothier  * CDDL HEADER START
3074bb90dSTom Pothier  *
4074bb90dSTom Pothier  * The contents of this file are subject to the terms of the
5074bb90dSTom Pothier  * Common Development and Distribution License (the "License").
6074bb90dSTom Pothier  * You may not use this file except in compliance with the License.
7074bb90dSTom Pothier  *
8074bb90dSTom Pothier  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9074bb90dSTom Pothier  * or http://www.opensolaris.org/os/licensing.
10074bb90dSTom Pothier  * See the License for the specific language governing permissions
11074bb90dSTom Pothier  * and limitations under the License.
12074bb90dSTom Pothier  *
13074bb90dSTom Pothier  * When distributing Covered Code, include this CDDL HEADER in each
14074bb90dSTom Pothier  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15074bb90dSTom Pothier  * If applicable, add the following below this CDDL HEADER, with the
16074bb90dSTom Pothier  * fields enclosed by brackets "[]" replaced with your own identifying
17074bb90dSTom Pothier  * information: Portions Copyright [yyyy] [name of copyright owner]
18074bb90dSTom Pothier  *
19074bb90dSTom Pothier  * CDDL HEADER END
20074bb90dSTom Pothier  */
21074bb90dSTom Pothier 
22074bb90dSTom Pothier /*
235677a1bfSCheng Sean Ye  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24074bb90dSTom Pothier  */
25074bb90dSTom Pothier 
26074bb90dSTom Pothier /*
27074bb90dSTom Pothier  * x86 Generic FMA Topology Enumerator
28074bb90dSTom Pothier  */
29074bb90dSTom Pothier 
30074bb90dSTom Pothier 
31074bb90dSTom Pothier #include <fcntl.h>
32074bb90dSTom Pothier #include <unistd.h>
33074bb90dSTom Pothier #include <sys/types.h>
34074bb90dSTom Pothier #include <strings.h>
35074bb90dSTom Pothier #include <sys/fcntl.h>
36074bb90dSTom Pothier #include <fm/topo_mod.h>
37074bb90dSTom Pothier #include <fm/topo_hc.h>
38074bb90dSTom Pothier #include <sys/systeminfo.h>
39074bb90dSTom Pothier #include <sys/smbios.h>
40074bb90dSTom Pothier #include <sys/smbios_impl.h>
41074bb90dSTom Pothier #include <sys/fm/protocol.h>
42074bb90dSTom Pothier #include <x86pi_impl.h>
43074bb90dSTom Pothier 
44074bb90dSTom Pothier 
45074bb90dSTom Pothier static int x86pi_enum_start(topo_mod_t *, x86pi_enum_t *);
46efd31e1dSTrang Do static int x86pi_enum_gentopo(topo_mod_t *, tnode_t *);
47074bb90dSTom Pothier 
48074bb90dSTom Pothier /*
49074bb90dSTom Pothier  * Entry point called by libtopo when enumeration is required
50074bb90dSTom Pothier  */
51074bb90dSTom Pothier static topo_enum_f x86pi_enum;	/* libtopo enumeration entry point */
52074bb90dSTom Pothier 
53a98ca9daSTom Pothier /*
54a98ca9daSTom Pothier  * Top level chassis node in a multiple chassis system; or the chassis
55a98ca9daSTom Pothier  * node in a single chassis system.
56a98ca9daSTom Pothier  */
57a98ca9daSTom Pothier static tnode_t *motherchassis_node = NULL;
58a98ca9daSTom Pothier 
59a98ca9daSTom Pothier 
60074bb90dSTom Pothier /*
61074bb90dSTom Pothier  * Declare the operations vector and information structure used during
62074bb90dSTom Pothier  * module registration
63074bb90dSTom Pothier  */
64074bb90dSTom Pothier static topo_modops_t x86pi_ops =
65074bb90dSTom Pothier 	{ x86pi_enum, NULL };
66074bb90dSTom Pothier 
67074bb90dSTom Pothier static topo_modinfo_t	x86pi_modinfo =
68074bb90dSTom Pothier 	{ X86PI_DESC, X86PI_SCHEME, X86PI_VERSION, &x86pi_ops };
69074bb90dSTom Pothier 
70074bb90dSTom Pothier /*
71074bb90dSTom Pothier  * Used to pass SMBIOS' FM compatibility to the
72074bb90dSTom Pothier  * chip enumerator
73074bb90dSTom Pothier  */
74074bb90dSTom Pothier int x86pi_smbios = 0;
75074bb90dSTom Pothier 
762a685872SToomas Soome /* indication of successful fac node creation */
772a685872SToomas Soome int fac_done;
782a685872SToomas Soome /* one for each struct */
792a685872SToomas Soome smbs_cnt_t stypes[SMB_TYPE_OEM_HI];
802a685872SToomas Soome 
81074bb90dSTom Pothier /*
82074bb90dSTom Pothier  * Called by libtopo when the topo module is loaded.
83074bb90dSTom Pothier  */
84074bb90dSTom Pothier int
_topo_init(topo_mod_t * mod,topo_version_t version)85074bb90dSTom Pothier _topo_init(topo_mod_t *mod, topo_version_t version)
86074bb90dSTom Pothier {
87074bb90dSTom Pothier 	int	result;
88074bb90dSTom Pothier 	char	isa[MAXNAMELEN];
89074bb90dSTom Pothier 
90074bb90dSTom Pothier 	if (getenv("TOPOX86PIDBG") != NULL) {
91074bb90dSTom Pothier 		/* Debugging is requested for this module */
92074bb90dSTom Pothier 		topo_mod_setdebug(mod);
93074bb90dSTom Pothier 	}
94074bb90dSTom Pothier 	topo_mod_dprintf(mod, "module initializing.\n");
95074bb90dSTom Pothier 
96074bb90dSTom Pothier 	if (version != TOPO_VERSION) {
97d3c57c1fSTom Pothier 		(void) topo_mod_seterrno(mod, EMOD_VER_NEW);
98074bb90dSTom Pothier 		topo_mod_dprintf(mod, "incompatible topo version %d\n",
99074bb90dSTom Pothier 		    version);
100074bb90dSTom Pothier 		return (-1);
101074bb90dSTom Pothier 	}
102074bb90dSTom Pothier 
103074bb90dSTom Pothier 	/* Verify that this is a i86pc architecture machine */
104074bb90dSTom Pothier 	(void) sysinfo(SI_MACHINE, isa, MAXNAMELEN);
105074bb90dSTom Pothier 	if (strncmp(isa, "i86pc", MAXNAMELEN) != 0) {
106074bb90dSTom Pothier 		topo_mod_dprintf(mod, "not i86pc architecture: %s\n", isa);
107074bb90dSTom Pothier 		return (-1);
108074bb90dSTom Pothier 	}
109074bb90dSTom Pothier 
110074bb90dSTom Pothier 	result = topo_mod_register(mod, &x86pi_modinfo, TOPO_VERSION);
111074bb90dSTom Pothier 	if (result < 0) {
112074bb90dSTom Pothier 		topo_mod_dprintf(mod, "registration failed: %s\n",
113074bb90dSTom Pothier 		    topo_mod_errmsg(mod));
114074bb90dSTom Pothier 		/* module errno already set */
115074bb90dSTom Pothier 		return (-1);
116074bb90dSTom Pothier 	}
117074bb90dSTom Pothier 	topo_mod_dprintf(mod, "module ready.\n");
118074bb90dSTom Pothier 	return (0);
119074bb90dSTom Pothier }
120074bb90dSTom Pothier 
121074bb90dSTom Pothier 
122074bb90dSTom Pothier /*
123074bb90dSTom Pothier  * Clean up any data used by the module before it is unloaded.
124074bb90dSTom Pothier  */
125074bb90dSTom Pothier void
_topo_fini(topo_mod_t * mod)126074bb90dSTom Pothier _topo_fini(topo_mod_t *mod)
127074bb90dSTom Pothier {
128074bb90dSTom Pothier 	topo_mod_dprintf(mod, "module finishing.\n");
129074bb90dSTom Pothier 
130074bb90dSTom Pothier 	/* Unregister from libtopo */
131074bb90dSTom Pothier 	topo_mod_unregister(mod);
132074bb90dSTom Pothier }
133074bb90dSTom Pothier 
134074bb90dSTom Pothier 
135074bb90dSTom Pothier /*
136074bb90dSTom Pothier  * Enumeration entry point for the x86 Generic topology enumerator
137074bb90dSTom Pothier  */
138074bb90dSTom Pothier /* ARGSUSED */
139074bb90dSTom Pothier 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)140074bb90dSTom Pothier x86pi_enum(topo_mod_t *mod, tnode_t *t_parent, const char *name,
141074bb90dSTom Pothier     topo_instance_t min, topo_instance_t max, void *pi_private, void *data)
142074bb90dSTom Pothier {
143074bb90dSTom Pothier 	int		result;
144074bb90dSTom Pothier 	hrtime_t	starttime;
145074bb90dSTom Pothier 	x86pi_enum_t	x86pi;
146074bb90dSTom Pothier 
147074bb90dSTom Pothier 	/* Begin enumeration */
148074bb90dSTom Pothier 	starttime = gethrtime();
149074bb90dSTom Pothier 	topo_mod_dprintf(mod, "enumeration starting.\n");
150074bb90dSTom Pothier 
151074bb90dSTom Pothier 	/*
152074bb90dSTom Pothier 	 * Let's do some enumeration.
153074bb90dSTom Pothier 	 */
154074bb90dSTom Pothier 	bzero(&x86pi, sizeof (x86pi_enum_t));
155074bb90dSTom Pothier 	x86pi.t_parent = t_parent;
156074bb90dSTom Pothier 	result = x86pi_enum_start(mod, &x86pi);
157074bb90dSTom Pothier 	if (result != 0) {
158074bb90dSTom Pothier 		topo_mod_dprintf(mod, "Enumeration failed.\n");
159074bb90dSTom Pothier 		return (-1);
160074bb90dSTom Pothier 	}
161074bb90dSTom Pothier 
162074bb90dSTom Pothier 	/* Complete enumeration */
163074bb90dSTom Pothier 	topo_mod_dprintf(mod, "enumeration complete in %lld ms.\n",
164074bb90dSTom Pothier 	    ((gethrtime() - starttime)/MICROSEC));
165074bb90dSTom Pothier 
166074bb90dSTom Pothier 	/* All done */
167074bb90dSTom Pothier 	return (result);
168074bb90dSTom Pothier }
169074bb90dSTom Pothier 
170074bb90dSTom Pothier static int
x86pi_enum_start(topo_mod_t * mod,x86pi_enum_t * x86pi)171074bb90dSTom Pothier x86pi_enum_start(topo_mod_t *mod, x86pi_enum_t *x86pi)
172074bb90dSTom Pothier {
173074bb90dSTom Pothier 	int		rv;
174074bb90dSTom Pothier 	int		complvl = 0;
175074bb90dSTom Pothier 	smbios_hdl_t	*shp;
176074bb90dSTom Pothier 	char		*f = "x86pi_enum_start";
177074bb90dSTom Pothier 
178074bb90dSTom Pothier 	/*
179074bb90dSTom Pothier 	 * Verify BIOS compliance.
180074bb90dSTom Pothier 	 */
181074bb90dSTom Pothier 	shp = x86pi_smb_open(mod);
182074bb90dSTom Pothier 	if (shp == NULL) {
183074bb90dSTom Pothier 		topo_mod_dprintf(mod, "%s: failed to open SMBIOS\n", f);
184074bb90dSTom Pothier 		complvl = X86PI_NONE;
185074bb90dSTom Pothier 	} else {
186efd31e1dSTrang Do 		complvl = x86pi_check_comp(mod);
187074bb90dSTom Pothier 	}
188074bb90dSTom Pothier 
189074bb90dSTom Pothier 	topo_mod_dprintf(mod, "%s: SMBIOS x86pi compliance: %s\n", f,
190074bb90dSTom Pothier 	    complvl == X86PI_FULL ? "FULL" : "NONE");
191074bb90dSTom Pothier 
192074bb90dSTom Pothier 	if (complvl == X86PI_NONE) {
193074bb90dSTom Pothier 		/* fall back to legacy enumeration */
194074bb90dSTom Pothier 		topo_mod_dprintf(mod,
195074bb90dSTom Pothier 		    "%s: Calling legacy enumeration\n", f);
196074bb90dSTom Pothier 
197074bb90dSTom Pothier 		return (topo_mod_enummap(mod, x86pi->t_parent,
198074bb90dSTom Pothier 		    "i86pc-legacy", FM_FMRI_SCHEME_HC));
199074bb90dSTom Pothier 	}
200074bb90dSTom Pothier 
201074bb90dSTom Pothier 	x86pi->priv = (void *)shp;
202074bb90dSTom Pothier 	x86pi_smbios = complvl;
203074bb90dSTom Pothier 
204074bb90dSTom Pothier 	if (x86pi_hbr_enum_init(mod) < 0) {
205074bb90dSTom Pothier 		topo_mod_dprintf(mod, "%s: x86pi_hbr_enum_init() failed.\n", f);
206074bb90dSTom Pothier 		return (-1);
207074bb90dSTom Pothier 	}
208074bb90dSTom Pothier 
209074bb90dSTom Pothier 	/*
210074bb90dSTom Pothier 	 * Create the topology.
211074bb90dSTom Pothier 	 */
212074bb90dSTom Pothier 	fac_done = 0;
213efd31e1dSTrang Do 	rv = x86pi_enum_gentopo(mod, x86pi->t_parent);
2145677a1bfSCheng Sean Ye 
2155677a1bfSCheng Sean Ye 	x86pi_hbr_enum_fini(mod);
2165677a1bfSCheng Sean Ye 
217074bb90dSTom Pothier 	if (rv != 0) {
218074bb90dSTom Pothier 		return (-1);
219074bb90dSTom Pothier 	}
220074bb90dSTom Pothier 	x86pi->mod = mod;
221074bb90dSTom Pothier 
222074bb90dSTom Pothier 	if (fac_done == 0) {
223a98ca9daSTom Pothier 		(void) topo_mod_enummap(mod, motherchassis_node, "chassis",
224074bb90dSTom Pothier 		    FM_FMRI_SCHEME_HC);
225a98ca9daSTom Pothier 		(void) topo_mod_enummap(mod, motherchassis_node, "fan",
226074bb90dSTom Pothier 		    FM_FMRI_SCHEME_HC);
227a98ca9daSTom Pothier 		(void) topo_mod_enummap(mod, motherchassis_node, "psu",
228074bb90dSTom Pothier 		    FM_FMRI_SCHEME_HC);
229074bb90dSTom Pothier 	}
230074bb90dSTom Pothier 
231074bb90dSTom Pothier 	/* All done */
232074bb90dSTom Pothier 	topo_mod_dprintf(mod, "%s: done.\n", f);
233074bb90dSTom Pothier 	return (rv);
234074bb90dSTom Pothier }
235074bb90dSTom Pothier 
236074bb90dSTom Pothier /*
237074bb90dSTom Pothier  * Create the i86pc topology
238074bb90dSTom Pothier  *
239074bb90dSTom Pothier  * If either Type 2 or Type 3 structures have contained elements/handles,
240074bb90dSTom Pothier  * walk them creating the topo.
241074bb90dSTom Pothier  *
242074bb90dSTom Pothier  * If there are no contained elements/handles, build this topo:
243074bb90dSTom Pothier  *
244074bb90dSTom Pothier  *    Main Chassis
245074bb90dSTom Pothier  *      Motherboard
246074bb90dSTom Pothier  *        CMP Chip/Core/Strands
247074bb90dSTom Pothier  *          Memory Controllers/Memory Devices (DIMMs)
248074bb90dSTom Pothier  *        PCIE HostBrige
249074bb90dSTom Pothier  *          PCIE Root Complex
250074bb90dSTom Pothier  *
251074bb90dSTom Pothier  */
252074bb90dSTom Pothier static int
x86pi_enum_gentopo(topo_mod_t * mod,tnode_t * t_parent)253efd31e1dSTrang Do x86pi_enum_gentopo(topo_mod_t *mod, tnode_t *t_parent)
254074bb90dSTom Pothier {
255074bb90dSTom Pothier 	int		rv;
256074bb90dSTom Pothier 	int		nch, nbb, ncmp, i;
257074bb90dSTom Pothier 	int		ch_smbid, bb_smbid;
258074bb90dSTom Pothier 	tnode_t		*chassis_node = NULL;
259074bb90dSTom Pothier 	tnode_t		*basebd_node = NULL;
260074bb90dSTom Pothier 	smbs_cnt_t	*smbc;
261074bb90dSTom Pothier 	tnode_t		*pnode = NULL;
262074bb90dSTom Pothier 	id_t		psmbid;
263074bb90dSTom Pothier 	int		notvisited;
264074bb90dSTom Pothier 	int		bb_count, ch_count;
265074bb90dSTom Pothier 	int		min, max;
266074bb90dSTom Pothier 	int		ch_inst = 0;
26703f9f63dSTom Pothier 	int		disk_inst = 0;
268074bb90dSTom Pothier 	topo_instance_t	 hbri = 0, rci = 0;
269074bb90dSTom Pothier 	smbios_pciexrc_t hbr;
27003f9f63dSTom Pothier 	smbios_port_ext_t export;
271074bb90dSTom Pothier 	char		*f = "x86pi_enum_gentopo";
2722a685872SToomas Soome 	smbios_hdl_t	*shp;
273efd31e1dSTrang Do 
274efd31e1dSTrang Do 	shp = topo_mod_smbios(mod);
275efd31e1dSTrang Do 	if (shp == NULL) {
276efd31e1dSTrang Do 		topo_mod_dprintf(mod, "%s: failed to load SMBIOS\n", f);
277efd31e1dSTrang Do 		return (-1);
278efd31e1dSTrang Do 	}
279074bb90dSTom Pothier 
280074bb90dSTom Pothier 	if (t_parent == NULL) {
281074bb90dSTom Pothier 		topo_mod_dprintf(mod, "%s: NULL parent\n", f);
282074bb90dSTom Pothier 		return (-1);
283074bb90dSTom Pothier 	}
284074bb90dSTom Pothier 
285074bb90dSTom Pothier 	/*
286074bb90dSTom Pothier 	 * "Chassis'"
287074bb90dSTom Pothier 	 */
288074bb90dSTom Pothier 	/* Type 3 structs */
289074bb90dSTom Pothier 	stypes[SMB_TYPE_CHASSIS].type = SMB_TYPE_CHASSIS;
290efd31e1dSTrang Do 	x86pi_smb_strcnt(mod, &stypes[SMB_TYPE_CHASSIS]);
291074bb90dSTom Pothier 
292074bb90dSTom Pothier 	ch_count = stypes[SMB_TYPE_CHASSIS].count;
293074bb90dSTom Pothier 
294074bb90dSTom Pothier 	for (nch = 0; nch < ch_count; nch++) {
295074bb90dSTom Pothier 		topo_mod_dprintf(mod, "%s: found %d chassis\n", f,
296074bb90dSTom Pothier 		    stypes[SMB_TYPE_CHASSIS].count);
297074bb90dSTom Pothier 
298074bb90dSTom Pothier 		ch_smbid = stypes[SMB_TYPE_CHASSIS].ids[nch].id;
299074bb90dSTom Pothier 
300074bb90dSTom Pothier 		/*
301074bb90dSTom Pothier 		 * Expect SMBIOS to set the first Chassis Structure to be the
302074bb90dSTom Pothier 		 * parent/mother of all chassis
303074bb90dSTom Pothier 		 */
304074bb90dSTom Pothier 		if (nch == 0)
305074bb90dSTom Pothier 			motherchassis_node = chassis_node =
306efd31e1dSTrang Do 			    x86pi_gen_chassis(mod, t_parent, ch_smbid,
307efd31e1dSTrang Do 			    ch_inst++);
308074bb90dSTom Pothier 		else {
309074bb90dSTom Pothier 			if (motherchassis_node != NULL)
310074bb90dSTom Pothier 				chassis_node = x86pi_gen_chassis(mod,
311efd31e1dSTrang Do 				    motherchassis_node, ch_smbid, ch_inst++);
312074bb90dSTom Pothier 			else
313074bb90dSTom Pothier 				chassis_node = x86pi_gen_chassis(mod,
314efd31e1dSTrang Do 				    t_parent, ch_smbid, ch_inst++);
315074bb90dSTom Pothier 		}
316074bb90dSTom Pothier 
317074bb90dSTom Pothier 		if (chassis_node == NULL) {
318074bb90dSTom Pothier 			topo_mod_dprintf(mod,
319074bb90dSTom Pothier 			    "%s: Failed to create chassis %d\n", f, nch);
320074bb90dSTom Pothier 			continue;
321074bb90dSTom Pothier 		}
322074bb90dSTom Pothier 		stypes[SMB_TYPE_CHASSIS].ids[nch].node = chassis_node;
32303f9f63dSTom Pothier 
32403f9f63dSTom Pothier 		/* count SMBIOS extended port connector structures */
32503f9f63dSTom Pothier 		smbc = &stypes[SUN_OEM_EXT_PORT];
32603f9f63dSTom Pothier 		smbc->type = SUN_OEM_EXT_PORT;
327efd31e1dSTrang Do 		x86pi_smb_strcnt(mod, smbc);
32803f9f63dSTom Pothier 
32905ead181SVuong Nguyen 		/*
33005ead181SVuong Nguyen 		 * enumerate direct attached SATA disks if we found a
33105ead181SVuong Nguyen 		 * SUN_OEM_EXT_PORT record.
33205ead181SVuong Nguyen 		 */
33305ead181SVuong Nguyen 		if (smbc->count > 0) {
33405ead181SVuong Nguyen 			rv = topo_node_range_create(mod, chassis_node, BAY, 0,
33505ead181SVuong Nguyen 			    smbc->count + 1);
33605ead181SVuong Nguyen 			if (rv != 0) {
33705ead181SVuong Nguyen 				topo_mod_dprintf(mod,
33805ead181SVuong Nguyen 				    "%s: Failed to create %s range: %s\n",
33905ead181SVuong Nguyen 				    f, BAY, topo_mod_errmsg(mod));
34005ead181SVuong Nguyen 				continue;
34105ead181SVuong Nguyen 			}
34205ead181SVuong Nguyen 		} else {
34303f9f63dSTom Pothier 			topo_mod_dprintf(mod,
34405ead181SVuong Nguyen 			    "Skipping disk bay enumeration\n");
34503f9f63dSTom Pothier 		}
34603f9f63dSTom Pothier 
34703f9f63dSTom Pothier 		for (i = 0; i < smbc->count; i++) {
34803f9f63dSTom Pothier 			if (smbios_info_extport(shp, smbc->ids[i].id,
34903f9f63dSTom Pothier 			    &export) != 0) {
35003f9f63dSTom Pothier 				topo_mod_dprintf(mod,
35103f9f63dSTom Pothier 				    "smbios_info_export failed: id = %d\n",
35203f9f63dSTom Pothier 				    (int)smbc->ids[i].id);
35303f9f63dSTom Pothier 				continue;
35403f9f63dSTom Pothier 			}
35503f9f63dSTom Pothier 			if (export.smbporte_chassis != ch_smbid)
35603f9f63dSTom Pothier 				continue;
35703f9f63dSTom Pothier 
35803f9f63dSTom Pothier 			/*
35903f9f63dSTom Pothier 			 * x86pi_gen_bay:
36003f9f63dSTom Pothier 			 *   create "bay" node
36103f9f63dSTom Pothier 			 *   call "disk" enum passing in "bay" node
36203f9f63dSTom Pothier 			 */
363efd31e1dSTrang Do 			rv = x86pi_gen_bay(mod, chassis_node, &export,
364efd31e1dSTrang Do 			    disk_inst);
36503f9f63dSTom Pothier 			if (rv != 0)
36603f9f63dSTom Pothier 				topo_mod_dprintf(mod,
36703f9f63dSTom Pothier 				    "Failed to create disk %d\n", i);
36803f9f63dSTom Pothier 			disk_inst++;
36903f9f63dSTom Pothier 		}
370074bb90dSTom Pothier 	}
371074bb90dSTom Pothier 
372074bb90dSTom Pothier 	/*
373074bb90dSTom Pothier 	 * "Base Board"
374074bb90dSTom Pothier 	 */
375074bb90dSTom Pothier 	/* Type 2 structs */
376074bb90dSTom Pothier 	stypes[SMB_TYPE_BASEBOARD].type = SMB_TYPE_BASEBOARD;
377efd31e1dSTrang Do 	x86pi_smb_strcnt(mod, &stypes[SMB_TYPE_BASEBOARD]);
378074bb90dSTom Pothier 	bb_count = notvisited = stypes[SMB_TYPE_BASEBOARD].count;
379074bb90dSTom Pothier 
380074bb90dSTom Pothier 	for (nbb = 0; nbb < bb_count; nbb++) {
381074bb90dSTom Pothier 		stypes[SMB_TYPE_BASEBOARD].ids[nbb].visited = 0;
382074bb90dSTom Pothier 		stypes[SMB_TYPE_BASEBOARD].ids[nbb].con_by_id = 0;
383074bb90dSTom Pothier 		stypes[SMB_TYPE_BASEBOARD].ids[nbb].node = NULL;
384074bb90dSTom Pothier 	}
385efd31e1dSTrang Do 	(void) x86pi_bb_contains(mod);
386074bb90dSTom Pothier 
387074bb90dSTom Pothier 	min = 0;
388074bb90dSTom Pothier 	nbb = 0;
389074bb90dSTom Pothier 	do {
390074bb90dSTom Pothier 		/*
391074bb90dSTom Pothier 		 * We have reached end of the array due to the
392074bb90dSTom Pothier 		 * parent-child relationship, without visiting all
393074bb90dSTom Pothier 		 * baseboards! so re-iterate..
394074bb90dSTom Pothier 		 * (or)
395074bb90dSTom Pothier 		 * All baseboards are visited and their contained
396074bb90dSTom Pothier 		 * processors are enumerated
397074bb90dSTom Pothier 		 * (and/or)
398074bb90dSTom Pothier 		 * More baseboards pending a visit
399074bb90dSTom Pothier 		 */
400074bb90dSTom Pothier 		if (nbb > bb_count && notvisited)
401074bb90dSTom Pothier 			nbb = 0;
402074bb90dSTom Pothier 		else if (nbb > bb_count && !notvisited)
403074bb90dSTom Pothier 			break;
404074bb90dSTom Pothier 		if (stypes[SMB_TYPE_BASEBOARD].ids[nbb].visited ==
405074bb90dSTom Pothier 		    X86PI_VISITED) {
406074bb90dSTom Pothier 			nbb++;
407074bb90dSTom Pothier 			continue;
408074bb90dSTom Pothier 		}
409074bb90dSTom Pothier 
410074bb90dSTom Pothier 		/*
411074bb90dSTom Pothier 		 * Get the Top-most Parent Baseboard, irrespective
412074bb90dSTom Pothier 		 * of its index in the array of Type-2s
413074bb90dSTom Pothier 		 * If this Baseboard has no Baseboard parents
414074bb90dSTom Pothier 		 * place it under the chassis that contains it
415074bb90dSTom Pothier 		 */
416efd31e1dSTrang Do 		bb_smbid = x86pi_bb_topparent(mod, nbb, &pnode, &psmbid);
417074bb90dSTom Pothier 		if (bb_smbid == -1 || pnode == NULL) {
418074bb90dSTom Pothier 			topo_mod_dprintf(mod,
419074bb90dSTom Pothier 			    "Failed to get BaseBoard node (%d): parent\n",
420074bb90dSTom Pothier 			    nbb);
421074bb90dSTom Pothier 			return (-1);
422074bb90dSTom Pothier 		}
423074bb90dSTom Pothier 
424074bb90dSTom Pothier 		if (stypes[SMB_TYPE_BASEBOARD].ids[nbb].id != bb_smbid) {
425074bb90dSTom Pothier 			for (int i = 0; i < bb_count; i++) {
426074bb90dSTom Pothier 				if (bb_smbid ==
427074bb90dSTom Pothier 				    stypes[SMB_TYPE_BASEBOARD].ids[i].id) {
428074bb90dSTom Pothier 					stypes[SMB_TYPE_BASEBOARD].ids[i].\
429074bb90dSTom Pothier 					    visited = 1;
430074bb90dSTom Pothier 					notvisited--;
431074bb90dSTom Pothier 					break;
432074bb90dSTom Pothier 				}
433074bb90dSTom Pothier 			}
434074bb90dSTom Pothier 		} else {
435074bb90dSTom Pothier 			stypes[SMB_TYPE_BASEBOARD].ids[nbb].visited = 1;
436074bb90dSTom Pothier 			notvisited--;
437074bb90dSTom Pothier 		}
438074bb90dSTom Pothier 
439efd31e1dSTrang Do 		basebd_node = x86pi_gen_bboard(mod, pnode, bb_smbid,
440efd31e1dSTrang Do 		    nbb, psmbid);
441074bb90dSTom Pothier 		if (basebd_node == NULL) {
442074bb90dSTom Pothier 			topo_mod_dprintf(mod,
443074bb90dSTom Pothier 			    "Failed to create BaseBoard node (%d)\n", nbb);
444074bb90dSTom Pothier 			nbb++;
445074bb90dSTom Pothier 			continue;
446074bb90dSTom Pothier 		}
447074bb90dSTom Pothier 
448074bb90dSTom Pothier 		stypes[SMB_TYPE_BASEBOARD].ids[nbb].node = basebd_node;
449074bb90dSTom Pothier 		/*
450074bb90dSTom Pothier 		 * Look for contained handles here and if there are
451074bb90dSTom Pothier 		 * make sure the chip handle below is part of it.
452074bb90dSTom Pothier 		 */
453efd31e1dSTrang Do 		ncmp = x86pi_bb_getchips(mod, nbb, bb_count);
454074bb90dSTom Pothier 		if (ncmp > 0) {
455074bb90dSTom Pothier 			max = min + ncmp - 1;
456074bb90dSTom Pothier 			/* make sure the chip enum is loaded */
457074bb90dSTom Pothier 			topo_mod_dprintf(mod, "%s: loading chip enum\n", f);
458074bb90dSTom Pothier 
459074bb90dSTom Pothier 			if (topo_mod_load(mod, CHIP, TOPO_VERSION) == NULL) {
460074bb90dSTom Pothier 				topo_mod_dprintf(mod,
461074bb90dSTom Pothier 				    "%s: Failed to load %s module: %s\n", f,
462074bb90dSTom Pothier 				    CHIP, topo_strerror(topo_mod_errno(mod)));
463074bb90dSTom Pothier 			} else {
464074bb90dSTom Pothier 				/* create node range */
465074bb90dSTom Pothier 				topo_mod_dprintf(mod,
466074bb90dSTom Pothier 				    "%s: chip range %d to %d\n",
467074bb90dSTom Pothier 				    f, min, max);
468074bb90dSTom Pothier 				rv = topo_node_range_create(mod, basebd_node,
469074bb90dSTom Pothier 				    CHIP, min, max);
470074bb90dSTom Pothier 				if (rv != 0) {
471074bb90dSTom Pothier 					topo_mod_dprintf(mod,
472074bb90dSTom Pothier 					    "%s: Failed to create node range: "
473074bb90dSTom Pothier 					    "%s\n", f,
474074bb90dSTom Pothier 					    topo_strerror(topo_mod_errno(mod)));
475074bb90dSTom Pothier 				} else {
476074bb90dSTom Pothier 					/* call the chip enumerator */
477074bb90dSTom Pothier 					topo_mod_dprintf(mod, "%s: calling"
478074bb90dSTom Pothier 					    " chip enum\n", f);
479074bb90dSTom Pothier 					rv =
480074bb90dSTom Pothier 					    topo_mod_enumerate(mod, basebd_node,
481074bb90dSTom Pothier 					    CHIP, CHIP, min, max,
482074bb90dSTom Pothier 					    &x86pi_smbios);
483074bb90dSTom Pothier 					min = max + 1;
484074bb90dSTom Pothier 					if (rv != 0)
485074bb90dSTom Pothier 						topo_mod_dprintf(mod, "%s:%s"
486074bb90dSTom Pothier 						    "enumeration failed: \n",
487074bb90dSTom Pothier 						    f, CHIP);
488074bb90dSTom Pothier 				}
489074bb90dSTom Pothier 			}
490074bb90dSTom Pothier 		}
491074bb90dSTom Pothier 
492074bb90dSTom Pothier 		/* enumerate the hostbridge node */
493074bb90dSTom Pothier 		rv = topo_node_range_create(mod, basebd_node, HOSTBRIDGE,
494074bb90dSTom Pothier 		    0, 255);
495074bb90dSTom Pothier 		if (rv != 0) {
496074bb90dSTom Pothier 			topo_mod_dprintf(mod,
497074bb90dSTom Pothier 			    "%s: Failed to create %s range: %s\n",
498074bb90dSTom Pothier 			    f, HOSTBRIDGE, topo_mod_errmsg(mod));
499074bb90dSTom Pothier 			continue;
500074bb90dSTom Pothier 		}
501074bb90dSTom Pothier 
502074bb90dSTom Pothier 		smbc = &stypes[SUN_OEM_PCIEXRC];
503074bb90dSTom Pothier 		smbc->type = SUN_OEM_PCIEXRC;
504efd31e1dSTrang Do 		x86pi_smb_strcnt(mod, smbc);
505074bb90dSTom Pothier 		for (i = 0; i < smbc->count; i++) {
506074bb90dSTom Pothier 			if (smbios_info_pciexrc(shp, smbc->ids[i].id,
507074bb90dSTom Pothier 			    &hbr) != 0) {
508074bb90dSTom Pothier 				topo_mod_dprintf(mod,
509074bb90dSTom Pothier 				    "smbios_info_pciexrc failed: "
510074bb90dSTom Pothier 				    "id = %d\n", (int)smbc->ids[i].id);
511074bb90dSTom Pothier 				continue;
512074bb90dSTom Pothier 			}
513074bb90dSTom Pothier 
514074bb90dSTom Pothier 			if (hbr.smbpcie_bb != bb_smbid)
515074bb90dSTom Pothier 				continue;
516efd31e1dSTrang Do 			rv = x86pi_gen_hbr(mod, basebd_node,
517074bb90dSTom Pothier 			    smbc->ids[i].id, hbri, &rci);
518*6597d6fcSRobert Mustacchi 			if (rv != 0) {
519*6597d6fcSRobert Mustacchi 				topo_mod_dprintf(mod, "couldn't create "
520*6597d6fcSRobert Mustacchi 				    "hostbridge=%" PRIu64 "\n", hbri);
521*6597d6fcSRobert Mustacchi 			}
522074bb90dSTom Pothier 			hbri++;
523074bb90dSTom Pothier 		}
524074bb90dSTom Pothier 		nbb++;
525074bb90dSTom Pothier 
526074bb90dSTom Pothier 	} while (notvisited);
527074bb90dSTom Pothier 
528074bb90dSTom Pothier 	return (0);
529074bb90dSTom Pothier }
530