6396916 verification of dtd file name is wrong
authorcindi
Sat, 04 Nov 2006 01:18:55 -0800
changeset 3062 46d280f5351d
parent 3061 9b018ee62e07
child 3063 b252896b372b
6396916 verification of dtd file name is wrong 6399876 libtopo does not properly support an alternate root path 6399927 libtopo debug information indicates "no topology file found" when it is unable to parse file. 6421101 fmsim doesn't allow simulated topology to be specified with new libtopo 6422759 fmd memory leaks detected on system experiencing significant pcie fabric errors 6429072 memory leak in iob_tnode_create 6448718 libtopo needs better enum module APIs 6467144 topo_fmri_str2nvl doesn't handle authority or properties 6473916 fmd should return a full populated topo snapshot in fmd_hdl_topology() and fmd_fmri_topology() 6473918 hc scheme plugin is_present routine is broken 6477382 Need public header file for hc scheme component names and properties 6477385 fmtopo -V needs to be more friendly 6477426 fmtopo -d should not be so chatty 6477430 Need ability to load additional libtopo map files 6477442 libtopo should allow alternate platform topo map files 6477446 Remove unused topo methods from enumerator modules 6477453 pcibus and hostbridge interface boundaries are a mess 6477456 hc enumerators must support authority information 6477461 topo_fru_compute and topo_asru_compute should return static props when computation fails 6480930 fmtopo should support a -x option
deleted_files/usr/src/lib/fm/topo/files/SUNW,Sun-Blade-T6300/Makefile
deleted_files/usr/src/lib/fm/topo/modules/common/pcibus/pcifn_enum.c
deleted_files/usr/src/lib/fm/topo/modules/common/pcibus/pcifn_enum.h
deleted_files/usr/src/lib/fm/topo/modules/sun4v/ioboard/Makefile
deleted_files/usr/src/lib/fm/topo/modules/sun4v/ioboard/iob_platform.c
usr/src/cmd/fm/eversholt/files/Makefile.com
usr/src/cmd/fm/eversholt/files/common/pci.esc
usr/src/cmd/fm/eversholt/files/common/pciex.esc
usr/src/cmd/fm/fmd/Makefile.fmd
usr/src/cmd/fm/fmd/common/fmd.c
usr/src/cmd/fm/fmd/common/fmd.h
usr/src/cmd/fm/fmd/common/fmd_api.c
usr/src/cmd/fm/fmd/common/fmd_fmri.c
usr/src/cmd/fm/fmd/common/fmd_topo.c
usr/src/cmd/fm/fmd/common/fmd_topo.h
usr/src/cmd/fm/fmtopo/common/fmtopo.c
usr/src/cmd/fm/modules/common/eversholt/config.c
usr/src/cmd/fm/modules/common/eversholt/platform.c
usr/src/cmd/fm/modules/i86pc/sfx4500-disk/diskmon_conf.c
usr/src/cmd/fm/modules/i86pc/sfx4500-disk/schg_mgr.c
usr/src/cmd/fm/modules/i86pc/sfx4500-disk/topo_gather.c
usr/src/cmd/fm/modules/i86pc/sfx4500-disk/topo_gather.h
usr/src/cmd/fm/schemes/hc/scheme.c
usr/src/cmd/fm/schemes/mem/mem.c
usr/src/cmd/fm/scripts/fmsim.ksh
usr/src/lib/fm/topo/Makefile
usr/src/lib/fm/topo/Makefile.rootdirs
usr/src/lib/fm/topo/files/Makefile
usr/src/lib/fm/topo/files/Makefile.file
usr/src/lib/fm/topo/files/SUNW,SPARC-Enterprise/Makefile
usr/src/lib/fm/topo/files/SUNW,SPARC-Enterprise/hc-topology.xml
usr/src/lib/fm/topo/files/SUNW,Sun-Blade-T6300/Makefile
usr/src/lib/fm/topo/files/SUNW,Sun-Blade-T6300/hc-topology.xml
usr/src/lib/fm/topo/files/SUNW,Sun-Fire-15000/Makefile
usr/src/lib/fm/topo/files/SUNW,Sun-Fire-15000/hc-topology.xml
usr/src/lib/fm/topo/files/SUNW,Sun-Fire-T200/Makefile
usr/src/lib/fm/topo/files/SUNW,Sun-Fire-T200/hc-topology.xml
usr/src/lib/fm/topo/files/SUNW,Sun-Fire/Makefile
usr/src/lib/fm/topo/files/SUNW,Sun-Fire/hc-topology.xml
usr/src/lib/fm/topo/files/common/topology.dtd.1
usr/src/lib/fm/topo/files/i86pc/Makefile
usr/src/lib/fm/topo/files/i86pc/hc-topology.xml
usr/src/lib/fm/topo/files/sun4u/Makefile
usr/src/lib/fm/topo/files/sun4u/hc-topology.xml
usr/src/lib/fm/topo/files/sun4v/Makefile
usr/src/lib/fm/topo/files/sun4v/hc-topology.xml
usr/src/lib/fm/topo/libtopo/Makefile
usr/src/lib/fm/topo/libtopo/Makefile.com
usr/src/lib/fm/topo/libtopo/common/cpu.c
usr/src/lib/fm/topo/libtopo/common/cpu.h
usr/src/lib/fm/topo/libtopo/common/dev.c
usr/src/lib/fm/topo/libtopo/common/dev.h
usr/src/lib/fm/topo/libtopo/common/hc.c
usr/src/lib/fm/topo/libtopo/common/hc.h
usr/src/lib/fm/topo/libtopo/common/hc_canon.h
usr/src/lib/fm/topo/libtopo/common/libtopo.h
usr/src/lib/fm/topo/libtopo/common/mapfile-vers
usr/src/lib/fm/topo/libtopo/common/mem.c
usr/src/lib/fm/topo/libtopo/common/mem.h
usr/src/lib/fm/topo/libtopo/common/mkerror.sh
usr/src/lib/fm/topo/libtopo/common/mod.c
usr/src/lib/fm/topo/libtopo/common/mod.h
usr/src/lib/fm/topo/libtopo/common/pkg.c
usr/src/lib/fm/topo/libtopo/common/pkg.h
usr/src/lib/fm/topo/libtopo/common/topo_2xml.c
usr/src/lib/fm/topo/libtopo/common/topo_builtin.c
usr/src/lib/fm/topo/libtopo/common/topo_builtin.h
usr/src/lib/fm/topo/libtopo/common/topo_error.h
usr/src/lib/fm/topo/libtopo/common/topo_file.c
usr/src/lib/fm/topo/libtopo/common/topo_file.h
usr/src/lib/fm/topo/libtopo/common/topo_fmri.c
usr/src/lib/fm/topo/libtopo/common/topo_hc.h
usr/src/lib/fm/topo/libtopo/common/topo_method.c
usr/src/lib/fm/topo/libtopo/common/topo_method.h
usr/src/lib/fm/topo/libtopo/common/topo_mod.c
usr/src/lib/fm/topo/libtopo/common/topo_mod.h
usr/src/lib/fm/topo/libtopo/common/topo_mod.map
usr/src/lib/fm/topo/libtopo/common/topo_module.c
usr/src/lib/fm/topo/libtopo/common/topo_module.h
usr/src/lib/fm/topo/libtopo/common/topo_node.c
usr/src/lib/fm/topo/libtopo/common/topo_parse.c
usr/src/lib/fm/topo/libtopo/common/topo_parse.h
usr/src/lib/fm/topo/libtopo/common/topo_prop.c
usr/src/lib/fm/topo/libtopo/common/topo_prop.h
usr/src/lib/fm/topo/libtopo/common/topo_protocol.c
usr/src/lib/fm/topo/libtopo/common/topo_rtld.c
usr/src/lib/fm/topo/libtopo/common/topo_snap.c
usr/src/lib/fm/topo/libtopo/common/topo_subr.c
usr/src/lib/fm/topo/libtopo/common/topo_subr.h
usr/src/lib/fm/topo/libtopo/common/topo_tree.c
usr/src/lib/fm/topo/libtopo/common/topo_tree.h
usr/src/lib/fm/topo/libtopo/common/topo_xml.c
usr/src/lib/fm/topo/maps/Makefile
usr/src/lib/fm/topo/maps/Makefile.map
usr/src/lib/fm/topo/maps/SUNW,SPARC-Enterprise/Makefile
usr/src/lib/fm/topo/maps/SUNW,SPARC-Enterprise/SPARC-Enterprise-hc-topology.xml
usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-15000/Makefile
usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-15000/Sun-Fire-15000-hc-topology.xml
usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-T200/Makefile
usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-T200/SPARC-Enterprise-T1000-hc-topology.xml
usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-T200/Sun-Blade-T6300-hc-topology.xml
usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-T200/Sun-Fire-T1000-hc-topology.xml
usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-T200/Sun-Fire-T200-hc-topology.xml
usr/src/lib/fm/topo/maps/SUNW,Sun-Fire/Makefile
usr/src/lib/fm/topo/maps/SUNW,Sun-Fire/Sun-Fire-hc-topology.xml
usr/src/lib/fm/topo/maps/common/topology.dtd.1
usr/src/lib/fm/topo/maps/i86pc/Makefile
usr/src/lib/fm/topo/maps/i86pc/i86pc-hc-topology.xml
usr/src/lib/fm/topo/maps/i86pc/storage-hc-topology.xml
usr/src/lib/fm/topo/maps/sun4u/Makefile
usr/src/lib/fm/topo/maps/sun4u/sun4u-hc-topology.xml
usr/src/lib/fm/topo/maps/sun4v/Makefile
usr/src/lib/fm/topo/maps/sun4v/sun4v-hc-topology.xml
usr/src/lib/fm/topo/modules/Makefile.plugin
usr/src/lib/fm/topo/modules/SUNW,SPARC-Enterprise/ioboard/opl_hostbridge.c
usr/src/lib/fm/topo/modules/SUNW,SPARC-Enterprise/ioboard/opl_ioboard.c
usr/src/lib/fm/topo/modules/SUNW,SPARC-Enterprise/ioboard/opl_topo.h
usr/src/lib/fm/topo/modules/SUNW,Sun-Fire-15000/ioboard/iob_platform.c
usr/src/lib/fm/topo/modules/SUNW,Sun-Fire/ioboard/iob_platform.c
usr/src/lib/fm/topo/modules/common/did.c
usr/src/lib/fm/topo/modules/common/did.h
usr/src/lib/fm/topo/modules/common/did_hash.c
usr/src/lib/fm/topo/modules/common/did_impl.h
usr/src/lib/fm/topo/modules/common/did_props.c
usr/src/lib/fm/topo/modules/common/did_props.h
usr/src/lib/fm/topo/modules/common/hostbridge.c
usr/src/lib/fm/topo/modules/common/hostbridge.h
usr/src/lib/fm/topo/modules/common/hostbridge/hostbridge.c
usr/src/lib/fm/topo/modules/common/hostbridge/hostbridge.h
usr/src/lib/fm/topo/modules/common/pcibus.c
usr/src/lib/fm/topo/modules/common/pcibus.h
usr/src/lib/fm/topo/modules/common/pcibus/did.c
usr/src/lib/fm/topo/modules/common/pcibus/did.h
usr/src/lib/fm/topo/modules/common/pcibus/did_hash.c
usr/src/lib/fm/topo/modules/common/pcibus/did_impl.h
usr/src/lib/fm/topo/modules/common/pcibus/did_props.c
usr/src/lib/fm/topo/modules/common/pcibus/did_props.h
usr/src/lib/fm/topo/modules/common/pcibus/pcibus.c
usr/src/lib/fm/topo/modules/common/pcibus/pcibus.h
usr/src/lib/fm/topo/modules/common/pcibus/pcibus_labels.c
usr/src/lib/fm/topo/modules/common/pcibus/pcibus_labels.h
usr/src/lib/fm/topo/modules/common/pcibus/util.c
usr/src/lib/fm/topo/modules/common/pcibus/util.h
usr/src/lib/fm/topo/modules/common/pcibus_labels.c
usr/src/lib/fm/topo/modules/common/pcibus_labels.h
usr/src/lib/fm/topo/modules/common/pcifn_enum.c
usr/src/lib/fm/topo/modules/common/pcifn_enum.h
usr/src/lib/fm/topo/modules/common/util.c
usr/src/lib/fm/topo/modules/common/util.h
usr/src/lib/fm/topo/modules/i86pc/chip/chip.c
usr/src/lib/fm/topo/modules/i86pc/hostbridge/Makefile
usr/src/lib/fm/topo/modules/i86pc/hostbridge/hb_i86pc.c
usr/src/lib/fm/topo/modules/i86pc/pcibus/Makefile
usr/src/lib/fm/topo/modules/i86pc/pcibus/pci_i86pc.c
usr/src/lib/fm/topo/modules/i86pc/sata/sata.c
usr/src/lib/fm/topo/modules/i86pc/sata/sata.h
usr/src/lib/fm/topo/modules/sun4/chip/chip.c
usr/src/lib/fm/topo/modules/sun4/hostbridge/Makefile.hb
usr/src/lib/fm/topo/modules/sun4/hostbridge/hb_sun4.c
usr/src/lib/fm/topo/modules/sun4/hostbridge/hb_sun4.h
usr/src/lib/fm/topo/modules/sun4/ioboard/Makefile.iob
usr/src/lib/fm/topo/modules/sun4/ioboard/ioboard.c
usr/src/lib/fm/topo/modules/sun4/ioboard/ioboard.h
usr/src/lib/fm/topo/modules/sun4u/hostbridge/hb_sun4u.c
usr/src/lib/fm/topo/modules/sun4u/pcibus/Makefile
usr/src/lib/fm/topo/modules/sun4u/pcibus/pci_sun4u.c
usr/src/lib/fm/topo/modules/sun4v/Makefile
usr/src/lib/fm/topo/modules/sun4v/hostbridge/hb_sun4v.c
usr/src/lib/fm/topo/modules/sun4v/ioboard/Makefile
usr/src/lib/fm/topo/modules/sun4v/ioboard/iob_platform.c
usr/src/lib/fm/topo/modules/sun4v/pcibus/Makefile
usr/src/lib/fm/topo/modules/sun4v/pcibus/pci_sun4v.c
usr/src/lib/fm/topo/modules/sun4v/pcibus/pci_sun4v.h
usr/src/pkgdefs/SUNWfmd/prototype_com
usr/src/pkgdefs/SUNWfmd/prototype_i386
usr/src/pkgdefs/SUNWfmd/prototype_sparc
usr/src/tools/scripts/bfu.sh
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/lib/fm/topo/files/SUNW,Sun-Blade-T6300/Makefile	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,34 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+
+PLATFORMS = SUNW,Sun-Blade-T6300
+CLASS = platform
+DTDFILE = 
+TOPOFILE = hc-topology.xml
+SRCDIR = ../SUNW,Sun-Blade-T6300
+
+include ../Makefile.file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/lib/fm/topo/modules/common/pcibus/pcifn_enum.c	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,122 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <limits.h>
+#include <fm/libtopo.h>
+#include "did.h"
+#include "did_props.h"
+#include "pcifn_enum.h"
+
+static topo_mod_t *
+module_load(topo_mod_t *mp, tnode_t *parent, const char *name)
+{
+	topo_mod_t *rp = NULL;
+	char *plat, *mach;
+	char *path;
+	char *rootdir;
+	int err;
+
+	plat = mach = NULL;
+
+	if (topo_prop_get_string(parent,
+	    TOPO_PGROUP_SYSTEM, TOPO_PROP_PLATFORM, &plat, &err) < 0) {
+		(void) topo_mod_seterrno(mp, err);
+		return (NULL);
+	}
+	if (topo_prop_get_string(parent,
+	    TOPO_PGROUP_SYSTEM, TOPO_PROP_MACHINE, &mach, &err) < 0) {
+		(void) topo_mod_seterrno(mp, err);
+		return (NULL);
+	}
+	path = topo_mod_alloc(mp, PATH_MAX);
+	rootdir = topo_mod_rootdir(mp);
+	(void) snprintf(path, PATH_MAX,
+	    PATH_TEMPLATE, rootdir ? rootdir : "", plat, name);
+
+	if ((rp = topo_mod_load(mp, path)) == NULL) {
+		topo_mod_dprintf(mp, "Unable to load %s.\n", path);
+		(void) snprintf(path, PATH_MAX,
+		    PATH_TEMPLATE, rootdir ? rootdir : "", mach, name);
+		if ((rp = topo_mod_load(mp, path)) == NULL)
+			topo_mod_dprintf(mp, "Unable to load %s.\n", path);
+	}
+	topo_mod_strfree(mp, plat);
+	topo_mod_strfree(mp, mach);
+	topo_mod_free(mp, path, PATH_MAX);
+	return (rp);
+}
+
+static int
+module_run(topo_mod_t *mp, tnode_t *parent, pfn_enum_t *ep)
+{
+	return (topo_mod_enumerate(mp, parent,
+	    ep->pfne_modname, ep->pfne_childname,
+	    ep->pfne_imin, ep->pfne_imax));
+}
+
+int
+pcifn_enum(topo_mod_t *mp, tnode_t *parent)
+{
+	char *ccstr;
+	int rv = 0;
+	int i, e;
+	uint_t cc;
+	topo_mod_t *child_mod;
+
+	topo_mod_dprintf(mp, "Enumerating beneath pci(ex) function.\n");
+
+	/*
+	 * Extract the class code of the PCI function and make sure
+	 * it matches the type that the module cares about.
+	 */
+	if (topo_prop_get_string(parent,
+	    TOPO_PGROUP_PCI, TOPO_PROP_CLASS, &ccstr, &e) < 0)
+		return (0);
+	if (sscanf(ccstr, "%x", &cc) != 1) {
+		topo_mod_strfree(mp, ccstr);
+		return (0);
+	}
+	topo_mod_strfree(mp, ccstr);
+	cc = cc >> 16;
+
+	for (i = 0; i < Pcifn_enumerator_count; i++) {
+
+		if (cc != Pcifn_enumerators[i].pfne_class)
+			continue;
+
+		child_mod = module_load(mp, parent,
+		    Pcifn_enumerators[i].pfne_modname);
+
+		if (child_mod) {
+			rv = module_run(mp, parent,
+			    &Pcifn_enumerators[i]) != 0 ? -1 : 0;
+			topo_mod_unload(child_mod);
+		}
+	}
+	return (rv);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/lib/fm/topo/modules/common/pcibus/pcifn_enum.h	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,65 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef	_PCIFN_ENUM_H
+#define	_PCIFN_ENUM_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/types.h>
+#include <sys/pci.h>
+#include <fm/topo_mod.h>
+
+#define	PATH_TEMPLATE "%s/usr/platform/%s/lib/fm/topo/plugins/%s.so"
+
+/*
+ * When a pci or pci-express function is enumerated in the topology
+ * we'll attempt to load modules that can expand the topology
+ * beneath that function.  This data structure helps us track which modules
+ * to attempt to load, whether or not the loading was successful
+ * so we don't waste time trying again, and if loading is successful,
+ * the module pointer returned by topo_mod_load().
+ */
+typedef struct pfn_enum {
+	uint_t pfne_class;	/* expected PCI class of the parent function */
+	const char *pfne_modname; /* enumerator module name */
+	const char *pfne_childname; /* name of nodes to enumerate */
+	topo_instance_t pfne_imin; /* minimum instance number to enumerate */
+	topo_instance_t pfne_imax; /* maximum instance number to enumerate */
+} pfn_enum_t;
+
+/*
+ * The current list of modules to potentially load and expand topology
+ * beneath pci(-express) functions.
+ */
+pfn_enum_t Pcifn_enumerators[] = {
+	{ PCI_CLASS_MASS, "sata", "sata-port", 0, 7	},
+	{ PCI_CLASS_MASS, "scsi", "disk", 0, 15		}
+};
+
+int Pcifn_enumerator_count = sizeof (Pcifn_enumerators) / sizeof (pfn_enum_t);
+
+#endif /* _PCIFN_ENUM_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/lib/fm/topo/modules/sun4v/ioboard/Makefile	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,31 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+
+CLASS = arch
+ARCH = sun4v
+
+include ../../sun4/ioboard/Makefile.iob
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deleted_files/usr/src/lib/fm/topo/modules/sun4v/ioboard/iob_platform.c	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,169 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+/*
+ * SUNW,Sun-Fire platform ioboard topology enumerator
+ */
+
+#include <string.h>
+#include <libdevinfo.h>
+#include <fm/topo_mod.h>
+#include <sys/fm/protocol.h>
+
+#include <ioboard.h>
+#include <hostbridge.h>
+#include <util.h>
+
+#define	IOBOARD	"ioboard"
+#define	LABEL	"IOBD"
+#define	IOBDFRU	"hc:///component="LABEL
+#define	ERIE	"SUNW,Sun-Fire-T1000"
+#define	ERIE2	"SUNW,SPARC-Enterprise-T1000"
+#define	HB_MAX	1
+
+/*ARGSUSED*/
+int
+platform_iob_label(tnode_t *node, nvlist_t *ignored, nvlist_t **out,
+    topo_mod_t *mod)
+{
+	return (0);
+}
+
+static tnode_t *
+iob_node_create(tnode_t *parent, topo_mod_t *mod)
+{
+	int err;
+	tnode_t *ion;
+	nvlist_t *fmri, *args = NULL, *pfmri = NULL;
+	topo_hdl_t *thp = topo_mod_handle(mod);
+
+	(void) topo_node_resource(parent, &pfmri, &err);
+	if (pfmri != NULL) {
+		if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0 ||
+		    nvlist_add_nvlist(args, TOPO_METH_FMRI_ARG_PARENT, pfmri)
+		    != 0) {
+			nvlist_free(pfmri);
+			nvlist_free(args);
+			(void) topo_mod_seterrno(mod, EMOD_FMRI_NVL);
+			return (NULL);
+		}
+		nvlist_free(pfmri);
+	}
+
+	if ((fmri = topo_fmri_create(thp, FM_FMRI_SCHEME_HC, IOBOARD, 0, args,
+		&err)) == NULL) {
+		topo_mod_dprintf(mod, "creation of tnode for ioboard=0 "
+		    "failed: %s\n", topo_strerror(err));
+		(void) topo_mod_seterrno(mod, err);
+		nvlist_free(args);
+		return (NULL);
+	}
+	nvlist_free(args);
+	ion = topo_node_bind(mod, parent, IOBOARD, 0, fmri, NULL);
+	if (ion == NULL) {
+		nvlist_free(fmri);
+		topo_mod_dprintf(mod, "unable to bind ioboard=0: %s",
+		    topo_strerror(topo_mod_errno(mod)));
+		return (NULL); /* mod_errno already set */
+	}
+	nvlist_free(fmri);
+
+	if (topo_fmri_str2nvl(thp, IOBDFRU, &fmri, &err) == 0) {
+		(void) topo_node_fru_set(ion, fmri, 0, &err);
+		nvlist_free(fmri);
+	}
+	(void) topo_node_label_set(ion, "IOBD", &err);
+
+	return (ion);
+}
+
+/*ARGSUSED*/
+int
+platform_iob_enum(tnode_t *parent, topo_instance_t imin, topo_instance_t imax,
+    did_hash_t *didhash, di_prom_handle_t promtree, topo_mod_t *mod)
+{
+	int err;
+	tnode_t *ion;
+	char *plat;
+
+	if (topo_prop_get_string(parent,
+	    TOPO_PGROUP_SYSTEM, TOPO_PROP_PLATFORM, &plat, &err) < 0) {
+		return (topo_mod_seterrno(mod, err));
+	}
+
+	/*
+	 * The SUNW,SunFireT1000 (Erie) platform links in the SUNW,SunFireT200
+	 * (Ontario) top-level /usr/platform/SUNW,SunFireT200 and its
+	 * hc-topology. Unfortunately, the SUNW,SunFireT1000 does not contain an
+	 * ioboard.  For SUNW,SunFireT1000 systems, we must begin the I/O
+	 * topology directly below the motherboard.
+	 *
+	 * To further the mess, on the SUNW,SunFireT200 (Ontario) platform, a
+	 * mistake was made with the topology defintion.  The ioboard was made
+	 * a peer to the motherboard.  This is incorrect in terms of
+	 * what we allow for an hc topology according the Fault
+	 * Managed Resources specification and what is physically
+	 * possible in the system.  Nevertheless, a change to
+	 * the topology will result in mis-diagnoses for systems
+	 * that have already shipped. In the interest of backward
+	 * compatibility, we continue to allow the
+	 * ioboard to be a peer to the motherboard SUNW,SunFireT200 systems.
+	 */
+	if ((strcmp(plat, ERIE) == 0) ||
+	    (strcmp(plat, ERIE2) == 0)) {
+		if (strcmp(topo_node_name(parent), "motherboard") != 0) {
+			topo_mod_strfree(mod, plat);
+			return (0);
+		}
+		ion = parent;
+	} else if (strcmp(topo_node_name(parent), "motherboard") == 0) {
+		topo_mod_strfree(mod, plat);
+		return (0);
+	} else {
+		ion = iob_node_create(parent, mod);
+	}
+
+	topo_mod_strfree(mod, plat);
+
+	if (ion == NULL) {
+		topo_mod_dprintf(mod, "Enumeration of ioboard failed: %s\n",
+		    topo_strerror(topo_mod_errno(mod)));
+		return (-1); /* mod_errno already set */
+	}
+
+	if (child_range_add(mod, ion, HOSTBRIDGE, 0, HB_MAX) < 0 ||
+	    topo_mod_enumerate(mod, ion, HOSTBRIDGE, HOSTBRIDGE, 0, HB_MAX)
+	    < 0) {
+		topo_mod_dprintf(mod, "Enumeration of %s=%d "
+		    "failed: %s\n", HOSTBRIDGE, 0,
+		    topo_strerror(topo_mod_errno(mod)));
+		return (-1); /* mod_errno already set */
+	}
+
+	return (0);
+}
--- a/usr/src/cmd/fm/eversholt/files/Makefile.com	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/cmd/fm/eversholt/files/Makefile.com	Sat Nov 04 01:18:55 2006 -0800
@@ -2,9 +2,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
 #
 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 # or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 #ident	"%Z%%M%	%I%	%E% SMI"
@@ -52,7 +51,7 @@
 	$(USR_PLAT_EFT_FILES) $(ROOT_COMMON_EFT_FILES)
 
 %.eft: ../common/%.esc
-	$(ESC) -o $@ $<
+	$(ESC) -I$(ROOT)/usr/include  -o $@ $<
 
 %.eft: %.esc
 	$(ESC) -o $@ $<
--- a/usr/src/cmd/fm/eversholt/files/common/pci.esc	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/cmd/fm/eversholt/files/common/pci.esc	Sat Nov 04 01:18:55 2006 -0800
@@ -27,6 +27,8 @@
 
 #pragma dictionary "PCI"
 
+#include <fm/topo_hc.h>
+
 #define PCI_DEV_FIT 1000
 #define PCI_BUS_FIT 500
 
@@ -50,17 +52,17 @@
 #define NONFATAL_DPE_D_TIME 168h
 
 #define	IS_LEAF \
-	(confprop(asru(pcibus/pcidev/pcifn), "CLASS-CODE") != "60400" && \
-	confprop(asru(pcibus/pcidev/pcifn), "CLASS-CODE") != "60401")
+	(confprop(asru(pcibus/pcidev/pcifn), TOPO_PCI_CLASS) != "60400" && \
+	confprop(asru(pcibus/pcidev/pcifn), TOPO_PCI_CLASS) != "60401")
 
 #define	IS_BDG \
-	(confprop(asru(pcibus/pcidev/pcifn), "CLASS-CODE") == "60400" || \
-	confprop(asru(pcibus/pcidev/pcifn), "CLASS-CODE") == "60401")
+	(confprop(asru(pcibus/pcidev/pcifn), TOPO_PCI_CLASS) == "60400" || \
+	confprop(asru(pcibus/pcidev/pcifn), TOPO_PCI_CLASS) == "60401")
 
 #define	FD_IS_LEAF \
-	(confprop(asru(pcibus/pcidev[fromdev]/pcifn), "CLASS-CODE") != \
+	(confprop(asru(pcibus/pcidev[fromdev]/pcifn), TOPO_PCI_CLASS) != \
 	"60400" && \
-	confprop(asru(pcibus/pcidev[fromdev]/pcifn), "CLASS-CODE") != "60401")
+	confprop(asru(pcibus/pcidev[fromdev]/pcifn), TOPO_PCI_CLASS) != "60401")
 
 /*
  * note general rule for errors is that for upstream propagations
--- a/usr/src/cmd/fm/eversholt/files/common/pciex.esc	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/cmd/fm/eversholt/files/common/pciex.esc	Sat Nov 04 01:18:55 2006 -0800
@@ -27,6 +27,8 @@
 
 #pragma dictionary "PCIEX"
 
+#include <fm/topo_hc.h>
+
 /*
  * FIT rates - assume leaf devices are somewhat less reliable than
  * root complexes, switches and bridges
@@ -87,7 +89,7 @@
 
 #define SOURCE_ID_MATCHES_OWN_BDF \
 	(payloadprop("source-valid") == 1 && \
-	payloadprop("source-id") == (confprop(asru(pciexrc), "BDF") + 0))
+	payloadprop("source-id") == (confprop(asru(pciexrc), TOPO_PCI_BDF) + 0))
 
 /*
  * Other useful macros. These use the EXCAP property (PCI Express Capabilities
@@ -109,35 +111,39 @@
 	is_under(pciexbus/pciexdev/pciexfn, pcibus[b]/pcidev[d]/pcifn[f])
 
 #define IS_SWD \
-	(confprop(asru(pciexbus/pciexdev/pciexfn), "EXCAP") == "pciexswd")
+	(confprop(asru(pciexbus/pciexdev/pciexfn), TOPO_PCI_EXCAP) == \
+	"pciexswd")
 
 #define IS_SWU \
-	(confprop(asru(pciexbus/pciexdev/pciexfn), "EXCAP") == "pciexswu")
+	(confprop(asru(pciexbus/pciexdev/pciexfn), TOPO_PCI_EXCAP) == \
+	"pciexswu")
 
 #define IS_LEAF \
-	(confprop(asru(pciexbus/pciexdev/pciexfn), "EXCAP") == "pciexdev")
+	(confprop(asru(pciexbus/pciexdev/pciexfn), TOPO_PCI_EXCAP) == \
+	"pciexdev")
 
 #define	IS_PCI_LEAF \
-	(confprop(asru(pcibus/pcidev/pcifn), "CLASS-CODE") != "60400" && \
-	confprop(asru(pcibus/pcidev/pcifn), "CLASS-CODE") != "60401")
+	(confprop(asru(pcibus/pcidev/pcifn), TOPO_PCI_CLASS) != "60400" && \
+	confprop(asru(pcibus/pcidev/pcifn), TOPO_PCI_CLASS) != "60401")
 
 #define	BDF_IS_PCI_LEAF \
-	(confprop(asru(pcibus[b]/pcidev[d]/pcifn[f]),"CLASS-CODE") != \
+	(confprop(asru(pcibus[b]/pcidev[d]/pcifn[f]),TOPO_PCI_CLASS) != \
 	"60400" && \
-	confprop(asru(pcibus[b]/pcidev[d]/pcifn[f]), "CLASS-CODE") != "60401")
+	confprop(asru(pcibus[b]/pcidev[d]/pcifn[f]), TOPO_PCI_CLASS) != "60401")
 
 #define	BDF_IS_PCI_IMM_LEAF \
-	(confprop(asru(pciexfn/pcibus[b]/pcidev[d]/pcifn[f]),"CLASS-CODE") != \
-	"60400" && \
-	confprop(asru(pciexfn/pcibus[b]/pcidev[d]/pcifn[f]), "CLASS-CODE") != \
-	"60401")
+	(confprop(asru(pciexfn/pcibus[b]/pcidev[d]/pcifn[f]),TOPO_PCI_CLASS) \
+	!= "60400" && \
+	confprop(asru(pciexfn/pcibus[b]/pcidev[d]/pcifn[f]), TOPO_PCI_CLASS) \
+	!= "60401")
 
 #define IS_BDG \
-	(confprop(asru(pciexbus/pciexdev/pciexfn), "EXCAP") == "pcibus")
+	(confprop(asru(pciexbus/pciexdev/pciexfn), TOPO_PCI_EXCAP) == \
+	"pcibus")
 
 #define BDF_IS_LEAF \
-	(confprop(asru(pciexbus[b]/pciexdev[d]/pciexfn[f]), "EXCAP") == \
-	"pciexdev")
+	(confprop(asru(pciexbus[b]/pciexdev[d]/pciexfn[f]), \
+	TOPO_PCI_EXCAP) == "pciexdev")
 
 /*
  * define faults
@@ -1837,11 +1843,11 @@
 
 prop error.io.pciex.badreq-u@pciexbus[b]/pciexdev[d] (0)->
     ereport.io.pciex.tl.ur@pciexfn {
-	(confprop(asru(pciexfn), "EXCAP") == "pciexswd") &&
+	(confprop(asru(pciexfn), TOPO_PCI_EXCAP) == "pciexswd") &&
 	(payloadprop("source-valid") == 0 ||
 	(payloadprop("source-id") & 0xfff8) == ((b << 8) | (d << 3))) },
     ereport.io.pciex.tl.ca@pciexfn {
-	(confprop(asru(pciexfn), "EXCAP") == "pciexswd") &&
+	(confprop(asru(pciexfn), TOPO_PCI_EXCAP) == "pciexswd") &&
 	(payloadprop("source-valid") == 0 ||
 	(payloadprop("source-id") & 0xfff8) == ((b << 8) | (d << 3))) };
 
--- a/usr/src/cmd/fm/fmd/Makefile.fmd	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/cmd/fm/fmd/Makefile.fmd	Sat Nov 04 01:18:55 2006 -0800
@@ -66,6 +66,7 @@
 	fmd_thread.c \
 	fmd_time.c \
 	fmd_timerq.c \
+	fmd_topo.c \
 	fmd_trace.c \
 	fmd_ustat.c \
 	fmd_xdr_adm.c \
--- a/usr/src/cmd/fm/fmd/common/fmd.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/cmd/fm/fmd/common/fmd.c	Sat Nov 04 01:18:55 2006 -0800
@@ -31,7 +31,6 @@
 #include <sys/param.h>
 #include <sys/systeminfo.h>
 #include <sys/fm/util.h>
-#include <fm/libtopo.h>
 
 #include <smbios.h>
 #include <limits.h>
@@ -60,6 +59,7 @@
 #include <fmd_idspace.h>
 #include <fmd_rpc.h>
 #include <fmd_dr.h>
+#include <fmd_topo.h>
 #include <fmd_xprt.h>
 #include <fmd_ctl.h>
 #include <sys/openpromio.h>
@@ -313,6 +313,8 @@
 { "fltlog.enospc", FMD_TYPE_UINT64, "events not appended to fltlog (ENOSPC)" },
 { "log.enospc", FMD_TYPE_UINT64, "events not appended to other logs (ENOSPC)" },
 { "dr.gen", FMD_TYPE_UINT64, "dynamic reconfiguration generation" },
+{ "topo.gen", FMD_TYPE_UINT64, "topology snapshot generation" },
+{ "topo.drgen", FMD_TYPE_UINT64, "current topology DR generation number" },
 };
 
 void
@@ -371,6 +373,7 @@
 	(void) pthread_mutex_init(&dp->d_thr_lock, NULL);
 	(void) pthread_mutex_init(&dp->d_mod_lock, NULL);
 	(void) pthread_mutex_init(&dp->d_stats_lock, NULL);
+	(void) pthread_mutex_init(&dp->d_topo_lock, NULL);
 	(void) pthread_rwlock_init(&dp->d_log_lock, NULL);
 
 	/*
@@ -614,8 +617,7 @@
 	if (dp->d_conf != NULL)
 		fmd_conf_close(dp->d_conf);
 
-	if (dp->d_topo != NULL)
-		topo_close(dp->d_topo);
+	fmd_topo_fini();
 
 	nvlist_free(dp->d_auth);
 	(void) nv_alloc_fini(&dp->d_nva);
@@ -736,7 +738,7 @@
 	const char *name;
 	fmd_conf_path_t *pap;
 	fmd_event_t *e;
-	int dbout, err;
+	int dbout;
 
 	/*
 	 * Cache all the current debug property settings in d_fmd_debug,
@@ -768,10 +770,7 @@
 	name = dp->d_rootdir != NULL &&
 	    *dp->d_rootdir != '\0' ? dp->d_rootdir : NULL;
 
-	if ((dp->d_topo = topo_open(TOPO_VERSION, name, &err)) == NULL) {
-		fmd_error(EFMD_EXIT, "failed to initialize "
-		    "topology library: %s\n", topo_strerror(err));
-	}
+	fmd_topo_init();
 
 	dp->d_clockptr = dp->d_clockops->fto_init();
 	dp->d_xprt_ids = fmd_idspace_create("xprt_ids", 1, INT_MAX);
--- a/usr/src/cmd/fm/fmd/common/fmd.h	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/cmd/fm/fmd/common/fmd.h	Sat Nov 04 01:18:55 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -60,6 +59,8 @@
 	fmd_stat_t ds_flt_enospc;	/* number of events w/ ENOSPC fltlog */
 	fmd_stat_t ds_oth_enospc;	/* number of events w/ ENOSPC others */
 	fmd_stat_t ds_dr_gen;		/* dynamic reconfiguration generation */
+	fmd_stat_t ds_topo_gen;		/* topology snapshot generation */
+	fmd_stat_t ds_topo_drgen;	/* topology DR generation */
 } fmd_statistics_t;
 
 typedef struct fmd {
@@ -110,7 +111,8 @@
 	void *d_dr_hdl;			/* DR event handle (see fmd_dr.c) */
 	nv_alloc_t d_nva;		/* libnvpair allocator handle */
 	nvlist_t *d_auth;		/* FMRI authority nvlist */
-	struct topo_hdl *d_topo;	/* libtopo handle */
+	pthread_mutex_t d_topo_lock;	/* lock for topo hdl */
+	fmd_list_t d_topo_list;		/* list of all topology snapshots */
 
 	struct fmd_conf *d_conf;	/* global configuration properties */
 	uint_t d_fg;			/* cached value of "fg" property */
--- a/usr/src/cmd/fm/fmd/common/fmd_api.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/cmd/fm/fmd/common/fmd_api.c	Sat Nov 04 01:18:55 2006 -0800
@@ -28,7 +28,6 @@
 
 #include <sys/types.h>
 #include <sys/fm/protocol.h>
-#include <fm/libtopo.h>
 
 #include <unistd.h>
 #include <signal.h>
@@ -52,6 +51,7 @@
 #include <fmd_buf.h>
 #include <fmd_asru.h>
 #include <fmd_fmri.h>
+#include <fmd_topo.h>
 #include <fmd_ckpt.h>
 #include <fmd_xprt.h>
 
@@ -701,7 +701,8 @@
 		    "fmd version %d != client version %d\n", TOPO_VERSION, v);
 	}
 
-	thp = fmd.d_topo;
+	thp = fmd_topo_handle(v);
+
 	fmd_module_unlock(mp);
 	return (thp);
 }
--- a/usr/src/cmd/fm/fmd/common/fmd_fmri.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/cmd/fm/fmd/common/fmd_fmri.c	Sat Nov 04 01:18:55 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -37,10 +36,9 @@
 #include <fmd_string.h>
 #include <fmd_scheme.h>
 #include <fmd_fmri.h>
+#include <fmd_topo.h>
 #include <fmd.h>
 
-#include <fm/libtopo.h>
-
 /*
  * Interfaces to be used by the plugins
  */
@@ -234,8 +232,7 @@
 struct topo_hdl *
 fmd_fmri_topology(int version)
 {
-	ASSERT(version == TOPO_VERSION);
-	return (fmd.d_topo);
+	return (fmd_topo_handle(version));
 }
 
 /*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fm/fmd/common/fmd_topo.c	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,128 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+/*
+ * FMD Topology Handling
+ *
+ * Fault manager scheme and module plug-ins may need access to the latest
+ * libtopo snapshot.  Upon fmd initialization, a snapshot is taken and
+ * made available via fmd_fmri_topology() and fmd_hdl_topology().  Each
+ * of these routines returns a libtopo snapshot handle back to the caller.
+ * New snapshots are taken if and when a DR event causes the DR generation
+ * number to increase.  The current snapshot is retained to assure consistency
+ * for modules still using older snapshots and the latest snapshot handle is
+ * returned to the caller.
+ */
+
+#include <fmd_alloc.h>
+#include <fmd_error.h>
+#include <fmd_subr.h>
+#include <fmd_topo.h>
+#include <fmd.h>
+
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <fm/fmd_fmri.h>
+#include <fm/libtopo.h>
+
+static void
+fmd_topo_update(void)
+{
+	int err;
+	topo_hdl_t *tp;
+	fmd_topo_t *ftp;
+	char *id;
+	const char *name;
+
+	ASSERT(MUTEX_HELD(&fmd.d_topo_lock));
+
+	name = fmd.d_rootdir != NULL &&
+	    *fmd.d_rootdir != '\0' ? fmd.d_rootdir : NULL;
+
+	/*
+	 * Update the topology snapshot.
+	 */
+	if ((tp = topo_open(TOPO_VERSION, name, &err)) == NULL)
+		fmd_panic("failed to open topology library: %s",
+		    topo_strerror(err));
+
+	if ((id = topo_snap_hold(tp, NULL, &err)) == NULL)
+		fmd_panic("failed to get topology snapshot: %s",
+		    topo_strerror(err));
+
+	topo_hdl_strfree(tp, id);
+
+	ftp = fmd_alloc(sizeof (fmd_topo_t), FMD_SLEEP);
+	ftp->ft_hdl = tp;
+	fmd.d_stats->ds_topo_gen.fmds_value.ui64++;
+	fmd_list_prepend(&fmd.d_topo_list, ftp);
+
+}
+
+topo_hdl_t *
+fmd_topo_handle(int version)
+{
+	uint64_t curgen;
+	fmd_topo_t *ftp;
+
+	if (version != TOPO_VERSION)
+		return (NULL);
+
+	(void) pthread_mutex_lock(&fmd.d_topo_lock);
+	if ((curgen = fmd_fmri_get_drgen()) >
+	    fmd.d_stats->ds_topo_drgen.fmds_value.ui64) {
+		fmd.d_stats->ds_topo_drgen.fmds_value.ui64 = curgen;
+		fmd_topo_update();
+	}
+	ftp = fmd_list_next(&fmd.d_topo_list);
+	(void) pthread_mutex_unlock(&fmd.d_topo_lock);
+
+	return ((topo_hdl_t *)ftp->ft_hdl);
+}
+
+void
+fmd_topo_init(void)
+{
+	(void) pthread_mutex_lock(&fmd.d_topo_lock);
+	fmd_topo_update();
+	(void) pthread_mutex_unlock(&fmd.d_topo_lock);
+}
+
+void
+fmd_topo_fini(void)
+{
+	fmd_topo_t *ftp;
+
+	(void) pthread_mutex_lock(&fmd.d_topo_lock);
+	while ((ftp = fmd_list_next(&fmd.d_topo_list)) != NULL) {
+		fmd_list_delete(&fmd.d_topo_list, ftp);
+		topo_close(ftp->ft_hdl);
+		fmd_free(ftp, sizeof (fmd_topo_t));
+	}
+	(void) pthread_mutex_unlock(&fmd.d_topo_lock);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fm/fmd/common/fmd_topo.h	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,52 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _FMD_TOPO_H
+#define	_FMD_TOPO_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <fm/libtopo.h>
+
+#include <fmd_list.h>
+
+extern void fmd_topo_init(void);
+extern void fmd_topo_fini(void);
+extern topo_hdl_t *fmd_topo_handle(int);
+
+typedef struct fmd_topo {
+	fmd_list_t ft_list;
+	topo_hdl_t *ft_hdl;
+} fmd_topo_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FMD_TOPO_H */
--- a/usr/src/cmd/fm/fmtopo/common/fmtopo.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/cmd/fm/fmtopo/common/fmtopo.c	Sat Nov 04 01:18:55 2006 -0800
@@ -28,39 +28,50 @@
 
 #include <sys/fm/protocol.h>
 #include <fm/libtopo.h>
+#include <ctype.h>
 #include <limits.h>
 #include <strings.h>
 #include <stdio.h>
 #include <errno.h>
+#include <sys/param.h>
 
 #define	FMTOPO_EXIT_SUCCESS	0
 #define	FMTOPO_EXIT_ERROR	1
 #define	FMTOPO_EXIT_USAGE	2
 
+#define	STDERR	"stderr"
+#define	DOTS	"..."
+#define	ALL	"all"
+
 static const char *g_pname;
 
 static const char *opt_R = "/";
+static const char *opt_P = NULL;
 static const char *opt_s = FM_FMRI_SCHEME_HC;
 
-static int opt_e;
-static int opt_d;
-static int opt_v;
-static int opt_V;
+static int opt_e = 0;
+static int opt_d = 0;
+static int opt_V = 0;
+static int opt_p = 0;
+static int opt_x = 0;
 
 static int
 usage(FILE *fp)
 {
 	(void) fprintf(fp,
-	    "Usage: %s [-Cdev] [-R root] [-s scheme]\n", g_pname);
+	    "Usage: %s [-edpvVx] [-Cdev] [-P properties] [-R root] "
+		    "[-s scheme]\n", g_pname);
 
 	(void) fprintf(fp,
 	    "\t-C  dump core after completing execution\n"
-	    "\t-d  set debug mode for libtopo\n"
-	    "\t-e  display nodes as paths using esc/eft notation\n"
+	    "\t-d  set debug mode for libtopo modules\n"
+	    "\t-e  display FMRIs as paths using esc/eft notation\n"
+	    "\t-P  display of FMRI with the specified properties\n"
+	    "\t-p  display of FMRI protocol properties\n"
 	    "\t-R  set root directory for libtopo plug-ins and other files\n"
 	    "\t-s  display topology for the specified FMRI scheme\n"
-	    "\t-v  set verbose mode (display node ASRU, FRU and label)\n"
-	    "\t-V  set verbose mode (display node properties)\n");
+	    "\t-V  set verbose mode\n"
+	    "\t-x  display a xml formatted topology\n");
 
 	return (FMTOPO_EXIT_USAGE);
 }
@@ -89,7 +100,7 @@
 
 	(void) printf("%s\n", name);
 
-	if (opt_v) {
+	if (opt_p) {
 		char *aname = NULL, *fname = NULL, *lname = NULL;
 		nvlist_t *asru = NULL;
 		nvlist_t *fru = NULL;
@@ -120,23 +131,8 @@
 			(void) printf("\tLabel: -\n");
 		}
 	}
-
 	nvlist_free(fmri);
 
-	if (opt_d) {
-		fmri = NULL;
-
-		if (topo_fmri_str2nvl(thp, name, &fmri, &err) < 0) {
-			(void) fprintf(stderr, "%s: failed to convert "
-			    "alternate fmri for %s=%d: %s\n", g_pname,
-			    topo_node_name(node), topo_node_instance(node),
-			    topo_strerror(err));
-		} else {
-			nvlist_print(stderr, fmri);
-			nvlist_free(fmri);
-		}
-	}
-
 	topo_hdl_strfree(thp, name);
 }
 
@@ -194,28 +190,302 @@
 	(void) printf("%s\n", buf);
 }
 
+static void
+print_prop_nameval(topo_hdl_t *thp, nvlist_t *nvl, int skip)
+{
+	int err;
+	topo_type_t type;
+	char *tstr, *propn, buf[48];
+	nvpair_t *pv_nvp;
+
+	if ((pv_nvp = nvlist_next_nvpair(nvl, NULL)) == NULL)
+		return;
+
+	/* Print property name */
+	if ((pv_nvp = nvlist_next_nvpair(nvl, NULL)) == NULL ||
+	    nvpair_name(pv_nvp) == NULL ||
+	    strcmp(TOPO_PROP_VAL_NAME, nvpair_name(pv_nvp)) != 0) {
+		(void) fprintf(stderr, "%s: malformed property name\n",
+		    g_pname);
+		return;
+	} else {
+	    (void) nvpair_value_string(pv_nvp, &propn);
+	}
+
+	if ((pv_nvp = nvlist_next_nvpair(nvl, pv_nvp)) == NULL ||
+	    nvpair_name(pv_nvp) == NULL ||
+	    strcmp(nvpair_name(pv_nvp), TOPO_PROP_VAL_TYPE) != 0 ||
+	    nvpair_type(pv_nvp) != DATA_TYPE_INT32)  {
+		(void) fprintf(stderr, "%s: malformed property type for %s\n",
+		    g_pname, propn);
+		return;
+	} else {
+		(void) nvpair_value_int32(pv_nvp, (int32_t *)&type);
+	}
+
+	switch (type) {
+		case TOPO_TYPE_BOOLEAN: tstr = "boolean"; break;
+		case TOPO_TYPE_INT32: tstr = "int32"; break;
+		case TOPO_TYPE_UINT32: tstr = "uint32"; break;
+		case TOPO_TYPE_INT64: tstr = "int64"; break;
+		case TOPO_TYPE_UINT64: tstr = "uint64"; break;
+		case TOPO_TYPE_STRING: tstr = "string"; break;
+		case TOPO_TYPE_FMRI: tstr = "fmri"; break;
+		case TOPO_TYPE_INT32_ARRAY: tstr = "int32[]"; break;
+		case TOPO_TYPE_UINT32_ARRAY: tstr = "uint32[]"; break;
+		case TOPO_TYPE_INT64_ARRAY: tstr = "int64[]"; break;
+		case TOPO_TYPE_UINT64_ARRAY: tstr = "uint64[]"; break;
+		case TOPO_TYPE_STRING_ARRAY: tstr = "string[]"; break;
+		case TOPO_TYPE_FMRI_ARRAY: tstr = "fmri[]"; break;
+		default: tstr = "unknown type";
+	}
+
+	if (!skip)
+		printf("    %-17s %-8s ", propn, tstr);
+
+	/*
+	 * Get property value
+	 */
+	if (nvpair_name(pv_nvp) == NULL ||
+	    (pv_nvp = nvlist_next_nvpair(nvl, pv_nvp)) == NULL) {
+		(void) fprintf(stderr, "%s: malformed property value\n",
+		    g_pname);
+		return;
+	}
+
+	if (skip)
+		return;
+
+	switch (nvpair_type(pv_nvp)) {
+		case DATA_TYPE_INT32: {
+			int32_t val;
+			(void) nvpair_value_int32(pv_nvp, &val);
+			(void) printf(" %d", val);
+			break;
+		}
+		case DATA_TYPE_UINT32: {
+			uint32_t val;
+			(void) nvpair_value_uint32(pv_nvp, &val);
+			(void) printf(" 0x%x", val);
+			break;
+		}
+		case DATA_TYPE_INT64: {
+			int64_t val;
+			(void) nvpair_value_int64(pv_nvp, &val);
+			(void) printf(" %lld", (longlong_t)val);
+			break;
+		}
+		case DATA_TYPE_UINT64: {
+			uint64_t val;
+			(void) nvpair_value_uint64(pv_nvp, &val);
+			(void) printf(" 0x%llx", (u_longlong_t)val);
+			break;
+		}
+		case DATA_TYPE_STRING: {
+			char *val;
+			(void) nvpair_value_string(pv_nvp, &val);
+			if (!opt_V && strlen(val) > 48) {
+				(void) snprintf(buf, 48, "%s...", val);
+				(void) printf(" %s", buf);
+			} else {
+				(void) printf(" %s", val);
+			}
+			break;
+		}
+		case DATA_TYPE_NVLIST: {
+			nvlist_t *val;
+			char *fmri;
+			(void) nvpair_value_nvlist(pv_nvp, &val);
+			if (topo_fmri_nvl2str(thp, val, &fmri, &err) != 0) {
+				if (opt_V)
+					nvlist_print(stdout, nvl);
+				break;
+			}
+
+			if (!opt_V && strlen(fmri) > 48) {
+				(void) snprintf(buf, 48, "%s", fmri);
+				(void) snprintf(&buf[45], 4, "%s", DOTS);
+				(void) printf(" %s", buf);
+			} else {
+				(void) printf(" %s", fmri);
+			}
+
+			topo_hdl_strfree(thp, fmri);
+			break;
+		}
+		default:
+			(void) fprintf(stderr, " unknown data type (%d)",
+			    nvpair_type(pv_nvp));
+			break;
+		}
+		(void) printf("\n");
+}
+
+static void
+print_pgroup(char *pgn, char *dstab, char *nstab, int32_t version, int skip)
+{
+	char buf[30];
+
+	if (skip)
+		return;
+
+	if (!opt_V && strlen(pgn) > 30) {
+		(void) snprintf(buf, 26, "%s", pgn);
+		(void) snprintf(&buf[27], 4, "%s", DOTS);
+		printf("  group: %-30s version: %-3d stability: %s/%s\n",
+		    buf, version, nstab, dstab);
+	} else {
+		printf("  group: %-30s version: %-3d stability: %s/%s\n",
+		    pgn, version, nstab, dstab);
+	}
+}
+
+static int
+cmp_name(const char *props, char *pgn)
+{
+	char buf[MAXNAMELEN];
+	size_t count;
+	char *begin, *end, *value, *next;
+	char *np;
+
+	if (props == NULL)
+		return (0);
+
+	if (strcmp(props, ALL) == 0)
+		return (0);
+
+
+	value = np = strdup(props);
+
+	for (end = np; *end != '\0'; value = next) {
+		end = strchr(value, ',');
+		if (end != NULL)
+			next = end + 1; /* skip the comma */
+		else
+			next = end = value + strlen(value);
+
+		/*
+		 * Eat up white space at beginning or end of the
+		 * property group name
+		 */
+		begin = value;
+		while (begin < end && isspace(*begin))
+			begin++;
+		while (begin < end && isspace(*(end - 1)))
+			end--;
+
+		if (begin >= end)
+			return (1);
+
+		count = end - begin;
+		count += 1;
+
+		if (count > sizeof (buf))
+			return (1);
+
+		(void) snprintf(buf, count, "%s", begin);
+		if (strcmp(pgn, buf) == 0) {
+			free(np);
+			return (0);
+		}
+	}
+
+	free(np);
+	return (1);
+}
+
+static void
+print_props(topo_hdl_t *thp, nvlist_t *p_nv, const char *props)
+{
+	char *pgn = NULL, *dstab = NULL, *nstab = NULL;
+	int32_t version = 0;
+	nvlist_t *pg_nv, *pv_nv;
+	nvpair_t *nvp, *pg_nvp;
+	int pg_done = 0, skip = 0;
+
+	for (nvp = nvlist_next_nvpair(p_nv, NULL); nvp != NULL;
+	    nvp = nvlist_next_nvpair(p_nv, nvp)) {
+		if (strcmp(TOPO_PROP_GROUP, nvpair_name(nvp)) != 0 ||
+		    nvpair_type(nvp) != DATA_TYPE_NVLIST)
+			continue;
+
+		(void) nvpair_value_nvlist(nvp, &pg_nv);
+		for (pg_nvp = nvlist_next_nvpair(pg_nv, NULL); pg_nvp != NULL;
+		    pg_nvp = nvlist_next_nvpair(pg_nv, pg_nvp)) {
+			/*
+			 * Print property group name and stability levels
+			 */
+			if (strcmp(TOPO_PROP_GROUP_NAME, nvpair_name(pg_nvp))
+			    == 0 && nvpair_type(pg_nvp) == DATA_TYPE_STRING) {
+				(void) nvpair_value_string(pg_nvp, &pgn);
+
+				skip = cmp_name(props, pgn);
+
+			} else if (strcmp(TOPO_PROP_GROUP_NSTAB,
+			    nvpair_name(pg_nvp)) == 0 &&
+			    nvpair_type(pg_nvp) == DATA_TYPE_STRING) {
+				(void) nvpair_value_string(pg_nvp, &nstab);
+			} else if (strcmp(TOPO_PROP_GROUP_DSTAB,
+			    nvpair_name(pg_nvp)) == 0 &&
+			    nvpair_type(pg_nvp) == DATA_TYPE_STRING) {
+				(void) nvpair_value_string(pg_nvp, &dstab);
+			} else if (strcmp(TOPO_PROP_GROUP_VERSION,
+			    nvpair_name(pg_nvp)) == 0 &&
+			    nvpair_type(pg_nvp) == DATA_TYPE_INT32) {
+				(void) nvpair_value_int32(pg_nvp, &version);
+			}
+
+			if (!pg_done) {
+				if (pgn && dstab && nstab && version) {
+					print_pgroup(pgn, dstab, nstab,
+					    version, skip);
+					pg_done++;
+				} else {
+					continue;
+				}
+			/*
+			 * Print property name-value pair
+			 */
+			} else if (strcmp(TOPO_PROP_VAL, nvpair_name(pg_nvp))
+			    == 0 && nvpair_type(pg_nvp) == DATA_TYPE_NVLIST) {
+				(void) nvpair_value_nvlist(pg_nvp, &pv_nv);
+				print_prop_nameval(thp, pv_nv, skip);
+
+			}
+		}
+		pg_done = 0;
+		skip = 0;
+	}
+}
+
 /*ARGSUSED*/
 static int
 print_tnode(topo_hdl_t *thp, tnode_t *node, void *arg)
 {
-	if (opt_e && strcmp(opt_s, FM_FMRI_SCHEME_HC) == 0)
+	int err;
+	nvlist_t *nvl;
+
+	if (opt_e && strcmp(opt_s, FM_FMRI_SCHEME_HC) == 0) {
 		print_everstyle(node);
-	else
-		print_fmri(thp, node);
+		return (TOPO_WALK_NEXT);
+	}
 
-	if (opt_V) {
-		nvlist_t *nvl = topo_prop_get_all(thp, node);
+	print_fmri(thp, node);
 
-		if (nvl == NULL) {
-			(void) fprintf(stderr, "%s: failed to get properties "
-			    "for %s=%d\n", g_pname, topo_node_name(node),
-			    topo_node_instance(node));
+	if (opt_V || opt_P) {
+		if ((nvl = topo_prop_getprops(node, &err)) == NULL) {
+			(void) fprintf(stderr, "%s: failed to get "
+			    "properties for %s=%d: %s\n", g_pname,
+			    topo_node_name(node), topo_node_instance(node),
+			    topo_strerror(err));
 		} else {
-			nvlist_print(stdout, nvl);
+			print_props(thp, nvl, opt_P);
 			nvlist_free(nvl);
 		}
 	}
 
+	printf("\n");
+
 	return (TOPO_WALK_NEXT);
 }
 
@@ -225,12 +495,12 @@
 	topo_hdl_t *thp;
 	topo_walk_t *twp;
 	char *uuid;
-	int c, err;
+	int c, err = 0;
 
 	g_pname = argv[0];
 
 	while (optind < argc) {
-		while ((c = getopt(argc, argv, "aCdeR:s:vV")) != -1) {
+		while ((c = getopt(argc, argv, "aCdeP:pR:s:vVx")) != -1) {
 			switch (c) {
 			case 'C':
 				atexit(abort);
@@ -241,8 +511,11 @@
 			case 'e':
 				opt_e++;
 				break;
-			case 'v':
-				opt_v++;
+			case 'P':
+				opt_P = optarg;
+				break;
+			case 'p':
+				opt_p++;
 				break;
 			case 'V':
 				opt_V++;
@@ -253,6 +526,9 @@
 			case 's':
 				opt_s = optarg;
 				break;
+			case 'x':
+				opt_x++;
+				break;
 			default:
 				return (usage(stderr));
 			}
@@ -272,15 +548,31 @@
 	}
 
 	if (opt_d)
-		topo_debug_set(thp, TOPO_DBG_ALL, "stderr");
+		topo_debug_set(thp, "module", "stderr");
 
 	if ((uuid = topo_snap_hold(thp, NULL, &err)) == NULL) {
 		(void) fprintf(stderr, "%s: failed to snapshot topology: %s\n",
 		    g_pname, topo_strerror(err));
 		topo_close(thp);
 		return (FMTOPO_EXIT_ERROR);
+	} else if (err != 0) {
+		(void) fprintf(stderr, "%s: topology snapshot incomplete\n",
+		    g_pname);
 	}
 
+
+	if (opt_x) {
+		err = 0;
+		if (topo_xml_print(thp, stdout, opt_s, &err) < 0)
+			(void) fprintf(stderr, "%s: failed to print xml "
+			    "formatted topology:%s",  g_pname,
+			    topo_strerror(err));
+
+		topo_hdl_strfree(thp, uuid);
+		topo_snap_release(thp);
+		topo_close(thp);
+		return (err ? FMTOPO_EXIT_ERROR : FMTOPO_EXIT_SUCCESS);
+	}
 	if ((twp = topo_walk_init(thp, opt_s, print_tnode, NULL, &err))
 	    == NULL) {
 		(void) fprintf(stderr, "%s: failed to walk %s topology:"
@@ -293,8 +585,18 @@
 		return (err ? FMTOPO_EXIT_ERROR : FMTOPO_EXIT_SUCCESS);
 	}
 
-	if (!opt_e)
-		(void) printf("Topology Snapshot %s\n", uuid);
+	/*
+	 * Print standard header
+	 */
+	if (!opt_e) {
+		char buf[32];
+		time_t tod = time(NULL);
+
+		printf("TIME                 UUID\n");
+		(void) strftime(buf, sizeof (buf), "%b %d %T", localtime(&tod));
+		(void) printf("%-15s %-32s\n", buf, uuid);
+		(void) printf("\n");
+	}
 
 	topo_hdl_strfree(thp, uuid);
 
@@ -307,9 +609,6 @@
 		return (FMTOPO_EXIT_ERROR);
 	}
 
-	if (opt_d)
-		(void) printf("--------------------\n");
-
 	topo_walk_fini(twp);
 	topo_snap_release(thp);
 	topo_close(thp);
--- a/usr/src/cmd/fm/modules/common/eversholt/config.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/cmd/fm/modules/common/eversholt/config.c	Sat Nov 04 01:18:55 2006 -0800
@@ -41,6 +41,7 @@
 #include <ctype.h>
 #include <string.h>
 #include <strings.h>
+#include <fm/topo_hc.h>
 #include "alloc.h"
 #include "out.h"
 #include "literals.h"
@@ -341,7 +342,7 @@
 		/*
 		 * If this property is a device path, cache it for quick lookup
 		 */
-		if (pn == stable("DEV")) {
+		if (pn == stable(TOPO_IO_DEV)) {
 			sv = stable(pv);
 			out(O_ALTFP|O_VERB3, "caching %s\n", sv);
 			cdata->devcache = lut_add(cdata->devcache,
--- a/usr/src/cmd/fm/modules/common/eversholt/platform.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/cmd/fm/modules/common/eversholt/platform.c	Sat Nov 04 01:18:55 2006 -0800
@@ -48,7 +48,9 @@
 #include <sys/param.h>
 #include <sys/fm/protocol.h>
 #include <fm/fmd_api.h>
+#include <fm/fmd_fmri.h>
 #include <fm/libtopo.h>
+#include <fm/topo_hc.h>
 #include "alloc.h"
 #include "out.h"
 #include "tree.h"
@@ -395,6 +397,12 @@
 	char buf[32];	/* big enough for any 64-bit int */
 
 	/*
+	 * malformed prop nvpair
+	 */
+	if (propn == NULL)
+		return;
+
+	/*
 	 * We can only handle properties of string type
 	 */
 	switch (nvpair_type(pv_nvp)) {
@@ -427,6 +435,8 @@
 		break;
 
 	default:
+		out(O_ALTFP, "cfgcollect: failed to get property value for "
+		    "%s", propn);
 		return;
 	}
 
@@ -436,6 +446,9 @@
 	(void) snprintf(rawdata->nextfree,
 	    rawdata->end - rawdata->nextfree, "%s=%s",
 	    propn, propv);
+	if (strcmp(propn, TOPO_PROP_RESOURCE) == 0)
+		out(O_ALTFP, "cfgcollect: %s", propv);
+
 	rawdata->nextfree += addlen;
 
 	if (fmristr != NULL)
@@ -450,7 +463,7 @@
 cfgcollect(topo_hdl_t *thp, tnode_t *node, void *arg)
 {
 	struct cfgdata *rawdata = (struct cfgdata *)arg;
-	int addlen;
+	int err, addlen;
 	char *propn, *path = NULL;
 	nvlist_t *p_nv, *pg_nv, *pv_nv;
 	nvpair_t *nvp, *pg_nvp, *pv_nvp;
@@ -472,7 +485,7 @@
 	 * Better yet, topo properties could be represented as
 	 * a packed nvlist
 	 */
-	p_nv = topo_prop_get_all(thp, node);
+	p_nv = topo_prop_getprops(node, &err);
 	for (nvp = nvlist_next_nvpair(p_nv, NULL); nvp != NULL;
 	    nvp = nvlist_next_nvpair(p_nv, nvp)) {
 		if (strcmp(TOPO_PROP_GROUP, nvpair_name(nvp)) != 0 ||
@@ -490,22 +503,24 @@
 
 			(void) nvpair_value_nvlist(pg_nvp, &pv_nv);
 
+			propn = NULL;
 			for (pv_nvp = nvlist_next_nvpair(pv_nv, NULL);
 			    pv_nvp != NULL;
 			    pv_nvp = nvlist_next_nvpair(pv_nv, pv_nvp)) {
 
 				/* Get property name */
-				propn = nvpair_name(pv_nvp);
-				if (strcmp(TOPO_PROP_VAL_NAME, propn) != 0)
-					continue;
-				if (nvpair_value_string(pv_nvp, &propn) != 0)
-					continue;
+				if (strcmp(TOPO_PROP_VAL_NAME,
+				    nvpair_name(pv_nvp)) == 0)
+					(void) nvpair_value_string(pv_nvp,
+					    &propn);
 
 				/*
 				 * Get property value
 				 */
-				pv_nvp = nvlist_next_nvpair(pv_nv, pv_nvp);
-				add_prop_val(thp, rawdata, propn, pv_nvp);
+				if (strcmp(TOPO_PROP_VAL_VAL,
+				    nvpair_name(pv_nvp)) == 0)
+					add_prop_val(thp, rawdata, propn,
+					    pv_nvp);
 			}
 
 		}
@@ -523,22 +538,21 @@
 platform_config_snapshot(void)
 {
 	int err;
-	char *uuid;
 	topo_walk_t *twp;
+	static uint64_t lastgen;
+	uint64_t curgen;
 
 	/*
-	 *
 	 * If the DR generation number has changed,
 	 * we need to grab a new snapshot, otherwise we
 	 * can simply point them at the last config.
-	 *
-	 *	svgen = DRgen;
-	 *	if (svgen == (Drgen = fmd_drgen_get()) && Lastcfg != NULL) {
-	 *		Lastcfg->refcnt++;
-	 *		return (Lastcfg);
-	 *	}
 	 */
+	if ((curgen = fmd_fmri_get_drgen()) <= lastgen && Lastcfg != NULL) {
+		Lastcfg->refcnt++;
+		return (Lastcfg);
+	}
 
+	lastgen = curgen;
 	/* we're getting a new config, so clean up the last one */
 	if (Lastcfg != NULL)
 		config_free(Lastcfg);
@@ -551,19 +565,16 @@
 	Lastcfg->cpucache = NULL;
 
 	out(O_ALTFP, "platform_config_snapshot(): topo snapshot");
-	if ((uuid = topo_snap_hold(Eft_topo_hdl, NULL, &err)) == NULL)
-		out(O_DIE, "platform_config_snapshot: topo snapshot failed: %s",
-		    topo_strerror(err));
+
+	Eft_topo_hdl = fmd_hdl_topology(Hdl, TOPO_VERSION);
 
 	if ((twp = topo_walk_init(Eft_topo_hdl, FM_FMRI_SCHEME_HC, cfgcollect,
 	    Lastcfg, &err)) == NULL) {
-		topo_hdl_strfree(Eft_topo_hdl, uuid);
 		out(O_DIE, "platform_config_snapshot: NULL topology tree: %s",
 		    topo_strerror(err));
 	}
 
 	if (topo_walk_step(twp, TOPO_WALK_CHILD) == TOPO_WALK_ERR) {
-		topo_hdl_strfree(Eft_topo_hdl, uuid);
 		topo_walk_fini(twp);
 		out(O_DIE, "platform_config_snapshot: error walking topology "
 		    "tree");
@@ -571,8 +582,6 @@
 
 	topo_walk_fini(twp);
 
-	topo_hdl_strfree(Eft_topo_hdl, uuid);
-	topo_snap_release(Eft_topo_hdl);
 
 	return (Lastcfg);
 }
@@ -641,14 +650,15 @@
 	 * Find the driver for this resource and use that to get
 	 * mod and pkg fmris for ASRU and FRU respectively.
 	 */
-	if ((driverstr = cfgstrprop_lookup(croot, path, "DRIVER")) == NULL)
+	if ((driverstr = cfgstrprop_lookup(croot, path, TOPO_IO_DRIVER))
+	    == NULL)
 		return;
 
 	if (topo_hdl_nvalloc(Eft_topo_hdl, &arg, NV_UNIQUE_NAME) != 0) {
 		out(O_ALTFP, "Can not allocate nvlist for MOD fmri lookup");
 		return;
 	}
-	if (nvlist_add_string(arg, "DRIVER", driverstr) != 0) {
+	if (nvlist_add_string(arg, TOPO_IO_DRIVER, driverstr) != 0) {
 		out(O_ALTFP, "Failed to add DRIVER string to arg nvlist");
 		nvlist_free(arg);
 		return;
--- a/usr/src/cmd/fm/modules/i86pc/sfx4500-disk/diskmon_conf.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/cmd/fm/modules/i86pc/sfx4500-disk/diskmon_conf.c	Sat Nov 04 01:18:55 2006 -0800
@@ -857,7 +857,7 @@
 	u64 = fmd_prop_get_int32(hdl, GLOBAL_PROP_LOG_LEVEL);
 	g_verbose = (int)u64;
 
-	err = update_configuration_from_topo(NULL);
+	err = update_configuration_from_topo(hdl, NULL);
 
 	/* Pull in the properties from the DE configuration file */
 	while (fmd_props[i].fmdp_name != NULL) {
--- a/usr/src/cmd/fm/modules/i86pc/sfx4500-disk/schg_mgr.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/cmd/fm/modules/i86pc/sfx4500-disk/schg_mgr.c	Sat Nov 04 01:18:55 2006 -0800
@@ -234,7 +234,7 @@
 schg_update_fru_info(diskmon_t *diskp)
 {
 	if (diskp->initial_configuration ||
-	    update_configuration_from_topo(diskp) == TOPO_SUCCESS) {
+	    update_configuration_from_topo(g_fm_hdl, diskp) == TOPO_SUCCESS) {
 		diskp->initial_configuration = B_FALSE;
 		dm_assert(pthread_mutex_lock(&diskp->fru_mutex) == 0);
 		if (diskp->frup != NULL)
--- a/usr/src/cmd/fm/modules/i86pc/sfx4500-disk/topo_gather.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/cmd/fm/modules/i86pc/sfx4500-disk/topo_gather.c	Sat Nov 04 01:18:55 2006 -0800
@@ -43,6 +43,7 @@
 #include <config_admin.h>
 #include <sys/fm/protocol.h>
 #include <fm/libtopo.h>
+#include <fm/topo_hc.h>
 
 #include "sata.h"
 #include "sfx4500_props.h"
@@ -114,7 +115,7 @@
 	(void) nvlist_remove(dupfmri, FM_FMRI_HC_PART, DATA_TYPE_STRING);
 
 	thdl = fmd_hdl_topology(hdl, TOPO_VERSION);
-	if (thdl == NULL || topo_fmri_nvl2str(thdl, dupfmri, &buf, &err) != 0) {
+	if (topo_fmri_nvl2str(thdl, dupfmri, &buf, &err) != 0) {
 		nvlist_free(dupfmri);
 		return (NULL);
 	}
@@ -128,8 +129,9 @@
 }
 
 static nvlist_t *
-find_sfx4500_private_pgroup(topo_hdl_t *thp, tnode_t *node)
+find_sfx4500_private_pgroup(tnode_t *node)
 {
+	int err;
 	nvlist_t *list_of_lists, *nvlp, *dupnvlp;
 	nvlist_t *sfx4500_pgrp = NULL;
 	nvpair_t *nvp = NULL;
@@ -144,7 +146,7 @@
 	 * check inside each embedded nvlist to see if it's the pgroup we're
 	 * looking for.
 	 */
-	if ((list_of_lists = topo_prop_get_all(thp, node)) != NULL) {
+	if ((list_of_lists = topo_prop_getprops(node, &err)) != NULL) {
 		/*
 		 * Go through the list of nvlists, looking for the
 		 * property group we need.
@@ -257,9 +259,15 @@
 	*finalstringbuflen = buflen;
 }
 
+typedef struct walk_diskmon {
+	diskmon_t *target;
+	char *pfmri;
+} walk_diskmon_t;
+
 static int
-topo_add_disk(topo_hdl_t *thp, tnode_t *node, diskmon_t *target_diskp)
+topo_add_disk(topo_hdl_t *thp, tnode_t *node, walk_diskmon_t *wdp)
 {
+	diskmon_t *target_diskp = wdp->target;
 	nvlist_t	*fmri = NULL;
 	nvlist_t	*asru_fmri;
 	nvlist_t	*fru_fmri;
@@ -269,53 +277,25 @@
 	char		*serial = NULL;
 	char		*manuf = NULL;
 	char		*model = NULL;
-	char		*cstr = NULL;
 	char		*buf;
 	char		*label;
-	char		*p;
 	uint64_t	ptr = 0;
 	int		buflen;
 	int		err;
-	int		orig_cstr_len;
 	dm_fru_t	*frup;
 	diskmon_t	*diskp;
 
-	/*
-	 * Match this node to a disk in the configuration by looking at
-	 * our parent's fmri (and do that by getting our FMRI and chopping
-	 * off the last part).
-	 */
-	if (topo_node_resource(node, &fmri, &err) != 0) {
-		log_msg(MM_TOPO, "topo_add_disk: Could not generate FMRI for "
-		    "node %p!\n", (void *)node);
-		return (-1);
-	}
-
-	if (topo_fmri_nvl2str(thp, fmri, &cstr, &err) != 0) {
-		log_msg(MM_TOPO, "topo_add_disk: Could not create string for "
-		    "node %p's FMRI!\n", (void *)node);
-		nvlist_free(fmri);
-		return (-1);
-	}
-
-	nvlist_free(fmri);
-
-	/*
-	 * Chop off all but last path (since there's no way to get
-	 * the node's parent in the libtopo API).
-	 */
-	orig_cstr_len = strlen(cstr) + 1;
-	p = strrchr(cstr, '/');
-	dm_assert(p != NULL);
-	*p = 0;
-	if (nvlist_lookup_uint64(g_topo2diskmon, cstr, &ptr) != 0) {
-		log_msg(MM_TOPO, "No diskmon for parent of node %p.\n", node);
-		topo_hdl_free(thp, cstr, orig_cstr_len);
+	dm_assert(wdp->pfmri != NULL);
+	if (nvlist_lookup_uint64(g_topo2diskmon, wdp->pfmri, &ptr) != 0) {
+		log_msg(MM_TOPO, "No diskmon for %s: parent of node %p.\n",
+		    wdp->pfmri, node);
+		dstrfree(wdp->pfmri);
 		/* Skip this disk: */
 		return (0);
 	}
 
-	topo_hdl_free(thp, cstr, orig_cstr_len);
+	dstrfree(wdp->pfmri);
+	wdp->pfmri = NULL;
 
 	diskp = (diskmon_t *)(uintptr_t)ptr;
 
@@ -584,9 +564,10 @@
 
 
 static int
-topo_add_sata_port(topo_hdl_t *thp, tnode_t *node, diskmon_t *target_diskp)
+topo_add_sata_port(topo_hdl_t *thp, tnode_t *node, walk_diskmon_t *wdp)
 {
-	nvlist_t	*nvlp = find_sfx4500_private_pgroup(thp, node);
+	diskmon_t *target_diskp = wdp->target;
+	nvlist_t	*nvlp = find_sfx4500_private_pgroup(node);
 	nvlist_t	*prop_nvlp;
 	nvpair_t	*nvp = NULL;
 	char		*prop_name, *prop_value;
@@ -636,7 +617,7 @@
 			dm_assert(pthread_mutex_unlock(&diskp->fru_mutex) == 0);
 		}
 
-		dstrfree(cstr);
+		wdp->pfmri = cstr;
 		nvlist_free(nvlp);
 		return (0);
 	}
@@ -833,7 +814,7 @@
 				nvlist_free(diskprops);
 		}
 
-		dstrfree(cstr);
+		wdp->pfmri = cstr;
 	}
 
 
@@ -847,60 +828,59 @@
 {
 	char *nodename = topo_node_name(node);
 	if (strcmp(SATA_DISK, nodename) == 0)
-		return (topo_add_disk(thp, node, (diskmon_t *)arg)
+		return (topo_add_disk(thp, node, (walk_diskmon_t *)arg)
 		    ? TOPO_WALK_ERR : TOPO_WALK_NEXT);
 	else if (strcmp(SATA_PORT, nodename) == 0)
-		return (topo_add_sata_port(thp, node, (diskmon_t *)arg)
+		return (topo_add_sata_port(thp, node, (walk_diskmon_t *)arg)
 		    ? TOPO_WALK_ERR : TOPO_WALK_NEXT);
 
 	return (TOPO_WALK_NEXT);
 }
 
 
+/*ARGSUSED*/
 int
-update_configuration_from_topo(diskmon_t *diskp)
+update_configuration_from_topo(fmd_hdl_t *hdl, diskmon_t *diskp)
 {
 	int err;
 	topo_hdl_t *thp;
 	topo_walk_t *twp;
+	walk_diskmon_t wd;
 	char *uuid;
 
 	if ((thp = topo_open(TOPO_VERSION, NULL, &err)) == NULL) {
-
 		return (TOPO_OPEN_ERROR);
 	}
 
 	if ((uuid = topo_snap_hold(thp, NULL, &err)) == NULL) {
-
 		topo_close(thp);
 		return (TOPO_SNAP_ERROR);
 	}
 
-
-	if ((twp = topo_walk_init(thp, FM_FMRI_SCHEME_HC, gather_topo_cfg,
-	    diskp, &err)) == NULL) {
+	topo_hdl_strfree(thp, uuid);
 
-		topo_snap_release(thp);
-		topo_hdl_strfree(thp, uuid);
-		topo_close(thp);
-
+	wd.target = diskp;
+	wd.pfmri = NULL;
+	if ((twp = topo_walk_init(thp, FM_FMRI_SCHEME_HC, gather_topo_cfg,
+	    &wd, &err)) == NULL) {
+		topo_close(thp); /* topo_close() will release the snapshot */
 		return (err ? TOPO_WALK_INIT_ERROR : TOPO_SUCCESS);
 	}
 
-	topo_hdl_strfree(thp, uuid);
-
 	if (topo_walk_step(twp, TOPO_WALK_CHILD) == TOPO_WALK_ERR) {
 
 		topo_walk_fini(twp);
-		topo_snap_release(thp);
+		if (wd.pfmri != NULL)
+			dstrfree(wd.pfmri);
+
 		topo_close(thp);
-
 		return (TOPO_WALK_ERROR);
 	}
 
 	topo_walk_fini(twp);
-	topo_snap_release(thp);
 	topo_close(thp);
+	if (wd.pfmri != NULL)
+		dstrfree(wd.pfmri);
 
 	return (TOPO_SUCCESS);
 }
--- a/usr/src/cmd/fm/modules/i86pc/sfx4500-disk/topo_gather.h	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/cmd/fm/modules/i86pc/sfx4500-disk/topo_gather.h	Sat Nov 04 01:18:55 2006 -0800
@@ -44,7 +44,7 @@
 #define	TOPO_SNAP_ERROR		3
 #define	TOPO_OPEN_ERROR		4
 
-int		update_configuration_from_topo(diskmon_t *diskp);
+int		update_configuration_from_topo(fmd_hdl_t *, diskmon_t *diskp);
 int		init_configuration_from_topo(void);
 void		fini_configuration_from_topo(void);
 diskmon_t	*dm_fmri_to_diskmon(fmd_hdl_t *hdl, nvlist_t *fmri);
--- a/usr/src/cmd/fm/schemes/hc/scheme.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/cmd/fm/schemes/hc/scheme.c	Sat Nov 04 01:18:55 2006 -0800
@@ -25,67 +25,56 @@
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
-#include <fm/topo_mod.h>
+#include <strings.h>
 #include <fm/fmd_fmri.h>
 #include <fm/libtopo.h>
-
-typedef struct hc_walk_arg {
-	void	*p;
-	int	*resultp;
-} hc_walk_arg_t;
-
-static topo_hdl_t	*HC_thp = NULL;
-static char		*HC_uuid = NULL;
+#include <fm/topo_mod.h>
 
 int
 fmd_fmri_init(void)
 {
-	int err;
-
-	if ((HC_thp = topo_open(TOPO_VERSION, NULL, &err)) == NULL)
-		return (-1);
-
 	return (0);
 }
 
 void
 fmd_fmri_fini(void)
 {
-	if (HC_uuid) {
-		topo_snap_release(HC_thp);
-		topo_hdl_strfree(HC_thp, HC_uuid);
-		HC_uuid = NULL;
-	}
-	topo_close(HC_thp);
 }
 
+ssize_t
+fmd_fmri_nvl2str(nvlist_t *nvl, char *buf, size_t buflen)
+{
+	int err;
+	uint8_t version;
+	ssize_t len;
+	topo_hdl_t *thp;
+	char *str;
+
+	if (nvlist_lookup_uint8(nvl, FM_VERSION, &version) != 0 ||
+	    version > FM_HC_SCHEME_VERSION)
+		return (fmd_fmri_set_errno(EINVAL));
+
+	thp = fmd_fmri_topology(TOPO_VERSION);
+	if (topo_fmri_nvl2str(thp, nvl, &str, &err) != 0)
+		return (fmd_fmri_set_errno(EINVAL));
+
+	if (buf != NULL)
+		len = snprintf(buf, buflen, "%s", str);
+	else
+		len = strlen(str);
+
+	topo_hdl_strfree(thp, str);
+
+	return (len);
+}
+
+typedef struct hc_walk_arg {
+	void	*p;
+	int	*resultp;
+} hc_walk_arg_t;
+
 static int
-hc_update_topology(void)
-{
-	static uint64_t lastgen = 0;
-	int err;
-	uint64_t curgen;
-
-	if (HC_uuid == NULL ||
-	    (curgen = fmd_fmri_get_drgen()) > lastgen) {
-
-		lastgen = curgen;
-
-		if (HC_uuid) {
-			topo_snap_release(HC_thp);
-			topo_hdl_strfree(HC_thp, HC_uuid);
-			HC_uuid = NULL;
-		}
-
-		if ((HC_uuid = topo_snap_hold(HC_thp, NULL, &err)) == NULL) {
-			return (-1);
-		}
-	}
-	return (0);
-}
-
-static int
-hc_topo_walk(topo_walk_cb_t fn, void *arg, int *resultp)
+hc_topo_walk(topo_hdl_t *thp, topo_walk_cb_t fn, void *arg, int *resultp)
 {
 	int err, rv;
 	topo_walk_t *twp;
@@ -94,7 +83,7 @@
 	hcarg.p = arg;
 	hcarg.resultp = resultp;
 
-	if ((twp = topo_walk_init(HC_thp, FM_FMRI_SCHEME_HC, fn,
+	if ((twp = topo_walk_init(thp, FM_FMRI_SCHEME_HC, fn,
 	    &hcarg, &err)) == NULL)
 		return (-1);
 
@@ -105,163 +94,21 @@
 	return (rv);
 }
 
-/*
- * buf_append -- Append str to buf (if it's non-NULL).  Place prepend
- * in buf in front of str and append behind it (if they're non-NULL).
- * Continue to update size even if we run out of space to actually
- * stuff characters in the buffer.
- */
-static void
-buf_append(ssize_t *sz, char *buf, size_t buflen, char *str,
-    char *prepend, char *append)
-{
-	ssize_t left;
-
-	if (str == NULL)
-		return;
-
-	if (buflen == 0 || (left = buflen - *sz) < 0)
-		left = 0;
-
-	if (buf != NULL && left != 0)
-		buf += *sz;
-
-	if (prepend == NULL && append == NULL)
-		*sz += snprintf(buf, left, "%s", str);
-	else if (append == NULL)
-		*sz += snprintf(buf, left, "%s%s", prepend, str);
-	else if (prepend == NULL)
-		*sz += snprintf(buf, left, "%s%s", str, append);
-	else
-		*sz += snprintf(buf, left, "%s%s%s", prepend, str, append);
-}
-
-ssize_t
-fmd_fmri_nvl2str(nvlist_t *nvl, char *buf, size_t buflen)
-{
-	nvlist_t **hcprs = NULL;
-	nvlist_t *anvl = NULL;
-	uint8_t version;
-	ssize_t size = 0;
-	uint_t hcnprs;
-	char *achas = NULL;
-	char *adom = NULL;
-	char *aprod = NULL;
-	char *asrvr = NULL;
-	char *ahost = NULL;
-	char *serial = NULL;
-	char *part = NULL;
-	char *root = NULL;
-	char *rev = NULL;
-	int more_auth = 0;
-	int err, i;
-
-	if (nvlist_lookup_uint8(nvl, FM_VERSION, &version) != 0 ||
-	    version > FM_HC_SCHEME_VERSION)
-		return (fmd_fmri_set_errno(EINVAL));
-
-	/* Get authority, if present */
-	err = nvlist_lookup_nvlist(nvl, FM_FMRI_AUTHORITY, &anvl);
-	if (err != 0 && err != ENOENT)
-		return (fmd_fmri_set_errno(err));
-
-	if ((err = nvlist_lookup_string(nvl, FM_FMRI_HC_ROOT, &root)) != 0)
-		return (fmd_fmri_set_errno(EINVAL));
-
-	err = nvlist_lookup_nvlist_array(nvl, FM_FMRI_HC_LIST, &hcprs, &hcnprs);
-	if (err != 0 || hcprs == NULL)
-		return (fmd_fmri_set_errno(EINVAL));
-
-	if (anvl != NULL) {
-		(void) nvlist_lookup_string(anvl,
-		    FM_FMRI_AUTH_PRODUCT, &aprod);
-		(void) nvlist_lookup_string(anvl,
-		    FM_FMRI_AUTH_CHASSIS, &achas);
-		(void) nvlist_lookup_string(anvl,
-		    FM_FMRI_AUTH_DOMAIN, &adom);
-		(void) nvlist_lookup_string(anvl,
-		    FM_FMRI_AUTH_SERVER, &asrvr);
-		(void) nvlist_lookup_string(anvl,
-		    FM_FMRI_AUTH_HOST, &ahost);
-		if (aprod != NULL)
-			more_auth++;
-		if (achas != NULL)
-			more_auth++;
-		if (adom != NULL)
-			more_auth++;
-		if (asrvr != NULL)
-			more_auth++;
-		if (ahost != NULL)
-			more_auth++;
-	}
-
-	(void) nvlist_lookup_string(nvl, FM_FMRI_HC_SERIAL_ID, &serial);
-	(void) nvlist_lookup_string(nvl, FM_FMRI_HC_PART, &part);
-	(void) nvlist_lookup_string(nvl, FM_FMRI_HC_REVISION, &rev);
-
-	/* hc:// */
-	buf_append(&size, buf, buflen, FM_FMRI_SCHEME_HC, NULL, "://");
-
-	/* authority, if any */
-	if (aprod != NULL)
-		buf_append(&size, buf, buflen, aprod, FM_FMRI_AUTH_PRODUCT "=",
-		    --more_auth > 0 ? "," : NULL);
-	if (achas != NULL)
-		buf_append(&size, buf, buflen, achas, FM_FMRI_AUTH_CHASSIS "=",
-		    --more_auth > 0 ? "," : NULL);
-	if (adom != NULL)
-		buf_append(&size, buf, buflen, adom, FM_FMRI_AUTH_DOMAIN "=",
-		    --more_auth > 0 ? "," : NULL);
-	if (asrvr != NULL)
-		buf_append(&size, buf, buflen, asrvr, FM_FMRI_AUTH_SERVER "=",
-		    --more_auth > 0 ? "," : NULL);
-	if (ahost != NULL)
-		buf_append(&size, buf, buflen, ahost, FM_FMRI_AUTH_HOST "=",
-		    NULL);
-
-	/* separating slash */
-	if (serial != NULL || part != NULL || rev != NULL)
-		buf_append(&size, buf, buflen, "/", NULL, NULL);
-
-	/* hardware-id part */
-	buf_append(&size, buf, buflen, serial, ":" FM_FMRI_HC_SERIAL_ID "=",
-	    NULL);
-	buf_append(&size, buf, buflen, part, ":" FM_FMRI_HC_PART "=", NULL);
-	buf_append(&size, buf, buflen, rev, ":" FM_FMRI_HC_REVISION "=", NULL);
-
-	/* separating slash */
-	buf_append(&size, buf, buflen, "/", NULL, NULL);
-
-	/* hc-root */
-	buf_append(&size, buf, buflen, root, NULL, NULL);
-
-	/* all the pairs */
-	for (i = 0; i < hcnprs; i++) {
-		char *nm = NULL;
-		char *id = NULL;
-
-		if (i > 0)
-			buf_append(&size, buf, buflen, "/", NULL, NULL);
-		(void) nvlist_lookup_string(hcprs[i], FM_FMRI_HC_NAME, &nm);
-		(void) nvlist_lookup_string(hcprs[i], FM_FMRI_HC_ID, &id);
-		if (nm == NULL || id == NULL)
-			return (fmd_fmri_set_errno(EINVAL));
-		buf_append(&size, buf, buflen, nm, NULL, "=");
-		buf_append(&size, buf, buflen, id, NULL, NULL);
-	}
-
-	return (size);
-}
-
 /*ARGSUSED*/
 static int
 hc_topo_present(topo_hdl_t *thp, tnode_t *node, void *arg)
 {
 	int cmp, err;
-	nvlist_t *out = NULL;
-	nvlist_t *asru;
+	nvlist_t *out, *asru;
 	hc_walk_arg_t *hcargp = (hc_walk_arg_t *)arg;
 
+	/*
+	 * Only care about sata-ports and disks
+	 */
+	if (strcmp(topo_node_name(node), SATA_PORT) != 0 &&
+	    strcmp(topo_node_name(node), DISK) != 0)
+		return (TOPO_WALK_NEXT);
+
 	if (topo_node_asru(node, &asru, NULL, &err) != 0 ||
 	    asru == NULL) {
 		return (TOPO_WALK_NEXT);
@@ -280,49 +127,80 @@
 	/*
 	 * Yes, so try to execute the topo-present method.
 	 */
-	cmp = topo_method_invoke(node, TOPO_METH_PRESENT,
-	    TOPO_METH_PRESENT_VERSION, (nvlist_t *)hcargp->p, &out, &err);
-
-	if (out)
+	if (topo_method_invoke(node, TOPO_METH_PRESENT,
+	    TOPO_METH_PRESENT_VERSION, (nvlist_t *)hcargp->p, &out, &err)
+	    == 0) {
+		(void) nvlist_lookup_uint32(out, TOPO_METH_PRESENT_RET,
+		    (uint32_t *)hcargp->resultp);
 		nvlist_free(out);
-
-	if (cmp == 1) {
-		*(hcargp->resultp) = 1;
 		return (TOPO_WALK_TERMINATE);
-	} else if (cmp == 0) {
-		*(hcargp->resultp) = 0;
-		return (TOPO_WALK_TERMINATE);
+	} else {
+		return (TOPO_WALK_ERR);
 	}
 
-	return (TOPO_WALK_NEXT);
 }
 
-
 /*
- * fmd_fmri_present() is called by fmadm to determine if a faulty ASRU
- * is still present in the system.  In general we don't expect to get
- * ASRUs in this scheme, so it's unlikely this routine will get called.
- * In case it does, though, we just traverse our libtopo snapshot,
- * looking for a matching ASRU (minus the serial number information),
- * then invoke the "topo_present" method to determine presence.
+ * The SATA disk topology permits an ASRU to be declared as a pseudo-hc
+ * FMRI, something like this:
+ *
+ *	hc:///motherboard=0/hostbridge=0/pcibus=0/pcidev=1/pcifn=0/sata-port=1
+ *		ASRU: hc:///component=sata0/1
+ *		FRU: hc:///component=MB
+ *		Label: sata0/1
+ *
+ * This is a hack to support cfgadm attachment point ASRUs without defining
+ * a new scheme.  As a result, we need to support an is_present function for
+ * something * that begins with hc:///component=.  To do this, we compare the
+ * nvlist provided by the caller against the ASRU property for all possible
+ * topology nodes.
+ *
+ * The SATA phase 2 project will address the lack of a proper FMRI scheme
+ * for cfgadm attachment points.  This code may be removed when the SATA
+ * phase 2 FMA work is completed.
  */
-int
-fmd_fmri_present(nvlist_t *nvl)
+static int
+hc_sata_hack(nvlist_t *nvl)
 {
 	int ispresent = 1;
+	topo_hdl_t *thp;
 
 	/*
 	 * If there's an error during the topology update, punt by
 	 * indicating presence.
 	 */
-	if (hc_update_topology() < 0)
-		return (1);
-
-	(void) hc_topo_walk(hc_topo_present, nvl, &ispresent);
+	thp = fmd_fmri_topology(TOPO_VERSION);
+	(void) hc_topo_walk(thp, hc_topo_present, nvl, &ispresent);
 
 	return (ispresent);
 }
 
+int
+fmd_fmri_present(nvlist_t *nvl)
+{
+	int err, present;
+	topo_hdl_t *thp;
+	nvlist_t **hcprs;
+	char *nm;
+	uint_t hcnprs;
+
+	err = nvlist_lookup_nvlist_array(nvl, FM_FMRI_HC_LIST, &hcprs, &hcnprs);
+	err |= nvlist_lookup_string(hcprs[0], FM_FMRI_HC_NAME, &nm);
+	if (err != 0)
+		return (0);
+
+	if (strcmp(nm, "component") == 0)
+		return (hc_sata_hack(nvl));
+
+	thp = fmd_fmri_topology(TOPO_VERSION);
+	present = topo_fmri_present(thp, nvl, &err);
+
+	if (err != 0)
+		return (present);
+	else
+		return (1);
+}
+
 /*
  * fmd_fmri_unusable() is called by fmadm to determine if a faulty ASRU
  * is usable.  In general we don't expect to get ASRUs in this scheme,
--- a/usr/src/cmd/fm/schemes/mem/mem.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/cmd/fm/schemes/mem/mem.c	Sat Nov 04 01:18:55 2006 -0800
@@ -348,7 +348,7 @@
 	 * If we have a well-formed unum (hc-FMRI), use the string verbatim
 	 * to form the initial mem:/// components.  Otherwise use unum=%s.
 	 */
-	if (strncmp(rawunum, "hc:///", 6) != 0)
+	if (strncmp(rawunum, "hc://", 5) != 0)
 		prefix = FM_FMRI_MEM_UNUM "=";
 	else
 		prefix = "";
@@ -371,14 +371,18 @@
 	}
 
 	/*
-	 * If we have a well-formed unum (hc-FMRI), leave it as is.
+	 * If we have a well-formed unum (hc-FMRI), we skip over the
+	 * the scheme and authority prefix.
 	 * Otherwise, the spaces and colons will be escaped,
 	 * rendering the resulting FMRI pretty much unreadable.
 	 * We're therefore going to do some escaping of our own first.
 	 */
-	if (strncmp(rawunum, "hc:///", 6) == 0) {
+	if (strncmp(rawunum, "hc://", 5) == 0) {
+		rawunum += 5;
+		rawunum = strchr(rawunum, '/');
+		++rawunum;
 		/* LINTED: variable format specifier */
-		size = snprintf(buf, buflen, format, rawunum + 6, val);
+		size = snprintf(buf, buflen, format, rawunum, val);
 	} else {
 		preunum = fmd_fmri_strdup(rawunum);
 		presz = strlen(preunum) + 1;
--- a/usr/src/cmd/fm/scripts/fmsim.ksh	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/cmd/fm/scripts/fmsim.ksh	Sat Nov 04 01:18:55 2006 -0800
@@ -3,9 +3,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
 #
 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 # or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 #ident	"%Z%%M%	%I%	%E% SMI"
@@ -76,12 +75,21 @@
 		case $name in
 		_fmd_init)        cp $1 $2/usr/lib/fm/fmd/plugins; return ;;
 		fmd_fmri_nvl2str) cp $1 $2/usr/lib/fm/fmd/schemes; return ;;
-		topo_load)        cp $1 $2/usr/lib/fm/topo; return ;;
+		topo_load)        cp $1 $2/usr/lib/fm/topo/plugins; return ;;
 		esac
 	done
 	die "\nunknown .so type -- $1"
 }
 
+function cp_topo
+{
+	mkdir -p $2/usr/lib/fm/topo/maps
+	cp $1 $2/usr/lib/fm/topo/maps; 
+	for platdir in $2/usr/platform/*/lib/fm/topo/maps; do
+		rm -f $platdir/* 2>/dev/null
+	done
+}
+
 function list_cmds
 {
 	for cmd in fmadm fmdump fmstat; do
@@ -220,14 +228,15 @@
 	fmd.conf) cp $file $simroot/etc/fm/fmd ;;
 	*.conf)	cp $file $simroot/usr/lib/fm/fmd/plugins ;;
 	*.dict)	cp $file $simroot/usr/lib/fm/dict ;;
-	*.eft)	die "\neversholt fault tree file not yet supported -- $file" ;;
+	*.eft) cp $file $simroot/usr/lib/fm/eft ;;
 	*.esc)	die "\neversholt source file not yet supported -- $file" ;;
 	*.inj)	inj_args="$inj_args $file" ;;
 	*.log)	inj_args="$inj_args $file" ;;
 	*log)	inj_args="$inj_args $file" ;;
 	*.mo)	cp $file $simroot/usr/lib/locale/$LANG/LC_MESSAGES ;;
 	*.so)	cp_so $file $simroot ;;
-	*.topo) cp $file $simroot/usr/lib/fm/topo ;;
+	*.topo) die "\n .topo files not supported -- $file" ;;
+	*.xml) cp_topo $file $simroot ;;
 	*)	die "\nunknown file type or suffix -- $file" ;;
 	esac
 	echo " $base\c"
@@ -243,7 +252,7 @@
 # Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-#ident	"%Z%%M%	%I%	%E% SMI"
+#ident	"@(#)fmsim.ksh	1.5	06/10/11 SMI"
 
 #
 # fmsim(1M) script generated for $simroot $(date)
--- a/usr/src/lib/fm/topo/Makefile	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/Makefile	Sat Nov 04 01:18:55 2006 -0800
@@ -2,9 +2,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
 #
 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 # or http://www.opensolaris.org/os/licensing.
@@ -25,6 +24,6 @@
 #
 #ident	"%Z%%M%	%I%	%E% SMI"
 
-SUBDIRS = libtopo modules files
+SUBDIRS = libtopo modules maps
 
 include ../Makefile.subdirs
--- a/usr/src/lib/fm/topo/Makefile.rootdirs	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/Makefile.rootdirs	Sat Nov 04 01:18:55 2006 -0800
@@ -2,9 +2,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
 #
 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 # or http://www.opensolaris.org/os/licensing.
@@ -35,7 +34,7 @@
 $(ROOT)/usr/lib/fm/topo: $(ROOT)/usr/lib/fm
 	$(INS.dir)
 
-$(ROOT)/usr/lib/fm/topo/%: $(ROOT)/usr/lib/fm/topo
+$(ROOT)/usr/lib/fm/topo/$(MODCLASS): $(ROOT)/usr/lib/fm/topo
 	$(INS.dir)
 
 #
@@ -50,13 +49,3 @@
 
 $(ROOT)/usr/platform/%/lib/fm/topo/$(MODCLASS): $(ROOT)/usr/platform/%/lib/fm/topo
 	$(INS.dir)
-
-#
-# Define the transitive set of rules to create platform.xml install directories
-# within the proto area.  This is used by all Makefile.xml files
-#
-$(ROOT)/usr/platform/%/lib/fm:
-	$(INS.dir)
-
-$(ROOT)/usr/platform/%/lib/fm/topo: $(ROOT)/usr/platform/%/lib/fm
-	$(INS.dir)
--- a/usr/src/lib/fm/topo/files/Makefile	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
-
-sparc_SUBDIRS =	sun4u \
-		sun4v \
-		SUNW,Sun-Fire \
-		SUNW,Sun-Fire-T200 \
-		SUNW,Sun-Fire-15000 \
-		SUNW,SPARC-Enterprise \
-		SUNW,Sun-Blade-T6300
-
-i386_SUBDIRS = i86pc
-
-SUBDIRS = $($(MACH)_SUBDIRS)
-
-include ../../Makefile.subdirs
--- a/usr/src/lib/fm/topo/files/Makefile.file	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
-
-include ../../../Makefile.lib
-include ../../../../Makefile.lib
-
-DTDSRC = $(DTDFILE:%=../common/%)
-DTDTARG = $(DTDFILE:%=%)
-ROOT_DTDTARG = $(DTDTARG:%=$(ROOT)/usr/share/lib/xml/dtd/%)
-
-TOPOTARG = $(TOPOFILE:%=%)
-common_TOPOTARG = $(ROOT)/usr/lib/fm/topo/$(TOPOTARG)
-arch_TOPOTARG = $(ROOT)/usr/platform/$(ARCH)/lib/fm/topo/$(TOPOTARG)
-platform_TOPOTARG = \
-	$(PLATFORMS:%=$(ROOT)/usr/platform/%/lib/fm/topo/$(TOPOTARG))
-ROOT_TOPOTARG = $($(CLASS)_TOPOTARG)
-
-all: $(ROOT_DTDTARG) $(ROOT_TOPOTARG)
-
-clean:
-	$(RM) $(ROOT_DTDTARG) $(ROOT_TOPOTARG)
-
-clobber: clean
-
-check: $(CHECKHDRS)
-
-install_h lint _msg:
-
-$(ROOT_DTDTARG): $$(@D)
-	$(RM) $@; $(INS) -s -m 0444 -f $(@D) $(DTDSRC)
-
-$(ROOT_TOPOTARG): $$(@D)
-	$(RM) $@; $(INS) -s -m 0444 -f $(@D) $(TOPOTARG)
-
-install: $(ROOT_DTDTARG) $(ROOT_TOPOTARG)
-
-include ../../Makefile.rootdirs
-
--- a/usr/src/lib/fm/topo/files/SUNW,SPARC-Enterprise/Makefile	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#ident	"%Z%%M%	%I%	%E% SMI"
-
-PLATFORMS = SUNW,SPARC-Enterprise
-CLASS = platform
-DTDFILE = 
-TOPOFILE = hc-topology.xml
-SRCDIR = ../SUNW,SPARC-Enterprise
-
-include ../Makefile.file
--- a/usr/src/lib/fm/topo/files/SUNW,SPARC-Enterprise/hc-topology.xml	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1">
-<!--
- Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- Use is subject to license terms.
-
- CDDL HEADER START
-
- The contents of this file are subject to the terms of the
- Common Development and Distribution License (the "License").
- You may not use this file except in compliance with the License.
-
- You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- or http://www.opensolaris.org/os/licensing.
- See the License for the specific language governing permissions
- and limitations under the License.
-
- When distributing Covered Code, include this CDDL HEADER in each
- file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- If applicable, add the following below this CDDL HEADER, with the
- fields enclosed by brackets "[]" replaced with your own identifying
- information: Portions Copyright [yyyy] [name of copyright owner]
-
- CDDL HEADER END
-
-    ident	"%Z%%M%	%I%	%E% SMI"
--->
-
-<topology name='SUNW,SPARC-Enterprise' scheme='hc'>
-  <range name='chassis' min='0' max='0'>
-    <node instance='0'>
-      <propgroup name='protocol'>
-        <propval name='FRU' type='fmri'
-          value='hc:///chassis=0' />
-      </propgroup>
-    </node>
-    <dependents grouping='children'>
-      <range name='ioboard' min='0' max='15'>
-        <enum-method name='ioboard' version='1'
-          path='%r/usr/platform/SUNW,SPARC-Enterprise/lib/fm/topo/plugins' />
-      </range>
-    </dependents>
-  </range>
-</topology>
--- a/usr/src/lib/fm/topo/files/SUNW,Sun-Blade-T6300/Makefile	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
-
-PLATFORMS = SUNW,Sun-Blade-T6300
-CLASS = platform
-DTDFILE = 
-TOPOFILE = hc-topology.xml
-SRCDIR = ../SUNW,Sun-Blade-T6300
-
-include ../Makefile.file
--- a/usr/src/lib/fm/topo/files/SUNW,Sun-Blade-T6300/hc-topology.xml	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1">
-<!--
- Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- Use is subject to license terms.
-
- CDDL HEADER START
-
- The contents of this file are subject to the terms of the
- Common Development and Distribution License (the "License").
- You may not use this file except in compliance with the License.
-
- You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- or http://www.opensolaris.org/os/licensing.
- See the License for the specific language governing permissions
- and limitations under the License.
-
- When distributing Covered Code, include this CDDL HEADER in each
- file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- If applicable, add the following below this CDDL HEADER, with the
- fields enclosed by brackets "[]" replaced with your own identifying
- information: Portions Copyright [yyyy] [name of copyright owner]
-
- CDDL HEADER END
-
-    ident	"%Z%%M%	%I%	%E% SMI"
--->
-
-<topology name='SUNW,Sun-Blade-T6300' scheme='hc'>
-  <range name='motherboard' min='0' max='0'>
-    <node instance='0'>
-      <propgroup name='protocol'>
-        <propval name='FRU' type='fmri'
-          value='hc:///motherboard=0' />
-        <propval name='label' type='string'
-          value='MB' />
-      </propgroup>
-    </node>
-    <dependents grouping='children'>
-     <range name='hostbridge' min='0' max='254'>
-       <enum-method name='hostbridge' version='1'
-         path='%r/usr/platform/sun4v/lib/fm/topo/plugins' />
-     </range>
-    </dependents>
-  </range>
-</topology>
--- a/usr/src/lib/fm/topo/files/SUNW,Sun-Fire-15000/Makefile	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#ident	"%Z%%M%	%I%	%E% SMI"
-
-PLATFORMS = SUNW,Sun-Fire-15000
-CLASS = platform
-DTDFILE = 
-TOPOFILE = hc-topology.xml
-SRCDIR = ../SUNW,Sun-Fire-15000
-
-include ../Makefile.file
--- a/usr/src/lib/fm/topo/files/SUNW,Sun-Fire-15000/hc-topology.xml	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1">
-<!--
- Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- Use is subject to license terms.
-
- CDDL HEADER START
-
- The contents of this file are subject to the terms of the
- Common Development and Distribution License (the "License").
- You may not use this file except in compliance with the License.
-
- You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- or http://www.opensolaris.org/os/licensing.
- See the License for the specific language governing permissions
- and limitations under the License.
-
- When distributing Covered Code, include this CDDL HEADER in each
- file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- If applicable, add the following below this CDDL HEADER, with the
- fields enclosed by brackets "[]" replaced with your own identifying
- information: Portions Copyright [yyyy] [name of copyright owner]
-
- CDDL HEADER END
-
-    ident	"%Z%%M%	%I%	%E% SMI"
--->
-
-<topology name='SUNW,Sun-Fire-15000' scheme='hc'>
-  <range name='interconnect' min='0' max='0'>
-    <node instance='0'>
-      <propgroup name='protocol'>
-        <propval name='FRU' type='fmri'
-          value='hc:///interconnect=0' />
-      </propgroup>
-    </node>
-    <dependents grouping='children'>
-      <range name='ioboard' min='0' max='17'>
-        <enum-method name='ioboard' version='1'
-          path='%r/usr/platform/SUNW,Sun-Fire-15000/lib/fm/topo/plugins' />
-      </range>
-      <range name='cpu' min='0' max='100'>
-        <enum-method name='chip' version='1'
-          path='%r/usr/platform/sun4u/lib/fm/topo/plugins' />
-      </range>
-    </dependents>
-  </range>
-</topology>
--- a/usr/src/lib/fm/topo/files/SUNW,Sun-Fire-T200/Makefile	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#ident	"%Z%%M%	%I%	%E% SMI"
-
-PLATFORMS = SUNW,Sun-Fire-T200
-CLASS = platform
-DTDFILE = 
-TOPOFILE = hc-topology.xml
-SRCDIR = ../SUNW,Sun-Fire-T200
-
-include ../Makefile.file
--- a/usr/src/lib/fm/topo/files/SUNW,Sun-Fire-T200/hc-topology.xml	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1">
-<!--
- Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- Use is subject to license terms.
-
- CDDL HEADER START
-
- The contents of this file are subject to the terms of the
- Common Development and Distribution License (the "License").
- You may not use this file except in compliance with the License.
-
- You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- or http://www.opensolaris.org/os/licensing.
- See the License for the specific language governing permissions
- and limitations under the License.
-
- When distributing Covered Code, include this CDDL HEADER in each
- file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- If applicable, add the following below this CDDL HEADER, with the
- fields enclosed by brackets "[]" replaced with your own identifying
- information: Portions Copyright [yyyy] [name of copyright owner]
-
- CDDL HEADER END
-
-    ident	"%Z%%M%	%I%	%E% SMI"
--->
-
-<topology name='SUNW,Sun-Fire-T200' scheme='hc'>
-  <range name='motherboard' min='0' max='0'>
-    <node instance='0'>
-      <propgroup name='protocol'>
-        <propval name='FRU' type='fmri'
-          value='hc:///component=MB' />
-        <propval name='label' type='string'
-          value='MB' />
-      </propgroup>
-    </node>
-    <dependents grouping='children'>
-      <range name='ioboard' min='0' max='0'>
-        <enum-method name='ioboard' version='1'
-          path='%r/usr/platform/sun4v/lib/fm/topo/plugins' />
-      </range>
-    </dependents>
-  </range>
-  <range name='ioboard' min='0' max='0'>
-    <enum-method name='ioboard' version='1'
-      path='%r/usr/platform/sun4v/lib/fm/topo/plugins' />
-  </range>
-</topology>
--- a/usr/src/lib/fm/topo/files/SUNW,Sun-Fire/Makefile	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#ident	"%Z%%M%	%I%	%E% SMI"
-
-PLATFORMS = SUNW,Sun-Fire
-CLASS = platform
-DTDFILE = 
-TOPOFILE = hc-topology.xml
-SRCDIR = ../SUNW,Sun-Fire
-
-include ../Makefile.file
--- a/usr/src/lib/fm/topo/files/SUNW,Sun-Fire/hc-topology.xml	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1">
-<!--
- Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- Use is subject to license terms.
-
- CDDL HEADER START
-
- The contents of this file are subject to the terms of the
- Common Development and Distribution License (the "License").
- You may not use this file except in compliance with the License.
-
- You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- or http://www.opensolaris.org/os/licensing.
- See the License for the specific language governing permissions
- and limitations under the License.
-
- When distributing Covered Code, include this CDDL HEADER in each
- file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- If applicable, add the following below this CDDL HEADER, with the
- fields enclosed by brackets "[]" replaced with your own identifying
- information: Portions Copyright [yyyy] [name of copyright owner]
-
- CDDL HEADER END
-
-    ident	"%Z%%M%	%I%	%E% SMI"
--->
-
-<topology name='SUNW,Sun-Fire' scheme='hc'>
-  <range name='centerplane' min='0' max='0'>
-    <node instance='0'>
-      <propgroup name='protocol'>
-        <propval name='FRU' type='fmri'
-          value='hc:///centerplane=0' />
-      </propgroup>
-    </node>
-    <dependents grouping='children'>
-      <range name='ioboard' min='0' max='9'>
-        <enum-method name='ioboard' version='1'
-          path='%r/usr/platform/SUNW,Sun-Fire/lib/fm/topo/plugins' />
-      </range>
-      <range name='cpu' min='0' max='100'>
-        <enum-method name='chip' version='1'
-          path='%r/usr/platform/sun4u/lib/fm/topo/plugins' />
-      </range>
-    </dependents>
-  </range>
-</topology>
--- a/usr/src/lib/fm/topo/files/common/topology.dtd.1	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,295 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- Use is subject to license terms.
-
- CDDL HEADER START
-
- The contents of this file are subject to the terms of the
- Common Development and Distribution License, Version 1.0 only
- (the "License").  You may not use this file except in compliance
- with the License.
-
- You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- or http://www.opensolaris.org/os/licensing.
- See the License for the specific language governing permissions
- and limitations under the License.
-
- When distributing Covered Code, include this CDDL HEADER in each
- file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- If applicable, add the following below this CDDL HEADER, with the
- fields enclosed by brackets "[]" replaced with your own identifying
- information: Portions Copyright [yyyy] [name of copyright owner]
-
- CDDL HEADER END
-
-    ident	"%Z%%M%	%I%	%E% SMI"
--->
-
-<!--
-  Topology description DTD
-
-    Most attributes are string values (or an individual string from a
-    restricted set), but attributes with a specific type requirement are
-    noted in the comment describing the element.
--->
-
-<!--
-  XInclude support
-
-    Topologies may be composed via the xi:include tag.
-    libtopo(3LIB) interfaces enforce that all composed topologies be of the
-    same scheme.
--->
-
-<!ELEMENT xi:include
-	(xi:fallback) >
-
-<!ATTLIST xi:include
-  href CDATA #REQUIRED
-  parse (xml|text) "xml"
-  encoding CDATA #IMPLIED
-  xmlns:xi CDATA #FIXED "http://www.w3.org/2001/XInclude"
-  >
-
-<!ELEMENT xi:fallback
-  ANY
-  >
-<!ATTLIST xi:fallback
-  xmlns:xi CDATA #FIXED "http://www.w3.org/2001/XInclude"
-  >
-
-<!--
-  data-stability
-
-    This element associates an SMI stability level with the parent
-    element's data.  See attributes(5) for an explanation of interface
-    stability levels.
-
-    Its attribute is
-
-	value	The stability level of the parent element's data.
--->
-
-<!ELEMENT data-stability EMPTY>
-
-<!ATTLIST data-stability
-	value		( Standard | Stable | Evolving | Unstable |
-			External | Obsolete ) #REQUIRED >
-
-<!--
-  name-stability
-
-    This element associates an SMI stability level with the parent
-    element's name.  See attributes(5) for an explanation of interface
-    stability levels.
-
-    Its attribute is
-
-	value	The stability level of the parent element's name.
--->
-
-<!ELEMENT name-stability EMPTY>
-
-<!ATTLIST name-stability
-	value		( Standard | Stable | Evolving | Unstable |
-			External | Obsolete ) #REQUIRED >
-
-<!-- Properties and property groups -->
-
-<!--
-   propval
-
-     This element is for a singly valued property within a property
-     group.
-
-     Its attributes are
-
-	name	The name of this property.
-
-	type	The data type for this property.
-
-	value	The value for this property.  Must match type
-		restriction of type attribute.
-
-	immutable This value remains unchanged for the lifetime of a snapshot.
--->
-
-<!ELEMENT propval
-	(name-stability?, data-stability?) >
-
-<!ATTLIST propval
-	name		CDATA #REQUIRED
-	type		( int32 | uint32 | int64 | uint64 |
-			  string | fmri ) #REQUIRED
-	value		CDATA #REQUIRED
-	immutable	( true | false ) "true" >
-
-<!--
-  propgroup
-
-    This element is for a set of related properties on a topo node
-    It contains an optional stability element, as well as
-    zero or more property-containing elements.
-
-    Its attributes are
-
-	name	The name of this property group.
-
--->
-
-<!ELEMENT propgroup
-	( name-stability?, propval* ) >
-
-<!ATTLIST propgroup
-	name		CDATA #REQUIRED>
-
-<!-- Methods -->
-
-<!--
-  argval
-
-    An method argument. It has two attributes:
-
-	name	The name of the argument.
-	type	The data type of the argument.
--->
-
-<!ELEMENT argval EMPTY>
-
-<!ATTLIST argval
-	name		CDATA #REQUIRED
-	type		CDATA #REQUIRED >
-
-<!--
-  enum-method
-
-    This element describes the enumeration method used to
-    populate a composition of topo nodes.  Its interpretation is
-    left to the enumerator to which a particular topo node is
-    assigned.  It contains a set of attributes, context, and an optional
-    stability element for the optional args that can be included.
-
-    Its attributes are
-
-	name	Name of this method.  The method names are
-		usually a defined interface of the enumerator to which a
-		topo instance assigned.
-
-	path	location of enumerator
-
-	version Version of the enumeration API
--->
-
-<!ELEMENT enum-method
-	( apply-method* ) >
-
-<!ATTLIST enum-method
-	name		CDATA #REQUIRED
-	path		CDATA #REQUIRED
-	version		CDATA #REQUIRED >
-
-<!--
-  apply-method
-
-    This element describes one of the methods used by an enumerator
-    to act populate a composition of topo nodes.  Its interpretation is
-    left to the enumerator to which a particular topo node is
-    assigned.  It contains a set of attributes, context, and an optional
-    stability element for the optional args that can be included.
-
-    Its attributes are
-
-	name	Name of this method.  The method names are
-		usually a defined interface of the enumerator to which a
-		topo instance assigned.
-
-	version Version of the function API
-
-	description English description of the method
--->
-
-<!ELEMENT apply-method
-	( name-stability?, argval* ) >
-
-<!ATTLIST apply-method
-	name		CDATA #REQUIRED
-	version		CDATA #REQUIRED
-	description	CDATA #REQUIRED >
-
-<!--
-  node
-
-    This element identifies a known topology node.
-
-    Its attributes are
-
-	name	The name of the topo node
-
-	instance The instance number of the known node
-
--->
-
-<!ELEMENT node
-	( propgroup*, dependents* ) >
-
-<!ATTLIST node
-	instance	CDATA #REQUIRED >
-
-<!--
-  dependents
-
-	Ranges may have a number of "dependent" ranges, linked to
-	the original range hierarchically as children or siblings. 
-
-	Its attribute is:
-		grouping	"children", "siblings"
--->
-
-<!ELEMENT dependents 
-	( range | xi:include )+ >
-
-<!ATTLIST dependents 
-	grouping ( children | siblings ) #REQUIRED >
-
-<!--
-  range
-
-    This element identifies a range of possible topology nodes.
-
-    Its attributes are
-
-	name	The common name of all the possible topo nodes
-
-	min	The smallest allowed instance number for an
-		actual topo node.
-
-	max	The largest allowed instance number for an
-		actual topo node.
-
--->
-
-<!ELEMENT range
-	( enum-method?, node*, propgroup*, dependents* ) >
-
-<!ATTLIST range
-	name		CDATA #REQUIRED
-	min		CDATA #REQUIRED
-	max		CDATA #REQUIRED >
-
-<!--
-  topology
-
-	This is the root-level for the scheme-specific topology
-
-	Its attributes are:
-		name	topology name
-		scheme  "hc", "dev"
--->
-
-<!ELEMENT topology
-	(range* | xi:include*)>
-
-<!ATTLIST topology
-	name	CDATA #REQUIRED
-	scheme (hc | dev) #REQUIRED >
--- a/usr/src/lib/fm/topo/files/i86pc/Makefile	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#ident	"%Z%%M%	%I%	%E% SMI"
-
-ARCH = i86pc
-CLASS = arch
-DTDFILE = topology.dtd.1
-TOPOFILE = hc-topology.xml
-SRCDIR = ../i86pc
-
-include ../Makefile.file
--- a/usr/src/lib/fm/topo/files/i86pc/hc-topology.xml	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1">
-<!--
- Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- Use is subject to license terms.
-
- CDDL HEADER START
-
- The contents of this file are subject to the terms of the
- Common Development and Distribution License (the "License").
- You may not use this file except in compliance with the License.
-
- You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- or http://www.opensolaris.org/os/licensing.
- See the License for the specific language governing permissions
- and limitations under the License.
-
- When distributing Covered Code, include this CDDL HEADER in each
- file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- If applicable, add the following below this CDDL HEADER, with the
- fields enclosed by brackets "[]" replaced with your own identifying
- information: Portions Copyright [yyyy] [name of copyright owner]
-
- CDDL HEADER END
-
-    ident	"%Z%%M%	%I%	%E% SMI"
--->
-
-<topology name='i86pc' scheme='hc'>
-
-  <range name='motherboard' min='0' max='0'>
-    <node instance='0'>
-      <propgroup name='protocol'>
-        <propval name='FRU' type='fmri'
-          value='hc:///motherboard=0' />
-        <propval name='label' type='string'
-          value='MB' />
-      </propgroup>
-    </node>
-    <dependents grouping='children'>
-
-      <range name='chip' min='0' max='100'>
-        <enum-method name='chip' version='1'
-          path='%r/usr/platform/i86pc/lib/fm/topo/plugins' />
-      </range>
-
-      <range name='hostbridge' min='0' max='254'>
-        <enum-method name='hostbridge' version='1'
-          path='%r/usr/platform/i86pc/lib/fm/topo/plugins' />
-      </range>
-
-    </dependents>
-  </range>
-
-</topology>
--- a/usr/src/lib/fm/topo/files/sun4u/Makefile	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#ident	"%Z%%M%	%I%	%E% SMI"
-
-ARCH = sun4u
-CLASS = arch
-DTDFILE = topology.dtd.1
-TOPOFILE = hc-topology.xml
-SRCDIR = ../sun4u
-
-include ../Makefile.file
--- a/usr/src/lib/fm/topo/files/sun4u/hc-topology.xml	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1">
-<!--
- Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- Use is subject to license terms.
-
- CDDL HEADER START
-
- The contents of this file are subject to the terms of the
- Common Development and Distribution License (the "License").
- You may not use this file except in compliance with the License.
-
- You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- or http://www.opensolaris.org/os/licensing.
- See the License for the specific language governing permissions
- and limitations under the License.
-
- When distributing Covered Code, include this CDDL HEADER in each
- file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- If applicable, add the following below this CDDL HEADER, with the
- fields enclosed by brackets "[]" replaced with your own identifying
- information: Portions Copyright [yyyy] [name of copyright owner]
-
- CDDL HEADER END
-
-    ident	"%Z%%M%	%I%	%E% SMI"
--->
-
-<topology name='sun4u' scheme='hc'>
-  <range name='motherboard' min='0' max='0'>
-    <node instance='0'>
-      <propgroup name='protocol'>
-        <propval name='FRU' type='fmri'
-          value='hc:///motherboard=0' />
-        <propval name='label' type='string'
-          value='MB' />
-      </propgroup>
-    </node>
-    <dependents grouping='children'>
-      <range name='hostbridge' min='0' max='254'>
-        <enum-method name='hostbridge' version='1'
-          path='%r/usr/platform/sun4u/lib/fm/topo/plugins' />
-      </range>
-      <range name='cpu' min='0' max='100'>
-        <enum-method name='chip' version='1'
-          path='%r/usr/platform/sun4u/lib/fm/topo/plugins' />
-      </range>
-    </dependents>
-  </range>
-</topology>
--- a/usr/src/lib/fm/topo/files/sun4v/Makefile	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#ident	"%Z%%M%	%I%	%E% SMI"
-
-ARCH = sun4v
-CLASS = arch
-DTDFILE = 
-TOPOFILE = hc-topology.xml
-SRCDIR = ../sun4v
-
-include ../Makefile.file
--- a/usr/src/lib/fm/topo/files/sun4v/hc-topology.xml	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1">
-<!--
- Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- Use is subject to license terms.
-
- CDDL HEADER START
-
- The contents of this file are subject to the terms of the
- Common Development and Distribution License (the "License").
- You may not use this file except in compliance with the License.
-
- You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- or http://www.opensolaris.org/os/licensing.
- See the License for the specific language governing permissions
- and limitations under the License.
-
- When distributing Covered Code, include this CDDL HEADER in each
- file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- If applicable, add the following below this CDDL HEADER, with the
- fields enclosed by brackets "[]" replaced with your own identifying
- information: Portions Copyright [yyyy] [name of copyright owner]
-
- CDDL HEADER END
-
-    ident	"%Z%%M%	%I%	%E% SMI"
--->
-
-<topology name='sun4v' scheme='hc'>
-  <range name='motherboard' min='0' max='0'>
-    <node instance='0'>
-      <propgroup name='protocol'>
-        <propval name='FRU' type='fmri'
-          value='hc:///motherboard=0' />
-        <propval name='label' type='string'
-          value='MB' />
-      </propgroup>
-    </node>
-    <dependents grouping='children'>
-     <range name='hostbridge' min='0' max='254'>
-       <enum-method name='hostbridge' version='1'
-         path='%r/usr/platform/sun4v/lib/fm/topo/plugins' />
-     </range>
-    </dependents>
-  </range>
-</topology>
--- a/usr/src/lib/fm/topo/libtopo/Makefile	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/Makefile	Sat Nov 04 01:18:55 2006 -0800
@@ -28,7 +28,7 @@
 include ../../../Makefile.lib
 include ../../Makefile.lib
 
-FMHDRS = libtopo.h topo_mod.h
+FMHDRS = libtopo.h topo_mod.h topo_hc.h
 HDRDIR = common
 
 SUBDIRS = $(MACH)
--- a/usr/src/lib/fm/topo/libtopo/Makefile.com	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/Makefile.com	Sat Nov 04 01:18:55 2006 -0800
@@ -37,6 +37,7 @@
 	pkg.c
 
 LIBSRCS = \
+	topo_2xml.c \
 	topo_alloc.c \
 	topo_builtin.c \
 	topo_error.c \
@@ -78,7 +79,8 @@
 LINTFLAGS = -msux
 LINTFLAGS64 = -msux -Xarch=$(MACH64:sparcv9=v9)
 
-$(DYNLIB)  := LDLIBS += -lnvpair -lelf -lumem -lxml2 -lkstat -luuid -lc
+$(DYNLIB)  := LDLIBS += \
+	-lnvpair -lelf -lumem -lxml2 -lkstat -luuid -ldevinfo -lsmbios -lc
 
 $(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC)
 $(LINTLIB) := LINTFLAGS = -nsvx
@@ -100,8 +102,9 @@
 	$(POST_PROCESS_O)
 
 ../common/topo_error.c: ../common/mkerror.sh ../common/topo_error.h
-	sh ../common/mkerror.sh internal < ../common/topo_error.h > $@
-	sh ../common/mkerror.sh external < ../common/topo_mod.h >> $@
+	sh ../common/mkerror.sh liberrors < ../common/topo_error.h > $@
+	sh ../common/mkerror.sh properrors < ../common/libtopo.h >> $@
+	sh ../common/mkerror.sh moderrors < ../common/topo_mod.h >> $@
 
 include ../../../../Makefile.targ
 include ../../../Makefile.targ
--- a/usr/src/lib/fm/topo/libtopo/common/cpu.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/cpu.c	Sat Nov 04 01:18:55 2006 -0800
@@ -27,80 +27,65 @@
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 #include <errno.h>
-#include <kstat.h>
 #include <limits.h>
 #include <strings.h>
 #include <unistd.h>
 #include <fm/topo_mod.h>
 #include <sys/fm/protocol.h>
 
-#include <topo_error.h>
-
-typedef struct cpu_node {
-	kstat_ctl_t *cn_kc;
-	kstat_t **cn_cpustats;
-	uint_t cn_ncpustats;
-} cpu_node_t;
+#include <topo_method.h>
+#include <cpu.h>
 
 static int cpu_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t,
-    topo_instance_t, void *);
+    topo_instance_t, void *, void *);
 static void cpu_release(topo_mod_t *, tnode_t *);
 static int cpu_nvl2str(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
     nvlist_t **);
 static int cpu_str2nvl(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
     nvlist_t **);
-static int cpu_present(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
-    nvlist_t **);
-static int cpu_unusable(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
-    nvlist_t **);
-static int cpu_contains(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
-    nvlist_t **);
-static int cpu_expand(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
-    nvlist_t **);
 static int cpu_fmri_asru(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
     nvlist_t **);
 static nvlist_t *fmri_create(topo_mod_t *, uint32_t, uint8_t, char *);
 
-#define	CPU_VERSION	TOPO_VERSION
-
 static const topo_method_t cpu_methods[] = {
 	{ TOPO_METH_NVL2STR, TOPO_METH_NVL2STR_DESC, TOPO_METH_NVL2STR_VERSION,
 	    TOPO_STABILITY_INTERNAL, cpu_nvl2str },
 	{ TOPO_METH_STR2NVL, TOPO_METH_STR2NVL_DESC, TOPO_METH_STR2NVL_VERSION,
 	    TOPO_STABILITY_INTERNAL, cpu_str2nvl },
-	{ TOPO_METH_PRESENT, TOPO_METH_PRESENT_DESC, TOPO_METH_PRESENT_VERSION,
-	    TOPO_STABILITY_INTERNAL, cpu_present },
-	{ TOPO_METH_CONTAINS, TOPO_METH_CONTAINS_DESC,
-	    TOPO_METH_CONTAINS_VERSION, TOPO_STABILITY_INTERNAL, cpu_contains },
-	{ TOPO_METH_UNUSABLE, TOPO_METH_UNUSABLE_DESC,
-	    TOPO_METH_UNUSABLE_VERSION, TOPO_STABILITY_INTERNAL, cpu_unusable },
-	{ TOPO_METH_EXPAND, TOPO_METH_EXPAND_DESC,
-	    TOPO_METH_EXPAND_VERSION, TOPO_STABILITY_INTERNAL, cpu_expand },
 	{ TOPO_METH_ASRU_COMPUTE, TOPO_METH_ASRU_COMPUTE_DESC,
 	    TOPO_METH_ASRU_COMPUTE_VERSION, TOPO_STABILITY_INTERNAL,
 	    cpu_fmri_asru },
+	{ TOPO_METH_FMRI, TOPO_METH_FMRI_DESC, TOPO_METH_FMRI_VERSION,
+	    TOPO_STABILITY_INTERNAL, cpu_fmri_asru },
 	{ NULL }
 };
 
-static const topo_modinfo_t cpu_info =
-	{ "cpu", CPU_VERSION, cpu_enum, cpu_release };
+static const topo_modops_t cpu_ops =
+	{ cpu_enum, cpu_release };
 
-void
-cpu_init(topo_mod_t *mod)
+static const topo_modinfo_t cpu_info =
+	{ "cpu", FM_FMRI_SCHEME_CPU, CPU_VERSION, &cpu_ops };
+
+int
+cpu_init(topo_mod_t *mod, topo_version_t version)
 {
 	cpu_node_t *cpuip;
 
-	topo_mod_setdebug(mod, TOPO_DBG_ALL);
+	if (getenv("TOPOCPUDEBUG"))
+		topo_mod_setdebug(mod);
 	topo_mod_dprintf(mod, "initializing cpu builtin\n");
 
+	if (version != CPU_VERSION)
+		return (topo_mod_seterrno(mod, EMOD_VER_NEW));
+
 	if ((cpuip = topo_mod_zalloc(mod, sizeof (cpu_node_t))) == NULL)
-		return;
+		return (topo_mod_seterrno(mod, EMOD_NOMEM));
 
 	if ((cpuip->cn_kc = kstat_open()) == NULL) {
 		topo_mod_dprintf(mod, "kstat_open failed: %s\n",
 		    strerror(errno));
 		topo_mod_free(mod, cpuip, sizeof (cpu_node_t));
-		return;
+		return (-1);
 	}
 
 	cpuip->cn_ncpustats = sysconf(_SC_CPUID_MAX);
@@ -108,18 +93,22 @@
 	    cpuip->cn_ncpustats + 1) * sizeof (kstat_t *))) == NULL) {
 		(void) kstat_close(cpuip->cn_kc);
 		topo_mod_free(mod, cpuip, sizeof (cpu_node_t));
-		return;
+		return (-1);
 	}
 
-	if (topo_mod_register(mod, &cpu_info, (void *)cpuip) != 0) {
+	if (topo_mod_register(mod, &cpu_info, TOPO_VERSION) != 0) {
 		topo_mod_dprintf(mod, "failed to register cpu_info: "
 		    "%s\n", topo_mod_errmsg(mod));
 		topo_mod_free(mod, cpuip->cn_cpustats,
 		    (cpuip->cn_ncpustats + 1) * sizeof (kstat_t *));
 		(void) kstat_close(cpuip->cn_kc);
 		topo_mod_free(mod, cpuip, sizeof (cpu_node_t));
-		return;
+		return (-1);
 	}
+
+	topo_mod_setspecific(mod, (void *)cpuip);
+
+	return (0);
 }
 
 void
@@ -127,7 +116,7 @@
 {
 	cpu_node_t *cpuip;
 
-	cpuip = topo_mod_private(mod);
+	cpuip = topo_mod_getspecific(mod);
 
 	if (cpuip->cn_cpustats != NULL)
 		topo_mod_free(mod, cpuip->cn_cpustats,
@@ -183,7 +172,7 @@
 
 		if ((fmri = fmri_create(mod, cpu_id, 0, s)) == NULL)
 			continue;
-		(void) topo_node_bind(mod, rnode, name, cpu_id, fmri, NULL);
+		(void) topo_node_bind(mod, rnode, name, cpu_id, fmri);
 		nvlist_free(fmri);
 	}
 
@@ -194,7 +183,7 @@
 /*ARGSUSED*/
 static int
 cpu_enum(topo_mod_t *mod, tnode_t *pnode, const char *name,
-    topo_instance_t min, topo_instance_t max, void *arg)
+    topo_instance_t min, topo_instance_t max, void *arg, void *notused2)
 {
 	cpu_node_t *cpuip = (cpu_node_t *)arg;
 
@@ -349,38 +338,6 @@
 	return (0);
 }
 
-/*ARGSUSED*/
-static int
-cpu_present(topo_mod_t *mod, tnode_t *node, topo_version_t version,
-    nvlist_t *in, nvlist_t **out)
-{
-	return (topo_mod_seterrno(mod, EMOD_METHOD_NOTSUP));
-}
-
-/*ARGSUSED*/
-static int
-cpu_contains(topo_mod_t *mod, tnode_t *node, topo_version_t version,
-    nvlist_t *in, nvlist_t **out)
-{
-	return (topo_mod_seterrno(mod, EMOD_METHOD_NOTSUP));
-}
-
-/*ARGSUSED*/
-static int
-cpu_unusable(topo_mod_t *mod, tnode_t *node, topo_version_t version,
-    nvlist_t *in, nvlist_t **out)
-{
-	return (topo_mod_seterrno(mod, EMOD_METHOD_NOTSUP));
-}
-
-/*ARGSUSED*/
-static int
-cpu_expand(topo_mod_t *mod, tnode_t *node, topo_version_t version,
-    nvlist_t *in, nvlist_t **out)
-{
-	return (topo_mod_seterrno(mod, EMOD_METHOD_NOTSUP));
-}
-
 static nvlist_t *
 fmri_create(topo_mod_t *mod, uint32_t cpu_id, uint8_t cpumask, char *s)
 {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/libtopo/common/cpu.h	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,53 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef	_CPU_H
+#define	_CPU_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#include <kstat.h>
+
+#define	CPU_VERSION	1
+
+typedef struct cpu_node {
+	kstat_ctl_t *cn_kc;
+	kstat_t **cn_cpustats;
+	uint_t cn_ncpustats;
+} cpu_node_t;
+
+extern int cpu_init(topo_mod_t *, topo_version_t);	/* see cpu.c */
+extern void cpu_fini(topo_mod_t *);			/* see cpu.c */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _CPU_H */
--- a/usr/src/lib/fm/topo/libtopo/common/dev.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/dev.c	Sat Nov 04 01:18:55 2006 -0800
@@ -36,11 +36,12 @@
 #include <fm/topo_mod.h>
 #include <sys/fm/protocol.h>
 
+#include <topo_method.h>
 #include <topo_subr.h>
-#include <topo_error.h>
+#include <dev.h>
 
 static int dev_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t,
-    topo_instance_t, void *);
+    topo_instance_t, void *, void *);
 static void dev_release(topo_mod_t *, tnode_t *);
 static int dev_fmri_nvl2str(topo_mod_t *, tnode_t *, topo_version_t,
     nvlist_t *, nvlist_t **);
@@ -49,8 +50,6 @@
 static int dev_fmri_create_meth(topo_mod_t *, tnode_t *, topo_version_t,
     nvlist_t *, nvlist_t **);
 
-#define	DEV_VERSION	TOPO_VERSION
-
 static const topo_method_t dev_methods[] = {
 	{ TOPO_METH_NVL2STR, TOPO_METH_NVL2STR_DESC, TOPO_METH_NVL2STR_VERSION,
 	    TOPO_STABILITY_INTERNAL, dev_fmri_nvl2str },
@@ -61,20 +60,28 @@
 	{ NULL }
 };
 
+static const topo_modops_t dev_ops =
+	{ dev_enum, dev_release };
 static const topo_modinfo_t dev_info =
-	{ "dev", DEV_VERSION, dev_enum, dev_release };
+	{ "dev", FM_FMRI_SCHEME_DEV, DEV_VERSION, &dev_ops };
 
-void
-dev_init(topo_mod_t *mod)
+int
+dev_init(topo_mod_t *mod, topo_version_t version)
 {
-	topo_mod_setdebug(mod, TOPO_DBG_ALL);
+	if (getenv("TOPOHCDEBUG"))
+		topo_mod_setdebug(mod);
 	topo_mod_dprintf(mod, "initializing dev builtin\n");
 
-	if (topo_mod_register(mod, &dev_info, NULL) != 0) {
+	if (version != DEV_VERSION)
+		return (topo_mod_seterrno(mod, EMOD_VER_NEW));
+
+	if (topo_mod_register(mod, &dev_info, TOPO_VERSION) != 0) {
 		topo_mod_dprintf(mod, "failed to register dev_info: "
 		    "%s\n", topo_mod_errmsg(mod));
-		return;
+		return (-1);
 	}
+
+	return (0);
 }
 
 void
@@ -86,7 +93,7 @@
 /*ARGSUSED*/
 static int
 dev_enum(topo_mod_t *mod, tnode_t *pnode, const char *name,
-    topo_instance_t min, topo_instance_t max, void *arg)
+    topo_instance_t min, topo_instance_t max, void *notused1, void *notused2)
 {
 	(void) topo_method_register(mod, pnode, dev_methods);
 	return (0);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/libtopo/common/dev.h	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,45 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef	_DEV_H
+#define	_DEV_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#define	DEV_VERSION	1
+
+extern int dev_init(topo_mod_t *, topo_version_t);	/* see dev.c */
+extern void dev_fini(topo_mod_t *);			/* see dev.c */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _DEV_H */
--- a/usr/src/lib/fm/topo/libtopo/common/hc.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/hc.c	Sat Nov 04 01:18:55 2006 -0800
@@ -35,26 +35,21 @@
 #include <alloca.h>
 #include <limits.h>
 #include <fm/topo_mod.h>
+#include <fm/topo_hc.h>
 #include <sys/param.h>
 #include <sys/systeminfo.h>
 #include <sys/fm/protocol.h>
-#include <topo_parse.h>
-#include <topo_subr.h>
+#include <sys/stat.h>
+#include <sys/systeminfo.h>
+#include <sys/utsname.h>
 
-#include <hc_canon.h>
-
-#define	HC			"hc"
-#define	HC_VERSION		TOPO_VERSION
+#include <topo_method.h>
+#include <topo_subr.h>
+#include <hc.h>
 
 static int hc_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t,
-    topo_instance_t, void *);
+    topo_instance_t, void *, void *);
 static void hc_release(topo_mod_t *, tnode_t *);
-static int hc_contains(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
-    nvlist_t **);
-static int hc_present(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
-    nvlist_t **);
-static int hc_unusable(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
-    nvlist_t **);
 static int hc_fmri_nvl2str(topo_mod_t *, tnode_t *, topo_version_t,
     nvlist_t *, nvlist_t **);
 static int hc_fmri_str2nvl(topo_mod_t *, tnode_t *, topo_version_t,
@@ -69,12 +64,6 @@
     const char *);
 
 const topo_method_t hc_methods[] = {
-	{ "hc_contains", "Hardware Component Contains", HC_VERSION,
-	    TOPO_STABILITY_INTERNAL, hc_contains },
-	{ "hc_present", "Hardware Component Present", HC_VERSION,
-	    TOPO_STABILITY_INTERNAL, hc_present },
-	{ "hc_unusable", "Hardware Component Unusable", HC_VERSION,
-	    TOPO_STABILITY_INTERNAL, hc_unusable },
 	{ TOPO_METH_NVL2STR, TOPO_METH_NVL2STR_DESC, TOPO_METH_NVL2STR_VERSION,
 	    TOPO_STABILITY_INTERNAL, hc_fmri_nvl2str },
 	{ TOPO_METH_STR2NVL, TOPO_METH_STR2NVL_DESC, TOPO_METH_STR2NVL_VERSION,
@@ -86,67 +75,187 @@
 	{ NULL }
 };
 
-const topo_modinfo_t hc_info =
-	{ HC, HC_VERSION, hc_enum, hc_release };
+static const topo_modops_t hc_ops =
+	{ hc_enum, hc_release };
+static const topo_modinfo_t hc_info =
+	{ HC, FM_FMRI_SCHEME_HC, HC_VERSION, &hc_ops };
 
-void
-hc_init(topo_mod_t *mp)
+static const hcc_t hc_canon[] = {
+	{ CMP, TOPO_STABILITY_PRIVATE },
+	{ CENTERPLANE, TOPO_STABILITY_PRIVATE },
+	{ CHASSIS, TOPO_STABILITY_PRIVATE },
+	{ CHIP, TOPO_STABILITY_PRIVATE },
+	{ CHIP_SELECT, TOPO_STABILITY_PRIVATE },
+	{ CPU, TOPO_STABILITY_PRIVATE },
+	{ DIMM, TOPO_STABILITY_PRIVATE },
+	{ DISK, TOPO_STABILITY_PRIVATE },
+	{ DRAMCHANNEL, TOPO_STABILITY_PRIVATE },
+	{ HOSTBRIDGE, TOPO_STABILITY_PRIVATE },
+	{ INTERCONNECT, TOPO_STABILITY_PRIVATE },
+	{ IOBOARD, TOPO_STABILITY_PRIVATE },
+	{ MEMORYCONTROL, TOPO_STABILITY_PRIVATE },
+	{ MOTHERBOARD, TOPO_STABILITY_PRIVATE },
+	{ PCI_BUS, TOPO_STABILITY_PRIVATE },
+	{ PCI_DEVICE, TOPO_STABILITY_PRIVATE },
+	{ PCI_FUNCTION, TOPO_STABILITY_PRIVATE },
+	{ PCIEX_BUS, TOPO_STABILITY_PRIVATE },
+	{ PCIEX_DEVICE, TOPO_STABILITY_PRIVATE },
+	{ PCIEX_FUNCTION, TOPO_STABILITY_PRIVATE },
+	{ PCIEX_ROOT, TOPO_STABILITY_PRIVATE },
+	{ PCIEX_SWUP, TOPO_STABILITY_PRIVATE },
+	{ PCIEX_SWDWN, TOPO_STABILITY_PRIVATE },
+	{ RANK, TOPO_STABILITY_PRIVATE },
+	{ SATA_PORT, TOPO_STABILITY_PRIVATE },
+	{ SYSTEMBOARD, TOPO_STABILITY_PRIVATE }
+};
+
+static int hc_ncanon = sizeof (hc_canon) / sizeof (hcc_t);
+
+int
+hc_init(topo_mod_t *mod, topo_version_t version)
 {
 	/*
 	 * Turn on module debugging output
 	 */
-	topo_mod_setdebug(mp, TOPO_DBG_ALL);
-	topo_mod_dprintf(mp, "initializing hc builtin\n");
+	if (getenv("TOPOHCDEBUG"))
+		topo_mod_setdebug(mod);
+
+	topo_mod_dprintf(mod, "initializing hc builtin\n");
+
+	if (version != HC_VERSION)
+		return (topo_mod_seterrno(mod, EMOD_VER_NEW));
 
-	if (topo_mod_register(mp, &hc_info, NULL) != 0) {
-		topo_mod_dprintf(mp, "failed to register hc: "
-		    "%s\n", topo_mod_errmsg(mp));
+	if (topo_mod_register(mod, &hc_info, TOPO_VERSION) != 0) {
+		topo_mod_dprintf(mod, "failed to register hc: "
+		    "%s\n", topo_mod_errmsg(mod));
+		return (-1); /* mod errno already set */
 	}
+
+	return (0);
 }
 
 void
-hc_fini(topo_mod_t *mp)
+hc_fini(topo_mod_t *mod)
+{
+	topo_mod_unregister(mod);
+}
+
+
+static const topo_pgroup_info_t sys_pgroup = {
+	TOPO_PGROUP_SYSTEM,
+	TOPO_STABILITY_PRIVATE,
+	TOPO_STABILITY_PRIVATE,
+	1
+};
+
+static const topo_pgroup_info_t auth_pgroup = {
+	FM_FMRI_AUTHORITY,
+	TOPO_STABILITY_PRIVATE,
+	TOPO_STABILITY_PRIVATE,
+	1
+};
+
+static void
+hc_prop_set(tnode_t *node, nvlist_t *auth)
 {
-	topo_mod_unregister(mp);
+	int err;
+	char isa[MAXNAMELEN];
+	struct utsname uts;
+	char *prod, *csn, *server;
+
+	if (topo_pgroup_create(node, &auth_pgroup, &err) != 0) {
+		if (err != ETOPO_PROP_DEFD)
+			return;
+	}
+
+	/*
+	 * Inherit if we can, it saves memory
+	 */
+	if (topo_prop_inherit(node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_PRODUCT,
+	    &err) != 0) {
+		if (nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT, &prod)
+		    == 0)
+			(void) topo_prop_set_string(node, FM_FMRI_AUTHORITY,
+			    FM_FMRI_AUTH_PRODUCT, TOPO_PROP_IMMUTABLE, prod,
+			    &err);
+	}
+	if (topo_prop_inherit(node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_CHASSIS,
+	    &err) != 0) {
+		if (nvlist_lookup_string(auth, FM_FMRI_AUTH_CHASSIS, &csn) == 0)
+			(void) topo_prop_set_string(node, FM_FMRI_AUTHORITY,
+			    FM_FMRI_AUTH_CHASSIS, TOPO_PROP_IMMUTABLE, csn,
+			    &err);
+	}
+	if (topo_prop_inherit(node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_SERVER,
+	    &err) != 0) {
+		if (nvlist_lookup_string(auth, FM_FMRI_AUTH_SERVER, &server)
+		    == 0)
+			(void) topo_prop_set_string(node, FM_FMRI_AUTHORITY,
+			    FM_FMRI_AUTH_SERVER, TOPO_PROP_IMMUTABLE, server,
+			    &err);
+	}
+
+	if (topo_pgroup_create(node, &sys_pgroup, &err) != 0)
+		return;
+
+	isa[0] = '\0';
+	(void) sysinfo(SI_ARCHITECTURE, isa, sizeof (isa));
+	(void) uname(&uts);
+	(void) topo_prop_set_string(node, TOPO_PGROUP_SYSTEM, TOPO_PROP_ISA,
+	    TOPO_PROP_IMMUTABLE, isa, &err);
+	(void) topo_prop_set_string(node, TOPO_PGROUP_SYSTEM, TOPO_PROP_MACHINE,
+	    TOPO_PROP_IMMUTABLE, uts.machine, &err);
 }
 
 /*ARGSUSED*/
 int
-hc_enum(topo_mod_t *mp, tnode_t *pnode, const char *name, topo_instance_t min,
-    topo_instance_t max, void *notused)
+hc_enum(topo_mod_t *mod, tnode_t *pnode, const char *name, topo_instance_t min,
+    topo_instance_t max, void *notused1, void *arg)
 {
 	nvlist_t *pfmri = NULL;
 	nvlist_t *nvl;
+	nvlist_t *auth;
+	tnode_t *node;
 	int err;
 	/*
 	 * Register root node methods
 	 */
 	if (strcmp(name, HC) == 0) {
-		(void) topo_method_register(mp, pnode, hc_methods);
+		(void) topo_method_register(mod, pnode, hc_methods);
 		return (0);
 	}
 	if (min != max) {
-		topo_mod_dprintf(mp,
+		topo_mod_dprintf(mod,
 		    "Request to enumerate %s component with an "
 		    "ambiguous instance number, min (%d) != max (%d).\n",
 		    HC, min, max);
-		return (topo_mod_seterrno(mp, EINVAL));
+		return (topo_mod_seterrno(mod, EINVAL));
 	}
 
 	(void) topo_node_resource(pnode, &pfmri, &err);
-	nvl = hc_fmri_create(mp, pfmri, FM_HC_SCHEME_VERSION, name, min,
-	    NULL, NULL, NULL, NULL);
+	if (arg == NULL)
+		auth = topo_mod_auth(mod, pnode);
+	nvl = hc_fmri_create(mod, pfmri, FM_HC_SCHEME_VERSION, name, min,
+	    auth, NULL, NULL, NULL);
 	nvlist_free(pfmri);	/* callee ignores NULLs */
-	if (nvl == NULL)
+	if (nvl == NULL) {
+		nvlist_free(auth);
 		return (-1);
+	}
 
-	if (topo_node_bind(mp, pnode, name, min, nvl, NULL) == NULL) {
-		topo_mod_dprintf(mp, "topo_node_bind failed: %s\n",
-		    topo_strerror(topo_mod_errno(mp)));
+	if ((node = topo_node_bind(mod, pnode, name, min, nvl)) == NULL) {
+		topo_mod_dprintf(mod, "topo_node_bind failed: %s\n",
+		    topo_strerror(topo_mod_errno(mod)));
+		nvlist_free(auth);
 		nvlist_free(nvl);
 		return (-1);
 	}
+
+	if (arg == NULL)
+		hc_prop_set(node, auth);
 	nvlist_free(nvl);
+	nvlist_free(auth);
+
 	return (0);
 }
 
@@ -159,31 +268,7 @@
 
 /*ARGSUSED*/
 static int
-hc_contains(topo_mod_t *mp, tnode_t *node, topo_version_t version,
-    nvlist_t *in, nvlist_t **out)
-{
-	return (topo_mod_seterrno(mp, EMOD_METHOD_NOTSUP));
-}
-
-/*ARGSUSED*/
-static int
-hc_present(topo_mod_t *mp, tnode_t *node, topo_version_t version,
-    nvlist_t *in, nvlist_t **out)
-{
-	return (topo_mod_seterrno(mp, EMOD_METHOD_NOTSUP));
-}
-
-/*ARGSUSED*/
-static int
-hc_unusable(topo_mod_t *mp, tnode_t *node, topo_version_t version,
-    nvlist_t *in, nvlist_t **out)
-{
-	return (topo_mod_seterrno(mp, EMOD_METHOD_NOTSUP));
-}
-
-/*ARGSUSED*/
-static int
-hc_compare(topo_mod_t *mp, tnode_t *node, topo_version_t version,
+hc_compare(topo_mod_t *mod, tnode_t *node, topo_version_t version,
     nvlist_t *in, nvlist_t **out)
 {
 	uint8_t v1, v2;
@@ -193,21 +278,21 @@
 	uint_t nhcp1, nhcp2;
 
 	if (version > TOPO_METH_COMPARE_VERSION)
-		return (topo_mod_seterrno(mp, EMOD_VER_NEW));
+		return (topo_mod_seterrno(mod, EMOD_VER_NEW));
 
 	if (nvlist_lookup_nvlist(in, "nv1", &nv1) != 0 ||
 	    nvlist_lookup_nvlist(in, "nv2", &nv2) != 0)
-		return (topo_mod_seterrno(mp, EMOD_METHOD_INVAL));
+		return (topo_mod_seterrno(mod, EMOD_METHOD_INVAL));
 
 	if (nvlist_lookup_uint8(nv1, FM_VERSION, &v1) != 0 ||
 	    nvlist_lookup_uint8(nv2, FM_VERSION, &v2) != 0 ||
 	    v1 > FM_HC_SCHEME_VERSION || v2 > FM_HC_SCHEME_VERSION)
-		return (topo_mod_seterrno(mp, EMOD_FMRI_VERSION));
+		return (topo_mod_seterrno(mod, EMOD_FMRI_VERSION));
 
 	err = nvlist_lookup_nvlist_array(nv1, FM_FMRI_HC_LIST, &hcp1, &nhcp1);
 	err |= nvlist_lookup_nvlist_array(nv2, FM_FMRI_HC_LIST, &hcp2, &nhcp2);
 	if (err != 0)
-		return (topo_mod_seterrno(mp, EMOD_FMRI_NVL));
+		return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
 
 	if (nhcp1 != nhcp2)
 		return (0);
@@ -223,7 +308,7 @@
 		(void) nvlist_lookup_string(hcp1[i], FM_FMRI_HC_ID, &id1);
 		(void) nvlist_lookup_string(hcp2[i], FM_FMRI_HC_ID, &id2);
 		if (nm1 == NULL || nm2 == NULL || id1 == NULL || id2 == NULL)
-			return (topo_mod_seterrno(mp, EMOD_FMRI_NVL));
+			return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
 
 		if (strcmp(nm1, nm2) == 0 && strcmp(id1, id2) == 0)
 			continue;
@@ -303,28 +388,19 @@
 	/* authority, if any */
 	if (aprod != NULL)
 		topo_fmristr_build(&size,
-		    buf, buflen, aprod, FM_FMRI_AUTH_PRODUCT "=",
-		    --more_auth > 0 ? "," : NULL);
+		    buf, buflen, aprod, ":" FM_FMRI_AUTH_PRODUCT "=", NULL);
 	if (achas != NULL)
 		topo_fmristr_build(&size,
-		    buf, buflen, achas, FM_FMRI_AUTH_CHASSIS "=",
-		    --more_auth > 0 ? "," : NULL);
+		    buf, buflen, achas, ":" FM_FMRI_AUTH_CHASSIS "=", NULL);
 	if (adom != NULL)
 		topo_fmristr_build(&size,
-		    buf, buflen, adom, FM_FMRI_AUTH_DOMAIN "=",
-		    --more_auth > 0 ? "," : NULL);
+		    buf, buflen, adom, ":" FM_FMRI_AUTH_DOMAIN "=", NULL);
 	if (asrvr != NULL)
 		topo_fmristr_build(&size,
-		    buf, buflen, asrvr, FM_FMRI_AUTH_SERVER "=",
-		    --more_auth > 0 ? "," : NULL);
+		    buf, buflen, asrvr, ":" FM_FMRI_AUTH_SERVER "=", NULL);
 	if (ahost != NULL)
 		topo_fmristr_build(&size,
-		    buf, buflen, ahost, FM_FMRI_AUTH_HOST "=",
-		    NULL);
-
-	/* separating slash */
-	if (serial != NULL || part != NULL || rev != NULL)
-		topo_fmristr_build(&size, buf, buflen, "/", NULL, NULL);
+		    buf, buflen, ahost, ":" FM_FMRI_AUTH_HOST "=", NULL);
 
 	/* hardware-id part */
 	topo_fmristr_build(&size,
@@ -430,9 +506,10 @@
 }
 
 static nvlist_t **
-make_hc_pairs(topo_mod_t *mod, char *fromstr, int *num)
+make_hc_pairs(topo_mod_t *mod, char *fmri, int *num)
 {
 	nvlist_t **pa;
+	char *hc, *fromstr;
 	char *starti, *startn, *endi, *endi2;
 	char *ne, *ns;
 	char *cname;
@@ -442,12 +519,18 @@
 	int npairs = 0;
 	int i, e;
 
+	if ((hc = topo_mod_strdup(mod, fmri + 5)) == NULL)
+		return (NULL);
+
 	/*
 	 * Count equal signs and slashes to determine how many
 	 * hc-pairs will be present in the final FMRI.  There should
 	 * be at least as many slashes as equal signs.  There can be
 	 * more, though if the string after an = includes them.
 	 */
+	if ((fromstr = strchr(hc, '/')) == NULL)
+		return (NULL);
+
 	find = fromstr;
 	while ((ne = strchr(find, '=')) != NULL) {
 		find = ne + 1;
@@ -463,8 +546,10 @@
 	/*
 	 * Do we appear to have a well-formed string version of the FMRI?
 	 */
-	if (nslashes < npairs || npairs == 0)
+	if (nslashes < npairs || npairs == 0) {
+		topo_mod_strfree(mod, hc);
 		return (NULL);
+	}
 
 	*num = npairs;
 
@@ -528,12 +613,101 @@
 			if (pa[i--] != NULL)
 				nvlist_free(pa[i + 1]);
 		topo_mod_free(mod, pa, npairs * sizeof (nvlist_t *));
+		topo_mod_strfree(mod, hc);
 		return (NULL);
 	}
 
+	topo_mod_strfree(mod, hc);
+
 	return (pa);
 }
 
+void
+make_hc_auth(topo_mod_t *mod, char *fmri, char **serial, char **part,
+char **rev, nvlist_t **auth)
+{
+	char *starti, *startn, *endi, *copy;
+	char *aname, *aid, *fs;
+	nvlist_t *na = NULL;
+	size_t len;
+
+	if ((copy = topo_mod_strdup(mod, fmri + 5)) == NULL)
+		return;
+
+	len = strlen(copy);
+
+	/*
+	 * Make sure there are a valid authority members
+	 */
+	startn = strchr(copy, ':');
+	fs = strchr(copy, '/');
+
+	if (startn == NULL || fs == NULL) {
+		topo_mod_strfree(mod, copy);
+		return;
+	}
+
+	/*
+	 * The first colon we encounter must occur before the
+	 * first slash
+	 */
+	if (startn > fs)
+		return;
+
+	do {
+		if (++startn >= copy + len)
+			break;
+
+		if ((starti = strchr(startn, '=')) == NULL)
+			break;
+
+		*starti = '\0';
+		if (++starti > copy + len)
+			break;
+
+		if ((aname = topo_mod_strdup(mod, startn)) == NULL)
+			break;
+
+		startn = endi = strchr(starti, ':');
+		if (endi == NULL)
+			if ((endi = strchr(starti, '/')) == NULL)
+				break;
+
+		*endi = '\0';
+		if ((aid = topo_mod_strdup(mod, starti)) == NULL) {
+			topo_mod_strfree(mod, aname);
+			break;
+		}
+
+		/*
+		 * Return possible serial, part and revision
+		 */
+		if (strcmp(aname, FM_FMRI_HC_SERIAL_ID) == 0) {
+			*serial = aid;
+		} else if (strcmp(aname, FM_FMRI_HC_PART) == 0) {
+			*part = aid;
+		} else if (strcmp(aname, FM_FMRI_HC_REVISION) == 0) {
+			*rev = aid;
+		} else {
+			if (na == NULL) {
+				if (topo_mod_nvalloc(mod, &na,
+				    NV_UNIQUE_NAME) == 0) {
+					nvlist_add_string(na, aname, aid);
+				}
+			} else {
+				(void) nvlist_add_string(na, aname, aid);
+			}
+		}
+		topo_mod_strfree(mod, aname);
+		topo_mod_strfree(mod, aid);
+
+	} while (startn != NULL);
+
+	*auth = na;
+
+	topo_mod_free(mod, copy, len + 1);
+}
+
 /*ARGSUSED*/
 static int
 hc_fmri_str2nvl(topo_mod_t *mod, tnode_t *node, topo_version_t version,
@@ -541,7 +715,9 @@
 {
 	nvlist_t **pa = NULL;
 	nvlist_t *nf = NULL;
-	char *str, *copy;
+	nvlist_t *auth = NULL;
+	char *str;
+	char *serial = NULL, *part = NULL, *rev = NULL;
 	int npairs;
 	int i, e;
 
@@ -552,17 +728,14 @@
 		return (topo_mod_seterrno(mod, EMOD_METHOD_INVAL));
 
 	/* We're expecting a string version of an hc scheme FMRI */
-	if (strncmp(str, "hc:///", 6) != 0)
+	if (strncmp(str, "hc://", 5) != 0)
 		return (topo_mod_seterrno(mod, EMOD_FMRI_MALFORM));
 
-	copy = topo_mod_strdup(mod, str + 5);
-	if ((pa = make_hc_pairs(mod, copy, &npairs)) == NULL) {
-		topo_mod_strfree(mod, copy);
+	if ((pa = make_hc_pairs(mod, str, &npairs)) == NULL)
 		return (topo_mod_seterrno(mod, EMOD_FMRI_MALFORM));
-	}
-	topo_mod_strfree(mod, copy);
 
-	if ((nf = hc_base_fmri_create(mod, NULL, NULL, NULL, NULL)) == NULL)
+	make_hc_auth(mod, str, &serial, &part, &rev, &auth);
+	if ((nf = hc_base_fmri_create(mod, auth, part, rev, serial)) == NULL)
 		goto hcfmbail;
 	if ((e = nvlist_add_uint32(nf, FM_FMRI_HC_LIST_SZ, npairs)) == 0)
 		e = nvlist_add_nvlist_array(nf, FM_FMRI_HC_LIST, pa, npairs);
@@ -573,6 +746,14 @@
 	for (i = 0; i < npairs; i++)
 		nvlist_free(pa[i]);
 	topo_mod_free(mod, pa, npairs * sizeof (nvlist_t *));
+	if (serial != NULL)
+		topo_mod_strfree(mod, serial);
+	if (part != NULL)
+		topo_mod_strfree(mod, part);
+	if (rev != NULL)
+		topo_mod_strfree(mod, rev);
+	nvlist_free(auth);
+
 	*out = nf;
 
 	return (0);
@@ -583,6 +764,13 @@
 	for (i = 0; i < npairs; i++)
 		nvlist_free(pa[i]);
 	topo_mod_free(mod, pa, npairs * sizeof (nvlist_t *));
+	if (serial != NULL)
+		topo_mod_strfree(mod, serial);
+	if (part != NULL)
+		topo_mod_strfree(mod, part);
+	if (rev != NULL)
+		topo_mod_strfree(mod, rev);
+	nvlist_free(auth);
 	return (topo_mod_seterrno(mod, EMOD_FMRI_MALFORM));
 }
 
@@ -629,20 +817,27 @@
 }
 
 static int
-hc_name_canonical(const char *name)
+hc_name_canonical(topo_mod_t *mod, const char *name)
 {
 	int i;
+
+	if (getenv("NOHCCHECK") != NULL)
+		return (1);
+
 	/*
 	 * Only enumerate elements with correct canonical names
 	 */
-	for (i = 0; i < Hc_ncanon; i++) {
-		if (strcmp(name, Hc_canon[i]) == 0)
+	for (i = 0; i < hc_ncanon; i++) {
+		if (strcmp(name, hc_canon[i].hcc_name) == 0)
 			break;
 	}
-	if (i >= Hc_ncanon)
+	if (i >= hc_ncanon) {
+		topo_mod_dprintf(mod, "non-canonical name %s\n",
+		    name);
 		return (0);
-	else
+	} else {
 		return (1);
+	}
 }
 
 static nvlist_t *
@@ -667,7 +862,7 @@
 	/*
 	 * Check that the requested name is in our canonical list
 	 */
-	if (hc_name_canonical(name) == 0)
+	if (hc_name_canonical(mod, name) == 0)
 		return (hc_create_seterror(mod,
 		    hcl, pelems, fmri, EMOD_NONCANON));
 	/*
@@ -717,7 +912,7 @@
 
 /*ARGSUSED*/
 static int
-hc_fmri_create_meth(topo_mod_t *mp, tnode_t *node, topo_version_t version,
+hc_fmri_create_meth(topo_mod_t *mod, tnode_t *node, topo_version_t version,
     nvlist_t *in, nvlist_t **out)
 {
 	int ret;
@@ -727,13 +922,13 @@
 	char *name, *serial, *rev, *part;
 
 	if (version > TOPO_METH_FMRI_VERSION)
-		return (topo_mod_seterrno(mp, EMOD_VER_NEW));
+		return (topo_mod_seterrno(mod, EMOD_VER_NEW));
 
 	/* First the must-have fields */
 	if (nvlist_lookup_string(in, TOPO_METH_FMRI_ARG_NAME, &name) != 0)
-		return (topo_mod_seterrno(mp, EMOD_METHOD_INVAL));
+		return (topo_mod_seterrno(mod, EMOD_METHOD_INVAL));
 	if (nvlist_lookup_uint32(in, TOPO_METH_FMRI_ARG_INST, &inst) != 0)
-		return (topo_mod_seterrno(mp, EMOD_METHOD_INVAL));
+		return (topo_mod_seterrno(mod, EMOD_METHOD_INVAL));
 
 	/*
 	 * args is optional
@@ -744,7 +939,7 @@
 	if ((ret = nvlist_lookup_nvlist(in, TOPO_METH_FMRI_ARG_NVL, &args))
 	    != 0) {
 		if (ret != ENOENT)
-			return (topo_mod_seterrno(mp, EMOD_METHOD_INVAL));
+			return (topo_mod_seterrno(mod, EMOD_METHOD_INVAL));
 	} else {
 
 		/* And then optional arguments */
@@ -759,8 +954,8 @@
 		    &serial);
 	}
 
-	*out = hc_fmri_create(mp,
-	    pfmri, version, name, inst, auth, part, rev, serial);
+	*out = hc_fmri_create(mod, pfmri, version, name, inst, auth, part,
+	    rev, serial);
 	if (*out == NULL)
 		return (-1);
 	return (0);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/libtopo/common/hc.h	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,56 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef	_HC_H
+#define	_HC_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#define	HC_VERSION	1
+#define	HC		"hc"
+
+/*
+ * Array declaring all known canonical HC scheme component names.
+ * Hopefully this file will one day be generated from the event registry
+ * automagically.
+ */
+typedef struct hcc {
+	const char *hcc_name;
+	topo_stability_t hcc_stability;
+} hcc_t;
+
+extern int hc_init(topo_mod_t *, topo_version_t);	/* see hc.c */
+extern void hc_fini(topo_mod_t *);			/* see hc.c */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _HC_H */
--- a/usr/src/lib/fm/topo/libtopo/common/hc_canon.h	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _HC_CANON_H
-#define	_HC_CANON_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-/*
- * Array declaring all known canonical HC scheme component names.
- * Hopefully this file will one day be generated from the event registry
- * automagically.
- */
-static const char *Hc_canon[] = {
-	"CMP",
-	"centerplane",
-	"chip",
-	"chip-select",
-	"cpu",
-	"dimm",
-	"rank",
-	"disk",
-	"hostbridge",
-	"interconnect",
-	"chassis",
-	"ioboard",
-	"memory-controller",
-	"dram-channel",
-	"motherboard",
-	"pcibus",
-	"pcidev",
-	"pciexbus",
-	"pciexdev",
-	"pciexfn",
-	"pciexrc",
-	"pcifn",
-	"sata-port",
-	"systemboard"
-};
-
-static int Hc_ncanon = sizeof (Hc_canon) / sizeof (const char *);
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif	/* _HC_CANON_H */
--- a/usr/src/lib/fm/topo/libtopo/common/libtopo.h	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/libtopo.h	Sat Nov 04 01:18:55 2006 -0800
@@ -30,6 +30,7 @@
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 #include <sys/nvpair.h>
+#include <stdio.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -51,18 +52,18 @@
  */
 
 typedef enum topo_stability {
-	TOPO_STABILITY_INTERNAL = 0,	/* private to libtopo */
+	TOPO_STABILITY_UNKNOWN = 0,	/* private to libtopo */
+	TOPO_STABILITY_INTERNAL,	/* private to libtopo */
 	TOPO_STABILITY_PRIVATE,		/* private to Sun */
 	TOPO_STABILITY_OBSOLETE,	/* scheduled for removal */
 	TOPO_STABILITY_EXTERNAL,	/* not controlled by Sun */
 	TOPO_STABILITY_UNSTABLE,	/* new or rapidly changing */
 	TOPO_STABILITY_EVOLVING,	/* less rapidly changing */
 	TOPO_STABILITY_STABLE,		/* mature interface from Sun */
-	TOPO_STABILITY_STANDARD,	/* industry standard */
-	TOPO_STABILITY_MAX		/* end */
+	TOPO_STABILITY_STANDARD		/* industry standard */
 } topo_stability_t;
 
-#define	TOPO_STABILITY_MAX   TOPO_STABILITY_STANDARD /* max valid stability */
+#define	TOPO_STABILITY_MAX	TOPO_STABILITY_STANDARD	/* max valid stab */
 
 typedef enum {
 	TOPO_TYPE_INVALID = 0,
@@ -74,15 +75,36 @@
 	TOPO_TYPE_STRING,	/* const char* */
 	TOPO_TYPE_TIME,		/* uint64_t */
 	TOPO_TYPE_SIZE,		/* uint64_t */
-	TOPO_TYPE_FMRI		/* nvlist_t */
+	TOPO_TYPE_FMRI,		/* nvlist_t */
+	TOPO_TYPE_INT32_ARRAY,	/* array of int32_t */
+	TOPO_TYPE_UINT32_ARRAY,	/* array of uint32_t */
+	TOPO_TYPE_INT64_ARRAY,	/* array of int64_t */
+	TOPO_TYPE_UINT64_ARRAY,	/* array of uint64_t */
+	TOPO_TYPE_STRING_ARRAY,	/* array of const char* */
+	TOPO_TYPE_FMRI_ARRAY	/* array of nvlist_t */
 } topo_type_t;
 
-typedef int (*topo_walk_cb_t)(topo_hdl_t *, tnode_t *, void *);
+typedef struct topo_pgroup_info {
+	const char *tpi_name;		/* property group name */
+	topo_stability_t tpi_namestab;	/* stability of group name */
+	topo_stability_t tpi_datastab;	/* stability of all property values */
+	topo_version_t tpi_version;	/* version of pgroup definition */
+} topo_pgroup_info_t;
+
+extern topo_stability_t topo_name2stability(const char *);
+extern const char *topo_stability2name(topo_stability_t);
 
 extern topo_hdl_t *topo_open(int, const char *, int *);
 extern void topo_close(topo_hdl_t *);
 extern char *topo_snap_hold(topo_hdl_t *, const char *, int *);
 extern void topo_snap_release(topo_hdl_t *);
+extern int topo_xml_print(topo_hdl_t *, FILE *, const char *scheme, int *);
+
+/*
+ * Snapshot walker support
+ */
+typedef int (*topo_walk_cb_t)(topo_hdl_t *, tnode_t *, void *);
+
 extern topo_walk_t *topo_walk_init(topo_hdl_t *, const char *, topo_walk_cb_t,
     void *, int *);
 extern int topo_walk_step(topo_walk_t *, int);
@@ -95,6 +117,9 @@
 #define	TOPO_WALK_CHILD		0x0001
 #define	TOPO_WALK_SIBLING	0x0002
 
+/*
+ * FMRI helper routines
+ */
 extern int topo_fmri_present(topo_hdl_t *, nvlist_t *, int *);
 extern int topo_fmri_contains(topo_hdl_t *, nvlist_t *, nvlist_t *, int *);
 extern int topo_fmri_unusable(topo_hdl_t *, nvlist_t *, int *);
@@ -120,14 +145,12 @@
 extern int topo_node_fru(tnode_t *, nvlist_t **, nvlist_t *, int *);
 extern int topo_node_resource(tnode_t *, nvlist_t **, int *);
 extern int topo_node_label(tnode_t *, char **, int *);
-extern int topo_node_asru_set(tnode_t *node, nvlist_t *, int, int *);
-extern int topo_node_fru_set(tnode_t *node, nvlist_t *, int, int *);
-extern int topo_node_label_set(tnode_t *node, char *, int *);
 extern int topo_method_invoke(tnode_t *node, const char *, topo_version_t,
     nvlist_t *, nvlist_t **, int *);
 
-extern int topo_pgroup_create(tnode_t *, const char *, topo_stability_t, int *);
+extern int topo_pgroup_create(tnode_t *, const topo_pgroup_info_t *, int *);
 extern void topo_pgroup_destroy(tnode_t *, const char *);
+extern topo_pgroup_info_t *topo_pgroup_info(tnode_t *, const char *, int *);
 extern int topo_prop_get_int32(tnode_t *, const char *, const char *,
     int32_t *, int *);
 extern int topo_prop_get_uint32(tnode_t *, const char *, const char *,
@@ -140,6 +163,18 @@
     char **, int *);
 extern int topo_prop_get_fmri(tnode_t *, const char *, const char *,
     nvlist_t **, int *);
+extern int topo_prop_get_int32_array(tnode_t *, const char *, const char *,
+    int32_t **, uint_t *, int *);
+extern int topo_prop_get_uint32_array(tnode_t *, const char *, const char *,
+    uint32_t **, uint_t *, int *);
+extern int topo_prop_get_int64_array(tnode_t *, const char *, const char *,
+    int64_t **, uint_t *, int *);
+extern int topo_prop_get_uint64_array(tnode_t *, const char *, const char *,
+    uint64_t **, uint_t *, int *);
+extern int topo_prop_get_string_array(tnode_t *, const char *, const char *,
+    char ***, uint_t *, int *);
+extern int topo_prop_get_fmri_array(tnode_t *, const char *, const char *,
+    nvlist_t ***, uint_t *, int *);
 extern int topo_prop_set_int32(tnode_t *, const char *, const char *, int,
     int32_t, int *);
 extern int topo_prop_set_uint32(tnode_t *, const char *, const char *, int,
@@ -152,15 +187,23 @@
     int, const char *, int *);
 extern int topo_prop_set_fmri(tnode_t *, const char *, const char *,
     int, const nvlist_t *, int *);
-extern int topo_prop_stability(tnode_t *, const char *, topo_stability_t *);
-extern nvlist_t *topo_prop_get_all(topo_hdl_t *, tnode_t *);
+extern int topo_prop_set_int32_array(tnode_t *, const char *, const char *, int,
+    int32_t *, uint_t, int *);
+extern int topo_prop_set_uint32_array(tnode_t *, const char *, const char *,
+    int, uint32_t *, uint_t, int *);
+extern int topo_prop_set_int64_array(tnode_t *, const char *, const char *,
+    int, int64_t *, uint_t, int *);
+extern int topo_prop_set_uint64_array(tnode_t *, const char *, const char *,
+    int, uint64_t *, uint_t, int *);
+extern int topo_prop_set_string_array(tnode_t *, const char *, const char *,
+    int, const char **, uint_t, int *);
+extern int topo_prop_set_fmri_array(tnode_t *, const char *, const char *,
+    int, const nvlist_t **, uint_t, int *);
+extern nvlist_t *topo_prop_getprops(tnode_t *, int *err);
 extern int topo_prop_inherit(tnode_t *, const char *, const char *, int *);
 
-#define	TOPO_PROP_SET_ONCE	0
-#define	TOPO_PROP_SET_MULTIPLE	1
-
-#define	TOPO_ASRU_COMPUTE	0x0001  /* Compute ASRU dynamically */
-#define	TOPO_FRU_COMPUTE	0x0002  /* Compute FRU dynamically */
+#define	TOPO_PROP_IMMUTABLE	0
+#define	TOPO_PROP_MUTABLE	1
 
 /* Protocol property group and property names */
 #define	TOPO_PGROUP_PROTOCOL	"protocol"	/* Required property group */
@@ -172,30 +215,44 @@
 #define	TOPO_PROP_LABEL		"label"		/*  property LABEL */
 
 /*
- * Legacy TOPO property group: this group supports legacy platform.topo
- * property names
- */
-#define	TOPO_PGROUP_LEGACY	"legacy"	/* Legacy property group */
-#define	TOPO_PROP_PLATASRU	"PLAT-ASRU"
-#define	TOPO_PROP_PLATFRU	"PLAT-FRU"
-
-/*
  * System property group
  */
 #define	TOPO_PGROUP_SYSTEM	"system"
-#define	TOPO_PROP_PLATFORM	"platform"
 #define	TOPO_PROP_ISA		"isa"
 #define	TOPO_PROP_MACHINE	"machine"
 
-/* Property node NVL names */
+/* Property node NVL names used in topo_prop_getprops */
 #define	TOPO_PROP_GROUP		"property-group"
 #define	TOPO_PROP_GROUP_NAME	"property-group-name"
+#define	TOPO_PROP_GROUP_DSTAB	"property-group-data-stability"
+#define	TOPO_PROP_GROUP_NSTAB	"property-group-name-stability"
+#define	TOPO_PROP_GROUP_VERSION	"property-group-version"
 #define	TOPO_PROP_VAL		"property"
 #define	TOPO_PROP_VAL_NAME	"property-name"
 #define	TOPO_PROP_VAL_VAL	"property-value"
+#define	TOPO_PROP_VAL_TYPE	"property-type"
+
+/*
+ * This enum definition is used to define a set of error tags associated with
+ * the libtopo various error conditions occuring during the adminstration of
+ * properties.  The shell script mkerror.sh is
+ * used to parse this file and create a corresponding topo_error.c source file.
+ * If you do something other than add a new error tag here, you may need to
+ * update the mkerror shell script as it is based upon simple regexps.
+ */
+typedef enum topo_prop_errno {
+    ETOPO_PROP_UNKNOWN = 3000, /* unknown topo prop error */
+    ETOPO_PROP_NOENT,   /* undefined property or property group */
+    ETOPO_PROP_DEFD,    /* static property already defined */
+    ETOPO_PROP_NOMEM,   /* memory limit exceeded during property allocation */
+    ETOPO_PROP_TYPE,    /* invalid property type */
+    ETOPO_PROP_NOINHERIT, /* can not inherit property */
+    ETOPO_PROP_NVL,	/* malformed property nvlist */
+    ETOPO_PROP_END	/* end of prop errno list (to ease auto-merge) */
+} topo_prop_errno_t;
 
 extern const char *topo_strerror(int);
-extern void topo_debug_set(topo_hdl_t *, int, char *);
+extern void topo_debug_set(topo_hdl_t *, const char *, const char *);
 extern void *topo_hdl_alloc(topo_hdl_t *, size_t);
 extern void *topo_hdl_zalloc(topo_hdl_t *, size_t);
 extern void topo_hdl_free(topo_hdl_t *, void *, size_t);
@@ -204,13 +261,6 @@
 extern char *topo_hdl_strdup(topo_hdl_t *, const char *);
 extern void topo_hdl_strfree(topo_hdl_t *, char *);
 
-#define	TOPO_DBG_ERR	0x0001	/* enable error handling debug messages */
-#define	TOPO_DBG_MOD	0x0002	/* enable module subsystem debug messages */
-#define	TOPO_DBG_LOG	0x0004	/* enable log subsystem debug messages */
-#define	TOPO_DBG_WALK	0x0008	/* enable walker subsystem debug messages */
-#define	TOPO_DBG_TREE	0x0010	/* enable tree subsystem debug messages */
-#define	TOPO_DBG_ALL	0xffff	/* enable all debug modes */
-
 #ifdef __cplusplus
 }
 #endif
--- a/usr/src/lib/fm/topo/libtopo/common/mapfile-vers	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/mapfile-vers	Sat Nov 04 01:18:55 2006 -0800
@@ -54,21 +54,32 @@
 	topo_method_unregister;
 	topo_method_unregister_all;
 	topo_mod_alloc;
+	topo_mod_auth;
 	topo_mod_clrdebug;
+	topo_mod_cpufmri;
+	topo_mod_devfmri;
+	topo_mod_devinfo;
 	topo_mod_dprintf;
 	topo_mod_enumerate;
+	topo_mod_enummap;
 	topo_mod_errmsg;
 	topo_mod_errno;
 	topo_mod_free;
-	topo_mod_handle;
+	topo_mod_getspecific;
+	topo_mod_hcfmri;
 	topo_mod_load;
+	topo_mod_memfmri;
+	topo_mod_modfmri;
 	topo_mod_nvalloc;
 	topo_mod_nvdup;
-	topo_mod_private;
+	topo_mod_nvl2str;
+	topo_mod_pkgfmri;
+	topo_mod_prominfo;
 	topo_mod_register;
-	topo_mod_rootdir;
 	topo_mod_setdebug;
 	topo_mod_seterrno;
+	topo_mod_setspecific;
+	topo_mod_str2nvl;
 	topo_mod_strdup;
 	topo_mod_strfree;
 	topo_mod_unload;
@@ -79,25 +90,32 @@
 	topo_node_bind;
 	topo_node_fru;
 	topo_node_fru_set;
+	topo_node_getspecific;
 	topo_node_instance;
 	topo_node_label;
 	topo_node_label_set;
 	topo_node_name;
-	topo_node_private;
 	topo_node_range_create;
 	topo_node_range_destroy;
 	topo_node_resource;
+	topo_node_setspecific;
 	topo_node_unbind;
 	topo_open;
 	topo_pgroup_create;
 	topo_pgroup_destroy;
-	topo_prop_get_all;
 	topo_prop_get_fmri;
 	topo_prop_get_int32;
 	topo_prop_get_int64;
 	topo_prop_get_string;
 	topo_prop_get_uint32;
 	topo_prop_get_uint64;
+	topo_prop_get_int32_array;
+	topo_prop_get_uint32_array;
+	topo_prop_get_int64_array;
+	topo_prop_get_uint64_array;
+	topo_prop_get_string_array;
+	topo_prop_get_fmri_array;
+	topo_prop_getprops;
 	topo_prop_inherit;
 	topo_prop_set_fmri;
 	topo_prop_set_int32;
@@ -105,13 +123,21 @@
 	topo_prop_set_string;
 	topo_prop_set_uint32;
 	topo_prop_set_uint64;
-	topo_prop_stability;
+	topo_prop_set_int32_array;
+	topo_prop_set_uint32_array;
+	topo_prop_set_int64_array;
+	topo_prop_set_uint64_array;
+	topo_prop_set_string_array;
+	topo_prop_set_fmri_array;
+	topo_name2stability;
+	topo_stability2name;
 	topo_snap_hold;
 	topo_snap_release;
 	topo_strerror;
 	topo_walk_fini;
 	topo_walk_init;
 	topo_walk_step;
+	topo_xml_print;
     local:
 	*;
 };
--- a/usr/src/lib/fm/topo/libtopo/common/mem.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/mem.c	Sat Nov 04 01:18:55 2006 -0800
@@ -34,57 +34,47 @@
 #include <fm/topo_mod.h>
 #include <sys/fm/protocol.h>
 
-#include <topo_error.h>
+#include <topo_method.h>
+#include <mem.h>
 
 static int mem_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t,
-    topo_instance_t, void *);
+    topo_instance_t, void *, void *);
 static void mem_release(topo_mod_t *, tnode_t *);
 static int mem_nvl2str(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
     nvlist_t **);
-static int mem_str2nvl(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
-    nvlist_t **);
-static int mem_present(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
-    nvlist_t **);
-static int mem_contains(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
-    nvlist_t **);
-static int mem_unusable(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
-    nvlist_t **);
-static int mem_expand(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
-    nvlist_t **);
-
-#define	MEM_VERSION	TOPO_VERSION
+static int mem_fmri_create(topo_mod_t *, tnode_t *, topo_version_t,
+    nvlist_t *, nvlist_t **);
 
 static const topo_method_t mem_methods[] = {
 	{ TOPO_METH_NVL2STR, TOPO_METH_NVL2STR_DESC, TOPO_METH_NVL2STR_VERSION,
 	    TOPO_STABILITY_INTERNAL, mem_nvl2str },
-	{ TOPO_METH_STR2NVL, TOPO_METH_STR2NVL_DESC, TOPO_METH_STR2NVL_VERSION,
-	    TOPO_STABILITY_INTERNAL, mem_str2nvl },
-	{ TOPO_METH_PRESENT, TOPO_METH_PRESENT_DESC, TOPO_METH_PRESENT_VERSION,
-	    TOPO_STABILITY_INTERNAL, mem_present },
-	{ TOPO_METH_CONTAINS, TOPO_METH_CONTAINS_DESC,
-	    TOPO_METH_CONTAINS_VERSION, TOPO_STABILITY_INTERNAL, mem_contains },
-	{ TOPO_METH_UNUSABLE, TOPO_METH_UNUSABLE_DESC,
-	    TOPO_METH_UNUSABLE_VERSION, TOPO_STABILITY_INTERNAL, mem_unusable },
-	{ TOPO_METH_EXPAND, TOPO_METH_UNUSABLE_DESC,
-	    TOPO_METH_EXPAND_VERSION, TOPO_STABILITY_INTERNAL, mem_expand },
+	{ TOPO_METH_FMRI, TOPO_METH_FMRI_DESC, TOPO_METH_FMRI_VERSION,
+	    TOPO_STABILITY_INTERNAL, mem_fmri_create },
 	{ NULL }
 };
 
+static const topo_modops_t mem_ops =
+	{ mem_enum, mem_release };
 static const topo_modinfo_t mem_info =
-	{ "mem", MEM_VERSION, mem_enum, mem_release };
+	{ "mem", FM_FMRI_SCHEME_MEM, MEM_VERSION, &mem_ops };
 
-void
-mem_init(topo_mod_t *mod)
+int
+mem_init(topo_mod_t *mod, topo_version_t version)
 {
 
-	topo_mod_setdebug(mod, TOPO_DBG_ALL);
+	topo_mod_setdebug(mod);
 	topo_mod_dprintf(mod, "initializing mem builtin\n");
 
-	if (topo_mod_register(mod, &mem_info, NULL) != 0) {
+	if (version != MEM_VERSION)
+		return (topo_mod_seterrno(mod, EMOD_VER_NEW));
+
+	if (topo_mod_register(mod, &mem_info, TOPO_VERSION) != 0) {
 		topo_mod_dprintf(mod, "failed to register mem_info: "
 		    "%s\n", topo_mod_errmsg(mod));
-		return;
+		return (-1); /* mod errno already set */
 	}
+
+	return (0);
 }
 
 void
@@ -96,7 +86,7 @@
 /*ARGSUSED*/
 static int
 mem_enum(topo_mod_t *mod, tnode_t *pnode, const char *name,
-    topo_instance_t min, topo_instance_t max, void *arg)
+    topo_instance_t min, topo_instance_t max, void *notused1, void *notused2)
 {
 	(void) topo_method_register(mod, pnode, mem_methods);
 
@@ -143,10 +133,14 @@
 		format = FM_FMRI_SCHEME_MEM ":///" "%1$s";
 
 	/*
-	 * If we have a well-formed unum we step over the hc:/// prefix
+	 * If we have a well-formed unum we step over the hc:// and
+	 * authority prefix
 	 */
-	if (strncmp(unum, "hc:///", 6) == 0)
-		unum += 6;
+	if (strncmp(unum, "hc://", 5) == 0) {
+		unum += 5;
+		unum = strchr(unum, '/');
+		++unum;
+	}
 
 	len = snprintf(NULL, 0, format, unum, val) + 1;
 	buf = topo_mod_zalloc(mod, len);
@@ -169,42 +163,65 @@
 	return (0);
 }
 
-/*ARGSUSED*/
-static int
-mem_str2nvl(topo_mod_t *mod, tnode_t *node, topo_version_t version,
-    nvlist_t *in, nvlist_t **out)
+static nvlist_t *
+mem_fmri(topo_mod_t *mod, uint64_t pa, uint64_t offset, char *unum, int flags)
 {
-	return (-1);
-}
+	int err;
+	nvlist_t *asru;
+
+	if (topo_mod_nvalloc(mod, &asru, NV_UNIQUE_NAME) != 0)
+		return (NULL);
+
+	/*
+	 * If we have a well-formed unum we step over the hc:/// and
+	 * authority prefix
+	 */
+	if (strncmp(unum, "hc://", 5) == 0) {
+		char *tstr;
 
-/*ARGSUSED*/
-static int
-mem_present(topo_mod_t *mod, tnode_t *node, topo_version_t version,
-    nvlist_t *in, nvlist_t **out)
-{
-	return (-1);
+		tstr = strchr(unum, '/');
+		unum = ++tstr;
+	}
+
+	err = nvlist_add_uint8(asru, FM_VERSION, FM_MEM_SCHEME_VERSION);
+	err |= nvlist_add_string(asru, FM_FMRI_SCHEME, FM_FMRI_SCHEME_MEM);
+	err |= nvlist_add_string(asru, FM_FMRI_MEM_UNUM, unum);
+	if (flags & TOPO_MEMFMRI_PA)
+		err |= nvlist_add_uint64(asru, FM_FMRI_MEM_PHYSADDR, pa);
+	if (flags & TOPO_MEMFMRI_OFFSET)
+		err |= nvlist_add_uint64(asru, FM_FMRI_MEM_OFFSET, offset);
+
+	if (err != 0) {
+		nvlist_free(asru);
+		return (NULL);
+	}
+
+	return (asru);
 }
 
 /*ARGSUSED*/
 static int
-mem_contains(topo_mod_t *mod, tnode_t *node, topo_version_t version,
-    nvlist_t *in, nvlist_t **out)
-{
-	return (-1);
-}
-
-/*ARGSUSED*/
-static int
-mem_unusable(topo_mod_t *mod, tnode_t *node, topo_version_t version,
+mem_fmri_create(topo_mod_t *mod, tnode_t *node, topo_version_t version,
     nvlist_t *in, nvlist_t **out)
 {
-	return (-1);
-}
+	uint64_t pa = 0, offset = 0;
+	int flags = 0;
+	nvlist_t *asru;
+	char *unum;
 
-/*ARGSUSED*/
-static int
-mem_expand(topo_mod_t *mod, tnode_t *node, topo_version_t version,
-    nvlist_t *in, nvlist_t **out)
-{
-	return (-1);
+	if (nvlist_lookup_uint64(in, FM_FMRI_MEM_PHYSADDR, &pa) == 0)
+		flags |= TOPO_MEMFMRI_PA;
+	if (nvlist_lookup_uint64(in, FM_FMRI_MEM_OFFSET, &offset) == 0)
+		flags |= TOPO_MEMFMRI_OFFSET;
+	if (nvlist_lookup_string(in, FM_FMRI_MEM_UNUM, &unum) != 0)
+		return (topo_mod_seterrno(mod, EMOD_FMRI_MALFORM));
+
+	asru = mem_fmri(mod, pa, offset, unum, flags);
+
+	if (asru == NULL)
+		return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
+
+	*out = asru;
+
+	return (0);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/libtopo/common/mem.h	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,45 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef	_MEM_H
+#define	_MEM_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#define	MEM_VERSION	1
+
+extern int mem_init(topo_mod_t *, topo_version_t);	/* see mem.c */
+extern void mem_fini(topo_mod_t *);			/* see mem.c */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _MEM_H */
--- a/usr/src/lib/fm/topo/libtopo/common/mkerror.sh	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/mkerror.sh	Sat Nov 04 01:18:55 2006 -0800
@@ -3,9 +3,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
 #
 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 # or http://www.opensolaris.org/os/licensing.
@@ -24,7 +23,7 @@
 # Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-#ident	"%Z%%M%	%I%	%E% SMI"
+#ident	"@(#)mkerror.sh	1.1	06/02/11 SMI"
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
@@ -32,7 +31,7 @@
 input="`cat`"
 [ -z "$input" ] && exit 1
 
-if [ $1 = "internal" ] ; then
+if [ $1 = "liberrors" ] ; then
 echo "\
 /*\n\
  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.\n\
@@ -79,9 +78,27 @@
 	return (topo_strerror(thp->th_errno));
 }"
 
+elif [ $1 = "properrors" ] ; then
+
+echo "\
+\n\
+static const char *const _topo_properrstrs[] = {"
+
+pattern='^[ ]*ETOPO_PROP_[A-Z0-9_]*.*\* \(.*\) \*.*'
+replace='	"\1",'
+
+echo "$input" | sed -n "s/$pattern/$replace/p" || exit 1
+
+echo "\
+};\n\
+\n\
+static const int _topo_nproperrstrs =\n\
+    sizeof (_topo_properrstrs) / sizeof (_topo_properrstrs[0]);"
+
 else
 
 echo "\
+\n\
 static const char *const _topo_moderrstrs[] = {"
 
 pattern='^[ ]*EMOD_[A-Z0-9_]*.*\* \(.*\) \*.*'
@@ -91,7 +108,6 @@
 
 echo "\
 };\n\
-\n\
 static const int _topo_nmoderrstrs =\n\
     sizeof (_topo_moderrstrs) / sizeof (_topo_moderrstrs[0]);\n\
 \n\
@@ -122,8 +138,12 @@
 
 	if (err >= ETOPO_UNKNOWN && (err - ETOPO_UNKNOWN) < _topo_nerrstrs)
 		s = _topo_errstrs[err - ETOPO_UNKNOWN];
-	else if (err >= EMOD_UNKNOWN && (err - EMOD_UNKNOWN) <  _topo_nmoderrstrs)
+	else if (err >= EMOD_UNKNOWN && (err - EMOD_UNKNOWN) <
+	    _topo_nmoderrstrs)
 		s = _topo_moderrstrs[err - EMOD_UNKNOWN];
+	else if (err >= ETOPO_PROP_UNKNOWN && (err - ETOPO_PROP_UNKNOWN) <
+	    _topo_nproperrstrs)
+		s = _topo_properrstrs[err - ETOPO_PROP_UNKNOWN];
 	else
 		s = _topo_errstrs[0];
 
--- a/usr/src/lib/fm/topo/libtopo/common/mod.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/mod.c	Sat Nov 04 01:18:55 2006 -0800
@@ -41,36 +41,43 @@
 #include <libelf.h>
 #include <gelf.h>
 
-#include <topo_error.h>
+#include <topo_method.h>
+#include <mod.h>
 
 static int mod_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t,
-    topo_instance_t, void *);
+    topo_instance_t, void *, void *);
 static void mod_release(topo_mod_t *, tnode_t *);
 static int mod_fmri_create_meth(topo_mod_t *, tnode_t *, topo_version_t,
     nvlist_t *, nvlist_t **);
 
-#define	MOD_VERSION	TOPO_VERSION
-
 static const topo_method_t mod_methods[] = {
 	{ TOPO_METH_FMRI, TOPO_METH_FMRI_DESC, TOPO_METH_FMRI_VERSION,
 	    TOPO_STABILITY_INTERNAL, mod_fmri_create_meth },
 	{ NULL }
 };
 
+static const topo_modops_t mod_modops =
+	{ mod_enum, mod_release };
 static const topo_modinfo_t mod_info =
-	{ "mod", MOD_VERSION, mod_enum, mod_release };
+	{ "mod", FM_FMRI_SCHEME_MOD, MOD_VERSION, &mod_modops };
 
-void
-mod_init(topo_mod_t *mod)
+int
+mod_init(topo_mod_t *mod, topo_version_t version)
 {
-	topo_mod_setdebug(mod, TOPO_DBG_ALL);
+	if (getenv("TOPOMODDEBUG"))
+		topo_mod_setdebug(mod);
 	topo_mod_dprintf(mod, "initializing mod builtin\n");
 
-	if (topo_mod_register(mod, &mod_info, NULL) != 0) {
+	if (version != MOD_VERSION)
+		return (topo_mod_seterrno(mod, EMOD_VER_NEW));
+
+	if (topo_mod_register(mod, &mod_info, TOPO_VERSION) != 0) {
 		topo_mod_dprintf(mod, "failed to register mod_info: "
 		    "%s\n", topo_mod_errmsg(mod));
-		return;
+		return (-1); /* mod errno already set */
 	}
+
+	return (0);
 }
 
 void
@@ -82,7 +89,7 @@
 /*ARGSUSED*/
 static int
 mod_enum(topo_mod_t *mod, tnode_t *pnode, const char *name,
-    topo_instance_t min, topo_instance_t max, void *arg)
+    topo_instance_t min, topo_instance_t max, void *notused1, void *notused2)
 {
 	(void) topo_method_register(mod, pnode, mod_methods);
 	return (0);
@@ -191,16 +198,12 @@
 static nvlist_t *
 mod_fmri_create(topo_mod_t *mp, const char *driver)
 {
-	topo_hdl_t *thp;
-	nvlist_t *arg = NULL;
 	nvlist_t *out = NULL;
 	nvlist_t *pkg = NULL;
 	char objpath[PATH_MAX];
 	char *path = NULL;
-	int err;
 
-	if (topo_mod_nvalloc(mp, &arg, NV_UNIQUE_NAME) != 0 ||
-	    topo_mod_nvalloc(mp, &out, NV_UNIQUE_NAME) != 0) {
+	if (topo_mod_nvalloc(mp, &out, NV_UNIQUE_NAME) != 0) {
 		(void) topo_mod_seterrno(mp, EMOD_FMRI_NVL);
 		goto mfc_bail;
 	}
@@ -209,23 +212,14 @@
 
 	if ((path = mod_binary_path_get(mp, objpath)) == NULL)
 		goto mfc_bail;
-	if (nvlist_add_string(arg, "path", path) != 0) {
-		(void) topo_mod_seterrno(mp, EMOD_FMRI_NVL);
-		goto mfc_bail;
-	}
 
 	if (mod_nvl_data(mp, out, objpath) < 0)
 		goto mfc_bail;
 
-	thp = topo_mod_handle(mp);
-	pkg = topo_fmri_create(thp,
-	    FM_FMRI_SCHEME_PKG, FM_FMRI_SCHEME_PKG, 0, arg, &err);
+	pkg = topo_mod_pkgfmri(mp, FM_PKG_SCHEME_VERSION, path);
 	if (pkg == NULL) {
-		(void) topo_mod_seterrno(mp, err);
 		goto mfc_bail;
 	}
-	nvlist_free(arg);
-	arg = NULL;
 
 	if (nvlist_add_nvlist(out, FM_FMRI_MOD_PKG, pkg) != 0) {
 		(void) topo_mod_seterrno(mp, EMOD_FMRI_NVL);
@@ -238,7 +232,6 @@
 mfc_bail:
 	nvlist_free(pkg);
 	nvlist_free(out);
-	nvlist_free(arg);
 	return (NULL);
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/libtopo/common/mod.h	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,45 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef	_MOD_H
+#define	_MOD_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#define	MOD_VERSION	1
+
+extern int mod_init(topo_mod_t *, topo_version_t);	/* see mod.c */
+extern void mod_fini(topo_mod_t *);			/* see mod.c */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _MOD_H */
--- a/usr/src/lib/fm/topo/libtopo/common/pkg.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/pkg.c	Sat Nov 04 01:18:55 2006 -0800
@@ -44,38 +44,45 @@
 #include <libelf.h>
 #include <gelf.h>
 
-#include <topo_error.h>
+#include <topo_method.h>
+#include <pkg.h>
 
 #define	BUFLEN	(2 * PATH_MAX)
 
 static int pkg_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t,
-    topo_instance_t, void *);
+    topo_instance_t, void *, void *);
 static void pkg_release(topo_mod_t *, tnode_t *);
 static int pkg_fmri_create_meth(topo_mod_t *, tnode_t *, topo_version_t,
     nvlist_t *, nvlist_t **);
 
-#define	PKG_VERSION	TOPO_VERSION
-
 static const topo_method_t pkg_methods[] = {
 	{ TOPO_METH_FMRI, TOPO_METH_FMRI_DESC, TOPO_METH_FMRI_VERSION,
 	    TOPO_STABILITY_INTERNAL, pkg_fmri_create_meth },
 	{ NULL }
 };
 
+static const topo_modops_t pkg_ops =
+	{ pkg_enum, pkg_release };
 static const topo_modinfo_t pkg_info =
-	{ "pkg", PKG_VERSION, pkg_enum, pkg_release };
+	{ "pkg", FM_FMRI_SCHEME_PKG, PKG_VERSION, &pkg_ops };
 
-void
-pkg_init(topo_mod_t *mod)
+int
+pkg_init(topo_mod_t *mod, topo_version_t version)
 {
-	topo_mod_setdebug(mod, TOPO_DBG_ALL);
+	if (getenv("TOPOPKGDEBUG"))
+		topo_mod_setdebug(mod);
 	topo_mod_dprintf(mod, "initializing mod builtin\n");
 
-	if (topo_mod_register(mod, &pkg_info, NULL) != 0) {
+	if (version != PKG_VERSION)
+		return (topo_mod_seterrno(mod, EMOD_VER_NEW));
+
+	if (topo_mod_register(mod, &pkg_info, TOPO_VERSION) != 0) {
 		topo_mod_dprintf(mod, "failed to register pkg_info: "
 		    "%s\n", topo_mod_errmsg(mod));
-		return;
+		return (-1);
 	}
+
+	return (0);
 }
 
 void
@@ -87,7 +94,7 @@
 /*ARGSUSED*/
 static int
 pkg_enum(topo_mod_t *mod, tnode_t *pnode, const char *name,
-    topo_instance_t min, topo_instance_t max, void *arg)
+    topo_instance_t min, topo_instance_t max, void *notused1, void *notused2)
 {
 	(void) topo_method_register(mod, pnode, pkg_methods);
 	return (0);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/libtopo/common/pkg.h	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,45 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef	_PKG_H
+#define	_PKG_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#define	PKG_VERSION	1
+
+extern int pkg_init(topo_mod_t *, topo_version_t);	/* see pkg.c */
+extern void pkg_fini(topo_mod_t *);			/* see pkg.c */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _PKG_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_2xml.c	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,294 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <stdio.h>
+#include <strings.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/fm/protocol.h>
+#include <sys/utsname.h>
+
+#include <topo_parse.h>
+#include <topo_prop.h>
+#include <topo_tree.h>
+
+#define	INT32BUFSZ	sizeof (UINT32_MAX) + 1
+#define	INT64BUFSZ	sizeof (UINT64_MAX) + 1
+#define	XML_VERSION	"1.0"
+
+static int txml_print_range(topo_hdl_t *, FILE *, tnode_t *, int);
+
+void
+print_header(FILE *fp)
+{
+	char buf[32];
+	time_t tod = time(NULL);
+	struct utsname uts;
+
+	(void) fprintf(fp, "<?xml version=\"%s\"?>\n", XML_VERSION);
+	(void) fprintf(fp, "<!DOCTYPE topology SYSTEM \"%s\">\n",
+	    TOPO_DTD_PATH);
+
+	(void) uname(&uts);
+	(void) strftime(buf, sizeof (buf), "%b %d %T", localtime(&tod));
+	(void) fprintf(fp, "<!--\n");
+	(void) fprintf(fp, " This topology map file was generated on "
+	    "%-15s for %s\n", buf, uts.nodename);
+	(void) fprintf(fp, "<-->\n\n");
+}
+
+void
+begin_element(FILE *fp, const char *ename, ...)
+{
+	char *name, *value;
+	va_list ap;
+
+	(void) fprintf(fp, "<%s ", ename);
+	va_start(ap, ename);
+	name = va_arg(ap, char *);
+	while (name != NULL) {
+		value = va_arg(ap, char *);
+		(void) fprintf(fp, "%s='%s' ", name, value);
+		name = va_arg(ap, char *);
+	}
+	(void) fprintf(fp, ">\n");
+}
+
+void
+begin_end_element(FILE *fp, const char *ename, ...)
+{
+	char *name, *value;
+	va_list ap;
+
+	(void) fprintf(fp, "<%s ", ename);
+	va_start(ap, ename);
+	name = va_arg(ap, char *);
+	while (name != NULL) {
+		value = va_arg(ap, char *);
+		(void) fprintf(fp, "%s='%s' ", name, value);
+		name = va_arg(ap, char *);
+	}
+	(void) fprintf(fp, "/>\n");
+}
+
+void
+end_element(FILE *fp, const char *ename)
+{
+	(void) fprintf(fp, "</%s>\n", ename);
+}
+
+static void
+txml_print_prop(topo_hdl_t *thp, FILE *fp, topo_propval_t *pv)
+{
+	int err;
+	char *fmri = NULL;
+	char vbuf[INT64BUFSZ], tbuf[10], *pval;
+	nvpair_t *nvp;
+
+	if ((nvp = nvlist_next_nvpair(pv->tp_val, NULL)) == NULL)
+		return;
+
+	switch (pv->tp_type) {
+		case TOPO_TYPE_INT32: {
+			int32_t val;
+			(void) nvpair_value_int32(nvp, &val);
+			(void) snprintf(vbuf, INT64BUFSZ, "%d", val);
+			(void) snprintf(tbuf, 10, "%s", Int32);
+			pval = vbuf;
+			break;
+		}
+		case TOPO_TYPE_UINT32: {
+			uint32_t val;
+			(void) nvpair_value_uint32(nvp, &val);
+			(void) snprintf(vbuf, INT64BUFSZ, "0x%x", val);
+			(void) snprintf(tbuf, 10, "%s", UInt32);
+			pval = vbuf;
+			break;
+		}
+		case TOPO_TYPE_INT64: {
+			int64_t val;
+			(void) nvpair_value_int64(nvp, &val);
+			(void) snprintf(vbuf, INT64BUFSZ, "%lld",
+			    (longlong_t)val);
+			(void) snprintf(tbuf, 10, "%s", Int64);
+			pval = vbuf;
+			break;
+		}
+		case TOPO_TYPE_UINT64: {
+			uint64_t val;
+			(void) nvpair_value_uint64(nvp, &val);
+			(void) snprintf(vbuf, INT64BUFSZ, "0x%llx",
+			    (u_longlong_t)val);
+			(void) snprintf(tbuf, 10, "%s", UInt64);
+			pval = vbuf;
+			break;
+		}
+		case TOPO_TYPE_STRING: {
+			(void) nvpair_value_string(nvp, &pval);
+			(void) snprintf(tbuf, 10, "%s", String);
+			break;
+		}
+		case TOPO_TYPE_FMRI: {
+			nvlist_t *val;
+
+			(void) nvpair_value_nvlist(nvp, &val);
+			if (topo_fmri_nvl2str(thp, val, &fmri, &err) == 0)
+				pval = fmri;
+			else
+				return;
+
+			(void) snprintf(tbuf, 10, "%s", FMRI);
+			break;
+		}
+	}
+
+	begin_end_element(fp, Propval, Name, pv->tp_name, Type, tbuf,
+	    Value, pval, NULL);
+
+	if (fmri != NULL)
+		topo_hdl_strfree(thp, fmri);
+
+}
+
+static void
+txml_print_pgroup(topo_hdl_t *thp, FILE *fp, topo_pgroup_t *pg)
+{
+	topo_ipgroup_info_t *pip = pg->tpg_info;
+	topo_proplist_t *plp;
+	const char *namestab, *datastab;
+	char version[INT32BUFSZ];
+
+	namestab = topo_stability2name(pip->tpi_namestab);
+	datastab = topo_stability2name(pip->tpi_datastab);
+	(void) snprintf(version, INT32BUFSZ, "%d", pip->tpi_version);
+	begin_element(fp, Propgrp, Name, pip->tpi_name, Namestab,
+	    namestab, Datastab, datastab, Version, version, NULL);
+	topo_hdl_strfree(thp, (char *)namestab);
+	topo_hdl_strfree(thp, (char *)datastab);
+	for (plp = topo_list_next(&pg->tpg_pvals); plp != NULL;
+	    plp = topo_list_next(plp)) {
+		txml_print_prop(thp, fp, plp->tp_pval);
+	}
+	end_element(fp, Propgrp);
+}
+
+static void
+txml_print_dependents(topo_hdl_t *thp, FILE *fp, tnode_t *node)
+{
+	if (topo_list_next(&node->tn_children) == NULL)
+		return;
+
+	if (txml_print_range(thp, fp, node, 1) == 1)
+		end_element(fp, Dependents);
+}
+
+static void
+txml_print_node(topo_hdl_t *thp, FILE *fp, tnode_t *node)
+{
+	char inst[INT32BUFSZ];
+	topo_pgroup_t *pg;
+
+	(void) snprintf(inst, INT32BUFSZ, "%d", node->tn_instance);
+	begin_element(fp, Node, Instance, inst, Static, True, NULL);
+	for (pg = topo_list_next(&node->tn_pgroups); pg != NULL;
+	    pg = topo_list_next(pg)) {
+		txml_print_pgroup(thp, fp, pg);
+	}
+	txml_print_dependents(thp, fp, node);
+	end_element(fp, Node);
+
+}
+
+static int
+txml_print_range(topo_hdl_t *thp, FILE *fp, tnode_t *node, int dependent)
+{
+	int i, create = 0, ret = 0;
+	topo_nodehash_t *nhp;
+	char min[INT32BUFSZ], max[INT32BUFSZ];
+
+	for (nhp = topo_list_next(&node->tn_children); nhp != NULL;
+	    nhp = topo_list_next(nhp)) {
+		(void) snprintf(min, INT32BUFSZ, "%d", nhp->th_range.tr_min);
+		(void) snprintf(max, INT32BUFSZ, "%d", nhp->th_range.tr_max);
+
+		/*
+		 * Some enumerators create empty ranges: make sure there
+		 * are real nodes before creating this range
+		 */
+		for (i = 0; i < nhp->th_arrlen; ++i) {
+			if (nhp->th_nodearr[i] != NULL)
+				++create;
+		}
+		if (!create)
+			continue;
+
+		if (dependent) {
+			begin_element(fp, Dependents, Grouping, Children, NULL);
+			dependent = 0;
+			ret = 1;
+		}
+		begin_element(fp, Range, Name, nhp->th_name, Min, min, Max,
+		    max, NULL);
+		for (i = 0; i < nhp->th_arrlen; ++i) {
+			if (nhp->th_nodearr[i] != NULL)
+				txml_print_node(thp, fp, nhp->th_nodearr[i]);
+		}
+		end_element(fp, Range);
+	}
+
+	return (ret);
+}
+
+static void
+txml_print_topology(topo_hdl_t *thp, FILE *fp, char *scheme, tnode_t *node)
+{
+	begin_element(fp, Topology, Name, thp->th_product, Scheme, scheme,
+	    NULL);
+	(void) txml_print_range(thp, fp, node, 0);
+	end_element(fp, Topology);
+
+}
+
+int
+topo_xml_print(topo_hdl_t *thp,  FILE *fp, const char *scheme, int *err)
+{
+	ttree_t *tp;
+
+	print_header(fp);
+	for (tp = topo_list_next(&thp->th_trees); tp != NULL;
+	    tp = topo_list_next(tp)) {
+		if (strcmp(scheme, tp->tt_scheme) == 0) {
+			txml_print_topology(thp, fp, tp->tt_scheme,
+			    tp->tt_root);
+			return (0);
+		}
+	}
+
+	*err = EINVAL;
+	return (-1);
+}
--- a/usr/src/lib/fm/topo/libtopo/common/topo_builtin.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_builtin.c	Sat Nov 04 01:18:55 2006 -0800
@@ -33,18 +33,25 @@
 #include <topo_error.h>
 #include <topo_subr.h>
 
+#include <cpu.h>
+#include <hc.h>
+#include <dev.h>
+#include <mem.h>
+#include <mod.h>
+#include <pkg.h>
+
 static const struct topo_builtin _topo_builtins[] = {
-	{ "cpu", cpu_init, cpu_fini },
-	{ "dev", dev_init, dev_fini },
-	{ "mem", mem_init, mem_fini },
-	{ "pkg", pkg_init, pkg_fini },
-	{ "mod", mod_init, mod_fini },
-	{ "hc", hc_init, hc_fini },
+	{ "cpu", CPU_VERSION, cpu_init, cpu_fini },
+	{ "dev", DEV_VERSION, dev_init, dev_fini },
+	{ "mem", MEM_VERSION, mem_init, mem_fini },
+	{ "pkg", PKG_VERSION, pkg_init, pkg_fini },
+	{ "mod", MOD_VERSION, mod_init, mod_fini },
+	{ "hc", HC_VERSION, hc_init, hc_fini },		/* hc must go last */
 	{ NULL, NULL, NULL }
 };
 
 static int
-bltin_init(topo_mod_t *mp)
+bltin_init(topo_mod_t *mp, topo_version_t version)
 {
 	const topo_builtin_t *bp;
 
@@ -55,12 +62,13 @@
 
 	mp->tm_data = (void *)bp;
 
-	(*bp->bltin_init)(mp);
-
-	if (mp->tm_info == NULL) {
-		topo_dprintf(TOPO_DBG_ERR,
-		    "unable initialize builtin module: %s\n", bp->bltin_name);
-		return (topo_mod_seterrno(mp, ETOPO_MOD_INIT));
+	if ((*bp->bltin_init)(mp, version) != 0 || mp->tm_info == NULL) {
+		if (mp->tm_errno == 0)
+			(void) topo_mod_seterrno(mp, ETOPO_MOD_INIT);
+		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
+		    "unable initialize builtin module: %s: %s\n",
+		    bp->bltin_name, topo_mod_errmsg(mp));
+		return (-1);
 	}
 
 	return (0);
@@ -79,7 +87,7 @@
 	return (0);
 }
 
-const topo_modops_t topo_bltin_ops = {
+const topo_imodops_t topo_bltin_ops = {
 	bltin_init,
 	bltin_fini,
 };
@@ -101,16 +109,18 @@
 		/*
 		 * Load scheme-specific module
 		 */
-		if ((mod = topo_modhash_load(thp, bp->bltin_name,
-		    &topo_bltin_ops)) == NULL) {
-			topo_dprintf(TOPO_DBG_ERR, "unable to create scheme "
+		if ((mod = topo_modhash_load(thp, bp->bltin_name, NULL,
+		    &topo_bltin_ops, bp->bltin_version)) == NULL) {
+			topo_dprintf(thp, TOPO_DBG_ERR,
+			    "unable to create scheme "
 			    "tree for %s:%s\n", bp->bltin_name,
 			    topo_hdl_errmsg(thp));
 			return (-1);
 		}
 		if ((tp = topo_tree_create(thp, mod, bp->bltin_name))
 		    == NULL) {
-			topo_dprintf(TOPO_DBG_ERR, "unable to create scheme "
+			topo_dprintf(thp, TOPO_DBG_ERR,
+			    "unable to create scheme "
 			    "tree for %s:%s\n", bp->bltin_name,
 			    topo_hdl_errmsg(thp));
 			return (-1);
@@ -124,7 +134,7 @@
 		 */
 		rnode = tp->tt_root;
 		if (topo_mod_enumerate(mod, rnode, mod->tm_name, rnode->tn_name,
-		    rnode->tn_instance, rnode->tn_instance) < 0) {
+		    rnode->tn_instance, rnode->tn_instance, NULL) < 0) {
 			/*
 			 * If we see a failure, note it in the handle and
 			 * drive on
--- a/usr/src/lib/fm/topo/libtopo/common/topo_builtin.h	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_builtin.h	Sat Nov 04 01:18:55 2006 -0800
@@ -47,25 +47,13 @@
 
 typedef struct topo_builtin {
 	const char *bltin_name;
-	void (*bltin_init)(topo_mod_t *);
+	topo_version_t bltin_version;
+	int (*bltin_init)(topo_mod_t *, topo_version_t version);
 	void (*bltin_fini)(topo_mod_t *);
 } topo_builtin_t;
 
 extern int topo_builtin_create(topo_hdl_t *, const char *);
 
-extern void hc_init(topo_mod_t *);	/* see hc.c */
-extern void hc_fini(topo_mod_t *);	/* see hc.c */
-extern void cpu_init(topo_mod_t *);	/* see cpu.c */
-extern void cpu_fini(topo_mod_t *);	/* see cpu.c */
-extern void dev_init(topo_mod_t *);	/* see dev.c */
-extern void dev_fini(topo_mod_t *);	/* see dev.c */
-extern void mem_init(topo_mod_t *);	/* see mem.c */
-extern void mem_fini(topo_mod_t *);	/* see mem.c */
-extern void mod_init(topo_mod_t *);	/* see mod.c */
-extern void mod_fini(topo_mod_t *);	/* see mod.c */
-extern void pkg_init(topo_mod_t *);	/* see pkg.c */
-extern void pkg_fini(topo_mod_t *);	/* see pkg.c */
-
 #ifdef	__cplusplus
 }
 #endif
--- a/usr/src/lib/fm/topo/libtopo/common/topo_error.h	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_error.h	Sat Nov 04 01:18:55 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -38,7 +37,7 @@
 
 /*
  * This enum definition is used to define a set of error tags associated with
- * the fmd daemon's various error conditions.  The shell script mkerror.sh is
+ * the libtopo internal error conditions.  The shell script mkerror.sh is
  * used to parse this file and create a corresponding topo_error.c source file.
  * If you do something other than add a new error tag here, you may need to
  * update the mkerror shell script as it is based upon simple regexps.
@@ -47,7 +46,7 @@
     ETOPO_UNKNOWN = 1000, /* unknown libtopo error */
     ETOPO_NOMEM,	/* memory limit exceeded */
     ETOPO_MODULE,	/* module detected or caused an error */
-    ETOPO_HDL_VER,	/* handle opened with invalid ABI version */
+    ETOPO_HDL_ABIVER,	/* handle opened with invalid ABI version */
     ETOPO_HDL_SNAP,	/* snapshot already taken */
     ETOPO_HDL_INVAL,	/* invalid argument specified */
     ETOPO_HDL_UUID,	/* uuid already set */
@@ -55,12 +54,15 @@
     ETOPO_MOD_FINI,	/* failed to uninitialize module */
     ETOPO_MOD_LOADED,	/* specified module is already loaded */
     ETOPO_MOD_NOMOD,	/* specified module is not loaded */
-    ETOPO_MOD_NONVL,	/* specified module is not loaded */
+    ETOPO_MOD_ABIVER,	/* module registered with invalid ABI version */
     ETOPO_MOD_INVAL,	/* module invalid argument */
     ETOPO_MOD_DUP,	/* module duplicate node entry */
     ETOPO_MOD_NOREG,	/* module failed to register */
     ETOPO_MOD_NOENT,	/* module path invalid */
+    ETOPO_MOD_XRD,	/* unable to read topology map file */
+    ETOPO_MOD_XENUM,	/* unable to enumerate from a topology map file */
     ETOPO_MOD_NOSUP,	/* enumerator not supported in this module */
+    ETOPO_MOD_VER,	/* module version mismatch while loading */
     ETOPO_RTLD_OPEN,	/* rtld failed to open shared library plug-in */
     ETOPO_RTLD_INIT,	/* shared library plug-in does not define _topo_init */
     ETOPO_RTLD_NOMEM,	/* memory limit exceeded when opening shared library */
@@ -76,11 +78,8 @@
     ETOPO_VER_OLD,	/* plugin compiled using an obsolete topo ABI */
     ETOPO_VER_NEW,	/* plugin is compiled using a newer topo ABI */
     ETOPO_ENUM_PARTIAL,	/* partial enumeration completed for client */
-    ETOPO_PROP_NOENT,	/* undefined property or property group */
-    ETOPO_PROP_DEFD,	/* static property already defined */
-    ETOPO_PROP_NOMEM,	/* memory limit exceeded during property allocation */
-    ETOPO_PROP_TYPE,	/* invalid property type */
-    ETOPO_PROP_NOINHERIT, /* can not inherit property */
+    ETOPO_ENUM_NOMAP,	/* no topology map file for enumeration */
+    ETOPO_ENUM_FATAL,	/* fatal enumeration error */
     ETOPO_FMRI_NVL,	/* nvlist allocation failure for FMRI */
     ETOPO_FMRI_VERSION, /* invalid FMRI scheme version */
     ETOPO_FMRI_MALFORM,	/* malformed FMRI */
--- a/usr/src/lib/fm/topo/libtopo/common/topo_file.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_file.c	Sat Nov 04 01:18:55 2006 -0800
@@ -28,6 +28,7 @@
 
 #include <limits.h>
 #include <string.h>
+#include <unistd.h>
 #include <sys/param.h>
 #include <topo_error.h>
 #include <topo_tree.h>
@@ -38,132 +39,70 @@
  * topo_file.c
  *
  *	This file hides the details of any file manipulation to
- *	establish topology for a given scheme.  It has two outward
- *	facing interfaces topo_file_load() and topo_file_unload().
+ *	establish topology for a given enumerator.
  */
 
-#define	TOPO_DEFAULT_FILE	"%s-topology.xml"
-#define	PLATFORM_TOPO_PATH	"%susr/platform/%s/lib/fm/topo/%s"
-#define	COMMON_TOPO_PATH	"%susr/lib/fm/topo/%s"
-
-static int
-xml_read(topo_hdl_t *hp, ttree_t *tp)
-{
-	topo_file_t *tfp;
-	char *pplat, *pmach;
-	int err, e;
-	char _topo_file[MAXNAMELEN * 2];
-	char _topo_path[PATH_MAX];
-
-
-	tfp = (topo_file_t *)tp->tt_file;
-
-	(void) snprintf(_topo_file,
-	    2 * MAXNAMELEN, TOPO_DEFAULT_FILE, tp->tt_scheme);
-
-	/*
-	 * Look for a platform-specific topology file first
-	 */
-	e = topo_prop_get_string(tp->tt_root, TOPO_PGROUP_SYSTEM,
-	    TOPO_PROP_PLATFORM, &pplat, &err);
-	if (e < 0)
-		return (topo_hdl_seterrno(hp, err));
-	(void) snprintf(_topo_path, PATH_MAX, PLATFORM_TOPO_PATH,
-	    hp->th_rootdir, pplat, _topo_file);
-
-	tfp->tf_fileinfo =
-	    topo_xml_read(tfp->tf_mod, _topo_path, tp->tt_scheme);
-	if (tfp->tf_fileinfo != NULL) {
-		topo_hdl_strfree(hp, pplat);
-		return (0);
-	}
-
-	topo_dprintf(TOPO_DBG_MOD, "failed to load topology file %s: %s\n",
-	    _topo_path, topo_strerror(topo_hdl_errno(hp)));
+#define	TOPO_DEFAULT_FILE	"maps/%s-%s-topology.xml"
+#define	TOPO_COMMON_FILE	"maps/%s-topology.xml"
 
-	/*
-	 * No luck with the platform-specific file, how about a
-	 * machine-specific one?
-	 */
-	e = topo_prop_get_string(tp->tt_root, TOPO_PGROUP_SYSTEM,
-	    TOPO_PROP_MACHINE, &pmach, &err);
-	if (e < 0) {
-		topo_hdl_strfree(hp, pplat);
-		return (topo_hdl_seterrno(hp, err));
-	}
-	/*
-	 * Don't waste time trying to open the same file twice in the
-	 * cases where the platform name is identical to the machine
-	 * name
-	 */
-	if (strcmp(pplat, pmach) != 0) {
-		(void) snprintf(_topo_path, PATH_MAX, PLATFORM_TOPO_PATH,
-		    hp->th_rootdir, pmach, _topo_file);
-		tfp->tf_fileinfo =
-		    topo_xml_read(tfp->tf_mod, _topo_path, tp->tt_scheme);
-	}
-	if (tfp->tf_fileinfo != NULL) {
-		topo_hdl_strfree(hp, pplat);
-		topo_hdl_strfree(hp, pmach);
-		return (0);
-	} else {
-		topo_dprintf(TOPO_DBG_MOD,
-		    "failed to load topology file %s: %s\n",
-		    _topo_path, topo_strerror(topo_hdl_errno(hp)));
-	}
-	topo_hdl_strfree(hp, pplat);
-	topo_hdl_strfree(hp, pmach);
-	(void) snprintf(_topo_path, PATH_MAX, COMMON_TOPO_PATH,
-	    hp->th_rootdir, _topo_file);
-	tfp->tf_fileinfo =
-	    topo_xml_read(tfp->tf_mod, _topo_path, tp->tt_scheme);
-	if (tfp->tf_fileinfo == NULL) {
-		topo_dprintf(TOPO_DBG_MOD,
-		    "failed to load topology file %s: %s\n",
-		    _topo_path, topo_strerror(topo_hdl_errno(hp)));
-		return (topo_hdl_seterrno(hp, ETOPO_FILE_NOENT));
-	}
-	return (0);
-}
-
-int
-topo_file_load(topo_hdl_t *thp, topo_mod_t *mod, ttree_t *tp)
+static void
+topo_file_unload(topo_file_t *tfp)
 {
-	topo_file_t *tfp;
-
-	if ((tfp = topo_hdl_zalloc(thp, sizeof (topo_file_t))) == NULL)
-		return (topo_hdl_seterrno(thp, ETOPO_NOMEM));
-
-	tp->tt_file = tfp;
-
-	tfp->tf_mod = mod;
-
-	if (xml_read(thp, tp) < 0) {
-		topo_file_unload(thp, tp);
-		return (-1);
-	}
-
-	if (topo_xml_enum(tfp->tf_mod, tfp->tf_fileinfo, tp->tt_root) < 0) {
-		topo_dprintf(TOPO_DBG_ERR,
-		    "Failed to enumerate topology: %s\n",
-		    topo_strerror(topo_hdl_errno(thp)));
-		topo_file_unload(thp, tp);
-		return (-1);
-	}
-	return (0);
-}
-
-void
-topo_file_unload(topo_hdl_t *thp, ttree_t *tp)
-{
-	topo_file_t *tfp = tp->tt_file;
 
 	if (tfp == NULL)
 		return;
 
-	if (tfp->tf_fileinfo != NULL)
-		tf_info_free(tfp->tf_mod, tfp->tf_fileinfo);
+	if (tfp->tf_filenm != NULL)
+		topo_mod_strfree(tfp->tf_mod, tfp->tf_filenm);
+
+	if (tfp->tf_tmap != NULL)
+		tf_info_free(tfp->tf_mod, tfp->tf_tmap);
+
+	topo_mod_free(tfp->tf_mod, tfp, sizeof (topo_file_t));
+}
+
+int
+topo_file_load(topo_mod_t *mod, tnode_t *node, const char *name,
+    const char *scheme)
+{
+	topo_file_t *tfp;
+	char fp[MAXNAMELEN];
+
+	if ((tfp = topo_mod_zalloc(mod, sizeof (topo_file_t))) == NULL)
+		return (topo_mod_seterrno(mod, ETOPO_NOMEM));
+
+	tfp->tf_mod = mod;
+
+	if (name != NULL)
+		(void) snprintf(fp, MAXNAMELEN, TOPO_DEFAULT_FILE, name,
+		    scheme);
+	else
+		(void) snprintf(fp, MAXNAMELEN, TOPO_COMMON_FILE, scheme);
 
-	topo_hdl_free(thp, tfp, sizeof (topo_file_t));
-	tp->tt_file = NULL;
+	if ((tfp->tf_filenm = topo_search_path(mod, mod->tm_rootdir, fp))
+	    == NULL) {
+		topo_file_unload(tfp);
+		return (topo_mod_seterrno(mod, ETOPO_MOD_NOENT));
+	}
+
+	if ((tfp->tf_tmap = topo_xml_read(mod, tfp->tf_filenm, scheme))
+	    == NULL) {
+		topo_dprintf(mod->tm_hdl, TOPO_DBG_ERR,
+		    "failed to load topology file %s: "
+		    "%s\n", tfp->tf_filenm, topo_strerror(ETOPO_MOD_XRD));
+		topo_file_unload(tfp);
+		return (topo_mod_seterrno(mod, ETOPO_MOD_XRD));
+	}
+
+	if (topo_xml_enum(mod, tfp->tf_tmap, node) < 0) {
+		topo_dprintf(mod->tm_hdl, TOPO_DBG_ERR,
+		    "Failed to enumerate topology: %s\n",
+		    topo_strerror(ETOPO_MOD_XENUM));
+		topo_file_unload(tfp);
+		return (topo_mod_seterrno(mod, ETOPO_MOD_XENUM));
+	}
+
+	topo_file_unload(tfp);
+
+	return (0);
 }
--- a/usr/src/lib/fm/topo/libtopo/common/topo_file.h	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_file.h	Sat Nov 04 01:18:55 2006 -0800
@@ -35,23 +35,14 @@
 extern "C" {
 #endif
 
-/*
- *  We support loading topology from a file.  The topo_tree routines
- *  don't need to know anymore than to call topo_file_load() to try to
- *  load the topology initially, and topo_file_unload() to clean up.
- */
 typedef struct topo_file {
-	/*
-	 * Currently we directly parse xml into topology nodes.  The
-	 * tf_info_t is created and used by the xml parsing routines.
-	 */
-	tf_info_t *tf_fileinfo;
-	/*
-	 * Module on whose behalf the enumeration-from-file is occuring.
-	 */
-	topo_mod_t *tf_mod;
+	tf_info_t *tf_tmap;		/* topology map file info */
+	char *tf_filenm;		/* topology file name */
+	topo_mod_t *tf_mod;		/* scheme-specific builtin mod */
 } topo_file_t;
 
+extern int topo_file_load(topo_mod_t *, tnode_t *, const char *, const char *);
+
 #ifdef	__cplusplus
 }
 #endif
--- a/usr/src/lib/fm/topo/libtopo/common/topo_fmri.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_fmri.c	Sat Nov 04 01:18:55 2006 -0800
@@ -32,6 +32,7 @@
 #include <sys/fm/protocol.h>
 #include <topo_alloc.h>
 #include <topo_error.h>
+#include <topo_method.h>
 #include <topo_subr.h>
 #include <topo_string.h>
 
@@ -42,7 +43,7 @@
 	if (nvlp != NULL)
 		nvlist_free(nvlp);
 
-	topo_dprintf(TOPO_DBG_ERR, "%s failed: %s\n", method,
+	topo_dprintf(thp, TOPO_DBG_ERR, "%s failed: %s\n", method,
 	    topo_strerror(err));
 
 	*errp = err;
@@ -56,7 +57,7 @@
 	if (nvlp != NULL)
 		nvlist_free(nvlp);
 
-	topo_dprintf(TOPO_DBG_ERR, "%s failed: %s\n", method,
+	topo_dprintf(thp, TOPO_DBG_ERR, "%s failed: %s\n", method,
 	    topo_strerror(err));
 
 	*errp = err;
@@ -99,18 +100,18 @@
 topo_fmri_str2nvl(topo_hdl_t *thp, const char *fmristr, nvlist_t **fmri,
     int *err)
 {
-	char *f, scheme[PATH_MAX];
+	char *f, buf[PATH_MAX];
 	nvlist_t *out = NULL, *in = NULL;
 	tnode_t *rnode;
 
-	(void) strlcpy(scheme, fmristr, sizeof (scheme));
-	if ((f = strrchr(scheme, ':')) == NULL)
+	(void) strlcpy(buf, fmristr, sizeof (buf));
+	if ((f = strchr(buf, ':')) == NULL)
 		return (set_error(thp, ETOPO_FMRI_MALFORM, err,
 		    TOPO_METH_STR2NVL, in));
 
 	*f = '\0'; /* strip trailing FMRI path */
 
-	if ((rnode = topo_hdl_root(thp, scheme)) == NULL)
+	if ((rnode = topo_hdl_root(thp, buf)) == NULL)
 		return (set_error(thp, ETOPO_METHOD_NOTSUP, err,
 		    TOPO_METH_STR2NVL, in));
 
@@ -137,14 +138,41 @@
 	return (0);
 }
 
+/* ARGSUSED */
+static int
+is_present(topo_hdl_t *thp, tnode_t *node, void *data)
+{
+	int err;
+	uint32_t present = 0;
+	nvlist_t *out = NULL;
+	nvlist_t *fmri = (nvlist_t *)data;
+
+	if (topo_method_invoke(node, TOPO_METH_PRESENT,
+	    TOPO_METH_PRESENT_VERSION, fmri, &out, &err) < 0) {
+		if (out != NULL)
+			nvlist_free(out);
+		return (present);
+	}
+
+	(void) nvlist_lookup_uint32(out, TOPO_METH_PRESENT_RET, &present);
+
+	nvlist_free(out);
+
+	return (present);
+}
+
 int
 topo_fmri_present(topo_hdl_t *thp, nvlist_t *fmri, int *err)
 {
-	int rc;
+	int ret = 0;
+	uint32_t present = 0;
 	char *scheme;
 	nvlist_t *out = NULL;
 	tnode_t *rnode;
 
+	if (topo_fmri_invoke(thp, fmri, is_present, fmri, &ret) == 0)
+		return (ret);
+
 	if (nvlist_lookup_string(fmri, FM_FMRI_SCHEME, &scheme) != 0)
 		return (set_error(thp, ETOPO_FMRI_MALFORM, err,
 		    TOPO_METH_PRESENT, out));
@@ -153,11 +181,16 @@
 		return (set_error(thp, ETOPO_METHOD_NOTSUP, err,
 		    TOPO_METH_PRESENT, out));
 
-	if ((rc = topo_method_invoke(rnode, TOPO_METH_PRESENT,
-	    TOPO_METH_PRESENT_VERSION, fmri, &out, err)) < 0)
-		return (set_error(thp, *err, err, TOPO_METH_PRESENT, out));
+	if (topo_method_invoke(rnode, TOPO_METH_PRESENT,
+	    TOPO_METH_PRESENT_VERSION, fmri, &out, err) < 0) {
+		(void) set_error(thp, *err, err, TOPO_METH_PRESENT, out);
+		return (present);
+	}
 
-	return (rc);
+	(void) nvlist_lookup_uint32(out, TOPO_METH_PRESENT_RET, &present);
+	nvlist_free(out);
+
+	return (present);
 }
 
 int
@@ -272,33 +305,17 @@
 int
 topo_fmri_asru(topo_hdl_t *thp, nvlist_t *nvl, nvlist_t **asru, int *err)
 {
-	char *uuid = NULL;
 	struct rsrc r;
 
-	if (thp->th_uuid == NULL) {
-		if ((uuid = topo_snap_hold(thp, NULL, err)) == NULL)
-			return (set_error(thp, *err, err, "topo_fmri_asru",
-			    NULL));
-	}
-
 	r.rs_flag = 0;
 	r.rs_err = 0;
 	r.rs_priv = nvl;
 	r.rs_fprop = asru;
 	if (topo_fmri_invoke(thp, nvl, get_prop, &r, err) < 0) {
-		if (uuid != NULL) {
-			topo_hdl_strfree(thp, uuid);
-			topo_snap_release(thp);
-		}
 
 		return (set_error(thp, *err, err, "topo_fmri_asru", NULL));
 	}
 
-	if (uuid != NULL) {
-		topo_hdl_strfree(thp, uuid);
-		topo_snap_release(thp);
-	}
-
 	return (0);
 }
 
@@ -306,33 +323,17 @@
 topo_fmri_fru(topo_hdl_t *thp, nvlist_t *nvl, nvlist_t **fru,
     int *err)
 {
-	char *uuid = NULL;
 	struct rsrc r;
 
-	if (thp->th_uuid == NULL) {
-		if ((uuid = topo_snap_hold(thp, NULL, err)) == NULL)
-			return (set_error(thp, *err, err, "topo_fmri_fru",
-			    NULL));
-	}
-
 	r.rs_flag = 1;
 	r.rs_err = 0;
 	r.rs_priv = nvl;
 	r.rs_fprop = fru;
 	if (topo_fmri_invoke(thp, nvl, get_prop, &r, err) < 0) {
-		if (uuid != NULL) {
-			topo_hdl_strfree(thp, uuid);
-			topo_snap_release(thp);
-		}
 
 		return (set_error(thp, *err, err, "topo_fmri_fru", NULL));
 	}
 
-	if (uuid != NULL) {
-		topo_hdl_strfree(thp, uuid);
-		topo_snap_release(thp);
-	}
-
 	return (0);
 }
 
@@ -380,7 +381,7 @@
 struct topo_lookup {
 	nvlist_t *tl_resource;
 	topo_walk_cb_t tl_func;
-	int tl_err;
+	int tl_ret;
 	void *tl_pdata;
 };
 
@@ -391,48 +392,51 @@
 	struct topo_lookup *tlp = (struct topo_lookup *)pdata;
 	nvlist_t *r1, *r2 = tlp->tl_resource;
 
-	if (topo_node_resource(node, &r1, &tlp->tl_err) != 0)
+	if (topo_node_resource(node, &r1, &tlp->tl_ret) != 0)
 		return (TOPO_WALK_ERR);
 
-	rc = topo_fmri_compare(thp, r1, r2, &tlp->tl_err);
+	rc = topo_fmri_compare(thp, r1, r2, &tlp->tl_ret);
 	nvlist_free(r1);
 	if (rc == 0)
 		return (TOPO_WALK_NEXT);
 	else if (rc == -1)
 		return (TOPO_WALK_ERR);
 
-	tlp->tl_err = tlp->tl_func(thp, node, tlp->tl_pdata);
+	tlp->tl_ret = tlp->tl_func(thp, node, tlp->tl_pdata);
 
 	return (TOPO_WALK_TERMINATE);
 }
 
 int
 topo_fmri_invoke(topo_hdl_t *thp, nvlist_t *nvl, topo_walk_cb_t cb_f,
-    void *pdata, int *err)
+    void *pdata, int *ret)
 {
+	int err;
 	topo_walk_t *wp;
 	char *scheme;
 	struct topo_lookup tl;
 
-	if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &scheme)	 != 0)
-		return (set_error(thp, ETOPO_METHOD_INVAL, err,
+	if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &scheme)   != 0)
+		return (set_error(thp, ETOPO_METHOD_INVAL, ret,
 		    "topo_fmri_invoke", NULL));
 
 	tl.tl_resource = nvl;
 	tl.tl_func = cb_f;
 	tl.tl_pdata = pdata;
-	tl.tl_err = 0;
-	if ((wp = topo_walk_init(thp, scheme, walk_lookup, &tl, err)) == NULL)
-		return (set_error(thp, *err, err, "topo_fmri_invoke", NULL));
+	tl.tl_ret = 0;
+	if ((wp = topo_walk_init(thp, scheme, walk_lookup, &tl, &err)) == NULL)
+		return (set_error(thp, err, ret, "topo_fmri_invoke", NULL));
 
-	(void) topo_walk_step(wp, TOPO_WALK_CHILD);
+	err = topo_walk_step(wp, TOPO_WALK_CHILD);
 	topo_walk_fini(wp);
 
-	if (tl.tl_err != 0) {
-		*err = tl.tl_err;
+	if (err == TOPO_WALK_ERR) {
+		*ret = err;
 		return (-1);
 	}
 
+	*ret = tl.tl_ret;
+
 	return (0);
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_hc.h	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,87 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _TOPO_HC_H
+#define	_TOPO_HC_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * Allowable hardware component names for hc FMRIs
+ */
+#define	CMP		"CMP"
+#define	CENTERPLANE	"centerplane"
+#define	CHASSIS		"chassis"
+#define	CHIP		"chip"
+#define	CHIP_SELECT	"chip-select"
+#define	CPU		"cpu"
+#define	DIMM		"dimm"
+#define	DISK		"disk"
+#define	DRAMCHANNEL	"dram-channel"
+#define	HOSTBRIDGE	"hostbridge"
+#define	INTERCONNECT	"interconnect"
+#define	IOBOARD		"ioboard"
+#define	MEMORYCONTROL	"memory-controller"
+#define	MOTHERBOARD	"motherboard"
+#define	PCI_BUS		"pcibus"
+#define	PCI_DEVICE	"pcidev"
+#define	PCI_FUNCTION    "pcifn"
+#define	PCIEX_BUS	"pciexbus"
+#define	PCIEX_DEVICE	"pciexdev"
+#define	PCIEX_FUNCTION  "pciexfn"
+#define	PCIEX_ROOT	"pciexrc"
+#define	PCIEX_SWUP	"pciexswu"
+#define	PCIEX_SWDWN	"pciexswd"
+#define	RANK		"rank"
+#define	SATA_PORT	"sata-port"
+#define	SYSTEMBOARD	"systemboard"
+
+/*
+ * Allowable hc node property group and property names
+ */
+#define	TOPO_PGROUP_IO		"io"
+#define	TOPO_IO_DEVTYPE		"devtype"
+#define	TOPO_IO_DRIVER		"driver"
+#define	TOPO_IO_DEV		"dev"
+#define	TOPO_IO_DEV_PATH	"devfs-path"
+#define	TOPO_IO_AP_PATH		"ap-path"
+
+#define	TOPO_PGROUP_PCI		"pci"
+#define	TOPO_PCI_VENDID		"vendor-id"
+#define	TOPO_PCI_DEVID		"device-id"
+#define	TOPO_PCI_EXCAP		"extended-capabilities"
+#define	TOPO_PCI_BDF		"BDF"
+#define	TOPO_PCI_CLASS		"class-code"
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _TOPO_HC_H */
--- a/usr/src/lib/fm/topo/libtopo/common/topo_method.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_method.c	Sat Nov 04 01:18:55 2006 -0800
@@ -99,7 +99,8 @@
 		topo_mod_free(mod, mp, sizeof (topo_imethod_t));
 	}
 
-	topo_dprintf(TOPO_DBG_ERR, "method registration failed for %s: %s\n",
+	topo_dprintf(mod->tm_hdl, TOPO_DBG_ERR,
+	    "method registration failed for %s: %s\n",
 	    mod->tm_name, topo_strerror(err));
 
 	return (topo_mod_seterrno(mod, err));
@@ -150,7 +151,8 @@
 		topo_list_append(&node->tn_methods, imp);
 		topo_node_unlock(node);
 
-		topo_dprintf(TOPO_DBG_MOD, "registered module %s method "
+		topo_dprintf(mod->tm_hdl, TOPO_DBG_MODSVC,
+		    "registered module %s method "
 		    "%s for %s=%d\n", mod->tm_name, imp->tim_name,
 		    topo_node_name(node), topo_node_instance(node));
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_method.h	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,83 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _TOPO_METHOD_H
+#define	_TOPO_METHOD_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * FMRI methods
+ */
+#define	TOPO_METH_ASRU_COMPUTE		"topo_asru_compute"
+#define	TOPO_METH_FRU_COMPUTE		"topo_fru_compute"
+#define	TOPO_METH_FMRI			"topo_fmri"
+#define	TOPO_METH_NVL2STR		"topo_nvl2str"
+#define	TOPO_METH_STR2NVL		"topo_str2nvl"
+#define	TOPO_METH_CONTAINS		"topo_contains"
+#define	TOPO_METH_UNUSABLE		"topo_unusable"
+#define	TOPO_METH_EXPAND		"topo_expand"
+#define	TOPO_METH_COMPARE		"topo_compare"
+
+#define	TOPO_METH_FMRI_VERSION			0
+#define	TOPO_METH_FRU_COMPUTE_VERSION		0
+#define	TOPO_METH_ASRU_COMPUTE_VERSION		0
+#define	TOPO_METH_NVL2STR_VERSION		0
+#define	TOPO_METH_STR2NVL_VERSION		0
+#define	TOPO_METH_CONTAINS_VERSION		0
+#define	TOPO_METH_UNUSABLE_VERSION		0
+#define	TOPO_METH_EXPAND_VERSION		0
+#define	TOPO_METH_COMPARE_VERSION		0
+
+#define	TOPO_METH_ASRU_COMPUTE_DESC		"Dynamic ASRU constructor"
+#define	TOPO_METH_FRU_COMPUTE_DESC		"Dynamic FRU constructor"
+#define	TOPO_METH_FMRI_DESC			"Dynamic FMRI constructor"
+#define	TOPO_METH_NVL2STR_DESC			"FMRI to string"
+#define	TOPO_METH_STR2NVL_DESC			"string to FMRI"
+#define	TOPO_METH_CONTAINS_DESC			"FMRI contains sub-FMRI"
+#define	TOPO_METH_UNUSABLE_DESC			"FMRI is unusable"
+#define	TOPO_METH_EXPAND_DESC			"expand FMRI"
+#define	TOPO_METH_COMPARE_DESC			"compare two FMRIs"
+
+#define	TOPO_METH_FMRI_ARG_NAME		"child-name"
+#define	TOPO_METH_FMRI_ARG_INST		"child-inst"
+#define	TOPO_METH_FMRI_ARG_NVL		"args"
+#define	TOPO_METH_FMRI_ARG_PARENT	"parent-fmri"
+#define	TOPO_METH_FMRI_ARG_AUTH		"auth"
+#define	TOPO_METH_FMRI_ARG_PART		"part"
+#define	TOPO_METH_FMRI_ARG_REV		"rev"
+#define	TOPO_METH_FMRI_ARG_SER		"serial"
+#define	TOPO_METH_FMRI_ARG_HCS		"hc-specific"
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _TOPO_METHOD_H */
--- a/usr/src/lib/fm/topo/libtopo/common/topo_mod.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_mod.c	Sat Nov 04 01:18:55 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -70,50 +69,59 @@
 #include <alloca.h>
 #include <unistd.h>
 #include <stdio.h>
+#include <sys/param.h>
+#include <sys/utsname.h>
+#include <sys/smbios.h>
+#include <sys/fm/protocol.h>
 
-#include <topo_module.h>
 #include <topo_alloc.h>
+#include <topo_error.h>
+#include <topo_file.h>
+#include <topo_module.h>
+#include <topo_method.h>
 #include <topo_string.h>
-#include <topo_error.h>
 #include <topo_subr.h>
+#include <topo_tree.h>
+
+#define	PLUGIN_PATH	"plugins"
+#define	PLUGIN_PATH_LEN	MAXNAMELEN + 5
 
 topo_mod_t *
-topo_mod_load(topo_mod_t *pmod, const char *path)
+topo_mod_load(topo_mod_t *pmod, const char *name,
+    topo_version_t version)
 {
-	int err = 0;
-	char *p;
+	char *path;
+	char file[PLUGIN_PATH_LEN];
 	topo_mod_t *mod = NULL;
 	topo_hdl_t *thp;
 
 	thp = pmod->tm_hdl;
 
 	/*
-	 * Already loaded, bump the ref count
+	 * Already loaded, topo_mod_lookup will bump the ref count
 	 */
-	if ((mod = topo_mod_lookup(thp, path)) != NULL) {
-		topo_mod_hold(mod);
+	if ((mod = topo_mod_lookup(thp, name, 1)) != NULL) {
+		if (mod->tm_info->tmi_version != version) {
+			topo_mod_rele(mod);
+			(void) topo_mod_seterrno(pmod, ETOPO_MOD_VER);
+			return (NULL);
+		}
 		return (mod);
 	}
 
-	/*
-	 * Check for a valid path
-	 */
-	if (access(path, F_OK) != 0) {
-		(void) topo_mod_seterrno(pmod, ETOPO_MOD_NOENT);
-		return (NULL);
+	(void) snprintf(file, PLUGIN_PATH_LEN, "%s/%s.so",
+	    PLUGIN_PATH, name);
+	path = topo_search_path(pmod, thp->th_rootdir, (const char *)file);
+	if (path == NULL ||
+	    (mod = topo_modhash_load(thp, name, path, &topo_rtld_ops, version))
+	    == NULL) { /* returned with mod held */
+			topo_mod_strfree(pmod, path);
+			(void) topo_mod_seterrno(pmod, topo_hdl_errno(thp) ?
+			    topo_hdl_errno(thp) : ETOPO_MOD_NOENT);
+			return (NULL);
 	}
 
-	if ((p = strrchr(path, '.')) != NULL && strcmp(p, ".so") == 0) {
-		if ((mod = topo_modhash_load(thp, path,
-		    &topo_rtld_ops)) == NULL) { /* returned with mod held */
-			(void) topo_mod_seterrno(pmod, err ? err :
-			    ETOPO_MOD_NOENT);
-			return (NULL);
-		}
-	} else {
-		(void) topo_mod_seterrno(pmod, err ? err : ETOPO_MOD_NOENT);
-		return (NULL);
-	}
+	topo_mod_strfree(pmod, path);
 
 	return (mod);
 }
@@ -130,49 +138,48 @@
 	if (mod->tm_info != NULL)
 		topo_mod_unregister(mod);
 
-	topo_dprintf(TOPO_DBG_ERR, "module registration failed for %s: %s\n",
+	topo_dprintf(mod->tm_hdl, TOPO_DBG_ERR,
+	    "module registration failed for %s: %s\n",
 	    mod->tm_name, topo_strerror(err));
 
 	return (topo_mod_seterrno(mod, err));
 }
 
 int
-topo_mod_register(topo_mod_t *mod, const topo_modinfo_t *mip, void *priv)
+topo_mod_register(topo_mod_t *mod, const topo_modinfo_t *mip,
+    topo_version_t version)
 {
 
 	assert(!(mod->tm_flags & TOPO_MOD_FINI ||
 	    mod->tm_flags & TOPO_MOD_REG));
 
-	if (mod->tm_version > mip->tmi_version)
-		return (set_register_error(mod, ETOPO_VER_OLD));
-	if (mod->tm_version < mip->tmi_version)
-		return (set_register_error(mod, ETOPO_VER_NEW));
+	if (version != TOPO_VERSION)
+		return (set_register_error(mod, EMOD_VER_ABI));
 
-	if ((mod->tm_info = topo_mod_alloc(mod, sizeof (topo_modinfo_t)))
+	if ((mod->tm_info = topo_mod_alloc(mod, sizeof (topo_imodinfo_t)))
 	    == NULL)
-		return (set_register_error(mod, ETOPO_NOMEM));
+		return (set_register_error(mod, EMOD_NOMEM));
+	if ((mod->tm_info->tmi_ops = topo_mod_alloc(mod,
+	    sizeof (topo_modops_t))) == NULL)
+		return (set_register_error(mod, EMOD_NOMEM));
 
 	mod->tm_info->tmi_desc = topo_mod_strdup(mod, mip->tmi_desc);
 	if (mod->tm_info->tmi_desc == NULL)
-		return (set_register_error(mod, ETOPO_NOMEM));
+		return (set_register_error(mod, EMOD_NOMEM));
+
+	mod->tm_info->tmi_scheme = topo_mod_strdup(mod, mip->tmi_scheme);
+	if (mod->tm_info->tmi_scheme == NULL)
+		return (set_register_error(mod, EMOD_NOMEM));
+
 
 	mod->tm_info->tmi_version = (topo_version_t)mip->tmi_version;
-	mod->tm_info->tmi_enum = mip->tmi_enum;
-	mod->tm_info->tmi_release = mip->tmi_release;
+	mod->tm_info->tmi_ops->tmo_enum = mip->tmi_ops->tmo_enum;
+	mod->tm_info->tmi_ops->tmo_release = mip->tmi_ops->tmo_release;
 
 	mod->tm_flags |= TOPO_MOD_REG;
-	mod->tm_priv = priv;
 
-	if (mod == NULL) {
-		topo_dprintf(TOPO_DBG_MOD, "registration succeeded for %s\n",
-		    mod->tm_name);
-
-		return (0);
-	}
-
-
-	topo_dprintf(TOPO_DBG_MOD, "registration succeeded for %s\n",
-	    mod->tm_name);
+	topo_dprintf(mod->tm_hdl, TOPO_DBG_MODSVC,
+	    "registration succeeded for %s\n", mod->tm_name);
 
 	return (0);
 }
@@ -190,40 +197,47 @@
 	if (mod->tm_info == NULL)
 		return;
 
+	if (mod->tm_info->tmi_ops != NULL)
+		topo_mod_free(mod, mod->tm_info->tmi_ops,
+		    sizeof (topo_modops_t));
 	if (mod->tm_info->tmi_desc != NULL)
 		topo_mod_strfree(mod, mod->tm_info->tmi_desc);
+	if (mod->tm_info->tmi_scheme != NULL)
+		topo_mod_strfree(mod, mod->tm_info->tmi_scheme);
 
-	topo_mod_free(mod, mod->tm_info, sizeof (topo_modinfo_t));
+	topo_mod_free(mod, mod->tm_info, sizeof (topo_imodinfo_t));
 
 	mod->tm_info = NULL;
 }
 
 int
 topo_mod_enumerate(topo_mod_t *mod, tnode_t *node, const char *enum_name,
-    const char *name, topo_instance_t min, topo_instance_t max)
+    const char *name, topo_instance_t min, topo_instance_t max, void *data)
 {
 	int err = 0;
 	topo_mod_t *enum_mod;
 
 	assert(mod->tm_flags & TOPO_MOD_REG);
 
-	if ((enum_mod = topo_mod_lookup(mod->tm_hdl, enum_name)) == NULL)
-		return (topo_mod_seterrno(mod, ETOPO_MOD_NOENT));
+	if ((enum_mod = topo_mod_lookup(mod->tm_hdl, enum_name, 0)) == NULL)
+		return (topo_mod_seterrno(mod, EMOD_MOD_NOENT));
 
 	topo_node_hold(node);
 
-	topo_dprintf(TOPO_DBG_MOD, "module %s enumerating node %s=%d\n",
-	    (char *)mod->tm_name, (char *)node->tn_name, node->tn_instance);
+	topo_dprintf(mod->tm_hdl, TOPO_DBG_MODSVC, "module %s enumerating "
+	    "node %s=%d\n", (char *)mod->tm_name, (char *)node->tn_name,
+	    node->tn_instance);
 
 	topo_mod_enter(enum_mod);
-	err = enum_mod->tm_info->tmi_enum(enum_mod, node, name, min, max,
-	    enum_mod->tm_priv);
+	err = enum_mod->tm_info->tmi_ops->tmo_enum(enum_mod, node, name, min,
+	    max, enum_mod->tm_priv, data);
 	topo_mod_exit(enum_mod);
 
 	if (err != 0) {
-		(void) topo_mod_seterrno(mod, ETOPO_MODULE);
+		(void) topo_mod_seterrno(mod, EMOD_UKNOWN_ENUM);
 
-		topo_dprintf(TOPO_DBG_ERR, "module %s failed enumeration for "
+		topo_dprintf(mod->tm_hdl, TOPO_DBG_ERR,
+		    "module %s failed enumeration for "
 		    " node %s=%d\n", (char *)mod->tm_name,
 		    (char *)node->tn_name, node->tn_instance);
 
@@ -236,28 +250,339 @@
 	return (0);
 }
 
-char *
-topo_mod_rootdir(topo_mod_t *mod)
+int
+topo_mod_enummap(topo_mod_t *mod, tnode_t *node, const char *name,
+    const char *scheme)
+{
+	return (topo_file_load(mod, node, (char *)name, (char *)scheme));
+}
+
+static nvlist_t *
+set_fmri_err(topo_mod_t *mod, int err)
+{
+	(void) topo_mod_seterrno(mod, err);
+	return (NULL);
+}
+
+nvlist_t *
+topo_mod_hcfmri(topo_mod_t *mod, tnode_t *pnode, int version, const char *name,
+    topo_instance_t inst, nvlist_t *hc_specific, nvlist_t *auth,
+    const char *part, const char *rev, const char *serial)
 {
-	return (mod->tm_rootdir);
+	int err;
+	nvlist_t *pfmri = NULL, *fmri = NULL, *args = NULL;
+	nvlist_t *nfp = NULL;
+
+	if (version != FM_HC_SCHEME_VERSION)
+		return (set_fmri_err(mod, EMOD_FMRI_VERSION));
+
+	/*
+	 * Do we have any args to pass?
+	 */
+	if (pnode != NULL || auth != NULL || part != NULL || rev != NULL ||
+	    serial != NULL || hc_specific != NULL) {
+		if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0)
+		    return (set_fmri_err(mod, EMOD_FMRI_NVL));
+	}
+
+	if (pnode != NULL) {
+		if (topo_node_resource(pnode, &pfmri, &err) < 0)
+			return (set_fmri_err(mod, EMOD_NVL_INVAL));
+
+		if (nvlist_add_nvlist(args, TOPO_METH_FMRI_ARG_PARENT,
+		    pfmri) != 0) {
+			nvlist_free(pfmri);
+			nvlist_free(args);
+			return (set_fmri_err(mod, EMOD_FMRI_NVL));
+		}
+		nvlist_free(pfmri);
+	}
+
+	/*
+	 * Add optional payload
+	 */
+	if (auth != NULL)
+		(void) nvlist_add_nvlist(args, TOPO_METH_FMRI_ARG_AUTH, auth);
+	if (part != NULL)
+		(void) nvlist_add_string(args, TOPO_METH_FMRI_ARG_PART, part);
+	if (rev != NULL)
+		(void) nvlist_add_string(args, TOPO_METH_FMRI_ARG_REV, rev);
+	if (serial != NULL)
+		(void) nvlist_add_string(args, TOPO_METH_FMRI_ARG_SER,
+		    serial);
+	if (hc_specific != NULL)
+		(void) nvlist_add_nvlist(args, TOPO_METH_FMRI_ARG_HCS,
+		    hc_specific);
+
+	if ((fmri = topo_fmri_create(mod->tm_hdl, FM_FMRI_SCHEME_HC, name, inst,
+	    args, &err)) == NULL) {
+		nvlist_free(args);
+		return (set_fmri_err(mod, err));
+	}
+
+	nvlist_free(args);
+
+	(void) topo_mod_nvdup(mod, fmri, &nfp);
+	nvlist_free(fmri);
+
+	return (nfp);
+}
+
+nvlist_t *
+topo_mod_devfmri(topo_mod_t *mod, int version, const char *dev_path,
+    const char *devid)
+{
+	int err;
+	nvlist_t *fmri, *args;
+	nvlist_t *nfp = NULL;
+
+	if (version != FM_DEV_SCHEME_VERSION)
+		return (set_fmri_err(mod, EMOD_FMRI_VERSION));
+
+	if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0)
+		return (set_fmri_err(mod, EMOD_FMRI_NVL));
+
+	if (nvlist_add_string(args, FM_FMRI_DEV_PATH, dev_path) != 0) {
+		nvlist_free(args);
+		return (set_fmri_err(mod, EMOD_FMRI_NVL));
+	}
+
+	(void) nvlist_add_string(args, FM_FMRI_DEV_ID, devid);
+
+	if ((fmri = topo_fmri_create(mod->tm_hdl, FM_FMRI_SCHEME_DEV,
+	    FM_FMRI_SCHEME_DEV, 0, args, &err)) == NULL) {
+		nvlist_free(args);
+		return (set_fmri_err(mod, err));
+	}
+
+	nvlist_free(args);
+
+	(void) topo_mod_nvdup(mod, fmri, &nfp);
+	nvlist_free(fmri);
+
+	return (nfp);
 }
 
-topo_hdl_t *
-topo_mod_handle(topo_mod_t *mod)
+nvlist_t *
+topo_mod_cpufmri(topo_mod_t *mod, int version, uint32_t cpu_id, uint8_t cpumask,
+    const char *serial)
+{
+	int err;
+	nvlist_t *fmri = NULL, *args = NULL;
+	nvlist_t *nfp = NULL;
+
+	if (version != FM_CPU_SCHEME_VERSION)
+		return (set_fmri_err(mod, EMOD_FMRI_VERSION));
+
+	if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0)
+		return (set_fmri_err(mod, EMOD_FMRI_NVL));
+
+	if (nvlist_add_uint32(args, FM_FMRI_CPU_ID, cpu_id) != 0) {
+		nvlist_free(args);
+		return (set_fmri_err(mod, EMOD_FMRI_NVL));
+	}
+
+	/*
+	 * Add optional payload
+	 */
+	(void) nvlist_add_uint8(args, FM_FMRI_CPU_MASK, cpumask);
+	(void) nvlist_add_string(args, FM_FMRI_CPU_SERIAL_ID, serial);
+
+	if ((fmri = topo_fmri_create(mod->tm_hdl, FM_FMRI_SCHEME_CPU,
+	    FM_FMRI_SCHEME_CPU, 0, args, &err)) == NULL) {
+		nvlist_free(args);
+		return (set_fmri_err(mod, err));
+	}
+
+	nvlist_free(args);
+
+	(void) topo_mod_nvdup(mod, fmri, &nfp);
+	nvlist_free(fmri);
+
+	return (nfp);
+}
+
+nvlist_t *
+topo_mod_memfmri(topo_mod_t *mod, int version, uint64_t pa, uint64_t offset,
+	const char *unum, int flags)
+{
+	int err;
+	nvlist_t *args = NULL, *fmri = NULL;
+	nvlist_t *nfp = NULL;
+
+	if (version != FM_MEM_SCHEME_VERSION)
+		return (set_fmri_err(mod, EMOD_FMRI_VERSION));
+
+	if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0)
+		return (set_fmri_err(mod, EMOD_FMRI_NVL));
+
+	err = nvlist_add_string(args, FM_FMRI_MEM_UNUM, unum);
+		nvlist_free(args);
+	if (flags & TOPO_MEMFMRI_PA)
+		err |= nvlist_add_uint64(args, FM_FMRI_MEM_PHYSADDR, pa);
+	if (flags & TOPO_MEMFMRI_OFFSET)
+		err |= nvlist_add_uint64(args, FM_FMRI_MEM_OFFSET, offset);
+
+	if (err != 0) {
+		nvlist_free(args);
+		return (set_fmri_err(mod, EMOD_FMRI_NVL));
+	}
+
+	if ((fmri = topo_fmri_create(mod->tm_hdl, FM_FMRI_SCHEME_MEM,
+	    FM_FMRI_SCHEME_MEM, 0, args, &err)) == NULL) {
+		nvlist_free(args);
+		return (set_fmri_err(mod, err));
+	}
+
+	nvlist_free(args);
+
+	(void) topo_mod_nvdup(mod, fmri, &nfp);
+	nvlist_free(fmri);
+
+	return (nfp);
+
+}
+
+nvlist_t *
+topo_mod_pkgfmri(topo_mod_t *mod, int version, const char *path)
 {
-	return (mod->tm_hdl);
+	int err;
+	nvlist_t *fmri = NULL, *args = NULL;
+	nvlist_t *nfp = NULL;
+
+	if (version != FM_PKG_SCHEME_VERSION)
+		return (set_fmri_err(mod, EMOD_FMRI_VERSION));
+
+	if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0)
+		return (set_fmri_err(mod, EMOD_FMRI_NVL));
+
+	if (nvlist_add_string(args, "path", path) != 0) {
+		nvlist_free(args);
+		return (set_fmri_err(mod, EMOD_FMRI_NVL));
+	}
+
+	if ((fmri = topo_fmri_create(mod->tm_hdl, FM_FMRI_SCHEME_CPU,
+	    FM_FMRI_SCHEME_CPU, 0, args, &err)) == NULL) {
+		nvlist_free(args);
+		return (set_fmri_err(mod, err));
+	}
+
+	nvlist_free(args);
+
+	(void) topo_mod_nvdup(mod, fmri, &nfp);
+	nvlist_free(fmri);
+
+	return (nfp);
+}
+
+nvlist_t *
+topo_mod_modfmri(topo_mod_t *mod, int version, const char *driver)
+{
+	int err;
+	nvlist_t *fmri = NULL, *args = NULL;
+	nvlist_t *nfp = NULL;
+
+	if (version != FM_MOD_SCHEME_VERSION)
+		return (set_fmri_err(mod, EMOD_FMRI_VERSION));
+
+	if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0)
+		return (set_fmri_err(mod, EMOD_FMRI_NVL));
+
+	if (nvlist_add_string(args, "DRIVER", driver) != 0) {
+		nvlist_free(args);
+		return (set_fmri_err(mod, EMOD_FMRI_NVL));
+	}
+
+	if ((fmri = topo_fmri_create(mod->tm_hdl, FM_FMRI_SCHEME_CPU,
+	    FM_FMRI_SCHEME_CPU, 0, args, &err)) == NULL) {
+		nvlist_free(args);
+		return (set_fmri_err(mod, err));
+	}
+
+	nvlist_free(args);
+
+	(void) topo_mod_nvdup(mod, fmri, &nfp);
+	nvlist_free(fmri);
+
+	return (nfp);
+}
+
+int
+topo_mod_str2nvl(topo_mod_t *mod, const char *fmristr, nvlist_t **fmri)
+{
+	int err;
+	nvlist_t *np = NULL;
+
+	if (topo_fmri_str2nvl(mod->tm_hdl, fmristr, &np, &err) < 0)
+		return (topo_mod_seterrno(mod, err));
+
+	if (topo_mod_nvdup(mod, np, fmri) < 0) {
+		nvlist_free(np);
+		return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
+	}
+
+	nvlist_free(np);
+
+	return (0);
+}
+
+int
+topo_mod_nvl2str(topo_mod_t *mod, nvlist_t *fmri, char **fmristr)
+{
+	int err;
+	char *sp;
+
+	if (topo_fmri_nvl2str(mod->tm_hdl, fmri, &sp, &err) < 0)
+		return (topo_mod_seterrno(mod, err));
+
+	if ((*fmristr = topo_mod_strdup(mod, sp)) == NULL) {
+		topo_hdl_strfree(mod->tm_hdl, sp);
+		return (topo_mod_seterrno(mod, EMOD_NOMEM));
+	}
+
+	topo_hdl_strfree(mod->tm_hdl, sp);
+
+	return (0);
 }
 
 void *
-topo_mod_private(topo_mod_t *mod)
+topo_mod_getspecific(topo_mod_t *mod)
 {
 	return (mod->tm_priv);
 }
 
 void
-topo_mod_setdebug(topo_mod_t *mod, int mask)
+topo_mod_setspecific(topo_mod_t *mod, void *data)
+{
+	mod->tm_priv = data;
+}
+
+void
+topo_mod_setdebug(topo_mod_t *mod)
+{
+	mod->tm_debug = 1;
+}
+
+di_node_t
+topo_mod_devinfo(topo_mod_t *mod)
 {
-	mod->tm_debug |= mask;
+	topo_hdl_t *thp = mod->tm_hdl;
+
+	if (thp->th_di == DI_NODE_NIL)
+		thp->th_di = di_init("/", DINFOCPYALL);
+
+	return (thp->th_di);
+}
+
+di_prom_handle_t
+topo_mod_prominfo(topo_mod_t *mod)
+{
+	topo_hdl_t *thp = mod->tm_hdl;
+
+	if (thp->th_pi == DI_PROM_HANDLE_NIL)
+		thp->th_pi = di_prom_init();
+
+	return (thp->th_pi);
 }
 
 void
@@ -270,12 +595,132 @@
 void
 topo_mod_dprintf(topo_mod_t *mod, const char *format, ...)
 {
-	if (mod->tm_debug & mod->tm_hdl->th_debug) {
-		va_list alist;
+	va_list alist;
+
+	if (mod->tm_debug == 0)
+		return;
+
+	va_start(alist, format);
+	topo_vdprintf(mod->tm_hdl, TOPO_DBG_MOD, (const char *)mod->tm_name,
+	    format, alist);
+	va_end(alist);
+}
+
+static char *
+topo_mod_product(topo_mod_t *mod)
+{
+	return (topo_mod_strdup(mod, mod->tm_hdl->th_product));
+}
+
+static char *
+topo_mod_server(topo_mod_t *mod)
+{
+	static struct utsname uts;
+
+	(void) uname(&uts);
+	return (topo_mod_strdup(mod, uts.nodename));
+}
+
+static char *
+topo_mod_csn(topo_mod_t *mod)
+{
+	char csn[MAXNAMELEN];
+	di_prom_handle_t promh = DI_PROM_HANDLE_NIL;
+	di_node_t rooth = DI_NODE_NIL;
+	char *bufp, *str;
+	smbios_hdl_t *shp;
+	smbios_system_t s1;
+	smbios_info_t s2;
+	id_t id;
+
+	if ((shp = smbios_open(NULL, SMB_VERSION, 0, NULL)) != NULL) {
+		if ((id = smbios_info_system(shp, &s1)) != SMB_ERR &&
+		    smbios_info_common(shp, id, &s2) != SMB_ERR) {
+			(void) strlcpy(csn, s2.smbi_serial, MAXNAMELEN);
+		}
+		smbios_close(shp);
+
+		if (strcmp(csn, SMB_DEFAULT1) == 0 ||
+		    strcmp(csn, SMB_DEFAULT2) == 0)
+			return (NULL);
+
+		/*
+		 * Terminate CSN at the first white space
+		 */
+		if ((str = strchr(csn, ' ')) != NULL)
+			*str = '\0';
 
-		va_start(alist, format);
-		(void) fputs("libtopo DEBUG: ", stderr);
-		(void) vfprintf(stderr, format, alist);
-		va_end(alist);
+	} else if ((rooth = topo_mod_devinfo(mod)) != DI_NODE_NIL &&
+	    (promh = topo_mod_prominfo(mod)) != DI_PROM_HANDLE_NIL) {
+		if (di_prom_prop_lookup_bytes(promh, rooth, "chassis-sn",
+		    (unsigned char **)&bufp) != -1) {
+			(void) strlcpy(csn, bufp, MAXNAMELEN);
+		} else {
+			return (NULL);
+		}
+	} else {
+		return (NULL);
 	}
+
+	return (topo_mod_strdup(mod, csn));
 }
+
+nvlist_t *
+topo_mod_auth(topo_mod_t *mod, tnode_t *pnode)
+{
+	int err;
+	char *prod = NULL;
+	char *csn = NULL;
+	char *server = NULL;
+	nvlist_t *auth;
+
+	(void) topo_prop_get_string(pnode, FM_FMRI_AUTHORITY,
+	    FM_FMRI_AUTH_PRODUCT, &prod, &err);
+	(void) topo_prop_get_string(pnode, FM_FMRI_AUTHORITY,
+	    FM_FMRI_AUTH_CHASSIS, &csn, &err);
+	(void) topo_prop_get_string(pnode, FM_FMRI_AUTHORITY,
+	    FM_FMRI_AUTH_SERVER, &server, &err);
+
+	/*
+	 * Let's do this the hard way
+	 */
+	if (prod == NULL)
+		prod = topo_mod_product(mod);
+	if (csn == NULL)
+		csn = topo_mod_csn(mod);
+	if (server == NULL) {
+		server = topo_mod_server(mod);
+	}
+
+	/*
+	 * No luck, return NULL
+	 */
+	if (!prod && !server && !csn)
+		return (NULL);
+
+	if ((err = topo_mod_nvalloc(mod, &auth, NV_UNIQUE_NAME)) != 0) {
+		(void) topo_mod_seterrno(mod, EMOD_FMRI_NVL);
+		return (NULL);
+	}
+
+	if (prod != NULL) {
+		err |= nvlist_add_string(auth, FM_FMRI_AUTH_PRODUCT, prod);
+		topo_mod_strfree(mod, prod);
+	}
+	if (server != NULL) {
+		err |= nvlist_add_string(auth, FM_FMRI_AUTH_SERVER, server);
+		topo_mod_strfree(mod, server);
+	}
+	if (csn != NULL) {
+		err |= nvlist_add_string(auth, FM_FMRI_AUTH_CHASSIS, csn);
+		topo_mod_strfree(mod, csn);
+	}
+
+	if (err != 0) {
+		nvlist_free(auth);
+		(void) topo_mod_seterrno(mod, EMOD_NVL_INVAL);
+		return (NULL);
+	}
+
+	return (auth);
+}
--- a/usr/src/lib/fm/topo/libtopo/common/topo_mod.h	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_mod.h	Sat Nov 04 01:18:55 2006 -0800
@@ -30,7 +30,9 @@
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 #include <fm/libtopo.h>
+#include <fm/topo_hc.h>
 #include <libnvpair.h>
+#include <libdevinfo.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -44,7 +46,7 @@
 typedef int topo_method_f(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
     nvlist_t **);
 typedef int topo_enum_f(topo_mod_t *, tnode_t *, const char *, topo_instance_t,
-    topo_instance_t, void *);
+    topo_instance_t, void *, void *);
 typedef void topo_release_f(topo_mod_t *, tnode_t *);
 
 typedef struct topo_method {
@@ -55,78 +57,82 @@
 	topo_method_f *tm_func;			/* Method function */
 } topo_method_t;
 
+typedef struct topo_modops {
+	topo_enum_f *tmo_enum;		/* enumeration op */
+	topo_release_f *tmo_release;	/* resource release op */
+} topo_modops_t;
+
 typedef struct topo_mod_info {
-	char *tmi_desc;			/* Client module description */
-	topo_version_t tmi_version;	/* Client module version */
-	topo_enum_f *tmi_enum;		/* enumerator function */
-	topo_release_f *tmi_release;	/* de-enumerator function */
+	const char *tmi_desc;		/* module description */
+	const char *tmi_scheme;		/* enumeration scheme type  */
+	topo_version_t tmi_version;	/* module version */
+	const topo_modops_t *tmi_ops;	/* module ops vector */
 } topo_modinfo_t;
 
-extern topo_mod_t *topo_mod_load(topo_mod_t *, const char *);
+extern topo_mod_t *topo_mod_load(topo_mod_t *, const char *, topo_version_t);
 extern void topo_mod_unload(topo_mod_t *);
-extern int topo_mod_register(topo_mod_t *, const topo_modinfo_t *, void *);
+extern int topo_mod_register(topo_mod_t *, const topo_modinfo_t *,
+    topo_version_t);
 extern void topo_mod_unregister(topo_mod_t *);
 extern int topo_mod_enumerate(topo_mod_t *, tnode_t *, const char *,
-    const char *, topo_instance_t, topo_instance_t);
+    const char *, topo_instance_t, topo_instance_t, void *);
+extern int topo_mod_enummap(topo_mod_t *mod, tnode_t *, const char *,
+    const char *);
 extern void topo_mod_release(topo_mod_t *, tnode_t *);
-extern char *topo_mod_rootdir(topo_mod_t *);
-extern void *topo_mod_private(topo_mod_t *);
-extern topo_hdl_t *topo_mod_handle(topo_mod_t *);
+extern void topo_mod_setspecific(topo_mod_t *, void *);
+extern void *topo_mod_getspecific(topo_mod_t *);
+
+extern nvlist_t *topo_mod_cpufmri(topo_mod_t *, int, uint32_t, uint8_t,
+    const char *);
+extern nvlist_t *topo_mod_devfmri(topo_mod_t *, int, const char *,
+    const char *);
+extern nvlist_t *topo_mod_hcfmri(topo_mod_t *, tnode_t *, int, const char *,
+    topo_instance_t, nvlist_t *, nvlist_t *, const char *, const char *,
+    const char *);
+extern nvlist_t *topo_mod_memfmri(topo_mod_t *, int, uint64_t, uint64_t,
+    const char *, int);
+extern nvlist_t *topo_mod_modfmri(topo_mod_t *, int, const char *);
+extern nvlist_t *topo_mod_pkgfmri(topo_mod_t *, int, const char *);
+extern int topo_mod_nvl2str(topo_mod_t *, nvlist_t *, char **);
+extern int topo_mod_str2nvl(topo_mod_t *, const char *,  nvlist_t **);
+
+/*
+ * Flags for topo_mod_memfmri
+ */
+#define	TOPO_MEMFMRI_PA		0x0001	/* Valid physical address */
+#define	TOPO_MEMFMRI_OFFSET	0x0002	/* Valid offset */
 
 extern int topo_method_register(topo_mod_t *, tnode_t *, const topo_method_t *);
 extern void topo_method_unregister(topo_mod_t *, tnode_t *, const char *);
 extern void topo_method_unregister_all(topo_mod_t *, tnode_t *);
 
+extern di_node_t topo_mod_devinfo(topo_mod_t *);
+extern di_prom_handle_t topo_mod_prominfo(topo_mod_t *);
+extern nvlist_t *topo_mod_auth(topo_mod_t *, tnode_t *);
+
 /*
  * FMRI methods
  */
-#define	TOPO_METH_ASRU_COMPUTE		"topo_asru_compute"
-#define	TOPO_METH_FRU_COMPUTE		"topo_fru_compute"
-#define	TOPO_METH_FMRI			"topo_fmri"
 #define	TOPO_METH_LABEL			"topo_label"
-#define	TOPO_METH_NVL2STR		"topo_nvl2str"
-#define	TOPO_METH_STR2NVL		"topo_str2nvl"
-#define	TOPO_METH_PRESENT		"topo_present"
-#define	TOPO_METH_CONTAINS		"topo_contains"
-#define	TOPO_METH_UNUSABLE		"topo_unusable"
-#define	TOPO_METH_EXPAND		"topo_expand"
-#define	TOPO_METH_COMPARE		"topo_compare"
-
-#define	TOPO_METH_FMRI_VERSION			0
-#define	TOPO_METH_LABEL_VERSION			0
-#define	TOPO_METH_FRU_COMPUTE_VERSION		0
-#define	TOPO_METH_ASRU_COMPUTE_VERSION		0
-#define	TOPO_METH_NVL2STR_VERSION		0
-#define	TOPO_METH_STR2NVL_VERSION		0
-#define	TOPO_METH_PRESENT_VERSION		0
-#define	TOPO_METH_CONTAINS_VERSION		0
-#define	TOPO_METH_UNUSABLE_VERSION		0
-#define	TOPO_METH_EXPAND_VERSION		0
-#define	TOPO_METH_COMPARE_VERSION		0
+#define	TOPO_METH_LABEL_DESC		"Dynamic label discovery"
+#define	TOPO_METH_LABEL_VERSION0	0
+#define	TOPO_METH_LABEL_VERSION		TOPO_METH_LABEL_VERSION0
+#define	TOPO_METH_LABEL_ARG_NVL	"label-specific"
+#define	TOPO_METH_LABEL_RET_STR	"label-string"
 
-#define	TOPO_METH_ASRU_COMPUTE_DESC		"Dynamic ASRU constructor"
-#define	TOPO_METH_FRU_COMPUTE_DESC		"Dynamic FRU constructor"
-#define	TOPO_METH_FMRI_DESC			"Dynamic FMRI constructor"
-#define	TOPO_METH_LABEL_DESC			"Dynamic label discovery"
-#define	TOPO_METH_NVL2STR_DESC			"FMRI to string"
-#define	TOPO_METH_STR2NVL_DESC			"string to FMRI"
-#define	TOPO_METH_PRESENT_DESC			"FMRI is present"
-#define	TOPO_METH_CONTAINS_DESC			"FMRI contains sub-FMRI"
-#define	TOPO_METH_UNUSABLE_DESC			"FMRI is unusable"
-#define	TOPO_METH_EXPAND_DESC			"expand FMRI"
-#define	TOPO_METH_COMPARE_DESC			"compare two FMRIs"
+#define	TOPO_METH_PRESENT		"topo_present"
+#define	TOPO_METH_PRESENT_DESC		"Dynamic label discovery"
+#define	TOPO_METH_PRESENT_VERSION0	0
+#define	TOPO_METH_PRESENT_VERSION	TOPO_METH_PRESENT_VERSION0
+#define	TOPO_METH_PRESENT_RET		"present-ret"
 
-#define	TOPO_METH_FMRI_ARG_NAME		"child-name"
-#define	TOPO_METH_FMRI_ARG_INST		"child-inst"
-#define	TOPO_METH_FMRI_ARG_NVL		"args"
-#define	TOPO_METH_FMRI_ARG_PARENT	"parent-fmri"
-#define	TOPO_METH_FMRI_ARG_AUTH		"auth"
-#define	TOPO_METH_FMRI_ARG_PART		"part"
-#define	TOPO_METH_FMRI_ARG_REV		"rev"
-#define	TOPO_METH_FMRI_ARG_SER		"serial"
+#define	TOPO_METH_ASRU_COMPUTE		"topo_asru_compute"
+#define	TOPO_METH_ASRU_COMPUTE_VERSION	0
+#define	TOPO_METH_ASRU_COMPUTE_DESC	"Dynamic ASRU constructor"
 
-#define	TOPO_METH_LABEL_ARG_NVL		"label-private"
-#define	TOPO_METH_LABEL_RET_STR		"label-string"
+#define	TOPO_METH_FRU_COMPUTE		"topo_fru_compute"
+#define	TOPO_METH_FRU_COMPUTE_VERSION	0
+#define	TOPO_METH_FRU_COMPUTE_DESC	"Dynamic FRU constructor"
 
 extern void *topo_mod_alloc(topo_mod_t *, size_t);
 extern void *topo_mod_zalloc(topo_mod_t *, size_t);
@@ -137,7 +143,7 @@
 extern int topo_mod_nvdup(topo_mod_t *, nvlist_t *, nvlist_t **);
 
 extern void topo_mod_clrdebug(topo_mod_t *);
-extern void topo_mod_setdebug(topo_mod_t *, int);
+extern void topo_mod_setdebug(topo_mod_t *);
 extern void topo_mod_dprintf(topo_mod_t *, const char *, ...);
 extern const char *topo_mod_errmsg(topo_mod_t *);
 extern int topo_mod_errno(topo_mod_t *);
@@ -149,12 +155,20 @@
     topo_instance_t, topo_instance_t);
 extern void topo_node_range_destroy(tnode_t *, const char *);
 extern tnode_t *topo_node_bind(topo_mod_t *, tnode_t *, const char *,
-    topo_instance_t, nvlist_t *, void *);
+    topo_instance_t, nvlist_t *);
 extern void topo_node_unbind(tnode_t *);
+extern void topo_node_setspecific(tnode_t *, void *);
+extern void *topo_node_getspecific(tnode_t *);
+extern int topo_node_asru_set(tnode_t *node, nvlist_t *, int, int *);
+extern int topo_node_fru_set(tnode_t *node, nvlist_t *, int, int *);
+extern int topo_node_label_set(tnode_t *node, char *, int *);
+
+#define	TOPO_ASRU_COMPUTE	0x0001	/* Compute ASRU dynamically */
+#define	TOPO_FRU_COMPUTE	0x0002	/* Compute FRU dynamically */
 
 /*
  * This enum definition is used to define a set of error tags associated with
- * the fmd daemon's various error conditions.  The shell script mkerror.sh is
+ * the module api error conditions.  The shell script mkerror.sh is
  * used to parse this file and create a corresponding topo_error.c source file.
  * If you do something other than add a new error tag here, you may need to
  * update the mkerror shell script as it is based upon simple regexps.
@@ -168,10 +182,13 @@
     EMOD_FMRI_NVL,		/* nvlist allocation failure for FMRI */
     EMOD_FMRI_VERSION,		/* invalid FMRI scheme version */
     EMOD_FMRI_MALFORM,		/* malformed FMRI */
-    EMOD_VER_OLD,		/* module compiled using an obsolete topo ABI */
-    EMOD_VER_NEW,		/* module is compiled using a newer topo ABI */
+    EMOD_VER_ABI,		/* registered with invalid ABI version */
+    EMOD_VER_OLD,		/* attempt to load obsolete module */
+    EMOD_VER_NEW,		/* attempt to load a newer module */
     EMOD_NVL_INVAL,		/* invalid nvlist */
     EMOD_NONCANON,		/* non-canonical component name requested */
+    EMOD_MOD_NOENT,		/* module lookup failed */
+    EMOD_UKNOWN_ENUM,		/* unknown enumeration error */
     EMOD_END			/* end of mod errno list (to ease auto-merge) */
 } topo_mod_errno_t;
 
--- a/usr/src/lib/fm/topo/libtopo/common/topo_mod.map	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_mod.map	Sat Nov 04 01:18:55 2006 -0800
@@ -5,9 +5,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
 #
 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 # or http://www.opensolaris.org/os/licensing.
@@ -30,7 +29,8 @@
 	topo_node_bind = FUNCTION extern;
 	topo_node_unbind = FUNCTION extern;
 	topo_node_name = FUNCTION extern;
-	topo_node_private = FUNCTION extern;
+	topo_node_setspecific = FUNCTION extern;
+	topo_node_getspecific = FUNCTION extern;
 	topo_node_instance = FUNCTION extern;
 
 	topo_mod_alloc = FUNCTION extern;
@@ -41,8 +41,6 @@
 	topo_mod_strfree = FUNCTION extern;
 	topo_mod_strdup = FUNCTION extern;
 
-	topo_fmri_create = FUNCTION extern;
-
 	topo_mod_clrdebug = FUNCTION extern;
 	topo_mod_setdebug = FUNCTION extern;
 	topo_mod_dprintf = FUNCTION extern;
@@ -54,10 +52,18 @@
 	topo_mod_register = FUNCTION extern;
 	topo_mod_unregister = FUNCTION extern;
 	topo_mod_enumerate = FUNCTION extern;
+	topo_mod_enummap = FUNCTION extern;
 	topo_mod_release = FUNCTION extern;
-	topo_mod_rootdir = FUNCTION extern;
-	topo_mod_handle = FUNCTION extern;
-	topo_mod_private = FUNCTION extern;
+	topo_mod_getspecific = FUNCTION extern;
+	topo_mod_setspecific = FUNCTION extern;
+	topo_mod_hcfmri = FUNCTION extern;
+	topo_mod_devfmri = FUNCTION extern;
+	topo_mod_cpufmri = FUNCTION extern;
+	topo_mod_pkgfmri = FUNCTION extern;
+	topo_mod_modfmri = FUNCTION extern;
+	topo_mod_nvl2str = FUNCTION extern;
+	topo_mod_str2nvl = FUNCTION extern;
+	topo_mod_auth = FUNCTION extern;
 
 	topo_method_register = FUNCTION extern;
 	topo_method_unregister = FUNCTION extern;
--- a/usr/src/lib/fm/topo/libtopo/common/topo_module.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_module.c	Sat Nov 04 01:18:55 2006 -0800
@@ -50,8 +50,8 @@
 {
 	topo_mod_enter(mod);
 
-	if (mod->tm_info->tmi_release != NULL)
-		mod->tm_info->tmi_release(mod, node);
+	if (mod->tm_info->tmi_ops->tmo_release != NULL)
+		mod->tm_info->tmi_ops->tmo_release(mod, node);
 
 	topo_mod_exit(mod);
 }
@@ -129,17 +129,20 @@
 
 	mod->tm_flags = TOPO_MOD_FINI;
 
-	topo_dprintf(TOPO_DBG_MOD, "module %s stopped\n", mod->tm_name);
+	topo_dprintf(mod->tm_hdl, TOPO_DBG_MODSVC,
+	    "module %s stopped\n", mod->tm_name);
 }
 
 static int
-topo_mod_start(topo_mod_t *mod)
+topo_mod_start(topo_mod_t *mod, topo_version_t version)
 {
-	topo_dprintf(TOPO_DBG_MOD, "starting module %s\n", mod->tm_name);
+	topo_dprintf(mod->tm_hdl, TOPO_DBG_MODSVC,
+	    "starting module %s\n", mod->tm_name);
 
-	if (mod->tm_mops->mop_init(mod) != 0) {
-		mod->tm_errno = errno ? errno : ETOPO_MOD_INIT;
-		topo_dprintf(TOPO_DBG_ERR,
+	if (mod->tm_mops->mop_init(mod, version) != 0) {
+		if (mod->tm_errno == 0)
+			mod->tm_errno = ETOPO_MOD_INIT;
+		topo_dprintf(mod->tm_hdl, TOPO_DBG_ERR,
 		    "module %s failed to initialize: %s\n", mod->tm_name,
 		    topo_strerror(mod->tm_errno));
 		return (-1);
@@ -148,32 +151,26 @@
 	mod->tm_flags |= TOPO_MOD_INIT;
 
 	if (!(mod->tm_flags & TOPO_MOD_REG)) {
-		topo_dprintf(TOPO_DBG_ERR,
+		topo_dprintf(mod->tm_hdl, TOPO_DBG_ERR,
 		    "module %s failed to register\n", mod->tm_name);
 		mod->tm_errno = ETOPO_MOD_NOREG;
 		topo_mod_stop(mod);
 		return (-1);
 	}
 
-	topo_dprintf(TOPO_DBG_MOD, "module %s started\n", mod->tm_name);
-
 	return (0);
 }
 
 topo_mod_t *
-topo_mod_lookup(topo_hdl_t *thp, const char *path)
+topo_mod_lookup(topo_hdl_t *thp, const char *name, int bump)
 {
-	char *p;
-	char name[PATH_MAX];
 	topo_mod_t *mod;
 	topo_modhash_t *mhp = thp->th_modhash;
 
-	(void) strlcpy(name, topo_strbasename(path), sizeof (name));
-	if ((p = strrchr(name, '.')) != NULL && strcmp(p, ".so") == 0)
-	*p = '\0'; /* strip trailing .so from any module name */
-
 	topo_modhash_lock(mhp);
 	mod = topo_modhash_lookup(mhp, name);
+	if (mod != NULL && bump != 0)
+		topo_mod_hold(mod);
 	topo_modhash_unlock(mhp);
 
 	return (mod);
@@ -203,7 +200,7 @@
 static topo_mod_t *
 set_create_error(topo_hdl_t *thp, topo_mod_t *mod, const char *path, int err)
 {
-	topo_dprintf(TOPO_DBG_ERR, "unable to load module %s: %s\n",
+	topo_dprintf(thp, TOPO_DBG_ERR, "unable to load module %s: %s\n",
 	    path, topo_strerror(err));
 
 	if (mod != NULL)
@@ -216,7 +213,7 @@
 
 static topo_mod_t *
 topo_mod_create(topo_hdl_t *thp, const char *name, const char *path,
-    const topo_modops_t *ops)
+    const topo_imodops_t *ops, topo_version_t version)
 {
 	topo_mod_t *mod;
 
@@ -229,24 +226,23 @@
 	(void) pthread_mutex_init(&mod->tm_lock, NULL);
 
 	mod->tm_name = topo_hdl_strdup(thp, name);
-	mod->tm_path = topo_hdl_strdup(thp, path);
+	if (path != NULL)
+		mod->tm_path = topo_hdl_strdup(thp, path);
 	mod->tm_rootdir = topo_hdl_strdup(thp, thp->th_rootdir);
-	if (mod->tm_name == NULL || mod->tm_path == NULL ||
-	    mod->tm_rootdir == NULL)
+	if (mod->tm_name == NULL || mod->tm_rootdir == NULL)
 		return (set_create_error(thp, mod, path, ETOPO_NOMEM));
 
-	mod->tm_mops = (topo_modops_t *)ops;
+	mod->tm_mops = (topo_imodops_t *)ops;
 	mod->tm_hdl = thp;
 	mod->tm_alloc = thp->th_alloc;
-	mod->tm_version = TOPO_VERSION;
 
 	/*
 	 * Module will be held upon a successful return from topo_mod_start()
 	 */
-	if ((topo_mod_start(mod)) < 0)
+	if ((topo_mod_start(mod, version)) < 0)
 		return (set_create_error(thp, mod, path, mod->tm_errno));
 
-	topo_dprintf(TOPO_DBG_MOD, "loaded module %s\n", mod->tm_name);
+	topo_dprintf(thp, TOPO_DBG_MODSVC, "loaded module %s\n", mod->tm_name);
 
 	return (mod);
 }
@@ -305,20 +301,16 @@
 }
 
 topo_mod_t *
-topo_modhash_load(topo_hdl_t *thp, const char *path, const topo_modops_t *ops)
+topo_modhash_load(topo_hdl_t *thp, const char *name, const char *path,
+    const topo_imodops_t *ops, topo_version_t version)
 {
-	char name[PATH_MAX], *p;
 	topo_modhash_t *mhp = thp->th_modhash;
 	topo_mod_t *mod;
 	uint_t h;
 
 	topo_modhash_lock(mhp);
 
-	(void) strlcpy(name, topo_strbasename(path), sizeof (name));
-	if ((p = strrchr(name, '.')) != NULL && strcmp(p, ".so") == 0)
-		*p = '\0'; /* strip trailing .so from any module name */
-
-	if ((mod = topo_mod_create(thp, name, path, ops)) == NULL) {
+	if ((mod = topo_mod_create(thp, name, path, ops, version)) == NULL) {
 		topo_modhash_unlock(mhp);
 		return (NULL); /* th_errno set */
 	}
@@ -391,9 +383,12 @@
 		while (mp != NULL) {
 			topo_mod_stop(mp);
 
-			assert(mp->tm_refs == 1);
+			/*
+			 * At this point we are forcing all modules to
+			 * stop, ignore any remaining module reference counts.
+			 */
+			mp->tm_refs = 0;
 
-			--mp->tm_refs;
 			*pp = mp->tm_next;
 			topo_mod_destroy(mp);
 			mp = *pp;
--- a/usr/src/lib/fm/topo/libtopo/common/topo_module.h	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_module.h	Sat Nov 04 01:18:55 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -38,10 +37,10 @@
 extern "C" {
 #endif
 
-typedef struct topo_modops {
-	int (*mop_init)(struct topo_mod *);
+typedef struct topo_imodops {
+	int (*mop_init)(struct topo_mod *, topo_version_t version);
 	int (*mop_fini)(struct topo_mod *);
-} topo_modops_t;
+} topo_imodops_t;
 
 #define	TOPO_HASH_BUCKETS	3
 
@@ -52,6 +51,13 @@
 	uint_t mh_nelems;		/* number of modules in hash */
 };
 
+typedef struct topo_imod_info {
+	char *tmi_desc;			/* module description */
+	char *tmi_scheme;		/* enumeration scheme-type */
+	topo_version_t tmi_version;	/* module version */
+	topo_modops_t *tmi_ops;		/* module ops vector */
+} topo_imodinfo_t;
+
 struct topo_mod {
 	pthread_mutex_t tm_lock;	/* Lock for tm_cv/owner/flags/refs */
 	pthread_cond_t tm_cv;		/* Module condition variable */
@@ -63,14 +69,12 @@
 	char *tm_path;			/* Full pathname of module file */
 	char *tm_rootdir;		/* Relative root directory of module */
 	void *tm_priv;			/* Module private data */
-	topo_version_t tm_version;	/* Module ABI version */
-	topo_stability_t tm_stability;	/* SMI stability level */
 	uint_t tm_refs;			/* Module reference count */
 	uint_t tm_flags;		/* Miscellaneous flags (see below) */
 	uint_t tm_debug;		/* Debug printf mask */
 	void *tm_data;			/* Private rtld/builtin data */
-	topo_modops_t *tm_mops;		/* Module class ops vector */
-	topo_modinfo_t *tm_info;	/* Module info registered with handle */
+	topo_imodops_t *tm_mops;	/* Module class ops vector */
+	topo_imodinfo_t *tm_info;	/* Module info registered with handle */
 	int tm_errno;			/* Module error */
 };
 
@@ -79,8 +83,7 @@
 #define	TOPO_MOD_REG	0x004		/* topo_modinfo_t registered */
 #define	TOPO_MOD_UNREG	0x008		/* Module unregistered */
 
-extern const topo_modops_t topo_bltin_ops;
-extern const topo_modops_t topo_rtld_ops;
+extern const topo_imodops_t topo_rtld_ops;
 
 extern void topo_mod_enter(topo_mod_t *);
 extern void topo_mod_exit(topo_mod_t *);
@@ -90,13 +93,13 @@
 extern topo_modhash_t *topo_modhash_create(topo_hdl_t *);
 extern void topo_modhash_destroy(topo_hdl_t *);
 extern topo_mod_t *topo_modhash_lookup(topo_modhash_t *, const char *);
-extern topo_mod_t *topo_modhash_load(topo_hdl_t *, const char *,
-    const topo_modops_t *);
+extern topo_mod_t *topo_modhash_load(topo_hdl_t *, const char *, const char *,
+    const topo_imodops_t *, topo_version_t);
 extern void topo_modhash_unload(topo_mod_t *);
 extern void topo_modhash_unload_all(topo_hdl_t *);
 
 extern void topo_mod_release(topo_mod_t *, tnode_t *);
-extern topo_mod_t *topo_mod_lookup(topo_hdl_t *, const char *);
+extern topo_mod_t *topo_mod_lookup(topo_hdl_t *, const char *, int);
 
 #ifdef __cplusplus
 }
--- a/usr/src/lib/fm/topo/libtopo/common/topo_node.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_node.c	Sat Nov 04 01:18:55 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -77,10 +76,26 @@
 #include <assert.h>
 #include <pthread.h>
 #include <strings.h>
+#include <sys/fm/protocol.h>
 #include <topo_alloc.h>
+#include <topo_error.h>
+#include <topo_method.h>
+#include <topo_subr.h>
 #include <topo_tree.h>
-#include <topo_subr.h>
-#include <topo_error.h>
+
+static topo_pgroup_info_t protocol_pgroup = {
+	TOPO_PGROUP_PROTOCOL,
+	TOPO_STABILITY_PRIVATE,
+	TOPO_STABILITY_PRIVATE,
+	1
+};
+
+static const topo_pgroup_info_t auth_pgroup = {
+	FM_FMRI_AUTHORITY,
+	TOPO_STABILITY_PRIVATE,
+	TOPO_STABILITY_PRIVATE,
+	1
+};
 
 static void
 topo_node_destroy(tnode_t *node)
@@ -95,8 +110,6 @@
 
 	assert(node->tn_refs == 0);
 
-	topo_dprintf(TOPO_DBG_TREE, "destroying node %s=%d\n", node->tn_name,
-	    node->tn_instance);
 	/*
 	 * If not a root node, remove this node from the parent's node hash
 	 */
@@ -126,8 +139,8 @@
 	 * Allow enumerator to clean-up private data and then release
 	 * ref count
 	 */
-	if (mod->tm_info->tmi_release != NULL)
-		mod->tm_info->tmi_release(mod, node);
+	if (mod->tm_info->tmi_ops->tmo_release != NULL)
+		mod->tm_info->tmi_ops->tmo_release(mod, node);
 
 	topo_method_unregister_all(mod, node);
 
@@ -203,8 +216,14 @@
 	return (node->tn_instance);
 }
 
+void
+topo_node_setspecific(tnode_t *node, void *data)
+{
+	node->tn_priv = data;
+}
+
 void *
-topo_node_private(tnode_t *node)
+topo_node_getspecific(tnode_t *node)
 {
 	return (node->tn_priv);
 }
@@ -215,7 +234,7 @@
 {
 	topo_node_unlock(pnode);
 
-	topo_dprintf(TOPO_DBG_ERR, "unable to insert child:"
+	topo_dprintf(mod->tm_hdl, TOPO_DBG_ERR, "unable to insert child:"
 	    "%s\n", topo_strerror(err));
 
 	if (nhp != NULL) {
@@ -276,8 +295,8 @@
 	topo_list_append(&pnode->tn_children, nhp);
 	topo_node_unlock(pnode);
 
-	topo_dprintf(TOPO_DBG_MOD, "created node range %s[%d-%d]\n", name,
-	    min, max);
+	topo_dprintf(mod->tm_hdl, TOPO_DBG_MODSVC,
+	    "created node range %s[%d-%d]\n", name, min, max);
 
 	return (0);
 }
@@ -370,7 +389,7 @@
 	if (node == NULL)
 		return (NULL);
 
-	topo_dprintf(TOPO_DBG_ERR, "unable to bind %s=%d: "
+	topo_dprintf(mod->tm_hdl, TOPO_DBG_ERR, "unable to bind %s=%d: "
 	    "%s\n", (node->tn_name != NULL ? node->tn_name : "unknown"),
 	    node->tn_instance, topo_strerror(err));
 
@@ -382,7 +401,7 @@
 
 tnode_t *
 topo_node_bind(topo_mod_t *mod, tnode_t *pnode, const char *name,
-    topo_instance_t inst, nvlist_t *fmri, void *priv)
+    topo_instance_t inst, nvlist_t *fmri)
 {
 	int h, err;
 	tnode_t *node;
@@ -430,33 +449,30 @@
 	if (fmri == NULL)
 		return (node_bind_seterror(mod, pnode, node, ETOPO_NODE_INVAL));
 
-	if (topo_pgroup_create(node, TOPO_PGROUP_PROTOCOL,
-	    TOPO_STABILITY_PRIVATE, &err) < 0)
+	if (topo_pgroup_create(node, &protocol_pgroup, &err) < 0)
 		return (node_bind_seterror(mod, pnode, node, err));
 
 	if (topo_prop_set_fmri(node, TOPO_PGROUP_PROTOCOL, TOPO_PROP_RESOURCE,
-	    TOPO_PROP_SET_ONCE, fmri, &err) < 0)
+	    TOPO_PROP_IMMUTABLE, fmri, &err) < 0)
 		return (node_bind_seterror(mod, pnode, node, err));
 
-	topo_dprintf(TOPO_DBG_MOD, "node bound %s=%d\n", node->tn_name,
-	    node->tn_instance);
+	topo_dprintf(mod->tm_hdl, TOPO_DBG_MODSVC,
+	    "node bound %s=%d\n", node->tn_name, node->tn_instance);
 
 	node->tn_state |= TOPO_NODE_BOUND;
-	node->tn_priv = priv;
 
 	topo_node_hold(node);
 	nhp->th_nodearr[h] = node;
 	++pnode->tn_refs;
 	topo_node_unlock(pnode);
 
-	if (topo_pgroup_create(node, TOPO_PGROUP_SYSTEM,
-	    TOPO_STABILITY_PRIVATE, &err) == 0) {
-		(void) topo_prop_inherit(node, TOPO_PGROUP_SYSTEM,
-		    TOPO_PROP_PLATFORM, &err);
-		(void) topo_prop_inherit(node, TOPO_PGROUP_SYSTEM,
-		    TOPO_PROP_ISA, &err);
-		(void) topo_prop_inherit(node, TOPO_PGROUP_SYSTEM,
-		    TOPO_PROP_MACHINE, &err);
+	if (topo_pgroup_create(node, &auth_pgroup, &err) == 0) {
+		(void) topo_prop_inherit(node, FM_FMRI_AUTHORITY,
+		    FM_FMRI_AUTH_PRODUCT, &err);
+		(void) topo_prop_inherit(node, FM_FMRI_AUTHORITY,
+		    FM_FMRI_AUTH_CHASSIS, &err);
+		(void) topo_prop_inherit(node, FM_FMRI_AUTHORITY,
+		    FM_FMRI_AUTH_SERVER, &err);
 	}
 
 	return (node);
--- a/usr/src/lib/fm/topo/libtopo/common/topo_parse.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_parse.c	Sat Nov 04 01:18:55 2006 -0800
@@ -31,24 +31,16 @@
 #include <topo_alloc.h>
 #include <topo_error.h>
 #include <topo_parse.h>
-
-extern const char * const Name;
-const char * const Min = "min";
-const char * const Max = "max";
-
+#include <topo_subr.h>
 
 tf_info_t *
-tf_info_new(topo_mod_t *mp, const char *fn, xmlDocPtr doc, xmlChar *scheme)
+tf_info_new(topo_mod_t *mp, xmlDocPtr doc, xmlChar *scheme)
 {
 	tf_info_t *r;
 
 	if ((r = topo_mod_zalloc(mp, sizeof (tf_info_t))) == NULL)
 		return (NULL);
 	r->tf_flags = TF_LIVE;
-	if ((r->tf_fn = topo_mod_strdup(mp, fn)) == NULL) {
-		tf_info_free(mp, r);
-		return (NULL);
-	}
 	if ((r->tf_scheme = topo_mod_strdup(mp, (char *)scheme)) == NULL) {
 		tf_info_free(mp, r);
 		return (NULL);
@@ -62,8 +54,6 @@
 {
 	if (p->tf_xdoc != NULL)
 		xmlFreeDoc(p->tf_xdoc);
-	if (p->tf_fn != NULL)
-		topo_mod_strfree(mp, p->tf_fn);
 	if (p->tf_scheme != NULL)
 		topo_mod_strfree(mp, p->tf_scheme);
 	tf_rdata_free(mp, p->tf_rd);
@@ -77,7 +67,7 @@
 	uint64_t ui;
 	xmlChar *name = NULL;
 
-	topo_mod_dprintf(mp, "new rdata\n");
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "new rdata\n");
 	if ((r = topo_mod_zalloc(mp, sizeof (tf_rdata_t))) == NULL) {
 		(void) topo_mod_seterrno(mp, ETOPO_NOMEM);
 		return (NULL);
@@ -136,7 +126,7 @@
 {
 	tf_idata_t *r;
 
-	topo_mod_dprintf(mp, "new idata %d\n", i);
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "new idata %d\n", i);
 	if ((r = topo_mod_zalloc(mp, sizeof (tf_idata_t))) == NULL)
 		return (NULL);
 	r->ti_tn = tn;
@@ -155,11 +145,10 @@
 }
 
 int
-tf_idata_insert(topo_mod_t *mp, tf_idata_t **head, tf_idata_t *ni)
+tf_idata_insert(tf_idata_t **head, tf_idata_t *ni)
 {
 	tf_idata_t *l, *p;
 
-	topo_mod_dprintf(mp, "idata insert %d\n", ni->ti_i);
 	p = NULL;
 	for (l = *head; l != NULL; l = l->ti_next) {
 		if (ni->ti_i < l->ti_i)
@@ -175,10 +164,9 @@
 }
 
 tf_idata_t *
-tf_idata_lookup(topo_mod_t *mp, tf_idata_t *head, topo_instance_t i)
+tf_idata_lookup(tf_idata_t *head, topo_instance_t i)
 {
 	tf_idata_t *f;
-	topo_mod_dprintf(mp, "idata lookup %d\n", i);
 	for (f = head; f != NULL; f = f->ti_next)
 		if (i == f->ti_i)
 			break;
@@ -190,7 +178,8 @@
 {
 	tf_pad_t *r;
 
-	topo_mod_dprintf(mp, "new pad p=%d, d=%d\n", pcnt, dcnt);
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "new pad p=%d, d=%d\n",
+	    pcnt, dcnt);
 	if ((r = topo_mod_zalloc(mp, sizeof (tf_pad_t))) == NULL)
 		return (NULL);
 	r->tpad_pgcnt = pcnt;
@@ -223,7 +212,5 @@
 		return;
 	if (p->te_name != NULL)
 		xmlFree(p->te_name);
-	if (p->te_path != NULL)
-		xmlFree(p->te_path);
 	topo_mod_free(mp, p, sizeof (tf_edata_t));
 }
--- a/usr/src/lib/fm/topo/libtopo/common/topo_parse.h	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_parse.h	Sat Nov 04 01:18:55 2006 -0800
@@ -33,15 +33,13 @@
 #include <libxml/parser.h>
 #include <libnvpair.h>
 #include <fm/libtopo.h>
+#include <fm/topo_mod.h>
 
 #ifdef	__cplusplus
 extern "C" {
 #endif
 
-#define	TOPO_DTD_PATH	"topology.dtd.1"
-#define	TOPO_FILE	"topology.xml"
-#define	TOPO_PLATFORM_PATH	"%susr/platform/%s/lib/fm/topo/%s"
-#define	TOPO_COMMON_PATH	"%susr/lib/fm/topo/%s"
+#define	TOPO_DTD_PATH	"/usr/share/lib/xml/dtd/topology.dtd.1"
 
 /*
  * Plenty of room to hold string representation of an instance
@@ -61,11 +59,8 @@
  */
 typedef struct tf_edata {
 	char *te_name;		/* name of the enumerator, if any */
-	char *te_path;		/* path to the enumerator, if any */
 	topo_stability_t te_stab; /* stability of the enumerator, if any */
-	int te_vers;		/* version of the enumerator, if any */
-	int te_amcnt;		/* number of apply-methods */
-	nvlist_t **te_ams;	/* apply-methods */
+	topo_version_t te_vers;		/* version of the enumerator, if any */
 } tf_edata_t;
 
 /* properties and dependents off of an instance or a range */
@@ -108,7 +103,6 @@
  * affected, etc.
  */
 typedef struct tf_info {
-	char *tf_fn;		/* name of file read */
 	char *tf_scheme;	/* scheme of topology in file */
 	/* UUID ? */
 	uint_t tf_flags;	/* behavior modifiers (see values below) */
@@ -127,18 +121,69 @@
 #define	INV_PGRP_ALLPROPS "propgrp-props"
 #define	INV_PGRP_NAME	"propgrp-name"
 #define	INV_PGRP_NPROP	"propgrp-numprops"
-#define	INV_PGRP_STAB	"propgrp-name-stability"
+#define	INV_PGRP_NMSTAB	"propgrp-name-stability"
+#define	INV_PGRP_DSTAB	"propgrp-data-stability"
+#define	INV_PGRP_VER	"propgrp-version"
 #define	INV_PNAME	"prop-name"
 #define	INV_PVAL	"prop-val"
 #define	INV_PVALTYPE	"prop-valtype"
 
-extern tf_idata_t *tf_idata_lookup(topo_mod_t *, tf_idata_t *, topo_instance_t);
+/*
+ * Valid .xml element and attribute names
+ */
+#define	Children "children"
+#define	Dependents "dependents"
+#define	FMRI "fmri"
+#define	Grouping "grouping"
+#define	Immutable "immutable"
+#define	Instance "instance"
+#define	Int32 "int32"
+#define	Int64 "int64"
+#define	Name "name"
+#define	Path "path"
+#define	Range "range"
+#define	Scheme "scheme"
+#define	Siblings "siblings"
+#define	Static "static"
+#define	String "string"
+#define	Topology "topology"
+#define	Type "type"
+#define	UInt32 "uint32"
+#define	UInt64 "uint64"
+#define	Value "value"
+#define	Verify "verify"
+#define	Version "version"
+#define	Min "min"
+#define	Max "max"
+
+#define	Enum_meth "enum-method"
+#define	Propgrp "propgroup"
+#define	Propval "propval"
+
+#define	Node "node"
+#define	Hc "hc"
+
+#define	True "true"
+#define	False "false"
+
+#define	Namestab "name-stability"
+#define	Datastab "data-stability"
+
+#define	Evolving "Evolving"
+#define	External "External"
+#define	Internal "Internal"
+#define	Obsolete "Obsolete"
+#define	Private "Private"
+#define	Stable "Stable"
+#define	Standard "Standard"
+#define	Unstable "Unstable"
+
+extern tf_idata_t *tf_idata_lookup(tf_idata_t *, topo_instance_t);
 extern tf_rdata_t *tf_rdata_new(topo_mod_t *,
     tf_info_t *, xmlNodePtr, tnode_t *);
 extern tf_idata_t *tf_idata_new(topo_mod_t *, topo_instance_t, tnode_t *);
 extern tf_info_t *topo_xml_read(topo_mod_t *, const char *, const char *);
-extern tf_info_t *tf_info_new(topo_mod_t *,
-    const char *, xmlDocPtr, xmlChar *);
+extern tf_info_t *tf_info_new(topo_mod_t *, xmlDocPtr, xmlChar *);
 extern tf_pad_t *tf_pad_new(topo_mod_t *, int, int);
 extern void topo_xml_cleanup(topo_mod_t *, tf_info_t *);
 extern void tf_rdata_free(topo_mod_t *, tf_rdata_t *);
@@ -148,9 +193,10 @@
 extern void tf_pad_free(topo_mod_t *, tf_pad_t *);
 extern int topo_xml_range_process(topo_mod_t *, xmlNodePtr, tf_rdata_t *);
 extern int topo_xml_enum(topo_mod_t *, tf_info_t *, tnode_t *);
-extern int tf_idata_insert(topo_mod_t *, tf_idata_t **, tf_idata_t *);
+extern int tf_idata_insert(tf_idata_t **, tf_idata_t *);
 extern int xmlattr_to_int(topo_mod_t *, xmlNodePtr, const char *, uint64_t *);
-extern int xmlattr_to_stab(topo_mod_t *, xmlNodePtr, topo_stability_t *);
+extern int xmlattr_to_stab(topo_mod_t *, xmlNodePtr, const char *,
+    topo_stability_t *);
 
 #ifdef	__cplusplus
 }
--- a/usr/src/lib/fm/topo/libtopo/common/topo_prop.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_prop.c	Sat Nov 04 01:18:55 2006 -0800
@@ -42,7 +42,7 @@
 	 */
 	for (pg = topo_list_next(&node->tn_pgroups); pg != NULL;
 	    pg = topo_list_next(pg)) {
-		if (strcmp(pg->tpg_name, pgname) == 0) {
+		if (strcmp(pg->tpg_info->tpi_name, pgname) == 0) {
 			return (pg);
 		}
 	}
@@ -84,65 +84,187 @@
 }
 
 static int
-prop_val_add(nvlist_t *nvl, topo_propval_t *pv)
+prop_val_add(nvlist_t *nvl, topo_propval_t *pv, int *err)
 {
+	int ret = 0;
+	uint_t nelems;
+
+	if (nvlist_add_int32(nvl, TOPO_PROP_VAL_TYPE, pv->tp_type) != 0)
+		return (-1);
+
 	switch (pv->tp_type) {
 		case TOPO_TYPE_INT32:
-			return (nvlist_add_int32(nvl, TOPO_PROP_VAL_VAL,
-			    pv->tp_u.tp_int32));
+		{
+			int32_t val;
+			if ((ret = nvlist_lookup_int32(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, &val)) < 0)
+				break;
+			ret = nvlist_add_int32(nvl, TOPO_PROP_VAL_VAL, val);
+		}
+		break;
 		case TOPO_TYPE_UINT32:
-			return (nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL,
-			    pv->tp_u.tp_uint32));
+		{
+			uint32_t val;
+			if ((ret = nvlist_lookup_uint32(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, &val)) < 0)
+				break;
+			ret = nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, val);
+		}
+		break;
 		case TOPO_TYPE_INT64:
-			return (nvlist_add_int64(nvl, TOPO_PROP_VAL_VAL,
-			    pv->tp_u.tp_int64));
+		{
+			int64_t val;
+			if ((ret = nvlist_lookup_int64(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, &val)) < 0)
+				break;
+			ret = nvlist_add_int64(nvl, TOPO_PROP_VAL_VAL, val);
+		}
+		break;
 		case TOPO_TYPE_UINT64:
-			return (nvlist_add_uint64(nvl, TOPO_PROP_VAL_VAL,
-			    pv->tp_u.tp_uint64));
+		{
+			uint64_t val;
+			if ((ret = nvlist_lookup_uint64(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, &val)) < 0)
+				break;
+			ret = nvlist_add_uint64(nvl, TOPO_PROP_VAL_VAL, val);
+		}
+		break;
 		case TOPO_TYPE_STRING:
-			return (nvlist_add_string(nvl, TOPO_PROP_VAL_VAL,
-			    pv->tp_u.tp_string));
+		{
+			char *val;
+			if ((ret = nvlist_lookup_string(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, &val)) < 0)
+				break;
+			ret = nvlist_add_string(nvl, TOPO_PROP_VAL_VAL, val);
+		}
+		break;
 		case TOPO_TYPE_FMRI:
-			return (nvlist_add_nvlist(nvl, TOPO_PROP_VAL_VAL,
-			    pv->tp_u.tp_fmri));
+		{
+			nvlist_t *val;
+			if ((ret = nvlist_lookup_nvlist(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, &val)) < 0)
+				break;
+			ret =  nvlist_add_nvlist(nvl, TOPO_PROP_VAL_VAL, val);
+		}
+		break;
+		case TOPO_TYPE_INT32_ARRAY:
+		{
+			int32_t *val;
+			if ((ret = nvlist_lookup_int32_array(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, &val, &nelems)) < 0)
+				break;
+			ret = nvlist_add_int32_array(nvl, TOPO_PROP_VAL_VAL,
+			    val, nelems);
+		}
+		break;
+		case TOPO_TYPE_UINT32_ARRAY:
+		{
+			uint32_t *val;
+			if ((ret = nvlist_lookup_uint32_array(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, &val, &nelems)) < 0)
+				break;
+			ret = nvlist_add_uint32_array(nvl, TOPO_PROP_VAL_VAL,
+			    val, nelems);
+		}
+		break;
+		case TOPO_TYPE_INT64_ARRAY:
+		{
+			int64_t *val;
+			if ((ret = nvlist_lookup_int64_array(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, &val, &nelems)) < 0)
+				break;
+			ret = nvlist_add_int64_array(nvl, TOPO_PROP_VAL_VAL,
+			    val, nelems);
+		}
+		break;
+		case TOPO_TYPE_UINT64_ARRAY:
+		{
+			uint64_t *val;
+			if ((ret = nvlist_lookup_uint64_array(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, &val, &nelems)) < 0)
+				break;
+			ret = nvlist_add_uint64_array(nvl, TOPO_PROP_VAL_VAL,
+			    val, nelems);
+		}
+		break;
+		case TOPO_TYPE_STRING_ARRAY:
+		{
+			char **val;
+			if ((ret = nvlist_lookup_string_array(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, &val, &nelems)) < 0)
+				break;
+			ret = nvlist_add_string_array(nvl, TOPO_PROP_VAL_VAL,
+			    val, nelems);
+		}
+		break;
+		case TOPO_TYPE_FMRI_ARRAY:
+		{
+			nvlist_t **val;
+			if ((ret = nvlist_lookup_nvlist_array(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, &val, &nelems)) < 0)
+				break;
+			ret = nvlist_add_nvlist_array(nvl, TOPO_PROP_VAL_VAL,
+			    val, nelems);
+		}
+		break;
 		default:
-			return (ETOPO_PROP_TYPE);
+			ret = ETOPO_PROP_TYPE;
 	}
+
+	if (ret != 0) {
+		if (ret == ENOMEM)
+			*err = ETOPO_NOMEM;
+		else
+			*err = ETOPO_PROP_NVL;
+		return (-1);
+	}
+
+	return (0);
 }
 
 nvlist_t *
-get_all_seterror(topo_hdl_t *thp, nvlist_t *nvl, int err)
+get_all_seterror(tnode_t *node, nvlist_t *nvl, int *errp, int err)
 {
+	topo_node_unlock(node);
+
 	if (nvl != NULL)
 		nvlist_free(nvl);
 
-	(void) topo_hdl_seterrno(thp, err);
+	*errp = err;
 
 	return (NULL);
 }
 
 nvlist_t *
-topo_prop_get_all(topo_hdl_t *thp, tnode_t *node)
+topo_prop_getprops(tnode_t *node, int *err)
 {
-	int err;
+	int ret;
+	topo_hdl_t *thp = node->tn_hdl;
 	nvlist_t *nvl, *pgnvl, *pvnvl;
 	topo_pgroup_t *pg;
 	topo_propval_t *pv;
 	topo_proplist_t *pvl;
 
 	if (topo_hdl_nvalloc(thp, &nvl, 0) != 0) {
-		return (get_all_seterror(thp, NULL, ETOPO_NOMEM));
+		return (get_all_seterror(node, NULL, err, ETOPO_NOMEM));
 	}
 
+	topo_node_lock(node);
 	for (pg = topo_list_next(&node->tn_pgroups); pg != NULL;
 	    pg = topo_list_next(pg)) {
-		err = 0;
 		if (topo_hdl_nvalloc(thp, &pgnvl, 0) != 0)
-			return (get_all_seterror(thp, nvl, ETOPO_NOMEM));
+			return (get_all_seterror(node, nvl, err, ETOPO_NOMEM));
 
-		if ((err = nvlist_add_string(pgnvl, TOPO_PROP_GROUP_NAME,
-		    pg->tpg_name)) != 0)
-			return (get_all_seterror(thp, nvl, err));
+		if (nvlist_add_string(pgnvl, TOPO_PROP_GROUP_NAME,
+		    pg->tpg_info->tpi_name) != 0 ||
+		    nvlist_add_string(pgnvl, TOPO_PROP_GROUP_NSTAB,
+		    topo_stability2name(pg->tpg_info->tpi_namestab)) != 0 ||
+		    nvlist_add_string(pgnvl, TOPO_PROP_GROUP_DSTAB,
+		    topo_stability2name(pg->tpg_info->tpi_datastab)) != 0 ||
+		    nvlist_add_int32(pgnvl, TOPO_PROP_GROUP_VERSION,
+		    pg->tpg_info->tpi_version) != 0)
+			return (get_all_seterror(node, nvl, err,
+			    ETOPO_PROP_NVL));
 
 		for (pvl = topo_list_next(&pg->tpg_pvals); pvl != NULL;
 		    pvl = topo_list_next(pvl)) {
@@ -151,38 +273,40 @@
 			if (topo_hdl_nvalloc(thp, &pvnvl, 0)
 			    != 0) {
 				nvlist_free(pgnvl);
-				return (get_all_seterror(thp, nvl,
+				return (get_all_seterror(node, nvl, err,
 				    ETOPO_NOMEM));
 			}
-			if ((err = nvlist_add_string(pvnvl, TOPO_PROP_VAL_NAME,
+			if ((ret = nvlist_add_string(pvnvl, TOPO_PROP_VAL_NAME,
 			    pv->tp_name)) != 0) {
 				nvlist_free(pgnvl);
 				nvlist_free(pvnvl);
-				return (get_all_seterror(thp, nvl, err));
+				return (get_all_seterror(node, nvl, err, ret));
 			}
-			if ((err = prop_val_add(pvnvl, pv)) != 0) {
+			if (prop_val_add(pvnvl, pv, err) < 0) {
 				nvlist_free(pgnvl);
 				nvlist_free(pvnvl);
-				return (get_all_seterror(thp, nvl, err));
+				return (get_all_seterror(node, nvl, err, ret));
 			}
-			if ((err = nvlist_add_nvlist(pgnvl, TOPO_PROP_VAL,
+			if ((ret = nvlist_add_nvlist(pgnvl, TOPO_PROP_VAL,
 			    pvnvl)) != 0) {
 				nvlist_free(pgnvl);
 				nvlist_free(pvnvl);
-				return (get_all_seterror(thp, nvl, err));
+				return (get_all_seterror(node, nvl, err, ret));
 			}
 
 			nvlist_free(pvnvl);
 		}
-		if ((err = nvlist_add_nvlist(nvl, TOPO_PROP_GROUP, pgnvl))
+		if ((ret = nvlist_add_nvlist(nvl, TOPO_PROP_GROUP, pgnvl))
 		    != 0) {
 			nvlist_free(pgnvl);
-			return (get_all_seterror(thp, nvl, err));
+			return (get_all_seterror(node, nvl, err, ret));
 		}
 
 		nvlist_free(pgnvl);
 	}
 
+	topo_node_unlock(node);
+
 	return (nvl);
 }
 
@@ -194,73 +318,12 @@
 	return (-1);
 }
 
-int
-topo_prop_get_int32(tnode_t *node, const char *pgname, const char *pname,
-    int32_t *val, int *err)
-{
-	topo_propval_t *pv;
-
-	topo_node_lock(node);
-	if ((pv = topo_prop_get(node, pgname, pname, err))
-	    == NULL)
-		return (get_seterror(node, err, *err));
-
-	if (pv->tp_type != TOPO_TYPE_INT32)
-		return (get_seterror(node, err, ETOPO_PROP_TYPE));
-
-	*val = pv->tp_u.tp_int32;
-
-	topo_node_unlock(node);
-
-	return (0);
-}
-
-int
-topo_prop_get_uint32(tnode_t *node, const char *pgname, const char *pname,
-    uint32_t *val, int *err)
+static int
+prop_getval(tnode_t *node, const char *pgname, const char *pname, void *val,
+    topo_type_t type, uint_t *nelems, int *err)
 {
-	topo_propval_t *pv;
-
-	topo_node_lock(node);
-	if ((pv = topo_prop_get(node, pgname, pname, err))
-	    == NULL)
-		return (get_seterror(node, err, *err));
-
-	if (pv->tp_type != TOPO_TYPE_UINT32)
-		return (get_seterror(node, err, ETOPO_PROP_TYPE));
-
-	*val = pv->tp_u.tp_uint32;
-
-	topo_node_unlock(node);
-
-	return (0);
-}
-
-int
-topo_prop_get_int64(tnode_t *node, const char *pgname, const char *pname,
-    int64_t *val, int *err)
-{
-	topo_propval_t *pv;
-
-	topo_node_lock(node);
-	if ((pv = topo_prop_get(node, pgname, pname, err))
-	    == NULL)
-		return (get_seterror(node, err, *err));
-
-	if (pv->tp_type != TOPO_TYPE_INT64)
-		return (get_seterror(node, err, ETOPO_PROP_TYPE));
-
-	*val = pv->tp_u.tp_int64;
-
-	topo_node_unlock(node);
-
-	return (0);
-}
-
-int
-topo_prop_get_uint64(tnode_t *node, const char *pgname, const char *pname,
-    uint64_t *val, int *err)
-{
+	int i, j, ret = 0;
+	topo_hdl_t *thp = node->tn_hdl;
 	topo_propval_t *pv;
 
 	topo_node_lock(node);
@@ -268,76 +331,288 @@
 	    == NULL)
 		return (get_seterror(node, err, *err));
 
-	if (pv->tp_type != TOPO_TYPE_UINT64)
+	if (pv->tp_type != type)
 		return (get_seterror(node, err, ETOPO_PROP_TYPE));
 
-	*val = pv->tp_u.tp_int64;
+	switch (type) {
+		case TOPO_TYPE_INT32:
+			ret = nvlist_lookup_int32(pv->tp_val, TOPO_PROP_VAL_VAL,
+			    (int32_t *)val);
+			break;
+		case TOPO_TYPE_UINT32:
+			ret = nvlist_lookup_uint32(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, (uint32_t *)val);
+			break;
+		case TOPO_TYPE_INT64:
+			ret = nvlist_lookup_int64(pv->tp_val, TOPO_PROP_VAL_VAL,
+			    (int64_t *)val);
+			break;
+		case TOPO_TYPE_UINT64:
+			ret = nvlist_lookup_uint64(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, (uint64_t *)val);
+			break;
+		case TOPO_TYPE_STRING: {
+			char *str;
+
+			ret = nvlist_lookup_string(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, &str);
+			if (ret == 0)
+				*(char **)val = topo_hdl_strdup(thp, str);
+			break;
+		}
+		case TOPO_TYPE_FMRI: {
+			nvlist_t *nvl;
+
+			ret = nvlist_lookup_nvlist(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, &nvl);
+			if (ret == 0)
+				ret = topo_hdl_nvdup(thp, nvl,
+				    (nvlist_t **)val);
+			break;
+		}
+		case TOPO_TYPE_INT32_ARRAY: {
+			int32_t *a1, *a2;
+
+			if ((ret = nvlist_lookup_int32_array(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
+				break;
+			if ((a1 = topo_hdl_alloc(thp, sizeof (int32_t) *
+			    *nelems)) == NULL) {
+				ret = ETOPO_NOMEM;
+				break;
+			}
+			for (i = 0; i < *nelems; ++i)
+				a1[i] = a2[i];
+			*(int32_t **)val = a1;
+			break;
+		}
+		case TOPO_TYPE_UINT32_ARRAY: {
+			uint32_t *a1, *a2;
+
+			if ((ret = nvlist_lookup_uint32_array(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
+				break;
+			if ((a1 = topo_hdl_alloc(thp, sizeof (uint32_t) *
+			    *nelems)) == NULL) {
+				ret = ETOPO_NOMEM;
+				break;
+			}
+			for (i = 0; i < *nelems; ++i)
+				a1[i] = a2[i];
+			*(uint32_t **)val = a1;
+			break;
+		}
+		case TOPO_TYPE_INT64_ARRAY: {
+			int64_t *a1, *a2;
+
+			if ((ret = nvlist_lookup_int64_array(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
+				break;
+			if ((a1 = topo_hdl_alloc(thp, sizeof (int64_t) *
+			    *nelems)) == NULL) {
+				ret = ETOPO_NOMEM;
+				break;
+			}
+			for (i = 0; i < *nelems; ++i)
+				a1[i] = a2[i];
+			*(int64_t **)val = a1;
+			break;
+		}
+		case TOPO_TYPE_UINT64_ARRAY: {
+			uint64_t *a1, *a2;
+
+			if ((ret = nvlist_lookup_uint64_array(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
+				break;
+			if ((a1 = topo_hdl_alloc(thp, sizeof (uint64_t) *
+			    *nelems)) == NULL) {
+				ret = ETOPO_NOMEM;
+				break;
+			}
+			for (i = 0; i < *nelems; ++i)
+				a1[i] = a2[i];
+			*(uint64_t **)val = a1;
+			break;
+		}
+		case TOPO_TYPE_STRING_ARRAY: {
+			char **a1, **a2;
+
+			if ((ret = nvlist_lookup_string_array(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
+				break;
+			if ((a1 = topo_hdl_alloc(thp, sizeof (char *) *
+			    *nelems)) == NULL) {
+				ret = ETOPO_NOMEM;
+				break;
+			}
+			for (i = 0; i < *nelems; ++i) {
+				if ((a1[i] = topo_hdl_strdup(thp, a2[i]))
+				    == NULL) {
+					for (j = 0; j < i; ++j)
+						topo_hdl_free(thp, a1[j],
+						    sizeof (char *));
+					topo_hdl_free(thp, a1,
+					    sizeof (char *) * *nelems);
+					break;
+				}
+			}
+			*(char ***)val = a1;
+			break;
+		}
+		case TOPO_TYPE_FMRI_ARRAY: {
+			nvlist_t **a1, **a2;
+
+			if ((ret = nvlist_lookup_nvlist_array(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
+				break;
+			if ((a1 = topo_hdl_alloc(thp, sizeof (nvlist_t *) *
+			    *nelems)) == NULL) {
+				ret = ETOPO_NOMEM;
+				break;
+			}
+			for (i = 0; i < *nelems; ++i) {
+				if (topo_hdl_nvdup(thp, a2[i], &a1[i]) < 0) {
+					for (j = 0; j < i; ++j)
+						nvlist_free(a1[j]);
+					topo_hdl_free(thp, a1,
+					    sizeof (nvlist_t *) * *nelems);
+					break;
+				}
+			}
+			*(nvlist_t ***)val = a1;
+			break;
+		}
+		default:
+			ret = ETOPO_PROP_NOENT;
+	}
+
+	if (ret != 0)
+		if (ret == ENOENT)
+			return (get_seterror(node, err, ETOPO_PROP_NOENT));
+		else if (ret < ETOPO_UNKNOWN)
+			return (get_seterror(node, err, ETOPO_PROP_NVL));
+		else
+			return (get_seterror(node, err, ret));
 
 	topo_node_unlock(node);
+	return (0);
+}
 
-	return (0);
+int
+topo_prop_get_int32(tnode_t *node, const char *pgname, const char *pname,
+    int32_t *val, int *err)
+{
+	return (prop_getval(node, pgname, pname, (void *)val, TOPO_TYPE_INT32,
+	    NULL, err));
+}
+
+int
+topo_prop_get_uint32(tnode_t *node, const char *pgname, const char *pname,
+    uint32_t *val, int *err)
+{
+	return (prop_getval(node, pgname, pname, (void *)val, TOPO_TYPE_UINT32,
+	    NULL, err));
+}
+
+int
+topo_prop_get_int64(tnode_t *node, const char *pgname, const char *pname,
+    int64_t *val, int *err)
+{
+	return (prop_getval(node, pgname, pname, (void *)val, TOPO_TYPE_INT64,
+	    NULL, err));
+}
+
+int
+topo_prop_get_uint64(tnode_t *node, const char *pgname, const char *pname,
+    uint64_t *val, int *err)
+{
+	return (prop_getval(node, pgname, pname, (void *)val, TOPO_TYPE_UINT64,
+	    NULL, err));
 }
 
 int
 topo_prop_get_string(tnode_t *node, const char *pgname, const char *pname,
     char **val, int *err)
 {
-	topo_propval_t *pv;
-
-	topo_node_lock(node);
-	if ((pv = topo_prop_get(node, pgname, pname, err)) == NULL)
-		return (get_seterror(node, err, *err));
-
-	if (pv->tp_type != TOPO_TYPE_STRING)
-		return (get_seterror(node, err, ETOPO_PROP_TYPE));
-
-	if ((*val = topo_hdl_strdup(node->tn_hdl, pv->tp_u.tp_string))
-	    == NULL)
-		return (get_seterror(node, err, ETOPO_NOMEM));
-
-	topo_node_unlock(node);
-
-	return (0);
+	return (prop_getval(node, pgname, pname, (void *)val, TOPO_TYPE_STRING,
+	    NULL, err));
 }
 
 int
 topo_prop_get_fmri(tnode_t *node, const char *pgname, const char *pname,
     nvlist_t **val, int *err)
 {
-	topo_propval_t *pv;
-
-	topo_node_lock(node);
-	if ((pv = topo_prop_get(node, pgname, pname, err)) == NULL)
-		return (get_seterror(node, err, *err));
+	return (prop_getval(node, pgname, pname, (void *)val, TOPO_TYPE_FMRI,
+	    NULL, err));
+}
 
-	if (pv->tp_type != TOPO_TYPE_FMRI)
-		return (get_seterror(node, err, ETOPO_PROP_TYPE));
+int
+topo_prop_get_int32_array(tnode_t *node, const char *pgname, const char *pname,
+    int32_t **val, uint_t *nelem, int *err)
+{
+	return (prop_getval(node, pgname, pname, (void *)val,
+	    TOPO_TYPE_INT32_ARRAY, nelem, err));
+}
 
-	if (topo_hdl_nvdup(node->tn_hdl, pv->tp_u.tp_fmri, val) < 0)
-		return (get_seterror(node, err, ETOPO_NOMEM));
-
-	topo_node_unlock(node);
-
-	return (0);
+int
+topo_prop_get_uint32_array(tnode_t *node, const char *pgname, const char *pname,
+    uint32_t **val, uint_t *nelem, int *err)
+{
+	return (prop_getval(node, pgname, pname, (void *)val,
+	    TOPO_TYPE_UINT32_ARRAY, nelem, err));
 }
 
-static void
-topo_propval_strfree(topo_propval_t *pv)
+int
+topo_prop_get_int64_array(tnode_t *node, const char *pgname, const char *pname,
+    int64_t **val, uint_t *nelem, int *err)
 {
-	topo_hdl_strfree(pv->tp_hdl, pv->tp_u.tp_string);
+	return (prop_getval(node, pgname, pname, (void *)val,
+	    TOPO_TYPE_INT64_ARRAY, nelem, err));
 }
 
-static void
-topo_propval_nvlfree(topo_propval_t *pv)
+int
+topo_prop_get_uint64_array(tnode_t *node, const char *pgname, const char *pname,
+    uint64_t **val, uint_t *nelem, int *err)
 {
-	nvlist_free(pv->tp_u.tp_fmri);
+	return (prop_getval(node, pgname, pname, (void *)val,
+	    TOPO_TYPE_UINT64_ARRAY, nelem, err));
+}
+
+int
+topo_prop_get_string_array(tnode_t *node, const char *pgname, const char *pname,
+    char ***val, uint_t *nelem, int *err)
+{
+	return (prop_getval(node, pgname, pname, (void *)val,
+	    TOPO_TYPE_STRING_ARRAY, nelem, err));
+}
+
+int
+topo_prop_get_fmri_array(tnode_t *node, const char *pgname, const char *pname,
+    nvlist_t ***val, uint_t *nelem, int *err)
+{
+	return (prop_getval(node, pgname, pname, (void *)val,
+	    TOPO_TYPE_FMRI_ARRAY, nelem, err));
 }
 
 static int
-set_seterror(tnode_t *node, int *errp, int err)
+set_seterror(tnode_t *node, topo_proplist_t *pvl, int *errp, int err)
 {
+	topo_hdl_t *thp = node->tn_hdl;
+	topo_propval_t *pv;
+
+	if (pvl != NULL) {
+		pv = pvl->tp_pval;
+		if (pv != NULL) {
+			if (pv->tp_name != NULL)
+				topo_hdl_strfree(thp, pv->tp_name);
+			if (pv->tp_val != NULL)
+				nvlist_free(pv->tp_val);
+			topo_hdl_free(thp, pv, sizeof (topo_propval_t));
+		}
+		topo_hdl_free(thp, pvl, sizeof (topo_proplist_t));
+	}
+
 	topo_node_unlock(node);
-
 	*errp = err;
 
 	return (-1);
@@ -345,8 +620,9 @@
 
 static int
 topo_prop_set(tnode_t *node, const char *pgname, const char *pname,
-    topo_type_t type, int flag, void *val, int *err)
+    topo_type_t type, int flag, void *val, int nelems, int *err)
 {
+	int ret, new_prop = 0;
 	topo_hdl_t *thp = node->tn_hdl;
 	topo_pgroup_t *pg;
 	topo_propval_t *pv;
@@ -354,13 +630,18 @@
 
 	topo_node_lock(node);
 	if ((pg = pgroup_get(node, pgname)) == NULL)
-		return (set_seterror(node, err, ETOPO_PROP_NOENT));
+		return (set_seterror(node, NULL, err, ETOPO_PROP_NOENT));
 
+	/*
+	 * Replace existing prop value with new one
+	 */
 	if ((pv = propval_get(pg, pname)) != NULL) {
 		if (pv->tp_type != type)
-			return (set_seterror(node, err, ETOPO_PROP_TYPE));
-		else if (pv->tp_flag == TOPO_PROP_SET_ONCE)
-			return (set_seterror(node, err, ETOPO_PROP_DEFD));
+			return (set_seterror(node, NULL, err, ETOPO_PROP_TYPE));
+		else if (pv->tp_flag == TOPO_PROP_IMMUTABLE)
+			return (set_seterror(node, NULL, err, ETOPO_PROP_DEFD));
+		nvlist_free(pv->tp_val);
+		pv->tp_val = NULL;
 	} else {
 		/*
 		 * Property values may be a shared resources among
@@ -369,58 +650,90 @@
 		 */
 		if ((pvl = topo_hdl_zalloc(thp, sizeof (topo_proplist_t)))
 		    == NULL)
-			return (set_seterror(node, err, ETOPO_NOMEM));
+			return (set_seterror(node, NULL, err, ETOPO_NOMEM));
 
 		if ((pv = topo_hdl_zalloc(thp, sizeof (topo_propval_t)))
-		    == NULL) {
-			topo_hdl_free(thp, pvl, sizeof (topo_proplist_t));
-			return (set_seterror(node, err, ETOPO_NOMEM));
-		}
+		    == NULL)
+			return (set_seterror(node, pvl, err, ETOPO_NOMEM));
+		pvl->tp_pval = pv;
+
 		if ((pv->tp_name = topo_hdl_strdup(thp, pname))
-		    == NULL) {
-			topo_hdl_free(thp, pvl, sizeof (topo_proplist_t));
-			topo_hdl_free(thp, pv, sizeof (topo_propval_t));
-			return (set_seterror(node, err, ETOPO_NOMEM));
-		}
+		    == NULL)
+			return (set_seterror(node, pvl, err, ETOPO_NOMEM));
 		pv->tp_flag = flag;
 		pv->tp_type = type;
 		pv->tp_hdl = thp;
 		topo_prop_hold(pv);
-		pvl->tp_pval = pv;
-		topo_list_append(&pg->tpg_pvals, pvl);
-
-
+		new_prop++;
 	}
 
+	if (topo_hdl_nvalloc(thp, &pv->tp_val, NV_UNIQUE_NAME) < 0)
+		return (set_seterror(node, pvl, err, ETOPO_PROP_NVL));
+
+	ret = 0;
 	switch (type) {
 		case TOPO_TYPE_INT32:
-			pv->tp_u.tp_int32 = *(int32_t *)val;
+			ret = nvlist_add_int32(pv->tp_val, TOPO_PROP_VAL_VAL,
+			    *(int32_t *)val);
 			break;
 		case TOPO_TYPE_UINT32:
-			pv->tp_u.tp_uint32 = *(uint32_t *)val;
+			ret = nvlist_add_uint32(pv->tp_val, TOPO_PROP_VAL_VAL,
+			    *(uint32_t *)val);
 			break;
 		case TOPO_TYPE_INT64:
-			pv->tp_u.tp_int64 = *(int64_t *)val;
+			ret = nvlist_add_int64(pv->tp_val, TOPO_PROP_VAL_VAL,
+			    *(int64_t *)val);
 			break;
 		case TOPO_TYPE_UINT64:
-			pv->tp_u.tp_uint64 = *(uint64_t *)val;
+			ret = nvlist_add_uint64(pv->tp_val, TOPO_PROP_VAL_VAL,
+			    *(uint64_t *)val);
 			break;
 		case TOPO_TYPE_STRING:
-			pv->tp_u.tp_string = topo_hdl_strdup(thp, (char *)val);
-			if (pv->tp_u.tp_string == NULL)
-				return (set_seterror(node, err, ETOPO_NOMEM));
-			pv->tp_free = topo_propval_strfree;
+			ret = nvlist_add_string(pv->tp_val, TOPO_PROP_VAL_VAL,
+			    (char *)val);
 			break;
 		case TOPO_TYPE_FMRI:
-			if (topo_hdl_nvdup(thp,
-			    (nvlist_t *)val, &pv->tp_u.tp_fmri) < 0)
-				return (set_seterror(node, err, ETOPO_NOMEM));
-			pv->tp_free = topo_propval_nvlfree;
+			ret = nvlist_add_nvlist(pv->tp_val, TOPO_PROP_VAL_VAL,
+			    (nvlist_t *)val);
+			break;
+		case TOPO_TYPE_INT32_ARRAY:
+			ret = nvlist_add_int32_array(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, (int32_t *)val, nelems);
+			break;
+		case TOPO_TYPE_UINT32_ARRAY:
+			ret = nvlist_add_uint32_array(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, (uint32_t *)val, nelems);
+			break;
+		case TOPO_TYPE_INT64_ARRAY:
+			ret = nvlist_add_int64_array(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, (int64_t *)val, nelems);
+			break;
+		case TOPO_TYPE_UINT64_ARRAY:
+			ret = nvlist_add_uint64_array(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, (uint64_t *)val, nelems);
+			break;
+		case TOPO_TYPE_STRING_ARRAY:
+			ret = nvlist_add_string_array(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, (char **)val, nelems);
+			break;
+		case TOPO_TYPE_FMRI_ARRAY:
+			ret = nvlist_add_nvlist_array(pv->tp_val,
+			    TOPO_PROP_VAL_VAL, (nvlist_t **)val, nelems);
 			break;
 		default:
-			return (set_seterror(node, err, ETOPO_PROP_TYPE));
+			return (set_seterror(node, pvl, err, ETOPO_PROP_TYPE));
 	}
 
+	if (ret != 0) {
+		if (ret == ENOMEM)
+			return (set_seterror(node, pvl, err, ETOPO_NOMEM));
+		else
+			return (set_seterror(node, pvl, err, ETOPO_PROP_NVL));
+	}
+
+	if (new_prop > 0)
+		topo_list_append(&pg->tpg_pvals, pvl);
+
 	topo_node_unlock(node);
 
 	return (0);
@@ -431,7 +744,7 @@
     int flag, int32_t val, int *err)
 {
 	return (topo_prop_set(node, pgname, pname, TOPO_TYPE_INT32, flag,
-	    &val, err));
+	    &val, 1, err));
 }
 
 int
@@ -439,7 +752,7 @@
     int flag, uint32_t val, int *err)
 {
 	return (topo_prop_set(node, pgname, pname, TOPO_TYPE_UINT32, flag,
-	    &val, err));
+	    &val, 1, err));
 }
 
 int
@@ -447,7 +760,7 @@
     int flag, int64_t val, int *err)
 {
 	return (topo_prop_set(node, pgname, pname, TOPO_TYPE_INT64, flag,
-	    &val, err));
+	    &val, 1, err));
 }
 
 int
@@ -455,7 +768,7 @@
     int flag, uint64_t val, int *err)
 {
 	return (topo_prop_set(node, pgname, pname, TOPO_TYPE_UINT64, flag,
-	    &val, err));
+	    &val, 1, err));
 }
 
 int
@@ -463,7 +776,7 @@
     int flag, const char *val, int *err)
 {
 	return (topo_prop_set(node, pgname, pname, TOPO_TYPE_STRING, flag,
-	    (void *)val, err));
+	    (void *)val, 1, err));
 }
 
 int
@@ -471,7 +784,55 @@
     int flag, const nvlist_t *fmri, int *err)
 {
 	return (topo_prop_set(node, pgname, pname, TOPO_TYPE_FMRI, flag,
-	    (void *)fmri, err));
+	    (void *)fmri, 1, err));
+}
+
+int
+topo_prop_set_int32_array(tnode_t *node, const char *pgname, const char *pname,
+    int flag, int32_t *val, uint_t nelems, int *err)
+{
+	return (topo_prop_set(node, pgname, pname, TOPO_TYPE_INT32_ARRAY, flag,
+	    val, nelems, err));
+}
+
+int
+topo_prop_set_uint32_array(tnode_t *node, const char *pgname, const char *pname,
+    int flag, uint32_t *val, uint_t nelems, int *err)
+{
+	return (topo_prop_set(node, pgname, pname, TOPO_TYPE_UINT32_ARRAY, flag,
+	    val, nelems, err));
+}
+
+int
+topo_prop_set_int64_array(tnode_t *node, const char *pgname, const char *pname,
+    int flag, int64_t *val, uint_t nelems, int *err)
+{
+	return (topo_prop_set(node, pgname, pname, TOPO_TYPE_INT64_ARRAY, flag,
+	    val, nelems, err));
+}
+
+int
+topo_prop_set_uint64_array(tnode_t *node, const char *pgname, const char *pname,
+    int flag, uint64_t *val, uint_t nelems, int *err)
+{
+	return (topo_prop_set(node, pgname, pname, TOPO_TYPE_UINT64_ARRAY, flag,
+	    val, nelems, err));
+}
+
+int
+topo_prop_set_string_array(tnode_t *node, const char *pgname, const char *pname,
+    int flag, const char **val, uint_t nelems, int *err)
+{
+	return (topo_prop_set(node, pgname, pname, TOPO_TYPE_STRING_ARRAY, flag,
+	    (void *)val, nelems, err));
+}
+
+int
+topo_prop_set_fmri_array(tnode_t *node, const char *pgname, const char *pname,
+    int flag, const nvlist_t **fmri, uint_t nelems, int *err)
+{
+	return (topo_prop_set(node, pgname, pname, TOPO_TYPE_FMRI_ARRAY, flag,
+	    (void *)fmri, nelems, err));
 }
 
 static int
@@ -508,7 +869,7 @@
 	/*
 	 * Can this propval be inherited?
 	 */
-	if (pv->tp_flag != TOPO_PROP_SET_ONCE)
+	if (pv->tp_flag != TOPO_PROP_IMMUTABLE)
 		return (inherit_seterror(node, err, ETOPO_PROP_NOINHERIT));
 
 	/*
@@ -532,56 +893,108 @@
 	return (0);
 }
 
-int
-topo_prop_stability(tnode_t *node, const char *pgname, topo_stability_t *stab)
+topo_pgroup_info_t *
+topo_pgroup_info(tnode_t *node, const char *pgname, int *err)
 {
+	topo_hdl_t *thp = node->tn_hdl;
 	topo_pgroup_t *pg;
+	topo_ipgroup_info_t *pip;
+	topo_pgroup_info_t *info;
 
+	topo_node_lock(node);
 	for (pg = topo_list_next(&node->tn_pgroups); pg != NULL;
 	    pg = topo_list_next(pg)) {
-		if (strcmp(pgname, pg->tpg_name) == 0) {
-			*stab = pg->tpg_stability;
-			return (0);
+		if (strcmp(pgname, pg->tpg_info->tpi_name) == 0) {
+			if ((info = topo_hdl_alloc(thp,
+			    sizeof (topo_pgroup_info_t))) == NULL)
+				return (NULL);
+
+			pip = pg->tpg_info;
+			if ((info->tpi_name =
+				topo_hdl_strdup(thp, pip->tpi_name)) == NULL) {
+				*err = ETOPO_PROP_NOMEM;
+				topo_hdl_free(thp, info,
+				    sizeof (topo_pgroup_info_t));
+				topo_node_unlock(node);
+				return (NULL);
+			}
+			info->tpi_namestab = pip->tpi_namestab;
+			info->tpi_datastab = pip->tpi_datastab;
+			info->tpi_version = pip->tpi_version;
+			topo_node_unlock(node);
+			return (info);
 		}
 	}
 
+	*err = ETOPO_PROP_NOENT;
+	topo_node_unlock(node);
+	return (NULL);
+}
+
+static int
+pgroup_seterr(tnode_t *node, topo_pgroup_t *pg, topo_ipgroup_info_t *pip,
+    int *err)
+{
+	topo_hdl_t *thp = node->tn_hdl;
+
+	if (pip != NULL) {
+		if (pip->tpi_name != NULL)
+			topo_hdl_strfree(thp, (char *)pip->tpi_name);
+		topo_hdl_free(thp, pip, sizeof (topo_ipgroup_info_t));
+	}
+
+	topo_hdl_free(thp, pg, sizeof (topo_pgroup_t));
+	*err = ETOPO_NOMEM;
+
+	topo_node_unlock(node);
+
 	return (-1);
 }
 
 int
-topo_pgroup_create(tnode_t *node, const char *pname, topo_stability_t stab,
-    int *err)
+topo_pgroup_create(tnode_t *node, const topo_pgroup_info_t *pinfo, int *err)
 {
 	topo_pgroup_t *pg;
+	topo_ipgroup_info_t *pip;
+	topo_hdl_t *thp = node->tn_hdl;
 
 	*err = 0;
 
+	topo_node_lock(node);
 	/*
 	 * Check for an existing pgroup
 	 */
 	for (pg = topo_list_next(&node->tn_pgroups); pg != NULL;
 	    pg = topo_list_next(pg)) {
-		if (strcmp(pg->tpg_name, pname) == 0) {
+		if (strcmp(pg->tpg_info->tpi_name, pinfo->tpi_name) == 0) {
 			*err = ETOPO_PROP_DEFD;
+			topo_node_unlock(node);
 			return (-1);
 		}
 	}
 
-	if ((pg = topo_hdl_zalloc(node->tn_hdl,
-	    sizeof (topo_pgroup_t))) == NULL) {
+	if ((pg = topo_hdl_zalloc(thp, sizeof (topo_pgroup_t))) == NULL) {
 		*err = ETOPO_NOMEM;
+		topo_node_unlock(node);
 		return (-1);
 	}
 
-	if ((pg->tpg_name = topo_hdl_strdup(node->tn_hdl, pname)) == NULL) {
-		topo_hdl_free(node->tn_hdl, pg, sizeof (topo_pgroup_t));
-		*err = ETOPO_NOMEM;
-		return (-1);
-	}
+	if ((pip = topo_hdl_zalloc(thp, sizeof (topo_ipgroup_info_t)))
+	    == NULL)
+		return (pgroup_seterr(node, pg, pip, err));
 
-	pg->tpg_stability = stab;
+	if ((pip->tpi_name = topo_hdl_strdup(thp, pinfo->tpi_name))
+	    == NULL)
+		return (pgroup_seterr(node, pg, pip, err));
+
+	pip->tpi_namestab = pinfo->tpi_namestab;
+	pip->tpi_datastab = pinfo->tpi_datastab;
+	pip->tpi_version = pinfo->tpi_version;
+
+	pg->tpg_info = pip;
 
 	topo_list_append(&node->tn_pgroups, pg);
+	topo_node_unlock(node);
 
 	return (0);
 }
@@ -592,11 +1005,12 @@
 	topo_hdl_t *thp = node->tn_hdl;
 	topo_pgroup_t *pg;
 	topo_proplist_t *pvl;
+	topo_ipgroup_info_t *pip;
 
 	topo_node_lock(node);
 	for (pg = topo_list_next(&node->tn_pgroups); pg != NULL;
 	    pg = topo_list_next(pg)) {
-		if (strcmp(pg->tpg_name, pname) == 0) {
+		if (strcmp(pg->tpg_info->tpi_name, pname) == 0) {
 			break;
 		}
 	}
@@ -613,12 +1027,16 @@
 	}
 
 	topo_list_delete(&node->tn_pgroups, pg);
+	topo_node_unlock(node);
 
-	if (pg->tpg_name != NULL)
-		topo_hdl_strfree(thp, pg->tpg_name);
+	pip = pg->tpg_info;
+	if (pip != NULL) {
+		if (pip->tpi_name != NULL)
+			topo_hdl_strfree(thp, (char *)pip->tpi_name);
+		topo_hdl_free(thp, pip, sizeof (topo_ipgroup_info_t));
+	}
+
 	topo_hdl_free(thp, pg, sizeof (topo_pgroup_t));
-
-	topo_node_unlock(node);
 }
 
 void
@@ -627,6 +1045,7 @@
 	topo_hdl_t *thp = node->tn_hdl;
 	topo_pgroup_t *pg;
 	topo_proplist_t *pvl;
+	topo_ipgroup_info_t *pip;
 
 	topo_node_lock(node);
 	while ((pg = topo_list_next(&node->tn_pgroups)) != NULL) {
@@ -638,8 +1057,13 @@
 
 		topo_list_delete(&node->tn_pgroups, pg);
 
-		if (pg->tpg_name != NULL)
-			topo_hdl_strfree(thp, pg->tpg_name);
+		pip = pg->tpg_info;
+		if (pip != NULL) {
+			if (pip->tpi_name != NULL)
+				topo_hdl_strfree(thp, (char *)pip->tpi_name);
+			topo_hdl_free(thp, pip, sizeof (topo_pgroup_info_t));
+		}
+
 		topo_hdl_free(thp, pg, sizeof (topo_pgroup_t));
 	}
 	topo_node_unlock(node);
@@ -652,8 +1076,8 @@
 	if (pv->tp_name != NULL)
 		topo_hdl_strfree(thp, pv->tp_name);
 
-	if (pv->tp_free != NULL)
-		pv->tp_free(pv);
+	if (pv->tp_val != NULL)
+		nvlist_free(pv->tp_val);
 
 	topo_hdl_free(thp, pv, sizeof (topo_propval_t));
 }
--- a/usr/src/lib/fm/topo/libtopo/common/topo_prop.h	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_prop.h	Sat Nov 04 01:18:55 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -37,28 +36,27 @@
 extern "C" {
 #endif
 
+typedef struct topo_ipgroup_info {
+	char *tpi_name;			/* property group name */
+	topo_stability_t tpi_namestab;	/* stability of group name */
+	topo_stability_t tpi_datastab;	/* stability of all property values */
+	topo_version_t  tpi_version;	/* version of pgroup definition */
+} topo_ipgroup_info_t;
+
 typedef struct topo_pgroup {
 	topo_list_t tpg_list;		/* next/prev pointers */
-	char *tpg_name;			/* Group name */
-	topo_stability_t tpg_stability;	/* SMI Stability level */
-	topo_list_t tpg_pvals;		/* Property values */
+	topo_ipgroup_info_t *tpg_info;	/* name, version, stability */
+	topo_list_t tpg_pvals;		/* property values */
 } topo_pgroup_t;
 
 typedef struct topo_propval {
-	char *tp_name;			/* Prop name */
-	topo_type_t tp_type;		/* Prop type */
-	int tp_flag;			/* Dynamic property */
+	char *tp_name;			/* prop name */
+	topo_type_t tp_type;		/* prop type */
+	int tp_flag;			/* dynamic property */
 	int tp_refs;			/* ref count for this prop val */
 	topo_hdl_t *tp_hdl;		/* handle pointer for allocations */
-	void (*tp_free)(struct topo_propval *); /* Prop value destructor */
-	union {
-		int32_t tp_int32;
-		int32_t tp_uint32;
-		int64_t tp_int64;
-		int64_t tp_uint64;
-		char *tp_string;
-		nvlist_t *tp_fmri;
-	} tp_u;
+	void (*tp_free)(struct topo_propval *); /* prop value destructor */
+	nvlist_t *tp_val;
 } topo_propval_t;
 
 typedef struct topo_proplist {
@@ -66,7 +64,6 @@
 	topo_propval_t *tp_pval;	/* actual value */
 } topo_proplist_t;
 
-extern int topo_prop_inherit(tnode_t *, const char *, const char *, int *);
 extern void topo_prop_hold(topo_propval_t *);
 extern void topo_prop_rele(topo_propval_t *);
 extern void topo_pgroup_destroy_all(tnode_t *);
--- a/usr/src/lib/fm/topo/libtopo/common/topo_protocol.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_protocol.c	Sat Nov 04 01:18:55 2006 -0800
@@ -32,6 +32,7 @@
 
 #include <topo_alloc.h>
 #include <topo_error.h>
+#include <topo_method.h>
 #include <topo_protocol.h>
 #include <topo_subr.h>
 
@@ -157,7 +158,7 @@
 			node->tn_fflags |= TOPO_ASRU_COMPUTE;
 
 		if (topo_prop_set_fmri(node, TOPO_PGROUP_PROTOCOL,
-		    TOPO_PROP_ASRU, TOPO_PROP_SET_ONCE, asru, err) < 0)
+		    TOPO_PROP_ASRU, TOPO_PROP_IMMUTABLE, asru, err) < 0)
 			return (-1);
 	}
 
@@ -184,7 +185,7 @@
 			node->tn_fflags |= TOPO_FRU_COMPUTE;
 
 		if (topo_prop_set_fmri(node, TOPO_PGROUP_PROTOCOL,
-		    TOPO_PROP_FRU, TOPO_PROP_SET_ONCE, fru, err) < 0)
+		    TOPO_PROP_FRU, TOPO_PROP_IMMUTABLE, fru, err) < 0)
 			return (-1);
 	}
 
@@ -194,6 +195,7 @@
 int
 topo_node_label_set(tnode_t *node, char *label, int *err)
 {
+
 	/*
 	 * Inherit FRU property from our parent if * not specified
 	 */
@@ -204,7 +206,7 @@
 		}
 	} else {
 		if (topo_prop_set_string(node, TOPO_PGROUP_PROTOCOL,
-		    TOPO_PROP_LABEL, TOPO_PROP_SET_ONCE, label, err) < 0)
+		    TOPO_PROP_LABEL, TOPO_PROP_IMMUTABLE, label, err) < 0)
 			return (-1);
 	}
 
--- a/usr/src/lib/fm/topo/libtopo/common/topo_rtld.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_rtld.c	Sat Nov 04 01:18:55 2006 -0800
@@ -38,8 +38,8 @@
 
 typedef struct topo_rtld {
 	void *rtld_dlp;		/* libdl(3DL) handle for shared library */
-	int (*rtld_init)(topo_mod_t *); /* shared library's _topo_init() */
-	void (*rtld_fini)(topo_mod_t *); /* shared library's _topo_fini() */
+	int (*rtld_init)(topo_mod_t *, topo_version_t); /* .so _topo_init() */
+	void (*rtld_fini)(topo_mod_t *); /* .so _topo_fini() */
 } topo_rtld_t;
 
 static int
@@ -64,14 +64,14 @@
 }
 
 static int
-rtld_init(topo_mod_t *mod)
+rtld_init(topo_mod_t *mod, topo_version_t version)
 {
 	int err;
 	topo_rtld_t *rp;
 	void *dlp;
 
 	if ((dlp = dlopen(mod->tm_path, RTLD_LOCAL | RTLD_NOW)) == NULL) {
-		topo_dprintf(TOPO_DBG_ERR,
+		topo_dprintf(mod->tm_hdl, TOPO_DBG_ERR,
 		    "dlopen() failed: %s\n", dlerror());
 		return (topo_mod_seterrno(mod, ETOPO_RTLD_OPEN));
 	}
@@ -93,7 +93,7 @@
 	/*
 	 * Call _topo_init() in the module.
 	 */
-	err = rp->rtld_init(mod);
+	err = rp->rtld_init(mod, version);
 
 	if (err < 0 || !(mod->tm_flags & TOPO_MOD_REG)) {
 		(void) rtld_fini(mod);
@@ -103,7 +103,7 @@
 	return (0);
 }
 
-const topo_modops_t topo_rtld_ops = {
+const topo_imodops_t topo_rtld_ops = {
 	rtld_init,
 	rtld_fini,
 };
--- a/usr/src/lib/fm/topo/libtopo/common/topo_snap.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_snap.c	Sat Nov 04 01:18:55 2006 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -69,12 +68,18 @@
  * and release nodes that may be still held.
  */
 
+#include <alloca.h>
+#include <ctype.h>
 #include <pthread.h>
 #include <limits.h>
 #include <assert.h>
 #include <fcntl.h>
+#include <smbios.h>
+#include <sys/param.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/systeminfo.h>
+#include <sys/utsname.h>
 #include <uuid/uuid.h>
 
 #include <fm/libtopo.h>
@@ -98,18 +103,57 @@
 	return (NULL);
 }
 
+static char *
+smbios_fix(topo_hdl_t *thp, char *begin)
+{
+	char buf[MAXNAMELEN];
+	size_t count;
+	char *str, *end, *pp;
+
+	end = begin + strlen(begin);
+
+	while (begin < end && isspace(*begin))
+		begin++;
+	while (begin < end && isspace(*(end - 1)))
+		end--;
+
+	if (begin >= end)
+		return (NULL);
+
+	count = end - begin;
+	count += 1;
+
+	if (count > sizeof (buf))
+		return (NULL);
+
+	(void) snprintf(buf, count, "%s", begin);
+	while ((str = strchr(buf, ' ')) != NULL)
+		*str = '-';
+
+	pp = topo_hdl_strdup(thp, buf);
+	return (pp);
+}
+
 topo_hdl_t *
 topo_open(int version, const char *rootdir, int *errp)
 {
 	topo_hdl_t *thp = NULL;
 	topo_alloc_t *tap;
+
+	char platform[MAXNAMELEN];
+	char isa[MAXNAMELEN];
+	struct utsname uts;
 	struct stat st;
 
-	if (version < TOPO_VERSION)
-		return (set_open_errno(thp, errp, ETOPO_HDL_VER));
+	smbios_hdl_t *shp;
+	smbios_system_t s1;
+	smbios_info_t s2;
+	id_t id;
 
-	if (version > TOPO_VERSION)
-		return (set_open_errno(thp, errp, ETOPO_HDL_VER));
+	char *dbflags, *dbout;
+
+	if (version != TOPO_VERSION)
+		return (set_open_errno(thp, errp, ETOPO_HDL_ABIVER));
 
 	if (rootdir != NULL && stat(rootdir, &st) < 0)
 		return (set_open_errno(thp, errp, ETOPO_HDL_INVAL));
@@ -117,8 +161,12 @@
 	if ((thp = topo_zalloc(sizeof (topo_hdl_t), 0)) == NULL)
 		return (set_open_errno(thp, errp, ETOPO_NOMEM));
 
-	if ((tap = topo_zalloc(sizeof (topo_alloc_t), 0)) == NULL)
+	(void) pthread_mutex_init(&thp->th_lock, NULL);
+
+	if ((tap = topo_zalloc(sizeof (topo_alloc_t), 0)) == NULL) {
+		topo_close(thp);
 		return (set_open_errno(thp, errp, ETOPO_NOMEM));
+	}
 
 	/*
 	 * Install default allocators
@@ -135,22 +183,68 @@
 	if ((thp->th_modhash = topo_modhash_create(thp)) == NULL)
 		return (set_open_errno(thp, errp, ETOPO_NOMEM));
 
+	/*
+	 * Set-up system information and search paths for modules
+	 * and topology map files
+	 */
 	if (rootdir == NULL) {
 		rootdir = topo_hdl_strdup(thp, "/");
 		thp->th_rootdir = (char *)rootdir;
 	} else {
-		if (strlen(rootdir) > PATH_MAX)
+		int len;
+		char *rpath;
+
+		len = strlen(rootdir);
+		if (len >= PATH_MAX)
 			return (set_open_errno(thp, errp, EINVAL));
 
-		thp->th_rootdir = topo_hdl_strdup(thp, rootdir);
+		if (rootdir[len] != '/') {
+			rpath = alloca(len + 1);
+			(void) snprintf(rpath, len + 1, "%s/", rootdir);
+		} else {
+			rpath = (char *)rootdir;
+		}
+		thp->th_rootdir = topo_hdl_strdup(thp, rpath);
 	}
 
-	if (thp->th_rootdir == NULL)
+	platform[0] = '\0';
+	isa[0] = '\0';
+	(void) sysinfo(SI_PLATFORM, platform, sizeof (platform));
+	(void) sysinfo(SI_ARCHITECTURE, isa, sizeof (isa));
+	(void) uname(&uts);
+	thp->th_platform = topo_hdl_strdup(thp, platform);
+	thp->th_isa = topo_hdl_strdup(thp, isa);
+	thp->th_machine = topo_hdl_strdup(thp, uts.machine);
+	if ((shp = smbios_open(NULL, SMB_VERSION, 0, NULL)) != NULL) {
+		if ((id = smbios_info_system(shp, &s1)) != SMB_ERR &&
+		    smbios_info_common(shp, id, &s2) != SMB_ERR) {
+
+			if (strcmp(s2.smbi_product, SMB_DEFAULT1) != 0 &&
+			    strcmp(s2.smbi_product, SMB_DEFAULT2) != 0) {
+				thp->th_product = smbios_fix(thp,
+				    (char *)s2.smbi_product);
+			}
+		}
+		smbios_close(shp);
+	} else {
+		thp->th_product = topo_hdl_strdup(thp, thp->th_platform);
+	}
+
+	if (thp->th_rootdir == NULL) {
+		topo_close(thp);
 		return (set_open_errno(thp, errp, ETOPO_NOMEM));
+	}
+
+	dbflags	 = getenv("TOPO_DEBUG");
+	dbout = getenv("TOPO_DEBUG_OUT");
+	if (dbflags != NULL)
+		topo_debug_set(thp, dbflags, dbout);
 
 	if (topo_builtin_create(thp, thp->th_rootdir) != 0) {
-		topo_dprintf(TOPO_DBG_ERR, "failed to load builtin modules: "
-		    "%s\n", topo_hdl_errmsg(thp));
+		topo_dprintf(thp, TOPO_DBG_ERR,
+		    "failed to load builtin modules: %s\n",
+		    topo_hdl_errmsg(thp));
+		topo_close(thp);
 		return (NULL);
 	}
 
@@ -163,6 +257,14 @@
 	ttree_t *tp;
 
 	topo_hdl_lock(thp);
+	if (thp->th_platform != NULL)
+		topo_hdl_strfree(thp, thp->th_platform);
+	if (thp->th_isa != NULL)
+		topo_hdl_strfree(thp, thp->th_isa);
+	if (thp->th_machine != NULL)
+		topo_hdl_strfree(thp, thp->th_machine);
+	if (thp->th_product != NULL)
+		topo_hdl_strfree(thp, thp->th_product);
 	if (thp->th_rootdir != NULL)
 		topo_hdl_strfree(thp, thp->th_rootdir);
 
@@ -176,7 +278,7 @@
 	 */
 	while ((tp = topo_list_next(&thp->th_trees)) != NULL) {
 		topo_list_delete(&thp->th_trees, tp);
-		topo_tree_destroy(thp, tp);
+		topo_tree_destroy(tp);
 	}
 
 	/*
@@ -209,7 +311,7 @@
 
 	if ((thp->th_uuid = topo_hdl_zalloc(thp, TOPO_UUID_SIZE)) == NULL) {
 		*errp = ETOPO_NOMEM;
-		topo_dprintf(TOPO_DBG_ERR, "unable to allocate uuid: %s\n",
+		topo_dprintf(thp, TOPO_DBG_ERR, "unable to allocate uuid: %s\n",
 		    topo_strerror(*errp));
 		topo_hdl_unlock(thp);
 		return (NULL);
@@ -219,9 +321,9 @@
 	uuid_unparse(uuid, thp->th_uuid);
 
 	if (topo_tree_enum_all(thp) < 0) {
-		topo_dprintf(TOPO_DBG_ERR, "enumeration failure: %s\n",
+		topo_dprintf(thp, TOPO_DBG_ERR, "enumeration failure: %s\n",
 		    topo_hdl_errmsg(thp));
-		if (topo_hdl_errno(thp) != ETOPO_ENUM_PARTIAL) {
+		if (topo_hdl_errno(thp) == ETOPO_ENUM_FATAL) {
 			*errp = thp->th_errno;
 			topo_hdl_unlock(thp);
 			return (NULL);
@@ -231,6 +333,9 @@
 	if ((ustr = topo_hdl_strdup(thp, thp->th_uuid)) == NULL)
 		*errp = ETOPO_NOMEM;
 
+	thp->th_di = DI_NODE_NIL;
+	thp->th_pi = DI_PROM_HANDLE_NIL;
+
 	topo_hdl_unlock(thp);
 
 	return (ustr);
@@ -316,14 +421,12 @@
 			topo_mod_rele(mod);
 		}
 
-		/*
-		 * Release the file handle
-		 */
-		if (tp->tt_file != NULL)
-			topo_file_unload(thp, tp);
-
 	}
 
+	if (thp->th_uuid != NULL) {
+		topo_hdl_free(thp, thp->th_uuid, TOPO_UUID_SIZE);
+		thp->th_uuid = NULL;
+	}
 }
 
 void
@@ -333,11 +436,7 @@
 		return;
 
 	topo_hdl_lock(thp);
-	if (thp->th_uuid != NULL) {
-		topo_hdl_free(thp, thp->th_uuid, TOPO_UUID_SIZE);
-		topo_snap_destroy(thp);
-		thp->th_uuid = NULL;
-	}
+	topo_snap_destroy(thp);
 	topo_hdl_unlock(thp);
 
 }
@@ -405,7 +504,8 @@
 	if (nnp == NULL)
 		return (TOPO_WALK_TERMINATE);
 
-	topo_dprintf(TOPO_DBG_WALK, "walk through child node %s=%d\n",
+	topo_dprintf(wp->tw_thp, TOPO_DBG_WALK,
+	    "walk through child node %s=%d\n",
 	    nnp->tn_name, nnp->tn_instance);
 
 	topo_node_hold(nnp); /* released on return from walk_step */
@@ -429,7 +529,8 @@
 	if (nnp == NULL)
 		return (TOPO_WALK_TERMINATE);
 
-	topo_dprintf(TOPO_DBG_WALK, "walk through sibling node %s=%d\n",
+	topo_dprintf(wp->tw_thp, TOPO_DBG_WALK,
+	    "walk through sibling node %s=%d\n",
 	    nnp->tn_name, nnp->tn_instance);
 
 	topo_node_hold(nnp); /* released on return from walk_step */
@@ -457,12 +558,14 @@
 	 * End of the line
 	 */
 	if (cnp == NULL) {
-		topo_dprintf(TOPO_DBG_WALK, "walk_step terminated\n");
+		topo_dprintf(wp->tw_thp, TOPO_DBG_WALK,
+		    "walk_step terminated\n");
 		topo_node_rele(cnp);
 		return (TOPO_WALK_TERMINATE);
 	}
 
-	topo_dprintf(TOPO_DBG_WALK, "%s walk_step through node %s=%d\n",
+	topo_dprintf(wp->tw_thp, TOPO_DBG_WALK,
+	    "%s walk_step through node %s=%d\n",
 	    (flag == TOPO_WALK_CHILD ? "TOPO_WALK_CHILD" : "TOPO_WALK_SIBLING"),
 	    cnp->tn_name, cnp->tn_instance);
 
@@ -522,12 +625,14 @@
 	 * End of the line
 	 */
 	if (cnp == NULL) {
-		topo_dprintf(TOPO_DBG_WALK, "walk_bottomup terminated\n");
+		topo_dprintf(wp->tw_thp, TOPO_DBG_WALK,
+		    "walk_bottomup terminated\n");
 		topo_node_rele(cnp);
 		return (TOPO_WALK_TERMINATE);
 	}
 
-	topo_dprintf(TOPO_DBG_WALK, "%s walk_bottomup through node %s=%d\n",
+	topo_dprintf(wp->tw_thp, TOPO_DBG_WALK,
+	    "%s walk_bottomup through node %s=%d\n",
 	    (flag == TOPO_WALK_CHILD ? "TOPO_WALK_CHILD" : "TOPO_WALK_SIBLING"),
 	    cnp->tn_name, cnp->tn_instance);
 
--- a/usr/src/lib/fm/topo/libtopo/common/topo_subr.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_subr.c	Sat Nov 04 01:18:55 2006 -0800
@@ -27,8 +27,11 @@
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 #include <alloca.h>
+#include <ctype.h>
+#include <limits.h>
 #include <syslog.h>
 #include <strings.h>
+#include <unistd.h>
 
 #include <topo_error.h>
 #include <topo_subr.h>
@@ -36,9 +39,6 @@
 struct _rwlock;
 struct _lwp_mutex;
 
-int _topo_debug = 0;	/* debug messages enabled (off) */
-int _topo_dbout = 0;	/* debug messages output mode */
-
 int
 topo_rw_read_held(pthread_rwlock_t *lock)
 {
@@ -73,50 +73,133 @@
 }
 
 const char *
-topo_stability_name(topo_stability_t s)
+topo_stability2name(topo_stability_t s)
 {
 	switch (s) {
-	case TOPO_STABILITY_INTERNAL:	return ("Internal");
-	case TOPO_STABILITY_PRIVATE:	return ("Private");
-	case TOPO_STABILITY_OBSOLETE:	return ("Obsolete");
-	case TOPO_STABILITY_EXTERNAL:	return ("External");
-	case TOPO_STABILITY_UNSTABLE:	return ("Unstable");
-	case TOPO_STABILITY_EVOLVING:	return ("Evolving");
-	case TOPO_STABILITY_STABLE:	return ("Stable");
-	case TOPO_STABILITY_STANDARD:	return ("Standard");
-	default:			return (NULL);
+	case TOPO_STABILITY_INTERNAL:	return (TOPO_STABSTR_INTERNAL);
+	case TOPO_STABILITY_PRIVATE:	return (TOPO_STABSTR_PRIVATE);
+	case TOPO_STABILITY_OBSOLETE:	return (TOPO_STABSTR_OBSOLETE);
+	case TOPO_STABILITY_EXTERNAL:	return (TOPO_STABSTR_EXTERNAL);
+	case TOPO_STABILITY_UNSTABLE:	return (TOPO_STABSTR_UNSTABLE);
+	case TOPO_STABILITY_EVOLVING:	return (TOPO_STABSTR_EVOLVING);
+	case TOPO_STABILITY_STABLE:	return (TOPO_STABSTR_STABLE);
+	case TOPO_STABILITY_STANDARD:	return (TOPO_STABSTR_STANDARD);
+	default:			return (TOPO_STABSTR_UNKNOWN);
 	}
 }
 
+topo_stability_t
+topo_name2stability(const char *name)
+{
+	if (strcmp(name, TOPO_STABSTR_INTERNAL) == 0)
+		return (TOPO_STABILITY_INTERNAL);
+	else if (strcmp(name, TOPO_STABSTR_PRIVATE) == 0)
+		return (TOPO_STABILITY_PRIVATE);
+	else if (strcmp(name, TOPO_STABSTR_OBSOLETE) == 0)
+		return (TOPO_STABILITY_OBSOLETE);
+	else if (strcmp(name, TOPO_STABSTR_EXTERNAL) == 0)
+		return (TOPO_STABILITY_EXTERNAL);
+	else if (strcmp(name, TOPO_STABSTR_UNSTABLE) == 0)
+		return (TOPO_STABILITY_UNSTABLE);
+	else if (strcmp(name, TOPO_STABSTR_EVOLVING) == 0)
+		return (TOPO_STABILITY_EVOLVING);
+	else if (strcmp(name, TOPO_STABSTR_STABLE) == 0)
+		return (TOPO_STABILITY_STABLE);
+	else if (strcmp(name, TOPO_STABSTR_STANDARD) == 0)
+		return (TOPO_STABILITY_STANDARD);
+
+	return (TOPO_STABILITY_UNKNOWN);
+}
+
 static const topo_debug_mode_t _topo_dbout_modes[] = {
 	{ "stderr", "send debug messages to stderr", TOPO_DBOUT_STDERR },
 	{ "syslog", "send debug messages to syslog", TOPO_DBOUT_SYSLOG },
 	{ NULL, NULL, 0 }
 };
 
+static const topo_debug_mode_t _topo_dbflag_modes[] = {
+	{ "error", "error handling debug messages enabled", TOPO_DBG_ERR },
+	{ "module", "module debug messages enabled", TOPO_DBG_MOD },
+	{ "modulesvc", "module services debug messages enabled",
+	    TOPO_DBG_MODSVC },
+	{ "walk", "walker subsystem debug messages enabled", TOPO_DBG_WALK },
+	{ "xml", "xml file parsing messages enabled", TOPO_DBG_XML },
+	{ "all", "all debug modes enabled", TOPO_DBG_ALL},
+	{ NULL, NULL, 0 }
+};
+
 void
-topo_debug_set(topo_hdl_t *thp, int mask, char *dout)
+env_process_value(topo_hdl_t *thp, const char *begin, const char *end)
 {
-	int i;
+	char buf[MAXNAMELEN];
+	size_t count;
+	topo_debug_mode_t *dbp;
 
-	for (i = 0; i < 2; ++i) {
-		if (strcmp(_topo_dbout_modes[i].tdm_name, dout) == 0) {
-			thp->th_dbout = _topo_dbout =
-			    _topo_dbout_modes[i].tdm_mode;
-			thp->th_debug = _topo_debug = mask;
-			topo_dprintf(mask, _topo_dbout_modes[i].tdm_desc);
-		}
+	while (begin < end && isspace(*begin))
+		begin++;
+
+	while (begin < end && isspace(*(end - 1)))
+		end--;
+
+	if (begin >= end)
+		return;
+
+	count = end - begin;
+	count += 1;
+
+	if (count > sizeof (buf))
+		return;
+
+	(void) snprintf(buf, count, "%s", begin);
+
+	for (dbp = (topo_debug_mode_t *)_topo_dbflag_modes;
+	    dbp->tdm_name != NULL; ++dbp) {
+		if (strcmp(buf, dbp->tdm_name) == 0)
+			thp->th_debug |= dbp->tdm_mode;
 	}
 }
 
 void
-topo_vdprintf(int mask, const char *format, va_list ap)
+topo_debug_set(topo_hdl_t *thp, const char *dbmode, const char *dout)
+{
+	char *end, *value, *next;
+	topo_debug_mode_t *dbp;
+
+	topo_hdl_lock(thp);
+	value = (char *)dbmode;
+
+	for (end = (char *)dbmode; *end != '\0'; value = next) {
+		end = strchr(value, ',');
+		if (end != NULL)
+			next = end + 1;	/* skip the comma */
+		else
+			next = end = value + strlen(value);
+
+		env_process_value(thp, value, end);
+	}
+
+	if (dout == NULL) {
+		topo_hdl_unlock(thp);
+		return;
+	}
+
+	for (dbp = (topo_debug_mode_t *)_topo_dbout_modes;
+	    dbp->tdm_name != NULL; ++dbp) {
+		if (strcmp(dout, dbp->tdm_name) == 0)
+		thp->th_dbout = dbp->tdm_mode;
+	}
+	topo_hdl_unlock(thp);
+}
+
+void
+topo_vdprintf(topo_hdl_t *thp, int mask, const char *mod, const char *format,
+    va_list ap)
 {
 	char *msg;
 	size_t len;
 	char c;
 
-	if (!(_topo_debug & mask))
+	if (!(thp->th_debug & mask))
 		return;
 
 	len = vsnprintf(&c, 1, format, ap);
@@ -126,24 +209,31 @@
 	if (msg[len - 1] != '\n')
 		(void) strcpy(&msg[len], "\n");
 
-	if (_topo_dbout == TOPO_DBOUT_STDERR)
-		(void) fprintf(stderr, "libtopo DEBUG: %s", msg);
-
-	if (_topo_dbout == TOPO_DBOUT_SYSLOG)
-		syslog(LOG_DEBUG | LOG_USER, "libtopo DEBUG: %s", msg);
+	if (thp->th_dbout == TOPO_DBOUT_SYSLOG) {
+		if (mod == NULL) {
+			syslog(LOG_DEBUG | LOG_USER, "libtopo DEBUG: %s", msg);
+		} else {
+			syslog(LOG_DEBUG | LOG_USER, "libtopo DEBUG: %s: %s",
+			    mod, msg);
+		}
+	} else {
+		if (mod == NULL) {
+			(void) fprintf(stderr, "libtopo DEBUG: %s", msg);
+		} else {
+			(void) fprintf(stderr, "libtopo DEBUG: %s: %s", mod,
+			    msg);
+		}
+	}
 }
 
-/*PRINTFLIKE2*/
+/*PRINTFLIKE3*/
 void
-topo_dprintf(int mask, const char *format, ...)
+topo_dprintf(topo_hdl_t *thp, int mask, const char *format, ...)
 {
 	va_list ap;
 
-	if (!(_topo_debug & mask))
-		return;
-
 	va_start(ap, format);
-	topo_vdprintf(mask, format, ap);
+	topo_vdprintf(thp, mask, NULL, format, ap);
 	va_end(ap);
 }
 
@@ -191,3 +281,35 @@
 	else
 		*sz += snprintf(buf, left, "%s%s%s", prepend, str, append);
 }
+
+#define	TOPO_PLATFORM_PATH	"%s/usr/platform/%s/lib/fm/topo/%s"
+#define	TOPO_COMMON_PATH	"%s/usr/lib/fm/topo/%s"
+
+char *
+topo_search_path(topo_mod_t *mod, const char *rootdir, const char *file)
+{
+	char *pp, sp[PATH_MAX];
+	topo_hdl_t *thp = mod->tm_hdl;
+
+	/*
+	 * Search for file name in order of platform, machine and common
+	 * topo directories
+	 */
+	(void) snprintf(sp, PATH_MAX, TOPO_PLATFORM_PATH, rootdir,
+	    thp->th_platform, file);
+	if (access(sp, F_OK) != 0) {
+		(void) snprintf(sp, PATH_MAX, TOPO_PLATFORM_PATH,
+		    thp->th_rootdir, thp->th_machine, file);
+		if (access(sp, F_OK) != 0) {
+			(void) snprintf(sp, PATH_MAX, TOPO_COMMON_PATH,
+			    thp->th_rootdir, file);
+			if (access(sp, F_OK) != 0) {
+				return (NULL);
+			}
+		}
+	}
+
+	pp = topo_mod_strdup(mod, sp);
+
+	return (pp);
+}
--- a/usr/src/lib/fm/topo/libtopo/common/topo_subr.h	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_subr.h	Sat Nov 04 01:18:55 2006 -0800
@@ -48,6 +48,24 @@
 #define	TOPO_DBOUT_STDERR	0	/* Debug messages to stderr */
 #define	TOPO_DBOUT_SYSLOG	1	/* Debug messages to syslog */
 
+#define	TOPO_DBG_ERR	0x0001	/* enable error handling debug messages */
+#define	TOPO_DBG_MOD	0x0002	/* enable module debug messages */
+#define	TOPO_DBG_MODSVC	0x0004	/* enable module services debug messages */
+#define	TOPO_DBG_WALK	0x0008	/* enable walker debug messages */
+#define	TOPO_DBG_XML	0x0010	/* enable xml parsing debug messages */
+#define	TOPO_DBG_ALL	0xffff	/* enable all debug modes */
+
+#define	TOPO_STABSTR_INTERNAL	"Internal"	/* private to libtopo */
+#define	TOPO_STABSTR_PRIVATE	"Private"	/* private to Sun */
+#define	TOPO_STABSTR_OBSOLETE	"Obsolete"	/* scheduled for removal */
+#define	TOPO_STABSTR_EXTERNAL	"External"	/* not controlled by Sun */
+#define	TOPO_STABSTR_UNSTABLE	"Unstable"	/* new or rapidly changing */
+#define	TOPO_STABSTR_EVOLVING	"Evolving"	/* less rapidly changing */
+#define	TOPO_STABSTR_STABLE	"Stable"	/* mature interface from Sun */
+#define	TOPO_STABSTR_STANDARD	"Standard"	/* industry standard */
+#define	TOPO_STABSTR_UNKNOWN	"Unknown"	/* stability unknown */
+
+
 extern int topo_rw_read_held(pthread_rwlock_t *);
 extern int topo_rw_write_held(pthread_rwlock_t *);
 extern int topo_mutex_held(pthread_mutex_t *);
@@ -60,10 +78,12 @@
 extern int topo_version_str2num(const char *, topo_version_t);
 extern int topo_version_defined(topo_version_t);
 
-extern void topo_dprintf(int, const char *, ...);
-extern void topo_vdprintf(int, const char *, va_list);
+extern void topo_dprintf(topo_hdl_t *, int, const char *, ...);
+extern void topo_vdprintf(topo_hdl_t *, int, const char *, const char *,
+    va_list);
 
 extern tnode_t *topo_hdl_root(topo_hdl_t *, const char *);
+extern char *topo_search_path(topo_mod_t *, const char *, const char *);
 
 extern void topo_fmristr_build(ssize_t *, char *, size_t, char *, char *,
     char *);
--- a/usr/src/lib/fm/topo/libtopo/common/topo_tree.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_tree.c	Sat Nov 04 01:18:55 2006 -0800
@@ -62,6 +62,7 @@
 
 #include <topo_alloc.h>
 #include <topo_error.h>
+#include <topo_file.h>
 #include <topo_module.h>
 #include <topo_string.h>
 #include <topo_subr.h>
@@ -71,7 +72,7 @@
 set_create_error(topo_hdl_t *thp, ttree_t *tp, int err)
 {
 	if (tp != NULL)
-		topo_tree_destroy(thp, tp);
+		topo_tree_destroy(tp);
 
 	if (err != 0)
 		(void) topo_hdl_seterrno(thp, err);
@@ -79,46 +80,24 @@
 	return (NULL);
 }
 
-static void
-set_system_props(tnode_t *node)
-{
-	int err;
-	char platform[MAXNAMELEN];
-	char isa[MAXNAMELEN];
-	struct utsname uts;
-
-	platform[0] = '\0';
-	isa[0] = '\0';
-	(void) sysinfo(SI_PLATFORM, platform, sizeof (platform));
-	(void) sysinfo(SI_ARCHITECTURE, isa, sizeof (isa));
-	(void) uname(&uts);
-
-	(void) topo_pgroup_create(node, TOPO_PGROUP_SYSTEM,
-	    TOPO_STABILITY_PRIVATE, &err);
-	(void) topo_prop_set_string(node, TOPO_PGROUP_SYSTEM,
-	    TOPO_PROP_PLATFORM, TOPO_PROP_SET_ONCE, platform, &err);
-	(void) topo_prop_set_string(node, TOPO_PGROUP_SYSTEM,
-	    TOPO_PROP_ISA, TOPO_PROP_SET_ONCE, isa, &err);
-	(void) topo_prop_set_string(node, TOPO_PGROUP_SYSTEM,
-	    TOPO_PROP_MACHINE, TOPO_PROP_SET_ONCE, uts.machine, &err);
-}
-
 ttree_t *
 topo_tree_create(topo_hdl_t *thp, topo_mod_t *mod, const char *scheme)
 {
 	ttree_t *tp;
 	tnode_t *rp;
 
-	if ((tp = topo_hdl_zalloc(thp, sizeof (ttree_t))) == NULL)
+	if ((tp = topo_mod_zalloc(mod, sizeof (ttree_t))) == NULL)
 		return (set_create_error(thp, NULL, ETOPO_NOMEM));
 
-	if ((tp->tt_scheme = topo_hdl_strdup(thp, scheme)) == NULL)
+	tp->tt_mod = mod;
+
+	if ((tp->tt_scheme = topo_mod_strdup(mod, scheme)) == NULL)
 		return (set_create_error(thp, tp, ETOPO_NOMEM));
 
 	/*
 	 * Initialize a private walker for internal use
 	 */
-	if ((tp->tt_walk = topo_hdl_zalloc(thp, sizeof (topo_walk_t))) == NULL)
+	if ((tp->tt_walk = topo_mod_zalloc(mod, sizeof (topo_walk_t))) == NULL)
 		return (set_create_error(thp, tp, ETOPO_NOMEM));
 
 	/*
@@ -133,7 +112,6 @@
 	rp->tn_enum = mod;
 	rp->tn_hdl = thp;
 
-	set_system_props(rp);
 	topo_node_hold(rp);
 
 	tp->tt_walk->tw_root = rp;
@@ -147,16 +125,16 @@
 }
 
 void
-topo_tree_destroy(topo_hdl_t *thp, ttree_t *tp)
+topo_tree_destroy(ttree_t *tp)
 {
+	topo_mod_t *mod;
+
 	if (tp == NULL)
 		return;
 
+	mod = tp->tt_mod;
 	if (tp->tt_walk != NULL)
-		topo_hdl_free(thp, tp->tt_walk, sizeof (topo_walk_t));
-
-	if (tp->tt_file != NULL)
-		topo_file_unload(thp, tp);
+		topo_mod_free(mod, tp->tt_walk, sizeof (topo_walk_t));
 
 	if (tp->tt_root != NULL) {
 		assert(tp->tt_root->tn_refs == 1);
@@ -168,28 +146,71 @@
 	 * topo_node_rele().
 	 */
 	if (tp->tt_scheme != NULL)
-		topo_hdl_strfree(thp, tp->tt_scheme);
+		topo_mod_strfree(mod, tp->tt_scheme);
 
-	topo_hdl_free(thp, tp, sizeof (ttree_t));
+	topo_mod_free(mod, tp, sizeof (ttree_t));
 }
 
 static int
 topo_tree_enum(topo_hdl_t *thp, ttree_t *tp)
 {
-	tnode_t *rnode;
+	char *pp;
 
-	rnode = tp->tt_root;
 	/*
-	 * Attempt to populate the tree from a topology file
+	 * Attempt to enumerate the tree from a topology map in the
+	 * following order:
+	 *	<product-name>-<scheme>-topology
+	 *	<platform-name>-<scheme>-topology (uname -i)
+	 *	<machine-name>-<scheme>-topology (uname -m)
+	 *	<scheme>-topology
+	 *
+	 * Trim any SUNW, from the product or platform name
+	 * before loading file
 	 */
-	if (topo_file_load(thp, rnode->tn_enum, tp) < 0) {
-		/*
-		 * If this tree does not have a matching static topology file,
-		 * continue on.
-		 */
-		if (topo_hdl_errno(thp) != ETOPO_FILE_NOENT)
-			return (topo_hdl_seterrno(thp, ETOPO_ENUM_PARTIAL));
+	if (thp->th_product == NULL ||
+	    (pp = strchr(thp->th_product, ',')) == NULL)
+		pp = thp->th_product;
+	else
+		pp++;
+	if (topo_file_load(tp->tt_root->tn_enum, tp->tt_root,
+	    pp, tp->tt_scheme) < 0) {
+		if ((pp = strchr(thp->th_platform, ',')) == NULL)
+			pp = thp->th_platform;
+		else
+			pp++;
+
+		if (topo_file_load(tp->tt_root->tn_enum, tp->tt_root,
+		    pp, tp->tt_scheme) < 0) {
+			if (topo_file_load(tp->tt_root->tn_enum, tp->tt_root,
+			    thp->th_machine, tp->tt_scheme) < 0) {
+
+				if (topo_file_load(tp->tt_root->tn_enum,
+				    tp->tt_root, NULL, tp->tt_scheme) < 0) {
+					topo_dprintf(thp, TOPO_DBG_ERR, "no "
+					    "topology map found for the %s "
+					    "FMRI set\n", tp->tt_scheme);
+					return (topo_hdl_seterrno(thp,
+					    ETOPO_ENUM_NOMAP));
+				}
+			}
+		}
 	}
+
+	/*
+	 * It would be nice to leave the devinfo and prominfo trees
+	 * active but the interfaces consume copious amounts of memory
+	 * while searching for property information
+	 */
+	if (thp->th_di != DI_NODE_NIL) {
+		di_fini(thp->th_di);
+		thp->th_di = DI_NODE_NIL;
+	}
+	if (thp->th_pi != DI_PROM_HANDLE_NIL) {
+		di_prom_fini(thp->th_pi);
+		thp->th_pi = DI_PROM_HANDLE_NIL;
+	}
+
+
 	return (0);
 }
 
--- a/usr/src/lib/fm/topo/libtopo/common/topo_tree.h	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_tree.h	Sat Nov 04 01:18:55 2006 -0800
@@ -91,9 +91,9 @@
 
 typedef struct topo_tree {
 	topo_list_t tt_list;		/* next/prev pointers */
-	char *tt_scheme;		/* Scheme name */
-	void *tt_file;			/* Topology file info */
-	struct topo_node *tt_root;	/* Root node */
+	char *tt_scheme;		/* scheme name */
+	topo_mod_t *tt_mod;		/* builtin enumerator mod */
+	struct topo_node *tt_root;	/* root node */
 	topo_walk_t *tt_walk;		/* private walker */
 } ttree_t;
 
@@ -118,6 +118,12 @@
 	pthread_mutex_t	th_lock;	/* lock protecting hdl */
 	char *th_uuid;			/* uuid of snapshot */
 	char *th_rootdir;		/* Root directory of plugin paths */
+	char *th_platform;		/* platform name */
+	char *th_isa;			/* isa name */
+	char *th_machine;		/* machine name */
+	char *th_product;		/* product name */
+	di_node_t th_di;		/* handle  to root of devinfo tree */
+	di_prom_handle_t th_pi;		/* handle to root of prom tree */
 	topo_modhash_t *th_modhash;	/* Module hash */
 	topo_list_t th_trees;		/* Scheme-specific topo tree list */
 	topo_alloc_t *th_alloc;		/* allocators */
@@ -127,14 +133,13 @@
 };
 
 #define	TOPO_UUID_SIZE	37	/* libuuid limit + 1 */
+#define	SMB_DEFAULT1	"To Be Filled By O.E.M."
+#define	SMB_DEFAULT2	"Not Available At This Time"
 
 extern ttree_t *topo_tree_create(topo_hdl_t *, topo_mod_t *, const char *);
-extern void topo_tree_destroy(topo_hdl_t *, ttree_t *);
+extern void topo_tree_destroy(ttree_t *);
 extern int topo_tree_enum_all(topo_hdl_t *);
 
-extern int topo_file_load(topo_hdl_t *, topo_mod_t *, ttree_t *);
-extern void topo_file_unload(topo_hdl_t *, ttree_t *);
-
 extern void topo_node_lock(tnode_t *);
 extern void topo_node_unlock(tnode_t *);
 extern void topo_node_hold(tnode_t *);
--- a/usr/src/lib/fm/topo/libtopo/common/topo_xml.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_xml.c	Sat Nov 04 01:18:55 2006 -0800
@@ -45,66 +45,12 @@
 #include <topo_parse.h>
 #include <topo_error.h>
 
-const char * const Children = "children";
-const char * const Dependents = "dependents";
-const char * const FMRI = "fmri";
-const char * const Grouping = "grouping";
-const char * const Immutable = "immutable";
-const char * const Instance = "instance";
-const char * const Int32 = "int32";
-const char * const Int64 = "int64";
-const char * const Name = "name";
-const char * const Path = "path";
-const char * const Range = "range";
-const char * const Scheme = "scheme";
-const char * const Siblings = "siblings";
-const char * const String = "string";
-const char * const Topology = "topology";
-const char * const Type = "type";
-const char * const UInt32 = "uint32";
-const char * const UInt64 = "uint64";
-const char * const Value = "value";
-const char * const Verify = "verify";
-const char * const Version = "version";
-
-const char * const Enum_meth = "enum-method";
-const char * const Propgrp = "propgroup";
-const char * const Propval = "propval";
-
-const char * const Node = "node";
-const char * const Hc = "hc";
-
-const char * const True = "true";
-const char * const False = "false";
-
-const char * const Namestab = "name-stability";
-const char * const Datastab = "data-stability";
-
-const char * const Evolving = "Evolving";
-const char * const External = "External";
-const char * const Internal = "Internal";
-const char * const Obsolete = "Obsolete";
-const char * const Private = "Private";
-const char * const Stable = "Stable";
-const char * const Standard = "Standard";
-const char * const Unstable = "Unstable";
-
 static tf_rdata_t *topo_xml_walk(topo_mod_t *,
     tf_info_t *, xmlNodePtr, tnode_t *);
 
-static void
-txml_dump(int g, xmlNodePtr p)
-{
-	if (p && p->name) {
-		topo_dprintf(TOPO_DBG_MOD, "%d %s\n", g, p->name);
-
-		for (p = p->xmlChildrenNode; p != NULL; p = p->next)
-			txml_dump(g + 1, p);
-	}
-}
-
 int
-xmlattr_to_stab(topo_mod_t *mp, xmlNodePtr n, topo_stability_t *rs)
+xmlattr_to_stab(topo_mod_t *mp, xmlNodePtr n, const char *stabname,
+    topo_stability_t *rs)
 {
 	xmlChar *str;
 	int rv = 0;
@@ -114,8 +60,12 @@
 		*rs = TOPO_STABILITY_PRIVATE;
 		return (0);
 	}
-	if ((str = xmlGetProp(n, (xmlChar *)Value)) == NULL)
+	if ((str = xmlGetProp(n, (xmlChar *)stabname)) == NULL) {
+		topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
+		    "attribute to stability:\n");
 		return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
+	}
+
 	if (xmlStrcmp(str, (xmlChar *)Internal) == 0) {
 		*rs = TOPO_STABILITY_INTERNAL;
 	} else if (xmlStrcmp(str, (xmlChar *)Private) == 0) {
@@ -147,7 +97,7 @@
 	xmlChar *str;
 	xmlChar *estr;
 
-	topo_mod_dprintf(mp, "attribute to int\n");
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "attribute to int\n");
 	if ((str = xmlGetProp(n, (xmlChar *)propname)) == NULL)
 		return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
 	*value = strtoull((char *)str, (char **)&estr, 10);
@@ -164,14 +114,12 @@
 xmlattr_to_fmri(topo_mod_t *mp,
     xmlNodePtr xn, const char *propname, nvlist_t **rnvl)
 {
-	int err;
 	xmlChar *str;
 
-	topo_mod_dprintf(mp, "attribute to int\n");
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "attribute to int\n");
 	if ((str = xmlGetProp(xn, (xmlChar *)propname)) == NULL)
 		return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
-	if (topo_fmri_str2nvl(topo_mod_handle(mp), (const char *)str, rnvl,
-	    &err) < 0)
+	if (topo_mod_str2nvl(mp, (const char *)str, rnvl) < 0)
 		return (-1);
 	xmlFree(str);
 	return (0);
@@ -183,7 +131,7 @@
 	topo_type_t rv;
 	xmlChar *str;
 	if ((str = xmlGetProp(xn, (xmlChar *)Type)) == NULL) {
-		topo_mod_dprintf(mp, "Property missing type");
+		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "Property missing type");
 		(void) topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR);
 		return (TOPO_TYPE_INVALID);
 	}
@@ -201,7 +149,8 @@
 		rv = TOPO_TYPE_STRING;
 	} else {
 		xmlFree(str);
-		topo_mod_dprintf(mp, "Unrecognized type attribute.\n");
+		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
+		    "Unrecognized type attribute.\n");
 		(void) topo_mod_seterrno(mp, ETOPO_PRSR_BADTYPE);
 		return (TOPO_TYPE_INVALID);
 	}
@@ -220,14 +169,16 @@
 
 	if ((str = xmlGetProp(xn, (xmlChar *)Immutable)) != NULL) {
 		if (xmlStrcmp(str, (xmlChar *)False) == 0)
-			e = nvlist_add_boolean_value(nvl, INV_IMMUTE, B_FALSE);
+			(void) nvlist_add_boolean_value(nvl, INV_IMMUTE,
+			    B_FALSE);
 		else
-			e = nvlist_add_boolean_value(nvl, INV_IMMUTE, B_TRUE);
+			(void) nvlist_add_boolean_value(nvl, INV_IMMUTE,
+			    B_TRUE);
 		xmlFree(str);
-		if (e != 0)
-			return (-1);
+	} else {
+		(void) nvlist_add_boolean_value(nvl, INV_IMMUTE, B_TRUE);
 	}
-	/* FMXXX stability of the property value */
+
 	if ((ptype = xmlattr_to_type(mp, xn)) == TOPO_TYPE_INVALID)
 		return (-1);
 	e = nvlist_add_int32(nvl, INV_PVALTYPE, ptype);
@@ -267,11 +218,13 @@
 		xmlFree(str);
 		break;
 	default:
-		topo_mod_dprintf(mp, "Unrecognized type attribute.\n");
+		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
+		    "Unrecognized type attribute.\n");
 		return (topo_mod_seterrno(mp, ETOPO_PRSR_BADTYPE));
 	}
 	if (e != 0) {
-		topo_mod_dprintf(mp, "Nvlist construction failed.\n");
+		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
+		    "Nvlist construction failed.\n");
 		return (topo_mod_seterrno(mp, ETOPO_NOMEM));
 	}
 	return (0);
@@ -285,9 +238,10 @@
 	xmlChar *grptype;
 	int sibs = 0;
 
-	topo_mod_dprintf(mp, "dependent create\n");
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "dependent create\n");
 	if ((grptype = xmlGetProp(dxn, (xmlChar *)Grouping)) == NULL) {
-		topo_mod_dprintf(mp, "Dependents missing grouping attribute");
+		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
+		    "Dependents missing grouping attribute");
 		return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
 	}
 
@@ -298,7 +252,7 @@
 	} else if (xmlStrcmp(grptype, (xmlChar *)Children) == 0) {
 		rp = pad->tpad_child;
 	} else {
-		topo_mod_dprintf(mp,
+		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
 		    "Dependents have bogus grouping attribute");
 		xmlFree(grptype);
 		return (topo_mod_seterrno(mp, ETOPO_PRSR_BADGRP));
@@ -310,7 +264,7 @@
 		rp = rp->rd_next;
 	}
 	if ((np = topo_xml_walk(mp, xinfo, dxn, ptn)) == NULL) {
-		topo_mod_dprintf(mp,
+		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
 		    "error within dependent .xml topology: "
 		    "%s\n", topo_strerror(topo_mod_errno(mp)));
 		return (-1);
@@ -330,7 +284,7 @@
 {
 	xmlNodePtr cn;
 
-	topo_mod_dprintf(mp, "dependents create\n");
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "dependents create\n");
 	for (cn = pxn->xmlChildrenNode; cn != NULL; cn = cn->next) {
 		if (xmlStrcmp(cn->name, (xmlChar *)Dependents) == 0) {
 			if (dependent_create(mp, xinfo, pad, cn, ptn) < 0)
@@ -353,7 +307,7 @@
 	char *str;
 	int err, e;
 
-	topo_mod_dprintf(mp, "prop create\n");
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "prop create\n");
 	switch (ptype) {
 	case TOPO_TYPE_INT32:
 		e = nvlist_lookup_int32(pfmri, INV_PVAL, &i32);
@@ -377,7 +331,8 @@
 		e = ETOPO_PRSR_BADTYPE;
 	}
 	if (e != 0) {
-		topo_mod_dprintf(mp, "prop value lookup failed.\n");
+		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
+		    "prop value lookup failed.\n");
 		return (topo_mod_seterrno(mp, e));
 	}
 	switch (ptype) {
@@ -400,8 +355,15 @@
 		e = topo_prop_set_string(ptn, gnm, pnm, flag, str, &err);
 		break;
 	}
-	if (e != 0) {
-		topo_mod_dprintf(mp, "prop set failed.\n");
+	if (e != 0 && err != ETOPO_PROP_DEFD) {
+
+		/*
+		 * Some properties may have already been set
+		 * in topo_node_bind() or topo_prop_inherit if we are
+		 * enumerating from a static .xml file
+		 */
+		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "prop set "
+		    "failed %s/%s:%s\n", gnm, pnm, topo_strerror(err));
 		return (topo_mod_seterrno(mp, err));
 	}
 	return (0);
@@ -419,28 +381,28 @@
 	int pn;
 	int e;
 
-	topo_mod_dprintf(mp, "props create\n");
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "props create\n");
 	for (pn = 0; pn < nprops; pn++) {
 		e = nvlist_lookup_string(props[pn], INV_PNAME, &pnm);
 		if (e != 0) {
-			topo_mod_dprintf(mp,
+			topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
 			    "props create lookup (%s) failure: %s",
 			    INV_PNAME, topo_strerror(e));
 			return (topo_mod_seterrno(mp, ETOPO_PRSR_NVPROP));
 		}
 		e = nvlist_lookup_boolean_value(props[pn], INV_IMMUTE, &pim);
 		if (e != 0) {
-			topo_mod_dprintf(mp,
+			topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
 			    "props create lookup (%s) failure: %s",
 			    INV_IMMUTE, topo_strerror(e));
 			return (topo_mod_seterrno(mp, ETOPO_PRSR_NVPROP));
 		}
 		flag = (pim == B_TRUE) ?
-		    TOPO_PROP_SET_ONCE : TOPO_PROP_SET_MULTIPLE;
+		    TOPO_PROP_IMMUTABLE : TOPO_PROP_MUTABLE;
 
 		e = nvlist_lookup_int32(props[pn], INV_PVALTYPE, &i32);
 		if (e != 0) {
-			topo_mod_dprintf(mp,
+			topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
 			    "props create lookup (%s) failure: %s",
 			    INV_PVALTYPE, topo_strerror(e));
 			return (topo_mod_seterrno(mp, ETOPO_PRSR_NVPROP));
@@ -455,34 +417,66 @@
 static int
 pgroups_create(topo_mod_t *mp, tf_pad_t *pad, tnode_t *ptn)
 {
-	topo_stability_t gs;
+	topo_pgroup_info_t pgi;
 	nvlist_t **props;
 	char *gnm;
+	char *nmstab, *dstab;
 	uint32_t rnprops, nprops;
-	uint32_t ui32;
+	uint32_t gv;
 	int pg;
 	int e;
 
-	topo_mod_dprintf(mp, "pgroups create\n");
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pgroups create\n");
 	for (pg = 0; pg < pad->tpad_pgcnt; pg++) {
 		e = nvlist_lookup_string(pad->tpad_pgs[pg],
 		    INV_PGRP_NAME, &gnm);
 		if (e != 0) {
-			topo_mod_dprintf(mp, "pad lookup (%s) failed.\n",
+			topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
+			    "pad lookup (%s) failed.\n",
 			    INV_PGRP_NAME);
 			return (topo_mod_seterrno(mp, ETOPO_PRSR_NVPROP));
 		}
-		e = nvlist_lookup_uint32(pad->tpad_pgs[pg],
-		    INV_PGRP_STAB, &ui32);
+		e = nvlist_lookup_string(pad->tpad_pgs[pg],
+		    INV_PGRP_NMSTAB, &nmstab);
+		if (e != 0) {
+			if (e != ENOENT) {
+				topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
+				    "pad lookup (%s) "
+				    "failed.\n", INV_PGRP_NMSTAB);
+				return (topo_mod_seterrno(mp,
+				    ETOPO_PRSR_NVPROP));
+			} else {
+				nmstab = TOPO_STABSTR_PRIVATE;
+			}
+		}
+		e = nvlist_lookup_string(pad->tpad_pgs[pg],
+		    INV_PGRP_DSTAB, &dstab);
 		if (e != 0) {
-			topo_mod_dprintf(mp, "pad lookup (%s) failed.\n",
-			    INV_PGRP_STAB);
+			if (e != ENOENT) {
+				topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
+				    "pad lookup (%s) failed.\n",
+				    INV_PGRP_DSTAB);
+				return (topo_mod_seterrno(mp,
+				    ETOPO_PRSR_NVPROP));
+			} else {
+				dstab = TOPO_STABSTR_PRIVATE;
+			}
+		}
+		e = nvlist_lookup_uint32(pad->tpad_pgs[pg],
+		    INV_PGRP_VER, &gv);
+		if (e != 0) {
+			topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
+			    "pad lookup (%s) failed.\n",
+			    INV_PGRP_VER);
 			return (topo_mod_seterrno(mp, ETOPO_PRSR_NVPROP));
 		}
-		gs = (topo_stability_t)ui32;
-		if (topo_pgroup_create(ptn, gnm, gs, &e) != 0) {
+		pgi.tpi_name = gnm;
+		pgi.tpi_namestab = topo_name2stability(nmstab);
+		pgi.tpi_datastab = topo_name2stability(dstab);
+		pgi.tpi_version = gv;
+		if (topo_pgroup_create(ptn, &pgi, &e) != 0) {
 			if (e != ETOPO_PROP_DEFD) {
-				topo_mod_dprintf(mp,
+				topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
 				    "pgroups create failure: %s\n",
 				    topo_strerror(e));
 				return (-1);
@@ -493,8 +487,8 @@
 		e |= nvlist_lookup_nvlist_array(pad->tpad_pgs[pg],
 		    INV_PGRP_ALLPROPS, &props, &nprops);
 		if (rnprops != nprops) {
-			topo_mod_dprintf(mp,
-			    "warning: recorded number of props %d does not "
+			topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
+			    "recorded number of props %d does not "
 			    "match number of props recorded %d.\n",
 			    rnprops, nprops);
 		}
@@ -510,9 +504,10 @@
 	nvlist_t *pnvl = NULL;
 	xmlChar *pname;
 
-	topo_mod_dprintf(mp, "pval record\n");
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pval record\n");
 	if ((pname = xmlGetProp(xn, (xmlChar *)Name)) == NULL) {
-		topo_mod_dprintf(mp, "propval lacks a name\n");
+		topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
+		    "propval lacks a name\n");
 		(void) topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR);
 		return (NULL);
 	}
@@ -538,8 +533,8 @@
 static int
 pgroup_record(topo_mod_t *mp, xmlNodePtr pxn, tf_pad_t *rpad, int pi)
 {
-	topo_stability_t nmstab;
-	xmlNodePtr sn = NULL;
+	topo_stability_t nmstab, dstab;
+	uint64_t ver;
 	xmlNodePtr cn;
 	xmlChar *name;
 	nvlist_t **apl = NULL;
@@ -548,29 +543,43 @@
 	int ai = 0;
 	int e;
 
-	topo_mod_dprintf(mp, "pgroup record\n");
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pgroup record\n");
 	if ((name = xmlGetProp(pxn, (xmlChar *)Name)) == NULL) {
-		topo_mod_dprintf(mp, "propgroup lacks a name\n");
+		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
+		    "propgroup lacks a name\n");
+		return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
+	}
+	if (xmlattr_to_int(mp, pxn, Version, &ver) < 0) {
+		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
+		    "propgroup lacks a version\n");
 		return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
 	}
-	topo_mod_dprintf(mp, "pgroup %s\n", (char *)name);
+	if (xmlattr_to_stab(mp, pxn, Namestab, &nmstab) < 0) {
+		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
+		    "propgroup lacks name-stability\n");
+		return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
+	}
+	if (xmlattr_to_stab(mp, pxn, Datastab, &dstab) < 0) {
+		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
+		    "propgroup lacks data-stability\n");
+		return (topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR));
+	}
+
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pgroup %s\n", (char *)name);
 	for (cn = pxn->xmlChildrenNode; cn != NULL; cn = cn->next) {
 		if (xmlStrcmp(cn->name, (xmlChar *)Propval) == 0)
 			pcnt++;
-		else if (xmlStrcmp(cn->name, (xmlChar *)Namestab) == 0)
-			sn = cn;
 	}
-	if (xmlattr_to_stab(mp, sn, &nmstab) < 0) {
-		xmlFree(name);
-		return (-1);
-	}
+
 	if (topo_mod_nvalloc(mp, &pgnvl, NV_UNIQUE_NAME) < 0) {
 		xmlFree(name);
 		return (-1);
 	}
 
 	e = nvlist_add_string(pgnvl, INV_PGRP_NAME, (char *)name);
-	e |= nvlist_add_uint32(pgnvl, INV_PGRP_STAB, nmstab);
+	e |= nvlist_add_uint32(pgnvl, INV_PGRP_NMSTAB, nmstab);
+	e |= nvlist_add_uint32(pgnvl, INV_PGRP_DSTAB, dstab);
+	e |= nvlist_add_uint32(pgnvl, INV_PGRP_VER, ver);
 	e |= nvlist_add_uint32(pgnvl, INV_PGRP_NPROP, pcnt);
 	if (e != 0 ||
 	    (apl = topo_mod_zalloc(mp, pcnt * sizeof (nvlist_t *))) == NULL) {
@@ -608,7 +617,7 @@
 	xmlNodePtr cn;
 	int pi = 0;
 
-	topo_mod_dprintf(mp, "pgroups record\n");
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "pgroups record\n");
 	for (cn = pxn->xmlChildrenNode; cn != NULL; cn = cn->next) {
 		if (xmlStrcmp(cn->name, (xmlChar *)Propgrp) == 0) {
 			if (pgroup_record(mp, cn, rpad, pi++) < 0)
@@ -627,41 +636,47 @@
     tf_info_t *xinfo, xmlNodePtr pxn, tnode_t *ptn, tf_pad_t **rpad)
 {
 	xmlNodePtr cn;
+	tf_pad_t *new = *rpad;
 	int pgcnt = 0;
 	int dcnt = 0;
 
-	topo_mod_dprintf(mp, "pad process beneath %s\n", topo_node_name(ptn));
-	if (*rpad == NULL) {
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
+	    "pad process beneath %s\n", topo_node_name(ptn));
+	if (new == NULL) {
 		for (cn = pxn->xmlChildrenNode; cn != NULL; cn = cn->next) {
 			if (xmlStrcmp(cn->name, (xmlChar *)Dependents) == 0)
 				dcnt++;
 			else if (xmlStrcmp(cn->name, (xmlChar *)Propgrp) == 0)
 				pgcnt++;
 		}
-		if ((*rpad = tf_pad_new(mp, pgcnt, dcnt)) == NULL)
+		if ((new = tf_pad_new(mp, pgcnt, dcnt)) == NULL)
 			return (-1);
-		if (dcnt == 0 && pgcnt == 0)
+		if (dcnt == 0 && pgcnt == 0) {
+			*rpad = new;
 			return (0);
+		}
+
 		if (pgcnt > 0) {
-			(*rpad)->tpad_pgs =
+			new->tpad_pgs =
 			    topo_mod_zalloc(mp, pgcnt * sizeof (nvlist_t *));
-			if ((*rpad)->tpad_pgs == NULL) {
-				tf_pad_free(mp, *rpad);
-				return (-1);
+			if (new->tpad_pgs == NULL) {
+				tf_pad_free(mp, new);
+				return (NULL);
 			}
-			if (pgroups_record(mp, pxn, *rpad) < 0) {
-				tf_pad_free(mp, *rpad);
-				return (-1);
+			if (pgroups_record(mp, pxn, new) < 0) {
+				tf_pad_free(mp, new);
+				return (NULL);
 			}
 		}
+		*rpad = new;
 	}
 
-	if ((*rpad)->tpad_dcnt > 0)
-		if (dependents_create(mp, xinfo, *rpad, pxn, ptn) < 0)
+	if (new->tpad_dcnt > 0)
+		if (dependents_create(mp, xinfo, new, pxn, ptn) < 0)
 			return (-1);
 
-	if ((*rpad)->tpad_pgcnt > 0)
-		if (pgroups_create(mp, *rpad, ptn) < 0)
+	if (new->tpad_pgcnt > 0)
+		if (pgroups_create(mp, new, ptn) < 0)
 			return (-1);
 	return (0);
 }
@@ -669,37 +684,49 @@
 static int
 node_process(topo_mod_t *mp, xmlNodePtr nn, tf_rdata_t *rd)
 {
+	xmlChar *str;
 	topo_instance_t inst;
 	tf_idata_t *newi;
 	tnode_t *ntn;
 	uint64_t ui;
 	int rv = -1;
+	int s = 0;
 
-	topo_mod_dprintf(mp, "node process %s\n", rd->rd_name);
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
+	    "node process %s\n", rd->rd_name);
+
 	if (xmlattr_to_int(mp, nn, Instance, &ui) < 0)
 		goto nodedone;
 	inst = (topo_instance_t)ui;
 
-	if (topo_mod_enumerate(rd->rd_mod,
-	    rd->rd_pn, rd->rd_finfo->tf_scheme, rd->rd_name, inst, inst) < 0)
+	if ((str = xmlGetProp(nn, (xmlChar *)Static)) != NULL) {
+		if (xmlStrcmp(str, (xmlChar *)True) == 0)
+			s = 1;
+	}
+
+	if (topo_mod_enumerate(rd->rd_mod, rd->rd_pn, rd->rd_finfo->tf_scheme,
+	    rd->rd_name, inst, inst, s == 1 ? &s : NULL) < 0)
 		goto nodedone;
 	ntn = topo_node_lookup(rd->rd_pn, rd->rd_name, inst);
 	if (ntn == NULL)
 		goto nodedone;
 
 	if ((newi = tf_idata_new(mp, inst, ntn)) == NULL) {
-		topo_mod_dprintf(mp, "tf_idata_new failed.\n");
+		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
+		    "tf_idata_new failed.\n");
 		goto nodedone;
 	}
-	if (tf_idata_insert(mp, &rd->rd_instances, newi) < 0) {
-		topo_mod_dprintf(mp, "tf_idata_insert failed.\n");
+	if (tf_idata_insert(&rd->rd_instances, newi) < 0) {
+		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
+		    "tf_idata_insert failed.\n");
 		goto nodedone;
 	}
 	if (pad_process(mp, rd->rd_finfo, nn, ntn, &newi->ti_pad) < 0)
 		goto nodedone;
 	rv = 0;
 nodedone:
-	topo_mod_dprintf(mp, "done with node %s.\n", rd->rd_name);
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "done with node %s.\n",
+	    rd->rd_name);
 	return (rv);
 }
 
@@ -709,20 +736,15 @@
 	tf_edata_t *einfo;
 	uint64_t ui;
 
-	topo_mod_dprintf(mp, "enum attributes process\n");
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "enum attributes process\n");
 	if ((einfo = topo_mod_zalloc(mp, sizeof (tf_edata_t))) == NULL) {
 		(void) topo_mod_seterrno(mp, ETOPO_NOMEM);
 		return (NULL);
 	}
 	einfo->te_name = (char *)xmlGetProp(en, (xmlChar *)Name);
 	if (einfo->te_name == NULL) {
-		topo_mod_dprintf(mp, "Enumerator name attribute missing.\n");
-		(void) topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR);
-		goto enodedone;
-	}
-	einfo->te_path = (char *)xmlGetProp(en, (xmlChar *)Path);
-	if (einfo->te_path == NULL) {
-		topo_mod_dprintf(mp, "Enumerator path attribute missing.\n");
+		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
+		    "Enumerator name attribute missing.\n");
 		(void) topo_mod_seterrno(mp, ETOPO_PRSR_NOATTR);
 		goto enodedone;
 	}
@@ -738,58 +760,47 @@
 enodedone:
 	if (einfo->te_name != NULL)
 		xmlFree(einfo->te_name);
-	if (einfo->te_path != NULL)
-		xmlFree(einfo->te_path);
 	return (NULL);
 }
 
 static int
 enum_run(topo_mod_t *mp, tf_rdata_t *rd)
 {
+	topo_hdl_t *thp = mp->tm_hdl;
 	int e = -1;
 
 	/*
-	 * first see if the module is already loaded
+	 * Check if the enumerator module is already loaded.
+	 * Module loading is single-threaded at this point so there's
+	 * no need to worry about the module going away or bumping the
+	 * ref count.
 	 */
-	rd->rd_mod = topo_mod_lookup(mp->tm_hdl, rd->rd_einfo->te_name);
-	if (rd->rd_mod == NULL) {
-		char *mostpath = topo_mod_alloc(mp, PATH_MAX);
-		char *skip;
-		int prepend = 0;
-
-		if (mostpath == NULL)
-			return (-1);
-		skip = rd->rd_einfo->te_path;
-		if (*skip == '%' && *(skip + 1) == 'r') {
-			prepend = 1;
-			skip += 2;
-		}
-		(void) snprintf(mostpath,
-		    PATH_MAX, "%s%s/%s.so",
-		    (prepend == 1) ? topo_mod_rootdir(mp) : "",
-		    skip, rd->rd_einfo->te_name);
-		topo_mod_dprintf(mp,
-		    "enum_run, load %s.\n", mostpath);
-		if ((rd->rd_mod = topo_mod_load(mp, mostpath)) == NULL) {
-			topo_mod_dprintf(mp,
+	if ((rd->rd_mod = topo_mod_lookup(thp, rd->rd_einfo->te_name,
+	    0)) == NULL) {
+		if ((rd->rd_mod = topo_mod_load(mp, rd->rd_einfo->te_name,
+		    rd->rd_einfo->te_vers)) == NULL) {
+			topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
 			    "mod_load of %s failed: %s.\n",
-			    mostpath, topo_strerror(topo_mod_errno(mp)));
-			topo_free(mostpath, PATH_MAX);
+			    rd->rd_einfo->te_name,
+			    topo_strerror(topo_mod_errno(mp)));
+			(void) topo_hdl_seterrno(thp, topo_mod_errno(mp));
 			return (e);
 		}
-		topo_free(mostpath, PATH_MAX);
 	}
 	/*
 	 * We're live, so let's enumerate.
 	 */
-	topo_mod_dprintf(mp, "enumerate request. (%s)\n",
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "enumerate request. (%s)\n",
 	    rd->rd_einfo->te_name);
 	e = topo_mod_enumerate(rd->rd_mod, rd->rd_pn, rd->rd_einfo->te_name,
-	    rd->rd_name, rd->rd_min, rd->rd_max);
-	topo_mod_dprintf(mp, "back from enumeration. %d\n", e);
+	    rd->rd_name, rd->rd_min, rd->rd_max, NULL);
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "back from enumeration. %d\n",
+	    e);
 	if (e != 0) {
-		topo_mod_dprintf(mp, "Enumeration failed (%s)\n",
+		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
+		    "Enumeration failed (%s)\n",
 		    topo_strerror(topo_mod_errno(mp)));
+		(void) topo_hdl_seterrno(thp, EMOD_PARTIAL_ENUM);
 		return (topo_mod_seterrno(mp, EMOD_PARTIAL_ENUM));
 	}
 	return (e);
@@ -807,12 +818,13 @@
 	tnode_t *ct;
 	int e;
 
-	topo_mod_dprintf(mp, "process %s range beneath %s\n",
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "process %s range beneath %s\n",
 	    rd->rd_name, topo_node_name(rd->rd_pn));
 	e = topo_node_range_create(mp,
 	    rd->rd_pn, rd->rd_name, rd->rd_min, rd->rd_max);
 	if (e != 0) {
-		topo_mod_dprintf(mp, "Range create failed due to %s.\n",
+		topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
+		    "Range create failed due to %s.\n",
 		    topo_strerror(topo_mod_errno(mp)));
 		return (-1);
 	}
@@ -824,8 +836,11 @@
 		if ((rd->rd_einfo = enum_attributes_process(mp, cn)) == NULL)
 			return (-1);
 		if (enum_run(mp, rd) < 0) {
-			topo_mod_dprintf(mp, "Enumeration failed.\n");
-			return (-1);
+			/*
+			 * Note the failure but continue on
+			 */
+			topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
+			    "Enumeration failed.\n");
 		}
 	}
 
@@ -833,7 +848,7 @@
 	for (cn = rn->xmlChildrenNode; cn != NULL; cn = cn->next) {
 		if (xmlStrcmp(cn->name, (xmlChar *)Node) == 0)
 			if (node_process(mp, cn, rd) < 0) {
-				topo_mod_dprintf(mp,
+				topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR,
 				    "node processing failed: %s.\n",
 				    topo_strerror(topo_mod_errno(mp)));
 				return (topo_mod_seterrno(mp,
@@ -853,7 +868,7 @@
 			return (-1);
 		ct = topo_child_next(rd->rd_pn, ct);
 	}
-	topo_mod_dprintf(mp, "end range process %s\n",
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "end range process %s\n",
 	    rd->rd_name);
 	return (0);
 }
@@ -870,15 +885,16 @@
 	 * as 'ranges', these define topology nodes may exist, and need
 	 * to be verified.
 	 */
-	topo_mod_dprintf(mp, "topo_xml_walk\n");
+	topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "topo_xml_walk\n");
 	rr = pr = NULL;
 	for (curr = croot->xmlChildrenNode; curr != NULL; curr = curr->next) {
 		if (curr->name == NULL) {
-			topo_mod_dprintf(mp, "Ignoring nameless xmlnode.\n");
+			topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
+			    "Ignoring nameless xmlnode\n");
 			continue;
 		}
 		if (xmlStrcmp(curr->name, (xmlChar *)Range) != 0) {
-			topo_mod_dprintf(mp,
+			topo_dprintf(mp->tm_hdl, TOPO_DBG_XML,
 			    "Ignoring non-range %s.\n", curr->name);
 			continue;
 		}
@@ -906,11 +922,12 @@
 	xmlNodePtr xroot;
 
 	if ((xroot = xmlDocGetRootElement(xinfo->tf_xdoc)) == NULL) {
-		topo_mod_dprintf(tmp, "Couldn't get root xmlNode.\n");
+		topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
+		    "Couldn't get root xmlNode.\n");
 		return (-1);
 	}
 	if ((xinfo->tf_rd = topo_xml_walk(tmp, xinfo, xroot, troot)) == NULL) {
-		topo_mod_dprintf(tmp,
+		topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
 		    "error within .xml topology: %s\n",
 		    topo_strerror(topo_mod_errno(tmp)));
 		return (-1);
@@ -933,7 +950,7 @@
 	char *dtdpath = NULL;
 	int readflags = 0;
 	tf_info_t *r;
-	int e;
+	int e, validate = 0;
 
 	/*
 	 * Since topologies can XInclude other topologies, and libxml2
@@ -947,6 +964,7 @@
 		dtdpath = getenv("TOPO_DTD");
 		if (dtdpath != NULL)
 			xmlLoadExtDtdDefaultValue = 0;
+		validate = 1;
 	}
 
 	/*
@@ -957,7 +975,8 @@
 		readflags = XML_PARSE_NOERROR | XML_PARSE_NOWARNING;
 
 	if ((document = xmlReadFd(fd, filenm, NULL, readflags)) == NULL) {
-		topo_mod_dprintf(tmp, "couldn't parse document.\n");
+		topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
+		    "couldn't parse document.\n");
 		return (NULL);
 	}
 
@@ -965,18 +984,19 @@
 	 * Verify that this is a document type we understand.
 	 */
 	if ((dtd = xmlGetIntSubset(document)) == NULL) {
-		topo_mod_dprintf(tmp, "document has no DTD.\n");
+		topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
+		    "document has no DTD.\n");
 		return (NULL);
 	}
 
-	if (strcmp((const char *)dtd->SystemID, TOPO_DTD_PATH) == -1) {
-		topo_mod_dprintf(tmp,
-		    "document DTD unknown; bad topology file?\n");
+	if (strcmp((const char *)dtd->SystemID, TOPO_DTD_PATH) != 0) {
+		topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
+		    "document DTD unknown; bad topology file\n");
 		return (NULL);
 	}
 
 	if ((cursor = xmlDocGetRootElement(document)) == NULL) {
-		topo_mod_dprintf(tmp, "document is empty.\n");
+		topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR, "document is empty.\n");
 		xmlFreeDoc(document);
 		return (NULL);
 	}
@@ -986,19 +1006,20 @@
 	 * expected scheme.
 	 */
 	if (xmlStrcmp(cursor->name, (xmlChar *)Topology) != 0) {
-		topo_mod_dprintf(tmp,
+		topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
 		    "document is not a topology description.\n");
 		xmlFreeDoc(document);
 		return (NULL);
 	}
 	if ((scheme = xmlGetProp(cursor, (xmlChar *)Scheme)) == NULL) {
-		topo_mod_dprintf(tmp, "topology lacks a scheme.\n");
+		topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
+		    "topology lacks a scheme.\n");
 		(void) topo_mod_seterrno(tmp, ETOPO_PRSR_NOATTR);
 		xmlFreeDoc(document);
 		return (NULL);
 	}
 	if (xmlStrcmp(scheme, (xmlChar *)escheme) != 0) {
-		topo_mod_dprintf(tmp,
+		topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
 		    "topology in unrecognized scheme, %s, expecting %s\n",
 		    scheme, escheme);
 		(void) topo_mod_seterrno(tmp, ETOPO_PRSR_BADSCH);
@@ -1010,7 +1031,7 @@
 	if (dtdpath != NULL) {
 		dtd = xmlParseDTD(NULL, (xmlChar *)dtdpath);
 		if (dtd == NULL) {
-			topo_mod_dprintf(tmp,
+			topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
 			    "Could not parse DTD \"%s\".\n",
 			    dtdpath);
 			return (NULL);
@@ -1023,34 +1044,32 @@
 	}
 
 	if (xmlXIncludeProcessFlags(document, XML_PARSE_XINCLUDE) == -1) {;
-		topo_mod_dprintf(tmp,
+		topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
 		    "couldn't handle XInclude statements in document\n");
 		return (NULL);
 	}
 
-	if ((vcp = xmlNewValidCtxt()) == NULL) {
-		xmlFree(scheme);
-		scheme = NULL;
-		return (NULL);
-	}
-	vcp->warning = xmlParserValidityWarning;
-	vcp->error = xmlParserValidityError;
+	if (validate) {
+		if ((vcp = xmlNewValidCtxt()) == NULL) {
+			xmlFree(scheme);
+			scheme = NULL;
+			return (NULL);
+		}
+		vcp->warning = xmlParserValidityWarning;
+		vcp->error = xmlParserValidityError;
 
-	e = xmlValidateDocument(vcp, document);
+		e = xmlValidateDocument(vcp, document);
 
-	xmlFreeValidCtxt(vcp);
+		xmlFreeValidCtxt(vcp);
 
-	if (e == 0) {
-		topo_mod_dprintf(tmp, "Document is not valid.\n");
-		xmlFreeDoc(document);
-		return (NULL);
+		if (e == 0)
+			topo_dprintf(tmp->tm_hdl, TOPO_DBG_ERR,
+			    "Document is not valid.\n");
 	}
 
-	if ((r = tf_info_new(tmp, filenm, document, scheme)) == NULL)
+	if ((r = tf_info_new(tmp, document, scheme)) == NULL)
 		return (NULL);
 
-	/* txml_dump(0, cursor); */
-
 	xmlFree(scheme);
 	scheme = NULL;
 	return (r);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/maps/Makefile	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,39 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+
+sparc_SUBDIRS =	sun4u \
+		sun4v \
+		SUNW,Sun-Fire \
+		SUNW,Sun-Fire-T200 \
+		SUNW,Sun-Fire-15000 \
+		SUNW,SPARC-Enterprise
+
+i386_SUBDIRS = i86pc
+
+SUBDIRS = $($(MACH)_SUBDIRS)
+
+include ../../Makefile.subdirs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/maps/Makefile.map	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,73 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+
+.KEEP_STATE:
+.SUFFIXES: .xml
+
+MODCLASS = maps
+
+include ../../../Makefile.lib
+include ../../../../Makefile.lib
+
+DTDSRC = $(DTDFILE:%=../common/%)
+DTDTARG = $(DTDFILE:%=%)
+ROOTDTDTARG = $(DTDTARG:%=$(ROOT)/usr/share/lib/xml/dtd/%)
+
+common_ROOTTOPOROOT = $(ROOT)/usr/lib/fm/topo/$(MODCLASS)
+arch_ROOTTOPOROOT = $(ROOT)/usr/platform/$(ARCH)/lib/fm/topo/$(MODCLASS)
+platform_ROOTTOPOROOT = \
+	$(PLATFORMS:%=$(ROOT)/usr/platform/%/lib/fm/topo/$(MODCLASS))
+ROOTTOPOROOT = $($(CLASS)_ROOTTOPOROOT)
+ROOTTOPOMAPS = $(TOPOFILE:%=$(ROOTTOPOROOT)/%)
+
+install:= FILEMODE =	0444
+
+.xml:
+	$(RM) $@
+	$(CAT) $< > $@
+
+include ../../Makefile.rootdirs
+
+all: $(TOPOFILE)
+
+clean:
+	$(RM) $(ROOTTOPOMAPS)
+
+clobber: clean
+
+check: $(CHECKHDRS)
+
+install_h lint _msg:
+
+$($(CLASS)_ROOTTOPOROOT)/%: %
+	$(INS.file)
+
+$(ROOTDTDTARG): $$(@D)
+	$(RM) $@; $(INS) -s -m 0444 -f $(@D) $(DTDSRC)
+
+install: all $(ROOTDTDTARG) $(ROOTTOPOROOT) $(ROOTTOPOMAPS)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/maps/SUNW,SPARC-Enterprise/Makefile	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,34 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#ident	"%Z%%M%	%I%	%E% SMI"
+
+PLATFORMS = SUNW,SPARC-Enterprise
+CLASS = platform
+DTDFILE =
+TOPOFILE = SPARC-Enterprise-hc-topology.xml
+SRCDIR = ../SUNW,SPARC-Enterprise
+
+include ../Makefile.map
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/maps/SUNW,SPARC-Enterprise/SPARC-Enterprise-hc-topology.xml	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,45 @@
+<?xml version="1.0"?>
+<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1">
+<!--
+ Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ Use is subject to license terms.
+
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License (the "License").
+ You may not use this file except in compliance with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+
+    ident	"%Z%%M%	%I%	%E% SMI"
+-->
+
+<topology name='SUNW,SPARC-Enterprise' scheme='hc'>
+  <range name='chassis' min='0' max='0'>
+    <node instance='0'>
+      <propgroup name='protocol' version='1'
+        name-stability='Private' data-stability='Private' >
+        <propval name='FRU' type='fmri'
+          value='hc:///chassis=0' />
+      </propgroup>
+    </node>
+    <dependents grouping='children'>
+      <range name='ioboard' min='0' max='15'>
+        <enum-method name='ioboard' version='1'
+          path='%r/usr/platform/SUNW,SPARC-Enterprise/lib/fm/topo/plugins' />
+      </range>
+    </dependents>
+  </range>
+</topology>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-15000/Makefile	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,34 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#ident	"%Z%%M%	%I%	%E% SMI"
+
+PLATFORMS = SUNW,Sun-Fire-15000
+CLASS = platform
+DTDFILE =
+TOPOFILE = Sun-Fire-15000-hc-topology.xml
+SRCDIR = ../SUNW,Sun-Fire-15000
+
+include ../Makefile.map
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-15000/Sun-Fire-15000-hc-topology.xml	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1">
+<!--
+ Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ Use is subject to license terms.
+
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License (the "License").
+ You may not use this file except in compliance with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+
+    ident	"%Z%%M%	%I%	%E% SMI"
+-->
+
+<topology name='SUNW,Sun-Fire-15000' scheme='hc'>
+  <range name='interconnect' min='0' max='0'>
+    <node instance='0'>
+      <propgroup name='protocol' version='1'
+        name-stability='Private' data-stability='Private' >
+        <propval name='FRU' type='fmri'
+          value='hc:///component=interconnect' />
+        <propval name='label' type='string'
+          value='interconnect' />
+      </propgroup>
+    </node>
+    <dependents grouping='children'>
+      <range name='ioboard' min='0' max='17'>
+        <enum-method name='ioboard' version='1' />
+      </range>
+      <range name='cpu' min='0' max='100'>
+        <enum-method name='chip' version='1' />
+      </range>
+    </dependents>
+  </range>
+</topology>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-T200/Makefile	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,38 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#ident	"%Z%%M%	%I%	%E% SMI"
+
+PLATFORMS = SUNW,Sun-Fire-T200
+CLASS = platform
+DTDFILE =
+TOPOFILE = Sun-Fire-T200-hc-topology.xml	\
+	Sun-Fire-T1000-hc-topology.xml	\
+	SPARC-Enterprise-T1000-hc-topology.xml \
+	Sun-Blade-T6300-hc-topology.xml
+
+SRCDIR = ../SUNW,Sun-Fire-T200
+
+include ../Makefile.map
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-T200/SPARC-Enterprise-T1000-hc-topology.xml	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1">
+<!--
+ Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ Use is subject to license terms.
+
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License (the "License").
+ You may not use this file except in compliance with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+
+    ident	"%Z%%M%	%I%	%E% SMI"
+-->
+
+<topology name='SUNW,SPARC-Enterprise-T1000' scheme='hc'>
+  <range name='motherboard' min='0' max='0'>
+    <node instance='0'>
+     <propgroup name='protocol' version='1'
+        name-stability='Private' data-stability='Private' >
+        <propval name='FRU' type='fmri'
+          value='hc:///component=MB' />
+        <propval name='label' type='string'
+          value='MB' />
+      </propgroup>
+    </node>
+    <dependents grouping='children'>
+     <range name='hostbridge' min='0' max='254'>
+       <enum-method name='hostbridge' version='1' />
+     </range>
+    </dependents>
+  </range>
+</topology>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-T200/Sun-Blade-T6300-hc-topology.xml	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1">
+<!--
+ Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ Use is subject to license terms.
+
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License (the "License").
+ You may not use this file except in compliance with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+
+    ident	"%Z%%M%	%I%	%E% SMI"
+-->
+
+<topology name='SUNW,Sun-Blade-T6300' scheme='hc'>
+  <range name='motherboard' min='0' max='0'>
+    <node instance='0'>
+     <propgroup name='protocol' version='1'
+        name-stability='Private' data-stability='Private' >
+        <propval name='FRU' type='fmri'
+          value='hc:///component=MB' />
+        <propval name='label' type='string'
+          value='MB' />
+      </propgroup>
+    </node>
+    <dependents grouping='children'>
+     <range name='hostbridge' min='0' max='254'>
+       <enum-method name='hostbridge' version='1' />
+     </range>
+    </dependents>
+  </range>
+</topology>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-T200/Sun-Fire-T1000-hc-topology.xml	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1">
+<!--
+ Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ Use is subject to license terms.
+
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License (the "License").
+ You may not use this file except in compliance with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+
+    ident	"%Z%%M%	%I%	%E% SMI"
+-->
+
+<topology name='SUNW,Sun-Fire-T1000' scheme='hc'>
+  <range name='motherboard' min='0' max='0'>
+    <node instance='0'>
+     <propgroup name='protocol' version='1'
+        name-stability='Private' data-stability='Private' >
+        <propval name='FRU' type='fmri'
+          value='hc:///component=MB' />
+        <propval name='label' type='string'
+          value='MB' />
+      </propgroup>
+    </node>
+    <dependents grouping='children'>
+     <range name='hostbridge' min='0' max='254'>
+       <enum-method name='hostbridge' version='1' />
+     </range>
+    </dependents>
+  </range>
+</topology>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-T200/Sun-Fire-T200-hc-topology.xml	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,57 @@
+<?xml version="1.0"?>
+<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1">
+<!--
+ Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ Use is subject to license terms.
+
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License (the "License").
+ You may not use this file except in compliance with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+
+    ident	"%Z%%M%	%I%	%E% SMI"
+-->
+
+<topology name='SUNW,Sun-Fire-T200' scheme='hc'>
+  <range name='motherboard' min='0' max='0'>
+    <node instance='0'>
+     <propgroup name='protocol' version='1'
+        name-stability='Private' data-stability='Private' >
+        <propval name='FRU' type='fmri'
+          value='hc:///component=MB' />
+        <propval name='label' type='string'
+          value='MB' />
+      </propgroup>
+    </node>
+  </range>
+  <range name='ioboard' min='0' max='0'>
+    <node instance='0'>
+     <propgroup name='protocol' version='1'
+        name-stability='Private' data-stability='Private' >
+        <propval name='FRU' type='fmri'
+          value='hc:///component=IOBD' />
+        <propval name='label' type='string'
+          value='IOBD' />
+      </propgroup>
+      </node>
+      <dependents grouping='children'>
+        <range name='hostbridge' min='0' max='254'>
+          <enum-method name='hostbridge' version='1' />
+        </range>
+      </dependents>
+    </range>
+</topology>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire/Makefile	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,34 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#ident	"%Z%%M%	%I%	%E% SMI"
+
+PLATFORMS = SUNW,Sun-Fire
+CLASS = platform
+DTDFILE =
+TOPOFILE = Sun-Fire-hc-topology.xml
+SRCDIR = ../SUNW,Sun-Fire
+
+include ../Makefile.map
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire/Sun-Fire-hc-topology.xml	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1">
+<!--
+ Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ Use is subject to license terms.
+
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License (the "License").
+ You may not use this file except in compliance with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+
+    ident	"%Z%%M%	%I%	%E% SMI"
+-->
+
+<topology name='SUNW,Sun-Fire' scheme='hc'>
+  <range name='centerplane' min='0' max='0'>
+    <node instance='0'>
+      <propgroup name='protocol' version='1'
+        name-stability='Private' data-stability='Private' >
+        <propval name='FRU' type='fmri'
+          value='hc:///component=centerplane' />
+        <propval name='label' type='string'
+          value='centerplane' />
+      </propgroup>
+    </node>
+    <dependents grouping='children'>
+      <range name='ioboard' min='0' max='9'>
+        <enum-method name='ioboard' version='1' />
+      </range>
+      <range name='cpu' min='0' max='100'>
+        <enum-method name='chip' version='1' />
+      </range>
+    </dependents>
+  </range>
+</topology>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/maps/common/topology.dtd.1	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ Use is subject to license terms.
+
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License (the "License").
+ You may not use this file except in compliance with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+
+    ident	"%Z%%M%	%I%	%E% SMI"
+-->
+
+<!--
+  Topology description DTD
+
+    Most attributes are string values (or an individual string from a
+    restricted set), but attributes with a specific type requirement are
+    noted in the comment describing the element.
+-->
+
+<!--
+  XInclude support
+
+    Topologies may be composed via the xi:include tag.
+    libtopo(3LIB) interfaces enforce that all composed topologies be of the
+    same scheme.
+-->
+
+<!ELEMENT xi:include
+	(xi:fallback) >
+
+<!ATTLIST xi:include
+  href CDATA #REQUIRED
+  parse (xml|text) "xml"
+  encoding CDATA #IMPLIED
+  xmlns:xi CDATA #FIXED "http://www.w3.org/2001/XInclude"
+  >
+
+<!ELEMENT xi:fallback
+  ANY
+  >
+<!ATTLIST xi:fallback
+  xmlns:xi CDATA #FIXED "http://www.w3.org/2001/XInclude"
+  >
+
+<!-- Properties and property groups -->
+
+<!--
+   propval
+
+     This element is for a singly valued property within a property
+     group.
+
+     Its attributes are
+
+	name	The name of this property.
+
+	type	The data type for this property.
+
+	value	The value for this property.  Must match type
+		restriction of type attribute.
+
+	immutable This value remains unchanged for the lifetime of a snapshot.
+-->
+
+<!ELEMENT propval EMPTY >
+
+<!ATTLIST propval
+	name		CDATA #REQUIRED
+	type		( int32 | uint32 | int64 | uint64 |
+			  string | fmri ) #REQUIRED
+	value		CDATA #REQUIRED
+	immutable	( true | false ) "true" >
+
+<!--
+  propgroup
+
+    This element is for a set of related properties on a topo node
+    It contains an optional stability element, as well as
+    zero or more property-containing elements.
+
+    Its attributes are
+
+	name		The name of this property group.
+	name-stability	Stability level of the property group name
+	data-stability	Stability level of the property names and content
+	version		Version of the propery group definition
+
+-->
+
+<!ELEMENT propgroup
+	( propval* ) >
+
+<!ATTLIST propgroup
+	name		CDATA #REQUIRED
+	version		CDATA #REQUIRED
+	name-stability	( Private | Standard | Stable | Evolving | Unstable |
+                        External | Obsolete ) #REQUIRED
+	data-stability	( Private | Standard | Stable | Evolving | Unstable |
+                        External | Obsolete ) #REQUIRED >
+
+<!-- Methods -->
+
+<!--
+  enum-method
+
+    This element describes the enumeration method used to
+    populate a composition of topo nodes.  Its interpretation is
+    left to the enumerator to which a particular topo node is
+    assigned.  It contains a set of attributes, context, and an optional
+    stability element for the optional args that can be included.
+
+    Its attributes are
+
+	name	Name of this method.  The method names are
+		usually a defined interface of the enumerator to which a
+		topo instance assigned.
+
+	version Version of the enumeration API
+
+-->
+
+<!ELEMENT enum-method EMPTY >
+
+<!ATTLIST enum-method
+	name		CDATA #REQUIRED
+	version		CDATA #REQUIRED >
+
+<!--
+  node
+
+    This element identifies a known topology node.
+
+    Its attributes are
+
+	instance The instance number of the known node
+
+	static	Boolean to determine if node is statically created
+		by the XML parser or an enumerator
+
+-->
+
+<!ELEMENT node
+	( propgroup*, dependents* ) >
+
+<!ATTLIST node
+	instance	CDATA #REQUIRED
+	static          ( true | false ) "false" >
+
+<!--
+  dependents
+
+	Ranges may have a number of "dependent" ranges, linked to
+	the original range hierarchically as children or siblings. 
+
+	Its attribute is:
+		grouping	"children", "siblings"
+-->
+
+<!ELEMENT dependents 
+	( range | xi:include )+ >
+
+<!ATTLIST dependents 
+	grouping ( children | siblings ) #REQUIRED >
+
+<!--
+  range
+
+    This element identifies a range of possible topology nodes.
+
+    Its attributes are
+
+	name	The common name of all the possible topo nodes
+
+	min	The smallest allowed instance number for an
+		actual topo node.
+
+	max	The largest allowed instance number for an
+		actual topo node.
+
+-->
+
+<!ELEMENT range
+	( enum-method?, node*, propgroup*, dependents* ) >
+
+<!ATTLIST range
+	name		CDATA #REQUIRED
+	min		CDATA #REQUIRED
+	max		CDATA #REQUIRED >
+
+<!--
+  topology
+
+	This is the root-level for the scheme-specific topology
+
+	Its attributes are:
+		name	topology name
+		scheme  "hc", "dev"
+-->
+
+<!ELEMENT topology
+	(range* | xi:include*)>
+
+<!ATTLIST topology
+	name	CDATA #REQUIRED
+	scheme (hc | dev) #REQUIRED >
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/maps/i86pc/Makefile	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,33 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#ident	"%Z%%M%	%I%	%E% SMI"
+
+ARCH = i86pc
+CLASS = arch
+DTDFILE = topology.dtd.1
+TOPOFILE = i86pc-hc-topology.xml storage-hc-topology.xml
+SRCDIR = ../i86pc
+
+include ../Makefile.map
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/maps/i86pc/i86pc-hc-topology.xml	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1">
+<!--
+ Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ Use is subject to license terms.
+
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License (the "License").
+ You may not use this file except in compliance with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+
+    ident	"%Z%%M%	%I%	%E% SMI"
+-->
+
+<topology name='i86pc' scheme='hc'>
+
+  <range name='motherboard' min='0' max='0'>
+    <node instance='0'>
+      <propgroup name='protocol' version='1'
+        name-stability='Private' data-stability='Private' >
+        <propval name='FRU' type='fmri'
+          value='hc:///component=motherboard' />
+        <propval name='label' type='string'
+          value='MB' />
+      </propgroup>
+    </node>
+    <dependents grouping='children'>
+      <range name='chip' min='0' max='100'>
+        <enum-method name='chip' version='1' />
+      </range>
+      <range name='hostbridge' min='0' max='254'>
+        <enum-method name='hostbridge' version='1' />
+      </range>
+    </dependents>
+  </range>
+
+</topology>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/maps/i86pc/storage-hc-topology.xml	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1">
+<!--
+ Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ Use is subject to license terms.
+
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License (the "License").
+ You may not use this file except in compliance with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+
+    ident	"%Z%%M%	%I%	%E% SMI"
+-->
+
+<topology name='storage' scheme='hc'>
+
+  <range name='sata-port' min='0' max='7'>
+      <enum-method name='sata' version='1' />
+  </range>
+
+  <range name='disk' min='0' max='15'>
+      <enum-method name='scsi' version='1' />
+  </range>
+
+</topology>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/maps/sun4u/Makefile	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,34 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#ident	"%Z%%M%	%I%	%E% SMI"
+
+ARCH = sun4u
+CLASS = arch
+DTDFILE = topology.dtd.1
+TOPOFILE = sun4u-hc-topology.xml
+SRCDIR = ../sun4u
+
+include ../Makefile.map
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/maps/sun4u/sun4u-hc-topology.xml	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1">
+<!--
+ Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ Use is subject to license terms.
+
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License (the "License").
+ You may not use this file except in compliance with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+
+    ident	"%Z%%M%	%I%	%E% SMI"
+-->
+
+<topology name='sun4u' scheme='hc'>
+  <range name='motherboard' min='0' max='0'>
+    <node instance='0'>
+      <propgroup name='protocol' version='1'
+        name-stability='Private' data-stability='Private' >
+        <propval name='FRU' type='fmri'
+          value='hc:///component=MB' />
+        <propval name='label' type='string'
+          value='MB' />
+      </propgroup>
+    </node>
+    <dependents grouping='children'>
+      <range name='hostbridge' min='0' max='254'>
+        <enum-method name='hostbridge' version='1' />
+      </range>
+      <range name='cpu' min='0' max='100'>
+        <enum-method name='chip' version='1' />
+      </range>
+    </dependents>
+  </range>
+</topology>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/maps/sun4v/Makefile	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,34 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#ident	"%Z%%M%	%I%	%E% SMI"
+
+ARCH = sun4v
+CLASS = arch
+DTDFILE =
+TOPOFILE = sun4v-hc-topology.xml
+SRCDIR = ../sun4v
+
+include ../Makefile.map
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/maps/sun4v/sun4v-hc-topology.xml	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1">
+<!--
+ Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ Use is subject to license terms.
+
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License (the "License").
+ You may not use this file except in compliance with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+
+    ident	"%Z%%M%	%I%	%E% SMI"
+-->
+
+<topology name='sun4v' scheme='hc'>
+  <range name='motherboard' min='0' max='0'>
+    <node instance='0'>
+     <propgroup name='protocol' version='1'
+        name-stability='Private' data-stability='Private' >
+        <propval name='FRU' type='fmri'
+          value='hc:///component=MB' />
+        <propval name='label' type='string'
+          value='MB' />
+      </propgroup>
+    </node>
+    <dependents grouping='children'>
+     <range name='hostbridge' min='0' max='254'>
+       <enum-method name='hostbridge' version='1' />
+     </range>
+    </dependents>
+  </range>
+</topology>
--- a/usr/src/lib/fm/topo/modules/Makefile.plugin	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/Makefile.plugin	Sat Nov 04 01:18:55 2006 -0800
@@ -64,7 +64,7 @@
 CFLAGS += $(CTF_FLAGS) $(CCVERBOSE) $(XSTRCONST) $(CC_PICFLAGS)
 CFLAGS += -G $(XREGSFLAG)
 
-CPPFLAGS += -I. -I../../common -I../../../libtopo/common
+CPPFLAGS += -I.
 CPPFLAGS += -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT
 LDFLAGS += $(ZIGNORE) -M$(APIMAP)
 LDLIBS += -L$(ROOTLIBDIR)/fm -R/usr/lib/fm -ltopo -lnvpair -lc
@@ -79,7 +79,7 @@
 	$(CTFMERGE) -L VERSION -o $@ $(OBJS)
 	$(POST_PROCESS_SO)
 
-%.o: ../../common/%.c
+%.o: ../../common/$(MODULE)/%.c
 	$(COMPILE.c) $<
 	$(CTFCONVERT_O)
 
@@ -93,7 +93,7 @@
 clobber: clean
 	$(RM) $(PROG)
 
-%.ln: ../../common/%.c
+%.ln: ../../common/$(MODULE)/%.c
 	$(LINT.c) -c $<
 
 %.ln: %.c
--- a/usr/src/lib/fm/topo/modules/SUNW,SPARC-Enterprise/ioboard/opl_hostbridge.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/SUNW,SPARC-Enterprise/ioboard/opl_hostbridge.c	Sat Nov 04 01:18:55 2006 -0800
@@ -30,42 +30,31 @@
 #include <strings.h>
 #include <libdevinfo.h>
 #include <fm/topo_mod.h>
+#include <fm/topo_hc.h>
 #include <sys/fm/protocol.h>
 #include "opl_topo.h"
 
-/*
- * The following #define's are also in did_props.h, but I can't include that
- * header file here. They should probably be moved to a centrally-located
- * header file somewhere, since they may also be needed by diagnosis engines
- * or agents.
- */
-#define	TOPO_PGROUP_IO		"io"
-#define	TOPO_PROP_DEVTYPE	"DEVTYPE"
-#define	TOPO_PROP_DRIVER	"DRIVER"
-#define	TOPO_PROP_DEV		"DEV"
-
-#define	TOPO_PGROUP_PCI		"pci"
-#define	TOPO_PROP_EXCAP		"EXCAP"
-#define	TOPO_PROP_BDF		"BDF"
-#define	TOPO_PROP_VENDID	"VENDOR-ID"
-#define	TOPO_PROP_DEVID		"DEVICE-ID"
-#define	TOPO_PROP_CLASS		"CLASS-CODE"
-
-#define	PCIEX_ROOT		"pciexrc"
-
+static const topo_pgroup_info_t io_pgroup =
+	{ TOPO_PGROUP_IO, TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
+static const topo_pgroup_info_t pci_pgroup =
+	{ TOPO_PGROUP_PCI, TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
 
 /*
  * Check the root complex device node for a slot-names property.
  */
 const char *
-opl_get_slot_name(di_node_t n, di_prom_handle_t opl_promtree)
+opl_get_slot_name(topo_mod_t *mod, di_node_t n)
 {
+	di_prom_handle_t ptp = DI_PROM_HANDLE_NIL;
 	di_prom_prop_t pp = DI_PROM_PROP_NIL;
 	uchar_t *buf;
 
-	for (pp = di_prom_prop_next(opl_promtree, n, pp);
+	if ((ptp = topo_mod_prominfo(mod)) == DI_PROM_PROP_NIL)
+		return (NULL);
+
+	for (pp = di_prom_prop_next(ptp, n, pp);
 	    pp != DI_PROM_PROP_NIL;
-	    pp = di_prom_prop_next(opl_promtree, n, pp)) {
+	    pp = di_prom_prop_next(ptp, n, pp)) {
 		if (strcmp(di_prom_prop_name(pp), OPL_SLOT_NAMES) == 0) {
 			if (di_prom_prop_data(pp, &buf) <= sizeof (uint32_t))
 				continue;
@@ -79,51 +68,35 @@
 opl_node_create(topo_mod_t *mp, tnode_t *parent, const char *name, int inst,
     void *priv)
 {
-	int err;
 	tnode_t *node;
 	nvlist_t *fmri;
-	nvlist_t *args = NULL;
-	nvlist_t *pfmri = NULL;
-	topo_hdl_t *thp = topo_mod_handle(mp);
+	nvlist_t *auth = topo_mod_auth(mp, parent);
 
 	if (parent == NULL || inst < 0) {
 		return (NULL);
 	}
 
-	/* Get parent FMRI */
-	(void) topo_node_resource(parent, &pfmri, &err);
-	if (pfmri != NULL) {
-		if (topo_mod_nvalloc(mp, &args, NV_UNIQUE_NAME) != 0 ||
-		    nvlist_add_nvlist(args, TOPO_METH_FMRI_ARG_PARENT, pfmri)
-		    != 0) {
-			nvlist_free(pfmri);
-			nvlist_free(args);
-			(void) topo_mod_seterrno(mp, EMOD_FMRI_NVL);
-			return (NULL);
-		}
-		nvlist_free(pfmri);
-	}
-
 	/* Create FMRI */
-	if ((fmri = topo_fmri_create(thp, FM_FMRI_SCHEME_HC, name, inst,
-	    args, &err)) == NULL) {
-		topo_mod_dprintf(mp, "create of tnode for %s failed: %s\n",
+	if ((fmri = topo_mod_hcfmri(mp, parent, FM_HC_SCHEME_VERSION, name,
+	    inst, NULL, auth, NULL, NULL, NULL)) == NULL) {
+		topo_mod_dprintf(mp, "create of tnode for %s failed: %s",
 		    name, topo_strerror(topo_mod_errno(mp)));
-		(void) topo_mod_seterrno(mp, err);
-		nvlist_free(args);
+		nvlist_free(auth);
 		return (NULL);
 	}
-	nvlist_free(args);
+	nvlist_free(auth);
 
 	/* Create and bind node  */
-	node = topo_node_bind(mp, parent, name, inst, fmri, priv);
+	node = topo_node_bind(mp, parent, name, inst, fmri);
 	if (node == NULL) {
 		nvlist_free(fmri);
 		topo_mod_dprintf(mp, "unable to bind root complex: %s\n",
 		    topo_strerror(topo_mod_errno(mp)));
 		return (NULL); /* mod_errno already set */
 	}
+
 	nvlist_free(fmri);
+	topo_node_setspecific(node, priv);
 
 	return (node);
 }
@@ -132,16 +105,14 @@
  * Create a root complex node.
  */
 static tnode_t *
-opl_rc_node_create(topo_mod_t *mp, tnode_t *parent, di_node_t dnode, int inst,
-    di_prom_handle_t opl_promtree)
+opl_rc_node_create(topo_mod_t *mp, tnode_t *parent, di_node_t dnode, int inst)
 {
 	int err;
 	tnode_t *rcn;
-	topo_hdl_t *thp = topo_mod_handle(mp);
 	const char *slot_name;
 	char *dnpath;
 
-	rcn = opl_node_create(mp, parent, PCIEXRC, inst, (void *)dnode);
+	rcn = opl_node_create(mp, parent, PCIEX_ROOT, inst, (void *)dnode);
 	if (rcn == NULL) {
 		return (NULL);
 	}
@@ -150,14 +121,14 @@
 	 * If this root complex connects to a slot, it will have a
 	 * slot-names property.
 	 */
-	slot_name = opl_get_slot_name(dnode, opl_promtree);
+	slot_name = opl_get_slot_name(mp, dnode);
 	if (slot_name) {
 		char fru_str[64];
 		nvlist_t *fru_fmri;
 		/* Add FRU fmri */
 		snprintf(fru_str, sizeof (fru_str), "hc:///component=%s",
 		    slot_name);
-		if (topo_fmri_str2nvl(thp, fru_str, &fru_fmri, &err) == 0) {
+		if (topo_mod_str2nvl(mp, fru_str, &fru_fmri) == 0) {
 			(void) topo_node_fru_set(rcn, fru_fmri, 0, &err);
 			nvlist_free(fru_fmri);
 		}
@@ -173,25 +144,10 @@
 	 * Set ASRU to be the dev-scheme ASRU
 	 */
 	if ((dnpath = di_devfs_path(dnode)) != NULL) {
-		nvlist_t *in;
 		nvlist_t *fmri;
-		if (topo_mod_nvalloc(mp, &in, NV_UNIQUE_NAME) != 0) {
-			topo_mod_dprintf(mp, "topo_mod_nvalloc failed\n");
-			di_devfs_path_free(dnpath);
-			topo_mod_seterrno(mp, EMOD_FMRI_NVL);
-			return (NULL);
-		}
-		if (nvlist_add_string(in, FM_FMRI_DEV_PATH,
-		    dnpath) != 0) {
-			topo_mod_dprintf(mp, "nvlist_add_string failed\n");
-			nvlist_free(in);
-			di_devfs_path_free(dnpath);
-			topo_mod_seterrno(mp, EMOD_NOMEM);
-			return (NULL);
-		}
-		fmri = topo_fmri_create(thp, FM_FMRI_SCHEME_DEV,
-		    FM_FMRI_SCHEME_DEV, 0, in, &err);
-		nvlist_free(in);
+
+		fmri = topo_mod_devfmri(mp, FM_DEV_SCHEME_VERSION,
+		    dnpath, NULL);
 		if (fmri == NULL) {
 			topo_mod_dprintf(mp,
 			    "dev:///%s fmri creation failed.\n",
@@ -217,15 +173,13 @@
 	 */
 
 	/* Add the io and pci property groups */
-	if (topo_pgroup_create(rcn, TOPO_PGROUP_IO,
-	    TOPO_STABILITY_PRIVATE, &err) < 0) {
+	if (topo_pgroup_create(rcn, &io_pgroup, &err) < 0) {
 		topo_mod_dprintf(mp, "topo_pgroup_create failed\n");
 		di_devfs_path_free(dnpath);
 		topo_mod_seterrno(mp, err);
 		return (NULL);
 	}
-	if (topo_pgroup_create(rcn, TOPO_PGROUP_PCI,
-	    TOPO_STABILITY_PRIVATE, &err) < 0) {
+	if (topo_pgroup_create(rcn, &pci_pgroup, &err) < 0) {
 		topo_mod_dprintf(mp, "topo_pgroup_create failed\n");
 		di_devfs_path_free(dnpath);
 		topo_mod_seterrno(mp, err);
@@ -233,8 +187,8 @@
 	}
 	/* Add the devfs path property */
 	if (dnpath) {
-		if (topo_prop_set_string(rcn, TOPO_PGROUP_IO, TOPO_PROP_DEV,
-		    TOPO_PROP_SET_ONCE, dnpath, &err) != 0) {
+		if (topo_prop_set_string(rcn, TOPO_PGROUP_IO, TOPO_IO_DEV,
+		    TOPO_PROP_IMMUTABLE, dnpath, &err) != 0) {
 			topo_mod_dprintf(mp, "Failed to set DEV property\n");
 			di_devfs_path_free(dnpath);
 			topo_mod_seterrno(mp, err);
@@ -242,23 +196,23 @@
 		di_devfs_path_free(dnpath);
 	}
 	/* Oberon device type is always "pciex" */
-	if (topo_prop_set_string(rcn, TOPO_PGROUP_IO, TOPO_PROP_DEVTYPE,
-	    TOPO_PROP_SET_ONCE, OPL_PX_DEVTYPE, &err) != 0) {
+	if (topo_prop_set_string(rcn, TOPO_PGROUP_IO, TOPO_IO_DEVTYPE,
+	    TOPO_PROP_IMMUTABLE, OPL_PX_DEVTYPE, &err) != 0) {
 		topo_mod_dprintf(mp, "Failed to set DEVTYPE property\n");
 	}
 	/* Oberon driver is always "px" */
-	if (topo_prop_set_string(rcn, TOPO_PGROUP_IO, TOPO_PROP_DRIVER,
-	    TOPO_PROP_SET_ONCE, OPL_PX_DRV, &err) != 0) {
+	if (topo_prop_set_string(rcn, TOPO_PGROUP_IO, TOPO_IO_DRIVER,
+	    TOPO_PROP_IMMUTABLE, OPL_PX_DRV, &err) != 0) {
 		topo_mod_dprintf(mp, "Failed to set DRIVER property\n");
 	}
 	/* This is a PCIEX Root Complex */
-	if (topo_prop_set_string(rcn, TOPO_PGROUP_PCI, TOPO_PROP_EXCAP,
-	    TOPO_PROP_SET_ONCE, PCIEX_ROOT, &err) != 0) {
+	if (topo_prop_set_string(rcn, TOPO_PGROUP_PCI, TOPO_PCI_EXCAP,
+	    TOPO_PROP_IMMUTABLE, PCIEX_ROOT, &err) != 0) {
 		topo_mod_dprintf(mp, "Failed to set EXCAP property\n");
 	}
 	/* BDF of Oberon root complex is constant */
 	if (topo_prop_set_string(rcn, TOPO_PGROUP_PCI,
-	    TOPO_PROP_BDF, TOPO_PROP_SET_ONCE, OPL_PX_BDF, &err) != 0) {
+	    TOPO_PCI_BDF, TOPO_PROP_IMMUTABLE, OPL_PX_BDF, &err) != 0) {
 		topo_mod_dprintf(mp, "Failed to set EXCAP property\n");
 	}
 
@@ -286,7 +240,7 @@
 	(void) topo_node_label_set(hbn, NULL, &err);
 
 	/* Make room for children */
-	topo_node_range_create(mp, hbn, PCIEXRC, 0, OPL_RC_MAX);
+	topo_node_range_create(mp, hbn, PCIEX_ROOT, 0, OPL_RC_MAX);
 
 	return (hbn);
 }
@@ -297,7 +251,7 @@
  */
 int
 opl_hb_enum(topo_mod_t *mp, const ioboard_contents_t *iob, tnode_t *ion,
-    int brd, di_prom_handle_t opl_promtree)
+    int brd)
 {
 	int hb;
 	int rc;
@@ -307,7 +261,7 @@
 	topo_mod_t *pcimod;
 
 	/* Load the pcibus module. We'll need it later. */
-	pcimod = topo_mod_load(mp, PCI_MOD_PATH);
+	pcimod = topo_mod_load(mp, PCI_BUS, PCI_BUS_VERS);
 	if (pcimod == NULL) {
 		topo_mod_dprintf(mp, "can't load pcibus module: %s\n",
 		    topo_strerror(topo_mod_errno(mp)));
@@ -347,8 +301,7 @@
 			}
 
 			/* Create the root complex node */
-			rcnode = opl_rc_node_create(mp, hbnode, p, rc,
-			    opl_promtree);
+			rcnode = opl_rc_node_create(mp, hbnode, p, rc);
 			if (rcnode == NULL) {
 				topo_mod_dprintf(mp,
 				    "unable to create rcnode: %s\n",
@@ -359,7 +312,7 @@
 
 			/* Enumerate pcibus nodes under the root complex */
 			if (topo_mod_enumerate(pcimod, rcnode,
-			    PCI_BUS, PCIEX_BUS, 0, 255) != 0) {
+			    PCI_BUS, PCIEX_BUS, 0, 255, NULL) != 0) {
 				topo_mod_dprintf(mp,
 				    "error enumerating pcibus: %s\n",
 				    topo_strerror(topo_mod_errno(mp)));
--- a/usr/src/lib/fm/topo/modules/SUNW,SPARC-Enterprise/ioboard/opl_ioboard.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/SUNW,SPARC-Enterprise/ioboard/opl_ioboard.c	Sat Nov 04 01:18:55 2006 -0800
@@ -33,6 +33,7 @@
 #include <strings.h>
 #include <libdevinfo.h>
 #include <fm/topo_mod.h>
+#include <fm/topo_hc.h>
 #include <sys/fm/protocol.h>
 #include "opl_topo.h"
 
@@ -42,13 +43,16 @@
 #define	IOBDFRU		"hc:///component=" LABEL
 
 static int opl_iob_enum(topo_mod_t *hdl, tnode_t *parent, const char *name,
-    topo_instance_t imin, topo_instance_t imax, void *notused);
+    topo_instance_t imin, topo_instance_t imax, void *notused1, void *notused2);
 
-const topo_modinfo_t IobInfo = {
+static const topo_modops_t Iobops =
+	{ opl_iob_enum, NULL };
+
+static const topo_modinfo_t IobInfo = {
 	IOBOARD,
+	FM_FMRI_SCHEME_HC,
 	IOB_ENUMR_VERS,
-	opl_iob_enum,
-	NULL};
+	&Iobops};
 
 void
 _topo_init(topo_mod_t *modhdl)
@@ -57,10 +61,10 @@
 	 * Turn on module debugging output
 	 */
 	if (getenv("TOPOIOBDBG") != NULL)
-		topo_mod_setdebug(modhdl, TOPO_DBG_ALL);
+		topo_mod_setdebug(modhdl);
 	topo_mod_dprintf(modhdl, "initializing ioboard enumerator\n");
 
-	topo_mod_register(modhdl, &IobInfo, NULL);
+	topo_mod_register(modhdl, &IobInfo, TOPO_VERSION);
 }
 
 void
@@ -74,16 +78,19 @@
  * device node.
  */
 static int
-opl_get_physical_board(di_node_t n, di_prom_handle_t opl_promtree)
+opl_get_physical_board(topo_mod_t *mod, di_node_t n)
 {
+	di_prom_handle_t ptp = DI_PROM_HANDLE_NIL;
 	di_prom_prop_t pp = DI_PROM_PROP_NIL;
 	uchar_t *buf;
 	int val;
 
+	if ((ptp = topo_mod_prominfo(mod)) == DI_PROM_HANDLE_NIL)
+		return (-1);
 
-	for (pp = di_prom_prop_next(opl_promtree, n, pp);
+	for (pp = di_prom_prop_next(ptp, n, pp);
 	    pp != DI_PROM_PROP_NIL;
-	    pp = di_prom_prop_next(opl_promtree, n, pp)) {
+	    pp = di_prom_prop_next(ptp, n, pp)) {
 		if (strcmp(di_prom_prop_name(pp), OPL_PHYSICAL_BD) == 0) {
 			if (di_prom_prop_data(pp, &buf) < sizeof (val))
 				continue;
@@ -98,8 +105,8 @@
  * Creates a map of logical boards to physical location.
  */
 static void
-opl_map_boards(int lsb_to_psb[OPL_IOB_MAX], di_node_t opl_devtree,
-    di_prom_handle_t opl_promtree)
+opl_map_boards(topo_mod_t *mod, di_node_t opl_devtree,
+    int lsb_to_psb[OPL_IOB_MAX])
 {
 	di_node_t n;
 	int i;
@@ -129,7 +136,7 @@
 		a = OPL_MC_STR2BA(ba);
 		lsb = OPL_MC_LSB(a);
 
-		psb = opl_get_physical_board(n, opl_promtree);
+		psb = opl_get_physical_board(mod, n);
 		if (psb < 0 || psb >= OPL_IOB_MAX) {
 			/* psb mapping is out of range, skip */
 			continue;
@@ -148,41 +155,25 @@
 	int err;
 	tnode_t *ion;
 	nvlist_t *fmri;
-	nvlist_t *args = NULL;
-	nvlist_t *pfmri = NULL;
-	topo_hdl_t *thp = topo_mod_handle(mp);
 	char label[8];
 	char fmri_str[32];
+	nvlist_t *auth = topo_mod_auth(mp, parent);
 
 	if (parent == NULL || inst < 0) {
 		return (NULL);
 	}
 
-	/* Get parent FMRI */
-	(void) topo_node_resource(parent, &pfmri, &err);
-	if (pfmri != NULL) {
-		if (topo_mod_nvalloc(mp, &args, NV_UNIQUE_NAME) != 0 ||
-		    nvlist_add_nvlist(args, TOPO_METH_FMRI_ARG_PARENT, pfmri)
-		    != 0) {
-			nvlist_free(pfmri);
-			nvlist_free(args);
-			(void) topo_mod_seterrno(mp, EMOD_FMRI_NVL);
-			return (NULL);
-		}
-		nvlist_free(pfmri);
-	}
 	/* Create ioboard FMRI */
-	if ((fmri = topo_fmri_create(thp, FM_FMRI_SCHEME_HC, IOBOARD, inst,
-	    args, &err)) == NULL) {
+	if ((fmri = topo_mod_hcfmri(mp, parent, FM_HC_SCHEME_VERSION, IOBOARD,
+	    inst, NULL, auth, NULL, NULL, NULL)) == NULL) {
+		nvlist_free(auth);
 		topo_mod_dprintf(mp, "create of tnode for ioboard failed: %s\n",
 		    topo_strerror(topo_mod_errno(mp)));
-		(void) topo_mod_seterrno(mp, err);
-		nvlist_free(args);
 		return (NULL);
 	}
-	nvlist_free(args);
+	nvlist_free(auth);
 	/* Create node for this ioboard */
-	ion = topo_node_bind(mp, parent, IOBOARD, inst, fmri, NULL);
+	ion = topo_node_bind(mp, parent, IOBOARD, inst, fmri);
 	if (ion == NULL) {
 		nvlist_free(fmri);
 		topo_mod_dprintf(mp, "unable to bind ioboard: %s\n",
@@ -192,7 +183,7 @@
 	nvlist_free(fmri);
 	/* Create and add FRU fmri for this ioboard */
 	snprintf(fmri_str, sizeof (fmri_str), IOBDFRU, inst);
-	if (topo_fmri_str2nvl(thp, fmri_str, &fmri, &err) == 0) {
+	if (topo_mod_str2nvl(mp, fmri_str, &fmri) == 0) {
 		(void) topo_node_fru_set(ion, fmri, 0, &err);
 		nvlist_free(fmri);
 	}
@@ -213,28 +204,20 @@
 /*ARGSUSED*/
 static int
 opl_iob_enum(topo_mod_t *mp, tnode_t *parent, const char *name,
-    topo_instance_t imin, topo_instance_t imax, void *notused)
+    topo_instance_t imin, topo_instance_t imax, void *notused1, void *notused2)
 {
+	di_node_t opl_devtree;
 	di_node_t pnode;
 	tnode_t *ion;
 	topo_instance_t inst;
 	int lsb_to_psb[OPL_IOB_MAX];
 	ioboard_contents_t ioboard_list[OPL_IOB_MAX];
 	int retval = 0;
-	di_prom_handle_t opl_promtree = DI_PROM_HANDLE_NIL;
-	di_node_t opl_devtree;
 
 	/* Validate the name is correct */
 	if (strcmp(name, "ioboard") != 0) {
 		return (-1);
 	}
-	/* Initialize devinfo once for the module */
-	if ((opl_promtree = di_prom_init()) == DI_PROM_HANDLE_NIL) {
-		(void) topo_mod_seterrno(mp, errno);
-		topo_mod_dprintf(mp,
-		    "Ioboard enumerator: di_prom_handle_init failed.\n");
-		return (-1);
-	}
 	/* Make sure we don't exceed OPL_IOB_MAX */
 	if (imax >= OPL_IOB_MAX) {
 		imax = OPL_IOB_MAX;
@@ -242,7 +225,7 @@
 
 	bzero(ioboard_list, sizeof (ioboard_list));
 
-	opl_devtree = di_init("/", DINFOCPYALL);
+	opl_devtree = topo_mod_devinfo(mp);
 	if (opl_devtree == DI_NODE_NIL) {
 		(void) topo_mod_seterrno(mp, errno);
 		topo_mod_dprintf(mp, "devinfo init failed.\n");
@@ -254,7 +237,7 @@
 	 * the device node bus address) to physical board numbers, so we
 	 * can create meaningful fru labels.
 	 */
-	opl_map_boards(lsb_to_psb, opl_devtree, opl_promtree);
+	opl_map_boards(mp, opl_devtree, lsb_to_psb);
 
 	/*
 	 * Figure out which boards are installed by finding hostbridges
@@ -299,10 +282,7 @@
 			break;
 		}
 		/* Enumerate hostbridges on this ioboard, sets errno */
-		retval = opl_hb_enum(mp, &ioboard_list[inst], ion, inst,
-		    opl_promtree);
+		retval = opl_hb_enum(mp, &ioboard_list[inst], ion, inst);
 	}
-	di_fini(opl_devtree);
-	di_prom_fini(opl_promtree);
 	return (retval);
 }
--- a/usr/src/lib/fm/topo/modules/SUNW,SPARC-Enterprise/ioboard/opl_topo.h	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/SUNW,SPARC-Enterprise/ioboard/opl_topo.h	Sat Nov 04 01:18:55 2006 -0800
@@ -29,19 +29,14 @@
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
+#include <fm/topo_hc.h>
+#include <fm/topo_mod.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-/*
- * OPL-specific enumerators.
- */
-#define	IOBOARD		"ioboard"
-#define	HOSTBRIDGE	"hostbridge"
-#define	PCIEXRC		"pciexrc"
-#define	PCI_BUS		"pcibus"
-#define	PCIEX_BUS	"pciexbus"
-#define	PCI_MOD_PATH	"/usr/platform/sun4u/lib/fm/topo/plugins/pcibus.so"
+#define	PCI_BUS_VERS	1
 
 /*
  * OPL uses the Jupiter Bus Bindings (see FWARC/2005/076) which specifies
@@ -88,7 +83,7 @@
 
 /* Shared device tree root node */
 int opl_hb_enum(topo_mod_t *mp, const ioboard_contents_t *iob,
-    tnode_t *parent, int brd, di_prom_handle_t opl_promtree);
+    tnode_t *parent, int brd);
 
 #ifdef __cplusplus
 }
--- a/usr/src/lib/fm/topo/modules/SUNW,Sun-Fire-15000/ioboard/iob_platform.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/SUNW,Sun-Fire-15000/ioboard/iob_platform.c	Sat Nov 04 01:18:55 2006 -0800
@@ -33,16 +33,17 @@
 #include <string.h>
 #include <libdevinfo.h>
 #include <fm/topo_mod.h>
+#include <fm/topo_hc.h>
 
-#include "did.h"
-#include "hostbridge.h"
-#include "ioboard.h"
-#include "util.h"
+#include <did.h>
+#include <hostbridge.h>
+#include <ioboard.h>
+#include <util.h>
 
 /*ARGSUSED*/
 int
-platform_iob_label(tnode_t *node, nvlist_t *ignored, nvlist_t **out,
-    topo_mod_t *mod)
+platform_iob_label(topo_mod_t *mod, tnode_t *node, nvlist_t *ignored,
+    nvlist_t **out)
 {
 	/*
 	 * For E15K, the label is simply IOXX where XX is the
@@ -65,8 +66,8 @@
 
 /*ARGSUSED*/
 int
-platform_iob_enum(tnode_t *parent, topo_instance_t imin, topo_instance_t imax,
-    did_hash_t *didhash, di_prom_handle_t promtree, topo_mod_t *mod)
+platform_iob_enum(topo_mod_t *mod, tnode_t *parent, topo_instance_t imin,
+    topo_instance_t imax)
 {
 	/*
 	 * An E15K and its successors may have up to 18 I/O boards,
@@ -83,7 +84,7 @@
 	did_t *iobs[18][2][2];
 	int brd, br, bus, i;
 
-	devtree = di_init("/", DINFOCPYALL);
+	devtree = topo_mod_devinfo(mod);
 	if (devtree == DI_NODE_NIL) {
 		topo_mod_dprintf(mod, "devinfo init failed.");
 		return (-1);
@@ -98,9 +99,8 @@
 	while (pnode != DI_NODE_NIL) {
 		did_t *d;
 
-		d = split_bus_address(didhash,
-		    pnode, IOB_BASEADDR, BUS_ADDRDIST, 0, 17, &brd, &br, &bus,
-		    promtree, mod);
+		d = split_bus_address(mod,
+		    pnode, IOB_BASEADDR, BUS_ADDRDIST, 0, 17, &brd, &br, &bus);
 		if (d == NULL) {
 			pnode = di_drv_next_node(pnode);
 			continue;
@@ -120,27 +120,26 @@
 		did_did_link_set(iobs[i][0][0], iobs[i][0][1]);
 		did_did_link_set(iobs[i][1][0], iobs[i][1][1]);
 		did_did_chain_set(iobs[i][0][0], iobs[i][1][0]);
-		if ((ion = ioboard_declare(parent, i, iobs[i][0][0],
-		    promtree, mod)) == NULL) {
+		if ((ion = ioboard_declare(mod, parent, i, iobs[i][0][0]))
+		    == NULL) {
 			topo_mod_dprintf(mod,
 			    "Creation of tnode for %s%d failed.\n", IOBOARD, i);
 			continue;
 		}
-		if (topo_mod_enumerate(mod,
-		    ion, HOSTBRIDGE, HOSTBRIDGE, 0, 0) < 0) {
+		if (topo_mod_enumerate(mod, ion, HOSTBRIDGE, HOSTBRIDGE, 0, 0,
+		    iobs[i][0][0]) < 0) {
 			topo_mod_dprintf(mod,
 			    "Enumeration of %s%d/%s%d failed.\n",
 			    IOBOARD, i, HOSTBRIDGE, 0);
 			continue;
 		}
-		if (topo_mod_enumerate(mod,
-		    ion, HOSTBRIDGE, HOSTBRIDGE, 1, 1) < 0) {
+		if (topo_mod_enumerate(mod, ion, HOSTBRIDGE, HOSTBRIDGE, 1, 1,
+		    iobs[i][0][0]) < 0) {
 			topo_mod_dprintf(mod,
 			    "Enumeration of %s%d/%s%d failed.\n",
 			    IOBOARD, i, HOSTBRIDGE, 1);
 			continue;
 		}
 	}
-	di_fini(devtree);
 	return (0);
 }
--- a/usr/src/lib/fm/topo/modules/SUNW,Sun-Fire/ioboard/iob_platform.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/SUNW,Sun-Fire/ioboard/iob_platform.c	Sat Nov 04 01:18:55 2006 -0800
@@ -33,16 +33,17 @@
 #include <string.h>
 #include <libdevinfo.h>
 #include <fm/topo_mod.h>
+#include <fm/topo_hc.h>
 
-#include "did.h"
-#include "hostbridge.h"
-#include "ioboard.h"
-#include "util.h"
+#include <did.h>
+#include <hostbridge.h>
+#include <ioboard.h>
+#include <util.h>
 
 /*ARGSUSED*/
 int
-platform_iob_label(tnode_t *node, nvlist_t *ignored, nvlist_t **out,
-    topo_mod_t *mod)
+platform_iob_label(topo_mod_t *mod, tnode_t *node, nvlist_t *ignored,
+    nvlist_t **out)
 {
 	/*
 	 * For SUNW,Sun-Fire the label is simply N0.IBXX where XX is the
@@ -65,8 +66,8 @@
 
 /*ARGSUSED*/
 int
-platform_iob_enum(tnode_t *parent, topo_instance_t imin, topo_instance_t imax,
-    did_hash_t *didhash, di_prom_handle_t promtree, topo_mod_t *mod)
+platform_iob_enum(topo_mod_t *mod, tnode_t *parent, topo_instance_t imin,
+    topo_instance_t imax)
 {
 	/*
 	 * A SUNW,Sun-Fire and its successors may have up to 4 I/O boards,
@@ -83,7 +84,7 @@
 	did_t *iobs[18][2][2];
 	int brd, br, bus, i;
 
-	devtree = di_init("/", DINFOCPYALL);
+	devtree = topo_mod_devinfo(mod);
 	if (devtree == DI_NODE_NIL) {
 		topo_mod_dprintf(mod, "devinfo init failed.");
 		return (-1);
@@ -98,9 +99,8 @@
 	while (pnode != DI_NODE_NIL) {
 		did_t *d;
 
-		d = split_bus_address(didhash,
-		    pnode, IOB_BASEADDR, BUS_ADDRDIST, 6, 9, &brd, &br, &bus,
-		    promtree, mod);
+		d = split_bus_address(mod,
+		    pnode, IOB_BASEADDR, BUS_ADDRDIST, 6, 9, &brd, &br, &bus);
 		if (d == NULL) {
 			pnode = di_drv_next_node(pnode);
 			continue;
@@ -120,27 +120,26 @@
 		did_did_link_set(iobs[i][0][0], iobs[i][0][1]);
 		did_did_link_set(iobs[i][1][0], iobs[i][1][1]);
 		did_did_chain_set(iobs[i][0][0], iobs[i][1][0]);
-		if ((ion = ioboard_declare(parent, i, iobs[i][0][0],
-		    promtree, mod)) == NULL) {
+		if ((ion = ioboard_declare(mod, parent, i, iobs[i][0][0]))
+		    == NULL) {
 			topo_mod_dprintf(mod,
 			    "Creation of tnode for %s%d failed.\n", IOBOARD, i);
 			continue;
 		}
 		if (topo_mod_enumerate(mod,
-		    ion, HOSTBRIDGE, HOSTBRIDGE, 0, 0) < 0) {
+		    ion, HOSTBRIDGE, HOSTBRIDGE, 0, 0, iobs[i][0][0]) < 0) {
 			topo_mod_dprintf(mod,
 			    "Enumeration of %s%d/%s%d failed.\n",
 			    IOBOARD, i, HOSTBRIDGE, 0);
 			continue;
 		}
 		if (topo_mod_enumerate(mod,
-		    ion, HOSTBRIDGE, HOSTBRIDGE, 1, 1) < 0) {
+		    ion, HOSTBRIDGE, HOSTBRIDGE, 1, 1, iobs[i][0][0]) < 0) {
 			topo_mod_dprintf(mod,
 			    "Enumeration of %s%d/%s%d failed.\n",
 			    IOBOARD, i, HOSTBRIDGE, 1);
 			continue;
 		}
 	}
-	di_fini(devtree);
 	return (0);
 }
--- a/usr/src/lib/fm/topo/modules/common/did.c	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,554 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-/*
- * did.c
- *	The acronym did means "Dev-Info-Data".  Many properties and
- *	characteristics of topology nodes are, with a bit of coaxing
- *	derived from devinfo nodes.  These routines do some of the
- *	derivation and also encapsulate the discoveries in did_t
- *	structures that get associated with topology nodes as their
- *	"private" data.
- */
-#include <alloca.h>
-#include <assert.h>
-#include <string.h>
-#include <strings.h>
-#include <sys/types.h>
-#include <libtopo.h>
-#include <libnvpair.h>
-#include <libdevinfo.h>
-#include <sys/pcie.h>
-
-#include "topo_mod.h"
-#include "hostbridge.h"
-#include "pcibus.h"
-#include "did_impl.h"
-#include "did_props.h"
-
-static void slotnm_destroy(slotnm_t *);
-
-static slotnm_t *
-slotnm_create(topo_mod_t *mp, int dev, char *str)
-{
-	slotnm_t *p;
-
-	if ((p = topo_mod_alloc(mp, sizeof (slotnm_t))) == NULL)
-		return (NULL);
-	p->snm_mod = mp;
-	p->snm_next = NULL;
-	p->snm_dev = dev;
-	p->snm_label = topo_mod_strdup(mp, str);
-	if (p->snm_label == NULL) {
-		slotnm_destroy(p);
-		return (NULL);
-	}
-	return (p);
-}
-
-static void
-slotnm_destroy(slotnm_t *p)
-{
-	if (p == NULL)
-		return;
-	slotnm_destroy(p->snm_next);
-	if (p->snm_label != NULL)
-		topo_mod_strfree(p->snm_mod, p->snm_label);
-	topo_mod_free(p->snm_mod, p, sizeof (slotnm_t));
-}
-
-static int
-slotnm_cp(did_t *from, did_t *to, int *nslots)
-{
-	slotnm_t *nxt, *new;
-	slotnm_t *last = NULL;
-
-	*nslots = 0;
-	for (nxt = from->dp_slotnames; nxt != NULL; nxt = nxt->snm_next) {
-		new = slotnm_create(to->dp_mod, nxt->snm_dev, nxt->snm_label);
-		if (new == NULL) {
-			if (to->dp_slotnames != NULL)
-				slotnm_destroy(to->dp_slotnames);
-			to->dp_slotnames = NULL;
-			*nslots = 0;
-			return (-1);
-		}
-		if (last == NULL) {
-			to->dp_slotnames = last = new;
-		} else {
-			last->snm_next = new;
-			last = new;
-		}
-		(*nslots)++;
-	}
-	if (*nslots > 0)
-		topo_mod_dprintf(to->dp_mod,
-		    "%p inherits %d slot label(s) from %p.\n",
-		    to, *nslots, from);
-	return (0);
-}
-
-static int
-di_physlotinfo_get(topo_mod_t *mp, di_node_t src, uint_t excap,
-    int *slotnum, char **slotnm, di_prom_handle_t promtree)
-{
-	char *slotbuf;
-	int sz;
-	uchar_t *buf;
-
-	*slotnum = -1;
-	(void) di_uintprop_get(src, DI_PHYSPROP, (uint_t *)slotnum,
-	    promtree);
-	/*
-	 * If no physical slot number property was found, then the
-	 * capabilities register may indicate the pci-express device
-	 * implements a slot, and we should record which slot.
-	 */
-	if (*slotnum == -1 && (excap & PCIE_PCIECAP_SLOT_IMPL) != 0) {
-		uint_t slotcap;
-		int e;
-		e = di_uintprop_get(src, "pcie-slotcap-reg", &slotcap,
-		    promtree);
-		if (e == 0)
-			*slotnum = slotcap >> PCIE_SLOTCAP_PHY_SLOT_NUM_SHIFT;
-	}
-	if (*slotnum == -1)
-		return (0);
-
-	/*
-	 * For PCI-Express, there is only one downstream device, so check for
-	 * a slot-names property, and if it exists, ignore the slotmask value
-	 * and use the string as the label.
-	 */
-	if (di_bytes_get(src, DI_SLOTPROP, &sz, &buf, promtree) == 0 &&
-	    sz > 4) {
-		slotbuf = (char *)&buf[4];
-	} else {
-		/*
-		 * Make generic description string "SLOT <num>", allow up to
-		 * 10 digits for number
-		 */
-		slotbuf = alloca(16);
-		(void) snprintf(slotbuf, 16, "SLOT %d", *slotnum);
-	}
-	if ((*slotnm = topo_mod_strdup(mp, slotbuf)) == NULL)
-		return (-1);
-
-	return (0);
-}
-
-static int
-di_slotinfo_get(topo_mod_t *mp, di_node_t src, int *nslots, slotnm_t **slots,
-    di_prom_handle_t promtree)
-{
-	slotnm_t *lastslot = NULL;
-	slotnm_t *newslot;
-	uchar_t *slotbuf;
-	uint_t slotmap = 0;
-	char *slotname;
-	int andbit;
-	int sz = -1;
-
-	*slots = NULL;
-	*nslots = 0;
-	if (di_bytes_get(src, DI_SLOTPROP, &sz, &slotbuf, promtree) < 0)
-		return (0);
-	if (sz < sizeof (uint_t))
-		return (0);
-	bcopy(slotbuf, &slotmap, sizeof (uint_t));
-	if (slotmap == 0)
-		return (0);
-
-	slotname = (char *)&slotbuf[4];
-	for (andbit = 0; andbit < 32; andbit++) {
-		if (slotmap & (1 << andbit)) {
-			char *s = slotname;
-			slotname += strlen(s) + 1;
-			if ((newslot = slotnm_create(mp, andbit, s)) == NULL) {
-				slotnm_destroy(*slots);
-				*slots = NULL;
-				*nslots = 0;
-				return (-1);
-			}
-			if (lastslot == NULL)
-				*slots = lastslot = newslot;
-			else {
-				lastslot->snm_next = newslot;
-				lastslot = newslot;
-			}
-			(*nslots)++;
-		}
-	}
-	return (0);
-}
-
-int
-did_physslot(did_t *did)
-{
-	assert(did != NULL);
-	return (did->dp_physlot);
-}
-
-
-did_hash_t *
-did_hash(did_t *did)
-{
-	assert(did != NULL);
-	return (did->dp_hash);
-}
-
-did_t *
-did_create(did_hash_t *dhash, di_node_t src,
-    int ibrd, int ibrdge, int irc, int ibus, di_prom_handle_t promtree)
-{
-	topo_mod_t *mp;
-	did_t *np;
-	did_t *pd;
-	uint_t code;
-	uint_t reg;
-
-	mp = dhash->dph_mod;
-	if ((pd = did_hash_lookup(dhash, src)) != NULL) {
-		topo_mod_dprintf(mp, "Attempt to create existing did_t.\n");
-		assert(ibus == TRUST_BDF || (pd->dp_bus == ibus));
-		return (pd);
-	}
-
-	if ((np = topo_mod_zalloc(mp, sizeof (did_t))) == NULL)
-		return (NULL);
-	np->dp_mod = mp;
-	np->dp_src = src;
-	np->dp_hash = dhash;
-
-	/*
-	 * We must have a reg prop and from it we extract the bus #,
-	 * device #, and function #.
-	 */
-	if (di_uintprop_get(src, DI_REGPROP, &reg, promtree) < 0) {
-		topo_mod_free(mp, np, sizeof (did_t));
-		return (NULL);
-	}
-	np->dp_board = ibrd;
-	np->dp_bridge = ibrdge;
-	np->dp_rc = irc;
-	if (ibus == TRUST_BDF)
-		np->dp_bus = PCI_REG_BUS_G(reg);
-	else
-		np->dp_bus = ibus;
-	np->dp_dev = PCI_REG_DEV_G(reg);
-	np->dp_fn = PCI_REG_FUNC_G(reg);
-	np->dp_bdf = (PCI_REG_BUS_G(reg) << 8) | (PCI_REG_DEV_G(reg) << 3) |
-	    PCI_REG_FUNC_G(reg);
-	/*
-	 * There *may* be a class code we can capture.  If there wasn't
-	 * one, capture that fact by setting the class value to -1.
-	 */
-	if (di_uintprop_get(src, DI_CCPROP, &code, promtree) == 0) {
-		np->dp_class = GETCLASS(code);
-		np->dp_subclass = GETSUBCLASS(code);
-	} else {
-		np->dp_class = -1;
-	}
-	/*
-	 * There *may* be a PCI-express capabilities register we can capture.
-	 * If there wasn't one, the capabilities will be the out-of-bounds
-	 * value of zero.
-	 */
-	(void) di_uintprop_get(src, "pcie-capid-reg", &np->dp_excap,
-	    promtree);
-	/*
-	 * There *may* be a physical slot number property we can capture.
-	 */
-	if (di_physlotinfo_get(mp,
-	    src, np->dp_excap, &np->dp_physlot, &np->dp_physlot_label,
-	    promtree) < 0) {
-		topo_mod_free(mp, np, sizeof (did_t));
-		return (NULL);
-	}
-	/*
-	 * There *may* be PCI slot info we can capture
-	 */
-	if (di_slotinfo_get(mp, src, &np->dp_nslots, &np->dp_slotnames,
-	    promtree) < 0) {
-		if (np->dp_physlot_label != NULL)
-			topo_mod_strfree(mp, np->dp_physlot_label);
-		topo_mod_free(mp, np, sizeof (did_t));
-		return (NULL);
-	}
-	did_hash_insert(dhash, src, np);
-	did_hold(np);
-	return (np);
-}
-
-did_t *
-did_link_get(did_t *dp)
-{
-	assert(dp != NULL);
-	return (dp->dp_link);
-}
-
-did_t *
-did_chain_get(did_t *dp)
-{
-	assert(dp != NULL);
-	return (dp->dp_chain);
-}
-
-void
-did_link_set(tnode_t *head, did_t *tail)
-{
-	did_t *hd, *pd;
-
-	assert(head != NULL);
-	pd = hd = topo_node_private(head);
-	assert(hd != NULL);
-	while ((hd = did_link_get(hd)) != NULL)
-		pd = hd;
-	pd->dp_link = tail;
-	tail->dp_link = NULL;
-}
-
-void
-did_did_link_set(did_t *from, did_t *to)
-{
-	assert(from != NULL && to != NULL);
-	from->dp_link = to;
-}
-
-void
-did_did_chain_set(did_t *from, did_t *to)
-{
-	assert(from != NULL && to != NULL);
-	from->dp_chain = to;
-}
-
-void
-did_destroy(did_t *dp)
-{
-	assert(dp != NULL);
-
-	/*
-	 * did_destroy() is called only from did_hash_destroy() when
-	 * all references to the did_t have been released.  We can
-	 * safely destroy the did_t.  If at some later time, more
-	 * fine-grained reference count control is desired, this
-	 * code will need to change
-	 */
-
-	if (dp->dp_physlot_label != NULL)
-		topo_mod_strfree(dp->dp_mod, dp->dp_physlot_label);
-	slotnm_destroy(dp->dp_slotnames);
-	topo_mod_free(dp->dp_mod, dp, sizeof (did_t));
-}
-
-void
-did_hold(did_t *dp)
-{
-	assert(dp != NULL);
-	dp->dp_refcnt++;
-}
-
-void
-did_rele(did_t *dp)
-{
-	assert(dp != NULL);
-	assert(dp->dp_refcnt > 0);
-	dp->dp_refcnt--;
-}
-
-di_node_t
-did_dinode(did_t *dp)
-{
-	assert(dp != NULL);
-	assert(dp->dp_src != NULL);
-	return (dp->dp_src);
-}
-
-topo_mod_t *
-did_mod(did_t *dp)
-{
-	assert(dp != NULL);
-	return (dp->dp_mod);
-}
-
-void
-did_markrc(did_t *dp)
-{
-	assert(dp != NULL);
-	dp->dp_excap |= PCIE_PCIECAP_DEV_TYPE_ROOT;
-}
-
-void
-did_BDF(did_t *dp, int *bus, int *dev, int *fn)
-{
-	assert(dp != NULL);
-	if (bus != NULL)
-		*bus = dp->dp_bus;
-	if (dev != NULL)
-		*dev = dp->dp_dev;
-	if (fn != NULL)
-		*fn = dp->dp_fn;
-}
-
-int
-did_board(did_t *did)
-{
-	assert(did != NULL);
-	return (did->dp_board);
-}
-
-int
-did_bridge(did_t *did)
-{
-	assert(did != NULL);
-	return (did->dp_bridge);
-}
-
-int
-did_rc(did_t *did)
-{
-	assert(did != NULL);
-	return (did->dp_rc);
-}
-
-static int
-did_numlabels(did_t *dp)
-{
-	assert(dp != NULL);
-	return (dp->dp_nslots);
-}
-
-int
-did_excap(did_t *dp)
-{
-	assert(dp != NULL);
-	return ((int)dp->dp_excap);
-}
-
-int
-did_bdf(did_t *dp)
-{
-	assert(dp != NULL);
-	return ((int)dp->dp_bdf);
-}
-
-const char *
-did_label(did_t *dp, int dev)
-{
-	slotnm_t *slot;
-
-	assert(dp != NULL);
-	if (dp->dp_physlot_label != NULL)
-		return (dp->dp_physlot_label);
-	for (slot = dp->dp_slotnames; slot != NULL; slot = slot->snm_next)
-		if (slot->snm_dev == dev)
-			break;
-	if (slot != NULL)
-		return (slot->snm_label);
-	return (NULL);
-}
-
-did_t *
-did_find(did_hash_t *dhash, di_node_t dn)
-{
-	return (did_hash_lookup(dhash, dn));
-}
-
-int
-pci_BDF_get(did_hash_t *dhash, di_node_t dn, int *bus, int *dev, int *fn)
-{
-	did_t *dp;
-
-	if ((dp = did_find(dhash, dn)) == NULL)
-		return (-1);
-	*bus = dp->dp_bus;
-	*dev = dp->dp_dev;
-	*fn = dp->dp_fn;
-	did_rele(dp);
-	return (0);
-}
-
-int
-pci_classcode_get(did_hash_t *dhash,
-    di_node_t dn, uint_t *class, uint_t *sub)
-{
-	did_t *dp;
-
-	if ((dp = did_find(dhash, dn)) == NULL)
-		return (-1);
-	if (dp->dp_class < 0) {
-		did_rele(dp);
-		return (-1);
-	}
-	*class = dp->dp_class;
-	*sub = dp->dp_subclass;
-	did_rele(dp);
-	return (0);
-}
-
-int
-pciex_cap_get(did_hash_t *dhash, di_node_t dn)
-{
-	did_t *dp;
-
-	if ((dp = did_find(dhash, dn)) == NULL)
-		return (-1);
-	did_rele(dp);
-	return (dp->dp_excap);
-}
-
-int
-did_inherit(did_t *pdp, did_t *dp)
-{
-	/*
-	 * If the child already has a label, we're done.
-	 */
-	assert(dp != NULL);
-	if (did_numlabels(dp) > 0)
-		return (0);
-
-	assert(pdp != NULL);
-
-	/*
-	 * If the child and parent are the same, we're done.
-	 */
-	if (dp == pdp)
-		return (0);
-
-	if (pdp->dp_physlot_label != NULL) {
-		topo_mod_dprintf(dp->dp_mod,
-		    "%p inherits physlot label from %p.\n", dp, pdp);
-		dp->dp_physlot_label =
-		    topo_mod_strdup(dp->dp_mod, pdp->dp_physlot_label);
-		if (dp->dp_physlot_label == NULL)
-			return (-1);
-	}
-	if (slotnm_cp(pdp, dp, &dp->dp_nslots) < 0)
-		return (-1);
-	return (0);
-}
--- a/usr/src/lib/fm/topo/modules/common/did.h	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _DID_H
-#define	_DID_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <sys/pci.h>
-#include <fm/topo_mod.h>
-#include <libdevinfo.h>
-#include <libnvpair.h>
-#include "did_impl.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern topo_mod_t *did_mod(did_t *);
-extern di_node_t did_dinode(did_t *);
-extern void did_BDF(did_t *, int *, int *, int *);
-extern void did_markrc(did_t *);
-extern const char *did_label(did_t *, int);
-extern int did_board(did_t *);
-extern int did_bridge(did_t *);
-extern int did_rc(did_t *);
-extern int did_physslot(did_t *);
-extern int did_inherit(did_t *, did_t *);
-extern int did_excap(did_t *);
-extern int did_bdf(did_t *);
-
-extern did_t *did_create(did_hash_t *, di_node_t, int, int, int, int,
-    di_prom_handle_t);
-extern did_t *did_find(did_hash_t *, di_node_t);
-extern did_t *did_link_get(did_t *);
-extern did_t *did_chain_get(did_t *);
-extern void did_destroy(did_t *);
-extern did_hash_t *did_hash(did_t *);
-extern void did_hash_fini(did_hash_t *);
-extern void did_hold(did_t *);
-extern void did_link_set(tnode_t *, did_t *);
-extern void did_did_link_set(did_t *, did_t *);
-extern void did_did_chain_set(did_t *, did_t *);
-extern void did_rele(did_t *);
-extern did_hash_t *did_hash_init(topo_mod_t *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _DID_H */
--- a/usr/src/lib/fm/topo/modules/common/did_hash.c	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,156 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <libdevinfo.h>
-#include <topo_mod.h>
-
-#include "pcibus.h"
-#include "did_impl.h"
-#include "did_props.h"
-
-did_hash_t *
-did_hash_init(topo_mod_t *hdl)
-{
-	return (did_hash_create(hdl));
-}
-
-void
-did_hash_fini(did_hash_t *dh)
-{
-	if (dh == NULL)
-		return;
-	did_hash_destroy(dh);
-}
-
-static uint64_t
-did_dnhash(di_node_t key)
-{
-	static uint64_t key_divisor = 0;
-	uint64_t keyn;
-
-	/*
-	 * A bit naughty here, we're aware that a di_info_t is a
-	 * pointer to a struct.  For our hashing, we want use the size
-	 * of that struct, which we determine here, somewhat
-	 * impolitely.
-	 */
-	if (key_divisor == 0)
-		key_divisor = sizeof (*key);
-
-	keyn = (uintptr_t)key;
-
-	return (keyn / key_divisor);
-}
-
-did_hash_t *
-did_hash_create(topo_mod_t *hdl)
-{
-	did_hash_t *r = topo_mod_zalloc(hdl, sizeof (did_hash_t));
-
-	if (r == NULL) {
-		(void) topo_mod_seterrno(hdl, EMOD_NOMEM);
-		return (NULL);
-	}
-	r->dph_mod = hdl;
-	r->dph_hashlen = REC_HASHLEN;
-	r->dph_hash = topo_mod_zalloc(hdl,
-	    r->dph_hashlen * sizeof (did_t *));
-	if (r->dph_hash == NULL) {
-		topo_mod_free(hdl, r, sizeof (did_hash_t));
-		(void) topo_mod_seterrno(hdl, EMOD_NOMEM);
-		return (NULL);
-	}
-	return (r);
-}
-
-void
-did_hash_destroy(did_hash_t *ht)
-{
-	did_t *e, *n;
-	int idx;
-
-	if (ht == NULL)
-		return;
-	for (idx = 0; idx < ht->dph_hashlen; idx++) {
-		for (e = ht->dph_hash[idx]; e != NULL; ) {
-			n = e->dp_next;
-			did_destroy(e);
-			e = n;
-		}
-	}
-	topo_mod_free(ht->dph_mod,
-	    ht->dph_hash, ht->dph_hashlen * sizeof (did_t *));
-	topo_mod_free(ht->dph_mod, ht, sizeof (did_hash_t));
-}
-
-void
-did_hash_insert(did_hash_t *tab, di_node_t key, did_t *new)
-{
-	did_t *assertchk;
-	int idx = did_dnhash(key) % tab->dph_hashlen;
-
-	tab->dph_nelems++;
-	did_hold(new);
-	topo_mod_dprintf(tab->dph_mod, "Insert [key=%p] into %p, bucket %d\n",
-	    key, (void *)tab, idx);
-	if (tab->dph_hash[idx] == NULL) {
-		tab->dph_hash[idx] = new;
-		topo_mod_dprintf(tab->dph_mod, "first entry.\n");
-	} else {
-		/*
-		 * We should not be putting in a duplicate entry
-		 */
-		for (assertchk = tab->dph_hash[idx];
-		    assertchk != NULL;
-		    assertchk = assertchk->dp_next)
-			assert(assertchk->dp_src != key);
-		new->dp_next = tab->dph_hash[idx];
-		tab->dph_hash[idx] = new;
-	}
-}
-
-did_t *
-did_hash_lookup(did_hash_t *tab, di_node_t key)
-{
-	did_t *e;
-	int idx = did_dnhash(key) % tab->dph_hashlen;
-
-	e = tab->dph_hash[idx];
-	while (e != NULL) {
-		if (e->dp_src == key) {
-			did_hold(e);
-			return (e);
-		}
-		e = e->dp_next;
-	}
-	return (NULL);
-}
--- a/usr/src/lib/fm/topo/modules/common/did_impl.h	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _DID_IMPL_H
-#define	_DID_IMPL_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <sys/pci.h>
-#include <fm/libtopo.h>
-#include <libdevinfo.h>
-#include <libnvpair.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define	REC_HASHLEN	253
-
-struct did_hash;
-
-/*
- * Slot name info is attached to devinfo nodes, compressed inside of
- * a "slot-names" property.  When we dig this out we store each name
- * as an FMRI, along with the device number to which it applies.
- */
-typedef struct slotnm {
-	topo_mod_t *snm_mod;	/* module that allocated the slot name */
-	struct slotnm *snm_next;
-	int snm_dev;	 /* device on the bus that implements the slot */
-	char *snm_label; /* label describing the slot */
-} slotnm_t;
-
-/*
- * Private data stored with a tnode_t.  We collect slot-name info from
- * di_nodes that describe buses, but then don't use it until we get to
- * a tnode_t actually describing a function of a device.  We also use
- * this struct to pass around bus, dev, function info so that doesn't
- * have to be re-computed.
- */
-typedef struct did {
-	struct did *dp_next; /* for chaining in a hash bucket */
-	struct did *dp_link; /* for chaining to related did_t */
-	struct did *dp_chain; /* for chaining to another chain of did_ts */
-	struct did_hash *dp_hash; /* the hash table where we reside */
-	topo_mod_t *dp_mod; /* module that allocated the did private data */
-	di_node_t dp_src; /* di_node_t from which the info was derived */
-	int dp_refcnt;	/* multiple nodes allowed to point at a did_t */
-	uint_t dp_excap;	/* PCI-Express capabilities */
-	int dp_physlot;		/* PCI-Express physical slot # */
-	char *dp_physlot_label; /* PCI-Express slot implemented */
-	int dp_class;		/* PCI class */
-	int dp_subclass;	/* PCI subclass */
-	int dp_board;		/* Board number */
-	int dp_bridge;		/* Bridge number */
-	int dp_rc;		/* Root Complex number */
-	int dp_bus;		/* PCI bus number */
-	int dp_dev;		/* PCI device number on the above bus */
-	int dp_fn;		/* PCI function number of the above device */
-	int dp_bdf;		/* PCI "real" bdf */
-	/*
-	 * There may be some slot name info on devinfo node for a bus or
-	 * hostbridge.  We'll copy or reference it for child nodes of that
-	 * bus or hostbridge.
-	 */
-	int dp_nslots;		/* number of slots actually described */
-	slotnm_t *dp_slotnames; /* the slot names as labels */
-} did_t;
-
-typedef struct did_hash {
-	did_t **dph_hash;	/* hash bucket array */
-	uint_t dph_hashlen;	/* size of hash bucket array */
-	uint_t dph_nelems;	/* number of elements in the hash */
-	topo_mod_t *dph_mod;	/* module that allocated the hash table */
-} did_hash_t;
-
-extern did_hash_t *did_hash_create(topo_mod_t *);
-extern did_t *did_hash_lookup(did_hash_t *, di_node_t);
-extern void did_hash_destroy(did_hash_t *);
-extern void did_hash_insert(did_hash_t *, di_node_t, did_t *);
-
-extern did_t *did_create(did_hash_t *, di_node_t, int, int, int, int,
-    di_prom_handle_t);
-extern void did_destroy(did_t *);
-extern void did_hold(did_t *);
-extern void did_rele(did_t *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _DID_IMPL_H */
--- a/usr/src/lib/fm/topo/modules/common/did_props.c	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,758 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <assert.h>
-#include <alloca.h>
-#include <string.h>
-#include <strings.h>
-#include <limits.h>
-#include <sys/types.h>
-#include <sys/pci.h>
-#include <sys/pcie.h>
-#include <sys/fm/protocol.h>
-#include <fm/topo_mod.h>
-#include <libdevinfo.h>
-#include <topo_error.h>
-
-#include "hostbridge.h"
-#include "pcibus.h"
-#include "did.h"
-#include "did_props.h"
-
-static int ASRU_set(tnode_t *, did_t *,
-    const char *, const char *, const char *, di_prom_handle_t);
-static int FRU_set(tnode_t *, did_t *,
-    const char *, const char *, const char *, di_prom_handle_t);
-static int DEVprop_set(tnode_t *, did_t *,
-    const char *, const char *, const char *, di_prom_handle_t);
-static int DRIVERprop_set(tnode_t *, did_t *,
-    const char *, const char *, const char *, di_prom_handle_t);
-static int EXCAP_set(tnode_t *, did_t *,
-    const char *, const char *, const char *, di_prom_handle_t);
-static int BDF_set(tnode_t *, did_t *,
-    const char *, const char *, const char *, di_prom_handle_t);
-static int label_set(tnode_t *, did_t *,
-    const char *, const char *, const char *, di_prom_handle_t);
-static int maybe_di_chars_copy(tnode_t *, did_t *,
-    const char *, const char *, const char *, di_prom_handle_t);
-static int maybe_di_uint_to_str(tnode_t *, did_t *,
-    const char *, const char *, const char *, di_prom_handle_t);
-
-/*
- * Arrays of "property translation routines" to set the properties a
- * given type of topology node should have.
- *
- * Note that the label_set translation *MUST COME BEFORE* the FRU
- * translation.  For the near term we're setting the FRU fmri to
- * be a legacy-hc style FMRI based on the label, so the label needs
- * to have been set before we do the FRU translation.
- *
- */
-
-txprop_t Fn_common_props[] = {
-	{ NULL, TOPO_PGROUP_IO, TOPO_PROP_DEV,
-	    TOPO_STABILITY_PRIVATE, DEVprop_set },
-	{ DI_DEVTYPPROP, TOPO_PGROUP_IO, TOPO_PROP_DEVTYPE,
-	    TOPO_STABILITY_PRIVATE, maybe_di_chars_copy },
-	{ DI_DEVIDPROP, TOPO_PGROUP_PCI, TOPO_PROP_DEVID,
-	    TOPO_STABILITY_PRIVATE, maybe_di_uint_to_str },
-	{ NULL, TOPO_PGROUP_IO, TOPO_PROP_DRIVER,
-	    TOPO_STABILITY_PRIVATE, DRIVERprop_set },
-	{ NULL, TOPO_PGROUP_PCI, TOPO_PROP_EXCAP,
-	    TOPO_STABILITY_PRIVATE, EXCAP_set },
-	{ DI_CLASSPROP, TOPO_PGROUP_PCI, TOPO_PROP_CLASS,
-	    TOPO_STABILITY_PRIVATE, maybe_di_uint_to_str },
-	{ DI_VENDIDPROP, TOPO_PGROUP_PCI, TOPO_PROP_VENDID,
-	    TOPO_STABILITY_PRIVATE, maybe_di_uint_to_str },
-	{ NULL, TOPO_PGROUP_PROTOCOL, TOPO_PROP_LABEL,
-	    TOPO_STABILITY_PRIVATE, label_set },
-	{ NULL, TOPO_PGROUP_PROTOCOL, TOPO_PROP_FRU,
-	    TOPO_STABILITY_PRIVATE, FRU_set },
-	{ NULL, TOPO_PGROUP_PROTOCOL, TOPO_PROP_ASRU,
-	    TOPO_STABILITY_PRIVATE, ASRU_set }
-};
-
-txprop_t Dev_common_props[] = {
-	{ NULL, TOPO_PGROUP_PROTOCOL, TOPO_PROP_LABEL,
-	    TOPO_STABILITY_PRIVATE, label_set },
-	{ NULL, TOPO_PGROUP_PROTOCOL, TOPO_PROP_FRU,
-	    TOPO_STABILITY_PRIVATE, FRU_set },
-	{ NULL, TOPO_PGROUP_PROTOCOL, TOPO_PROP_ASRU,
-	    TOPO_STABILITY_PRIVATE, ASRU_set }
-};
-
-txprop_t Bus_common_props[] = {
-	{ DI_DEVTYPPROP, TOPO_PGROUP_IO, TOPO_PROP_DEVTYPE,
-	    TOPO_STABILITY_PRIVATE, maybe_di_chars_copy },
-	{ NULL, TOPO_PGROUP_IO, TOPO_PROP_DRIVER,
-	    TOPO_STABILITY_PRIVATE, DRIVERprop_set },
-	{ NULL, TOPO_PGROUP_PROTOCOL, TOPO_PROP_LABEL,
-	    TOPO_STABILITY_PRIVATE, label_set },
-	{ NULL, TOPO_PGROUP_PROTOCOL, TOPO_PROP_FRU,
-	    TOPO_STABILITY_PRIVATE, FRU_set },
-	{ NULL, TOPO_PGROUP_PROTOCOL, TOPO_PROP_ASRU,
-	    TOPO_STABILITY_PRIVATE, ASRU_set }
-};
-
-txprop_t RC_common_props[] = {
-	{ NULL, TOPO_PGROUP_IO, TOPO_PROP_DEV,
-	    TOPO_STABILITY_PRIVATE, DEVprop_set },
-	{ DI_DEVTYPPROP, TOPO_PGROUP_IO, TOPO_PROP_DEVTYPE,
-	    TOPO_STABILITY_PRIVATE, maybe_di_chars_copy },
-	{ NULL, TOPO_PGROUP_IO, TOPO_PROP_DRIVER,
-	    TOPO_STABILITY_PRIVATE, DRIVERprop_set },
-	{ NULL, TOPO_PGROUP_PCI, TOPO_PROP_EXCAP,
-	    TOPO_STABILITY_PRIVATE, EXCAP_set },
-	{ NULL, TOPO_PGROUP_PCI, TOPO_PROP_BDF,
-	    TOPO_STABILITY_PRIVATE, BDF_set },
-	{ NULL, TOPO_PGROUP_PROTOCOL, TOPO_PROP_LABEL,
-	    TOPO_STABILITY_PRIVATE, label_set },
-	{ NULL, TOPO_PGROUP_PROTOCOL, TOPO_PROP_FRU,
-	    TOPO_STABILITY_PRIVATE, FRU_set },
-	{ NULL, TOPO_PGROUP_PROTOCOL, TOPO_PROP_ASRU,
-	    TOPO_STABILITY_PRIVATE, ASRU_set }
-};
-
-txprop_t ExHB_common_props[] = {
-	{ NULL, TOPO_PGROUP_PROTOCOL, TOPO_PROP_LABEL,
-	    TOPO_STABILITY_PRIVATE, label_set },
-	{ NULL, TOPO_PGROUP_PROTOCOL, TOPO_PROP_FRU,
-	    TOPO_STABILITY_PRIVATE, FRU_set },
-	{ NULL, TOPO_PGROUP_PROTOCOL, TOPO_PROP_ASRU,
-	    TOPO_STABILITY_PRIVATE, ASRU_set }
-};
-
-txprop_t IOB_common_props[] = {
-	{ NULL, TOPO_PGROUP_PROTOCOL, TOPO_PROP_LABEL,
-	    TOPO_STABILITY_PRIVATE, label_set },
-	{ NULL, TOPO_PGROUP_PROTOCOL, TOPO_PROP_FRU,
-	    TOPO_STABILITY_PRIVATE, FRU_set },
-	{ NULL, TOPO_PGROUP_PROTOCOL, TOPO_PROP_ASRU,
-	    TOPO_STABILITY_PRIVATE, ASRU_set }
-};
-
-txprop_t HB_common_props[] = {
-	{ NULL, TOPO_PGROUP_IO, TOPO_PROP_DEV,
-	    TOPO_STABILITY_PRIVATE, DEVprop_set },
-	{ NULL, TOPO_PGROUP_IO, TOPO_PROP_DRIVER,
-	    TOPO_STABILITY_PRIVATE, DRIVERprop_set },
-	{ NULL, TOPO_PGROUP_PROTOCOL, TOPO_PROP_LABEL,
-	    TOPO_STABILITY_PRIVATE, label_set },
-	{ NULL, TOPO_PGROUP_PROTOCOL, TOPO_PROP_FRU,
-	    TOPO_STABILITY_PRIVATE, FRU_set },
-	{ NULL, TOPO_PGROUP_PROTOCOL, TOPO_PROP_ASRU,
-	    TOPO_STABILITY_PRIVATE, ASRU_set }
-};
-
-int Bus_propcnt = sizeof (Bus_common_props) / sizeof (txprop_t);
-int Dev_propcnt = sizeof (Dev_common_props) / sizeof (txprop_t);
-int ExHB_propcnt = sizeof (ExHB_common_props) / sizeof (txprop_t);
-int HB_propcnt = sizeof (HB_common_props) / sizeof (txprop_t);
-int IOB_propcnt = sizeof (IOB_common_props) / sizeof (txprop_t);
-int RC_propcnt = sizeof (RC_common_props) / sizeof (txprop_t);
-int Fn_propcnt = sizeof (Fn_common_props) / sizeof (txprop_t);
-
-/*
- * If this devinfo node came originally from OBP data, we'll have prom
- * properties associated with the node where we can find properties of
- * interest.  We ignore anything after the the first four bytes of the
- * property, and interpet those first four bytes as our unsigned
- * integer.  If we don't find the property or it's not large enough,
- * 'val' will remained unchanged and we'll return -1.  Otherwise 'val'
- * gets updated with the property value and we return 0.
- */
-static int
-promprop2uint(di_node_t n, const char *propnm, uint_t *val,
-    di_prom_handle_t promtree)
-{
-	di_prom_prop_t pp = DI_PROM_PROP_NIL;
-	uchar_t *buf;
-
-	while ((pp = di_prom_prop_next(promtree, n, pp)) != DI_PROM_PROP_NIL) {
-		if (strcmp(di_prom_prop_name(pp), propnm) == 0) {
-			if (di_prom_prop_data(pp, &buf) < sizeof (uint_t))
-				continue;
-			bcopy(buf, val, sizeof (uint_t));
-			return (0);
-		}
-	}
-	return (-1);
-}
-
-/*
- * If this devinfo node was added by the PCI hotplug framework it
- * doesn't have the PROM properties, but hopefully has the properties
- * we're looking for attached directly to the devinfo node.  We only
- * care about the first four bytes of the property, which we read as
- * our unsigned integer.  The remaining bytes are ignored.  If we
- * don't find the property we're looking for, or can't get its value,
- * 'val' remains unchanged and we return -1.  Otherwise 'val' gets the
- * property value and we return 0.
- */
-static int
-hwprop2uint(di_node_t n, const char *propnm, uint_t *val)
-{
-	di_prop_t hp = DI_PROP_NIL;
-	uchar_t *buf;
-
-	while ((hp = di_prop_next(n, hp)) != DI_PROP_NIL) {
-		if (strcmp(di_prop_name(hp), propnm) == 0) {
-			if (di_prop_bytes(hp, &buf) < sizeof (uint_t))
-				continue;
-			bcopy(buf, val, sizeof (uint_t));
-			return (0);
-		}
-	}
-	return (-1);
-}
-
-int
-di_uintprop_get(di_node_t n, const char *pnm, uint_t *pv,
-    di_prom_handle_t promtree)
-{
-	if (hwprop2uint(n, pnm, pv) < 0)
-		if (promprop2uint(n, pnm, pv, promtree) < 0)
-			return (-1);
-	return (0);
-}
-
-int
-di_bytes_get(di_node_t n, const char *pnm, int *sz, uchar_t **db,
-    di_prom_handle_t promtree)
-{
-	di_prom_prop_t pp = DI_PROM_PROP_NIL;
-	di_prop_t hp = DI_PROP_NIL;
-
-	*sz = -1;
-	while ((hp = di_prop_next(n, hp)) != DI_PROP_NIL) {
-		if (strcmp(di_prop_name(hp), pnm) == 0) {
-			if ((*sz = di_prop_bytes(hp, db)) < 0)
-				continue;
-			break;
-		}
-	}
-	if (*sz < 0) {
-		while ((pp = di_prom_prop_next(promtree, n, pp)) !=
-		    DI_PROM_PROP_NIL) {
-			if (strcmp(di_prom_prop_name(pp), pnm) == 0) {
-				*sz = di_prom_prop_data(pp, db);
-				if (*sz < 0)
-					continue;
-				break;
-			}
-		}
-	}
-	if (*sz < 0)
-		return (-1);
-	return (0);
-}
-
-/*
- * fix_dev_prop -- sometimes di_devfs_path() doesn't tell the whole
- * story, leaving off the device and function number.  Chances are if
- * devfs doesn't put these on then we'll never see this device as an
- * error detector called out in an ereport.  Unfortunately, there are
- * races and we sometimes do get ereports from devices that devfs
- * decides aren't there.  For example, the error injector card seems
- * to bounce in and out of existence according to devfs.  We tack on
- * the missing dev and fn here so that the DEV property used to look
- * up the topology node is correct.
- */
-static char *
-dev_path_fix(topo_mod_t *mp, char *path, int devno, int fnno)
-{
-	char *lastslash;
-	char *newpath;
-	int need;
-
-	/*
-	 * We only care about the last component of the dev path. If
-	 * we don't find a slash, something is weird.
-	 */
-	lastslash = strrchr(path, '/');
-	assert(lastslash != NULL);
-
-	/*
-	 * If an @ sign is present in the last component, the
-	 * di_devfs_path() result had the device,fn unit-address.
-	 * In that case there's nothing we need do.
-	 */
-	if (strchr(lastslash, '@') != NULL)
-		return (path);
-
-	if (fnno == 0)
-		need = snprintf(NULL, 0, "%s@%x", path, devno);
-	else
-		need = snprintf(NULL, 0, "%s@%x,%x", path, devno, fnno);
-	need++;
-
-	if ((newpath = topo_mod_alloc(mp, need)) == NULL) {
-		topo_mod_strfree(mp, path);
-		return (NULL);
-	}
-
-	if (fnno == 0)
-		(void) snprintf(newpath, need, "%s@%x", path, devno);
-	else
-		(void) snprintf(newpath, need, "%s@%x,%x", path, devno, fnno);
-
-	topo_mod_strfree(mp, path);
-	return (newpath);
-}
-
-/*
- * dev_for_hostbridge() -- For hostbridges we truncate the devfs path
- * after the first element in the bus address.
- */
-static char *
-dev_for_hostbridge(topo_mod_t *mp, char *path)
-{
-	char *lastslash;
-	char *newpath;
-	char *comma;
-
-	/*
-	 * We only care about the last component of the dev path. If
-	 * we don't find a slash, something is weird.
-	 */
-	lastslash = strrchr(path, '/');
-	assert(lastslash != NULL);
-
-	/*
-	 * Find the comma in the last component component@x,y, and
-	 * truncate the comma and any following number.
-	 */
-	comma = strchr(lastslash, ',');
-	assert(comma != NULL);
-
-	*comma = '\0';
-	if ((newpath = topo_mod_strdup(mp, path)) == NULL)
-		return (path);
-	*comma = ',';
-	topo_mod_strfree(mp, path);
-	return (newpath);
-}
-
-/*ARGSUSED*/
-static int
-ASRU_set(tnode_t *tn, did_t *pd,
-    const char *dpnm, const char *tpgrp, const char *tpnm,
-    di_prom_handle_t promtree)
-{
-	topo_mod_t *mp;
-	topo_hdl_t *hp;
-	nvlist_t *fmri, *in;
-	char *dnpath, *path, *fpath, *nm;
-	int d, e, f;
-
-	/*
-	 * If this topology node represents a function of device,
-	 * set the ASRU to a dev scheme FMRI based on the value of
-	 * di_devfs_path().  If that path is NULL, set the ASRU to
-	 * be the resource describing this topology node.  If this
-	 * isn't a function, inherit any ASRU from the parent.
-	 */
-	mp = did_mod(pd);
-	hp = topo_mod_handle(mp);
-	nm = topo_node_name(tn);
-	if (strcmp(nm, PCI_FUNCTION) == 0 || strcmp(nm, PCIEX_FUNCTION) == 0 ||
-	    strcmp(nm, PCIEX_ROOT) == 0) {
-		if ((dnpath = di_devfs_path(did_dinode(pd))) != NULL) {
-			/*
-			 * Dup the path, dev_path_fix() may replace it and
-			 * dev_path_fix() wouldn't know to use
-			 * di_devfs_path_free()
-			 */
-			if ((path = topo_mod_strdup(mp, dnpath)) == NULL) {
-				di_devfs_path_free(dnpath);
-				return (topo_mod_seterrno(mp, EMOD_NOMEM));
-			}
-			di_devfs_path_free(dnpath);
-			did_BDF(pd, NULL, &d, &f);
-			if ((fpath = dev_path_fix(mp, path, d, f)) == NULL)
-				return (topo_mod_seterrno(mp, EMOD_NOMEM));
-
-			if (topo_mod_nvalloc(mp, &in, NV_UNIQUE_NAME) != 0) {
-				topo_mod_strfree(mp, fpath);
-				return (topo_mod_seterrno(mp, EMOD_FMRI_NVL));
-			}
-			if (nvlist_add_string(in,
-			    FM_FMRI_DEV_PATH, fpath) != 0) {
-				nvlist_free(in);
-				topo_mod_strfree(mp, fpath);
-				return (topo_mod_seterrno(mp, EMOD_NOMEM));
-			}
-			fmri = topo_fmri_create(hp, FM_FMRI_SCHEME_DEV,
-			    FM_FMRI_SCHEME_DEV, 0, in, &e);
-			nvlist_free(in);
-			if (fmri == NULL) {
-				topo_mod_dprintf(mp,
-				    "dev:///%s fmri creation failed.\n", fpath);
-				topo_mod_strfree(mp, fpath);
-				return (topo_mod_seterrno(mp, e));
-			}
-			topo_mod_strfree(mp, fpath);
-		} else {
-			topo_mod_dprintf(mp, "NULL di_devfs_path.\n");
-			if (topo_prop_get_fmri(tn, TOPO_PGROUP_PROTOCOL,
-			    TOPO_PROP_RESOURCE, &fmri, &e) < 0)
-				return (topo_mod_seterrno(mp, e));
-		}
-		if (topo_node_asru_set(tn, fmri, 0, &e) < 0) {
-			nvlist_free(fmri);
-			return (topo_mod_seterrno(mp, e));
-		}
-		nvlist_free(fmri);
-		return (0);
-	}
-	if (topo_node_asru_set(tn, NULL, 0, &e) < 0)
-		if (e != ETOPO_PROP_NOENT)
-			return (topo_mod_seterrno(mp, e));
-	return (0);
-}
-
-/*
- * Hopefully this hack routine goes away when fmdump can print the labels.
- */
-static int
-FRU_fmri_hack(topo_mod_t *mp, tnode_t *tn, const char *label)
-{
-	topo_hdl_t *hp;
-	char buf[PATH_MAX];
-	nvlist_t *fmri;
-	int err, e;
-
-	hp = topo_mod_handle(mp);
-
-	(void) snprintf(buf, PATH_MAX, "hc:///component=%s", label);
-	if (topo_fmri_str2nvl(hp, buf, &fmri, &err) < 0)
-		return (topo_mod_seterrno(mp, err));
-
-	e = topo_node_fru_set(tn, fmri, 0, &err);
-	nvlist_free(fmri);
-	if (e < 0)
-		return (topo_mod_seterrno(mp, err));
-	return (0);
-}
-
-/*ARGSUSED*/
-static int
-FRU_set(tnode_t *tn, did_t *pd,
-    const char *dpnm, const char *tpgrp, const char *tpnm,
-    di_prom_handle_t promtree)
-{
-	topo_mod_t *mp;
-	char *label, *nm;
-	int e;
-
-	nm = topo_node_name(tn);
-	mp = did_mod(pd);
-
-	/*
-	 * If this topology node represents something other than an
-	 * ioboard or a device that implements a slot, inherit the
-	 * parent's FRU value.  If there is no label, inherit our
-	 * parent's FRU value.  Otherwise, munge up an fmri based on
-	 * the label.
-	 */
-	if (strcmp(nm, "ioboard") != 0 && strcmp(nm, PCI_DEVICE) != 0 &&
-	    strcmp(nm, PCIEX_DEVICE) != 0) {
-		if (topo_node_fru_set(tn, NULL, 0, &e) < 0) {
-			if (e != ETOPO_PROP_NOENT)
-				return (topo_mod_seterrno(mp, e));
-		}
-		return (0);
-	}
-
-	if (topo_prop_get_string(tn,
-	    TOPO_PGROUP_PROTOCOL, TOPO_PROP_LABEL, &label, &e) < 0) {
-		if (e != ETOPO_PROP_NOENT)
-			return (topo_mod_seterrno(mp, e));
-		if (topo_node_fru_set(tn, NULL, 0, &e) < 0) {
-			if (e != ETOPO_PROP_NOENT)
-				return (topo_mod_seterrno(mp, e));
-		}
-		return (0);
-	}
-	e = FRU_fmri_hack(mp, tn, label);
-	topo_mod_strfree(mp, label);
-	return (e);
-}
-
-/*ARGSUSED*/
-static int
-label_set(tnode_t *tn, did_t *pd,
-    const char *dpnm, const char *tpgrp, const char *tpnm,
-    di_prom_handle_t promtree)
-{
-	topo_mod_t *mp;
-	nvlist_t *in, *out;
-	char *label;
-	int err;
-
-	mp = did_mod(pd);
-	if (topo_mod_nvalloc(mp, &in, NV_UNIQUE_NAME) != 0)
-		return (topo_mod_seterrno(mp, EMOD_FMRI_NVL));
-	if (nvlist_add_uint64(in, TOPO_METH_LABEL_ARG_NVL, (uintptr_t)pd) !=
-	    0) {
-		nvlist_free(in);
-		return (topo_mod_seterrno(mp, EMOD_NOMEM));
-	}
-	if (topo_method_invoke(tn,
-	    TOPO_METH_LABEL, TOPO_METH_LABEL_VERSION, in, &out, &err) != 0) {
-		nvlist_free(in);
-		return (topo_mod_seterrno(mp, err));
-	}
-	nvlist_free(in);
-	if (out != NULL &&
-	    nvlist_lookup_string(out, TOPO_METH_LABEL_RET_STR, &label) == 0) {
-		if (topo_prop_set_string(tn, TOPO_PGROUP_PROTOCOL,
-		    TOPO_PROP_LABEL, TOPO_PROP_SET_ONCE, label, &err) != 0) {
-			nvlist_free(out);
-			return (topo_mod_seterrno(mp, err));
-		}
-		nvlist_free(out);
-	}
-	return (0);
-}
-
-/*ARGSUSED*/
-static int
-EXCAP_set(tnode_t *tn, did_t *pd,
-    const char *dpnm, const char *tpgrp, const char *tpnm,
-    di_prom_handle_t promtree)
-{
-	int excap;
-	int err;
-	int e = 0;
-
-	if ((excap = did_excap(pd)) <= 0)
-		return (0);
-
-	switch (excap & PCIE_PCIECAP_DEV_TYPE_MASK) {
-	case PCIE_PCIECAP_DEV_TYPE_ROOT:
-		e = topo_prop_set_string(tn, TOPO_PGROUP_PCI,
-		    TOPO_PROP_EXCAP, TOPO_PROP_SET_ONCE, PCIEX_ROOT, &err);
-		break;
-	case PCIE_PCIECAP_DEV_TYPE_UP:
-		e = topo_prop_set_string(tn, TOPO_PGROUP_PCI,
-		    TOPO_PROP_EXCAP, TOPO_PROP_SET_ONCE, PCIEX_SWUP, &err);
-		break;
-	case PCIE_PCIECAP_DEV_TYPE_DOWN:
-		e = topo_prop_set_string(tn, TOPO_PGROUP_PCI,
-		    TOPO_PROP_EXCAP, TOPO_PROP_SET_ONCE, PCIEX_SWDWN, &err);
-		break;
-	case PCIE_PCIECAP_DEV_TYPE_PCI2PCIE:
-		e = topo_prop_set_string(tn, TOPO_PGROUP_PCI,
-		    TOPO_PROP_EXCAP, TOPO_PROP_SET_ONCE, PCIEX_BUS, &err);
-		break;
-	case PCIE_PCIECAP_DEV_TYPE_PCIE2PCI:
-		e = topo_prop_set_string(tn, TOPO_PGROUP_PCI,
-		    TOPO_PROP_EXCAP, TOPO_PROP_SET_ONCE, PCI_BUS, &err);
-		break;
-	case PCIE_PCIECAP_DEV_TYPE_PCIE_DEV:
-		e = topo_prop_set_string(tn, TOPO_PGROUP_PCI,
-		    TOPO_PROP_EXCAP, TOPO_PROP_SET_ONCE, PCIEX_DEVICE, &err);
-		break;
-	}
-	if (e != 0)
-		return (topo_mod_seterrno(did_mod(pd), err));
-	return (0);
-}
-
-/*ARGSUSED*/
-static int
-DEVprop_set(tnode_t *tn, did_t *pd,
-    const char *dpnm, const char *tpgrp, const char *tpnm,
-    di_prom_handle_t promtree)
-{
-	topo_mod_t *mp;
-	char *dnpath;
-	char *path, *fpath;
-	int d, f;
-	int err, e;
-
-	mp = did_mod(pd);
-	if ((dnpath = di_devfs_path(did_dinode(pd))) == NULL) {
-		topo_mod_dprintf(mp, "NULL di_devfs_path.\n");
-		return (topo_mod_seterrno(mp, ETOPO_PROP_NOENT));
-	}
-	if ((path = topo_mod_strdup(mp, dnpath)) == NULL) {
-		di_devfs_path_free(dnpath);
-		return (-1);
-	}
-	di_devfs_path_free(dnpath);
-
-	/* The DEV path is modified for hostbridges */
-	if (strcmp(topo_node_name(tn), HOSTBRIDGE) == 0) {
-		fpath = dev_for_hostbridge(did_mod(pd), path);
-	} else {
-		did_BDF(pd, NULL, &d, &f);
-		fpath = dev_path_fix(mp, path, d, f);
-	}
-	if (fpath == NULL)
-		return (-1);
-	e = topo_prop_set_string(tn,
-	    tpgrp, tpnm, TOPO_PROP_SET_ONCE, fpath, &err);
-	topo_mod_strfree(mp, fpath);
-	if (e != 0)
-		return (topo_mod_seterrno(mp, err));
-	return (0);
-}
-
-/*ARGSUSED*/
-static int
-DRIVERprop_set(tnode_t *tn, did_t *pd,
-    const char *dpnm, const char *tpgrp, const char *tpnm,
-    di_prom_handle_t promtree)
-{
-	char *dnm;
-	int err;
-
-	if ((dnm = di_driver_name(did_dinode(pd))) == NULL)
-		return (0);
-	if (topo_prop_set_string(tn,
-	    tpgrp, tpnm, TOPO_PROP_SET_ONCE, dnm, &err) < 0)
-		return (topo_mod_seterrno(did_mod(pd), err));
-
-	return (0);
-}
-
-/*ARGSUSED*/
-static int
-maybe_di_chars_copy(tnode_t *tn, did_t *pd,
-    const char *dpnm, const char *tpgrp, const char *tpnm,
-    di_prom_handle_t promtree)
-{
-	topo_mod_t *mp;
-	uchar_t *typbuf;
-	char *tmpbuf;
-	int sz = -1;
-	int err, e;
-
-	if (di_bytes_get(did_dinode(pd), dpnm, &sz, &typbuf,
-	    promtree) < 0)
-		return (0);
-	mp = did_mod(pd);
-	tmpbuf = topo_mod_alloc(mp, sz + 1);
-	bcopy(typbuf, tmpbuf, sz);
-	tmpbuf[sz] = 0;
-	e = topo_prop_set_string(tn,
-	    tpgrp, tpnm, TOPO_PROP_SET_ONCE, tmpbuf, &err);
-	topo_mod_free(mp, tmpbuf, sz + 1);
-	if (e != 0)
-		return (topo_mod_seterrno(mp, err));
-	return (0);
-}
-
-static int
-uint_to_strprop(topo_mod_t *mp, uint_t v, tnode_t *tn,
-    const char *tpgrp, const char *tpnm)
-{
-	char str[21]; /* sizeof (UINT64_MAX) + '\0' */
-	int e;
-
-	(void) snprintf(str, 21, "%x", v);
-	if (topo_prop_set_string(tn,
-	    tpgrp, tpnm, TOPO_PROP_SET_ONCE, str, &e) < 0)
-		return (topo_mod_seterrno(mp, e));
-	return (0);
-}
-
-static int
-maybe_di_uint_to_str(tnode_t *tn, did_t *pd,
-    const char *dpnm, const char *tpgrp, const char *tpnm,
-    di_prom_handle_t promtree)
-{
-	uint_t v;
-
-	if (di_uintprop_get(did_dinode(pd), dpnm, &v,
-	    promtree) < 0)
-		return (0);
-
-	return (uint_to_strprop(did_mod(pd), v, tn, tpgrp, tpnm));
-}
-
-/*ARGSUSED*/
-static int
-BDF_set(tnode_t *tn, did_t *pd,
-    const char *dpnm, const char *tpgrp, const char *tpnm,
-    di_prom_handle_t promtree)
-{
-	int bdf;
-	char str[23]; /* '0x' + sizeof (UINT64_MAX) + '\0' */
-	int e;
-
-	if ((bdf = did_bdf(pd)) <= 0)
-		return (0);
-
-	(void) snprintf(str, 23, "0x%x", bdf);
-	if (topo_prop_set_string(tn,
-	    tpgrp, tpnm, TOPO_PROP_SET_ONCE, str, &e) < 0)
-		return (topo_mod_seterrno(did_mod(pd), e));
-	return (0);
-}
-
-int
-did_props_set(tnode_t *tn, did_t *pd, txprop_t txarray[], int txnum,
-    di_prom_handle_t promtree)
-{
-	topo_mod_t *mp;
-	const char *ppgroup = NULL;
-	int i, r, e;
-
-	mp = did_mod(pd);
-	for (i = 0; i < txnum; i++) {
-		/*
-		 * Ensure the property group has been created.
-		 */
-		if (ppgroup == NULL ||
-		    strcmp(txarray[i].tx_tpgroup, ppgroup) != 0) {
-			if (topo_pgroup_create(tn, txarray[i].tx_tpgroup,
-			    txarray[i].tx_pgstab, &e) < 0) {
-				if (e != ETOPO_PROP_DEFD)
-					return (topo_mod_seterrno(mp, e));
-			}
-		}
-
-		topo_mod_dprintf(mp,
-		    "Setting property %s in group %s.\n",
-		    txarray[i].tx_tprop, txarray[i].tx_tpgroup);
-		r = txarray[i].tx_xlate(tn, pd,
-		    txarray[i].tx_diprop, txarray[i].tx_tpgroup,
-		    txarray[i].tx_tprop, promtree);
-		if (r != 0) {
-			topo_mod_dprintf(mp, "failed.\n");
-			topo_mod_dprintf(mp, "Error was %s.\n",
-			    topo_strerror(topo_mod_errno(mp)));
-			return (-1);
-		}
-		topo_mod_dprintf(mp, "succeeded.\n");
-	}
-	return (0);
-}
--- a/usr/src/lib/fm/topo/modules/common/did_props.h	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _DID_PROPS_H
-#define	_DID_PROPS_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <sys/pci.h>
-#include <fm/libtopo.h>
-#include <libdevinfo.h>
-#include <libnvpair.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * pci_props_set() processes an array of structures that translate
- * from devinfo props to properties on topology nodes.  The structure
- * provides the name of a devinfo prop, the name of the property
- * group, the name of the property and the stability of the property
- * group that should be established on the topology node, as well as a
- * function to do the work.
- */
-typedef struct txprop {
-	const char *tx_diprop;	/* property examined off the di_node_t */
-	const char *tx_tpgroup;	/* property group defined on the tnode_t */
-	const char *tx_tprop;	/* property defined on the tnode_t */
-	topo_stability_t tx_pgstab;	/* stability of property group */
-	/*
-	 * translation function
-	 *	If NULL, the devinfo prop's value is copied to the
-	 *	topo property.
-	 */
-	int (*tx_xlate)(tnode_t *, did_t *,
-	    const char *, const char *, const char *, di_prom_handle_t);
-} txprop_t;
-
-#define	TOPO_PGROUP_PCI		"pci"
-#define	TOPO_PGROUP_IO		"io"
-
-#define	TOPO_PROP_DEVTYPE	"DEVTYPE"
-#define	TOPO_PROP_DRIVER	"DRIVER"
-#define	TOPO_PROP_VENDID	"VENDOR-ID"
-#define	TOPO_PROP_DEVID		"DEVICE-ID"
-#define	TOPO_PROP_CLASS		"CLASS-CODE"
-#define	TOPO_PROP_EXCAP		"EXCAP"
-#define	TOPO_PROP_BDF		"BDF"
-#define	TOPO_PROP_DEV		"DEV"
-
-#define	DI_DEVTYPPROP	"device_type"
-#define	DI_VENDIDPROP	"vendor-id"
-#define	DI_DEVIDPROP	"device-id"
-#define	DI_CLASSPROP	"class-code"
-#define	DI_REGPROP	"reg"
-#define	DI_CCPROP	"class-code"
-#define	DI_PHYSPROP	"physical-slot#"
-#define	DI_SLOTPROP	"slot-names"
-
-extern int did_props_set(tnode_t *, did_t *, txprop_t[], int,
-    di_prom_handle_t);
-
-extern int pciex_cap_get(did_hash_t *, di_node_t);
-extern int pci_BDF_get(did_hash_t *, di_node_t, int *, int *, int *);
-extern int pci_classcode_get(did_hash_t *, di_node_t, uint_t *, uint_t *);
-
-extern int di_uintprop_get(di_node_t, const char *, uint_t *,
-    di_prom_handle_t);
-extern int di_bytes_get(di_node_t, const char *, int *, uchar_t **,
-    di_prom_handle_t);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _DID_PROPS_H */
--- a/usr/src/lib/fm/topo/modules/common/hostbridge.c	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,421 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <string.h>
-#include <fm/topo_mod.h>
-#include <libdevinfo.h>
-#include <limits.h>
-#include <sys/fm/protocol.h>
-#include <sys/param.h>
-#include <sys/systeminfo.h>
-#include <assert.h>
-#include <pthread.h>
-
-#include "pcibus.h"
-#include "hostbridge.h"
-#include "did.h"
-#include "did_props.h"
-#include "util.h"
-
-/*
- * hostbridge.c
- *	Generic code shared by all the hostbridge enumerators
- */
-
-static void hb_release(topo_mod_t *, tnode_t *);
-static int hb_contains(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
-    nvlist_t **);
-static int hb_present(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
-    nvlist_t **);
-static int hb_label(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
-    nvlist_t **);
-static int hb_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t,
-    topo_instance_t, void *);
-
-extern txprop_t ExHB_common_props[];
-extern txprop_t HB_common_props[];
-extern txprop_t RC_common_props[];
-extern int ExHB_propcnt;
-extern int HB_propcnt;
-extern int RC_propcnt;
-
-static int specific_hb_enum(tnode_t *, const char *, topo_instance_t,
-    topo_instance_t, di_prom_handle_t, topo_mod_t *);
-
-const topo_modinfo_t Hb_info =
-	{ HOSTBRIDGE, HB_ENUMR_VERS, hb_enum, hb_release };
-
-const topo_method_t Hb_methods[] = {
-	{ "hb_contains", "hb element contains other element", HB_ENUMR_VERS,
-	    TOPO_STABILITY_INTERNAL, hb_contains },
-	{ "hb_present", "hb element currently present", HB_ENUMR_VERS,
-	    TOPO_STABILITY_INTERNAL, hb_present },
-	{ TOPO_METH_LABEL, TOPO_METH_LABEL_DESC,
-	    TOPO_METH_LABEL_VERSION, TOPO_STABILITY_INTERNAL, hb_label },
-	{ NULL }
-};
-
-void
-_topo_init(topo_mod_t *modhdl)
-{
-	/*
-	 * Turn on module debugging output
-	 */
-	if (getenv("TOPOHBDBG") != NULL)
-		topo_mod_setdebug(modhdl, TOPO_DBG_ALL);
-	topo_mod_dprintf(modhdl, "initializing hostbridge enumerator\n");
-
-	topo_mod_register(modhdl, &Hb_info, NULL);
-	topo_mod_dprintf(modhdl, "Hostbridge enumr initd\n");
-}
-
-void
-_topo_fini(topo_mod_t *modhdl)
-{
-	topo_mod_unregister(modhdl);
-}
-
-/*ARGSUSED*/
-static int
-hb_contains(topo_mod_t *mp, tnode_t *node, topo_version_t version,
-    nvlist_t *in, nvlist_t **out)
-{
-	return (0);
-}
-
-/*ARGSUSED*/
-static int
-hb_present(topo_mod_t *mp, tnode_t *node, topo_version_t version,
-    nvlist_t *in, nvlist_t **out)
-{
-	return (0);
-}
-
-static int
-hb_label(topo_mod_t *mp, tnode_t *node, topo_version_t version,
-    nvlist_t *in, nvlist_t **out)
-{
-	if (version > TOPO_METH_LABEL_VERSION)
-		return (topo_mod_seterrno(mp, EMOD_VER_NEW));
-	return (platform_hb_label(node, in, out, mp));
-}
-
-static topo_mod_t *
-pci_enumr_load(topo_mod_t *mp, tnode_t *parent)
-{
-	topo_mod_t *rp = NULL;
-	char *plat, *mach;
-	char *pcipath;
-	char *rootdir;
-	int err;
-
-	plat = mach = NULL;
-
-	if (topo_prop_get_string(parent,
-	    TOPO_PGROUP_SYSTEM, TOPO_PROP_PLATFORM, &plat, &err) < 0) {
-		(void) topo_mod_seterrno(mp, err);
-		return (NULL);
-	}
-	if (topo_prop_get_string(parent,
-	    TOPO_PGROUP_SYSTEM, TOPO_PROP_MACHINE, &mach, &err) < 0) {
-		(void) topo_mod_seterrno(mp, err);
-		return (NULL);
-	}
-	pcipath = topo_mod_alloc(mp, PATH_MAX);
-	rootdir = topo_mod_rootdir(mp);
-	(void) snprintf(pcipath,
-	    PATH_MAX, PATH_TO_PCI_ENUM, rootdir ? rootdir : "", plat);
-
-	if ((rp = topo_mod_load(mp, pcipath)) == NULL) {
-		topo_mod_dprintf(mp,
-		    "%s enumerator could not load %s.\n", HOSTBRIDGE, pcipath);
-		(void) snprintf(pcipath,
-		    PATH_MAX, PATH_TO_PCI_ENUM, rootdir ? rootdir : "", mach);
-		if ((rp = topo_mod_load(mp, pcipath)) == NULL) {
-			topo_mod_dprintf(mp,
-			    "%s enumerator could not load %s.\n",
-			    HOSTBRIDGE, pcipath);
-		}
-	}
-	topo_mod_strfree(mp, plat);
-	topo_mod_strfree(mp, mach);
-	topo_mod_free(mp, pcipath, PATH_MAX);
-	return (rp);
-}
-
-/*ARGSUSED*/
-static int
-hb_enum(topo_mod_t *mp, tnode_t *pn, const char *name, topo_instance_t imin,
-    topo_instance_t imax, void *notused)
-{
-	topo_mod_t *pcimod;
-	did_hash_t *didhash;
-	di_prom_handle_t promtree;
-	int rv;
-
-	if (strcmp(name, HOSTBRIDGE) != 0) {
-		topo_mod_dprintf(mp,
-		    "Currently only know how to enumerate %s components.\n",
-		    HOSTBRIDGE);
-		return (0);
-	}
-
-	/*
-	 * Load the pcibus enumerator, we'll soon need it!
-	 */
-	if ((pcimod = pci_enumr_load(mp, pn)) == NULL)
-		return (-1);
-
-	if ((promtree = di_prom_init()) == DI_PROM_HANDLE_NIL) {
-		topo_mod_unload(pcimod);
-		topo_mod_dprintf(mp,
-		    "Hostbridge enumerator: di_prom_handle_init failed.\n");
-		return (-1);
-	}
-
-	/*
-	 * If we're asked to enumerate a whole range of hostbridges, then
-	 * we need to find them all.  If we're just asked to enumerate a
-	 * single hostbridge, we expect our caller to have passed us linked
-	 * did_t structures we can use to enumerate the singled out hostbridge.
-	 */
-	if (imin != imax) {
-
-		if ((didhash = did_hash_init(mp)) == NULL) {
-			topo_mod_dprintf(mp,
-			    "Hash initialization for hostbridge "
-			    "enumerator failed.\n");
-			topo_mod_unload(pcimod);
-			return (-1);
-		}
-		if ((rv = platform_hb_enum(pn, name, imin, imax, didhash,
-		    promtree, mp)) < 0)
-			topo_mod_seterrno(mp, EMOD_PARTIAL_ENUM);
-		di_prom_fini(promtree);
-		did_hash_fini(didhash);
-		topo_mod_unload(pcimod);
-		return (rv);
-	} else {
-		rv = specific_hb_enum(pn, name, imin, imax, promtree, mp);
-		di_prom_fini(promtree);
-		topo_mod_unload(pcimod);
-		return (rv);
-	}
-}
-
-/*ARGSUSED*/
-static void
-hb_release(topo_mod_t *mp, tnode_t *node)
-{
-	topo_method_unregister_all(mp, node);
-}
-
-static tnode_t *
-hb_tnode_create(tnode_t *parent,
-    const char *name, topo_instance_t i, void *priv, topo_mod_t *mod)
-{
-	topo_hdl_t *thp;
-	nvlist_t *args, *fmri, *pfmri;
-	tnode_t *ntn;
-	int err;
-
-	thp = topo_mod_handle(mod);
-
-	if (topo_node_resource(parent, &pfmri, &err) < 0) {
-		topo_mod_seterrno(mod, err);
-		topo_mod_dprintf(mod,
-		    "Unable to retrieve parent resource.\n");
-		return (NULL);
-	}
-	if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0) {
-		(void) topo_mod_seterrno(mod, EMOD_FMRI_NVL);
-		nvlist_free(pfmri);
-		return (NULL);
-	}
-	err = nvlist_add_nvlist(args, TOPO_METH_FMRI_ARG_PARENT, pfmri);
-	if (err != 0) {
-		nvlist_free(pfmri);
-		nvlist_free(args);
-		(void) topo_mod_seterrno(mod, EMOD_FMRI_NVL);
-		return (NULL);
-	}
-
-	fmri = topo_fmri_create(thp, FM_FMRI_SCHEME_HC, name, i, args, &err);
-	if (fmri == NULL) {
-		nvlist_free(pfmri);
-		nvlist_free(args);
-		(void) topo_mod_seterrno(mod, err);
-		topo_mod_dprintf(mod,
-		    "Unable to make nvlist for %s bind: %s.\n",
-		    name, topo_strerror(err));
-		return (NULL);
-	}
-
-	nvlist_free(pfmri);
-	nvlist_free(args);
-	ntn = topo_node_bind(mod, parent, name, i, fmri, priv);
-	if (ntn == NULL) {
-		topo_mod_dprintf(mod,
-		    "topo_node_bind (%s%d/%s%d) failed: %s\n",
-		    topo_node_name(parent), topo_node_instance(parent),
-		    name, i,
-		    topo_strerror(topo_mod_errno(mod)));
-		nvlist_free(fmri);
-		return (NULL);
-	}
-	nvlist_free(fmri);
-	if (topo_method_register(mod, ntn, Hb_methods) < 0) {
-		topo_mod_dprintf(mod, "topo_method_register failed: %s\n",
-		    topo_strerror(topo_mod_errno(mod)));
-		topo_node_unbind(ntn);
-		return (NULL);
-	}
-	return (ntn);
-}
-
-tnode_t *
-pcihostbridge_declare(tnode_t *parent, di_node_t din, topo_instance_t i,
-    did_hash_t *didhash, di_prom_handle_t promtree, topo_mod_t *mod)
-{
-	did_t *pd;
-	tnode_t *ntn;
-
-	if ((pd = did_find(didhash, din)) == NULL)
-		return (NULL);
-	if ((ntn = hb_tnode_create(parent, HOSTBRIDGE, i, pd, mod)) == NULL)
-		return (NULL);
-	if (did_props_set(ntn, pd, HB_common_props, HB_propcnt,
-	    promtree) < 0) {
-		topo_node_unbind(ntn);
-		return (NULL);
-	}
-	/*
-	 * We expect to find pci buses beneath the hostbridge.
-	 */
-	if (child_range_add(mod, ntn, PCI_BUS, 0, MAX_HB_BUSES) < 0) {
-		topo_node_unbind(ntn);
-		return (NULL);
-	}
-	return (ntn);
-}
-
-tnode_t *
-pciexhostbridge_declare(tnode_t *parent, di_node_t din, topo_instance_t hi,
-    did_hash_t *didhash, di_prom_handle_t promtree, topo_mod_t *mod)
-{
-	did_t *pd;
-	tnode_t *ntn;
-
-	if ((pd = did_find(didhash, din)) == NULL)
-		return (NULL);
-	if ((ntn = hb_tnode_create(parent, HOSTBRIDGE, hi, din, mod)) == NULL)
-		return (NULL);
-	if (did_props_set(ntn, pd, ExHB_common_props, ExHB_propcnt,
-	    promtree) < 0) {
-		topo_node_unbind(ntn);
-		return (NULL);
-	}
-	/*
-	 * We expect to find root complexes beneath the hostbridge.
-	 */
-	if (child_range_add(mod, ntn, PCIEX_ROOT, 0, MAX_HB_BUSES) < 0) {
-		topo_node_unbind(ntn);
-		return (NULL);
-	}
-	return (ntn);
-}
-
-tnode_t *
-pciexrc_declare(tnode_t *parent, di_node_t din, topo_instance_t ri,
-    did_hash_t *didhash, di_prom_handle_t promtree, topo_mod_t *mod)
-{
-	did_t *pd;
-	tnode_t *ntn;
-
-	if ((pd = did_find(didhash, din)) == NULL)
-		return (NULL);
-	did_markrc(pd);
-	if ((ntn = hb_tnode_create(parent, PCIEX_ROOT, ri, din, mod)) == NULL)
-		return (NULL);
-	if (did_props_set(ntn, pd, RC_common_props, RC_propcnt,
-	    promtree) < 0) {
-		topo_node_unbind(ntn);
-		return (NULL);
-	}
-	/*
-	 * We expect to find pci-express buses beneath a root complex
-	 */
-	if (child_range_add(mod, ntn, PCIEX_BUS, 0, MAX_HB_BUSES) < 0) {
-		topo_node_range_destroy(ntn, PCIEX_BUS);
-		return (NULL);
-	}
-	return (ntn);
-}
-
-/*ARGSUSED*/
-static int
-specific_hb_enum(tnode_t *pn, const char *name, topo_instance_t imin,
-    topo_instance_t imax, di_prom_handle_t promtree, topo_mod_t *mod)
-{
-	tnode_t *hb;
-	did_t *iodid, *didp;
-	did_hash_t *didhash;
-	char *pname;
-	int brc = 0;
-	int bus;
-
-	pname = topo_node_name(pn);
-	if ((iodid = topo_node_private(pn)) == NULL) {
-		topo_mod_dprintf(mod,
-		    "Parent %s node missing private data.\n"
-		    "Unable to proceed with %s enumeration.\n",
-		    pname, name);
-		return (-1);
-	}
-	didhash = did_hash(iodid);
-
-	/*
-	 * Find the hostbridge of interest
-	 */
-	didp = iodid;
-	for (brc = 0; brc < imin; brc++)
-		didp = did_chain_get(didp);
-	assert(didp != NULL);
-
-	if ((hb = pcihostbridge_declare(pn, did_dinode(didp), imin, didhash,
-	    promtree, mod)) == NULL)
-		return (-1);
-	while (didp != NULL) {
-		did_BDF(didp, &bus, NULL, NULL);
-		if (topo_mod_enumerate(mod,
-		    hb, PCI_BUS, PCI_BUS, bus, bus) != 0)
-			return (topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM));
-		didp = did_link_get(didp);
-	}
-	return (0);
-}
--- a/usr/src/lib/fm/topo/modules/common/hostbridge.h	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _HOSTBRIDGE_H
-#define	_HOSTBRIDGE_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <libdevinfo.h>
-#include "did.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define	HB_ENUMR_VERS	1
-
-#define	PATH_TO_HB_ENUM "%s/usr/platform/%s/lib/fm/topo/plugins/hostbridge.so"
-
-#define	HOSTBRIDGE	"hostbridge"
-
-#define	MAX_HBS	255
-
-/*
- * Solaris Drivers for hostbridge ASICs.
- */
-#define	SCHIZO "pcisch"
-#define	PSYCHO "pcipsy"
-#define	NPE "npe"
-#define	PCIE_PCI "pcie_pci"
-#define	PCI_PCI "pci_pci"
-#define	PCI "pci"
-#define	PX "px"
-
-/*
- * These #defines are special values of bus and root complex instance
- * numbers, used in calls to did_create().  They're here because it's
- * the hostbridge enumerator that generally establishes the did_t values
- * at the top level.
- */
-#define	TRUST_BDF	(-1)	/* Believe the bus value in the reg property */
-#define	NO_RC		(-2)	/* Not a pci-express bus, so no root complex */
-
-/*
- * PCI-express bridges to PCI, root complex instance is set to
- * (instance of the PCI-express side root complex - TO_PCI)
- */
-#define	TO_PCI		(1000)
-
-struct did_hash;
-
-extern tnode_t *pcihostbridge_declare(tnode_t *, di_node_t, topo_instance_t,
-    struct did_hash *, di_prom_handle_t, topo_mod_t *);
-extern tnode_t *pciexhostbridge_declare(tnode_t *, di_node_t, topo_instance_t,
-    struct did_hash *, di_prom_handle_t, topo_mod_t *);
-extern tnode_t *pciexrc_declare(tnode_t *, di_node_t, topo_instance_t,
-    struct did_hash *, di_prom_handle_t, topo_mod_t *);
-
-extern int platform_hb_label(tnode_t *, nvlist_t *, nvlist_t **, topo_mod_t *);
-extern int platform_hb_enum(tnode_t *,
-    const char *, topo_instance_t, topo_instance_t, did_hash_t *,
-    di_prom_handle_t, topo_mod_t *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _HOSTBRIDGE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/common/hostbridge/hostbridge.c	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,357 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <string.h>
+#include <fm/topo_mod.h>
+#include <fm/topo_hc.h>
+#include <libdevinfo.h>
+#include <limits.h>
+#include <sys/fm/protocol.h>
+#include <sys/param.h>
+#include <sys/systeminfo.h>
+#include <assert.h>
+
+#include <hostbridge.h>
+#include <pcibus.h>
+#include <did.h>
+#include <did_props.h>
+#include <util.h>
+
+/*
+ * hostbridge.c
+ *	Generic code shared by all the hostbridge enumerators
+ */
+static void hb_release(topo_mod_t *, tnode_t *);
+static int hb_label(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
+    nvlist_t **);
+static int hb_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t,
+    topo_instance_t, void *, void *);
+
+extern int platform_hb_label(topo_mod_t *, tnode_t *, nvlist_t *, nvlist_t **);
+extern int platform_hb_enum(topo_mod_t *, tnode_t *,
+    const char *, topo_instance_t, topo_instance_t);
+
+extern txprop_t ExHB_common_props[];
+extern txprop_t HB_common_props[];
+extern txprop_t RC_common_props[];
+extern int ExHB_propcnt;
+extern int HB_propcnt;
+extern int RC_propcnt;
+
+static int specific_hb_enum(topo_mod_t *, tnode_t *, const char *,
+    topo_instance_t, topo_instance_t, void *);
+
+static const topo_modops_t Hb_ops =
+	{ hb_enum, hb_release };
+static const topo_modinfo_t Hb_info =
+	{ HOSTBRIDGE, FM_FMRI_SCHEME_HC, HB_ENUMR_VERS, &Hb_ops };
+
+static const topo_method_t Hb_methods[] = {
+	{ TOPO_METH_LABEL, TOPO_METH_LABEL_DESC,
+	    TOPO_METH_LABEL_VERSION, TOPO_STABILITY_INTERNAL, hb_label },
+	{ NULL }
+};
+
+static const topo_pgroup_info_t hb_auth_pgroup = {
+	FM_FMRI_AUTHORITY,
+	TOPO_STABILITY_PRIVATE,
+	TOPO_STABILITY_PRIVATE,
+	1
+};
+
+int
+_topo_init(topo_mod_t *modhdl, topo_version_t version)
+{
+	/*
+	 * Turn on module debugging output
+	 */
+	if (getenv("TOPOHBDBG") != NULL)
+		topo_mod_setdebug(modhdl);
+	topo_mod_dprintf(modhdl, "initializing hostbridge enumerator\n");
+
+	if (version != HB_ENUMR_VERS)
+		return (topo_mod_seterrno(modhdl, EMOD_VER_NEW));
+
+	if (topo_mod_register(modhdl, &Hb_info, TOPO_VERSION) < 0) {
+		topo_mod_dprintf(modhdl, "hostbridge registration failed: %s\n",
+		    topo_mod_errmsg(modhdl));
+		return (-1); /* mod errno already set */
+	}
+
+	topo_mod_dprintf(modhdl, "Hostbridge enumr initd\n");
+
+	return (0);
+}
+
+void
+_topo_fini(topo_mod_t *modhdl)
+{
+	topo_mod_unregister(modhdl);
+}
+
+static int
+hb_label(topo_mod_t *mp, tnode_t *node, topo_version_t version,
+    nvlist_t *in, nvlist_t **out)
+{
+	if (version > TOPO_METH_LABEL_VERSION)
+		return (topo_mod_seterrno(mp, EMOD_VER_NEW));
+	return (platform_hb_label(mp, node, in, out));
+}
+
+static topo_mod_t *
+pci_enumr_load(topo_mod_t *mp)
+{
+	topo_mod_t *rp = NULL;
+
+	if ((rp = topo_mod_load(mp, PCI_ENUM, PCI_ENUMR_VERS)) == NULL) {
+		topo_mod_dprintf(mp,
+		    "%s enumerator could not load %s.\n", HOSTBRIDGE, PCI_ENUM);
+	}
+	return (rp);
+}
+
+/*ARGSUSED*/
+static int
+hb_enum(topo_mod_t *mp, tnode_t *pn, const char *name, topo_instance_t imin,
+    topo_instance_t imax, void *notused, void *data)
+{
+	topo_mod_t *pcimod;
+
+	if (strcmp(name, HOSTBRIDGE) != 0) {
+		topo_mod_dprintf(mp,
+		    "Currently only know how to enumerate %s components.\n",
+		    HOSTBRIDGE);
+		return (0);
+	}
+	/*
+	 * Load the pcibus enumerator
+	 */
+	if ((pcimod = pci_enumr_load(mp)) == NULL)
+		return (-1);
+
+	/*
+	 * If we're asked to enumerate a whole range of hostbridges, then
+	 * we need to find them all.  If we're just asked to enumerate a
+	 * single hostbridge, we expect our caller to have passed us linked
+	 * did_t structures we can use to enumerate the singled out hostbridge.
+	 */
+	if (imin != imax) {
+		int rv;
+
+		if (did_hash_init(mp) < 0) {
+			topo_mod_dprintf(mp,
+			    "Hash initialization for hostbridge "
+			    "enumerator failed.\n");
+			topo_mod_unload(pcimod);
+			return (-1);
+		}
+		if ((rv = platform_hb_enum(mp, pn, name, imin, imax)) < 0)
+			topo_mod_seterrno(mp, EMOD_PARTIAL_ENUM);
+		did_hash_fini(mp);
+		return (rv);
+	} else {
+		return (specific_hb_enum(mp, pn, name, imin, imax,
+		    data));
+	}
+}
+
+/*ARGSUSED*/
+static void
+hb_release(topo_mod_t *mp, tnode_t *node)
+{
+	topo_method_unregister_all(mp, node);
+
+	/*
+	 * node private data (did_t) for this node is destroyed in
+	 * did_hash_destroy()
+	 */
+
+}
+
+static tnode_t *
+hb_tnode_create(topo_mod_t *mod, tnode_t *parent,
+    const char *name, topo_instance_t i, void *priv)
+{
+	int err;
+	nvlist_t *fmri;
+	tnode_t *ntn;
+	nvlist_t *auth = topo_mod_auth(mod, parent);
+
+	fmri = topo_mod_hcfmri(mod, parent, FM_HC_SCHEME_VERSION, name, i,
+	    NULL, auth, NULL, NULL, NULL);
+	nvlist_free(auth);
+	if (fmri == NULL) {
+		topo_mod_dprintf(mod,
+		    "Unable to make nvlist for %s bind: %s.\n",
+		    name, topo_mod_errmsg(mod));
+		return (NULL);
+	}
+
+	ntn = topo_node_bind(mod, parent, name, i, fmri);
+	if (ntn == NULL) {
+		topo_mod_dprintf(mod,
+		    "topo_node_bind (%s%d/%s%d) failed: %s\n",
+		    topo_node_name(parent), topo_node_instance(parent),
+		    name, i,
+		    topo_strerror(topo_mod_errno(mod)));
+		nvlist_free(fmri);
+		return (NULL);
+	}
+	nvlist_free(fmri);
+	topo_node_setspecific(ntn, priv);
+
+	if (topo_pgroup_create(ntn, &hb_auth_pgroup, &err) == 0) {
+		(void) topo_prop_inherit(ntn, FM_FMRI_AUTHORITY,
+		    FM_FMRI_AUTH_PRODUCT, &err);
+		(void) topo_prop_inherit(ntn, FM_FMRI_AUTHORITY,
+		    FM_FMRI_AUTH_CHASSIS, &err);
+		(void) topo_prop_inherit(ntn, FM_FMRI_AUTHORITY,
+		    FM_FMRI_AUTH_SERVER, &err);
+	}
+
+	if (topo_method_register(mod, ntn, Hb_methods) < 0) {
+		topo_mod_dprintf(mod, "topo_method_register failed: %s\n",
+		    topo_strerror(topo_mod_errno(mod)));
+		topo_node_unbind(ntn);
+		return (NULL);
+	}
+	return (ntn);
+}
+
+tnode_t *
+pcihostbridge_declare(topo_mod_t *mod, tnode_t *parent, di_node_t din,
+    topo_instance_t i)
+{
+	did_t *pd;
+	tnode_t *ntn;
+
+	if ((pd = did_find(mod, din)) == NULL)
+		return (NULL);
+	if ((ntn = hb_tnode_create(mod, parent, HOSTBRIDGE, i, din)) == NULL)
+		return (NULL);
+	if (did_props_set(ntn, pd, HB_common_props, HB_propcnt) < 0) {
+		topo_node_unbind(ntn);
+		return (NULL);
+	}
+	/*
+	 * We expect to find pci buses beneath the hostbridge.
+	 */
+	if (child_range_add(mod, ntn, PCI_BUS, 0, MAX_HB_BUSES) < 0) {
+		topo_node_unbind(ntn);
+		return (NULL);
+	}
+	return (ntn);
+}
+
+tnode_t *
+pciexhostbridge_declare(topo_mod_t *mod, tnode_t *parent, di_node_t din,
+    topo_instance_t hi)
+{
+	did_t *pd;
+	tnode_t *ntn;
+
+	if ((pd = did_find(mod, din)) == NULL)
+		return (NULL);
+	if ((ntn = hb_tnode_create(mod, parent, HOSTBRIDGE, hi, din)) == NULL)
+		return (NULL);
+	if (did_props_set(ntn, pd, ExHB_common_props, ExHB_propcnt) < 0) {
+		topo_node_unbind(ntn);
+		return (NULL);
+	}
+	/*
+	 * We expect to find root complexes beneath the hostbridge.
+	 */
+	if (child_range_add(mod, ntn, PCIEX_ROOT, 0, MAX_HB_BUSES) < 0) {
+		topo_node_unbind(ntn);
+		return (NULL);
+	}
+	return (ntn);
+}
+
+tnode_t *
+pciexrc_declare(topo_mod_t *mod, tnode_t *parent, di_node_t din,
+    topo_instance_t ri)
+{
+	did_t *pd;
+	tnode_t *ntn;
+
+	if ((pd = did_find(mod, din)) == NULL)
+		return (NULL);
+	did_markrc(pd);
+	if ((ntn = hb_tnode_create(mod, parent, PCIEX_ROOT, ri, din)) == NULL)
+		return (NULL);
+	if (did_props_set(ntn, pd, RC_common_props, RC_propcnt) < 0) {
+		topo_node_unbind(ntn);
+		return (NULL);
+	}
+	/*
+	 * We expect to find pci-express buses beneath a root complex
+	 */
+	if (child_range_add(mod, ntn, PCIEX_BUS, 0, MAX_HB_BUSES) < 0) {
+		topo_node_range_destroy(ntn, PCIEX_BUS);
+		return (NULL);
+	}
+	return (ntn);
+}
+
+/*ARGSUSED*/
+static int
+specific_hb_enum(topo_mod_t *mod, tnode_t *pn, const char *name,
+    topo_instance_t imin, topo_instance_t imax, void *priv)
+{
+	tnode_t *hb;
+	did_t *iodid = (did_t *)priv;
+	did_t *didp;
+	int brc = 0;
+	int bus;
+
+	did_setspecific(mod, priv);
+
+	/*
+	 * Find the hostbridge of interest
+	 */
+	didp = iodid;
+	for (brc = 0; brc < imin; brc++)
+		didp = did_chain_get(didp);
+	assert(didp != NULL);
+
+	if ((hb = pcihostbridge_declare(mod, pn, did_dinode(didp), imin))
+	    == NULL) {
+		return (-1);
+	}
+	while (didp != NULL) {
+		did_BDF(didp, &bus, NULL, NULL);
+		if (topo_mod_enumerate(mod,
+		    hb, PCI_BUS, PCI_BUS, bus, bus, didp) != 0) {
+			return (topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM));
+		}
+		didp = did_link_get(didp);
+	}
+
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/common/hostbridge/hostbridge.h	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,79 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _HOSTBRIDGE_H
+#define	_HOSTBRIDGE_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <libdevinfo.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define	HB_ENUMR_VERS	1
+
+#define	MAX_HBS	255
+
+/*
+ * Solaris Drivers for hostbridge ASICs.
+ */
+#define	SCHIZO		"pcisch"
+#define	PSYCHO		"pcipsy"
+#define	NPE		"npe"
+#define	PCIE_PCI	"pcie_pci"
+#define	PCI_PCI		"pci_pci"
+#define	PCI		"pci"
+#define	PX		"px"
+
+/*
+ * These #defines are special values of bus and root complex instance
+ * numbers, used in calls to did_create().  They're here because it's
+ * the hostbridge enumerator that generally establishes the did_t values
+ * at the top level.
+ */
+#define	TRUST_BDF	(-1)	/* Believe the bus value in the reg property */
+#define	NO_RC		(-2)	/* Not a pci-express bus, so no root complex */
+
+/*
+ * PCI-express bridges to PCI, root complex instance is set to
+ * (instance of the PCI-express side root complex - TO_PCI)
+ */
+#define	TO_PCI		(1000)
+
+extern tnode_t *pcihostbridge_declare(topo_mod_t *, tnode_t *, di_node_t,
+    topo_instance_t);
+extern tnode_t *pciexhostbridge_declare(topo_mod_t *, tnode_t *, di_node_t,
+    topo_instance_t);
+extern tnode_t *pciexrc_declare(topo_mod_t *, tnode_t *, di_node_t,
+    topo_instance_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HOSTBRIDGE_H */
--- a/usr/src/lib/fm/topo/modules/common/pcibus.c	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,623 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <sys/fm/protocol.h>
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <alloca.h>
-#include <sys/param.h>
-#include <sys/pci.h>
-#include <sys/pcie.h>
-#include <libdevinfo.h>
-#include <libnvpair.h>
-#include <fm/topo_mod.h>
-#include <pthread.h>
-
-#include "hostbridge.h"
-#include "pcibus.h"
-#include "did.h"
-#include "did_props.h"
-#include "util.h"
-
-extern txprop_t Bus_common_props[];
-extern txprop_t Dev_common_props[];
-extern txprop_t Fn_common_props[];
-extern int Bus_propcnt;
-extern int Dev_propcnt;
-extern int Fn_propcnt;
-
-extern int pcifn_enum(topo_mod_t *, tnode_t *);
-
-static void pci_release(topo_mod_t *, tnode_t *);
-static int pci_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t,
-    topo_instance_t, void *);
-static int pci_contains(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
-    nvlist_t **);
-static int pci_present(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
-    nvlist_t **);
-static int pci_label(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
-    nvlist_t **);
-
-const topo_modinfo_t Pci_info =
-	{ PCI_BUS, PCI_ENUMR_VERS, pci_enum, pci_release };
-
-const topo_method_t Pci_methods[] = {
-	{ "pci_contains", "pci element contains other element", PCI_ENUMR_VERS,
-	    TOPO_STABILITY_INTERNAL, pci_contains },
-	{ "pci_present", "pci element currently present", PCI_ENUMR_VERS,
-	    TOPO_STABILITY_INTERNAL, pci_present },
-	{ TOPO_METH_LABEL, TOPO_METH_LABEL_DESC,
-	    TOPO_METH_LABEL_VERSION, TOPO_STABILITY_INTERNAL, pci_label },
-	{ NULL }
-};
-
-void
-_topo_init(topo_mod_t *modhdl)
-{
-	/*
-	 * Turn on module debugging output
-	 */
-	if (getenv("TOPOPCIDBG") != NULL)
-		topo_mod_setdebug(modhdl, TOPO_DBG_ALL);
-	topo_mod_dprintf(modhdl, "initializing pcibus builtin\n");
-
-	topo_mod_register(modhdl, &Pci_info, NULL);
-	topo_mod_dprintf(modhdl, "PCI Enumr initd\n");
-}
-
-void
-_topo_fini(topo_mod_t *modhdl)
-{
-	topo_mod_unregister(modhdl);
-}
-
-/*ARGSUSED*/
-static int
-pci_contains(topo_mod_t *mp, tnode_t *node, topo_version_t version,
-    nvlist_t *in, nvlist_t **out)
-{
-	return (0);
-}
-
-/*ARGSUSED*/
-static int
-pci_present(topo_mod_t *mp, tnode_t *node, topo_version_t version,
-    nvlist_t *in, nvlist_t **out)
-{
-	return (0);
-}
-
-static int
-pci_label(topo_mod_t *mp, tnode_t *node, topo_version_t version,
-    nvlist_t *in, nvlist_t **out)
-{
-	if (version > TOPO_METH_LABEL_VERSION)
-		return (topo_mod_seterrno(mp, EMOD_VER_NEW));
-	return (platform_pci_label(node, in, out, mp));
-}
-
-static tnode_t *
-pci_tnode_create(tnode_t *parent,
-    const char *name, topo_instance_t i, void *priv, topo_mod_t *mod)
-{
-	tnode_t *ntn;
-
-	if ((ntn = tnode_create(mod, parent, name, i, priv)) == NULL)
-		return (NULL);
-	if (topo_method_register(mod, ntn, Pci_methods) < 0) {
-		topo_mod_dprintf(mod, "topo_method_register failed: %s\n",
-		    topo_strerror(topo_mod_errno(mod)));
-		topo_node_unbind(ntn);
-		return (NULL);
-	}
-	return (ntn);
-}
-
-/*ARGSUSED*/
-static int
-hostbridge_asdevice(tnode_t *bus, did_hash_t *didhash,
-    di_prom_handle_t promtree, topo_mod_t *mod)
-{
-	di_node_t di;
-	tnode_t *dev32;
-
-	di = topo_node_private(bus);
-	assert(di != DI_NODE_NIL);
-
-	if ((dev32 = pcidev_declare(bus, di, 32, didhash, promtree, mod))
-	    == NULL)
-		return (-1);
-	if (pcifn_declare(dev32, di, 0, didhash, promtree, mod) == NULL)
-		return (-1);
-	return (0);
-}
-
-tnode_t *
-pciexfn_declare(tnode_t *parent, di_node_t dn, topo_instance_t i,
-    did_hash_t *didhash, di_prom_handle_t promtree, topo_mod_t *mod)
-{
-	did_t *pd;
-	tnode_t *ntn;
-
-	if ((pd = did_find(didhash, dn)) == NULL)
-		return (NULL);
-	if ((ntn = pci_tnode_create(parent, PCIEX_FUNCTION, i, dn, mod))
-	    == NULL)
-		return (NULL);
-	if (did_props_set(ntn, pd, Fn_common_props, Fn_propcnt,
-	    promtree) < 0) {
-		topo_node_unbind(ntn);
-		return (NULL);
-	}
-	/*
-	 * We may find pci-express buses or plain-pci buses beneath a function
-	 */
-	if (child_range_add(mod, ntn, PCIEX_BUS, 0, MAX_HB_BUSES) < 0) {
-		topo_node_range_destroy(ntn, PCIEX_BUS);
-		return (NULL);
-	}
-	if (child_range_add(mod, ntn, PCI_BUS, 0, MAX_HB_BUSES) < 0) {
-		topo_node_range_destroy(ntn, PCI_BUS);
-		return (NULL);
-	}
-	return (ntn);
-}
-
-tnode_t *
-pciexdev_declare(tnode_t *parent, di_node_t dn, topo_instance_t i,
-    did_hash_t *didhash, di_prom_handle_t promtree, topo_mod_t *mod)
-{
-	did_t *pd;
-	tnode_t *ntn;
-
-	if ((pd = did_find(didhash, dn)) == NULL)
-		return (NULL);
-	if ((ntn = pci_tnode_create(parent, PCIEX_DEVICE, i, dn, mod)) == NULL)
-		return (NULL);
-	if (did_props_set(ntn, pd, Dev_common_props, Dev_propcnt,
-	    promtree) < 0) {
-		topo_node_unbind(ntn);
-		return (NULL);
-	}
-	/*
-	 * We can expect to find pci-express functions beneath the device
-	 */
-	if (child_range_add(mod,
-	    ntn, PCIEX_FUNCTION, 0, MAX_PCIDEV_FNS) < 0) {
-		topo_node_range_destroy(ntn, PCIEX_FUNCTION);
-		return (NULL);
-	}
-	return (ntn);
-}
-
-tnode_t *
-pciexbus_declare(tnode_t *parent, di_node_t dn, topo_instance_t i,
-    did_hash_t *didhash, di_prom_handle_t promtree, topo_mod_t *mod)
-{
-	did_t *pd;
-	tnode_t *ntn;
-
-	if ((pd = did_find(didhash, dn)) == NULL)
-		return (NULL);
-	if ((ntn = pci_tnode_create(parent, PCIEX_BUS, i, dn, mod)) == NULL)
-		return (NULL);
-	if (did_props_set(ntn, pd, Bus_common_props, Bus_propcnt,
-	    promtree) < 0) {
-		topo_node_range_destroy(ntn, PCI_DEVICE);
-		topo_node_unbind(ntn);
-		return (NULL);
-	}
-	/*
-	 * We can expect to find pci-express devices beneath the bus
-	 */
-	if (child_range_add(mod,
-	    ntn, PCIEX_DEVICE, 0, MAX_PCIBUS_DEVS) < 0) {
-		topo_node_range_destroy(ntn, PCIEX_DEVICE);
-		return (NULL);
-	}
-	return (ntn);
-}
-
-tnode_t *
-pcifn_declare(tnode_t *parent, di_node_t dn, topo_instance_t i,
-    did_hash_t *didhash, di_prom_handle_t promtree, topo_mod_t *mod)
-{
-	did_t *pd;
-	tnode_t *ntn;
-
-	if ((pd = did_find(didhash, dn)) == NULL)
-		return (NULL);
-	if ((ntn = pci_tnode_create(parent, PCI_FUNCTION, i, dn, mod)) == NULL)
-		return (NULL);
-	if (did_props_set(ntn, pd, Fn_common_props, Fn_propcnt,
-	    promtree) < 0) {
-		topo_node_unbind(ntn);
-		return (NULL);
-	}
-	/*
-	 * We may find pci buses beneath a function
-	 */
-	if (child_range_add(mod, ntn, PCI_BUS, 0, MAX_HB_BUSES) < 0) {
-		topo_node_unbind(ntn);
-		return (NULL);
-	}
-	return (ntn);
-}
-
-tnode_t *
-pcidev_declare(tnode_t *parent, di_node_t dn, topo_instance_t i,
-    did_hash_t *didhash, di_prom_handle_t promtree, topo_mod_t *mod)
-{
-	di_node_t pdn;
-	did_t *pd;
-	tnode_t *ntn;
-	did_t *ppd;
-
-	if ((pdn = topo_node_private(parent)) == DI_NODE_NIL)
-		return (NULL);
-	if ((ppd = did_find(didhash, pdn)) == NULL)
-		return (NULL);
-	if ((pd = did_find(didhash, dn)) == NULL)
-		return (NULL);
-	if ((ntn = pci_tnode_create(parent, PCI_DEVICE, i, dn, mod)) == NULL)
-		return (NULL);
-	/*
-	 * If our devinfo node is lacking certain information of its
-	 * own, we may need/want to inherit the information available
-	 * from our parent node's private data.
-	 */
-	did_inherit(ppd, pd);
-	if (did_props_set(ntn, pd, Dev_common_props, Dev_propcnt,
-	    promtree) < 0) {
-		topo_node_unbind(ntn);
-		return (NULL);
-	}
-	/*
-	 * We can expect to find pci functions beneath the device
-	 */
-	if (child_range_add(mod, ntn, PCI_FUNCTION, 0, MAX_PCIDEV_FNS) < 0) {
-		topo_node_range_destroy(ntn, PCI_FUNCTION);
-		topo_node_unbind(ntn);
-		return (NULL);
-	}
-	return (ntn);
-}
-
-tnode_t *
-pcibus_declare(tnode_t *parent, di_node_t dn, topo_instance_t i,
-    did_hash_t *didhash, di_prom_handle_t promtree, topo_mod_t *mod)
-{
-	did_t *pd;
-	tnode_t *ntn;
-	int hbchild = 0;
-
-	if ((pd = did_find(didhash, dn)) == NULL)
-		return (NULL);
-	if ((ntn = pci_tnode_create(parent, PCI_BUS, i, dn, mod)) == NULL)
-		return (NULL);
-	/*
-	 * If our devinfo node is lacking certain information of its
-	 * own, and our parent topology node is a hostbridge, we may
-	 * need/want to inherit information available in the
-	 * hostbridge node's private data.
-	 */
-	if (strcmp(topo_node_name(parent), HOSTBRIDGE) == 0)
-		hbchild = 1;
-	if (did_props_set(ntn, pd, Bus_common_props, Bus_propcnt,
-	    promtree) < 0) {
-		topo_node_unbind(ntn);
-		return (NULL);
-	}
-	/*
-	 * We can expect to find pci devices beneath the bus
-	 */
-	if (child_range_add(mod, ntn, PCI_DEVICE, 0, MAX_PCIBUS_DEVS) < 0) {
-		topo_node_unbind(ntn);
-		return (NULL);
-	}
-	/*
-	 * On each bus child of the hostbridge, we represent the
-	 * hostbridge as a device outside the range of legal device
-	 * numbers.
-	 */
-	if (hbchild == 1) {
-		if (hostbridge_asdevice(ntn, didhash, promtree, mod) < 0) {
-			topo_node_range_destroy(ntn, PCI_DEVICE);
-			topo_node_unbind(ntn);
-			return (NULL);
-		}
-	}
-	return (ntn);
-}
-
-static int
-pci_bridge_declare(tnode_t *fn, di_node_t din, int board,
-    int bridge, int rc, int depth, did_hash_t *didhash,
-    di_prom_handle_t promtree, topo_mod_t *mod)
-{
-	int err, excap, extyp;
-
-	excap = pciex_cap_get(didhash, din);
-	extyp = excap & PCIE_PCIECAP_DEV_TYPE_MASK;
-	if (excap <= 0 ||
-	    extyp != PCIE_PCIECAP_DEV_TYPE_PCIE2PCI)
-		err = pci_children_instantiate(fn,
-		    din, board, bridge, rc, TRUST_BDF, depth + 1, didhash,
-		    promtree, mod);
-	else
-		err = pci_children_instantiate(fn,
-		    din, board, bridge, rc - TO_PCI, TRUST_BDF, depth + 1,
-		    didhash, promtree, mod);
-	return (err);
-}
-
-static int
-declare_dev_and_fn(tnode_t *bus, tnode_t **dev, di_node_t din,
-    int board, int bridge, int rc, int devno, int fnno, int depth,
-    did_hash_t *didhash, di_prom_handle_t promtree, topo_mod_t *mod)
-{
-	tnode_t *fn;
-	uint_t class, subclass;
-	int err;
-
-	if (*dev == NULL) {
-		if (rc >= 0)
-			*dev = pciexdev_declare(bus, din, devno, didhash,
-			    promtree, mod);
-		else
-			*dev = pcidev_declare(bus, din, devno, didhash,
-			    promtree, mod);
-		if (*dev == NULL)
-			return (-1);
-	}
-	if (rc >= 0)
-		fn = pciexfn_declare(*dev, din, fnno, didhash, promtree, mod);
-	else
-		fn = pcifn_declare(*dev, din, fnno, didhash, promtree, mod);
-	if (fn == NULL)
-		return (-1);
-	if (pci_classcode_get(didhash, din, &class, &subclass) < 0)
-		return (-1);
-	if (class == PCI_CLASS_BRIDGE && subclass == PCI_BRIDGE_PCI)
-		err = pci_bridge_declare(fn, din, board, bridge, rc, depth,
-		    didhash, promtree, mod);
-	else
-		err = pcifn_enum(mod, fn);
-	if (err < 0)
-		return (-1);
-	else
-		return (0);
-}
-
-int
-pci_children_instantiate(tnode_t *parent, di_node_t pn,
-    int board, int bridge, int rc, int bover, int depth, did_hash_t *didhash,
-    di_prom_handle_t promtree, topo_mod_t *mod)
-{
-	did_t *pps[MAX_PCIBUS_DEVS][MAX_PCIDEV_FNS];
-	did_t *bp = NULL;
-	did_t *np;
-	di_node_t sib;
-	di_node_t din;
-	tnode_t *bn = NULL;
-	tnode_t *dn = NULL;
-	int pb = -1;
-	int b, d, f;
-
-	for (d = 0; d < MAX_PCIBUS_DEVS; d++)
-		for (f = 0; f < MAX_PCIDEV_FNS; f++)
-			pps[d][f] = NULL;
-
-	/* start at the parent's first sibling */
-	sib = di_child_node(pn);
-	while (sib != DI_NODE_NIL) {
-		np = did_create(didhash, sib, board, bridge, rc, bover,
-		    promtree);
-		if (np == NULL)
-			return (-1);
-		did_BDF(np, &b, &d, &f);
-		pps[d][f] = np;
-		if (bp == NULL)
-			bp = np;
-		if (pb < 0)
-			pb = ((bover == TRUST_BDF) ? b : bover);
-		sib = di_sibling_node(sib);
-	}
-	if (pb < 0 && bover < 0)
-		return (0);
-	if (rc >= 0)
-		bn = pciexbus_declare(parent, pn, ((pb < 0) ? bover : pb),
-		    didhash, promtree, mod);
-	else
-		bn = pcibus_declare(parent, pn, ((pb < 0) ? bover : pb),
-		    didhash, promtree, mod);
-	if (bn == NULL)
-		return (-1);
-	if (pb < 0)
-		return (0);
-
-	for (d = 0; d < MAX_PCIBUS_DEVS; d++) {
-		for (f = 0; f < MAX_PCIDEV_FNS; f++) {
-			if (pps[d][f] == NULL)
-				continue;
-			din = did_dinode(pps[d][f]);
-			if ((declare_dev_and_fn(bn,
-			    &dn, din, board, bridge, rc, d, f, depth,
-			    didhash, promtree, mod)) != 0)
-				return (-1);
-			did_rele(pps[d][f]);
-		}
-		dn = NULL;
-	}
-	return (0);
-}
-
-static int
-pciexbus_enum(tnode_t *ptn,
-    char *pnm, topo_instance_t min, topo_instance_t max,
-    di_prom_handle_t promtree, topo_mod_t *mod)
-{
-	di_node_t pdn;
-	int rc;
-	int retval;
-	did_hash_t *didhash;
-
-	/*
-	 * PCI-Express; root complex shares the hostbridge's instance
-	 * number.  Parent node's private data is a simple di_node_t
-	 * and we have to construct our own did hash and did_t.
-	 */
-	rc = topo_node_instance(ptn);
-
-	if ((pdn = topo_node_private(ptn)) == DI_NODE_NIL) {
-		topo_mod_dprintf(mod,
-		    "Parent %s node missing private data.\n"
-		    "Unable to proceed with %s enumeration.\n",
-		    pnm, PCIEX_BUS);
-		return (0);
-	}
-	if ((didhash = did_hash_init(mod)) == NULL ||
-	    (did_create(didhash, pdn, 0, 0, rc, TRUST_BDF, promtree) == NULL))
-		return (-1);	/* errno already set */
-	retval = pci_children_instantiate(ptn,
-	    pdn, 0, 0, rc, (min == max) ? min : TRUST_BDF, 0, didhash,
-	    promtree, mod);
-	did_hash_fini(didhash);
-	return (retval);
-}
-
-static int
-pcibus_enum(tnode_t *ptn, char *pnm, topo_instance_t min, topo_instance_t max,
-    di_prom_handle_t promtree, topo_mod_t *mod)
-{
-	did_t *hbdid, *didp;
-	int retval;
-	did_hash_t *didhash;
-
-	/*
-	 * PCI Bus; Parent node's private data is a did_t.  We'll
-	 * use the did hash established by the parent.
-	 */
-	if ((hbdid = topo_node_private(ptn)) == NULL) {
-		topo_mod_dprintf(mod,
-		    "Parent %s node missing private data.\n"
-		    "Unable to proceed with %s enumeration.\n",
-		    pnm, PCIEX_BUS);
-		return (0);
-	}
-	didhash = did_hash(hbdid);
-
-	/*
-	 * If we're looking for a specific bus-instance, find the right
-	 * did_t in the chain, otherwise, there should be only one did_t.
-	 */
-	if (min == max) {
-		int b;
-		didp = hbdid;
-		while (didp != NULL) {
-			did_BDF(didp, &b, NULL, NULL);
-			if (b == min)
-				break;
-			didp = did_link_get(didp);
-		}
-		if (didp == NULL) {
-			topo_mod_dprintf(mod,
-			    "Parent %s node missing private data related\n"
-			    "to %s instance %d.\n", pnm, PCI_BUS, min);
-			return (0);
-		}
-	} else {
-		assert(did_link_get(hbdid) == NULL);
-		didp = hbdid;
-	}
-	retval = pci_children_instantiate(ptn, did_dinode(didp),
-	    did_board(didp), did_bridge(didp), did_rc(didp),
-	    (min == max) ? min : TRUST_BDF, 0, didhash, promtree, mod);
-	return (retval);
-}
-
-/*ARGSUSED*/
-static int
-pci_enum(topo_mod_t *mp, tnode_t *ptn, const char *name,
-    topo_instance_t min, topo_instance_t max, void *notused)
-{
-	char *pnm;
-	int retval;
-	di_prom_handle_t promtree;
-
-	topo_mod_dprintf(mp, "Enumerating pci!\n");
-
-	if ((promtree = di_prom_init()) == DI_PROM_HANDLE_NIL) {
-		topo_mod_dprintf(mp,
-		    "Pcibus enumerator: di_prom_handle_init failed.\n");
-		return (-1);
-	}
-
-	pnm = topo_node_name(ptn);
-	if (strcmp(pnm, HOSTBRIDGE) != 0 && strcmp(pnm, PCIEX_ROOT) != 0) {
-		topo_mod_dprintf(mp,
-		    "Currently can only enumerate a %s or %s directly\n",
-		    PCI_BUS, PCIEX_BUS);
-		topo_mod_dprintf(mp,
-		    "descended from a %s or %s node.\n",
-		    HOSTBRIDGE, PCIEX_ROOT);
-		di_prom_fini(promtree);
-		return (0);
-	}
-
-	if (strcmp(name, PCI_BUS) == 0) {
-		retval = pcibus_enum(ptn, pnm, min, max, promtree, mp);
-	} else if (strcmp(name, PCIEX_BUS) == 0) {
-		retval = pciexbus_enum(ptn, pnm, min, max, promtree, mp);
-	} else {
-		topo_mod_dprintf(mp,
-		    "Currently only know how to enumerate %s or %s not %s.\n",
-		    PCI_BUS, PCIEX_BUS, name);
-		di_prom_fini(promtree);
-		return (0);
-	}
-	di_prom_fini(promtree);
-	return (retval);
-}
-
-/*ARGSUSED*/
-static void
-pci_release(topo_mod_t *mp, tnode_t *node)
-{
-	topo_method_unregister_all(mp, node);
-
-	/*
-	 * node private data (did_t) for this node is destroyed in
-	 * did_hash_destroy()
-	 */
-
-	topo_node_unbind(node);
-}
--- a/usr/src/lib/fm/topo/modules/common/pcibus.h	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _PCIBUS_H
-#define	_PCIBUS_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <sys/pci.h>
-#include <fm/topo_mod.h>
-#include <fm/libtopo.h>
-#include <libdevinfo.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define	PCI_ENUMR_VERS	1
-
-#define	PATH_TO_PCI_ENUM "%s/usr/platform/%s/lib/fm/topo/plugins/pcibus.so"
-
-#define	PCI_BUS		"pcibus"
-#define	PCI_DEVICE	"pcidev"
-#define	PCI_FUNCTION	"pcifn"
-#define	PCIEX_ROOT	"pciexrc"
-#define	PCIEX_SWUP	"pciexswu"
-#define	PCIEX_SWDWN	"pciexswd"
-#define	PCIEX_BUS	"pciexbus"
-#define	PCIEX_DEVICE	"pciexdev"
-#define	PCIEX_FUNCTION	"pciexfn"
-
-#define	PCIEXTYPE "pciex"
-#define	PCITYPE "pci"
-
-#define	MAX_HB_BUSES	255
-#define	MAX_PCIBUS_DEVS	32
-#define	MAX_PCIDEV_FNS	8
-
-#define	GETCLASS(x) (((x) & 0xff0000) >> 16)
-#define	GETSUBCLASS(x) (((x) & 0xff00) >> 8)
-
-struct did_hash;
-
-extern tnode_t *pcibus_declare(tnode_t *, di_node_t, topo_instance_t,
-    struct did_hash *, di_prom_handle_t, topo_mod_t *);
-extern tnode_t *pcidev_declare(tnode_t *, di_node_t, topo_instance_t,
-    struct did_hash *, di_prom_handle_t, topo_mod_t *);
-extern tnode_t *pcifn_declare(tnode_t *, di_node_t, topo_instance_t,
-    struct did_hash *, di_prom_handle_t, topo_mod_t *);
-extern tnode_t *pciexbus_declare(tnode_t *, di_node_t, topo_instance_t,
-    struct did_hash *, di_prom_handle_t, topo_mod_t *);
-extern tnode_t *pciexdev_declare(tnode_t *, di_node_t, topo_instance_t,
-    struct did_hash *, di_prom_handle_t, topo_mod_t *);
-extern tnode_t *pciexfn_declare(tnode_t *, di_node_t, topo_instance_t,
-    struct did_hash *, di_prom_handle_t, topo_mod_t *);
-extern int pci_children_instantiate(tnode_t *, di_node_t,
-    int, int, int, int, int, struct did_hash *, di_prom_handle_t,
-    topo_mod_t *);
-
-extern int platform_pci_label(tnode_t *, nvlist_t *, nvlist_t **, topo_mod_t *);
-
-extern const topo_method_t Pci_methods[];
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _PCIBUS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/common/pcibus/did.c	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,546 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+/*
+ * did.c
+ *	The acronym did means "Dev-Info-Data".  Many properties and
+ *	characteristics of topology nodes are, with a bit of coaxing
+ *	derived from devinfo nodes.  These routines do some of the
+ *	derivation and also encapsulate the discoveries in did_t
+ *	structures that get associated with topology nodes as their
+ *	"private" data.
+ */
+#include <alloca.h>
+#include <assert.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <fm/topo_mod.h>
+#include <libnvpair.h>
+#include <libdevinfo.h>
+#include <sys/pcie.h>
+
+#include <hostbridge.h>
+#include <pcibus.h>
+#include <did_props.h>
+
+#include "did_impl.h"
+
+static void slotnm_destroy(slotnm_t *);
+
+static slotnm_t *
+slotnm_create(topo_mod_t *mp, int dev, char *str)
+{
+	slotnm_t *p;
+
+	if ((p = topo_mod_alloc(mp, sizeof (slotnm_t))) == NULL)
+		return (NULL);
+	p->snm_mod = mp;
+	p->snm_next = NULL;
+	p->snm_dev = dev;
+	p->snm_label = topo_mod_strdup(mp, str);
+	if (p->snm_label == NULL) {
+		slotnm_destroy(p);
+		return (NULL);
+	}
+	return (p);
+}
+
+static void
+slotnm_destroy(slotnm_t *p)
+{
+	if (p == NULL)
+		return;
+	slotnm_destroy(p->snm_next);
+	if (p->snm_label != NULL)
+		topo_mod_strfree(p->snm_mod, p->snm_label);
+	topo_mod_free(p->snm_mod, p, sizeof (slotnm_t));
+}
+
+static int
+slotnm_cp(did_t *from, did_t *to, int *nslots)
+{
+	slotnm_t *nxt, *new;
+	slotnm_t *last = NULL;
+
+	*nslots = 0;
+	for (nxt = from->dp_slotnames; nxt != NULL; nxt = nxt->snm_next) {
+		new = slotnm_create(to->dp_mod, nxt->snm_dev, nxt->snm_label);
+		if (new == NULL) {
+			if (to->dp_slotnames != NULL)
+				slotnm_destroy(to->dp_slotnames);
+			to->dp_slotnames = NULL;
+			*nslots = 0;
+			return (-1);
+		}
+		if (last == NULL) {
+			to->dp_slotnames = last = new;
+		} else {
+			last->snm_next = new;
+			last = new;
+		}
+		(*nslots)++;
+	}
+	if (*nslots > 0)
+		topo_mod_dprintf(to->dp_mod,
+		    "%p inherits %d slot label(s) from %p.\n",
+		    to, *nslots, from);
+	return (0);
+}
+
+static int
+di_physlotinfo_get(topo_mod_t *mp, di_node_t src, uint_t excap,
+    int *slotnum, char **slotnm)
+{
+	char *slotbuf;
+	int sz;
+	uchar_t *buf;
+
+	*slotnum = -1;
+	(void) di_uintprop_get(mp, src, DI_PHYSPROP, (uint_t *)slotnum);
+	/*
+	 * If no physical slot number property was found, then the
+	 * capabilities register may indicate the pci-express device
+	 * implements a slot, and we should record which slot.
+	 */
+	if (*slotnum == -1 && (excap & PCIE_PCIECAP_SLOT_IMPL) != 0) {
+		uint_t slotcap;
+		int e;
+		e = di_uintprop_get(mp, src, "pcie-slotcap-reg", &slotcap);
+		if (e == 0)
+			*slotnum = slotcap >> PCIE_SLOTCAP_PHY_SLOT_NUM_SHIFT;
+	}
+	if (*slotnum == -1)
+		return (0);
+
+	/*
+	 * For PCI-Express, there is only one downstream device, so check for
+	 * a slot-names property, and if it exists, ignore the slotmask value
+	 * and use the string as the label.
+	 */
+	if (di_bytes_get(mp, src, DI_SLOTPROP, &sz, &buf) == 0 &&
+	    sz > 4) {
+		slotbuf = (char *)&buf[4];
+	} else {
+		/*
+		 * Make generic description string "SLOT <num>", allow up to
+		 * 10 digits for number
+		 */
+		slotbuf = alloca(16);
+		(void) snprintf(slotbuf, 16, "SLOT %d", *slotnum);
+	}
+	if ((*slotnm = topo_mod_strdup(mp, slotbuf)) == NULL)
+		return (-1);
+
+	return (0);
+}
+
+static int
+di_slotinfo_get(topo_mod_t *mp, di_node_t src, int *nslots, slotnm_t **slots)
+{
+	slotnm_t *lastslot = NULL;
+	slotnm_t *newslot;
+	uchar_t *slotbuf;
+	uint_t slotmap = 0;
+	char *slotname;
+	int andbit;
+	int sz = -1;
+
+	*slots = NULL;
+	*nslots = 0;
+	if (di_bytes_get(mp, src, DI_SLOTPROP, &sz, &slotbuf) < 0)
+		return (0);
+	if (sz < sizeof (uint_t))
+		return (0);
+	bcopy(slotbuf, &slotmap, sizeof (uint_t));
+	if (slotmap == 0)
+		return (0);
+
+	slotname = (char *)&slotbuf[4];
+	for (andbit = 0; andbit < 32; andbit++) {
+		if (slotmap & (1 << andbit)) {
+			char *s = slotname;
+			slotname += strlen(s) + 1;
+			if ((newslot = slotnm_create(mp, andbit, s)) == NULL) {
+				slotnm_destroy(*slots);
+				*slots = NULL;
+				*nslots = 0;
+				return (-1);
+			}
+			if (lastslot == NULL)
+				*slots = lastslot = newslot;
+			else {
+				lastslot->snm_next = newslot;
+				lastslot = newslot;
+			}
+			(*nslots)++;
+		}
+	}
+	return (0);
+}
+
+int
+did_physslot(did_t *did)
+{
+	assert(did != NULL);
+	return (did->dp_physlot);
+}
+
+did_t *
+did_create(topo_mod_t *mp, di_node_t src,
+    int ibrd, int ibrdge, int irc, int ibus)
+{
+	did_t *np;
+	did_t *pd;
+	uint_t code;
+	uint_t reg;
+
+	if ((pd = did_hash_lookup(mp, src)) != NULL) {
+		topo_mod_dprintf(mp, "Attempt to create existing did_t.\n");
+		assert(ibus == TRUST_BDF || (pd->dp_bus == ibus));
+		return (pd);
+	}
+
+	if ((np = topo_mod_zalloc(mp, sizeof (did_t))) == NULL)
+		return (NULL);
+	np->dp_mod = mp;
+	np->dp_src = src;
+	np->dp_hash = (did_hash_t *)topo_mod_getspecific(mp);
+
+	/*
+	 * We must have a reg prop and from it we extract the bus #,
+	 * device #, and function #.
+	 */
+	if (di_uintprop_get(mp, src, DI_REGPROP, &reg) < 0) {
+		topo_mod_free(mp, np, sizeof (did_t));
+		return (NULL);
+	}
+	np->dp_board = ibrd;
+	np->dp_bridge = ibrdge;
+	np->dp_rc = irc;
+	if (ibus == TRUST_BDF)
+		np->dp_bus = PCI_REG_BUS_G(reg);
+	else
+		np->dp_bus = ibus;
+	np->dp_dev = PCI_REG_DEV_G(reg);
+	np->dp_fn = PCI_REG_FUNC_G(reg);
+	np->dp_bdf = (PCI_REG_BUS_G(reg) << 8) | (PCI_REG_DEV_G(reg) << 3) |
+	    PCI_REG_FUNC_G(reg);
+	/*
+	 * There *may* be a class code we can capture.  If there wasn't
+	 * one, capture that fact by setting the class value to -1.
+	 */
+	if (di_uintprop_get(mp, src, DI_CCPROP, &code) == 0) {
+		np->dp_class = GETCLASS(code);
+		np->dp_subclass = GETSUBCLASS(code);
+	} else {
+		np->dp_class = -1;
+	}
+	/*
+	 * There *may* be a PCI-express capabilities register we can capture.
+	 * If there wasn't one, the capabilities will be the out-of-bounds
+	 * value of zero.
+	 */
+	(void) di_uintprop_get(mp, src, "pcie-capid-reg", &np->dp_excap);
+	/*
+	 * There *may* be a physical slot number property we can capture.
+	 */
+	if (di_physlotinfo_get(mp,
+	    src, np->dp_excap, &np->dp_physlot, &np->dp_physlot_label) < 0) {
+		topo_mod_free(mp, np, sizeof (did_t));
+		return (NULL);
+	}
+	/*
+	 * There *may* be PCI slot info we can capture
+	 */
+	if (di_slotinfo_get(mp, src, &np->dp_nslots, &np->dp_slotnames) < 0) {
+		if (np->dp_physlot_label != NULL)
+			topo_mod_strfree(mp, np->dp_physlot_label);
+		topo_mod_free(mp, np, sizeof (did_t));
+		return (NULL);
+	}
+	did_hash_insert(mp, src, np);
+	did_hold(np);
+	return (np);
+}
+
+did_t *
+did_link_get(did_t *dp)
+{
+	assert(dp != NULL);
+	return (dp->dp_link);
+}
+
+did_t *
+did_chain_get(did_t *dp)
+{
+	assert(dp != NULL);
+	return (dp->dp_chain);
+}
+
+void
+did_link_set(topo_mod_t *mod, tnode_t *head, did_t *tail)
+{
+	did_t *hd, *pd;
+
+	assert(head != NULL);
+	pd = hd = did_find(mod, topo_node_getspecific(head));
+	assert(hd != NULL);
+	while ((hd = did_link_get(hd)) != NULL)
+		pd = hd;
+	pd->dp_link = tail;
+	tail->dp_link = NULL;
+}
+
+void
+did_did_link_set(did_t *from, did_t *to)
+{
+	assert(from != NULL && to != NULL);
+	from->dp_link = to;
+}
+
+void
+did_did_chain_set(did_t *from, did_t *to)
+{
+	assert(from != NULL && to != NULL);
+	from->dp_chain = to;
+}
+
+void
+did_destroy(did_t *dp)
+{
+	assert(dp != NULL);
+
+	/*
+	 * did_destroy() is called only from did_hash_destroy() when
+	 * all references to the did_t have been released.  We can
+	 * safely destroy the did_t.  If at some later time, more
+	 * fine-grained reference count control is desired, this
+	 * code will need to change
+	 */
+
+	if (dp->dp_physlot_label != NULL)
+		topo_mod_strfree(dp->dp_mod, dp->dp_physlot_label);
+	slotnm_destroy(dp->dp_slotnames);
+	topo_mod_free(dp->dp_mod, dp, sizeof (did_t));
+}
+
+void
+did_hold(did_t *dp)
+{
+	assert(dp != NULL);
+	dp->dp_refcnt++;
+}
+
+void
+did_rele(did_t *dp)
+{
+	assert(dp != NULL);
+	assert(dp->dp_refcnt > 0);
+	dp->dp_refcnt--;
+}
+
+di_node_t
+did_dinode(did_t *dp)
+{
+	assert(dp != NULL);
+	assert(dp->dp_src != NULL);
+	return (dp->dp_src);
+}
+
+topo_mod_t *
+did_mod(did_t *dp)
+{
+	assert(dp != NULL);
+	return (dp->dp_mod);
+}
+
+void
+did_markrc(did_t *dp)
+{
+	assert(dp != NULL);
+	dp->dp_excap |= PCIE_PCIECAP_DEV_TYPE_ROOT;
+}
+
+void
+did_BDF(did_t *dp, int *bus, int *dev, int *fn)
+{
+	assert(dp != NULL);
+	if (bus != NULL)
+		*bus = dp->dp_bus;
+	if (dev != NULL)
+		*dev = dp->dp_dev;
+	if (fn != NULL)
+		*fn = dp->dp_fn;
+}
+
+int
+did_board(did_t *did)
+{
+	assert(did != NULL);
+	return (did->dp_board);
+}
+
+int
+did_bridge(did_t *did)
+{
+	assert(did != NULL);
+	return (did->dp_bridge);
+}
+
+int
+did_rc(did_t *did)
+{
+	assert(did != NULL);
+	return (did->dp_rc);
+}
+
+static int
+did_numlabels(did_t *dp)
+{
+	assert(dp != NULL);
+	return (dp->dp_nslots);
+}
+
+int
+did_excap(did_t *dp)
+{
+	assert(dp != NULL);
+	return ((int)dp->dp_excap);
+}
+
+int
+did_bdf(did_t *dp)
+{
+	assert(dp != NULL);
+	return ((int)dp->dp_bdf);
+}
+
+const char *
+did_label(did_t *dp, int dev)
+{
+	slotnm_t *slot;
+
+	assert(dp != NULL);
+	if (dp->dp_physlot_label != NULL)
+		return (dp->dp_physlot_label);
+	for (slot = dp->dp_slotnames; slot != NULL; slot = slot->snm_next)
+		if (slot->snm_dev == dev)
+			break;
+	if (slot != NULL)
+		return (slot->snm_label);
+	return (NULL);
+}
+
+did_t *
+did_find(topo_mod_t *mp, di_node_t dn)
+{
+	return (did_hash_lookup(mp, dn));
+}
+
+int
+pci_BDF_get(topo_mod_t *mp, di_node_t dn, int *bus, int *dev, int *fn)
+{
+	did_t *dp;
+
+	if ((dp = did_find(mp, dn)) == NULL)
+		return (-1);
+	*bus = dp->dp_bus;
+	*dev = dp->dp_dev;
+	*fn = dp->dp_fn;
+	did_rele(dp);
+	return (0);
+}
+
+int
+pci_classcode_get(topo_mod_t *mp, di_node_t dn, uint_t *class, uint_t *sub)
+{
+	did_t *dp;
+
+	if ((dp = did_find(mp, dn)) == NULL)
+		return (-1);
+	if (dp->dp_class < 0) {
+		did_rele(dp);
+		return (-1);
+	}
+	*class = dp->dp_class;
+	*sub = dp->dp_subclass;
+	did_rele(dp);
+	return (0);
+}
+
+int
+pciex_cap_get(topo_mod_t *mp, di_node_t dn)
+{
+	did_t *dp;
+
+	if ((dp = did_find(mp, dn)) == NULL)
+		return (-1);
+	did_rele(dp);
+	return (dp->dp_excap);
+}
+
+int
+did_inherit(did_t *pdp, did_t *dp)
+{
+	/*
+	 * If the child already has a label, we're done.
+	 */
+	assert(dp != NULL);
+	if (did_numlabels(dp) > 0)
+		return (0);
+
+	assert(pdp != NULL);
+
+	/*
+	 * If the child and parent are the same, we're done.
+	 */
+	if (dp == pdp)
+		return (0);
+
+	if (pdp->dp_physlot_label != NULL) {
+		topo_mod_dprintf(dp->dp_mod,
+		    "%p inherits physlot label from %p.\n", dp, pdp);
+		dp->dp_physlot_label =
+		    topo_mod_strdup(dp->dp_mod, pdp->dp_physlot_label);
+		if (dp->dp_physlot_label == NULL)
+			return (-1);
+	}
+	if (slotnm_cp(pdp, dp, &dp->dp_nslots) < 0)
+		return (-1);
+	return (0);
+}
+
+void
+did_setspecific(topo_mod_t *mp, void *data)
+{
+	did_t *hbdid;
+
+	hbdid = (did_t *)data;
+	topo_mod_setspecific(mp, hbdid->dp_hash);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/common/pcibus/did.h	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,78 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _DID_H
+#define	_DID_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/pci.h>
+#include <fm/topo_mod.h>
+#include <libdevinfo.h>
+#include <libnvpair.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct did did_t;
+
+extern did_t *did_create(topo_mod_t *, di_node_t, int, int, int,
+    int);
+extern did_t *did_find(topo_mod_t *, di_node_t);
+extern did_t *did_hash_lookup(topo_mod_t *, di_node_t);
+extern void did_hash_insert(topo_mod_t *, di_node_t, did_t *);
+extern void did_hash_fini(topo_mod_t *);
+extern int did_hash_init(topo_mod_t *);
+extern void did_link_set(topo_mod_t *, tnode_t *, did_t *);
+extern void did_setspecific(topo_mod_t *, void *);
+
+extern topo_mod_t *did_mod(did_t *);
+extern di_node_t did_dinode(did_t *);
+extern void did_BDF(did_t *, int *, int *, int *);
+extern void did_markrc(did_t *);
+extern const char *did_label(did_t *, int);
+extern int did_board(did_t *);
+extern int did_bridge(did_t *);
+extern int did_rc(did_t *);
+extern int did_physslot(did_t *);
+extern int did_inherit(did_t *, did_t *);
+extern int did_excap(did_t *);
+extern int did_bdf(did_t *);
+extern did_t *did_link_get(did_t *);
+extern did_t *did_chain_get(did_t *);
+extern void did_destroy(did_t *);
+extern void did_hold(did_t *);
+extern void did_did_link_set(did_t *, did_t *);
+extern void did_did_chain_set(did_t *, did_t *);
+extern void did_rele(did_t *);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DID_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/common/pcibus/did_hash.c	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,172 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <libdevinfo.h>
+#include <fm/topo_mod.h>
+#include <pcibus.h>
+#include <did.h>
+
+#include "did_impl.h"
+#include "did_props.h"
+
+static did_hash_t *did_hash_create(topo_mod_t *);
+static void did_hash_destroy(did_hash_t *);
+
+int
+did_hash_init(topo_mod_t *hdl)
+{
+	did_hash_t *dh = did_hash_create(hdl);
+
+	if (dh != NULL) {
+		topo_mod_setspecific(hdl, (void *) dh);
+		return (0);
+	} else {
+		return (-1);
+	}
+}
+
+void
+did_hash_fini(topo_mod_t *mod)
+{
+	did_hash_t *dh = (did_hash_t *)topo_mod_getspecific(mod);
+
+	topo_mod_setspecific(mod, NULL);
+	if (dh == NULL)
+		return;
+	did_hash_destroy(dh);
+}
+
+static uint64_t
+did_dnhash(di_node_t key)
+{
+	static uint64_t key_divisor = 0;
+	uint64_t keyn;
+
+	/*
+	 * A bit naughty here, we're aware that a di_info_t is a
+	 * pointer to a struct.  For our hashing, we want use the size
+	 * of that struct, which we determine here, somewhat
+	 * impolitely.
+	 */
+	if (key_divisor == 0)
+		key_divisor = sizeof (*key);
+
+	keyn = (uintptr_t)key;
+
+	return (keyn / key_divisor);
+}
+
+static did_hash_t *
+did_hash_create(topo_mod_t *hdl)
+{
+	did_hash_t *r = topo_mod_zalloc(hdl, sizeof (did_hash_t));
+
+	if (r == NULL) {
+		(void) topo_mod_seterrno(hdl, EMOD_NOMEM);
+		return (NULL);
+	}
+	r->dph_mod = hdl;
+	r->dph_hashlen = REC_HASHLEN;
+	r->dph_hash = topo_mod_zalloc(hdl,
+	    r->dph_hashlen * sizeof (did_t *));
+	if (r->dph_hash == NULL) {
+		topo_mod_free(hdl, r, sizeof (did_hash_t));
+		(void) topo_mod_seterrno(hdl, EMOD_NOMEM);
+		return (NULL);
+	}
+	return (r);
+}
+
+static void
+did_hash_destroy(did_hash_t *ht)
+{
+	did_t *e, *n;
+	int idx;
+
+	if (ht == NULL)
+		return;
+	for (idx = 0; idx < ht->dph_hashlen; idx++) {
+		for (e = ht->dph_hash[idx]; e != NULL; ) {
+			n = e->dp_next;
+			did_destroy(e);
+			e = n;
+		}
+	}
+	topo_mod_free(ht->dph_mod,
+	    ht->dph_hash, ht->dph_hashlen * sizeof (did_t *));
+	topo_mod_free(ht->dph_mod, ht, sizeof (did_hash_t));
+}
+
+void
+did_hash_insert(topo_mod_t *mp, di_node_t key, did_t *new)
+{
+	did_hash_t *tab = (did_hash_t *)topo_mod_getspecific(mp);
+	did_t *assertchk;
+	int idx = did_dnhash(key) % tab->dph_hashlen;
+
+	tab->dph_nelems++;
+	did_hold(new);
+	topo_mod_dprintf(tab->dph_mod, "Insert [key=%p] into %p, bucket %d\n",
+	    key, (void *)tab, idx);
+	if (tab->dph_hash[idx] == NULL) {
+		tab->dph_hash[idx] = new;
+		topo_mod_dprintf(tab->dph_mod, "first entry.\n");
+	} else {
+		/*
+		 * We should not be putting in a duplicate entry
+		 */
+		for (assertchk = tab->dph_hash[idx];
+		    assertchk != NULL;
+		    assertchk = assertchk->dp_next)
+			assert(assertchk->dp_src != key);
+		new->dp_next = tab->dph_hash[idx];
+		tab->dph_hash[idx] = new;
+	}
+}
+
+did_t *
+did_hash_lookup(topo_mod_t *mp, di_node_t key)
+{
+	did_t *e;
+	did_hash_t *tab = (did_hash_t *)topo_mod_getspecific(mp);
+	int idx = did_dnhash(key) % tab->dph_hashlen;
+
+	e = tab->dph_hash[idx];
+	while (e != NULL) {
+		if (e->dp_src == key) {
+			did_hold(e);
+			return (e);
+		}
+		e = e->dp_next;
+	}
+	return (NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/common/pcibus/did_impl.h	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,105 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _DID_IMPL_H
+#define	_DID_IMPL_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/pci.h>
+#include <fm/libtopo.h>
+#include <libdevinfo.h>
+#include <libnvpair.h>
+#include <did.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define	REC_HASHLEN	253
+
+/*
+ * Slot name info is attached to devinfo nodes, compressed inside of
+ * a "slot-names" property.  When we dig this out we store each name
+ * as an FMRI, along with the device number to which it applies.
+ */
+typedef struct slotnm {
+	topo_mod_t *snm_mod;	/* module that allocated the slot name */
+	struct slotnm *snm_next;
+	int snm_dev;	 /* device on the bus that implements the slot */
+	char *snm_label; /* label describing the slot */
+} slotnm_t;
+
+typedef struct did_hash did_hash_t;
+
+/*
+ * Private data stored with a tnode_t.  We collect slot-name info from
+ * di_nodes that describe buses, but then don't use it until we get to
+ * a tnode_t actually describing a function of a device.  We also use
+ * this struct to pass around bus, dev, function info so that doesn't
+ * have to be re-computed.
+ */
+struct did {
+	struct did *dp_next; /* for chaining in a hash bucket */
+	struct did *dp_link; /* for chaining to related did_t */
+	struct did *dp_chain; /* for chaining to another chain of did_ts */
+	did_hash_t *dp_hash; /* the hash table where we reside */
+	topo_mod_t *dp_mod; /* module that allocated the did private data */
+	di_node_t dp_src; /* di_node_t from which the info was derived */
+	int dp_refcnt;	/* multiple nodes allowed to point at a did_t */
+	uint_t dp_excap;	/* PCI-Express capabilities */
+	int dp_physlot;		/* PCI-Express physical slot # */
+	char *dp_physlot_label; /* PCI-Express slot implemented */
+	int dp_class;		/* PCI class */
+	int dp_subclass;	/* PCI subclass */
+	int dp_board;		/* Board number */
+	int dp_bridge;		/* Bridge number */
+	int dp_rc;		/* Root Complex number */
+	int dp_bus;		/* PCI bus number */
+	int dp_dev;		/* PCI device number on the above bus */
+	int dp_fn;		/* PCI function number of the above device */
+	int dp_bdf;		/* PCI "real" bdf */
+	/*
+	 * There may be some slot name info on devinfo node for a bus or
+	 * hostbridge.  We'll copy or reference it for child nodes of that
+	 * bus or hostbridge.
+	 */
+	int dp_nslots;		/* number of slots actually described */
+	slotnm_t *dp_slotnames; /* the slot names as labels */
+};
+
+struct did_hash {
+	did_t **dph_hash;	/* hash bucket array */
+	uint_t dph_hashlen;	/* size of hash bucket array */
+	uint_t dph_nelems;	/* number of elements in the hash */
+	topo_mod_t *dph_mod;	/* module that allocated the hash table */
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DID_IMPL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/common/pcibus/did_props.c	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,704 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <assert.h>
+#include <alloca.h>
+#include <string.h>
+#include <strings.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/pci.h>
+#include <sys/pcie.h>
+#include <sys/fm/protocol.h>
+#include <fm/topo_mod.h>
+#include <fm/topo_hc.h>
+#include <libdevinfo.h>
+
+#include <hostbridge.h>
+#include <pcibus.h>
+#include <did.h>
+#include <did_props.h>
+
+static int ASRU_set(tnode_t *, did_t *,
+    const char *, const char *, const char *);
+static int FRU_set(tnode_t *, did_t *,
+    const char *, const char *, const char *);
+static int DEVprop_set(tnode_t *, did_t *,
+    const char *, const char *, const char *);
+static int DRIVERprop_set(tnode_t *, did_t *,
+    const char *, const char *, const char *);
+static int EXCAP_set(tnode_t *, did_t *,
+    const char *, const char *, const char *);
+static int BDF_set(tnode_t *, did_t *,
+    const char *, const char *, const char *);
+static int label_set(tnode_t *, did_t *,
+    const char *, const char *, const char *);
+static int maybe_di_chars_copy(tnode_t *, did_t *,
+    const char *, const char *, const char *);
+static int maybe_di_uint_to_str(tnode_t *, did_t *,
+    const char *, const char *, const char *);
+
+/*
+ * Arrays of "property translation routines" to set the properties a
+ * given type of topology node should have.
+ *
+ * Note that the label_set translation *MUST COME BEFORE* the FRU
+ * translation.  For the near term we're setting the FRU fmri to
+ * be a legacy-hc style FMRI based on the label, so the label needs
+ * to have been set before we do the FRU translation.
+ *
+ */
+
+static const topo_pgroup_info_t io_pgroup =
+	{ TOPO_PGROUP_IO, TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
+static const topo_pgroup_info_t pci_pgroup =
+	{ TOPO_PGROUP_PCI, TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
+
+static const topo_pgroup_info_t protocol_pgroup = {
+	TOPO_PGROUP_PROTOCOL,
+	TOPO_STABILITY_PRIVATE,
+	TOPO_STABILITY_PRIVATE,
+	1
+}; /* Request to create protocol will be ignored by libtopo */
+
+txprop_t Fn_common_props[] = {
+	{ NULL, &io_pgroup, TOPO_IO_DEV, DEVprop_set },
+	{ DI_DEVTYPPROP, &io_pgroup, TOPO_IO_DEVTYPE, maybe_di_chars_copy },
+	{ DI_DEVIDPROP, &pci_pgroup, TOPO_PCI_DEVID, maybe_di_uint_to_str },
+	{ NULL, &io_pgroup, TOPO_IO_DRIVER, DRIVERprop_set },
+	{ NULL, &pci_pgroup, TOPO_PCI_EXCAP, EXCAP_set },
+	{ DI_CLASSPROP, &pci_pgroup, TOPO_PCI_CLASS, maybe_di_uint_to_str },
+	{ DI_VENDIDPROP, &pci_pgroup, TOPO_PCI_VENDID, maybe_di_uint_to_str },
+	{ NULL, &protocol_pgroup, TOPO_PROP_LABEL, label_set },
+	{ NULL, &protocol_pgroup, TOPO_PROP_FRU, FRU_set },
+	{ NULL, &protocol_pgroup, TOPO_PROP_ASRU, ASRU_set }
+};
+
+txprop_t Dev_common_props[] = {
+	{ NULL, &protocol_pgroup, TOPO_PROP_LABEL, label_set },
+	{ NULL, &protocol_pgroup, TOPO_PROP_FRU, FRU_set },
+	{ NULL, &protocol_pgroup, TOPO_PROP_ASRU, ASRU_set }
+};
+
+txprop_t Bus_common_props[] = {
+	{ DI_DEVTYPPROP, &io_pgroup, TOPO_IO_DEVTYPE, maybe_di_chars_copy },
+	{ NULL, &io_pgroup, TOPO_IO_DRIVER, DRIVERprop_set },
+	{ NULL, &protocol_pgroup, TOPO_PROP_LABEL, label_set },
+	{ NULL, &protocol_pgroup, TOPO_PROP_FRU, FRU_set },
+	{ NULL, &protocol_pgroup, TOPO_PROP_ASRU, ASRU_set }
+};
+
+txprop_t RC_common_props[] = {
+	{ NULL, &io_pgroup, TOPO_IO_DEV, DEVprop_set },
+	{ DI_DEVTYPPROP, &io_pgroup, TOPO_IO_DEVTYPE, maybe_di_chars_copy },
+	{ NULL, &io_pgroup, TOPO_IO_DRIVER, DRIVERprop_set },
+	{ NULL, &pci_pgroup, TOPO_PCI_EXCAP, EXCAP_set },
+	{ NULL, &pci_pgroup, TOPO_PCI_BDF, BDF_set },
+	{ NULL, &protocol_pgroup, TOPO_PROP_LABEL, label_set },
+	{ NULL, &protocol_pgroup, TOPO_PROP_FRU, FRU_set },
+	{ NULL, &protocol_pgroup, TOPO_PROP_ASRU, ASRU_set }
+};
+
+txprop_t ExHB_common_props[] = {
+	{ NULL, &protocol_pgroup, TOPO_PROP_LABEL, label_set },
+	{ NULL, &protocol_pgroup, TOPO_PROP_FRU, FRU_set },
+	{ NULL, &protocol_pgroup, TOPO_PROP_ASRU, ASRU_set }
+};
+
+txprop_t IOB_common_props[] = {
+	{ NULL, &protocol_pgroup, TOPO_PROP_LABEL, label_set },
+	{ NULL, &protocol_pgroup, TOPO_PROP_FRU, FRU_set },
+	{ NULL, &protocol_pgroup, TOPO_PROP_ASRU, ASRU_set }
+};
+
+txprop_t HB_common_props[] = {
+	{ NULL, &io_pgroup, TOPO_IO_DEV, DEVprop_set },
+	{ NULL, &io_pgroup, TOPO_IO_DRIVER, DRIVERprop_set },
+	{ NULL, &protocol_pgroup, TOPO_PROP_LABEL, label_set },
+	{ NULL, &protocol_pgroup, TOPO_PROP_FRU, FRU_set },
+	{ NULL, &protocol_pgroup, TOPO_PROP_ASRU, ASRU_set }
+};
+
+int Bus_propcnt = sizeof (Bus_common_props) / sizeof (txprop_t);
+int Dev_propcnt = sizeof (Dev_common_props) / sizeof (txprop_t);
+int ExHB_propcnt = sizeof (ExHB_common_props) / sizeof (txprop_t);
+int HB_propcnt = sizeof (HB_common_props) / sizeof (txprop_t);
+int IOB_propcnt = sizeof (IOB_common_props) / sizeof (txprop_t);
+int RC_propcnt = sizeof (RC_common_props) / sizeof (txprop_t);
+int Fn_propcnt = sizeof (Fn_common_props) / sizeof (txprop_t);
+
+/*
+ * If this devinfo node came originally from OBP data, we'll have prom
+ * properties associated with the node where we can find properties of
+ * interest.  We ignore anything after the the first four bytes of the
+ * property, and interpet those first four bytes as our unsigned
+ * integer.  If we don't find the property or it's not large enough,
+ * 'val' will remained unchanged and we'll return -1.  Otherwise 'val'
+ * gets updated with the property value and we return 0.
+ */
+static int
+promprop2uint(topo_mod_t *mod, di_node_t n, const char *propnm, uint_t *val)
+{
+	di_prom_handle_t ptp = DI_PROM_HANDLE_NIL;
+	di_prom_prop_t pp = DI_PROM_PROP_NIL;
+	uchar_t *buf;
+
+	if ((ptp = topo_mod_prominfo(mod)) == DI_PROM_HANDLE_NIL)
+		return (-1);
+
+	while ((pp = di_prom_prop_next(ptp, n, pp)) != DI_PROM_PROP_NIL) {
+		if (strcmp(di_prom_prop_name(pp), propnm) == 0) {
+			if (di_prom_prop_data(pp, &buf) < sizeof (uint_t))
+				continue;
+			bcopy(buf, val, sizeof (uint_t));
+			return (0);
+		}
+	}
+	return (-1);
+}
+
+/*
+ * If this devinfo node was added by the PCI hotplug framework it
+ * doesn't have the PROM properties, but hopefully has the properties
+ * we're looking for attached directly to the devinfo node.  We only
+ * care about the first four bytes of the property, which we read as
+ * our unsigned integer.  The remaining bytes are ignored.  If we
+ * don't find the property we're looking for, or can't get its value,
+ * 'val' remains unchanged and we return -1.  Otherwise 'val' gets the
+ * property value and we return 0.
+ */
+static int
+hwprop2uint(di_node_t n, const char *propnm, uint_t *val)
+{
+	di_prop_t hp = DI_PROP_NIL;
+	uchar_t *buf;
+
+	while ((hp = di_prop_next(n, hp)) != DI_PROP_NIL) {
+		if (strcmp(di_prop_name(hp), propnm) == 0) {
+			if (di_prop_bytes(hp, &buf) < sizeof (uint_t))
+				continue;
+			bcopy(buf, val, sizeof (uint_t));
+			return (0);
+		}
+	}
+	return (-1);
+}
+
+int
+di_uintprop_get(topo_mod_t *mod, di_node_t n, const char *pnm, uint_t *pv)
+{
+	if (hwprop2uint(n, pnm, pv) < 0)
+		if (promprop2uint(mod, n, pnm, pv) < 0)
+			return (-1);
+	return (0);
+}
+
+int
+di_bytes_get(topo_mod_t *mod, di_node_t n, const char *pnm, int *sz,
+    uchar_t **db)
+{
+	di_prom_handle_t ptp = DI_PROM_HANDLE_NIL;
+	di_prom_prop_t pp = DI_PROM_PROP_NIL;
+	di_prop_t hp = DI_PROP_NIL;
+
+	if ((ptp = topo_mod_prominfo(mod)) == DI_PROM_HANDLE_NIL)
+		return (-1);
+
+	*sz = -1;
+	while ((hp = di_prop_next(n, hp)) != DI_PROP_NIL) {
+		if (strcmp(di_prop_name(hp), pnm) == 0) {
+			if ((*sz = di_prop_bytes(hp, db)) < 0)
+				continue;
+			break;
+		}
+	}
+	if (*sz < 0) {
+		while ((pp = di_prom_prop_next(ptp, n, pp)) !=
+		    DI_PROM_PROP_NIL) {
+			if (strcmp(di_prom_prop_name(pp), pnm) == 0) {
+				*sz = di_prom_prop_data(pp, db);
+				if (*sz < 0)
+					continue;
+				break;
+			}
+		}
+	}
+
+	if (*sz < 0)
+		return (-1);
+	return (0);
+}
+
+/*
+ * fix_dev_prop -- sometimes di_devfs_path() doesn't tell the whole
+ * story, leaving off the device and function number.  Chances are if
+ * devfs doesn't put these on then we'll never see this device as an
+ * error detector called out in an ereport.  Unfortunately, there are
+ * races and we sometimes do get ereports from devices that devfs
+ * decides aren't there.  For example, the error injector card seems
+ * to bounce in and out of existence according to devfs.  We tack on
+ * the missing dev and fn here so that the DEV property used to look
+ * up the topology node is correct.
+ */
+static char *
+dev_path_fix(topo_mod_t *mp, char *path, int devno, int fnno)
+{
+	char *lastslash;
+	char *newpath;
+	int need;
+
+	/*
+	 * We only care about the last component of the dev path. If
+	 * we don't find a slash, something is weird.
+	 */
+	lastslash = strrchr(path, '/');
+	assert(lastslash != NULL);
+
+	/*
+	 * If an @ sign is present in the last component, the
+	 * di_devfs_path() result had the device,fn unit-address.
+	 * In that case there's nothing we need do.
+	 */
+	if (strchr(lastslash, '@') != NULL)
+		return (path);
+
+	if (fnno == 0)
+		need = snprintf(NULL, 0, "%s@%x", path, devno);
+	else
+		need = snprintf(NULL, 0, "%s@%x,%x", path, devno, fnno);
+	need++;
+
+	if ((newpath = topo_mod_alloc(mp, need)) == NULL) {
+		topo_mod_strfree(mp, path);
+		return (NULL);
+	}
+
+	if (fnno == 0)
+		(void) snprintf(newpath, need, "%s@%x", path, devno);
+	else
+		(void) snprintf(newpath, need, "%s@%x,%x", path, devno, fnno);
+
+	topo_mod_strfree(mp, path);
+	return (newpath);
+}
+
+/*
+ * dev_for_hostbridge() -- For hostbridges we truncate the devfs path
+ * after the first element in the bus address.
+ */
+static char *
+dev_for_hostbridge(topo_mod_t *mp, char *path)
+{
+	char *lastslash;
+	char *newpath;
+	char *comma;
+
+	/*
+	 * We only care about the last component of the dev path. If
+	 * we don't find a slash, something is weird.
+	 */
+	lastslash = strrchr(path, '/');
+	assert(lastslash != NULL);
+
+	/*
+	 * Find the comma in the last component component@x,y, and
+	 * truncate the comma and any following number.
+	 */
+	comma = strchr(lastslash, ',');
+	assert(comma != NULL);
+
+	*comma = '\0';
+	if ((newpath = topo_mod_strdup(mp, path)) == NULL)
+		return (path);
+	*comma = ',';
+	topo_mod_strfree(mp, path);
+	return (newpath);
+}
+
+/*ARGSUSED*/
+static int
+ASRU_set(tnode_t *tn, did_t *pd,
+    const char *dpnm, const char *tpgrp, const char *tpnm)
+{
+	topo_mod_t *mp;
+	nvlist_t *fmri;
+	char *dnpath, *path, *fpath, *nm;
+	int d, e, f;
+
+	/*
+	 * If this topology node represents a function of device,
+	 * set the ASRU to a dev scheme FMRI based on the value of
+	 * di_devfs_path().  If that path is NULL, set the ASRU to
+	 * be the resource describing this topology node.  If this
+	 * isn't a function, inherit any ASRU from the parent.
+	 */
+	mp = did_mod(pd);
+	nm = topo_node_name(tn);
+	if (strcmp(nm, PCI_FUNCTION) == 0 || strcmp(nm, PCIEX_FUNCTION) == 0 ||
+	    strcmp(nm, PCIEX_ROOT) == 0) {
+		if ((dnpath = di_devfs_path(did_dinode(pd))) != NULL) {
+			/*
+			 * Dup the path, dev_path_fix() may replace it and
+			 * dev_path_fix() wouldn't know to use
+			 * di_devfs_path_free()
+			 */
+			if ((path = topo_mod_strdup(mp, dnpath)) == NULL) {
+				di_devfs_path_free(dnpath);
+				return (topo_mod_seterrno(mp, EMOD_NOMEM));
+			}
+			di_devfs_path_free(dnpath);
+			did_BDF(pd, NULL, &d, &f);
+			if ((fpath = dev_path_fix(mp, path, d, f)) == NULL)
+				return (topo_mod_seterrno(mp, EMOD_NOMEM));
+
+			fmri = topo_mod_devfmri(mp, FM_DEV_SCHEME_VERSION,
+			    fpath, NULL);
+			if (fmri == NULL) {
+				topo_mod_dprintf(mp,
+				    "dev:///%s fmri creation failed.\n", fpath);
+				topo_mod_strfree(mp, fpath);
+				return (-1);
+			}
+			topo_mod_strfree(mp, fpath);
+		} else {
+			topo_mod_dprintf(mp, "NULL di_devfs_path.\n");
+			if (topo_prop_get_fmri(tn, TOPO_PGROUP_PROTOCOL,
+			    TOPO_PROP_RESOURCE, &fmri, &e) < 0)
+				return (topo_mod_seterrno(mp, e));
+		}
+		if (topo_node_asru_set(tn, fmri, 0, &e) < 0) {
+			nvlist_free(fmri);
+			return (topo_mod_seterrno(mp, e));
+		}
+		nvlist_free(fmri);
+		return (0);
+	}
+	(void) topo_node_asru_set(tn, NULL, 0, &e);
+
+	return (0);
+}
+
+/*
+ * Hopefully this hack routine goes away when fmdump can print the labels.
+ */
+static int
+FRU_fmri_hack(topo_mod_t *mp, tnode_t *tn, const char *label)
+{
+	char buf[PATH_MAX];
+	nvlist_t *fmri;
+	int err, e;
+
+
+	(void) snprintf(buf, PATH_MAX, "hc:///component=%s", label);
+	if (topo_mod_str2nvl(mp, buf, &fmri) < 0)
+		return (-1);
+
+	e = topo_node_fru_set(tn, fmri, 0, &err);
+	nvlist_free(fmri);
+	if (e < 0)
+		return (topo_mod_seterrno(mp, err));
+	return (0);
+}
+
+/*ARGSUSED*/
+static int
+FRU_set(tnode_t *tn, did_t *pd,
+    const char *dpnm, const char *tpgrp, const char *tpnm)
+{
+	topo_mod_t *mp;
+	char *label, *nm;
+	int e;
+
+	nm = topo_node_name(tn);
+	mp = did_mod(pd);
+
+	/*
+	 * If this topology node represents something other than an
+	 * ioboard or a device that implements a slot, inherit the
+	 * parent's FRU value.  If there is no label, inherit our
+	 * parent's FRU value.  Otherwise, munge up an fmri based on
+	 * the label.
+	 */
+	if (strcmp(nm, "ioboard") != 0 && strcmp(nm, PCI_DEVICE) != 0 &&
+	    strcmp(nm, PCIEX_DEVICE) != 0) {
+		(void) topo_node_fru_set(tn, NULL, 0, &e);
+		return (0);
+	}
+
+	if (topo_prop_get_string(tn,
+	    TOPO_PGROUP_PROTOCOL, TOPO_PROP_LABEL, &label, &e) < 0) {
+		if (e != ETOPO_PROP_NOENT)
+			return (topo_mod_seterrno(mp, e));
+		(void) topo_node_fru_set(tn, NULL, 0, &e);
+		return (0);
+	}
+	e = FRU_fmri_hack(mp, tn, label);
+	topo_mod_strfree(mp, label);
+	return (e);
+}
+
+/*ARGSUSED*/
+static int
+label_set(tnode_t *tn, did_t *pd,
+    const char *dpnm, const char *tpgrp, const char *tpnm)
+{
+	topo_mod_t *mp;
+	nvlist_t *in, *out;
+	char *label;
+	int err;
+
+	mp = did_mod(pd);
+	if (topo_mod_nvalloc(mp, &in, NV_UNIQUE_NAME) != 0)
+		return (topo_mod_seterrno(mp, EMOD_FMRI_NVL));
+	if (nvlist_add_uint64(in, TOPO_METH_LABEL_ARG_NVL, (uintptr_t)pd) !=
+	    0) {
+		nvlist_free(in);
+		return (topo_mod_seterrno(mp, EMOD_NOMEM));
+	}
+	if (topo_method_invoke(tn,
+	    TOPO_METH_LABEL, TOPO_METH_LABEL_VERSION, in, &out, &err) != 0) {
+		nvlist_free(in);
+		return (topo_mod_seterrno(mp, err));
+	}
+	nvlist_free(in);
+	if (out != NULL &&
+	    nvlist_lookup_string(out, TOPO_METH_LABEL_RET_STR, &label) == 0) {
+		if (topo_prop_set_string(tn, TOPO_PGROUP_PROTOCOL,
+		    TOPO_PROP_LABEL, TOPO_PROP_IMMUTABLE, label, &err) != 0) {
+			nvlist_free(out);
+			return (topo_mod_seterrno(mp, err));
+		}
+		nvlist_free(out);
+	}
+	return (0);
+}
+
+/*ARGSUSED*/
+static int
+EXCAP_set(tnode_t *tn, did_t *pd,
+    const char *dpnm, const char *tpgrp, const char *tpnm)
+{
+	int excap;
+	int err;
+	int e = 0;
+
+	if ((excap = did_excap(pd)) <= 0)
+		return (0);
+
+	switch (excap & PCIE_PCIECAP_DEV_TYPE_MASK) {
+	case PCIE_PCIECAP_DEV_TYPE_ROOT:
+		e = topo_prop_set_string(tn, TOPO_PGROUP_PCI,
+		    TOPO_PCI_EXCAP, TOPO_PROP_IMMUTABLE, PCIEX_ROOT, &err);
+		break;
+	case PCIE_PCIECAP_DEV_TYPE_UP:
+		e = topo_prop_set_string(tn, TOPO_PGROUP_PCI,
+		    TOPO_PCI_EXCAP, TOPO_PROP_IMMUTABLE, PCIEX_SWUP, &err);
+		break;
+	case PCIE_PCIECAP_DEV_TYPE_DOWN:
+		e = topo_prop_set_string(tn, TOPO_PGROUP_PCI,
+		    TOPO_PCI_EXCAP, TOPO_PROP_IMMUTABLE, PCIEX_SWDWN, &err);
+		break;
+	case PCIE_PCIECAP_DEV_TYPE_PCI2PCIE:
+		e = topo_prop_set_string(tn, TOPO_PGROUP_PCI,
+		    TOPO_PCI_EXCAP, TOPO_PROP_IMMUTABLE, PCIEX_BUS, &err);
+		break;
+	case PCIE_PCIECAP_DEV_TYPE_PCIE2PCI:
+		e = topo_prop_set_string(tn, TOPO_PGROUP_PCI,
+		    TOPO_PCI_EXCAP, TOPO_PROP_IMMUTABLE, PCI_BUS, &err);
+		break;
+	case PCIE_PCIECAP_DEV_TYPE_PCIE_DEV:
+		e = topo_prop_set_string(tn, TOPO_PGROUP_PCI,
+		    TOPO_PCI_EXCAP, TOPO_PROP_IMMUTABLE, PCIEX_DEVICE, &err);
+		break;
+	}
+	if (e != 0)
+		return (topo_mod_seterrno(did_mod(pd), err));
+	return (0);
+}
+
+/*ARGSUSED*/
+static int
+DEVprop_set(tnode_t *tn, did_t *pd,
+    const char *dpnm, const char *tpgrp, const char *tpnm)
+{
+	topo_mod_t *mp;
+	char *dnpath;
+	char *path, *fpath;
+	int d, f;
+	int err, e;
+
+	mp = did_mod(pd);
+	if ((dnpath = di_devfs_path(did_dinode(pd))) == NULL) {
+		topo_mod_dprintf(mp, "NULL di_devfs_path.\n");
+		return (topo_mod_seterrno(mp, ETOPO_PROP_NOENT));
+	}
+	if ((path = topo_mod_strdup(mp, dnpath)) == NULL) {
+		di_devfs_path_free(dnpath);
+		return (-1);
+	}
+	di_devfs_path_free(dnpath);
+
+	/* The DEV path is modified for hostbridges */
+	if (strcmp(topo_node_name(tn), HOSTBRIDGE) == 0) {
+		fpath = dev_for_hostbridge(did_mod(pd), path);
+	} else {
+		did_BDF(pd, NULL, &d, &f);
+		fpath = dev_path_fix(mp, path, d, f);
+	}
+	if (fpath == NULL)
+		return (-1);
+	e = topo_prop_set_string(tn,
+	    tpgrp, tpnm, TOPO_PROP_IMMUTABLE, fpath, &err);
+	topo_mod_strfree(mp, fpath);
+	if (e != 0)
+		return (topo_mod_seterrno(mp, err));
+	return (0);
+}
+
+/*ARGSUSED*/
+static int
+DRIVERprop_set(tnode_t *tn, did_t *pd,
+    const char *dpnm, const char *tpgrp, const char *tpnm)
+{
+	char *dnm;
+	int err;
+
+	if ((dnm = di_driver_name(did_dinode(pd))) == NULL)
+		return (0);
+	if (topo_prop_set_string(tn,
+	    tpgrp, tpnm, TOPO_PROP_IMMUTABLE, dnm, &err) < 0)
+		return (topo_mod_seterrno(did_mod(pd), err));
+
+	return (0);
+}
+
+/*ARGSUSED*/
+static int
+maybe_di_chars_copy(tnode_t *tn, did_t *pd,
+    const char *dpnm, const char *tpgrp, const char *tpnm)
+{
+	topo_mod_t *mp;
+	uchar_t *typbuf;
+	char *tmpbuf;
+	int sz = -1;
+	int err, e;
+
+	if (di_bytes_get(did_mod(pd), did_dinode(pd), dpnm, &sz, &typbuf) < 0)
+		return (0);
+	mp = did_mod(pd);
+	tmpbuf = topo_mod_alloc(mp, sz + 1);
+	bcopy(typbuf, tmpbuf, sz);
+	tmpbuf[sz] = 0;
+	e = topo_prop_set_string(tn,
+	    tpgrp, tpnm, TOPO_PROP_IMMUTABLE, tmpbuf, &err);
+	topo_mod_free(mp, tmpbuf, sz + 1);
+	if (e != 0)
+		return (topo_mod_seterrno(mp, err));
+	return (0);
+}
+
+static int
+uint_to_strprop(topo_mod_t *mp, uint_t v, tnode_t *tn,
+    const char *tpgrp, const char *tpnm)
+{
+	char str[21]; /* sizeof (UINT64_MAX) + '\0' */
+	int e;
+
+	(void) snprintf(str, 21, "%x", v);
+	if (topo_prop_set_string(tn,
+	    tpgrp, tpnm, TOPO_PROP_IMMUTABLE, str, &e) < 0)
+		return (topo_mod_seterrno(mp, e));
+	return (0);
+}
+
+static int
+maybe_di_uint_to_str(tnode_t *tn, did_t *pd,
+    const char *dpnm, const char *tpgrp, const char *tpnm)
+{
+	uint_t v;
+
+	if (di_uintprop_get(did_mod(pd), did_dinode(pd), dpnm, &v) < 0)
+		return (0);
+
+	return (uint_to_strprop(did_mod(pd), v, tn, tpgrp, tpnm));
+}
+
+/*ARGSUSED*/
+static int
+BDF_set(tnode_t *tn, did_t *pd, const char *dpnm, const char *tpgrp,
+    const char *tpnm)
+{
+	int bdf;
+	char str[23]; /* '0x' + sizeof (UINT64_MAX) + '\0' */
+	int e;
+
+	if ((bdf = did_bdf(pd)) <= 0)
+		return (0);
+
+	(void) snprintf(str, 23, "0x%x", bdf);
+	if (topo_prop_set_string(tn,
+	    tpgrp, tpnm, TOPO_PROP_IMMUTABLE, str, &e) < 0)
+		return (topo_mod_seterrno(did_mod(pd), e));
+	return (0);
+}
+
+int
+did_props_set(tnode_t *tn, did_t *pd, txprop_t txarray[], int txnum)
+{
+	topo_mod_t *mp;
+	int i, r, e;
+
+	mp = did_mod(pd);
+	for (i = 0; i < txnum; i++) {
+		/*
+		 * Ensure the property group has been created.
+		 */
+		if (txarray[i].tx_tpgroup != NULL) {
+			if (topo_pgroup_create(tn, txarray[i].tx_tpgroup, &e)
+			    < 0) {
+				if (e != ETOPO_PROP_DEFD)
+					return (topo_mod_seterrno(mp, e));
+			}
+		}
+
+		topo_mod_dprintf(mp,
+		    "Setting property %s in group %s.\n",
+		    txarray[i].tx_tprop, txarray[i].tx_tpgroup->tpi_name);
+		r = txarray[i].tx_xlate(tn, pd,
+		    txarray[i].tx_diprop, txarray[i].tx_tpgroup->tpi_name,
+		    txarray[i].tx_tprop);
+		if (r != 0) {
+			topo_mod_dprintf(mp, "failed.\n");
+			topo_mod_dprintf(mp, "Error was %s.\n",
+			    topo_strerror(topo_mod_errno(mp)));
+			return (-1);
+		}
+		topo_mod_dprintf(mp, "succeeded.\n");
+	}
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/common/pcibus/did_props.h	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,87 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _DID_PROPS_H
+#define	_DID_PROPS_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/pci.h>
+#include <fm/topo_mod.h>
+#include <libdevinfo.h>
+#include <libnvpair.h>
+
+#include <did.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * pci_props_set() processes an array of structures that translate
+ * from devinfo props to properties on topology nodes.  The structure
+ * provides the name of a devinfo prop, the name of the property
+ * group, the name of the property and the stability of the property
+ * group that should be established on the topology node, as well as a
+ * function to do the work.
+ */
+typedef struct txprop {
+	const char *tx_diprop;	/* property examined off the di_node_t */
+	const topo_pgroup_info_t *tx_tpgroup; /* pgroup defined for tnode_t */
+	const char *tx_tprop;	/* property defined on the tnode_t */
+	/*
+	 * translation function
+	 *	If NULL, the devinfo prop's value is copied to the
+	 *	topo property.
+	 */
+	int (*tx_xlate)(tnode_t *, did_t *,
+	    const char *, const char *, const char *);
+} txprop_t;
+
+#define	DI_DEVTYPPROP	"device_type"
+#define	DI_VENDIDPROP	"vendor-id"
+#define	DI_DEVIDPROP	"device-id"
+#define	DI_CLASSPROP	"class-code"
+#define	DI_REGPROP	"reg"
+#define	DI_CCPROP	"class-code"
+#define	DI_PHYSPROP	"physical-slot#"
+#define	DI_SLOTPROP	"slot-names"
+
+extern int did_props_set(tnode_t *, did_t *, txprop_t[], int);
+
+extern int pciex_cap_get(topo_mod_t *, di_node_t);
+extern int pci_BDF_get(topo_mod_t *, di_node_t, int *, int *, int *);
+extern int pci_classcode_get(topo_mod_t *, di_node_t, uint_t *, uint_t *);
+
+extern int di_uintprop_get(topo_mod_t *, di_node_t, const char *, uint_t *);
+extern int di_bytes_get(topo_mod_t *, di_node_t, const char *, int *,
+    uchar_t **);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DID_PROPS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/common/pcibus/pcibus.c	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,590 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/fm/protocol.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <alloca.h>
+#include <sys/param.h>
+#include <sys/pci.h>
+#include <sys/pcie.h>
+#include <libdevinfo.h>
+#include <libnvpair.h>
+#include <fm/topo_mod.h>
+#include <fm/topo_hc.h>
+
+#include <hostbridge.h>
+#include <pcibus.h>
+#include <did.h>
+#include <did_props.h>
+#include <util.h>
+
+extern txprop_t Bus_common_props[];
+extern txprop_t Dev_common_props[];
+extern txprop_t Fn_common_props[];
+extern int Bus_propcnt;
+extern int Dev_propcnt;
+extern int Fn_propcnt;
+
+extern int platform_pci_label(topo_mod_t *mod, tnode_t *, nvlist_t *,
+    nvlist_t **);
+
+static void pci_release(topo_mod_t *, tnode_t *);
+static int pci_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t,
+    topo_instance_t, void *, void *);
+static int pci_label(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
+    nvlist_t **);
+
+static const topo_modops_t Pci_ops =
+	{ pci_enum, pci_release };
+static const topo_modinfo_t Pci_info =
+	{ PCI_BUS, FM_FMRI_SCHEME_HC, PCI_ENUMR_VERS, &Pci_ops };
+
+static const topo_method_t Pci_methods[] = {
+	{ TOPO_METH_LABEL, TOPO_METH_LABEL_DESC,
+	    TOPO_METH_LABEL_VERSION, TOPO_STABILITY_INTERNAL, pci_label },
+	{ NULL }
+};
+
+int
+_topo_init(topo_mod_t *modhdl, topo_version_t version)
+{
+	/*
+	 * Turn on module debugging output
+	 */
+	if (getenv("TOPOPCIDBG") != NULL)
+		topo_mod_setdebug(modhdl);
+	topo_mod_dprintf(modhdl, "initializing pcibus builtin\n");
+
+	if (version != PCI_ENUMR_VERS)
+		return (topo_mod_seterrno(modhdl, EMOD_VER_NEW));
+
+	topo_mod_register(modhdl, &Pci_info, TOPO_VERSION);
+	topo_mod_dprintf(modhdl, "PCI Enumr initd\n");
+
+	return (0);
+}
+
+void
+_topo_fini(topo_mod_t *modhdl)
+{
+	topo_mod_unregister(modhdl);
+}
+
+static int
+pci_label(topo_mod_t *mp, tnode_t *node, topo_version_t version,
+    nvlist_t *in, nvlist_t **out)
+{
+	if (version > TOPO_METH_LABEL_VERSION)
+		return (topo_mod_seterrno(mp, EMOD_VER_NEW));
+	return (platform_pci_label(mp, node, in, out));
+}
+
+static tnode_t *
+pci_tnode_create(topo_mod_t *mod, tnode_t *parent,
+    const char *name, topo_instance_t i, void *priv)
+{
+	tnode_t *ntn;
+
+	if ((ntn = tnode_create(mod, parent, name, i, priv)) == NULL)
+		return (NULL);
+	if (topo_method_register(mod, ntn, Pci_methods) < 0) {
+		topo_mod_dprintf(mod, "topo_method_register failed: %s\n",
+		    topo_strerror(topo_mod_errno(mod)));
+		topo_node_unbind(ntn);
+		return (NULL);
+	}
+	return (ntn);
+}
+
+/*ARGSUSED*/
+static int
+hostbridge_asdevice(topo_mod_t *mod, tnode_t *bus)
+{
+	di_node_t di;
+	tnode_t *dev32;
+
+	di = topo_node_getspecific(bus);
+	assert(di != DI_NODE_NIL);
+
+	if ((dev32 = pcidev_declare(mod, bus, di, 32)) == NULL)
+		return (-1);
+	if (pcifn_declare(mod, dev32, di, 0) == NULL)
+		return (-1);
+	return (0);
+}
+
+tnode_t *
+pciexfn_declare(topo_mod_t *mod, tnode_t *parent, di_node_t dn,
+    topo_instance_t i)
+{
+	did_t *pd;
+	tnode_t *ntn;
+
+	if ((pd = did_find(mod, dn)) == NULL)
+		return (NULL);
+	if ((ntn = pci_tnode_create(mod, parent, PCIEX_FUNCTION, i, dn))
+	    == NULL)
+		return (NULL);
+	if (did_props_set(ntn, pd, Fn_common_props, Fn_propcnt) < 0) {
+		topo_node_unbind(ntn);
+		return (NULL);
+	}
+	/*
+	 * We may find pci-express buses or plain-pci buses beneath a function
+	 */
+	if (child_range_add(mod, ntn, PCIEX_BUS, 0, MAX_HB_BUSES) < 0) {
+		topo_node_range_destroy(ntn, PCIEX_BUS);
+		return (NULL);
+	}
+	if (child_range_add(mod, ntn, PCI_BUS, 0, MAX_HB_BUSES) < 0) {
+		topo_node_range_destroy(ntn, PCI_BUS);
+		return (NULL);
+	}
+	return (ntn);
+}
+
+tnode_t *
+pciexdev_declare(topo_mod_t *mod, tnode_t *parent, di_node_t dn,
+    topo_instance_t i)
+{
+	did_t *pd;
+	tnode_t *ntn;
+
+	if ((pd = did_find(mod, dn)) == NULL)
+		return (NULL);
+	if ((ntn = pci_tnode_create(mod, parent, PCIEX_DEVICE, i, dn)) == NULL)
+		return (NULL);
+	if (did_props_set(ntn, pd, Dev_common_props, Dev_propcnt) < 0) {
+		topo_node_unbind(ntn);
+		return (NULL);
+	}
+
+	/*
+	 * We can expect to find pci-express functions beneath the device
+	 */
+	if (child_range_add(mod,
+	    ntn, PCIEX_FUNCTION, 0, MAX_PCIDEV_FNS) < 0) {
+		topo_node_range_destroy(ntn, PCIEX_FUNCTION);
+		return (NULL);
+	}
+	return (ntn);
+}
+
+tnode_t *
+pciexbus_declare(topo_mod_t *mod, tnode_t *parent, di_node_t dn,
+    topo_instance_t i)
+{
+	did_t *pd;
+	tnode_t *ntn;
+
+	if ((pd = did_find(mod, dn)) == NULL)
+		return (NULL);
+	if ((ntn = pci_tnode_create(mod, parent, PCIEX_BUS, i, dn)) == NULL)
+		return (NULL);
+	if (did_props_set(ntn, pd, Bus_common_props, Bus_propcnt) < 0) {
+		topo_node_range_destroy(ntn, PCI_DEVICE);
+		topo_node_unbind(ntn);
+		return (NULL);
+	}
+	/*
+	 * We can expect to find pci-express devices beneath the bus
+	 */
+	if (child_range_add(mod,
+	    ntn, PCIEX_DEVICE, 0, MAX_PCIBUS_DEVS) < 0) {
+		topo_node_range_destroy(ntn, PCIEX_DEVICE);
+		return (NULL);
+	}
+	return (ntn);
+}
+
+tnode_t *
+pcifn_declare(topo_mod_t *mod, tnode_t *parent, di_node_t dn,
+    topo_instance_t i)
+{
+	did_t *pd;
+	tnode_t *ntn;
+
+	if ((pd = did_find(mod, dn)) == NULL)
+		return (NULL);
+	if ((ntn = pci_tnode_create(mod, parent, PCI_FUNCTION, i, dn)) == NULL)
+		return (NULL);
+	if (did_props_set(ntn, pd, Fn_common_props, Fn_propcnt) < 0) {
+		topo_node_unbind(ntn);
+		return (NULL);
+	}
+	/*
+	 * We may find pci buses beneath a function
+	 */
+	if (child_range_add(mod, ntn, PCI_BUS, 0, MAX_HB_BUSES) < 0) {
+		topo_node_unbind(ntn);
+		return (NULL);
+	}
+	return (ntn);
+}
+
+tnode_t *
+pcidev_declare(topo_mod_t *mod, tnode_t *parent, di_node_t dn,
+    topo_instance_t i)
+{
+	did_t *pd;
+	did_t *ppd;
+	di_node_t pdn;
+	tnode_t *ntn;
+
+	if ((pdn = topo_node_getspecific(parent)) == DI_NODE_NIL)
+		return (NULL);
+	if ((ppd = did_find(mod, pdn)) == NULL)
+		return (NULL);
+	if ((pd = did_find(mod, dn)) == NULL)
+		return (NULL);
+	if ((ntn = pci_tnode_create(mod, parent, PCI_DEVICE, i, dn)) == NULL)
+		return (NULL);
+	/*
+	 * If our devinfo node is lacking certain information of its
+	 * own, we may need/want to inherit the information available
+	 * from our parent node's private data.
+	 */
+	did_inherit(ppd, pd);
+	if (did_props_set(ntn, pd, Dev_common_props, Dev_propcnt) < 0) {
+		topo_node_unbind(ntn);
+		return (NULL);
+	}
+
+	/*
+	 * We can expect to find pci functions beneath the device
+	 */
+	if (child_range_add(mod, ntn, PCI_FUNCTION, 0, MAX_PCIDEV_FNS) < 0) {
+		topo_node_range_destroy(ntn, PCI_FUNCTION);
+		topo_node_unbind(ntn);
+		return (NULL);
+	}
+	return (ntn);
+}
+
+tnode_t *
+pcibus_declare(topo_mod_t *mod, tnode_t *parent, di_node_t dn,
+    topo_instance_t i)
+{
+	did_t *pd;
+	tnode_t *ntn;
+	int hbchild = 0;
+
+	if ((pd = did_find(mod, dn)) == NULL)
+		return (NULL);
+	if ((ntn = pci_tnode_create(mod, parent, PCI_BUS, i, dn)) == NULL)
+		return (NULL);
+	/*
+	 * If our devinfo node is lacking certain information of its
+	 * own, and our parent topology node is a hostbridge, we may
+	 * need/want to inherit information available in the
+	 * hostbridge node's private data.
+	 */
+	if (strcmp(topo_node_name(parent), HOSTBRIDGE) == 0)
+		hbchild = 1;
+	if (did_props_set(ntn, pd, Bus_common_props, Bus_propcnt) < 0) {
+		topo_node_unbind(ntn);
+		return (NULL);
+	}
+	/*
+	 * We can expect to find pci devices beneath the bus
+	 */
+	if (child_range_add(mod, ntn, PCI_DEVICE, 0, MAX_PCIBUS_DEVS) < 0) {
+		topo_node_unbind(ntn);
+		return (NULL);
+	}
+	/*
+	 * On each bus child of the hostbridge, we represent the
+	 * hostbridge as a device outside the range of legal device
+	 * numbers.
+	 */
+	if (hbchild == 1) {
+		if (hostbridge_asdevice(mod, ntn) < 0) {
+			topo_node_range_destroy(ntn, PCI_DEVICE);
+			topo_node_unbind(ntn);
+			return (NULL);
+		}
+	}
+	return (ntn);
+}
+
+static int
+pci_bridge_declare(topo_mod_t *mod, tnode_t *fn, di_node_t din, int board,
+    int bridge, int rc, int depth)
+{
+	int err, excap, extyp;
+
+	excap = pciex_cap_get(mod, din);
+	extyp = excap & PCIE_PCIECAP_DEV_TYPE_MASK;
+	if (excap <= 0 ||
+	    extyp != PCIE_PCIECAP_DEV_TYPE_PCIE2PCI)
+		err = pci_children_instantiate(mod, fn, din, board, bridge,
+		    rc, TRUST_BDF, depth + 1);
+	else
+		err = pci_children_instantiate(mod, fn, din, board, bridge,
+		    rc - TO_PCI, TRUST_BDF, depth + 1);
+	return (err);
+}
+
+static int
+declare_dev_and_fn(topo_mod_t *mod, tnode_t *bus, tnode_t **dev, di_node_t din,
+    int board, int bridge, int rc, int devno, int fnno, int depth)
+{
+	int err = 0;
+	tnode_t *fn;
+	uint_t class, subclass;
+
+	if (*dev == NULL) {
+		if (rc >= 0)
+			*dev = pciexdev_declare(mod, bus, din, devno);
+		else
+			*dev = pcidev_declare(mod, bus, din, devno);
+		if (*dev == NULL)
+			return (-1);
+	}
+	if (rc >= 0)
+		fn = pciexfn_declare(mod, *dev, din, fnno);
+	else
+		fn = pcifn_declare(mod, *dev, din, fnno);
+	if (fn == NULL)
+		return (-1);
+	if (pci_classcode_get(mod, din, &class, &subclass) < 0)
+		return (-1);
+
+	/*
+	 * This function may be a bridge.  If not, check for a possible
+	 * topology map file and kick off its enumeration of lower-level
+	 * devices.
+	 */
+	if (class == PCI_CLASS_BRIDGE && subclass == PCI_BRIDGE_PCI)
+		err = pci_bridge_declare(mod, fn, din, board, bridge, rc,
+		    depth);
+	else if (class == PCI_CLASS_MASS)
+		(void) topo_mod_enummap(mod, fn, "storage", FM_FMRI_SCHEME_HC);
+
+	return (err);
+}
+
+int
+pci_children_instantiate(topo_mod_t *mod, tnode_t *parent, di_node_t pn,
+    int board, int bridge, int rc, int bover, int depth)
+{
+	did_t *pps[MAX_PCIBUS_DEVS][MAX_PCIDEV_FNS];
+	did_t *bp = NULL;
+	did_t *np;
+	di_node_t sib;
+	di_node_t din;
+	tnode_t *bn = NULL;
+	tnode_t *dn = NULL;
+	int pb = -1;
+	int b, d, f;
+
+	for (d = 0; d < MAX_PCIBUS_DEVS; d++)
+		for (f = 0; f < MAX_PCIDEV_FNS; f++)
+			pps[d][f] = NULL;
+
+	/* start at the parent's first sibling */
+	sib = di_child_node(pn);
+	while (sib != DI_NODE_NIL) {
+		np = did_create(mod, sib, board, bridge, rc, bover);
+		if (np == NULL)
+			return (-1);
+		did_BDF(np, &b, &d, &f);
+		pps[d][f] = np;
+		if (bp == NULL)
+			bp = np;
+		if (pb < 0)
+			pb = ((bover == TRUST_BDF) ? b : bover);
+		sib = di_sibling_node(sib);
+	}
+	if (pb < 0 && bover < 0)
+		return (0);
+	if (rc >= 0)
+		bn = pciexbus_declare(mod, parent, pn, ((pb < 0) ? bover : pb));
+	else
+		bn = pcibus_declare(mod, parent, pn, ((pb < 0) ? bover : pb));
+	if (bn == NULL)
+		return (-1);
+	if (pb < 0)
+		return (0);
+
+	for (d = 0; d < MAX_PCIBUS_DEVS; d++) {
+		for (f = 0; f < MAX_PCIDEV_FNS; f++) {
+			if (pps[d][f] == NULL)
+				continue;
+			din = did_dinode(pps[d][f]);
+			/*
+			 * Ignore error and try to enumerate as much as
+			 * possible.  If we ever need to check for an
+			 * error all declared buses, devices and functions
+			 * need to be cleaned up
+			 */
+			(void) declare_dev_and_fn(mod, bn,
+			    &dn, din, board, bridge, rc, d, f, depth);
+			did_rele(pps[d][f]);
+		}
+		dn = NULL;
+	}
+	return (0);
+}
+
+static int
+pciexbus_enum(topo_mod_t *mp, tnode_t *ptn, char *pnm, topo_instance_t min,
+    topo_instance_t max)
+{
+	di_node_t pdn;
+	int rc;
+	int retval;
+
+	/*
+	 * PCI-Express; root complex shares the hostbridge's instance
+	 * number.  Parent node's private data is a simple di_node_t
+	 * and we have to construct our own did hash and did_t.
+	 */
+	rc = topo_node_instance(ptn);
+
+	if ((pdn = topo_node_getspecific(ptn)) == DI_NODE_NIL) {
+		topo_mod_dprintf(mp,
+		    "Parent %s node missing private data.\n"
+		    "Unable to proceed with %s enumeration.\n", pnm, PCIEX_BUS);
+		return (0);
+	}
+	did_hash_init(mp);
+	if (did_create(mp, pdn, 0, 0, rc, TRUST_BDF) == NULL)
+		return (-1);	/* errno already set */
+	retval = pci_children_instantiate(mp, ptn, pdn, 0, 0, rc,
+	    (min == max) ? min : TRUST_BDF, 0);
+	did_hash_fini(mp);
+
+	return (retval);
+}
+
+static int
+pcibus_enum(topo_mod_t *mp, tnode_t *ptn, char *pnm, topo_instance_t min,
+    topo_instance_t max, void *data)
+{
+	did_t *didp, *hbdid = (did_t *)data;
+	int retval;
+
+	/*
+	 * XXTOPO: we should not be sharing private node data with another
+	 * module. PCI Bus; Parent node's private data is a did_t.  We'll
+	 * use the did hash established by the parent.
+	 */
+	did_setspecific(mp, data);
+
+	/*
+	 * If we're looking for a specific bus-instance, find the right
+	 * did_t in the chain, otherwise, there should be only one did_t.
+	 */
+	if (min == max) {
+		int b;
+		didp = hbdid;
+		while (didp != NULL) {
+			did_BDF(didp, &b, NULL, NULL);
+			if (b == min)
+				break;
+			didp = did_link_get(didp);
+		}
+		if (didp == NULL) {
+			topo_mod_dprintf(mp,
+			    "Parent %s node missing private data related\n"
+			    "to %s instance %d.\n", pnm, PCI_BUS, min);
+			topo_mod_setspecific(mp, NULL);
+			return (0);
+		}
+	} else {
+		assert(did_link_get(hbdid) == NULL);
+		didp = hbdid;
+	}
+	retval = pci_children_instantiate(mp, ptn, did_dinode(didp),
+	    did_board(didp), did_bridge(didp), did_rc(didp),
+	    (min == max) ? min : TRUST_BDF, 0);
+
+	topo_mod_setspecific(mp, NULL);
+
+	return (retval);
+}
+
+/*ARGSUSED*/
+static int
+pci_enum(topo_mod_t *mod, tnode_t *ptn, const char *name,
+    topo_instance_t min, topo_instance_t max, void *notused, void *data)
+{
+	int retval;
+	char *pname;
+
+	topo_mod_dprintf(mod, "Enumerating pci!\n");
+
+	if (strcmp(name, PCI_BUS) != 0 && strcmp(name, PCIEX_BUS) != 0) {
+		topo_mod_dprintf(mod,
+		    "Currently only know how to enumerate %s or %s.\n",
+		    PCI_BUS, PCIEX_BUS);
+		return (0);
+	}
+	pname = topo_node_name(ptn);
+	if (strcmp(pname, HOSTBRIDGE) != 0 && strcmp(pname, PCIEX_ROOT) != 0) {
+		topo_mod_dprintf(mod,
+		    "Currently can only enumerate a %s or %s directly\n",
+		    PCI_BUS, PCIEX_BUS);
+		topo_mod_dprintf(mod,
+		    "descended from a %s or %s node.\n",
+		    HOSTBRIDGE, PCIEX_ROOT);
+		return (0);
+	}
+
+	if (strcmp(name, PCI_BUS) == 0) {
+		retval = pcibus_enum(mod, ptn, pname, min, max, data);
+	} else if (strcmp(name, PCIEX_BUS) == 0) {
+		retval = pciexbus_enum(mod, ptn, pname, min, max);
+	} else {
+		topo_mod_dprintf(mod,
+		    "Currently only know how to enumerate %s or %s not %s.\n",
+		    PCI_BUS, PCIEX_BUS, name);
+		return (0);
+	}
+
+	return (retval);
+}
+
+/*ARGSUSED*/
+static void
+pci_release(topo_mod_t *mp, tnode_t *node)
+{
+	topo_method_unregister_all(mp, node);
+
+	/*
+	 * node private data (did_t) for this node is destroyed in
+	 * did_hash_destroy()
+	 */
+
+	topo_node_unbind(node);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/common/pcibus/pcibus.h	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,85 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _PCIBUS_H
+#define	_PCIBUS_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/pci.h>
+#include <fm/topo_mod.h>
+#include <libdevinfo.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define	PCI_ENUMR_VERS	1
+
+#define	PCI_ENUM "pcibus"
+
+#define	PCI_BUS		"pcibus"
+#define	PCI_DEVICE	"pcidev"
+#define	PCI_FUNCTION	"pcifn"
+#define	PCIEX_ROOT	"pciexrc"
+#define	PCIEX_SWUP	"pciexswu"
+#define	PCIEX_SWDWN	"pciexswd"
+#define	PCIEX_BUS	"pciexbus"
+#define	PCIEX_DEVICE	"pciexdev"
+#define	PCIEX_FUNCTION	"pciexfn"
+
+#define	PCIEXTYPE "pciex"
+#define	PCITYPE "pci"
+
+#define	MAX_HB_BUSES	255
+#define	MAX_PCIBUS_DEVS	32
+#define	MAX_PCIDEV_FNS	8
+
+#define	GETCLASS(x) (((x) & 0xff0000) >> 16)
+#define	GETSUBCLASS(x) (((x) & 0xff00) >> 8)
+
+extern tnode_t *pcibus_declare(topo_mod_t *, tnode_t *, di_node_t,
+    topo_instance_t);
+extern tnode_t *pcidev_declare(topo_mod_t *, tnode_t *, di_node_t,
+    topo_instance_t);
+extern tnode_t *pcifn_declare(topo_mod_t *, tnode_t *, di_node_t,
+    topo_instance_t);
+extern tnode_t *pciexbus_declare(topo_mod_t *, tnode_t *, di_node_t,
+    topo_instance_t);
+extern tnode_t *pciexdev_declare(topo_mod_t *, tnode_t *, di_node_t,
+    topo_instance_t);
+extern tnode_t *pciexfn_declare(topo_mod_t *, tnode_t *, di_node_t,
+    topo_instance_t);
+extern int pci_children_instantiate(topo_mod_t *, tnode_t *, di_node_t,
+    int, int, int, int, int);
+
+extern int platform_pci_label(topo_mod_t *, tnode_t *, nvlist_t *, nvlist_t **);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PCIBUS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/common/pcibus/pcibus_labels.c	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,213 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <libnvpair.h>
+#include <fm/topo_mod.h>
+#include <assert.h>
+#include <string.h>
+#include <sys/fm/protocol.h>
+
+#include <did.h>
+#include <pcibus.h>
+#include <pcibus_labels.h>
+
+extern slotnm_rewrite_t *Slot_Rewrites;
+extern physlot_names_t *Physlot_Names;
+extern missing_names_t *Missing_Names;
+
+static const char *
+pci_physslot_name_lookup(char *platform, did_t *dp)
+{
+	const char *rlabel = NULL;
+	int n, p, i;
+
+	if ((n = did_physslot(dp)) < 0 || Physlot_Names == NULL)
+		return (NULL);
+
+	for (p = 0; p < Physlot_Names->psn_nplats; p++) {
+		if (strcmp(Physlot_Names->psn_names[p].pnm_platform,
+		    platform) != 0)
+			continue;
+		for (i = 0; i < Physlot_Names->psn_names[p].pnm_nnames; i++) {
+			physnm_t ps;
+			ps = Physlot_Names->psn_names[p].pnm_names[i];
+			if (ps.ps_num == n) {
+				rlabel = ps.ps_label;
+				break;
+			}
+		}
+		break;
+	}
+	return (rlabel);
+}
+
+static const char *
+pci_slotname_rewrite(char *platform, const char *label)
+{
+	const char *rlabel = label;
+	int s, i;
+
+	if (Slot_Rewrites == NULL)
+		return (rlabel);
+
+	for (s = 0; s < Slot_Rewrites->srw_nplats; s++) {
+		if (strcmp(Slot_Rewrites->srw_platrewrites[s].prw_platform,
+		    platform) != 0)
+			continue;
+		for (i = 0;
+		    i < Slot_Rewrites->srw_platrewrites[s].prw_nrewrites;
+		    i++) {
+			slot_rwd_t rw;
+			rw = Slot_Rewrites->srw_platrewrites[s].prw_rewrites[i];
+			if (strcmp(rw.srw_obp, label) == 0) {
+				rlabel = rw.srw_new;
+				break;
+			}
+		}
+		break;
+	}
+	assert(rlabel != NULL);
+	return (rlabel);
+}
+
+static const char *
+pci_missing_match(topo_mod_t *mod, char *platform, did_t *dp)
+{
+	const char *rlabel = NULL;
+	int board, bridge, rc, bus, dev;
+	int p, i;
+
+	if (Missing_Names == NULL)
+		return (NULL);
+	bridge = did_bridge(dp);
+	board = did_board(dp);
+	rc = did_rc(dp);
+	did_BDF(dp, &bus, &dev, NULL);
+
+	topo_mod_dprintf(mod, "Missing a name for %d, %d, %d, %d, %d ?\n",
+	    board, bridge, rc, bus, dev);
+
+	for (p = 0; p < Missing_Names->mn_nplats; p++) {
+		if (strcmp(Missing_Names->mn_names[p].pdl_platform,
+		    platform) != 0)
+			continue;
+		for (i = 0; i < Missing_Names->mn_names[p].pdl_nnames; i++) {
+			devlab_t m;
+			m = Missing_Names->mn_names[p].pdl_names[i];
+			if (m.dl_board == board && m.dl_bridge == bridge &&
+			    m.dl_rc == rc && m.dl_bus == bus &&
+			    m.dl_dev == dev) {
+				rlabel = m.dl_label;
+				break;
+			}
+		}
+		break;
+	}
+	return (rlabel);
+}
+
+static const char *
+pci_slotname_lookup(topo_mod_t *mod, tnode_t *node, did_t *dp)
+{
+	const char *l;
+	char *plat, *pp;
+	int err;
+	int d;
+
+	if (topo_prop_get_string(node,
+	    FM_FMRI_AUTHORITY, FM_FMRI_AUTH_PRODUCT, &plat, &err) < 0) {
+		(void) topo_mod_seterrno(mod, err);
+		return (NULL);
+	}
+
+	/*
+	 * Trim SUNW, from the platform name
+	 */
+	pp = strchr(plat, ',');
+	++pp;
+
+	did_BDF(dp, NULL, &d, NULL);
+	if ((l = pci_physslot_name_lookup(pp, dp)) == NULL)
+		if ((l = did_label(dp, d)) != NULL) {
+			l = pci_slotname_rewrite(pp, l);
+		} else {
+			l = pci_missing_match(mod, pp, dp);
+		}
+	topo_mod_strfree(mod, plat);
+	return (l);
+}
+
+int
+pci_label_cmn(topo_mod_t *mod, tnode_t *node, nvlist_t *in, nvlist_t **out)
+{
+	uint64_t ptr;
+	const char *l;
+	did_t *dp;
+	char *nm;
+	int err;
+
+	/*
+	 * If it's not a device or a PCI-express bus (which could potentially
+	 * represent a slot, and therefore we might need to capture its slot
+	 * name information), just inherit any label from our parent
+	 */
+	*out = NULL;
+	nm = topo_node_name(node);
+	if (strcmp(nm, PCI_DEVICE) != 0 && strcmp(nm, PCIEX_DEVICE) != 0 &&
+	    strcmp(nm, PCIEX_BUS) != 0) {
+		if (topo_node_label_set(node, NULL, &err) < 0)
+			if (err != ETOPO_PROP_NOENT)
+				return (topo_mod_seterrno(mod, err));
+		return (0);
+	}
+
+	if (nvlist_lookup_uint64(in, TOPO_METH_LABEL_ARG_NVL, &ptr) != 0) {
+		topo_mod_dprintf(mod,
+		    "label method argument not found.\n");
+		return (-1);
+	}
+	dp = (did_t *)(uintptr_t)ptr;
+
+	/*
+	 * Is there a slotname associated with the device?
+	 */
+	if ((l = pci_slotname_lookup(mod, node, dp)) != NULL) {
+		nvlist_t *rnvl;
+
+		if (topo_mod_nvalloc(mod, &rnvl, NV_UNIQUE_NAME) != 0 ||
+		    nvlist_add_string(rnvl, TOPO_METH_LABEL_RET_STR, l) != 0)
+			return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
+		*out = rnvl;
+		return (0);
+	} else {
+		if (topo_node_label_set(node, NULL, &err) < 0)
+			if (err != ETOPO_PROP_NOENT)
+				return (topo_mod_seterrno(mod, err));
+		return (0);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/common/pcibus/pcibus_labels.h	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,110 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _PCIBUS_LABELS_H
+#define	_PCIBUS_LABELS_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <hostbridge.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * When all we're provided is a physical slot number, these structures
+ * allow us to attach an accompanying label.
+ */
+typedef struct physnm {
+	int ps_num;
+	const char *ps_label;
+} physnm_t;
+
+typedef struct pphysnm {
+	const char *pnm_platform;	/* platform on which the names apply */
+	int pnm_nnames;			/* number of names */
+	struct physnm *pnm_names;	/* array of labels */
+} pphysnm_t;
+
+typedef struct physlot_names {
+	int psn_nplats;
+	struct pphysnm *psn_names;
+} physlot_names_t;
+
+/*
+ * Sometimes OBP gets it wrong, there's a slot-names property, but it
+ * is incorrect.  These structures allow us to replace a given label A
+ * with a different label B prior to attaching the label to a topology node.
+ */
+typedef struct slot_rwd {
+	const char *srw_obp;		/* slot name found */
+	const char *srw_new;		/* replacement slot name */
+} slot_rwd_t;
+
+typedef struct plat_rwd {
+	const char *prw_platform;	/* platform on which the names apply */
+	int prw_nrewrites;		/* number of rewrites */
+	struct slot_rwd *prw_rewrites;	/* array of rewrites */
+} plat_rwd_t;
+
+typedef struct slotnm_rewrite {
+	int srw_nplats;
+	struct plat_rwd *srw_platrewrites;
+} slotnm_rewrite_t;
+
+/*
+ * We can locate a label without help from OBP slot-names or a
+ * physical slot-name, if need be.  Having to resort to this, though is
+ * really an indication that there's a bug in the platform OBP.
+ */
+typedef struct devlab {
+	int dl_board;
+	int dl_bridge;
+	int dl_rc;
+	int dl_bus;
+	int dl_dev;
+	const char *dl_label;
+} devlab_t;
+
+typedef struct pdevlabs {
+	const char *pdl_platform;	/* Name of the platform */
+	int pdl_nnames;			/* number of missing names */
+	struct devlab *pdl_names;	/* the missing names */
+} pdevlabs_t;
+
+typedef struct missing_names {
+	int mn_nplats;			/* number of platforms with entries */
+	struct pdevlabs *mn_names;	/* platform entries */
+} missing_names_t;
+
+extern int pci_label_cmn(topo_mod_t *mod, tnode_t *, nvlist_t *, nvlist_t **);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PCIBUS_LABELS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/common/pcibus/util.c	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,117 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <stdlib.h>
+#include <sys/fm/protocol.h>
+#include <fm/topo_mod.h>
+#include <fm/topo_hc.h>
+#include <fm/libtopo.h>
+
+int
+child_range_add(topo_mod_t *mp, tnode_t *tn, const char *cnm,
+    topo_instance_t imin, topo_instance_t imax)
+{
+	int e;
+
+	e = topo_node_range_create(mp, tn, cnm, imin, imax);
+	if (e != 0) {
+		topo_mod_dprintf(mp, "add child range (%s) failed: %s\n",
+		    cnm, topo_strerror(topo_mod_errno(mp)));
+		return (-1);
+	}
+	return (0);
+}
+
+ulong_t
+strtonum(topo_mod_t *mp, char *str, int *err)
+{
+	ulong_t r;
+	char *e;
+
+	r = strtoul(str, &e, 16);
+	if (e == str) {
+		topo_mod_dprintf(mp,
+		    "Trouble converting %s to a number!\n", str);
+		*err = -1;
+		return (0);
+	}
+	*err = 0;
+	return (r);
+}
+
+tnode_t *
+tnode_create(topo_mod_t *mp, tnode_t *parent,
+    const char *name, topo_instance_t i, void *priv)
+{
+	nvlist_t *fmri;
+	tnode_t *ntn;
+	nvlist_t *auth;
+
+	auth = topo_mod_auth(mp, parent);
+	fmri = topo_mod_hcfmri(mp, parent, FM_HC_SCHEME_VERSION, name, i, NULL,
+	    auth, NULL, NULL, NULL);
+	nvlist_free(auth);
+	if (fmri == NULL) {
+		topo_mod_dprintf(mp,
+		    "Unable to make nvlist for %s bind.\n", name);
+		return (NULL);
+	}
+
+	ntn = topo_node_bind(mp, parent, name, i, fmri);
+	if (ntn == NULL) {
+		topo_mod_dprintf(mp,
+		    "topo_node_bind (%s%d/%s%d) failed: %s\n",
+		    topo_node_name(parent), topo_node_instance(parent),
+		    name, i,
+		    topo_strerror(topo_mod_errno(mp)));
+		nvlist_free(fmri);
+		return (NULL);
+	}
+	nvlist_free(fmri);
+	topo_node_setspecific(ntn, priv);
+
+	return (ntn);
+}
+
+/*ARGSUSED*/
+int
+labelmethod_inherit(topo_mod_t *mp, tnode_t *tn, nvlist_t *in, nvlist_t **out)
+{
+	int err;
+
+	/*
+	 * Ignore the input and output nvlists and directly set the
+	 * label as inheritance from the parent
+	 */
+	*out = NULL;
+	if (topo_node_label_set(tn, NULL, &err) < 0) {
+		if (err != ETOPO_PROP_NOENT)
+			return (topo_mod_seterrno(mp, err));
+	}
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/fm/topo/modules/common/pcibus/util.h	Sat Nov 04 01:18:55 2006 -0800
@@ -0,0 +1,50 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _UTIL_H
+#define	_UTIL_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <fm/topo_mod.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int child_range_add(topo_mod_t *, tnode_t *, const char *,
+    topo_instance_t, topo_instance_t);
+extern int labelmethod_inherit(topo_mod_t *, tnode_t *, nvlist_t *,
+    nvlist_t **);
+extern ulong_t strtonum(topo_mod_t *, char *, int *);
+extern tnode_t *tnode_create(topo_mod_t *, tnode_t *, const char *,
+    topo_instance_t, void *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _UTIL_H */
--- a/usr/src/lib/fm/topo/modules/common/pcibus_labels.c	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,206 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <libnvpair.h>
-#include <fm/topo_mod.h>
-#include <assert.h>
-#include <string.h>
-
-#include "topo_error.h"
-#include "did.h"
-#include "pcibus.h"
-#include "pcibus_labels.h"
-
-extern slotnm_rewrite_t *Slot_Rewrites;
-extern physlot_names_t *Physlot_Names;
-extern missing_names_t *Missing_Names;
-
-static const char *
-pci_physslot_name_lookup(char *platform, did_t *dp)
-{
-	const char *rlabel = NULL;
-	int n, p, i;
-
-	if ((n = did_physslot(dp)) < 0 || Physlot_Names == NULL)
-		return (NULL);
-
-	for (p = 0; p < Physlot_Names->psn_nplats; p++) {
-		if (strcmp(Physlot_Names->psn_names[p].pnm_platform,
-		    platform) != 0)
-			continue;
-		for (i = 0; i < Physlot_Names->psn_names[p].pnm_nnames; i++) {
-			physnm_t ps;
-			ps = Physlot_Names->psn_names[p].pnm_names[i];
-			if (ps.ps_num == n) {
-				rlabel = ps.ps_label;
-				break;
-			}
-		}
-		break;
-	}
-	return (rlabel);
-}
-
-static const char *
-pci_slotname_rewrite(char *platform, const char *label)
-{
-	const char *rlabel = label;
-	int s, i;
-
-	if (Slot_Rewrites == NULL)
-		return (rlabel);
-
-	for (s = 0; s < Slot_Rewrites->srw_nplats; s++) {
-		if (strcmp(Slot_Rewrites->srw_platrewrites[s].prw_platform,
-		    platform) != 0)
-			continue;
-		for (i = 0;
-		    i < Slot_Rewrites->srw_platrewrites[s].prw_nrewrites;
-		    i++) {
-			slot_rwd_t rw;
-			rw = Slot_Rewrites->srw_platrewrites[s].prw_rewrites[i];
-			if (strcmp(rw.srw_obp, label) == 0) {
-				rlabel = rw.srw_new;
-				break;
-			}
-		}
-		break;
-	}
-	assert(rlabel != NULL);
-	return (rlabel);
-}
-
-static const char *
-pci_missing_match(char *platform, did_t *dp, topo_mod_t *mod)
-{
-	const char *rlabel = NULL;
-	int board, bridge, rc, bus, dev;
-	int p, i;
-
-	if (Missing_Names == NULL)
-		return (NULL);
-	bridge = did_bridge(dp);
-	board = did_board(dp);
-	rc = did_rc(dp);
-	did_BDF(dp, &bus, &dev, NULL);
-
-	topo_mod_dprintf(mod, "Missing a name for %d, %d, %d, %d, %d ?\n",
-	    board, bridge, rc, bus, dev);
-
-	for (p = 0; p < Missing_Names->mn_nplats; p++) {
-		if (strcmp(Missing_Names->mn_names[p].pdl_platform,
-		    platform) != 0)
-			continue;
-		for (i = 0; i < Missing_Names->mn_names[p].pdl_nnames; i++) {
-			devlab_t m;
-			m = Missing_Names->mn_names[p].pdl_names[i];
-			if (m.dl_board == board && m.dl_bridge == bridge &&
-			    m.dl_rc == rc && m.dl_bus == bus &&
-			    m.dl_dev == dev) {
-				rlabel = m.dl_label;
-				break;
-			}
-		}
-		break;
-	}
-	return (rlabel);
-}
-
-static const char *
-pci_slotname_lookup(tnode_t *node, did_t *dp, topo_mod_t *mod)
-{
-	const char *l;
-	char *plat;
-	int err;
-	int d;
-
-	if (topo_prop_get_string(node,
-	    TOPO_PGROUP_SYSTEM, TOPO_PROP_PLATFORM, &plat, &err) < 0) {
-		(void) topo_mod_seterrno(mod, err);
-		return (NULL);
-	}
-	did_BDF(dp, NULL, &d, NULL);
-	if ((l = pci_physslot_name_lookup(plat, dp)) == NULL)
-		if ((l = did_label(dp, d)) != NULL) {
-			l = pci_slotname_rewrite(plat, l);
-		} else {
-			l = pci_missing_match(plat, dp, mod);
-		}
-	topo_mod_strfree(mod, plat);
-	return (l);
-}
-
-int
-pci_label_cmn(tnode_t *node, nvlist_t *in, nvlist_t **out, topo_mod_t *mod)
-{
-	uint64_t ptr;
-	const char *l;
-	did_t *dp;
-	char *nm;
-	int err;
-
-	/*
-	 * If it's not a device or a PCI-express bus (which could potentially
-	 * represent a slot, and therefore we might need to capture its slot
-	 * name information), just inherit any label from our parent
-	 */
-	*out = NULL;
-	nm = topo_node_name(node);
-	if (strcmp(nm, PCI_DEVICE) != 0 && strcmp(nm, PCIEX_DEVICE) != 0 &&
-	    strcmp(nm, PCIEX_BUS) != 0) {
-		if (topo_node_label_set(node, NULL, &err) < 0)
-			if (err != ETOPO_PROP_NOENT)
-				return (topo_mod_seterrno(mod, err));
-		return (0);
-	}
-
-	if (nvlist_lookup_uint64(in, TOPO_METH_LABEL_ARG_NVL, &ptr) != 0) {
-		topo_mod_dprintf(mod,
-		    "label method argument not found.\n");
-		return (-1);
-	}
-	dp = (did_t *)(uintptr_t)ptr;
-
-	/*
-	 * Is there a slotname associated with the device?
-	 */
-	if ((l = pci_slotname_lookup(node, dp, mod)) != NULL) {
-		nvlist_t *rnvl;
-
-		if (topo_mod_nvalloc(mod, &rnvl, NV_UNIQUE_NAME) != 0 ||
-		    nvlist_add_string(rnvl, TOPO_METH_LABEL_RET_STR, l) != 0)
-			return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
-		*out = rnvl;
-		return (0);
-	} else {
-		if (topo_node_label_set(node, NULL, &err) < 0)
-			if (err != ETOPO_PROP_NOENT)
-				return (topo_mod_seterrno(mod, err));
-		return (0);
-	}
-}
--- a/usr/src/lib/fm/topo/modules/common/pcibus_labels.h	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _PCIBUS_LABELS_H
-#define	_PCIBUS_LABELS_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <hostbridge.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * When all we're provided is a physical slot number, these structures
- * allow us to attach an accompanying label.
- */
-typedef struct physnm {
-	int ps_num;
-	const char *ps_label;
-} physnm_t;
-
-typedef struct pphysnm {
-	const char *pnm_platform;	/* platform on which the names apply */
-	int pnm_nnames;			/* number of names */
-	struct physnm *pnm_names;	/* array of labels */
-} pphysnm_t;
-
-typedef struct physlot_names {
-	int psn_nplats;
-	struct pphysnm *psn_names;
-} physlot_names_t;
-
-/*
- * Sometimes OBP gets it wrong, there's a slot-names property, but it
- * is incorrect.  These structures allow us to replace a given label A
- * with a different label B prior to attaching the label to a topology node.
- */
-typedef struct slot_rwd {
-	const char *srw_obp;		/* slot name found */
-	const char *srw_new;		/* replacement slot name */
-} slot_rwd_t;
-
-typedef struct plat_rwd {
-	const char *prw_platform;	/* platform on which the names apply */
-	int prw_nrewrites;		/* number of rewrites */
-	struct slot_rwd *prw_rewrites;	/* array of rewrites */
-} plat_rwd_t;
-
-typedef struct slotnm_rewrite {
-	int srw_nplats;
-	struct plat_rwd *srw_platrewrites;
-} slotnm_rewrite_t;
-
-/*
- * We can locate a label without help from OBP slot-names or a
- * physical slot-name, if need be.  Having to resort to this, though is
- * really an indication that there's a bug in the platform OBP.
- */
-typedef struct devlab {
-	int dl_board;
-	int dl_bridge;
-	int dl_rc;
-	int dl_bus;
-	int dl_dev;
-	const char *dl_label;
-} devlab_t;
-
-typedef struct pdevlabs {
-	const char *pdl_platform;	/* Name of the platform */
-	int pdl_nnames;			/* number of missing names */
-	struct devlab *pdl_names;	/* the missing names */
-} pdevlabs_t;
-
-typedef struct missing_names {
-	int mn_nplats;			/* number of platforms with entries */
-	struct pdevlabs *mn_names;	/* platform entries */
-} missing_names_t;
-
-extern int pci_label_cmn(tnode_t *, nvlist_t *, nvlist_t **, topo_mod_t *mod);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _PCIBUS_LABELS_H */
--- a/usr/src/lib/fm/topo/modules/common/pcifn_enum.c	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <limits.h>
-#include <fm/libtopo.h>
-#include "did.h"
-#include "did_props.h"
-#include "pcifn_enum.h"
-
-static topo_mod_t *
-module_load(topo_mod_t *mp, tnode_t *parent, const char *name)
-{
-	topo_mod_t *rp = NULL;
-	char *plat, *mach;
-	char *path;
-	char *rootdir;
-	int err;
-
-	plat = mach = NULL;
-
-	if (topo_prop_get_string(parent,
-	    TOPO_PGROUP_SYSTEM, TOPO_PROP_PLATFORM, &plat, &err) < 0) {
-		(void) topo_mod_seterrno(mp, err);
-		return (NULL);
-	}
-	if (topo_prop_get_string(parent,
-	    TOPO_PGROUP_SYSTEM, TOPO_PROP_MACHINE, &mach, &err) < 0) {
-		(void) topo_mod_seterrno(mp, err);
-		return (NULL);
-	}
-	path = topo_mod_alloc(mp, PATH_MAX);
-	rootdir = topo_mod_rootdir(mp);
-	(void) snprintf(path, PATH_MAX,
-	    PATH_TEMPLATE, rootdir ? rootdir : "", plat, name);
-
-	if ((rp = topo_mod_load(mp, path)) == NULL) {
-		topo_mod_dprintf(mp, "Unable to load %s.\n", path);
-		(void) snprintf(path, PATH_MAX,
-		    PATH_TEMPLATE, rootdir ? rootdir : "", mach, name);
-		if ((rp = topo_mod_load(mp, path)) == NULL)
-			topo_mod_dprintf(mp, "Unable to load %s.\n", path);
-	}
-	topo_mod_strfree(mp, plat);
-	topo_mod_strfree(mp, mach);
-	topo_mod_free(mp, path, PATH_MAX);
-	return (rp);
-}
-
-static int
-module_run(topo_mod_t *mp, tnode_t *parent, pfn_enum_t *ep)
-{
-	return (topo_mod_enumerate(mp, parent,
-	    ep->pfne_modname, ep->pfne_childname,
-	    ep->pfne_imin, ep->pfne_imax));
-}
-
-int
-pcifn_enum(topo_mod_t *mp, tnode_t *parent)
-{
-	char *ccstr;
-	int rv = 0;
-	int i, e;
-	uint_t cc;
-	topo_mod_t *child_mod;
-
-	topo_mod_dprintf(mp, "Enumerating beneath pci(ex) function.\n");
-
-	/*
-	 * Extract the class code of the PCI function and make sure
-	 * it matches the type that the module cares about.
-	 */
-	if (topo_prop_get_string(parent,
-	    TOPO_PGROUP_PCI, TOPO_PROP_CLASS, &ccstr, &e) < 0)
-		return (0);
-	if (sscanf(ccstr, "%x", &cc) != 1) {
-		topo_mod_strfree(mp, ccstr);
-		return (0);
-	}
-	topo_mod_strfree(mp, ccstr);
-	cc = cc >> 16;
-
-	for (i = 0; i < Pcifn_enumerator_count; i++) {
-
-		if (cc != Pcifn_enumerators[i].pfne_class)
-			continue;
-
-		child_mod = module_load(mp, parent,
-		    Pcifn_enumerators[i].pfne_modname);
-
-		if (child_mod) {
-			rv = module_run(mp, parent,
-			    &Pcifn_enumerators[i]) != 0 ? -1 : 0;
-			topo_mod_unload(child_mod);
-		}
-	}
-	return (rv);
-}
--- a/usr/src/lib/fm/topo/modules/common/pcifn_enum.h	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef	_PCIFN_ENUM_H
-#define	_PCIFN_ENUM_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <sys/types.h>
-#include <sys/pci.h>
-#include <fm/topo_mod.h>
-
-#define	PATH_TEMPLATE "%s/usr/platform/%s/lib/fm/topo/plugins/%s.so"
-
-/*
- * When a pci or pci-express function is enumerated in the topology
- * we'll attempt to load modules that can expand the topology
- * beneath that function.  This data structure helps us track which modules
- * to attempt to load, whether or not the loading was successful
- * so we don't waste time trying again, and if loading is successful,
- * the module pointer returned by topo_mod_load().
- */
-typedef struct pfn_enum {
-	uint_t pfne_class;	/* expected PCI class of the parent function */
-	const char *pfne_modname; /* enumerator module name */
-	const char *pfne_childname; /* name of nodes to enumerate */
-	topo_instance_t pfne_imin; /* minimum instance number to enumerate */
-	topo_instance_t pfne_imax; /* maximum instance number to enumerate */
-} pfn_enum_t;
-
-/*
- * The current list of modules to potentially load and expand topology
- * beneath pci(-express) functions.
- */
-pfn_enum_t Pcifn_enumerators[] = {
-	{ PCI_CLASS_MASS, "sata", "sata-port", 0, 7	},
-	{ PCI_CLASS_MASS, "scsi", "disk", 0, 15		}
-};
-
-int Pcifn_enumerator_count = sizeof (Pcifn_enumerators) / sizeof (pfn_enum_t);
-
-#endif /* _PCIFN_ENUM_H */
--- a/usr/src/lib/fm/topo/modules/common/util.c	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,138 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <stdlib.h>
-#include <sys/fm/protocol.h>
-#include <fm/topo_mod.h>
-
-#include "topo_error.h"
-
-int
-child_range_add(topo_mod_t *mp, tnode_t *tn, const char *cnm,
-    topo_instance_t imin, topo_instance_t imax)
-{
-	int e;
-
-	e = topo_node_range_create(mp, tn, cnm, imin, imax);
-	if (e != 0) {
-		topo_mod_dprintf(mp, "add child range (%s) failed: %s\n",
-		    cnm, topo_strerror(topo_mod_errno(mp)));
-		return (-1);
-	}
-	return (0);
-}
-
-ulong_t
-strtonum(topo_mod_t *mp, char *str, int *err)
-{
-	ulong_t r;
-	char *e;
-
-	r = strtoul(str, &e, 16);
-	if (e == str) {
-		topo_mod_dprintf(mp,
-		    "Trouble converting %s to a number!\n", str);
-		*err = -1;
-		return (0);
-	}
-	*err = 0;
-	return (r);
-}
-
-tnode_t *
-tnode_create(topo_mod_t *mp, tnode_t *parent,
-    const char *name, topo_instance_t i, void *priv)
-{
-	topo_hdl_t *thp;
-	nvlist_t *fmri, *pfmri, *nvl;
-	tnode_t *ntn;
-	int err;
-
-	thp = topo_mod_handle(mp);
-
-	if (topo_node_resource(parent, &pfmri, &err) < 0) {
-		topo_mod_seterrno(mp, err);
-		topo_mod_dprintf(mp, "Unable to retrieve parent resource.\n");
-		return (NULL);
-	}
-	if (topo_mod_nvalloc(mp, &nvl, NV_UNIQUE_NAME) != 0) {
-		(void) topo_mod_seterrno(mp, EMOD_FMRI_NVL);
-		nvlist_free(pfmri);
-		return (NULL);
-	}
-	err = nvlist_add_nvlist(nvl, TOPO_METH_FMRI_ARG_PARENT, pfmri);
-	if (err != 0) {
-		nvlist_free(pfmri);
-		nvlist_free(nvl);
-		(void) topo_mod_seterrno(mp, EMOD_FMRI_NVL);
-		return (NULL);
-	}
-
-	fmri = topo_fmri_create(thp, FM_FMRI_SCHEME_HC, name, i, nvl, &err);
-	if (fmri == NULL) {
-		nvlist_free(pfmri);
-		nvlist_free(nvl);
-		topo_mod_seterrno(mp, err);
-		topo_mod_dprintf(mp,
-		    "Unable to make nvlist for %s bind.\n", name);
-		return (NULL);
-	}
-
-	nvlist_free(pfmri);
-	nvlist_free(nvl);
-	ntn = topo_node_bind(mp, parent, name, i, fmri, priv);
-	if (ntn == NULL) {
-		topo_mod_dprintf(mp,
-		    "topo_node_bind (%s%d/%s%d) failed: %s\n",
-		    topo_node_name(parent), topo_node_instance(parent),
-		    name, i,
-		    topo_strerror(topo_mod_errno(mp)));
-		nvlist_free(fmri);
-		return (NULL);
-	}
-	nvlist_free(fmri);
-	return (ntn);
-}
-
-/*ARGSUSED*/
-int
-labelmethod_inherit(topo_mod_t *mp, tnode_t *tn, nvlist_t *in, nvlist_t **out)
-{
-	int err;
-
-	/*
-	 * Ignore the input and output nvlists and directly set the
-	 * label as inheritance from the parent
-	 */
-	*out = NULL;
-	if (topo_node_label_set(tn, NULL, &err) < 0) {
-		if (err != ETOPO_PROP_NOENT)
-			return (topo_mod_seterrno(mp, err));
-	}
-	return (0);
-}
--- a/usr/src/lib/fm/topo/modules/common/util.h	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _UTIL_H
-#define	_UTIL_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <fm/topo_mod.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern int child_range_add(topo_mod_t *, tnode_t *, const char *,
-    topo_instance_t, topo_instance_t);
-extern int labelmethod_inherit(topo_mod_t *, tnode_t *, nvlist_t *,
-    nvlist_t **);
-extern ulong_t strtonum(topo_mod_t *, char *, int *);
-extern tnode_t *tnode_create(topo_mod_t *, tnode_t *, const char *,
-    topo_instance_t, void *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif	/* _UTIL_H */
--- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip.c	Sat Nov 04 01:18:55 2006 -0800
@@ -64,13 +64,28 @@
  */
 
 static int chip_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t,
-    topo_instance_t, void *);
+    topo_instance_t, void *, void *);
 
 static int mem_asru_compute(topo_mod_t *, tnode_t *, topo_version_t,
     nvlist_t *, nvlist_t **);
 
-const topo_modinfo_t chip_info =
-	{ "chip", CHIP_VERSION, chip_enum, NULL};
+static const topo_modops_t chip_ops =
+	{ chip_enum, NULL};
+static const topo_modinfo_t chip_info =
+	{ "chip", FM_FMRI_SCHEME_HC, CHIP_VERSION, &chip_ops };
+
+static const topo_pgroup_info_t cs_pgroup =
+	{ CS_PGROUP, TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
+static const topo_pgroup_info_t dimm_pgroup =
+	{ DIMM_PGROUP, TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
+static const topo_pgroup_info_t mc_pgroup =
+	{ MCT_PGROUP, TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
+static const topo_pgroup_info_t chip_pgroup =
+	{ CHIP_PGROUP, TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
+static const topo_pgroup_info_t rank_pgroup =
+	{ RANK_PGROUP, TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
+static const topo_pgroup_info_t chan_pgroup =
+	{ CHAN_PGROUP, TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
 
 const topo_method_t rank_methods[] = {
 	{ TOPO_METH_ASRU_COMPUTE, TOPO_METH_ASRU_COMPUTE_DESC,
@@ -79,18 +94,6 @@
 	{ NULL }
 };
 
-static const struct debugopt {
-	const char *optname;
-	int optval;
-} debugopts[] = {
-	{ "err", TOPO_DBG_ERR },
-	{ "mod", TOPO_DBG_MOD },
-	{ "log", TOPO_DBG_LOG },
-	{ "walk", TOPO_DBG_WALK },
-	{ "tree", TOPO_DBG_TREE },
-	{ "all", TOPO_DBG_ALL }
-};
-
 static nvlist_t *cs_fmri[MC_CHIP_NCS];
 
 static void
@@ -112,21 +115,10 @@
 int
 _topo_init(topo_mod_t *mod)
 {
-	const char *debugstr = getenv("TOPOCHPDBG");
 	chip_t *chip;
-	int i;
 
-	if (debugstr != NULL) {
-		for (i = 0; i < sizeof (debugopts) / sizeof (struct debugopt);
-		    i++) {
-			if (strncmp(debugstr, debugopts[i].optname, 4) == 0) {
-				topo_mod_clrdebug(mod);
-				topo_mod_setdebug(mod, debugopts[i].optval);
-				break;	/* handle a single option only */
-			}
-		}
-	}
-
+	if (getenv("TOPOCHIPDBG"))
+		topo_mod_setdebug(mod);
 	topo_mod_dprintf(mod, "initializing chip enumerator\n");
 
 	if ((chip = topo_mod_zalloc(mod, sizeof (chip_t))) == NULL)
@@ -147,7 +139,7 @@
 		return (topo_mod_seterrno(mod, EMOD_NOMEM));
 	}
 
-	if (topo_mod_register(mod, &chip_info, (void *)chip) != 0) {
+	if (topo_mod_register(mod, &chip_info, TOPO_VERSION) != 0) {
 		whinge(mod, NULL, "failed to register hc: "
 		    "%s\n", topo_mod_errmsg(mod));
 		topo_mod_free(mod, chip->chip_cpustats,
@@ -156,6 +148,7 @@
 		topo_mod_free(mod, chip, sizeof (chip_t));
 		return (-1); /* mod errno set */
 	}
+	topo_mod_setspecific(mod, (void *)chip);
 
 	return (0);
 }
@@ -163,7 +156,7 @@
 void
 _topo_fini(topo_mod_t *mod)
 {
-	chip_t *chip = topo_mod_private(mod);
+	chip_t *chip = topo_mod_getspecific(mod);
 
 	if (chip->chip_cpustats != NULL)
 		topo_mod_free(mod, chip->chip_cpustats,
@@ -185,7 +178,7 @@
 		return (0);
 
 	(void) topo_prop_set_string(cnode, CHIP_PGROUP, name,
-	    TOPO_PROP_SET_ONCE, k->value.str.addr.ptr, &err);
+	    TOPO_PROP_IMMUTABLE, k->value.str.addr.ptr, &err);
 
 	return (-1);
 }
@@ -199,32 +192,18 @@
 	if ((k = kstat_data_lookup(ksp, (char *)name)) == NULL)
 		return (0);
 
-	(void) topo_prop_set_int32(cnode, CHIP_PGROUP, name, TOPO_PROP_SET_ONCE,
-	    k->value.l, &err);
+	(void) topo_prop_set_int32(cnode, CHIP_PGROUP, name,
+	    TOPO_PROP_IMMUTABLE, k->value.l, &err);
 
 	return (-1);
 }
 
 static int
 mkrsrc(topo_mod_t *mod, tnode_t *pnode, const char *name, int inst,
-    nvlist_t **nvl)
+    nvlist_t *auth, nvlist_t **nvl)
 {
-	nvlist_t *args = NULL, *pfmri = NULL;
-	topo_hdl_t *thp = topo_mod_handle(mod);
-	int err;
-
-	if (topo_node_resource(pnode, &pfmri, &err) < 0 ||
-	    topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0 ||
-	    nvlist_add_nvlist(args, TOPO_METH_FMRI_ARG_PARENT, pfmri) != 0) {
-		nvlist_free(pfmri);
-		nvlist_free(args);
-		return (-1);
-	}
-
-	*nvl = topo_fmri_create(thp, FM_FMRI_SCHEME_HC, name, inst, args, &err);
-	nvlist_free(pfmri);
-	nvlist_free(args);
-
+	*nvl = topo_mod_hcfmri(mod, pnode, FM_HC_SCHEME_VERSION, name,
+	    inst, NULL, auth, NULL, NULL, NULL);
 	return (nvl != NULL ? 0 : -1);	/* caller must free nvlist */
 }
 
@@ -271,7 +250,7 @@
 
 static int
 cpu_create(topo_mod_t *mod, tnode_t *pnode, const char *name, int chipid,
-    chip_t *chip)
+    chip_t *chip, nvlist_t *auth)
 {
 	kstat_named_t *k;
 	nvlist_t *fmri, *asru;
@@ -320,13 +299,13 @@
 		}
 		clogid = k->value.l;
 
-		if (mkrsrc(mod, pnode, name, clogid, &fmri) != 0) {
+		if (mkrsrc(mod, pnode, name, clogid, auth, &fmri) != 0) {
 			whinge(mod, &nerr, "cpu_create: mkrsrc failed\n");
 			continue;
 		}
 
-		if ((cnode = topo_node_bind(mod, pnode, name, clogid, fmri,
-		    NULL)) == NULL) {
+		if ((cnode = topo_node_bind(mod, pnode, name, clogid, fmri))
+		    == NULL) {
 			whinge(mod, &nerr, "cpu_create: node bind failed\n");
 			nvlist_free(fmri);
 			continue;
@@ -358,7 +337,7 @@
 
 		if (nvpair_value_boolean_value(nvp, &val) == 0) {
 			(void) topo_prop_set_string(node, pgname, pname,
-			    TOPO_PROP_SET_ONCE, (val ? "true" : "false"), &err);
+			    TOPO_PROP_IMMUTABLE, val ? "true" : "false", &err);
 		}
 		return (0);
 	}
@@ -368,7 +347,7 @@
 
 		if (nvpair_value_uint64(nvp, &val) == 0) {
 			(void) topo_prop_set_uint64(node, pgname, pname,
-			    TOPO_PROP_SET_ONCE, val, &err);
+			    TOPO_PROP_IMMUTABLE, val, &err);
 		}
 		return (0);
 	}
@@ -378,7 +357,7 @@
 
 		if (nvpair_value_string(nvp, &str) == 0)
 			(void) topo_prop_set_string(node, pgname, pname,
-			    TOPO_PROP_SET_ONCE, str, &err);
+			    TOPO_PROP_IMMUTABLE, str, &err);
 		return (0);
 	}
 
@@ -391,7 +370,8 @@
 }
 
 static int
-dramchan_create(topo_mod_t *mod, tnode_t *pnode, const char *name)
+dramchan_create(topo_mod_t *mod, tnode_t *pnode, const char *name,
+    nvlist_t *auth)
 {
 	tnode_t *chnode;
 	nvlist_t *fmri;
@@ -419,14 +399,14 @@
 		return (-1);
 
 	for (i = 0; i < nchan; i++) {
-		if (mkrsrc(mod, pnode, name, i, &fmri) != 0) {
+		if (mkrsrc(mod, pnode, name, i, auth, &fmri) != 0) {
 			whinge(mod, &nerr, "dramchan_create: mkrsrc "
 			    "failed\n");
 			continue;
 		}
 
-		if ((chnode = topo_node_bind(mod, pnode, name, i, fmri,
-		    NULL)) == NULL) {
+		if ((chnode = topo_node_bind(mod, pnode, name, i, fmri))
+		    == NULL) {
 			nvlist_free(fmri);
 			whinge(mod, &nerr, "dramchan_create: node bind "
 			    "failed\n");
@@ -435,18 +415,18 @@
 
 		nvlist_free(fmri);
 
-		(void) topo_pgroup_create(chnode, CHAN_PGROUP,
-		    TOPO_STABILITY_PRIVATE, &err);
+		(void) topo_pgroup_create(chnode, &chan_pgroup, &err);
 
 		(void) topo_prop_set_string(chnode, CHAN_PGROUP, "channel",
-		    TOPO_PROP_SET_ONCE, i == 0 ? "A" : "B", &err);
+		    TOPO_PROP_IMMUTABLE, i == 0 ? "A" : "B", &err);
 	}
 
 	return (nerr == 0 ? 0 : -1);
 }
 
 static int
-cs_create(topo_mod_t *mod, tnode_t *pnode, const char *name, nvlist_t *mc)
+cs_create(topo_mod_t *mod, tnode_t *pnode, const char *name, nvlist_t *mc,
+    nvlist_t *auth)
 {
 	int i, err, nerr = 0;
 	nvpair_t *nvp;
@@ -471,13 +451,13 @@
 			continue;
 		}
 
-		if (mkrsrc(mod, pnode, name, csnum, &fmri) != 0) {
+		if (mkrsrc(mod, pnode, name, csnum, auth, &fmri) != 0) {
 			whinge(mod, &nerr, "cs_create: mkrsrc failed\n");
 			continue;
 		}
 
-		if ((csnode = topo_node_bind(mod, pnode, name, csnum, fmri,
-		    NULL)) == NULL) {
+		if ((csnode = topo_node_bind(mod, pnode, name, csnum, fmri))
+		    == NULL) {
 			nvlist_free(fmri);
 			whinge(mod, &nerr, "cs_create: node bind failed\n");
 			continue;
@@ -487,8 +467,7 @@
 
 		(void) topo_node_asru_set(csnode, fmri, 0, &err);
 
-		(void) topo_pgroup_create(csnode, CS_PGROUP,
-		    TOPO_STABILITY_PRIVATE, &err);
+		(void) topo_pgroup_create(csnode, &cs_pgroup, &err);
 
 		for (nvp = nvlist_next_nvpair(csarr[i], NULL); nvp != NULL;
 		    nvp = nvlist_next_nvpair(csarr[i], nvp)) {
@@ -552,7 +531,7 @@
 	}
 
 	/* use 'in' to obtain resource path;  could use node resource */
-	if (topo_fmri_nvl2str(topo_mod_handle(mod), in, &unum, &err) < 0)
+	if (topo_mod_nvl2str(mod, in, &unum) < 0)
 		return (topo_mod_seterrno(mod, err));
 
 	if ((asru = mem_fmri_create(mod)) == NULL) {
@@ -577,7 +556,7 @@
 }
 
 static int
-rank_create(topo_mod_t *mod, tnode_t *pnode, nvlist_t *dimmnvl)
+rank_create(topo_mod_t *mod, tnode_t *pnode, nvlist_t *dimmnvl, nvlist_t *auth)
 {
 	uint64_t *csnumarr;
 	char **csnamearr;
@@ -617,13 +596,13 @@
 	}
 
 	for (i = 0; i < ncs; i++) {
-		if (mkrsrc(mod, pnode, RANK_NODE_NAME, i, &fmri) < 0) {
+		if (mkrsrc(mod, pnode, RANK_NODE_NAME, i, auth, &fmri) < 0) {
 			whinge(mod, &nerr, "rank_create: mkrsrc failed\n");
 			continue;
 		}
 
 		if ((ranknode = topo_node_bind(mod, pnode, RANK_NODE_NAME, i,
-		    fmri, NULL)) == NULL) {
+		    fmri)) == NULL) {
 			nvlist_free(fmri);
 			whinge(mod, &nerr, "rank_create: node bind "
 			    "failed\n");
@@ -647,17 +626,16 @@
 			whinge(mod, &nerr, "rank_create: "
 			    "topo_method_register failed");
 
-		(void) topo_pgroup_create(ranknode, RANK_PGROUP,
-		    TOPO_STABILITY_PRIVATE, &err);
+		(void) topo_pgroup_create(ranknode, &rank_pgroup, &err);
 
 		(void) topo_prop_set_uint64(ranknode, RANK_PGROUP, "size",
-		    TOPO_PROP_SET_ONCE, rsz, &err);
+		    TOPO_PROP_IMMUTABLE, rsz, &err);
 
 		(void) topo_prop_set_string(ranknode, RANK_PGROUP, "csname",
-		    TOPO_PROP_SET_ONCE, csnamearr[i], &err);
+		    TOPO_PROP_IMMUTABLE, csnamearr[i], &err);
 
 		(void) topo_prop_set_uint64(ranknode, RANK_PGROUP, "csnum",
-		    TOPO_PROP_SET_ONCE, csnumarr[i], &err);
+		    TOPO_PROP_IMMUTABLE, csnumarr[i], &err);
 	}
 
 	nvlist_free(pfmri);
@@ -666,7 +644,8 @@
 }
 
 static int
-dimm_create(topo_mod_t *mod, tnode_t *pnode, const char *name, nvlist_t *mc)
+dimm_create(topo_mod_t *mod, tnode_t *pnode, const char *name, nvlist_t *mc,
+    nvlist_t *auth)
 {
 	int i, err, nerr = 0;
 	nvpair_t *nvp;
@@ -695,13 +674,13 @@
 			continue;
 		}
 
-		if (mkrsrc(mod, pnode, name, num, &fmri) < 0) {
+		if (mkrsrc(mod, pnode, name, num, auth, &fmri) < 0) {
 			whinge(mod, &nerr, "dimm_create: mkrsrc failed\n");
 			continue;
 		}
 
-		if ((dimmnode = topo_node_bind(mod, pnode, name, num, fmri,
-		    NULL)) == NULL) {
+		if ((dimmnode = topo_node_bind(mod, pnode, name, num, fmri))
+		    == NULL) {
 			nvlist_free(fmri);
 			whinge(mod, &nerr, "dimm_create: node bind "
 			    "failed\n");
@@ -729,8 +708,7 @@
 
 		nvlist_free(fmri);
 
-		(void) topo_pgroup_create(dimmnode, DIMM_PGROUP,
-		    TOPO_STABILITY_PRIVATE, &err);
+		(void) topo_pgroup_create(dimmnode, &dimm_pgroup, &err);
 
 		for (nvp = nvlist_next_nvpair(dimmarr[i], NULL); nvp != NULL;
 		    nvp = nvlist_next_nvpair(dimmarr[i], nvp)) {
@@ -743,7 +721,7 @@
 			nerr += nvprop_add(mod, nvp, DIMM_PGROUP, dimmnode);
 		}
 
-		nerr += rank_create(mod, dimmnode, dimmarr[i]);
+		nerr += rank_create(mod, dimmnode, dimmarr[i], auth);
 	}
 
 	return (nerr == 0 ? 0 : -1);
@@ -811,7 +789,7 @@
 }
 
 static int
-mc_create(topo_mod_t *mod, tnode_t *pnode, const char *name)
+mc_create(topo_mod_t *mod, tnode_t *pnode, const char *name, nvlist_t *auth)
 {
 	int err, rc = 0;
 	tnode_t *mcnode;
@@ -820,7 +798,7 @@
 	nvlist_t *mc = NULL;
 	int i;
 
-	if (mkrsrc(mod, pnode, name, 0, &fmri) != 0) {
+	if (mkrsrc(mod, pnode, name, 0, auth, &fmri) != 0) {
 		whinge(mod, NULL, "mc_create: mkrsrc failed\n");
 		return (-1);
 	}
@@ -836,7 +814,7 @@
 	 */
 	if ((mc = mc_lookup_by_mcid(mod, topo_node_instance(pnode))) == NULL ||
 	    (mcnode = topo_node_bind(mod, pnode,
-	    name, 0, fmri, NULL)) == NULL) {
+	    name, 0, fmri)) == NULL) {
 		if (mc != NULL)
 			nvlist_free(mc);
 		topo_node_range_destroy(pnode, name);
@@ -851,8 +829,7 @@
 	/*
 	 * Add memory controller properties
 	 */
-	(void) topo_pgroup_create(mcnode, MCT_PGROUP,
-	    TOPO_STABILITY_PRIVATE, &err);
+	(void) topo_pgroup_create(mcnode, &mc_pgroup, &err);
 
 	for (nvp = nvlist_next_nvpair(mc, NULL); nvp != NULL;
 	    nvp = nvlist_next_nvpair(mc, nvp)) {
@@ -869,9 +846,9 @@
 		}
 	}
 
-	if (dramchan_create(mod, mcnode, CHAN_NODE_NAME) != 0 ||
-	    cs_create(mod, mcnode, CS_NODE_NAME, mc) != 0 ||
-	    dimm_create(mod, mcnode, DIMM_NODE_NAME, mc) != 0)
+	if (dramchan_create(mod, mcnode, CHAN_NODE_NAME, auth) != 0 ||
+	    cs_create(mod, mcnode, CS_NODE_NAME, mc, auth) != 0 ||
+	    dimm_create(mod, mcnode, DIMM_NODE_NAME, mc, auth) != 0)
 		rc = -1;
 
 	/*
@@ -890,7 +867,7 @@
 
 static int
 chip_create(topo_mod_t *mod, tnode_t *pnode, const char *name,
-    topo_instance_t min, topo_instance_t max, chip_t *chip)
+    topo_instance_t min, topo_instance_t max, chip_t *chip, nvlist_t *auth)
 {
 	int i, nerr = 0;
 	kstat_t *ksp;
@@ -935,13 +912,13 @@
 		if (chipid < min || chipid > max)
 			continue;
 
-		if (mkrsrc(mod, pnode, name, chipid, &fmri) != 0) {
+		if (mkrsrc(mod, pnode, name, chipid, auth, &fmri) != 0) {
 			whinge(mod, &nerr, "chip_create: mkrsrc failed\n");
 			continue;
 		}
 
-		if ((cnode = topo_node_bind(mod, pnode, name, chipid, fmri,
-		    NULL)) == NULL) {
+		if ((cnode = topo_node_bind(mod, pnode, name, chipid, fmri))
+		    == NULL) {
 			nvlist_free(fmri);
 			whinge(mod, &nerr, "chip_create: node bind "
 			    "failed for chipid %d\n", chipid);
@@ -953,15 +930,14 @@
 
 		nvlist_free(fmri);
 
-		(void) topo_pgroup_create(cnode, CHIP_PGROUP,
-		    TOPO_STABILITY_PRIVATE, &err);
+		(void) topo_pgroup_create(cnode, &chip_pgroup, &err);
 		(void) chip_strprop(cnode, ksp, CHIP_VENDOR_ID);
 		(void) chip_longprop(cnode, ksp, CHIP_FAMILY);
 		(void) chip_longprop(cnode, ksp, CHIP_MODEL);
 		(void) chip_longprop(cnode, ksp, CHIP_STEPPING);
 
-		if (cpu_create(mod, cnode, CPU_NODE_NAME, chipid, chip) != 0 ||
-		    mc_create(mod, cnode, MCT_NODE_NAME) != 0)
+		if (cpu_create(mod, cnode, CPU_NODE_NAME, chipid, chip, auth)
+		    != 0 || mc_create(mod, cnode, MCT_NODE_NAME, auth) != 0)
 			nerr++;		/* have whinged elsewhere */
 	}
 
@@ -975,14 +951,21 @@
 	}
 }
 
+/*ARGSUSED*/
 static int
 chip_enum(topo_mod_t *mod, tnode_t *pnode, const char *name,
-    topo_instance_t min, topo_instance_t max, void *arg)
+    topo_instance_t min, topo_instance_t max, void *arg, void *notused)
 {
+	int rv = 0;
 	chip_t *chip = (chip_t *)arg;
+	nvlist_t *auth = NULL;
+
+	auth = topo_mod_auth(mod, pnode);
 
 	if (strcmp(name, "chip") == 0)
-		return (chip_create(mod, pnode, name, min, max, chip));
+		rv = chip_create(mod, pnode, name, min, max, chip, auth);
 
-	return (0);
+	nvlist_free(auth);
+
+	return (rv);
 }
--- a/usr/src/lib/fm/topo/modules/i86pc/hostbridge/Makefile	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/i86pc/hostbridge/Makefile	Sat Nov 04 01:18:55 2006 -0800
@@ -27,9 +27,29 @@
 MODULE = hostbridge
 ARCH = i86pc
 CLASS = arch
-HBSRCS = hostbridge.c did.c did_hash.c did_props.c util.c
-MODULESRCS = $(HBSRCS) hb_i86pc.c
+UTILDIR = ../../common/pcibus
+UTILSRCS = did.c did_hash.c did_props.c util.c
+HBDIR = ../../common/hostbridge
+HBSRCS = hostbridge.c hb_$(ARCH).c
+MODULESRCS = $(HBSRCS) $(UTILSRCS)
 
 include ../../Makefile.plugin
 
 LDLIBS += -ldevinfo
+
+CPPFLAGS += -I$(UTILDIR) -I$(HBDIR)
+
+%.o: $(UTILDIR)/%.c
+	$(COMPILE.c) -o $@ $<
+	$(CTFCONVERT_O)
+
+%.o: $(HBDIR)/%.c
+	$(COMPILE.c) -o $@ $<
+	$(CTFCONVERT_O)
+
+%.ln: $(UTILDIR)/%.c
+	$(LINT.c) -c $<
+
+%.ln: $(HBDIR)/%.c
+	$(LINT.c) -c $<
+
--- a/usr/src/lib/fm/topo/modules/i86pc/hostbridge/hb_i86pc.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/i86pc/hostbridge/hb_i86pc.c	Sat Nov 04 01:18:55 2006 -0800
@@ -27,58 +27,55 @@
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 #include <fm/topo_mod.h>
+#include <fm/topo_hc.h>
 #include <libdevinfo.h>
 #include <strings.h>
-#include "pcibus.h"
-#include "hostbridge.h"
-#include "did.h"
-#include "util.h"
+#include <pcibus.h>
+#include <hostbridge.h>
+#include <did.h>
+#include <util.h>
 
 static int
-hb_process(tnode_t *ptn, topo_instance_t hbi, di_node_t bn, did_hash_t *didhash,
-    di_prom_handle_t promtree, topo_mod_t *mod)
+hb_process(topo_mod_t *mod, tnode_t *ptn, topo_instance_t hbi, di_node_t bn)
 {
 	tnode_t *hb;
+	did_t *hbdid;
 
-	if (did_create(didhash, bn, 0, hbi, NO_RC, TRUST_BDF, promtree) == NULL)
+	if ((hbdid = did_create(mod, bn, 0, hbi, NO_RC, TRUST_BDF)) == NULL)
 		return (-1);
-	if ((hb = pcihostbridge_declare(ptn, bn, hbi, didhash,
-	    promtree, mod)) == NULL)
+	if ((hb = pcihostbridge_declare(mod, ptn, bn, hbi)) == NULL)
 		return (-1);
-	return (topo_mod_enumerate(mod, hb, PCI_BUS, PCI_BUS, 0,
-	    MAX_HB_BUSES));
+	return (topo_mod_enumerate(mod,
+	    hb, PCI_BUS, PCI_BUS, 0, MAX_HB_BUSES, (void *)hbdid));
 }
 
 static int
-rc_process(tnode_t *ptn, topo_instance_t hbi, di_node_t bn, did_hash_t *didhash,
-    di_prom_handle_t promtree, topo_mod_t *mod)
+rc_process(topo_mod_t *mod, tnode_t *ptn, topo_instance_t hbi, di_node_t bn)
 {
 	tnode_t *hb;
 	tnode_t *rc;
+	did_t *hbdid;
 
-	if (did_create(didhash, bn, 0, hbi, hbi, TRUST_BDF, promtree) == NULL)
+	if ((hbdid = did_create(mod, bn, 0, hbi, hbi, TRUST_BDF)) == NULL)
 		return (-1);
-	if ((hb = pciexhostbridge_declare(ptn, bn, hbi, didhash, promtree, mod))
-	    == NULL)
+	if ((hb = pciexhostbridge_declare(mod, ptn, bn, hbi)) == NULL)
 		return (-1);
-	if ((rc = pciexrc_declare(hb, bn, hbi, didhash, promtree, mod)) == NULL)
+	if ((rc = pciexrc_declare(mod, hb, bn, hbi)) == NULL)
 		return (-1);
 	return (topo_mod_enumerate(mod,
-	    rc, PCI_BUS, PCIEX_BUS, 0, MAX_HB_BUSES));
+	    rc, PCI_BUS, PCIEX_BUS, 0, MAX_HB_BUSES, (void *)hbdid));
 }
 
 
 int
-pci_hostbridges_find(tnode_t *ptn, did_hash_t *didhash,
-    di_prom_handle_t promtree, topo_mod_t *mod)
+pci_hostbridges_find(topo_mod_t *mod, tnode_t *ptn)
 {
 	di_node_t devtree;
-	di_node_t pnode;
-	di_node_t cnode;
+	di_node_t pnode, cnode;
 	int hbcnt = 0;
 
 	/* Scan for buses, top-level devinfo nodes with the right driver */
-	devtree = di_init("/", DINFOCPYALL);
+	devtree = topo_mod_devinfo(mod);
 	if (devtree == DI_NODE_NIL) {
 		topo_mod_dprintf(mod, "devinfo init failed.");
 		topo_node_range_destroy(ptn, HOSTBRIDGE);
@@ -87,9 +84,8 @@
 
 	pnode = di_drv_first_node(PCI, devtree);
 	while (pnode != DI_NODE_NIL) {
-		if (hb_process(ptn, hbcnt++, pnode, didhash, promtree, mod)
+		if (hb_process(mod, ptn, hbcnt++, pnode)
 		    < 0) {
-			di_fini(devtree);
 			topo_node_range_destroy(ptn, HOSTBRIDGE);
 			return (topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM));
 		}
@@ -103,9 +99,7 @@
 			if (di_driver_name(cnode) == NULL)
 				continue;
 			if (strcmp(di_driver_name(cnode), PCI_PCI) == 0) {
-				if (hb_process(ptn, hbcnt++, cnode, didhash,
-				    promtree, mod) < 0) {
-					di_fini(devtree);
+				if (hb_process(mod, ptn, hbcnt++, cnode) < 0) {
 					topo_node_range_destroy(ptn,
 					    HOSTBRIDGE);
 					return (topo_mod_seterrno(mod,
@@ -113,9 +107,7 @@
 				}
 			}
 			if (strcmp(di_driver_name(cnode), PCIE_PCI) == 0) {
-				if (rc_process(ptn, hbcnt++, cnode, didhash,
-				    promtree, mod) < 0) {
-					di_fini(devtree);
+				if (rc_process(mod, ptn, hbcnt++, cnode) < 0) {
 					topo_node_range_destroy(ptn,
 					    HOSTBRIDGE);
 					return (topo_mod_seterrno(mod,
@@ -125,22 +117,20 @@
 		}
 		pnode = di_drv_next_node(pnode);
 	}
-	di_fini(devtree);
 	return (0);
 }
 
 /*ARGSUSED*/
 int
-platform_hb_enum(tnode_t *parent, const char *name,
-    topo_instance_t imin, topo_instance_t imax, did_hash_t *didhash,
-    di_prom_handle_t promtree, topo_mod_t *mod)
+platform_hb_enum(topo_mod_t *mod, tnode_t *parent, const char *name,
+    topo_instance_t imin, topo_instance_t imax)
 {
-	return (pci_hostbridges_find(parent, didhash, promtree, mod));
+	return (pci_hostbridges_find(mod, parent));
 }
 
 /*ARGSUSED*/
 int
-platform_hb_label(tnode_t *node, nvlist_t *in, nvlist_t **out, topo_mod_t *mod)
+platform_hb_label(topo_mod_t *mod, tnode_t *node, nvlist_t *in, nvlist_t **out)
 {
 	return (labelmethod_inherit(mod, node, in, out));
 }
--- a/usr/src/lib/fm/topo/modules/i86pc/pcibus/Makefile	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/i86pc/pcibus/Makefile	Sat Nov 04 01:18:55 2006 -0800
@@ -29,16 +29,15 @@
 MODULE = pcibus
 ARCH = i86pc
 CLASS = arch
-PCISRCS = did.c			\
-	  did_hash.c		\
-	  did_props.c		\
-	  pcibus.c		\
-	  pcibus_labels.c	\
-	  pcifn_enum.c		\
-	  util.c
+UTILDIR = ../../common/pcibus
+HBDIR = ../../common/hostbridge
+UTILSRCS = did.c did_hash.c did_props.c util.c
+PCISRCS = pcibus.c pcibus_labels.c
 
-MODULESRCS = $(PCISRCS) pci_i86pc.c
+MODULESRCS = $(UTILSRCS) $(PCISRCS) pci_i86pc.c
 
 include ../../Makefile.plugin
 
 LDLIBS += -ldevinfo
+
+CPPFLAGS += -I$(UTILDIR) -I$(HBDIR)
--- a/usr/src/lib/fm/topo/modules/i86pc/pcibus/pci_i86pc.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/i86pc/pcibus/pci_i86pc.c	Sat Nov 04 01:18:55 2006 -0800
@@ -36,7 +36,8 @@
 missing_names_t *Missing_Names = NULL;
 
 int
-platform_pci_label(tnode_t *node, nvlist_t *in, nvlist_t **out, topo_mod_t *mod)
+platform_pci_label(topo_mod_t *mod, tnode_t *node, nvlist_t *in,
+    nvlist_t **out)
 {
-	return (pci_label_cmn(node, in, out, mod));
+	return (pci_label_cmn(mod, node, in, out));
 }
--- a/usr/src/lib/fm/topo/modules/i86pc/sata/sata.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/i86pc/sata/sata.c	Sat Nov 04 01:18:55 2006 -0800
@@ -55,8 +55,6 @@
 #include <sys/dkio.h>
 #include <pthread.h>
 
-#include "did_impl.h"
-#include "did_props.h"
 #include "sata.h"
 #include "sfx4500_props.h"
 
@@ -69,17 +67,27 @@
 	&SFX4500_machprops, NULL
 };
 
+static const topo_pgroup_info_t io_pgroup =
+	{ TOPO_PGROUP_IO, TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
+
+static const topo_pgroup_info_t storage_pgroup = {
+	TOPO_STORAGE_PGROUP,
+	TOPO_STABILITY_PRIVATE,
+	TOPO_STABILITY_PRIVATE,
+	1
+};
+
 int _topo_init(topo_mod_t *mod);
 void _topo_fini(topo_mod_t *mod);
 
 static char *devpath_from_asru(topo_mod_t *mp, tnode_t *pnode, int *dpathlen);
 static tnode_t *node_create(topo_mod_t *mod, tnode_t *pnode, const char *name,
     int instance, boolean_t add_fru, nvlist_t *fru, nvlist_t *asru,
-    char *label, int *err);
+    char *label, cfga_list_data_t *, int *err);
 static char *trimdup(const char *s, int *slen, topo_mod_t *mod);
 static boolean_t get_machine_name(char **name, int *namelen, topo_mod_t *mod);
-static int make_legacyhc_fmri(topo_hdl_t *thp, const char *str,
-    nvlist_t **fmri, int *err);
+static int make_legacyhc_fmri(topo_mod_t *mod, const char *str,
+    nvlist_t **fmri);
 static int sata_minorname_to_ap(char *minorname, char **ap, int *apbuflen,
     cfga_list_data_t **list_array, topo_mod_t *mod);
 static sata_dev_prop_t *lookup_sdp_by_minor(char *minorpath);
@@ -101,7 +109,7 @@
 static int sata_port_create(topo_mod_t *mod, tnode_t *pnode, const char *name,
     topo_instance_t min, topo_instance_t max);
 static int sata_enum(topo_mod_t *mod, tnode_t *pnode, const char *name,
-    topo_instance_t min, topo_instance_t max, void *arg);
+    topo_instance_t min, topo_instance_t max, void *notused1, void *notused2);
 static int sata_present(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
     nvlist_t **);
 static void sata_release(topo_mod_t *mod, tnode_t *nodep);
@@ -115,7 +123,7 @@
  * a presence method, and in those cases, the correct default is to
  * assert presence).
  */
-const topo_method_t SATA_METHODS[] = {
+static const topo_method_t SATA_METHODS[] = {
 	{ TOPO_METH_PRESENT, TOPO_METH_PRESENT_DESC, TOPO_METH_PRESENT_VERSION,
 	    TOPO_STABILITY_INTERNAL, sata_present },
 	{ NULL }
@@ -138,8 +146,11 @@
 static const char *pgroupname = NULL;
 
 
-const topo_modinfo_t sata_info =
-	{ "sata", SATA_VERSION, sata_enum, sata_release };
+static const topo_modops_t sata_ops =
+	{ sata_enum, sata_release };
+
+static const topo_modinfo_t sata_info =
+	{ "sata", FM_FMRI_SCHEME_HC, SATA_VERSION, &sata_ops };
 
 
 static void
@@ -209,23 +220,38 @@
  */
 static tnode_t *
 node_create(topo_mod_t *mod, tnode_t *pnode, const char *name, int instance,
-    boolean_t add_fru, nvlist_t *fru, nvlist_t *asru, char *label, int *err)
+    boolean_t add_fru, nvlist_t *fru, nvlist_t *asru, char *label,
+    cfga_list_data_t *cfgap, int *err)
 {
-	nvlist_t *pfmri = NULL, *fmri = NULL, *args = NULL;
+	int len = 0;
+	nvlist_t *fmri = NULL;
+	nvlist_t *auth = NULL;
 	tnode_t *cnode = NULL;
-	topo_hdl_t *thp;
+	char *mm = NULL, *model = NULL, *manuf = NULL, *serial = NULL;
+	char *firm = NULL;
+	int manuf_len, model_len, serial_len, firm_len;
 
-	thp = topo_mod_handle(mod);
+	if (cfgap != NULL) {
+		char *s;
 
-	if (topo_node_resource(pnode, &pfmri, err) == 0 &&
-	    topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) == 0 &&
-	    nvlist_add_nvlist(args, TOPO_METH_FMRI_ARG_PARENT, pfmri) == 0 &&
-	    (fmri = topo_fmri_create(thp, FM_FMRI_SCHEME_HC, name, instance,
-	    args, err)) != NULL &&
-	    (cnode = topo_node_bind(mod, pnode, name, instance, fmri,
-	    NULL)) != NULL) {
+		sata_info_to_fru(cfgap->ap_info, &model, &model_len, &manuf,
+		    &manuf_len, &serial, &serial_len, &firm, &firm_len, mod);
+		if ((s = strchr(model, ' ')) != NULL)
+			*s = '-';
+		len = manuf_len + model_len + 1;
+		if ((mm = topo_mod_alloc(mod, len)) != NULL)
+			(void) snprintf(mm, len, "%s-%s", manuf, model);
+		else
+			mm = model;
+	}
 
-		/* Set the FRU to the node's FMRI if called didn't specify it */
+	auth = topo_mod_auth(mod, pnode);
+	if ((fmri = topo_mod_hcfmri(mod, pnode, FM_HC_SCHEME_VERSION, name,
+	    instance, NULL, auth, mm, serial, firm))
+	    != NULL && (cnode = topo_node_bind(mod, pnode, name, instance,
+	    fmri)) != NULL) {
+
+		/* Set the FRU to the node's FMRI if caller didn't specify it */
 		if (add_fru)
 			(void) topo_node_fru_set(cnode, fru ? fru : fmri, 0,
 			    err);
@@ -237,12 +263,20 @@
 			(void) topo_node_label_set(cnode, label, err);
 	}
 
-	if (pfmri)
-		nvlist_free(pfmri);
+	if (len != 0)
+		topo_mod_free(mod, mm, len);
+	if (model)
+		topo_mod_free(mod, model, model_len);
+	if (manuf)
+		topo_mod_free(mod, manuf, manuf_len);
+	if (serial)
+		topo_mod_free(mod, serial, serial_len);
+	if (firm)
+		topo_mod_free(mod, firm, firm_len);
 	if (fmri)
 		nvlist_free(fmri);
-	if (args)
-		nvlist_free(args);
+	if (auth)
+		nvlist_free(auth);
 
 	return (cnode);
 }
@@ -294,7 +328,8 @@
 	int mnamelen;
 	char *mname;
 
-	topo_mod_setdebug(mod, TOPO_DBG_ALL);
+	if (getenv("SATADBG"))
+		topo_mod_setdebug(mod);
 	topo_mod_dprintf(mod, "initializing sata enumerator\n");
 
 	(void) pthread_mutex_lock(&global_data_mutex);
@@ -323,7 +358,7 @@
 	}
 	(void) pthread_mutex_unlock(&global_data_mutex);
 
-	if (topo_mod_register(mod, &sata_info, NULL) != 0) {
+	if (topo_mod_register(mod, &sata_info, TOPO_VERSION) != 0) {
 		topo_mod_dprintf(mod, "failed to register sata module: "
 		    "%s\n", topo_mod_errmsg(mod));
 		return (-1); /* mod errno set */
@@ -338,13 +373,13 @@
 }
 
 static int
-make_legacyhc_fmri(topo_hdl_t *thp, const char *str, nvlist_t **fmri, int *err)
+make_legacyhc_fmri(topo_mod_t *mod, const char *str, nvlist_t **fmri)
 {
 	char buf[PATH_MAX];
 
 	(void) snprintf(buf, PATH_MAX, "hc:///component=%s", str);
 
-	return (topo_fmri_str2nvl(thp, buf, fmri, err));
+	return (topo_mod_str2nvl(mod, buf, fmri));
 }
 
 
@@ -490,7 +525,14 @@
 		}
 	}
 
-	return (present);
+	if (topo_mod_nvalloc(mod, out_nvl, NV_UNIQUE_NAME) != 0)
+		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+	if (nvlist_add_uint32(*out_nvl, TOPO_METH_PRESENT_RET, present) != 0) {
+		nvlist_free(*out_nvl);
+		return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
+	}
+
+	return (0);
 }
 
 /*
@@ -627,6 +669,7 @@
 	dentlen = pathconf(devpath, _PC_NAME_MAX);
 	dentlen = ((dentlen <= 0) ? MAXNAMELEN : dentlen) +
 	    sizeof (struct dirent);
+	dentlen = sizeof (struct dirent) + pathconf(devpath, _PC_NAME_MAX);
 	dent = topo_mod_alloc(mod, dentlen);
 
 	/*
@@ -663,26 +706,29 @@
 	int i;
 #define	MAX_PNAME_LEN	128
 	char pname[MAX_PNAME_LEN];
+	topo_pgroup_info_t pgroup;
 
 	/*
 	 * Save the attachment point physical path
 	 */
-	(void) topo_pgroup_create(cnode, TOPO_PGROUP_IO,
-	    TOPO_STABILITY_PRIVATE, err);
+	(void) topo_pgroup_create(cnode, &io_pgroup, err);
 	(void) topo_prop_set_string(cnode, TOPO_PGROUP_IO,
-	    TOPO_IO_AP_PATH, TOPO_PROP_SET_ONCE,
+	    TOPO_IO_AP_PATH, TOPO_PROP_IMMUTABLE,
 	    sdp->ap_node, err);
 
 	/*
 	 * The private properties are the core of the configuration
 	 * mechanism for the sfx4500-disk Diagnosis Engine.
 	 */
-	(void) topo_pgroup_create(cnode, pgroupname,
-	    TOPO_STABILITY_PRIVATE, err);
+	pgroup.tpi_name = pgroupname;
+	pgroup.tpi_namestab = TOPO_STABILITY_PRIVATE;
+	pgroup.tpi_datastab = TOPO_STABILITY_PRIVATE;
+	pgroup.tpi_version = 1;
+	(void) topo_pgroup_create(cnode, &pgroup, err);
 
 	for (i = 0; sdp->properties[i].name != NULL; i++) {
 		(void) topo_prop_set_string(cnode, pgroupname,
-		    sdp->properties[i].name, TOPO_PROP_SET_ONCE,
+		    sdp->properties[i].name, TOPO_PROP_IMMUTABLE,
 		    (char *)sdp->properties[i].value, err);
 	}
 
@@ -696,13 +742,13 @@
 		(void) snprintf(pname, MAX_PNAME_LEN, SATA_IND_NAME "-%d",
 		    i);
 		(void) topo_prop_set_string(cnode, pgroupname, pname,
-		    TOPO_PROP_SET_ONCE, (char *)sdp->indicators[i].indicator,
+		    TOPO_PROP_IMMUTABLE, (char *)sdp->indicators[i].indicator,
 		    err);
 
 		(void) snprintf(pname, MAX_PNAME_LEN, SATA_IND_ACTION "-%d",
 		    i);
 		(void) topo_prop_set_string(cnode, pgroupname, pname,
-		    TOPO_PROP_SET_ONCE, (char *)sdp->indicators[i].action,
+		    TOPO_PROP_IMMUTABLE, (char *)sdp->indicators[i].action,
 		    err);
 	}
 
@@ -711,13 +757,13 @@
 		(void) snprintf(pname, MAX_PNAME_LEN, SATA_INDRULE_STATES "-%d",
 		    i);
 		(void) topo_prop_set_string(cnode, pgroupname, pname,
-		    TOPO_PROP_SET_ONCE, (char *)ruleset[i].states,
+		    TOPO_PROP_IMMUTABLE, (char *)ruleset[i].states,
 		    err);
 
 		(void) snprintf(pname, MAX_PNAME_LEN,
 		    SATA_INDRULE_ACTIONS "-%d", i);
 		(void) topo_prop_set_string(cnode, pgroupname, pname,
-		    TOPO_PROP_SET_ONCE, (char *)ruleset[i].actions,
+		    TOPO_PROP_IMMUTABLE, (char *)ruleset[i].actions,
 		    err);
 	}
 }
@@ -813,18 +859,16 @@
 
 	if (find_physical_disk_node(physpath, PATH_MAX, portnum, mod)) {
 
-		(void) topo_pgroup_create(cnode, TOPO_PGROUP_IO,
-		    TOPO_STABILITY_PRIVATE, err);
+		(void) topo_pgroup_create(cnode, &io_pgroup, err);
 
 		(void) topo_prop_set_string(cnode, TOPO_PGROUP_IO,
-		    TOPO_IO_DEV_PATH, TOPO_PROP_SET_ONCE,
+		    TOPO_IO_DEV_PATH, TOPO_PROP_IMMUTABLE,
 		    physpath + 8 /* strlen("/devices") */,
 		    err);
 		physpath_found = B_TRUE;
 	}
 
-	(void) topo_pgroup_create(cnode, TOPO_STORAGE_PGROUP,
-	    TOPO_STABILITY_PRIVATE, err);
+	(void) topo_pgroup_create(cnode, &storage_pgroup, err);
 
 	if ((ldev = strstr(cfgap->ap_log_id, "::")) != NULL) {
 		ldev += 2 /* strlen("::") */;
@@ -832,7 +876,7 @@
 			ldev = p + 1;
 		}
 		(void) topo_prop_set_string(cnode, TOPO_STORAGE_PGROUP,
-		    TOPO_STORAGE_LOGICAL_DISK_NAME, TOPO_PROP_SET_ONCE,
+		    TOPO_STORAGE_LOGICAL_DISK_NAME, TOPO_PROP_IMMUTABLE,
 		    ldev, err);
 	}
 
@@ -840,22 +884,22 @@
 	    &serial, &serial_len, &firm, &firm_len, mod);
 	if (model) {
 		(void) topo_prop_set_string(cnode, TOPO_STORAGE_PGROUP,
-		    TOPO_STORAGE_MODEL, TOPO_PROP_SET_ONCE, model, err);
+		    TOPO_STORAGE_MODEL, TOPO_PROP_IMMUTABLE, model, err);
 		topo_mod_free(mod, model, model_len);
 	}
 	if (manuf) {
 		(void) topo_prop_set_string(cnode, TOPO_STORAGE_PGROUP,
-		    TOPO_STORAGE_MANUFACTURER, TOPO_PROP_SET_ONCE, manuf, err);
+		    TOPO_STORAGE_MANUFACTURER, TOPO_PROP_IMMUTABLE, manuf, err);
 		topo_mod_free(mod, manuf, manuf_len);
 	}
 	if (serial) {
 		(void) topo_prop_set_string(cnode, TOPO_STORAGE_PGROUP,
-		    TOPO_STORAGE_SERIAL_NUM, TOPO_PROP_SET_ONCE, serial, err);
+		    TOPO_STORAGE_SERIAL_NUM, TOPO_PROP_IMMUTABLE, serial, err);
 		topo_mod_free(mod, serial, serial_len);
 	}
 	if (firm) {
 		(void) topo_prop_set_string(cnode, TOPO_STORAGE_PGROUP,
-		    TOPO_STORAGE_FIRMWARE_REV, TOPO_PROP_SET_ONCE, firm, err);
+		    TOPO_STORAGE_FIRMWARE_REV, TOPO_PROP_IMMUTABLE, firm, err);
 		topo_mod_free(mod, firm, firm_len);
 	}
 
@@ -885,7 +929,7 @@
 			(void) snprintf(capstr, sizeof (capstr), "%llu",
 			    capacity);
 			(void) topo_prop_set_string(cnode, TOPO_STORAGE_PGROUP,
-			    TOPO_STORAGE_CAPACITY, TOPO_PROP_SET_ONCE, capstr,
+			    TOPO_STORAGE_CAPACITY, TOPO_PROP_IMMUTABLE, capstr,
 			    err);
 		}
 	}
@@ -918,13 +962,10 @@
     int ndisks, int *err)
 {
 	tnode_t *cnode;
-	topo_hdl_t *thp;
 	sata_dev_prop_t *sdp;
 	nvlist_t *fru = NULL;
 	int i, nerrs = 0;
 
-	thp = topo_mod_handle(mod);
-
 	if (topo_node_range_create(mod, pnode, name, 0, ndisks - 1) < 0) {
 		topo_mod_dprintf(mod, "Unable to create "
 		    SATA_DISK " range [%d..%d]: %s\n",
@@ -942,12 +983,12 @@
 
 			if ((sdp = lookup_sdp_by_minor(cfglist[i].ap_phys_id))
 			    != NULL) {
-				if (make_legacyhc_fmri(thp, sdp->label, &fru,
-				    err) != 0) {
+				if (make_legacyhc_fmri(mod, sdp->label, &fru)
+				    != 0) {
 					topo_mod_dprintf(mod, "Error creating "
 					    "FRU while creating " SATA_DISK
 					    " nodes: %s\n",
-					    topo_strerror(*err));
+					    topo_mod_errmsg(mod));
 				}
 			}
 
@@ -962,7 +1003,7 @@
 			 */
 			if ((cnode = node_create(mod, pnode, name, i,
 			    B_TRUE, fru, pasru, sdp ? (char *)sdp->label : NULL,
-			    err)) != NULL) {
+			    &cfglist[i], err)) != NULL) {
 
 				sata_add_disk_props(cnode, portnum, &cfglist[i],
 				    err, mod);
@@ -998,13 +1039,10 @@
 	char *dpath;
 	char *ap = NULL;
 	char minorname[PATH_MAX];
-	topo_hdl_t *thp;
 	int apbuflen;
 	int dpathlen;
 	cfga_list_data_t *cfglist = NULL;
 
-	thp = topo_mod_handle(mod);
-
 	if (min < 0)
 		min = 0;
 
@@ -1028,16 +1066,8 @@
 		return (-1);
 	}
 
-	if (topo_node_range_create(mod, pnode, name, 0, max) < 0) {
-		topo_mod_dprintf(mod, "Unable to create "
-		    SATA_PORT " range [%d..%d]: %s\n",
-		    min, max, topo_mod_errmsg(mod));
-		topo_mod_free(mod, dpath, dpathlen);
-		return (-1);
-	}
-
 	/* Create the FRU - a legacy component FMRI */
-	if (make_legacyhc_fmri(thp, "MB", &fru, &err) != 0) {
+	if (make_legacyhc_fmri(mod, "motherboard", &fru) != 0) {
 		topo_mod_dprintf(mod, "Unable to create legacy FRU FMRI for "
 		    "node " SATA_PORT ": %s\n",
 		    topo_strerror(err));
@@ -1059,7 +1089,7 @@
 		}
 
 		/* Create the ASRU - a legacy component FMRI */
-		if (make_legacyhc_fmri(thp, ap, &asru, &err) != 0) {
+		if (make_legacyhc_fmri(mod, ap, &asru) != 0) {
 			free(cfglist);
 			topo_mod_free(mod, ap, apbuflen);
 			topo_mod_dprintf(mod, "failed to make ASRU FMRI: "
@@ -1075,7 +1105,7 @@
 		 * component being "MB".
 		 */
 		if ((cnode = node_create(mod, pnode, name, i, B_TRUE, fru,
-		    asru, ap, &err)) == NULL) {
+		    asru, ap, NULL, &err)) == NULL) {
 			nvlist_free(asru);
 			free(cfglist);
 			topo_mod_free(mod, ap, apbuflen);
@@ -1127,7 +1157,7 @@
 /*ARGSUSED*/
 static int
 sata_enum(topo_mod_t *mod, tnode_t *pnode, const char *name,
-    topo_instance_t min, topo_instance_t max, void *arg)
+    topo_instance_t min, topo_instance_t max, void *notused1, void *notused2)
 {
 	if (strcmp(name, SATA_PORT) == 0)
 		return (sata_port_create(mod, pnode, name, min, max));
--- a/usr/src/lib/fm/topo/modules/i86pc/sata/sata.h	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/i86pc/sata/sata.h	Sat Nov 04 01:18:55 2006 -0800
@@ -33,12 +33,13 @@
 extern "C" {
 #endif
 
+#include <fm/libtopo.h>
+
 /* Topo plugin version */
 #define	SATA_VERSION			1
 
 /* The names of the two nodes the plugin creates: */
-#define	SATA_DISK			"disk"
-#define	SATA_PORT			"sata-port"
+#define	SATA_DISK			DISK /* from topo_hc.h */
 
 #define	TOPO_STORAGE_PGROUP		"storage"
 
@@ -50,10 +51,6 @@
 #define	TOPO_STORAGE_FIRMWARE_REV	"disk-firmware-revision"
 #define	TOPO_STORAGE_CAPACITY		"disk-capacity-in-bytes"
 
-/* Properties added to the "io" pgroup: */
-#define	TOPO_IO_DEV_PATH		"dev-path"
-#define	TOPO_IO_AP_PATH			"ap-path"
-
 /* Properties added to the machine-specific properties pgroup */
 #define	SATA_IND_NAME			"indicator-name"
 #define	SATA_IND_ACTION			"indicator-action"
--- a/usr/src/lib/fm/topo/modules/sun4/chip/chip.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/sun4/chip/chip.c	Sat Nov 04 01:18:55 2006 -0800
@@ -65,17 +65,20 @@
 } chip_t;
 
 static int chip_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t,
-    topo_instance_t, void *);
+    topo_instance_t, void *, void *);
 
-const topo_modinfo_t chip_info =
-	{ "chip", CHIP_VERSION, chip_enum, NULL};
+static const topo_modops_t chip_ops =
+	{ chip_enum, NULL};
+static const topo_modinfo_t chip_info =
+	{ "chip", FM_FMRI_SCHEME_HC, CHIP_VERSION, &chip_ops };
 
 int
 _topo_init(topo_mod_t *mod)
 {
 	chip_t *chip;
 
-	topo_mod_setdebug(mod, TOPO_DBG_ALL);
+	if (getenv("TOPOCHIPDBG"))
+		topo_mod_setdebug(mod);
 	topo_mod_dprintf(mod, "initializing chip enumerator\n");
 
 	if ((chip = topo_mod_zalloc(mod, sizeof (chip_t))) == NULL)
@@ -96,7 +99,7 @@
 		return (-1);
 	}
 
-	if (topo_mod_register(mod, &chip_info, (void *)chip) != 0) {
+	if (topo_mod_register(mod, &chip_info, TOPO_VERSION) != 0) {
 		topo_mod_dprintf(mod, "failed to register hc: "
 		    "%s\n", topo_mod_errmsg(mod));
 		topo_mod_free(mod, chip->chip_cpustats,
@@ -105,6 +108,7 @@
 		topo_mod_free(mod, chip, sizeof (chip_t));
 		return (-1);
 	}
+	topo_mod_setspecific(mod, (void *)chip);
 
 	return (0);
 }
@@ -114,7 +118,7 @@
 {
 	chip_t *chip;
 
-	chip = topo_mod_private(mod);
+	chip = topo_mod_getspecific(mod);
 
 	if (chip->chip_cpustats != NULL)
 		topo_mod_free(mod, chip->chip_cpustats,
@@ -177,9 +181,8 @@
 	char *s, sbuf[21];
 	tnode_t *cnode;
 	kstat_named_t *ks, *kf;
-	nvlist_t *pfmri, *fmri, *asru;
-	nvlist_t *args = NULL;
-	topo_hdl_t *thp;
+	nvlist_t *fmri, *asru;
+	nvlist_t *auth = topo_mod_auth(mod, rnode);
 
 	/*
 	 * Override what was created for us
@@ -189,7 +192,6 @@
 	    < 0)
 		return (topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM));
 
-	thp = topo_mod_handle(mod);
 	for (i = 0; i <= chip->chip_ncpustats; i++) {
 
 		if ((chip_id = cpu_kstat_init(chip, i)) < 0)
@@ -203,29 +205,10 @@
 			s = NULL;
 		}
 
-		pfmri = NULL;
-		if (topo_node_resource(rnode, &pfmri, &err) < 0 ||
-		    topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0) {
-			nvlist_free(pfmri);
-			++nerr;
-			continue;
-		}
-		err = nvlist_add_nvlist(args, TOPO_METH_FMRI_ARG_PARENT, pfmri);
-		if (err != 0 ||
-		    (s != NULL &&
-		    nvlist_add_string(args, TOPO_METH_FMRI_ARG_SER, s) != 0)) {
-			nvlist_free(pfmri);
-			nvlist_free(args);
-			++nerr;
-			continue;
-		}
-		nvlist_free(pfmri);
-
-		fmri = topo_fmri_create(thp, FM_FMRI_SCHEME_HC,
-		    name, (topo_instance_t)chip_id, args, &err);
-		nvlist_free(args);
+		fmri = topo_mod_hcfmri(mod, rnode, FM_HC_SCHEME_VERSION, name,
+		    (topo_instance_t)chip_id, NULL, auth, NULL, NULL, s);
 		if (fmri == NULL || (cnode = topo_node_bind(mod,
-		    rnode, name, i, fmri, NULL)) == NULL) {
+		    rnode, name, i, fmri)) == NULL) {
 			++nerr;
 			nvlist_free(fmri);
 			continue;
@@ -252,29 +235,38 @@
 		    != NULL && strcmp(KSTAT_NAMED_STR_PTR(kf),
 		    "hc:///component=") != 0) {
 			nvlist_t *fru;
+			char *lp;
 
-			if (topo_fmri_str2nvl(thp, KSTAT_NAMED_STR_PTR(kf),
-			    &fru, &err) == 0) {
+			if (topo_mod_str2nvl(mod, KSTAT_NAMED_STR_PTR(kf),
+			    &fru) == 0) {
 				(void) topo_node_fru_set(cnode, fru, 0, &err);
 				nvlist_free(fru);
 			}
 
-			(void) topo_node_label_set(cnode,
-			    KSTAT_NAMED_STR_PTR(kf), &err);
+			if ((lp = strchr(KSTAT_NAMED_STR_PTR(kf), '='))
+			    == NULL) {
+				(void) topo_node_label_set(cnode, NULL, &err);
+			} else {
+				++lp;
+				(void) topo_node_label_set(cnode, lp, &err);
+			}
 		} else {
 			(void) topo_node_label_set(cnode, NULL, &err);
 		}
 	}
 
+	nvlist_free(auth);
+
 	if (nerr != 0)
 		return (topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM));
 	else
 		return (0);
 }
 
+/*ARGSUSED*/
 static int
 chip_enum(topo_mod_t *mod, tnode_t *rnode, const char *name,
-    topo_instance_t min, topo_instance_t max, void *arg)
+    topo_instance_t min, topo_instance_t max, void *arg, void *notused)
 {
 	chip_t *chip = (chip_t *)arg;
 
--- a/usr/src/lib/fm/topo/modules/sun4/hostbridge/Makefile.hb	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/sun4/hostbridge/Makefile.hb	Sat Nov 04 01:18:55 2006 -0800
@@ -28,17 +28,26 @@
 MODULE = hostbridge
 CLASS = arch
 SUN4DIR = ../../sun4/$(MODULE)
+UTILDIR = ../../common/pcibus
+HBDIR = ../../common/hostbridge
 HBSRCS = hostbridge.c hb_sun4.c did.c did_hash.c did_props.c util.c
 MODULESRCS = $(HBSRCS) hb_$(ARCH).c
 
 include ../../Makefile.plugin
 
 LDLIBS += -ldevinfo
-CPPFLAGS += -I$(SUN4DIR)
+CPPFLAGS += -I$(SUN4DIR) -I$(UTILDIR) -I$(HBDIR)
 
 %.o: $(SUN4DIR)/%.c
 	$(COMPILE.c) -o $@ $<
 	$(CTFCONVERT_O)
 
+%.o: $(UTILDIR)/%.c
+	$(COMPILE.c) -o $@ $<
+	$(CTFCONVERT_O)
+
 %.ln: $(SUN4DIR)/%.c
 	$(LINT.c) -c $<
+
+%.ln: $(UTILDIR)/%.c
+	$(LINT.c) -c $<
--- a/usr/src/lib/fm/topo/modules/sun4/hostbridge/hb_sun4.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/sun4/hostbridge/hb_sun4.c	Sat Nov 04 01:18:55 2006 -0800
@@ -32,15 +32,14 @@
 #include <sys/param.h>
 #include <sys/systeminfo.h>
 
-#include "hb_sun4.h"
-#include "util.h"
-#include "topo_error.h"
-#include "hostbridge.h"
-#include "pcibus.h"
-#include "did.h"
+#include <hb_sun4.h>
+#include <util.h>
+#include <hostbridge.h>
+#include <pcibus.h>
+#include <did.h>
 
 busorrc_t *
-busorrc_new(const char *bus_addr, di_node_t di, topo_mod_t *mod)
+busorrc_new(topo_mod_t *mod, const char *bus_addr, di_node_t di)
 {
 	busorrc_t *pp;
 	char *comma;
@@ -83,7 +82,7 @@
 }
 
 void
-busorrc_insert(busorrc_t **head, busorrc_t *new, topo_mod_t *mod)
+busorrc_insert(topo_mod_t *mod, busorrc_t **head, busorrc_t *new)
 {
 	busorrc_t *ppci, *pci;
 
@@ -122,7 +121,7 @@
 }
 
 int
-busorrc_add(busorrc_t **list, di_node_t n, topo_mod_t *mod)
+busorrc_add(topo_mod_t *mod, busorrc_t **list, di_node_t n)
 {
 	busorrc_t *nb;
 	char *ba;
@@ -130,49 +129,45 @@
 	topo_mod_dprintf(mod, "busorrc_add\n");
 	ba = di_bus_addr(n);
 	if (ba == NULL ||
-	    (nb = busorrc_new(ba, n, mod)) == NULL) {
+	    (nb = busorrc_new(mod, ba, n)) == NULL) {
 		topo_mod_dprintf(mod, "busorrc_new() failed.\n");
 		return (-1);
 	}
-	busorrc_insert(list, nb, mod);
+	busorrc_insert(mod, list, nb);
 	return (0);
 }
 
 void
-busorrc_free(busorrc_t *pb, topo_mod_t *mod)
+busorrc_free(topo_mod_t *mod, busorrc_t *pb)
 {
 	if (pb == NULL)
 		return;
-	busorrc_free(pb->br_nextbus, mod);
+	busorrc_free(mod, pb->br_nextbus);
 	topo_mod_free(mod, pb, sizeof (busorrc_t));
 }
 
 tnode_t *
-hb_process(tnode_t *ptn, topo_instance_t hbi, topo_instance_t bi,
-    di_node_t bn, did_hash_t *didhash, di_prom_handle_t promtree,
-    topo_mod_t *mod)
+hb_process(topo_mod_t *mod, tnode_t *ptn, topo_instance_t hbi,
+    topo_instance_t bi, di_node_t bn, did_t *hbdid)
 {
 	tnode_t *hb;
 
-	if ((hb = pcihostbridge_declare(ptn, bn, hbi, didhash,
-	    promtree, mod)) == NULL)
+	if ((hb = pcihostbridge_declare(mod, ptn, bn, hbi)) == NULL)
 		return (NULL);
-	if (topo_mod_enumerate(mod, hb, PCI_BUS, PCI_BUS, bi, bi) == 0)
+	if (topo_mod_enumerate(mod, hb, PCI_BUS, PCI_BUS, bi, bi, hbdid) == 0)
 		return (hb);
 	return (NULL);
 }
 
 tnode_t *
-rc_process(tnode_t *ptn, topo_instance_t rci, di_node_t bn,
-    did_hash_t *didhash, di_prom_handle_t promtree, topo_mod_t *mod)
+rc_process(topo_mod_t *mod, tnode_t *ptn, topo_instance_t rci, di_node_t bn)
 {
 	tnode_t *rc;
 
-	if ((rc = pciexrc_declare(ptn, bn, rci, didhash, promtree, mod))
-	    == NULL)
+	if ((rc = pciexrc_declare(mod, ptn, bn, rci)) == NULL)
 		return (NULL);
 	if (topo_mod_enumerate(mod,
-	    rc, PCI_BUS, PCIEX_BUS, 0, MAX_HB_BUSES) == 0)
+	    rc, PCI_BUS, PCIEX_BUS, 0, MAX_HB_BUSES, NULL) == 0)
 		return (rc);
 	return (NULL);
 }
@@ -199,8 +194,8 @@
  *	(Hostbridge #nhb, Root Complex #(rcs/hostbridge), ExBus #(buses/rc))
  */
 int
-declare_exbuses(busorrc_t *list, tnode_t *ptn, int nhb, int nrc,
-    did_hash_t *didhash, di_prom_handle_t promtree, topo_mod_t *mod)
+declare_exbuses(topo_mod_t *mod, busorrc_t *list, tnode_t *ptn, int nhb,
+    int nrc)
 {
 	tnode_t **rcs;
 	tnode_t **hb;
@@ -211,37 +206,36 @@
 	 * Allocate an array to point at the hostbridge tnode_t pointers.
 	 */
 	if ((hb = topo_mod_zalloc(mod, nhb * sizeof (tnode_t *))) == NULL)
-		return (topo_mod_seterrno(mod, ETOPO_NOMEM));
+		return (topo_mod_seterrno(mod, EMOD_NOMEM));
 
 	/*
 	 * Allocate an array to point at the root complex tnode_t pointers.
 	 */
 	if ((rcs = topo_mod_zalloc(mod, nrc * sizeof (tnode_t *))) == NULL)
-		return (topo_mod_seterrno(mod, ETOPO_NOMEM));
+		return (topo_mod_seterrno(mod, EMOD_NOMEM));
 
 	br = rc = 0;
 	for (p = list; p != NULL; p = p->br_nextbus) {
 		topo_mod_dprintf(mod,
 		    "declaring (%x,%x)\n", p->br_ba_bc, p->br_ba_ac);
 
-		if (did_create(didhash, p->br_din, 0, br, rc, rc,
-		    promtree) == NULL)
+		if (did_create(mod, p->br_din, 0, br, rc, rc) == NULL)
 			return (-1);
 
 		if (hb[br] == NULL) {
-			hb[br] = pciexhostbridge_declare(ptn, p->br_din, br,
-			    didhash, promtree, mod);
+			hb[br] = pciexhostbridge_declare(mod, ptn, p->br_din,
+			    br);
 			if (hb[br] == NULL)
 				return (-1);
 		}
 		if (rcs[rc] == NULL) {
-			rcs[rc] = rc_process(hb[br], rc, p->br_din, didhash,
-			    promtree, mod);
+			rcs[rc] = rc_process(mod, hb[br], rc, p->br_din);
 			if (rcs[rc] == NULL)
 				return (-1);
 		} else {
 			if (topo_mod_enumerate(mod,
-			    rcs[rc], PCI_BUS, PCIEX_BUS, 0, MAX_HB_BUSES) < 0)
+			    rcs[rc], PCI_BUS, PCIEX_BUS, 0, MAX_HB_BUSES,
+			    NULL) < 0)
 				return (-1);
 		}
 		rc++;
@@ -271,8 +265,7 @@
  *	(Hostbridge #nhb, Bus #(buses/hostbridge))
  */
 int
-declare_buses(busorrc_t *list, tnode_t *ptn, int nhb, did_hash_t *didhash,
-    di_prom_handle_t promtree, topo_mod_t *mod)
+declare_buses(topo_mod_t *mod, busorrc_t *list, tnode_t *ptn, int nhb)
 {
 	busorrc_t *p;
 	tnode_t **hb;
@@ -290,19 +283,18 @@
 		topo_mod_dprintf(mod,
 		    "declaring (%x,%x)\n", p->br_ba_bc, p->br_ba_ac);
 
-		if ((link = did_create(didhash, p->br_din, 0, br, NO_RC, bus,
-		    promtree)) == NULL)
+		if ((link =
+		    did_create(mod, p->br_din, 0, br, NO_RC, bus)) == NULL)
 			return (-1);
 
 		if (hb[br] == NULL) {
-			hb[br] = hb_process(ptn, br, bus, p->br_din, didhash,
-			    promtree, mod);
+			hb[br] = hb_process(mod, ptn, br, bus, p->br_din, link);
 			if (hb[br] == NULL)
 				return (-1);
 		} else {
-			did_link_set(hb[br], link);
+			did_link_set(mod, hb[br], link);
 			if (topo_mod_enumerate(mod,
-			    hb[br], PCI_BUS, PCI_BUS, bus, bus) < 0) {
+			    hb[br], PCI_BUS, PCI_BUS, bus, bus, link) < 0) {
 				return (-1);
 			}
 		}
--- a/usr/src/lib/fm/topo/modules/sun4/hostbridge/hb_sun4.h	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/sun4/hostbridge/hb_sun4.h	Sat Nov 04 01:18:55 2006 -0800
@@ -47,20 +47,14 @@
 
 struct did_hash;
 
-extern busorrc_t *busorrc_new(const char *, di_node_t, topo_mod_t *);
-extern void busorrc_insert(busorrc_t **, busorrc_t *, topo_mod_t *);
-extern int busorrc_add(busorrc_t **, di_node_t, topo_mod_t *);
-extern void busorrc_free(busorrc_t *, topo_mod_t *);
+extern busorrc_t *busorrc_new(topo_mod_t *, const char *, di_node_t);
+extern void busorrc_insert(topo_mod_t *, busorrc_t **, busorrc_t *);
+extern int busorrc_add(topo_mod_t *, busorrc_t **, di_node_t);
+extern void busorrc_free(topo_mod_t *, busorrc_t *);
 
-extern tnode_t *hb_process(tnode_t *,
-    topo_instance_t, topo_instance_t, di_node_t, struct did_hash *,
-    di_prom_handle_t, topo_mod_t *);
-extern tnode_t *rc_process(tnode_t *, topo_instance_t, di_node_t,
-    struct did_hash *, di_prom_handle_t, topo_mod_t *);
-extern int declare_buses(busorrc_t *, tnode_t *, int,
-    struct did_hash *, di_prom_handle_t, topo_mod_t *);
-extern int declare_exbuses(busorrc_t *, tnode_t *, int, int,
-    struct did_hash *, di_prom_handle_t, topo_mod_t *);
+extern tnode_t *rc_process(topo_mod_t *, tnode_t *, topo_instance_t, di_node_t);
+extern int declare_buses(topo_mod_t *, busorrc_t *, tnode_t *, int);
+extern int declare_exbuses(topo_mod_t *, busorrc_t *, tnode_t *, int, int);
 
 #ifdef __cplusplus
 }
--- a/usr/src/lib/fm/topo/modules/sun4/ioboard/Makefile.iob	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/sun4/ioboard/Makefile.iob	Sat Nov 04 01:18:55 2006 -0800
@@ -27,17 +27,27 @@
 
 MODULE = ioboard
 SUN4DIR = ../../sun4/$(MODULE)
-IOBSRCS = ioboard.c did.c did_hash.c did_props.c util.c
-MODULESRCS = $(IOBSRCS) iob_platform.c
+UTILDIR = ../../common/pcibus
+UTILSRCS = did.c did_hash.c did_props.c util.c
+HBDIR = ../../common/hostbridge
+IOBSRCS = ioboard.c
+MODULESRCS = $(UTILSRCS) $(IOBSRCS) iob_platform.c
 
 include ../../Makefile.plugin
 
 LDLIBS += -ldevinfo
-CPPFLAGS += -I$(SUN4DIR)
+CPPFLAGS += -I$(UTILDIR) -I$(HBDIR) -I$(SUN4DIR)
+
+%.o: $(UTILDIR)/%.c
+	$(COMPILE.c) -o $@ $<
+	$(CTFCONVERT_O)
 
 %.o: $(SUN4DIR)/%.c
 	$(COMPILE.c) -o $@ $<
 	$(CTFCONVERT_O)
 
+%.ln: $(UTILDIR)/%.c
+	$(LINT.c) -c $<
+
 %.ln: $(SUN4DIR)/%.c
 	$(LINT.c) -c $<
--- a/usr/src/lib/fm/topo/modules/sun4/ioboard/ioboard.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/sun4/ioboard/ioboard.c	Sat Nov 04 01:18:55 2006 -0800
@@ -29,42 +29,42 @@
 #include <string.h>
 #include <sys/fm/protocol.h>
 #include <fm/topo_mod.h>
+#include <fm/topo_hc.h>
 #include <libdevinfo.h>
 #include <limits.h>
 #include <sys/param.h>
 #include <sys/systeminfo.h>
 
-#include "hostbridge.h"
-#include "ioboard.h"
-#include "did.h"
-#include "did_props.h"
-#include "util.h"
+#include <hostbridge.h>
+#include <ioboard.h>
+#include <did.h>
+#include <did_props.h>
+#include <util.h>
 
 /*
  * ioboard.c
  *	Generic code shared by all the ioboard enumerators
  */
+
 static void iob_release(topo_mod_t *, tnode_t *);
-static int iob_contains(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
-    nvlist_t **);
-static int iob_present(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
-    nvlist_t **);
 static int iob_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t,
-    topo_instance_t, void *);
+    topo_instance_t, void *, void *);
 static int iob_label(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *,
     nvlist_t **);
 
+extern int platform_iob_enum(topo_mod_t *, tnode_t *, topo_instance_t,
+    topo_instance_t);
+extern int platform_iob_label(topo_mod_t *, tnode_t *, nvlist_t *, nvlist_t **);
+
 extern txprop_t IOB_common_props[];
 extern int IOB_propcnt;
 
-const topo_modinfo_t Iob_info =
-	{ IOBOARD, IOB_ENUMR_VERS, iob_enum, iob_release };
+static const topo_modops_t Iob_ops =
+	{ iob_enum, iob_release };
+static const topo_modinfo_t Iob_info =
+	{ IOBOARD, FM_FMRI_SCHEME_HC, IOB_ENUMR_VERS, &Iob_ops };
 
-const topo_method_t Iob_methods[] = {
-	{ "iob_contains", "ioboard element contains other element",
-	    IOB_ENUMR_VERS, TOPO_STABILITY_INTERNAL, iob_contains },
-	{ "iob_present", "ioboard element currently present",
-	    IOB_ENUMR_VERS, TOPO_STABILITY_INTERNAL, iob_present },
+static const topo_method_t Iob_methods[] = {
 	{ TOPO_METH_LABEL, TOPO_METH_LABEL_DESC,
 	    TOPO_METH_LABEL_VERSION, TOPO_STABILITY_INTERNAL, iob_label },
 	{ NULL }
@@ -77,96 +77,50 @@
 	 * Turn on module debugging output
 	 */
 	if (getenv("TOPOIOBDBG") != NULL)
-		topo_mod_setdebug(modhdl, TOPO_DBG_ALL);
+		topo_mod_setdebug(modhdl);
 	topo_mod_dprintf(modhdl, "initializing ioboard enumerator\n");
 
-	topo_mod_register(modhdl, &Iob_info, NULL);
+	topo_mod_register(modhdl, &Iob_info, TOPO_VERSION);
+
+	did_hash_init(modhdl);
 	topo_mod_dprintf(modhdl, "Ioboard enumr initd\n");
 }
 
 void
 _topo_fini(topo_mod_t *modhdl)
 {
+	did_hash_fini(modhdl);
 	topo_mod_unregister(modhdl);
 }
 
-/*ARGSUSED*/
-static int
-iob_contains(topo_mod_t *mp, tnode_t *node, topo_version_t version,
-    nvlist_t *in, nvlist_t **out)
-{
-	return (0);
-}
-
-/*ARGSUSED*/
-static int
-iob_present(topo_mod_t *mp, tnode_t *node, topo_version_t version,
-    nvlist_t *in, nvlist_t **out)
-{
-	return (0);
-}
-
 static int
 iob_label(topo_mod_t *mp, tnode_t *node, topo_version_t version,
     nvlist_t *in, nvlist_t **out)
 {
 	if (version > TOPO_METH_LABEL_VERSION)
 		return (topo_mod_seterrno(mp, EMOD_VER_NEW));
-	return (platform_iob_label(node, in, out, mp));
+	return (platform_iob_label(mp, node, in, out));
 }
 
 static topo_mod_t *
-hb_enumr_load(topo_mod_t *mp, tnode_t *parent)
+hb_enumr_load(topo_mod_t *mp)
 {
 	topo_mod_t *rp = NULL;
-	char *plat, *mach;
-	char *hbpath;
-	char *rootdir;
-	int err;
 
-	plat = mach = NULL;
-
-	if (topo_prop_get_string(parent,
-	    TOPO_PGROUP_SYSTEM, TOPO_PROP_PLATFORM, &plat, &err) < 0) {
-		(void) topo_mod_seterrno(mp, err);
-		return (NULL);
-	}
-	if (topo_prop_get_string(parent,
-	    TOPO_PGROUP_SYSTEM, TOPO_PROP_MACHINE, &mach, &err) < 0) {
-		(void) topo_mod_seterrno(mp, err);
-		return (NULL);
+	if ((rp = topo_mod_load(mp, HOSTBRIDGE, HB_ENUMR_VERS)) == NULL) {
+		topo_mod_dprintf(mp,
+		    "%s enumerator could not load %s.\n", IOBOARD, HOSTBRIDGE);
 	}
-	hbpath = topo_mod_alloc(mp, PATH_MAX);
-	rootdir = topo_mod_rootdir(mp);
-	(void) snprintf(hbpath,
-	    PATH_MAX, PATH_TO_HB_ENUM, rootdir ? rootdir : "", plat);
-
-	if ((rp = topo_mod_load(mp, hbpath)) == NULL) {
-		topo_mod_dprintf(mp,
-		    "%s enumerator could not load %s.\n", IOBOARD, hbpath);
-		(void) snprintf(hbpath,
-		    PATH_MAX, PATH_TO_HB_ENUM, rootdir ? rootdir : "", mach);
-		if ((rp = topo_mod_load(mp, hbpath)) == NULL) {
-			topo_mod_dprintf(mp,
-			    "%s enumerator could not load %s.\n",
-			    IOBOARD, hbpath);
-		}
-	}
-	topo_mod_strfree(mp, plat);
-	topo_mod_strfree(mp, mach);
-	topo_mod_free(mp, hbpath, PATH_MAX);
 	return (rp);
 }
 
 /*ARGSUSED*/
 static int
 iob_enum(topo_mod_t *mp, tnode_t *pn, const char *name, topo_instance_t imin,
-    topo_instance_t imax, void *notused)
+    topo_instance_t imax, void *notused1, void *notused2)
 {
 	topo_mod_t *hbmod;
 	int rv;
-	did_hash_t *didhash;
-	di_prom_handle_t promtree;
 
 	if (strcmp(name, IOBOARD) != 0) {
 		topo_mod_dprintf(mp,
@@ -174,33 +128,18 @@
 		    IOBOARD);
 		return (0);
 	}
-
-	if ((promtree = di_prom_init()) == DI_PROM_HANDLE_NIL) {
-		topo_mod_dprintf(mp,
-		    "Ioboard enumerator: di_prom_handle_init failed.\n");
-		return (-1);
-	}
-
 	/*
 	 * Load the hostbridge enumerator, we'll soon need it!
 	 */
-	if ((hbmod = hb_enumr_load(mp, pn)) == NULL) {
-		di_prom_fini(promtree);
+	if ((hbmod = hb_enumr_load(mp)) == NULL) {
 		return (-1);
 	}
 
-	if ((didhash = did_hash_init(mp)) == NULL) {
-		topo_mod_dprintf(mp,
-		    "Hash initialization for ioboard enumerator failed.\n");
-		di_prom_fini(promtree);
-		topo_mod_unload(hbmod);
-		return (-1);
-	}
+	did_hash_init(mp);
 
-	rv = platform_iob_enum(pn, imin, imax, didhash, promtree, mp);
+	rv = platform_iob_enum(mp, pn, imin, imax);
 
-	did_hash_fini(didhash);
-	di_prom_fini(promtree);
+	did_hash_fini(mp);
 	topo_mod_unload(hbmod);
 
 	if (rv < 0)
@@ -223,41 +162,22 @@
 }
 
 static tnode_t *
-iob_tnode_create(tnode_t *parent,
-    const char *name, topo_instance_t i, void *priv, topo_mod_t *mod)
+iob_tnode_create(topo_mod_t *mod, tnode_t *parent,
+    const char *name, topo_instance_t i, void *priv)
 {
-	topo_hdl_t *thp;
-	nvlist_t *args, *fmri, *pfmri;
+	nvlist_t *fmri;
 	tnode_t *ntn;
-	int err;
-
-	thp = topo_mod_handle(mod);
+	nvlist_t *auth = topo_mod_auth(mod, parent);
 
-	if (topo_node_resource(parent, &pfmri, &err) < 0) {
-		topo_mod_seterrno(mod, err);
-		topo_mod_dprintf(mod,
-		    "Unable to retrieve parent resource.\n");
-		return (NULL);
-	}
-	if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0) {
-		(void) topo_mod_seterrno(mod, EMOD_FMRI_NVL);
-		nvlist_free(pfmri);
-		return (NULL);
-	}
-	err = nvlist_add_nvlist(args, TOPO_METH_FMRI_ARG_PARENT, pfmri);
-	if (err != 0) {
-		nvlist_free(pfmri);
-		nvlist_free(args);
-		(void) topo_mod_seterrno(mod, EMOD_FMRI_NVL);
-		return (NULL);
-	}
-	fmri = topo_fmri_create(thp, FM_FMRI_SCHEME_HC, name, i, args, &err);
+	fmri = topo_mod_hcfmri(mod, parent, FM_HC_SCHEME_VERSION, name, i,
+	    NULL, auth, NULL, NULL, NULL);
+	nvlist_free(auth);
 	if (fmri == NULL) {
 		topo_mod_dprintf(mod,
 		    "Unable to make nvlist for %s bind.\n", name);
 		return (NULL);
 	}
-	ntn = topo_node_bind(mod, parent, name, i, fmri, priv);
+	ntn = topo_node_bind(mod, parent, name, i, fmri);
 	if (ntn == NULL) {
 		topo_mod_dprintf(mod,
 		    "topo_node_bind (%s%d/%s%d) failed: %s\n",
@@ -268,6 +188,8 @@
 		return (NULL);
 	}
 	nvlist_free(fmri);
+	topo_node_setspecific(ntn, priv);
+
 	if (topo_method_register(mod, ntn, Iob_methods) < 0) {
 		topo_mod_dprintf(mod, "topo_method_register failed: %s\n",
 		    topo_strerror(topo_mod_errno(mod)));
@@ -278,15 +200,13 @@
 }
 
 tnode_t *
-ioboard_declare(tnode_t *parent, topo_instance_t i, void *priv,
-    di_prom_handle_t promtree, topo_mod_t *mod)
+ioboard_declare(topo_mod_t *mod, tnode_t *parent, topo_instance_t i, void *priv)
 {
 	tnode_t *ntn;
 
-	if ((ntn = iob_tnode_create(parent, IOBOARD, i, priv, mod)) == NULL)
+	if ((ntn = iob_tnode_create(mod, parent, IOBOARD, i, priv)) == NULL)
 		return (NULL);
-	if (did_props_set(ntn, priv, IOB_common_props, IOB_propcnt,
-	    promtree) < 0) {
+	if (did_props_set(ntn, priv, IOB_common_props, IOB_propcnt) < 0) {
 		topo_node_unbind(ntn);
 		return (NULL);
 	}
@@ -301,9 +221,8 @@
 }
 
 did_t *
-split_bus_address(did_hash_t *dhash, di_node_t dp, uint_t baseaddr,
-    uint_t bussep, int minbrd, int maxbrd, int *brd, int *br, int *bus,
-    di_prom_handle_t promtree, topo_mod_t *mod)
+split_bus_address(topo_mod_t *mod, di_node_t dp, uint_t baseaddr,
+    uint_t bussep, int minbrd, int maxbrd, int *brd, int *br, int *bus)
 {
 	uint_t bc, ac;
 	char *comma;
@@ -350,5 +269,5 @@
 		    *brd, *br, *bus, bc, ac);
 		return (NULL);
 	}
-	return (did_create(dhash, dp, *brd, *br, NO_RC, *bus, promtree));
+	return (did_create(mod, dp, *brd, *br, NO_RC, *bus));
 }
--- a/usr/src/lib/fm/topo/modules/sun4/ioboard/ioboard.h	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/sun4/ioboard/ioboard.h	Sat Nov 04 01:18:55 2006 -0800
@@ -38,8 +38,6 @@
 
 #define	IOB_ENUMR_VERS	1
 
-#define	IOBOARD	"ioboard"
-
 /*
  * For all machines that currently use this enumerator, buses have one
  * of the following addresses.
@@ -47,19 +45,19 @@
 #define	IOB_BUSADDR1	0x600000
 #define	IOB_BUSADDR2	0x700000
 
-extern tnode_t *ioboard_declare(tnode_t *, topo_instance_t, void *,
-    di_prom_handle_t, topo_mod_t *);
+extern tnode_t *ioboard_declare(topo_mod_t *, tnode_t *, topo_instance_t,
+    void *);
 
-extern int platform_iob_enum(tnode_t *, topo_instance_t, topo_instance_t,
-    did_hash_t *, di_prom_handle_t, topo_mod_t *);
-extern int platform_iob_label(tnode_t *, nvlist_t *, nvlist_t **, topo_mod_t *);
+extern int platform_iob_enum(topo_mod_t *, tnode_t *, topo_instance_t,
+    topo_instance_t);
+extern int platform_iob_label(topo_mod_t *, tnode_t *, nvlist_t *, nvlist_t **);
 
 /*
  * This routine works for splitting up the string we get from
  * di_bus_addr() for all machines that currently use this enumerator.
  */
-extern did_t *split_bus_address(did_hash_t *, di_node_t, uint_t, uint_t,
-    int, int, int *, int *, int *, di_prom_handle_t, topo_mod_t *);
+extern did_t *split_bus_address(topo_mod_t *, di_node_t, uint_t, uint_t,
+    int, int, int *, int *, int *);
 
 #ifdef __cplusplus
 }
--- a/usr/src/lib/fm/topo/modules/sun4u/hostbridge/hb_sun4u.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/sun4u/hostbridge/hb_sun4u.c	Sat Nov 04 01:18:55 2006 -0800
@@ -26,14 +26,15 @@
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
-#include "hb_sun4.h"
-#include "hostbridge.h"
-#include "pcibus.h"
-#include "util.h"
-#include "did.h"
+#include <fm/topo_hc.h>
+
+#include <hb_sun4.h>
+#include <hostbridge.h>
+#include <pcibus.h>
+#include <util.h>
 
 int
-count_busorrc(busorrc_t *list, int *hbc, int *bph, topo_mod_t *mod)
+count_busorrc(topo_mod_t *mod, busorrc_t *list, int *hbc, int *bph)
 {
 	ulong_t start;
 	busorrc_t *p;
@@ -68,8 +69,7 @@
 }
 
 static int
-busorrc_process(busorrc_t *list, int isrc, tnode_t *ptn,
-    did_hash_t *didhash, di_prom_handle_t promtree, topo_mod_t *mod)
+busorrc_process(topo_mod_t *mod, busorrc_t *list, int isrc, tnode_t *ptn)
 {
 	int hbc, busper;
 
@@ -104,18 +104,16 @@
 	 * values of X2 maintains the correct associations of
 	 * buses/root complexes and bridges.
 	 */
-	if (count_busorrc(list, &hbc, &busper, mod) < 0)
+	if (count_busorrc(mod, list, &hbc, &busper) < 0)
 		return (-1);
 	if (isrc == 1)
-		return (declare_exbuses(list, ptn, hbc, busper, didhash,
-		    promtree, mod));
+		return (declare_exbuses(mod, list, ptn, hbc, busper));
 	else
-		return (declare_buses(list, ptn, hbc, didhash, promtree, mod));
+		return (declare_buses(mod, list, ptn, hbc));
 }
 
 static int
-pci_hostbridges_find(tnode_t *ptn, did_hash_t *didhash,
-    di_prom_handle_t promtree, topo_mod_t *mod)
+pci_hostbridges_find(topo_mod_t *mod, tnode_t *ptn)
 {
 	busorrc_t *buses = NULL;
 	busorrc_t *rcs = NULL;
@@ -123,7 +121,7 @@
 	di_node_t pnode;
 
 	/* Scan for buses, top-level devinfo nodes with the right driver */
-	devtree = di_init("/", DINFOCPYALL);
+	devtree = topo_mod_devinfo(mod);
 	if (devtree == DI_NODE_NIL) {
 		topo_mod_dprintf(mod, "devinfo init failed.");
 		topo_node_range_destroy(ptn, HOSTBRIDGE);
@@ -132,60 +130,54 @@
 
 	pnode = di_drv_first_node(PCI, devtree);
 	while (pnode != DI_NODE_NIL) {
-		if (busorrc_add(&buses, pnode, mod) < 0) {
-			di_fini(devtree);
+		if (busorrc_add(mod, &buses, pnode) < 0) {
 			return (topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM));
 		}
 		pnode = di_drv_next_node(pnode);
 	}
 	pnode = di_drv_first_node(PSYCHO, devtree);
 	while (pnode != DI_NODE_NIL) {
-		if (busorrc_add(&buses, pnode, mod) < 0) {
-			di_fini(devtree);
+		if (busorrc_add(mod, &buses, pnode) < 0) {
 			return (topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM));
 		}
 		pnode = di_drv_next_node(pnode);
 	}
 	pnode = di_drv_first_node(SCHIZO, devtree);
 	while (pnode != DI_NODE_NIL) {
-		if (busorrc_add(&buses, pnode, mod) < 0) {
-			di_fini(devtree);
+		if (busorrc_add(mod, &buses, pnode) < 0) {
 			return (topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM));
 		}
 		pnode = di_drv_next_node(pnode);
 	}
 	pnode = di_drv_first_node(PX, devtree);
 	while (pnode != DI_NODE_NIL) {
-		if (busorrc_add(&rcs, pnode, mod) < 0) {
-			di_fini(devtree);
+		if (busorrc_add(mod, &rcs, pnode) < 0) {
 			return (topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM));
 		}
 		pnode = di_drv_next_node(pnode);
 	}
-	if (busorrc_process(buses, 0, ptn, didhash, promtree, mod) < 0)
+	if (busorrc_process(mod, buses, 0, ptn) < 0)
 		return (topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM));
 
-	if (busorrc_process(rcs, 1, ptn, didhash, promtree, mod) < 0)
+	if (busorrc_process(mod, rcs, 1, ptn) < 0)
 		return (topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM));
 
-	busorrc_free(buses, mod);
-	busorrc_free(rcs, mod);
-	di_fini(devtree);
+	busorrc_free(mod, buses);
+	busorrc_free(mod, rcs);
 	return (0);
 }
 
 /*ARGSUSED*/
 int
-platform_hb_enum(tnode_t *parent, const char *name,
-    topo_instance_t imin, topo_instance_t imax, did_hash_t *didhash,
-    di_prom_handle_t promtree, topo_mod_t *mod)
+platform_hb_enum(topo_mod_t *mod, tnode_t *parent, const char *name,
+    topo_instance_t imin, topo_instance_t imax)
 {
-	return (pci_hostbridges_find(parent, didhash, promtree, mod));
+	return (pci_hostbridges_find(mod, parent));
 }
 
 /*ARGSUSED*/
 int
-platform_hb_label(tnode_t *node, nvlist_t *in, nvlist_t **out, topo_mod_t *mod)
+platform_hb_label(topo_mod_t *mod, tnode_t *node, nvlist_t *in, nvlist_t **out)
 {
 	return (labelmethod_inherit(mod, node, in, out));
 }
--- a/usr/src/lib/fm/topo/modules/sun4u/pcibus/Makefile	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/sun4u/pcibus/Makefile	Sat Nov 04 01:18:55 2006 -0800
@@ -29,16 +29,15 @@
 MODULE = pcibus
 ARCH = sun4u
 CLASS = arch
-PCISRCS = did.c			\
-	  did_hash.c		\
-	  did_props.c		\
-	  pcibus.c		\
-	  pcibus_labels.c	\
-	  pcifn_enum.c		\
-	  util.c
+UTILDIR = ../../common/pcibus
+HBDIR = ../../common/hostbridge
+UTILSRCS = did.c did_hash.c did_props.c util.c
+PCISRCS = pcibus.c pcibus_labels.c
 
-MODULESRCS = $(PCISRCS) pci_sun4u.c
+MODULESRCS = $(UTILSRCS) $(PCISRCS) pci_sun4u.c
 
 include ../../Makefile.plugin
 
 LDLIBS += -ldevinfo
+
+CPPFLAGS += -I$(UTILDIR) -I$(HBDIR)
--- a/usr/src/lib/fm/topo/modules/sun4u/pcibus/pci_sun4u.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/sun4u/pcibus/pci_sun4u.c	Sat Nov 04 01:18:55 2006 -0800
@@ -37,7 +37,8 @@
 #include "pci_sun4u.h"
 
 int
-platform_pci_label(tnode_t *node, nvlist_t *in, nvlist_t **out, topo_mod_t *mod)
+platform_pci_label(topo_mod_t *mod, tnode_t *node, nvlist_t *in,
+    nvlist_t **out)
 {
-	return (pci_label_cmn(node, in, out, mod));
+	return (pci_label_cmn(mod, node, in, out));
 }
--- a/usr/src/lib/fm/topo/modules/sun4v/Makefile	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/sun4v/Makefile	Sat Nov 04 01:18:55 2006 -0800
@@ -25,6 +25,6 @@
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
 
-SUBDIRS = chip hostbridge ioboard pcibus
+SUBDIRS = chip hostbridge pcibus
 
 include ../../../Makefile.subdirs
--- a/usr/src/lib/fm/topo/modules/sun4v/hostbridge/hb_sun4v.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/sun4v/hostbridge/hb_sun4v.c	Sat Nov 04 01:18:55 2006 -0800
@@ -26,15 +26,15 @@
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
-#include "hb_sun4.h"
-#include "hostbridge.h"
-#include "pcibus.h"
-#include "util.h"
-#include "did.h"
+#include <fm/topo_hc.h>
+
+#include <hb_sun4.h>
+#include <hostbridge.h>
+#include <pcibus.h>
+#include <util.h>
 
 static int
-rcs_process(busorrc_t *list, tnode_t *ptn, did_hash_t *didhash,
-    di_prom_handle_t promtree, topo_mod_t *mod)
+rcs_process(topo_mod_t *mod, busorrc_t *list, tnode_t *ptn)
 {
 	busorrc_t *p;
 	int nrc = 0;
@@ -53,19 +53,18 @@
 		nrc++;
 
 	topo_mod_dprintf(mod, "root complex count: %d\n", nrc);
-	return (declare_exbuses(list, ptn, 1, nrc, didhash, promtree, mod));
+	return (declare_exbuses(mod, list, ptn, 1, nrc));
 }
 
 static int
-pci_hostbridges_find(tnode_t *ptn, did_hash_t *didhash,
-    di_prom_handle_t promtree, topo_mod_t *mod)
+pci_hostbridges_find(topo_mod_t *mod, tnode_t *ptn)
 {
 	busorrc_t *rcs = NULL;
 	di_node_t devtree;
 	di_node_t pnode;
 
 	/* Scan for buses, top-level devinfo nodes with the right driver */
-	devtree = di_init("/", DINFOCPYALL);
+	devtree = topo_mod_devinfo(mod);
 	if (devtree == DI_NODE_NIL) {
 		topo_mod_dprintf(mod, "devinfo init failed.");
 		topo_node_range_destroy(ptn, HOSTBRIDGE);
@@ -73,30 +72,27 @@
 	}
 	pnode = di_drv_first_node(PX, devtree);
 	while (pnode != DI_NODE_NIL) {
-		if (busorrc_add(&rcs, pnode, mod) < 0) {
-			di_fini(devtree);
+		if (busorrc_add(mod, &rcs, pnode) < 0) {
 			return (-1);
 		}
 		pnode = di_drv_next_node(pnode);
 	}
-	rcs_process(rcs, ptn, didhash, promtree, mod);
-	busorrc_free(rcs, mod);
-	di_fini(devtree);
+	rcs_process(mod, rcs, ptn);
+	busorrc_free(mod, rcs);
 	return (0);
 }
 
 /*ARGSUSED*/
 int
-platform_hb_enum(tnode_t *parent, const char *name,
-    topo_instance_t imin, topo_instance_t imax, did_hash_t *didhash,
-    di_prom_handle_t promtree, topo_mod_t *mod)
+platform_hb_enum(topo_mod_t *mod, tnode_t *parent, const char *name,
+    topo_instance_t imin, topo_instance_t imax)
 {
-	return (pci_hostbridges_find(parent, didhash, promtree, mod));
+	return (pci_hostbridges_find(mod, parent));
 }
 
 /*ARGSUSED*/
 int
-platform_hb_label(tnode_t *node, nvlist_t *in, nvlist_t **out, topo_mod_t *mod)
+platform_hb_label(topo_mod_t *mod, tnode_t *node, nvlist_t *in, nvlist_t **out)
 {
 	return (labelmethod_inherit(mod, node, in, out));
 }
--- a/usr/src/lib/fm/topo/modules/sun4v/ioboard/Makefile	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
-
-CLASS = arch
-ARCH = sun4v
-
-include ../../sun4/ioboard/Makefile.iob
--- a/usr/src/lib/fm/topo/modules/sun4v/ioboard/iob_platform.c	Fri Nov 03 20:28:35 2006 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,169 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-/*
- * SUNW,Sun-Fire platform ioboard topology enumerator
- */
-
-#include <string.h>
-#include <libdevinfo.h>
-#include <fm/topo_mod.h>
-#include <sys/fm/protocol.h>
-
-#include <ioboard.h>
-#include <hostbridge.h>
-#include <util.h>
-
-#define	IOBOARD	"ioboard"
-#define	LABEL	"IOBD"
-#define	IOBDFRU	"hc:///component="LABEL
-#define	ERIE	"SUNW,Sun-Fire-T1000"
-#define	ERIE2	"SUNW,SPARC-Enterprise-T1000"
-#define	HB_MAX	1
-
-/*ARGSUSED*/
-int
-platform_iob_label(tnode_t *node, nvlist_t *ignored, nvlist_t **out,
-    topo_mod_t *mod)
-{
-	return (0);
-}
-
-static tnode_t *
-iob_node_create(tnode_t *parent, topo_mod_t *mod)
-{
-	int err;
-	tnode_t *ion;
-	nvlist_t *fmri, *args = NULL, *pfmri = NULL;
-	topo_hdl_t *thp = topo_mod_handle(mod);
-
-	(void) topo_node_resource(parent, &pfmri, &err);
-	if (pfmri != NULL) {
-		if (topo_mod_nvalloc(mod, &args, NV_UNIQUE_NAME) != 0 ||
-		    nvlist_add_nvlist(args, TOPO_METH_FMRI_ARG_PARENT, pfmri)
-		    != 0) {
-			nvlist_free(pfmri);
-			nvlist_free(args);
-			(void) topo_mod_seterrno(mod, EMOD_FMRI_NVL);
-			return (NULL);
-		}
-		nvlist_free(pfmri);
-	}
-
-	if ((fmri = topo_fmri_create(thp, FM_FMRI_SCHEME_HC, IOBOARD, 0, args,
-		&err)) == NULL) {
-		topo_mod_dprintf(mod, "creation of tnode for ioboard=0 "
-		    "failed: %s\n", topo_strerror(err));
-		(void) topo_mod_seterrno(mod, err);
-		nvlist_free(args);
-		return (NULL);
-	}
-	nvlist_free(args);
-	ion = topo_node_bind(mod, parent, IOBOARD, 0, fmri, NULL);
-	if (ion == NULL) {
-		nvlist_free(fmri);
-		topo_mod_dprintf(mod, "unable to bind ioboard=0: %s",
-		    topo_strerror(topo_mod_errno(mod)));
-		return (NULL); /* mod_errno already set */
-	}
-	nvlist_free(fmri);
-
-	if (topo_fmri_str2nvl(thp, IOBDFRU, &fmri, &err) == 0) {
-		(void) topo_node_fru_set(ion, fmri, 0, &err);
-		nvlist_free(fmri);
-	}
-	(void) topo_node_label_set(ion, "IOBD", &err);
-
-	return (ion);
-}
-
-/*ARGSUSED*/
-int
-platform_iob_enum(tnode_t *parent, topo_instance_t imin, topo_instance_t imax,
-    did_hash_t *didhash, di_prom_handle_t promtree, topo_mod_t *mod)
-{
-	int err;
-	tnode_t *ion;
-	char *plat;
-
-	if (topo_prop_get_string(parent,
-	    TOPO_PGROUP_SYSTEM, TOPO_PROP_PLATFORM, &plat, &err) < 0) {
-		return (topo_mod_seterrno(mod, err));
-	}
-
-	/*
-	 * The SUNW,SunFireT1000 (Erie) platform links in the SUNW,SunFireT200
-	 * (Ontario) top-level /usr/platform/SUNW,SunFireT200 and its
-	 * hc-topology. Unfortunately, the SUNW,SunFireT1000 does not contain an
-	 * ioboard.  For SUNW,SunFireT1000 systems, we must begin the I/O
-	 * topology directly below the motherboard.
-	 *
-	 * To further the mess, on the SUNW,SunFireT200 (Ontario) platform, a
-	 * mistake was made with the topology defintion.  The ioboard was made
-	 * a peer to the motherboard.  This is incorrect in terms of
-	 * what we allow for an hc topology according the Fault
-	 * Managed Resources specification and what is physically
-	 * possible in the system.  Nevertheless, a change to
-	 * the topology will result in mis-diagnoses for systems
-	 * that have already shipped. In the interest of backward
-	 * compatibility, we continue to allow the
-	 * ioboard to be a peer to the motherboard SUNW,SunFireT200 systems.
-	 */
-	if ((strcmp(plat, ERIE) == 0) ||
-	    (strcmp(plat, ERIE2) == 0)) {
-		if (strcmp(topo_node_name(parent), "motherboard") != 0) {
-			topo_mod_strfree(mod, plat);
-			return (0);
-		}
-		ion = parent;
-	} else if (strcmp(topo_node_name(parent), "motherboard") == 0) {
-		topo_mod_strfree(mod, plat);
-		return (0);
-	} else {
-		ion = iob_node_create(parent, mod);
-	}
-
-	topo_mod_strfree(mod, plat);
-
-	if (ion == NULL) {
-		topo_mod_dprintf(mod, "Enumeration of ioboard failed: %s\n",
-		    topo_strerror(topo_mod_errno(mod)));
-		return (-1); /* mod_errno already set */
-	}
-
-	if (child_range_add(mod, ion, HOSTBRIDGE, 0, HB_MAX) < 0 ||
-	    topo_mod_enumerate(mod, ion, HOSTBRIDGE, HOSTBRIDGE, 0, HB_MAX)
-	    < 0) {
-		topo_mod_dprintf(mod, "Enumeration of %s=%d "
-		    "failed: %s\n", HOSTBRIDGE, 0,
-		    topo_strerror(topo_mod_errno(mod)));
-		return (-1); /* mod_errno already set */
-	}
-
-	return (0);
-}
--- a/usr/src/lib/fm/topo/modules/sun4v/pcibus/Makefile	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/sun4v/pcibus/Makefile	Sat Nov 04 01:18:55 2006 -0800
@@ -29,16 +29,15 @@
 MODULE = pcibus
 ARCH = sun4v
 CLASS = arch
-PCISRCS = did.c			\
-	  did_hash.c		\
-	  did_props.c		\
-	  pcibus.c		\
-	  pcibus_labels.c	\
-	  pcifn_enum.c		\
-	  util.c
+UTILDIR = ../../common/pcibus
+HBDIR = ../../common/hostbridge
+UTILSRCS = did.c did_hash.c did_props.c util.c
+PCISRCS = pcibus.c pcibus_labels.c
 
-MODULESRCS = $(PCISRCS) pci_sun4v.c
+MODULESRCS = $(UTILSRCS) $(PCISRCS) pci_sun4v.c
 
 include ../../Makefile.plugin
 
 LDLIBS += -ldevinfo
+
+CPPFLAGS += -I$(UTILDIR) -I$(HBDIR)
--- a/usr/src/lib/fm/topo/modules/sun4v/pcibus/pci_sun4v.c	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/sun4v/pcibus/pci_sun4v.c	Sat Nov 04 01:18:55 2006 -0800
@@ -37,7 +37,8 @@
 #include "pci_sun4v.h"
 
 int
-platform_pci_label(tnode_t *node, nvlist_t *in, nvlist_t **out, topo_mod_t *mod)
+platform_pci_label(topo_mod_t *mod, tnode_t *node, nvlist_t *in,
+    nvlist_t **out)
 {
-	return (pci_label_cmn(node, in, out, mod));
+	return (pci_label_cmn(mod, node, in, out));
 }
--- a/usr/src/lib/fm/topo/modules/sun4v/pcibus/pci_sun4v.h	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/lib/fm/topo/modules/sun4v/pcibus/pci_sun4v.h	Sat Nov 04 01:18:55 2006 -0800
@@ -43,7 +43,7 @@
 };
 
 pphysnm_t plat_pnames[] = {
-	{ "SUNW,Sun-Fire-T200",
+	{ "Sun-Fire-T200",
 	    sizeof (t200_pnms) / sizeof (physnm_t),
 	    t200_pnms }
 };
@@ -60,7 +60,7 @@
 };
 
 pdevlabs_t plats_missing[] = {
-	{ "SUNW,Sun-Fire-T200",
+	{ "Sun-Fire-T200",
 	    sizeof (t200_missing) / sizeof (devlab_t),
 	    t200_missing }
 };
--- a/usr/src/pkgdefs/SUNWfmd/prototype_com	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/pkgdefs/SUNWfmd/prototype_com	Sat Nov 04 01:18:55 2006 -0800
@@ -41,6 +41,7 @@
 f none usr/include/fm/fmd_snmp.h 644 root bin
 f none usr/include/fm/libtopo.h 644 root bin
 f none usr/include/fm/topo_mod.h 644 root bin
+f none usr/include/fm/topo_hc.h 644 root bin
 d none usr/lib 755 root bin
 d none usr/lib/fm 755 root bin
 d none usr/lib/fm/dict 755 root bin
--- a/usr/src/pkgdefs/SUNWfmd/prototype_i386	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/pkgdefs/SUNWfmd/prototype_i386	Sat Nov 04 01:18:55 2006 -0800
@@ -68,7 +68,9 @@
 f none usr/platform/i86pc/lib/fm/topo/plugins/hostbridge.so 555 root bin
 f none usr/platform/i86pc/lib/fm/topo/plugins/pcibus.so 555 root bin
 f none usr/platform/i86pc/lib/fm/topo/plugins/sata.so 555 root bin
-f none usr/platform/i86pc/lib/fm/topo/hc-topology.xml 444 root bin
+d none usr/platform/i86pc/lib/fm/topo/maps 755 root bin
+f none usr/platform/i86pc/lib/fm/topo/maps/i86pc-hc-topology.xml 444 root bin
+f none usr/platform/i86pc/lib/fm/topo/maps/storage-hc-topology.xml 444 root bin
 d none usr/platform/i86pc/lib/fm/fmd 755 root bin
 d none usr/platform/i86pc/lib/fm/fmd/plugins 755 root bin
 f none usr/platform/i86pc/lib/fm/fmd/plugins/sfx4500-disk.so 555 root bin
--- a/usr/src/pkgdefs/SUNWfmd/prototype_sparc	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/pkgdefs/SUNWfmd/prototype_sparc	Sat Nov 04 01:18:55 2006 -0800
@@ -94,7 +94,8 @@
 f none usr/platform/sun4u/lib/fm/fmd/plugins/USII-io-diagnosis.so 555 root bin
 f none usr/platform/sun4u/lib/fm/fmd/plugins/USII-io-diagnosis.conf 644 root bin
 d none usr/platform/sun4u/lib/fm/topo 755 root bin
-f none usr/platform/sun4u/lib/fm/topo/hc-topology.xml 444 root bin
+d none usr/platform/sun4u/lib/fm/topo/maps 755 root bin
+f none usr/platform/sun4u/lib/fm/topo/maps/sun4u-hc-topology.xml 444 root bin
 d none usr/platform/sun4u/lib/fm/topo/plugins 755 root bin
 f none usr/platform/sun4u/lib/fm/topo/plugins/chip.so 555 root bin
 f none usr/platform/sun4u/lib/fm/topo/plugins/hostbridge.so 555 root bin
@@ -117,12 +118,12 @@
 f none usr/platform/sun4v/lib/fm/fmd/plugins/etm.so 555 root bin
 f none usr/platform/sun4v/lib/fm/fmd/plugins/etm.conf 644 root bin
 d none usr/platform/sun4v/lib/fm/topo 755 root bin
-f none usr/platform/sun4v/lib/fm/topo/hc-topology.xml 444 root bin
+d none usr/platform/sun4v/lib/fm/topo/maps 755 root bin
+f none usr/platform/sun4v/lib/fm/topo/maps/sun4v-hc-topology.xml 444 root bin
 d none usr/platform/sun4v/lib/fm/topo/plugins 755 root bin
 f none usr/platform/sun4v/lib/fm/topo/plugins/chip.so 555 root bin
 f none usr/platform/sun4v/lib/fm/topo/plugins/hostbridge.so 555 root bin
 f none usr/platform/sun4v/lib/fm/topo/plugins/pcibus.so 555 root bin
-f none usr/platform/sun4v/lib/fm/topo/plugins/ioboard.so 555 root bin
 d none usr/platform/SUNW,SPARC-Enterprise 755 root sys
 d none usr/platform/SUNW,SPARC-Enterprise/lib 755 root bin
 d none usr/platform/SUNW,SPARC-Enterprise/lib/fm 755 root bin
@@ -133,14 +134,16 @@
 f none usr/platform/SUNW,SPARC-Enterprise/lib/fm/fmd/plugins/event-transport.so 555 root bin
 f none usr/platform/SUNW,SPARC-Enterprise/lib/fm/fmd/plugins/event-transport.conf 644 root bin
 d none usr/platform/SUNW,SPARC-Enterprise/lib/fm/topo 755 root bin
-f none usr/platform/SUNW,SPARC-Enterprise/lib/fm/topo/hc-topology.xml 444 root bin
+d none usr/platform/SUNW,SPARC-Enterprise/lib/fm/topo/maps 755 root bin
+f none usr/platform/SUNW,SPARC-Enterprise/lib/fm/topo/maps/SPARC-Enterprise-hc-topology.xml 444 root bin
 d none usr/platform/SUNW,SPARC-Enterprise/lib/fm/topo/plugins 755 root bin
 f none usr/platform/SUNW,SPARC-Enterprise/lib/fm/topo/plugins/ioboard.so 555 root bin
 d none usr/platform/SUNW,Sun-Fire 755 root sys
 d none usr/platform/SUNW,Sun-Fire/lib 755 root bin
 d none usr/platform/SUNW,Sun-Fire/lib/fm 755 root bin
 d none usr/platform/SUNW,Sun-Fire/lib/fm/topo 755 root bin
-f none usr/platform/SUNW,Sun-Fire/lib/fm/topo/hc-topology.xml 444 root bin
+d none usr/platform/SUNW,Sun-Fire/lib/fm/topo/maps 755 root bin
+f none usr/platform/SUNW,Sun-Fire/lib/fm/topo/maps/Sun-Fire-hc-topology.xml 444 root bin
 d none usr/platform/SUNW,Sun-Fire/lib/fm/topo/plugins 755 root bin
 f none usr/platform/SUNW,Sun-Fire/lib/fm/topo/plugins/ioboard.so 555 root bin
 d none usr/platform/SUNW,Sun-Fire-15000 755 root sys
@@ -149,16 +152,16 @@
 d none usr/platform/SUNW,Sun-Fire-15000/lib/fm/eft 755 root bin
 f none usr/platform/SUNW,Sun-Fire-15000/lib/fm/eft/SUNW,Sun-Fire-15000.eft 444 root bin
 d none usr/platform/SUNW,Sun-Fire-15000/lib/fm/topo 755 root bin
-f none usr/platform/SUNW,Sun-Fire-15000/lib/fm/topo/hc-topology.xml 444 root bin
+d none usr/platform/SUNW,Sun-Fire-15000/lib/fm/topo/maps 755 root bin
+f none usr/platform/SUNW,Sun-Fire-15000/lib/fm/topo/maps/Sun-Fire-15000-hc-topology.xml 444 root bin
 d none usr/platform/SUNW,Sun-Fire-15000/lib/fm/topo/plugins 755 root bin
 f none usr/platform/SUNW,Sun-Fire-15000/lib/fm/topo/plugins/ioboard.so 555 root bin
 d none usr/platform/SUNW,Sun-Fire-T200 755 root sys
 d none usr/platform/SUNW,Sun-Fire-T200/lib 755 root bin
 d none usr/platform/SUNW,Sun-Fire-T200/lib/fm 755 root bin
 d none usr/platform/SUNW,Sun-Fire-T200/lib/fm/topo 755 root bin
-f none usr/platform/SUNW,Sun-Fire-T200/lib/fm/topo/hc-topology.xml 444 root bin
-d none usr/platform/SUNW,Sun-Blade-T6300 755 root sys
-d none usr/platform/SUNW,Sun-Blade-T6300/lib 755 root bin
-d none usr/platform/SUNW,Sun-Blade-T6300/lib/fm 755 root bin
-d none usr/platform/SUNW,Sun-Blade-T6300/lib/fm/topo 755 root bin
-f none usr/platform/SUNW,Sun-Blade-T6300/lib/fm/topo/hc-topology.xml 444 root bin
+d none usr/platform/SUNW,Sun-Fire-T200/lib/fm/topo/maps 755 root bin
+f none usr/platform/SUNW,Sun-Fire-T200/lib/fm/topo/maps/Sun-Fire-T200-hc-topology.xml 444 root bin
+f none usr/platform/SUNW,Sun-Fire-T200/lib/fm/topo/maps/Sun-Fire-T1000-hc-topology.xml 444 root bin
+f none usr/platform/SUNW,Sun-Fire-T200/lib/fm/topo/maps/SPARC-Enterprise-T1000-hc-topology.xml 444 root bin
+f none usr/platform/SUNW,Sun-Fire-T200/lib/fm/topo/maps/Sun-Blade-T6300-hc-topology.xml 444 root bin
--- a/usr/src/tools/scripts/bfu.sh	Fri Nov 03 20:28:35 2006 -0800
+++ b/usr/src/tools/scripts/bfu.sh	Sat Nov 04 01:18:55 2006 -0800
@@ -4616,6 +4616,7 @@
 	# Remove old topology data
 	#
 	rm -rf $usr/lib/fm/topo
+	rm -f $usr/platform/*/lib/fm/topo/hc-topology.xml
 
 	#
 	# Remove old prtopo and obsoleted include file.