113faa91sd/*
213faa91sd * CDDL HEADER START
313faa91sd *
413faa91sd * The contents of this file are subject to the terms of the
513faa91sd * Common Development and Distribution License (the "License").
613faa91sd * You may not use this file except in compliance with the License.
713faa91sd *
813faa91sd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
913faa91sd * or http://www.opensolaris.org/os/licensing.
1013faa91sd * See the License for the specific language governing permissions
1113faa91sd * and limitations under the License.
1213faa91sd *
1313faa91sd * When distributing Covered Code, include this CDDL HEADER in each
1413faa91sd * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1513faa91sd * If applicable, add the following below this CDDL HEADER, with the
1613faa91sd * fields enclosed by brackets "[]" replaced with your own identifying
1713faa91sd * information: Portions Copyright [yyyy] [name of copyright owner]
1813faa91sd *
1913faa91sd * CDDL HEADER END
2013faa91sd */
2113faa91sd
2213faa91sd/*
23b64bfe7Trang Do * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
2413faa91sd */
2513faa91sd
2613faa91sd#include <stdlib.h>
2713faa91sd#include <string.h>
2813faa91sd#include <strings.h>
2913faa91sd#include <fm/topo_mod.h>
3013faa91sd#include <fm/topo_hc.h>
3113faa91sd#include <libdevinfo.h>
3213faa91sd#include <limits.h>
3313faa91sd#include <sys/fm/protocol.h>
3413faa91sd#include <sys/param.h>
3513faa91sd#include <sys/systeminfo.h>
3613faa91sd#include <assert.h>
3713faa91sd#include <sys/utsname.h>
3813faa91sd#include <sys/systeminfo.h>
3913faa91sd#include <fm/fmd_fmri.h>
4013faa91sd#include <sys/types.h>
4113faa91sd#include <sys/mdesc.h>
4213faa91sd#include <sys/fm/ldom.h>
4313faa91sd
4413faa91sd#include "cpuboard_topo.h"
4513faa91sd
4613faa91sd/*
4713faa91sd * cpuboard.c
4813faa91sd *	sun4v specific cpuboard enumerator
4913faa91sd */
5013faa91sd
5113faa91sd#ifdef __cplusplus
5213faa91sdextern "C" {
5313faa91sd#endif
5413faa91sd
5513faa91sd#define	CPUBOARD_VERSION	TOPO_VERSION
5613faa91sd
5713faa91sd/* Until future PRI changes, make connection between cpuboard id and RC */
5813faa91sdchar *cpub_rcs[] = { CPUBOARD0_RC, CPUBOARD1_RC, CPUBOARD2_RC, CPUBOARD3_RC };
5913faa91sd
6013faa91sdstatic int cpuboard_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t,
6113faa91sd		    topo_instance_t, void *, void *);
6213faa91sd
6313faa91sdstatic const topo_modops_t cpuboard_ops =
6413faa91sd	{ cpuboard_enum, NULL };
6513faa91sd
6613faa91sdconst topo_modinfo_t cpuboard_info =
6713faa91sd	{CPUBOARD, FM_FMRI_SCHEME_HC, CPUBOARD_VERSION, &cpuboard_ops};
6813faa91sd
6913faa91sdstatic const topo_pgroup_info_t cpuboard_auth_pgroup =
7013faa91sd	{ FM_FMRI_AUTHORITY, TOPO_STABILITY_PRIVATE,
7113faa91sd	    TOPO_STABILITY_PRIVATE, 1 };
7213faa91sd
7313faa91sdstatic topo_mod_t *cpuboard_mod_hdl = NULL;
7413faa91sd
7513faa91sdstatic void *
7613faa91sdcpuboard_topo_alloc(size_t size)
7713faa91sd{
7813faa91sd	assert(cpuboard_mod_hdl != NULL);
7913faa91sd	return (topo_mod_alloc(cpuboard_mod_hdl, size));
8013faa91sd}
8113faa91sd
8213faa91sdstatic void
8313faa91sdcpuboard_topo_free(void *data, size_t size)
8413faa91sd{
8513faa91sd	assert(cpuboard_mod_hdl != NULL);
8613faa91sd	topo_mod_free(cpuboard_mod_hdl, data, size);
8713faa91sd}
8813faa91sd
8913faa91sdstatic int
9013faa91sdcpuboard_get_pri_info(topo_mod_t *mod, cpuboard_contents_t cpubs[])
9113faa91sd{
9213faa91sd	char isa[MAXNAMELEN];
9313faa91sd	md_t *mdp;
9413faa91sd	mde_cookie_t *listp;
9513faa91sd	uint64_t *bufp;
9613faa91sd	ssize_t bufsize = 0;
9713faa91sd	int  ncomp, num_nodes, i, len;
9813faa91sd	char *pstr = NULL;
9913faa91sd	char *sn = NULL, *pn = NULL;
10013faa91sd	char *dn = NULL;
1012535165Vuong Nguyen	uint32_t type = 0;
10213faa91sd	ldom_hdl_t *lhp;
10313faa91sd	uint64_t id;
10467d4b2fgk	int cpuboards_found = 0;
10513faa91sd
10613faa91sd	lhp = ldom_init(cpuboard_topo_alloc, cpuboard_topo_free);
10713faa91sd	if (lhp == NULL) {
10813faa91sd		topo_mod_dprintf(mod, "ldom_init failed\n");
10967d4b2fgk		return (0);
11013faa91sd	}
11113faa91sd
11213faa91sd	(void) sysinfo(SI_MACHINE, isa, MAXNAMELEN);
11313faa91sd	if (strcmp(isa, "sun4v") != 0) {
11413faa91sd		topo_mod_dprintf(mod, "not sun4v architecture%s\n", isa);
11513faa91sd		ldom_fini(lhp);
11667d4b2fgk		return (0);
11713faa91sd	}
11813faa91sd
1192535165Vuong Nguyen	(void) ldom_get_type(lhp, &type);
1202535165Vuong Nguyen	if ((type & LDOM_TYPE_CONTROL) != 0) {
1212535165Vuong Nguyen		bufsize = ldom_get_core_md(lhp, &bufp);
1222535165Vuong Nguyen	} else {
1232535165Vuong Nguyen		bufsize = ldom_get_local_md(lhp, &bufp);
1242535165Vuong Nguyen	}
1252535165Vuong Nguyen	if (bufsize < 1) {
1262535165Vuong Nguyen		topo_mod_dprintf(mod, "Failed to get pri/md, bufsize=%d\n",
12713faa91sd		    bufsize);
12813faa91sd		ldom_fini(lhp);
12967d4b2fgk		return (0);
13013faa91sd	}
1312535165Vuong Nguyen	topo_mod_dprintf(mod, "pri/md bufsize=%d\n", bufsize);
13213faa91sd
13313faa91sd	if ((mdp = md_init_intern(bufp, cpuboard_topo_alloc,
13413faa91sd	    cpuboard_topo_free)) == NULL ||
13513faa91sd	    (num_nodes = md_node_count(mdp)) < 1) {
13613faa91sd		topo_mod_dprintf(mod, "md_init_intern error\n");
13713faa91sd		cpuboard_topo_free(bufp, (size_t)bufsize);
13813faa91sd		ldom_fini(lhp);
13967d4b2fgk		return (0);
14013faa91sd	}
14113faa91sd	topo_mod_dprintf(mod, "num_nodes=%d\n", num_nodes);
14213faa91sd
14313faa91sd	if ((listp = (mde_cookie_t *)cpuboard_topo_alloc(
14413faa91sd	    sizeof (mde_cookie_t) * num_nodes)) == NULL) {
14513faa91sd		topo_mod_dprintf(mod, "alloc listp error\n");
14613faa91sd		cpuboard_topo_free(bufp, (size_t)bufsize);
14713faa91sd		(void) md_fini(mdp);
14813faa91sd		ldom_fini(lhp);
14967d4b2fgk		return (0);
15013faa91sd	}
15113faa91sd	ncomp = md_scan_dag(mdp, MDE_INVAL_ELEM_COOKIE,
15213faa91sd	    md_find_name(mdp, "component"),
15313faa91sd	    md_find_name(mdp, "fwd"), listp);
15413faa91sd	topo_mod_dprintf(mod, "ncomp=%d\n", ncomp);
15513faa91sd	if (ncomp <= 0) {
15613faa91sd		cpuboard_topo_free(listp, sizeof (mde_cookie_t) * num_nodes);
15713faa91sd		cpuboard_topo_free(bufp, (size_t)bufsize);
15813faa91sd		(void) md_fini(mdp);
15913faa91sd		ldom_fini(lhp);
16067d4b2fgk		return (0);
16113faa91sd	}
16213faa91sd	for (i = 0; i < ncomp; i++) {
16313faa91sd		/*
16413faa91sd		 * PRI nodes are still named "cpu-board", but the canonical
16513faa91sd		 * names are "cpuboard".
16613faa91sd		 */
16713faa91sd		if (md_get_prop_str(mdp, listp[i], "type", &pstr) == 0 &&
16813faa91sd		    pstr != NULL && strcmp(pstr, "cpu-board") == 0) {
16913faa91sd			if (md_get_prop_val(mdp, listp[i], "id", &id) < 0) {
17013faa91sd				topo_mod_dprintf(mod, "cpuboard_get_pri_info: "
17113faa91sd				    "id md_get_prop_val() failed. (%d: %s)\n",
17213faa91sd				    errno, strerror(errno));
17313faa91sd				continue;
17413faa91sd			}
17513faa91sd			if ((id >= CPUBOARD_MAX) || cpubs[id].present) {
176186d582Surya Prakki				(void) topo_mod_seterrno(mod, EMOD_NVL_INVAL);
17713faa91sd				topo_mod_dprintf(mod, "cpuboard_get_pri_info: "
17813faa91sd				    "id %llx out of range. (%d: %s)\n",
17913faa91sd				    id, errno, strerror(errno));
18013faa91sd				continue;
18113faa91sd			}
18213faa91sd			cpubs[id].present = 1;
18367d4b2fgk			cpuboards_found++;
18413faa91sd
18513faa91sd			topo_mod_dprintf(mod, "got cpu-board: %llx\n", id);
18613faa91sd
18713faa91sd			sn = pn = dn = NULL;
18813faa91sd
18913faa91sd			(void) md_get_prop_str(mdp, listp[i],
19013faa91sd			    "serial_number", &sn);
19113faa91sd			cpubs[id].sn = topo_mod_strdup(mod, sn);
19213faa91sd
19313faa91sd			(void) md_get_prop_str(mdp, listp[i],
19413faa91sd			    "part_number", &pn);
19513faa91sd
19613faa91sd			(void) md_get_prop_str(mdp, listp[i],
19713faa91sd			    "dash_number", &dn);
19813faa91sd			len = (pn ? strlen(pn) : 0) + (dn ? strlen(dn) : 0) + 1;
19913faa91sd			pstr = cpuboard_topo_alloc(len);
20013faa91sd			(void) snprintf(pstr, len, "%s%s",
20113faa91sd			    pn ? pn : "", dn ? dn : "");
20213faa91sd			cpubs[id].pn = topo_mod_strdup(mod, pstr);
20313faa91sd			cpuboard_topo_free(pstr, len);
20413faa91sd		}
20513faa91sd	}
20613faa91sd	cpuboard_topo_free(listp, sizeof (mde_cookie_t) * num_nodes);
20713faa91sd	cpuboard_topo_free(bufp, (size_t)bufsize);
20813faa91sd	(void) md_fini(mdp);
20913faa91sd	ldom_fini(lhp);
21013faa91sd
21167d4b2fgk	return (cpuboards_found);
21213faa91sd}
21313faa91sd
21413faa91sd/*ARGSUSED*/
21513faa91sdvoid
21613faa91sd_topo_init(topo_mod_t *mod, topo_version_t version)
21713faa91sd{
21813faa91sd	/*
21913faa91sd	 * Turn on module debugging output
22013faa91sd	 */
22113faa91sd	if (getenv("TOPOCPUBOARDDBG") != NULL) {
22213faa91sd		topo_mod_setdebug(mod);
22313faa91sd	}
22413faa91sd	topo_mod_dprintf(mod, "initializing cpuboard enumerator\n");
22513faa91sd
22613faa91sd	if (topo_mod_register(mod, &cpuboard_info, TOPO_VERSION) < 0) {
22713faa91sd		topo_mod_dprintf(mod, "cpuboard registration failed: %s\n",
22813faa91sd		    topo_mod_errmsg(mod));
22913faa91sd		return; /* mod errno already set */
23013faa91sd	}
23113faa91sd	topo_mod_dprintf(mod, "cpuboard enumr initd\n");
23213faa91sd}
23313faa91sd
23413faa91sdvoid
23513faa91sd_topo_fini(topo_mod_t *mod)
23613faa91sd{
23713faa91sd	topo_mod_unregister(mod);
23813faa91sd}
23913faa91sd
24013faa91sdstatic tnode_t *
24113faa91sdcpuboard_tnode_create(topo_mod_t *mod, tnode_t *parent,
24213faa91sd    const char *name, topo_instance_t i, void *priv, cpuboard_contents_t *cpubc)
24313faa91sd{
24413faa91sd	int err;
24513faa91sd	nvlist_t *fmri;
24613faa91sd	tnode_t *ntn;
24713faa91sd	nvlist_t *auth = topo_mod_auth(mod, parent);
24813faa91sd
24913faa91sd	fmri = topo_mod_hcfmri(mod, parent, FM_HC_SCHEME_VERSION, name, i,
25013faa91sd	    NULL, auth, cpubc->pn, NULL, cpubc->sn);
25113faa91sd	nvlist_free(auth);
25213faa91sd
25313faa91sd	if (fmri == NULL) {
25413faa91sd		topo_mod_dprintf(mod,
25513faa91sd		    "Unable to make nvlist for %s bind: %s.\n",
25613faa91sd		    name, topo_mod_errmsg(mod));
25713faa91sd		return (NULL);
25813faa91sd	}
25913faa91sd
26013faa91sd	ntn = topo_node_bind(mod, parent, name, i, fmri);
26113faa91sd	if (ntn == NULL) {
26213faa91sd		topo_mod_dprintf(mod,
26313faa91sd		    "topo_node_bind (%s%d/%s%d) failed: %s\n",
26413faa91sd		    topo_node_name(parent), topo_node_instance(parent),
26513faa91sd		    name, i,
26613faa91sd		    topo_strerror(topo_mod_errno(mod)));
26713faa91sd		nvlist_free(fmri);
26813faa91sd		return (NULL);
26913faa91sd	}
27013faa91sd	topo_mod_dprintf(mod,
27113faa91sd	    "cpuboard_tnode_create: topo_node_bind (%s%d/%s%d) created!\n",
27213faa91sd	    topo_node_name(parent), topo_node_instance(parent), name, i);
27313faa91sd	nvlist_free(fmri);
27413faa91sd	topo_node_setspecific(ntn, priv);
27513faa91sd
27613faa91sd	if (topo_pgroup_create(ntn, &cpuboard_auth_pgroup, &err) == 0) {
27713faa91sd		(void) topo_prop_inherit(ntn, FM_FMRI_AUTHORITY,
27813faa91sd		    FM_FMRI_AUTH_PRODUCT, &err);
27913faa91sd		(void) topo_prop_inherit(ntn, FM_FMRI_AUTHORITY,
2809c94f15Cheng Sean Ye		    FM_FMRI_AUTH_PRODUCT_SN, &err);
2819c94f15Cheng Sean Ye		(void) topo_prop_inherit(ntn, FM_FMRI_AUTHORITY,
28213faa91sd		    FM_FMRI_AUTH_CHASSIS, &err);
28313faa91sd		(void) topo_prop_inherit(ntn, FM_FMRI_AUTHORITY,
28413faa91sd		    FM_FMRI_AUTH_SERVER, &err);
28513faa91sd	}
28613faa91sd
28713faa91sd	return (ntn);
28813faa91sd}
28913faa91sd
29013faa91sdstatic int
29113faa91sdcpuboard_fru_set(topo_mod_t *mp, tnode_t *tn)
29213faa91sd{
29313faa91sd	nvlist_t *fmri;
29413faa91sd	int err, e;
29513faa91sd
29613faa91sd	if (topo_node_resource(tn, &fmri, &err) < 0 ||
29713faa91sd	    fmri == NULL) {
29813faa91sd		topo_mod_dprintf(mp, "FRU_fmri_set error: %s\n",
29913faa91sd		    topo_strerror(topo_mod_errno(mp)));
30013faa91sd		return (topo_mod_seterrno(mp, err));
30113faa91sd	}
30213faa91sd	e = topo_node_fru_set(tn, fmri, 0, &err);
30313faa91sd	nvlist_free(fmri);
30413faa91sd	if (e < 0)
30513faa91sd		return (topo_mod_seterrno(mp, err));
30613faa91sd	return (0);
30713faa91sd}
30813faa91sd
30913faa91sdstatic int
31013faa91sdcpuboard_label_set(topo_mod_t *mod, tnode_t *parent, tnode_t *node,
31113faa91sd	topo_instance_t n)
31213faa91sd{
31313faa91sd	char *label = NULL;
31413faa91sd	char *plabel = NULL;
31513faa91sd	const char *cpuboard_label = "/CPU";
31613faa91sd	int err, len;
31713faa91sd
31813faa91sd	if (topo_node_label(parent, &plabel, &err) != 0 ||
31913faa91sd	    plabel == NULL) {
32013faa91sd		return (-1);
32113faa91sd	}
32213faa91sd
32313faa91sd	len = strlen(plabel) + strlen(cpuboard_label) + 2;
32413faa91sd	label = topo_mod_alloc(mod, len);
32513faa91sd	(void) snprintf(label, len, "%s%s%d", plabel, cpuboard_label, n);
32613faa91sd	topo_mod_strfree(mod, plabel);
32713faa91sd
32813faa91sd	if (label != NULL) {
32913faa91sd		if (topo_prop_set_string(node, TOPO_PGROUP_PROTOCOL,
33013faa91sd		    TOPO_PROP_LABEL, TOPO_PROP_IMMUTABLE, label,
33113faa91sd		    &err) != 0) {
33213faa91sd			topo_mod_strfree(mod, label);
33313faa91sd			return (topo_mod_seterrno(mod, err));
33413faa91sd		}
33513faa91sd	}
33613faa91sd	topo_mod_free(mod, label, len);
33713faa91sd	return (0);
33813faa91sd}
33913faa91sd
34013faa91sd
34113faa91sd/*ARGSUSED*/
34213faa91sdstatic tnode_t *
34313faa91sdcpuboard_declare(tnode_t *parent, const char *name, topo_instance_t i,
34413faa91sd	void *priv, topo_mod_t *mod, cpuboard_contents_t *cpubc)
34513faa91sd{
34613faa91sd	tnode_t *ntn;
34713faa91sd	nvlist_t *fmri = NULL;
34813faa91sd	int err;
34913faa91sd
35013faa91sd	if ((ntn = cpuboard_tnode_create(mod, parent, name, i, priv,
35113faa91sd	    cpubc)) == NULL) {
35213faa91sd		topo_mod_dprintf(mod, "%s ntn = NULL\n", name);
35313faa91sd		return (NULL);
35413faa91sd	}
35513faa91sd
35613faa91sd	(void) cpuboard_fru_set(mod, ntn);
35713faa91sd
35813faa91sd	(void) cpuboard_label_set(mod, parent, ntn, i);
35913faa91sd
36013faa91sd	/* set ASRU to resource fmri */
36113faa91sd	if (topo_prop_get_fmri(ntn, TOPO_PGROUP_PROTOCOL,
36213faa91sd	    TOPO_PROP_RESOURCE, &fmri, &err) == 0)
36313faa91sd		(void) topo_node_asru_set(ntn, fmri, 0, &err);
36413faa91sd	nvlist_free(fmri);
36513faa91sd
36613faa91sd	return (ntn);
36713faa91sd}
36813faa91sd
36913faa91sdstatic int
37013faa91sdchip_instantiate(tnode_t *parent, const char *name, topo_mod_t *mod,
37113faa91sd    topo_instance_t inst)
37213faa91sd{
37313faa91sd	if (strcmp(name, CPUBOARD) != 0) {
37413faa91sd		topo_mod_dprintf(mod,
37513faa91sd		    "Currently only know how to enumerate %s components.\n",
37613faa91sd		    CPUBOARD);
37713faa91sd		return (0);
37813faa91sd	}
37913faa91sd	topo_mod_dprintf(mod,
38013faa91sd	    "Calling chip_enum for inst: %lx\n", inst);
38113faa91sd	if (topo_mod_enumerate(mod,
38213faa91sd	    parent, CHIP, CHIP, inst, inst, NULL) != 0) {
38313faa91sd		return (topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM));
38413faa91sd	}
38513faa91sd	return (0);
38613faa91sd}
38713faa91sd
38813faa91sdstatic topo_mod_t *
38913faa91sdchip_enum_load(topo_mod_t *mp)
39013faa91sd{
39113faa91sd	topo_mod_t *rp = NULL;
39213faa91sd
39313faa91sd	topo_mod_dprintf(mp, "chip_enum_load: %s\n", CPUBOARD);
39413faa91sd	if ((rp = topo_mod_load(mp, CHIP, TOPO_VERSION)) == NULL) {
39513faa91sd		topo_mod_dprintf(mp,
39613faa91sd		    "%s enumerator could not load %s enum. (%d: %s)\n",
39713faa91sd		    CPUBOARD, CHIP, errno, strerror(errno));
39813faa91sd	}
39913faa91sd	topo_mod_dprintf(mp, "chip_enum_load(EXIT): %s, rp=%p\n", CPUBOARD, rp);
40013faa91sd	return (rp);
40113faa91sd}
40213faa91sd
40313faa91sdstatic di_node_t
40413faa91sdcpuboard_findrc(topo_mod_t *mod, uint64_t id)
40513faa91sd{
40613faa91sd	di_node_t devtree;
40713faa91sd	di_node_t dnode;
40813faa91sd
40913faa91sd	if ((devtree = topo_mod_devinfo(mod)) == DI_NODE_NIL) {
41013faa91sd		topo_mod_dprintf(mod, "devinfo init failed.");
41113faa91sd		return (NULL);
41213faa91sd	}
41313faa91sd	dnode = di_drv_first_node(CPUBOARD_PX_DRV, devtree);
41413faa91sd	while (dnode != DI_NODE_NIL) {
41513faa91sd		char *path;
41613faa91sd
41713faa91sd		if ((path = di_devfs_path(dnode)) == NULL) {
41813faa91sd			topo_mod_dprintf(mod, "cpuboard_findrc: "
41913faa91sd			    "NULL di_devfs_path.\n");
42013faa91sd			(void) topo_mod_seterrno(mod, ETOPO_PROP_NOENT);
42113faa91sd			return (NULL);
42213faa91sd		}
42313faa91sd		topo_mod_dprintf(mod, "cpuboard_findrc: "
42413faa91sd		    "got px %d, node named: %s, path: %s\n",
42513faa91sd		    di_instance(dnode), di_node_name(dnode), path);
42613faa91sd
42713faa91sd		if (strcmp(cpub_rcs[id], path) == 0) {
42813faa91sd			di_devfs_path_free(path);
42913faa91sd			return (dnode);
43013faa91sd		}
43113faa91sd
43213faa91sd		di_devfs_path_free(path);
43313faa91sd
43413faa91sd		dnode = di_drv_next_node(dnode);
43513faa91sd	}
43613faa91sd	return (NULL);
43713faa91sd}
43813faa91sd
439b64bfe7Trang Dostatic void
440b64bfe7Trang Docpuboard_free_pri_info(topo_mod_t *mod, cpuboard_contents_t cpuboard_list[],
441b64bfe7Trang Do    topo_instance_t min, topo_instance_t max)
442b64bfe7Trang Do{
443b64bfe7Trang Do	int i;
444b64bfe7Trang Do
445b64bfe7Trang Do	for (i = min; i <= max; i++) {
446b64bfe7Trang Do		if (cpuboard_list[i].present == 0)
447b64bfe7Trang Do			continue;
448b64bfe7Trang Do		if (cpuboard_list[i].sn != NULL)
449b64bfe7Trang Do			topo_mod_strfree(mod, cpuboard_list[i].sn);
450b64bfe7Trang Do		if (cpuboard_list[i].pn != NULL)
451b64bfe7Trang Do			topo_mod_strfree(mod, cpuboard_list[i].pn);
452b64bfe7Trang Do	}
453b64bfe7Trang Do}
454b64bfe7Trang Do
45513faa91sd/*ARGSUSED*/
45613faa91sdstatic int
45713faa91sdcpuboard_enum(topo_mod_t *mod, tnode_t *parent, const char *name,
45813faa91sd	topo_instance_t min, topo_instance_t max, void *arg, void *notused)
45913faa91sd{
46013faa91sd	tnode_t *cpuboardn;
46113faa91sd	topo_instance_t i = 0;
46213faa91sd	cpuboard_contents_t cpuboard_list[CPUBOARD_MAX];
46313faa91sd
46413faa91sd	if (strcmp(name, CPUBOARD) != 0) {
46513faa91sd		topo_mod_dprintf(mod,
46613faa91sd		    "Currently only know how to enumerate %s components.\n",
46713faa91sd		    CPUBOARD);
46813faa91sd		return (-1);
46913faa91sd	}
47013faa91sd	/* Make sure we don't exceed CPUBOARD_MAX */
47113faa91sd	if (max >= CPUBOARD_MAX) {
47213faa91sd		max = CPUBOARD_MAX;
47313faa91sd	}
47413faa91sd
47513faa91sd	bzero(cpuboard_list, sizeof (cpuboard_list));
47613faa91sd
47713faa91sd	/* Scan PRI for cpu-boards. */
47813faa91sd	cpuboard_mod_hdl = mod;
47967d4b2fgk	if (cpuboard_get_pri_info(mod, cpuboard_list) == 0) {
48067d4b2fgk		int cpuboards_found = 0;
48167d4b2fgk		/*
48267d4b2fgk		 * if no PRI available (i.e. not in Control Domain),
48367d4b2fgk		 * use px driver to determine cpuboard presence.
48467d4b2fgk		 * NOTE: with this approach there will be no
48567d4b2fgk		 * identity information - no SN nor PN.
48667d4b2fgk		 */
48767d4b2fgk		bzero(cpuboard_list, sizeof (cpuboard_list));
48867d4b2fgk		for (i = min; i <= max; i++) {
48967d4b2fgk			if (cpuboard_findrc(mod, i) != NULL) {
49067d4b2fgk				cpuboard_list[i].present = 1;
49167d4b2fgk				cpuboards_found++;
49267d4b2fgk			}
49367d4b2fgk		}
49467d4b2fgk		if (cpuboards_found == 0) {
49567d4b2fgk			topo_mod_dprintf(mod, "No cpuboards found.\n");
49667d4b2fgk			return (-1);
49767d4b2fgk		}
49867d4b2fgk	}
49913faa91sd
500b64bfe7Trang Do	if (chip_enum_load(mod) == NULL) {
501b64bfe7Trang Do		cpuboard_free_pri_info(mod, cpuboard_list, min, max);
50213faa91sd		return (-1);
503b64bfe7Trang Do	}
50413faa91sd
50513faa91sd	for (i = min; i <= max; i++) {
50613faa91sd		if (cpuboard_list[i].present == 0)
50713faa91sd			continue;
50813faa91sd
50913faa91sd		cpuboardn = cpuboard_declare(parent, name, i,
51013faa91sd		    NULL, mod, &cpuboard_list[i]);
51113faa91sd		if (cpuboardn == NULL) {
51213faa91sd			topo_mod_dprintf(mod,
51313faa91sd			    "Enumeration of cpuboard failed: %s\n",
51413faa91sd			    topo_strerror(topo_mod_errno(mod)));
515b64bfe7Trang Do			cpuboard_free_pri_info(mod, cpuboard_list, min, max);
51613faa91sd			return (-1); /* mod_errno already set */
51713faa91sd		}
51813faa91sd		if (topo_node_range_create(mod, cpuboardn, CHIP, 0,
51913faa91sd		    CHIP_MAX) < 0) {
52013faa91sd			topo_node_unbind(cpuboardn);
52113faa91sd			topo_mod_dprintf(mod, "topo_node_range_create CHIP "
52213faa91sd			    "failed: %s\n", topo_strerror(topo_mod_errno(mod)));
523b64bfe7Trang Do			cpuboard_free_pri_info(mod, cpuboard_list, min, max);
52413faa91sd			return (-1); /* mod_errno already set */
52513faa91sd		}
52613faa91sd		if (chip_instantiate(cpuboardn, CPUBOARD, mod, i) < 0) {
52713faa91sd			topo_mod_dprintf(mod, "Enumeration of chip "
52813faa91sd			    "failed %s\n",
52913faa91sd			    topo_strerror(topo_mod_errno(mod)));
530b64bfe7Trang Do			cpuboard_free_pri_info(mod, cpuboard_list, min, max);
53113faa91sd			return (-1);
53213faa91sd		}
53313faa91sd		if (topo_node_range_create(mod, cpuboardn, HOSTBRIDGE, 0,
53413faa91sd		    HOSTBRIDGE_MAX) < 0) {
53513faa91sd			topo_node_unbind(cpuboardn);
53613faa91sd			topo_mod_dprintf(mod, "topo_node_range_create: "
53713faa91sd			    "HOSTBRIDGE failed: %s\n",
53813faa91sd			    topo_strerror(topo_mod_errno(mod)));
539b64bfe7Trang Do			cpuboard_free_pri_info(mod, cpuboard_list, min, max);
54013faa91sd			return (-1);
54113faa91sd		}
5422535165Vuong Nguyen		if (cpuboard_hb_enum(mod, cpuboard_findrc(mod, i), cpub_rcs[i],
54313faa91sd		    cpuboardn, i) < 0) {
54413faa91sd			topo_node_unbind(cpuboardn);
54513faa91sd			topo_mod_dprintf(mod, "cpuboard_hb_enum: "
54613faa91sd			    "failed: %s\n",
54713faa91sd			    topo_strerror(topo_mod_errno(mod)));
548b64bfe7Trang Do			cpuboard_free_pri_info(mod, cpuboard_list, min, max);
54913faa91sd			return (-1);
55013faa91sd		}
55113faa91sd	}
552b64bfe7Trang Do	cpuboard_free_pri_info(mod, cpuboard_list, min, max);
55313faa91sd	return (0);
55413faa91sd}
555