summaryrefslogtreecommitdiff
path: root/usr/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib')
-rw-r--r--usr/src/lib/fm/libfmd_log/common/fmd_filter.c33
-rw-r--r--usr/src/lib/fm/libfmd_log/common/fmd_log.h15
-rw-r--r--usr/src/lib/fm/libfmd_log/common/mapfile-vers3
-rw-r--r--usr/src/lib/fm/topo/libtopo/common/topo_hc.h2
-rw-r--r--usr/src/lib/fm/topo/maps/Makefile2
-rw-r--r--usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4200-M2/Makefile41
-rw-r--r--usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4200-M2/Sun-Fire-X4200-M2-hc-topology.xmlgen150
-rw-r--r--usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4200-Server/Makefile41
-rw-r--r--usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4200-Server/Sun-Fire-X4200-Server-hc-topology.xmlgen150
-rw-r--r--usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4500/Sun-Fire-X4500-hc-topology.xmlgen257
-rw-r--r--usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4540/Sun-Fire-X4540-hc-topology.xmlgen258
-rw-r--r--usr/src/lib/fm/topo/modules/Makefile.plugin12
-rw-r--r--usr/src/lib/fm/topo/modules/common/disk/Makefile4
-rw-r--r--usr/src/lib/fm/topo/modules/common/disk/disk.c678
-rw-r--r--usr/src/lib/fm/topo/modules/common/disk/disk.h28
-rw-r--r--usr/src/lib/fm/topo/modules/common/disk/disk_common.c868
-rw-r--r--usr/src/lib/libdevinfo/devinfo.c387
-rw-r--r--usr/src/lib/libdevinfo/libdevinfo.h317
-rw-r--r--usr/src/lib/libdevinfo/mapfile-vers96
-rw-r--r--usr/src/lib/libdiskmgt/common/findevs.c8
-rw-r--r--usr/src/lib/libnvpair/Makefile.com6
-rw-r--r--usr/src/lib/libnvpair/libnvpair.c353
-rw-r--r--usr/src/lib/libnvpair/libnvpair.h10
-rw-r--r--usr/src/lib/libnvpair/mapfile-vers6
24 files changed, 2574 insertions, 1151 deletions
diff --git a/usr/src/lib/fm/libfmd_log/common/fmd_filter.c b/usr/src/lib/fm/libfmd_log/common/fmd_filter.c
index dfc85c9758..b260816275 100644
--- a/usr/src/lib/fm/libfmd_log/common/fmd_filter.c
+++ b/usr/src/lib/fm/libfmd_log/common/fmd_filter.c
@@ -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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -30,6 +29,8 @@
#include <strings.h>
#include <libgen.h>
+#include <regex.h>
+#include <libnvpair.h>
#include <fmd_log_impl.h>
#include <fmd_log.h>
@@ -73,3 +74,27 @@ fmd_log_filter_after(fmd_log_t *lp, const fmd_log_record_t *rp, void *arg)
uint64_t nsec = ((struct timeval *)arg)->tv_usec * (NANOSEC / MICROSEC);
return (rp->rec_sec == sec ? rp->rec_nsec >= nsec : rp->rec_sec >= sec);
}
+
+/*ARGSUSED*/
+int
+fmd_log_filter_nv(fmd_log_t *lp, const fmd_log_record_t *rp, void *arg)
+{
+ fmd_log_filter_nvarg_t *argt = (fmd_log_filter_nvarg_t *)arg;
+ char *name = argt->nvarg_name;
+ char *value = argt->nvarg_value;
+ regex_t *value_regex = argt->nvarg_value_regex;
+ nvpair_t *nvp;
+ int ai;
+
+ /* see if nvlist has named member */
+ if (nvlist_lookup_nvpair_embedded_index(rp->rec_nvl, name,
+ &nvp, &ai, NULL) != 0)
+ return (0); /* name filter failure */
+
+ /* check value match for matching nvpair */
+ if ((value == NULL) ||
+ (nvpair_value_match_regex(nvp, ai, value, value_regex, NULL) == 1))
+ return (1); /* name/value filter pass */
+
+ return (0); /* value filter failure */
+}
diff --git a/usr/src/lib/fm/libfmd_log/common/fmd_log.h b/usr/src/lib/fm/libfmd_log/common/fmd_log.h
index 9c98d8236a..be705571b9 100644
--- a/usr/src/lib/fm/libfmd_log/common/fmd_log.h
+++ b/usr/src/lib/fm/libfmd_log/common/fmd_log.h
@@ -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 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -31,6 +30,7 @@
#include <libnvpair.h>
#include <exacct.h>
+#include <regex.h>
#ifdef __cplusplus
extern "C" {
@@ -101,10 +101,17 @@ extern fmd_log_rec_f fmd_log_filter_class; /* char *name of event class */
extern fmd_log_rec_f fmd_log_filter_uuid; /* char *uuid of list.suspect */
extern fmd_log_rec_f fmd_log_filter_before; /* struct timeval * latest */
extern fmd_log_rec_f fmd_log_filter_after; /* struct timeval * earliest */
+extern fmd_log_rec_f fmd_log_filter_nv; /* char *namevalue in event */
extern int fmd_log_filter(fmd_log_t *,
uint_t, fmd_log_filter_t *, const fmd_log_record_t *);
+typedef struct fmd_log_filter_nvarg {
+ char *nvarg_name;
+ char *nvarg_value;
+ regex_t *nvarg_value_regex;
+} fmd_log_filter_nvarg_t;
+
/*
* fmd_log_xiter() can be used to perform sophisticated iteration over an fmd
* log file such as that required by fmdump(1M). The arguments are as follows:
diff --git a/usr/src/lib/fm/libfmd_log/common/mapfile-vers b/usr/src/lib/fm/libfmd_log/common/mapfile-vers
index d7ba3e2c45..cecb3d2840 100644
--- a/usr/src/lib/fm/libfmd_log/common/mapfile-vers
+++ b/usr/src/lib/fm/libfmd_log/common/mapfile-vers
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -34,6 +34,7 @@ SUNWprivate {
fmd_log_filter_after;
fmd_log_filter_before;
fmd_log_filter_class;
+ fmd_log_filter_nv;
fmd_log_filter_uuid;
fmd_log_header;
fmd_log_iter;
diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_hc.h b/usr/src/lib/fm/topo/libtopo/common/topo_hc.h
index ba49a8bbb0..11d1090748 100644
--- a/usr/src/lib/fm/topo/libtopo/common/topo_hc.h
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_hc.h
@@ -82,8 +82,10 @@ extern "C" {
#define TOPO_IO_DRIVER "driver"
#define TOPO_IO_MODULE "module"
#define TOPO_IO_DEV "dev"
+#define TOPO_IO_DEVID "devid"
#define TOPO_IO_DEV_PATH "devfs-path"
#define TOPO_IO_AP_PATH "ap-path"
+#define TOPO_IO_PHYS_PATH "phys-path"
#define TOPO_PGROUP_PCI "pci"
#define TOPO_PCI_VENDID "vendor-id"
diff --git a/usr/src/lib/fm/topo/maps/Makefile b/usr/src/lib/fm/topo/maps/Makefile
index 1984b1bbf5..5af237b7b8 100644
--- a/usr/src/lib/fm/topo/maps/Makefile
+++ b/usr/src/lib/fm/topo/maps/Makefile
@@ -45,6 +45,8 @@ sparc_SUBDIRS = sun4u \
i386_SUBDIRS = i86pc \
i386 \
+ SUNW,Sun-Fire-X4200-Server \
+ SUNW,Sun-Fire-X4200-M2 \
SUNW,Sun-Fire-X4500 \
SUNW,Sun-Fire-X4540
diff --git a/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4200-M2/Makefile b/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4200-M2/Makefile
new file mode 100644
index 0000000000..fa4d771486
--- /dev/null
+++ b/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4200-M2/Makefile
@@ -0,0 +1,41 @@
+#
+# 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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# NOTE: The name of the xml file we are building is 'platform'
+# specific, but its build is structured as 'arch' specific since
+# 'uname -i' on all x86 platforms returns i86pc.
+
+ARCH = i86pc
+CLASS = arch
+DTDFILE =
+TOPOFILE = Sun-Fire-X4200-M2-hc-topology.xml
+SRCDIR = ../SUNW,Sun-Fire-X4200-M2
+
+PLATFORM = Sun-Fire-X4200-M2
+TOPOBASE = ../i86pc/i86pc-hc-topology.xml
+
+include ../Makefile.map
diff --git a/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4200-M2/Sun-Fire-X4200-M2-hc-topology.xmlgen b/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4200-M2/Sun-Fire-X4200-M2-hc-topology.xmlgen
new file mode 100644
index 0000000000..e8f94d0f65
--- /dev/null
+++ b/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4200-M2/Sun-Fire-X4200-M2-hc-topology.xmlgen
@@ -0,0 +1,150 @@
+#!/usr/local/bin/perl
+#
+# 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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+use Getopt::Std;
+
+# X4200-M2: platform specific begin
+my $sys_supported = { "name" => "Sun-Fire-X4200-M2",
+ "num_bays" => "4",
+ "bay_label" => "HD"};
+# X4200-M2: platform specific end
+
+$IFILE = "filehandle";
+$OFILE = "filehandle";
+
+sub Usage()
+{
+ print STDERR "Usage: xml-gen -p <platform> " .
+ "-i <input_xml_file> -o <output_xml_file>\n";
+}
+
+sub calc_nodes
+{
+# X4200-M2: platform specific begin
+ $controller = 0;
+# X4200-M2: platform specific end
+
+ for ($bay = 0; $bay < $sys_supported->{"num_bays"}; $bay++) {
+
+# X4200-M2: platform specific begin
+ $target = $bay;
+
+ # set hba path, target path, bay path, and attachment point
+ $hpath = "/pci\@7b,0/pci1022,7458\@11/pci1000,3060\@2";
+ $tpath = sprintf("/sd\@%x,0", $target);
+ $apoint = sprintf(":scsi::dsk/c%dt%dd0",
+ $controller + 1, $target);
+# X4200-M2: platform specific end
+
+ printf OFILE "\n <node instance='%d'>\n\n", $bay;
+
+ printf OFILE
+ " <propgroup name='protocol' version='1' " .
+ "name-stability='Private' data-stability='Private' >\n";
+ printf OFILE
+ " <propval name='label' type='string' " .
+ "value='%s%d' />\n",
+ $sys_supported->{"bay_label"}, $bay;
+ printf OFILE
+ " </propgroup>\n";
+
+ printf OFILE
+ " <propgroup name='io' version='1' " .
+ "name-stability='Private' data-stability='Private' >\n";
+ printf OFILE
+ " <propval name='ap-path' type='string' " .
+ "value='/devices%s%s' />\n", $hpath, $apoint;
+ printf OFILE
+ " </propgroup>\n";
+
+# no LED support
+
+ printf OFILE
+ " <propgroup name='binding' version='1' " .
+ "name-stability='Private' data-stability='Private' >\n";
+ printf OFILE
+ " <propval name='occupant-path' type='string' " .
+ "value='%s%s' />\n", $hpath, $tpath;
+ printf OFILE
+ " </propgroup>\n";
+
+ printf OFILE "\n </node>\n\n";
+ }
+}
+
+$ok = getopts("p:i:o:h", \%options);
+if ($options{'h'}) {
+ Usage();
+ exit (1);
+}
+
+$platform = $options{'p'};
+$input_file = $options{'i'};
+$output_file = $options{'o'};
+
+if (!$platform || !$input_file || !$output_file) {
+ Usage();
+ exit (1);
+}
+
+open(IFILE, "< $input_file") || die("$input_file cannot be opened.");
+open(OFILE, "> $output_file") || die("$output_file cannot be opened.");
+my $in_chassis_range = 0;
+
+while ($line = <IFILE>) {
+ chomp($line);
+
+ if ($line =~ /range\s+name\s?=\s?\Wchassis\W/) {
+ $in_chassis_range = 1;
+ }
+ if ($in_chassis_range && ($line =~ /<\/dependents>/)) {
+ last;
+ } else {
+ print OFILE "$line\n";
+ }
+}
+
+print OFILE " <!--xml-gen internal storage-->\n";
+printf OFILE " <range name='bay' min='0' max='%d'>\n",
+ $sys_supported->{"num_bays"}-1;
+
+calc_nodes(0);
+
+printf OFILE " <dependents grouping='children'>\n";
+printf OFILE " <range name='disk' min='0' max='0'>\n";
+printf OFILE " <enum-method name='disk' version='1' />\n";
+printf OFILE " </range>\n";
+printf OFILE " </dependents>\n\n";
+printf OFILE " </range>\n";
+
+print OFILE "$line\n";
+while ($line = <IFILE>) {
+ print OFILE $line;
+}
+
+close OFILE;
+close IFILE;
diff --git a/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4200-Server/Makefile b/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4200-Server/Makefile
new file mode 100644
index 0000000000..40cc3f7c5b
--- /dev/null
+++ b/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4200-Server/Makefile
@@ -0,0 +1,41 @@
+#
+# 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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+# NOTE: The name of the xml file we are building is 'platform'
+# specific, but its build is structured as 'arch' specific since
+# 'uname -i' on all x86 platforms returns i86pc.
+
+ARCH = i86pc
+CLASS = arch
+DTDFILE =
+TOPOFILE = Sun-Fire-X4200-Server-hc-topology.xml
+SRCDIR = ../SUNW,Sun-Fire-X4200-Server
+
+PLATFORM = Sun-Fire-X4200
+TOPOBASE = ../i86pc/i86pc-hc-topology.xml
+
+include ../Makefile.map
diff --git a/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4200-Server/Sun-Fire-X4200-Server-hc-topology.xmlgen b/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4200-Server/Sun-Fire-X4200-Server-hc-topology.xmlgen
new file mode 100644
index 0000000000..d6bd251c68
--- /dev/null
+++ b/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4200-Server/Sun-Fire-X4200-Server-hc-topology.xmlgen
@@ -0,0 +1,150 @@
+#!/usr/local/bin/perl
+#
+# 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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+use Getopt::Std;
+
+# X4200-Server: platform specific begin
+my $sys_supported = { "name" => "Sun-Fire-X4200-Server",
+ "num_bays" => "4",
+ "bay_label" => "HD"};
+# X4200-Server: platform specific end
+
+$IFILE = "filehandle";
+$OFILE = "filehandle";
+
+sub Usage()
+{
+ print STDERR "Usage: xml-gen -p <platform> " .
+ "-i <input_xml_file> -o <output_xml_file>\n";
+}
+
+sub calc_nodes
+{
+# X4200-Server: platform specific begin
+ $controller = 0;
+# X4200-Server: platform specific end
+
+ for ($bay = 0; $bay < $sys_supported->{"num_bays"}; $bay++) {
+
+# X4200-Server: platform specific begin
+ $target = $bay;
+
+ # set hba path, target path, bay path, and attachment point
+ $hpath = "/pci\@0,0/pci1022,7450\@2/pci1000,3060\@3";
+ $tpath = sprintf("/sd\@%x,0", $target);
+ $apoint = sprintf(":scsi::dsk/c%dt%dd0",
+ $controller + 1, $target);
+# X4200-Server: platform specific end
+
+ printf OFILE "\n <node instance='%d'>\n\n", $bay;
+
+ printf OFILE
+ " <propgroup name='protocol' version='1' " .
+ "name-stability='Private' data-stability='Private' >\n";
+ printf OFILE
+ " <propval name='label' type='string' " .
+ "value='%s%d' />\n",
+ $sys_supported->{"bay_label"}, $bay;
+ printf OFILE
+ " </propgroup>\n";
+
+ printf OFILE
+ " <propgroup name='io' version='1' " .
+ "name-stability='Private' data-stability='Private' >\n";
+ printf OFILE
+ " <propval name='ap-path' type='string' " .
+ "value='/devices%s%s' />\n", $hpath, $apoint;
+ printf OFILE
+ " </propgroup>\n";
+
+# no LED support
+
+ printf OFILE
+ " <propgroup name='binding' version='1' " .
+ "name-stability='Private' data-stability='Private' >\n";
+ printf OFILE
+ " <propval name='occupant-path' type='string' " .
+ "value='%s%s' />\n", $hpath, $tpath;
+ printf OFILE
+ " </propgroup>\n";
+
+ printf OFILE "\n </node>\n\n";
+ }
+}
+
+$ok = getopts("p:i:o:h", \%options);
+if ($options{'h'}) {
+ Usage();
+ exit (1);
+}
+
+$platform = $options{'p'};
+$input_file = $options{'i'};
+$output_file = $options{'o'};
+
+if (!$platform || !$input_file || !$output_file) {
+ Usage();
+ exit (1);
+}
+
+open(IFILE, "< $input_file") || die("$input_file cannot be opened.");
+open(OFILE, "> $output_file") || die("$output_file cannot be opened.");
+my $in_chassis_range = 0;
+
+while ($line = <IFILE>) {
+ chomp($line);
+
+ if ($line =~ /range\s+name\s?=\s?\Wchassis\W/) {
+ $in_chassis_range = 1;
+ }
+ if ($in_chassis_range && ($line =~ /<\/dependents>/)) {
+ last;
+ } else {
+ print OFILE "$line\n";
+ }
+}
+
+print OFILE " <!--xml-gen internal storage-->\n";
+printf OFILE " <range name='bay' min='0' max='%d'>\n",
+ $sys_supported->{"num_bays"}-1;
+
+calc_nodes(0);
+
+printf OFILE " <dependents grouping='children'>\n";
+printf OFILE " <range name='disk' min='0' max='0'>\n";
+printf OFILE " <enum-method name='disk' version='1' />\n";
+printf OFILE " </range>\n";
+printf OFILE " </dependents>\n\n";
+printf OFILE " </range>\n";
+
+print OFILE "$line\n";
+while ($line = <IFILE>) {
+ print OFILE $line;
+}
+
+close OFILE;
+close IFILE;
diff --git a/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4500/Sun-Fire-X4500-hc-topology.xmlgen b/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4500/Sun-Fire-X4500-hc-topology.xmlgen
index afb5b1c879..0d58d0b2d0 100644
--- a/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4500/Sun-Fire-X4500-hc-topology.xmlgen
+++ b/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4500/Sun-Fire-X4500-hc-topology.xmlgen
@@ -23,146 +23,144 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
+#pragma ident "%Z%%M% %I% %E% SMI"
#
use Getopt::Std;
-
-my $sys_supported = {"name" => "Sun-Fire-X4500",
- "prop_name" => "sfx4500",
- "num_bays" => "48"};
-
+# X4500: platform specific begin
+my $sys_supported = { "name" => "Sun-Fire-X4500",
+ "prop_name" => "sfx4500",
+ "num_bays" => "48",
+ "bay_label" => "HD_ID_"};
+# X4500: platform specific end
$IFILE = "filehandle";
$OFILE = "filehandle";
sub Usage()
{
- print STDERR "Usage: xml-gen -p <platform> -i <input_xml_file> -o <output_xml_file>\n";
+ print STDERR "Usage: xml-gen -p <platform> " .
+ "-i <input_xml_file> -o <output_xml_file>\n";
}
+# Define properties associated with LED manipulation.
+# We have three LEDs per disk: Present (PRSNT), OK-to-remove (OK2RM), and fault.
+# We track the following states (absent present configured unconfigured) via
+# the PRSNT/OK2RM LEDs (FAULT LED is maintained separately).
sub calc_sfx_prop
{
my $name = shift;
- my $hdd = shift;
+ my $bay = shift;
my $sid = shift;
- printf OFILE "\n";
- printf OFILE " <propgroup name='%s-properties'", $name;
- printf OFILE " version='1' name-stability='Private'";
- printf OFILE " data-stability='Private' >\n";
- printf OFILE " <propval name='fru-update-action'";
- printf OFILE " type='string' value='ipmi:fru gid=3 hdd=%d' />\n", $hdd;
- printf OFILE " <propval name='indicator-name-0'";
- printf OFILE " type='string' value='+PRSNT' />\n";
- printf OFILE " <propval name='indicator-action-0'";
- printf OFILE " type='string' value='ipmi:state sid=%d amask=0x0001' />\n",
- $sid;
- printf OFILE " <propval name='indicator-name-1'";
- printf OFILE " type='string' value='-PRSNT' />\n";
- printf OFILE " <propval name='indicator-action-1'";
- printf OFILE " type='string' value='ipmi:state sid=%d dmask=0x0001' />\n",
- $sid;
- printf OFILE " <propval name='indicator-name-2'";
- printf OFILE " type='string' value='+OK2RM' />\n";
- printf OFILE " <propval name='indicator-action-2'";
- printf OFILE " type='string' value='ipmi:state sid=%d amask=0x0008' />\n",
- $sid;
- printf OFILE " <propval name='indicator-name-3'";
- printf OFILE " type='string' value='-OK2RM' />\n";
- printf OFILE " <propval name='indicator-action-3'";
- printf OFILE " type='string' value='ipmi:state sid=%d dmask=0x0008' />\n",
- $sid;
- printf OFILE " <propval name='indicator-name-4'";
- printf OFILE " type='string' value='+FAULT' />\n";
- printf OFILE " <propval name='indicator-action-4'";
- printf OFILE " type='string' value='ipmi:state sid=%d amask=0x0002' />\n",
- $sid;
- printf OFILE " <propval name='indicator-name-5'";
- printf OFILE " type='string' value='-FAULT' />\n";
- printf OFILE " <propval name='indicator-action-5'";
- printf OFILE " type='string' value='ipmi:state sid=%d dmask=0x0002' />\n",
- $sid;
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "states-0' type='string' value='absent>present' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "actions-0' type='string' value='+PRSNT&amp;+OK2RM' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "states-1' type='string' value='present>configured' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "actions-1' type='string' value='+PRSNT&amp;-OK2RM' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "states-2' type='string' value='configured>unconfigured' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "actions-2' type='string' value='+OK2RM' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "states-3' type='string' value='unconfigured>configured' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "actions-3' type='string' value='-OK2RM' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "states-4' type='string' value='unconfigured>absent' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "actions-4' type='string' value='-OK2RM&amp;-PRSNT' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "states-5' type='string' value='configured>absent' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "actions-5' type='string' value='-OK2RM&amp;-PRSNT' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "states-6' type='string' value='present>absent' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "actions-6' type='string' value='-OK2RM&amp;-PRSNT' />\n";
- printf OFILE " </propgroup>\n";
- printf OFILE "\n";
+ my @names = (
+ "+PRSNT", "-PRSNT",
+ "+OK2RM", "-OK2RM",
+ "+FAULT", "-FAULT");
+ my @masks = (
+ "amask=0x0001", "dmask=0x0001",
+ "amask=0x0008", "dmask=0x0008",
+ "amask=0x0002", "dmask=0x0002");
+ my @states = (
+ "absent>present", "present>configured",
+ "configured>unconfigured", "unconfigured>configured",
+ "unconfigured>absent", "configured>absent",
+ "present>absent", "absent>configured");
+ my @actions = (
+ "+PRSNT&amp;+OK2RM", "+PRSNT&amp;-OK2RM",
+ "+OK2RM", "-OK2RM",
+ "-OK2RM&amp;-PRSNT", "-OK2RM&amp;-PRSNT",
+ "-OK2RM&amp;-PRSNT", "-OK2RM&amp;+PRSNT");
+
+ printf OFILE "\n";
+ printf OFILE
+ " <propgroup name='%s-properties' version='1' " .
+ "name-stability='Private' data-stability='Private' >\n", $name;
+ printf OFILE
+ " <propval name='fru-update-action' type='string' " .
+ "value='ipmi:fru gid=3 hdd=%d' />\n", $bay;
+
+ for ($i = 0; $i < 6; $i++) {
+ printf OFILE
+ " <propval name='indicator-name-%d' type='string' " .
+ "value='%s' />\n", $i, $names[$i];
+ printf OFILE
+ " <propval name='indicator-action-%d' " .
+ "type='string' value='ipmi:state sid=%d %s' />\n",
+ $i, $sid, $masks[$i];
+ }
+
+ for ($i = 0; $i < 8; $i++) {
+ printf OFILE
+ " <propval name='indicator-rule-states-%d' " .
+ "type='string' value='%s' />\n", $i, $states[$i];
+ printf OFILE
+ " <propval name='indicator-rule-actions-%d' " .
+ "type='string' value='%s' />\n", $i, $actions[$i];
+ }
+ printf OFILE
+ " </propgroup>\n\n";
}
-sub calc_nodes
+sub calc_nodes
{
+
+# X4500: platform specific begin
my @pci0=(1, 2, 0);
my @pci1=(4, 3, 8, 7, 2, 1);
+# X4500: platform specific end
+
+ for ($bay = 0; $bay < $sys_supported->{"num_bays"}; $bay++) {
- for ($cnt = 0; $cnt < $sys_supported->{"num_bays"}; $cnt++) {
- $hdd = $cnt;
- $sid = 90 + $cnt;
- $d = (($cnt/12) + (($cnt & 1) << 2));
- $index = (($cnt >> 2) % 3);
+# X4500: platform specific begin
+ $sid = 90 + $bay;
+ $target = (($bay/12) + (($bay & 1) << 2));
+ $index = (($bay >> 2) % 3);
$p0 = $pci0[$index];
- $index = (($cnt >> 1) % 6);
+ $index = (($bay >> 1) % 6);
$p1 = $pci1[$index];
- printf OFILE "\n";
- printf OFILE " <node instance='%d'>\n", $cnt;
- printf OFILE "\n";
- printf OFILE " <propgroup name='protocol'";
- printf OFILE " version='1' name-stability='Private'";
- printf OFILE " data-stability='Private' >\n";
- printf OFILE " <propval name='ASRU' ";
- printf OFILE "type='fmri' value=";
- printf OFILE "'dev:////pci@%d,0/pci1022,7458@%d", $p0, $p1;
- printf OFILE "/pci11ab,11ab\@1' />\n";
- printf OFILE " <propval name='label'";
- printf OFILE " type='string' value='bay%d' />\n", $cnt;
- printf OFILE " </propgroup>\n";
-
- printf OFILE " <propgroup name='io'";
- printf OFILE " version='1' name-stability='Private'";
- printf OFILE " data-stability='Private' >\n";
- printf OFILE " <propval name='ap-path'";
- printf OFILE " type='string'";
- printf OFILE " value='/devices/pci@%d,0/pci1022,7458@%d", $p0, $p1;
- printf OFILE "/pci11ab,11ab\@1:%d' />\n", $d;
- printf OFILE " </propgroup>\n";
-
- calc_sfx_prop($sys_supported->{"prop_name"}, $hdd, $sid);
- printf OFILE " <propgroup name='binding'";
- printf OFILE " version='1' name-stability='Private'";
- printf OFILE " data-stability='Private' >\n";
- printf OFILE " <propval name='occupant-path'";
- printf OFILE " type='string'";
- printf OFILE " value='/pci@%d,0/pci1022,7458@%d", $p0, $p1;
- printf OFILE "/pci11ab,11ab\@1/disk@%d,0' />\n", $d;
- printf OFILE " </propgroup>\n";
- printf OFILE "\n";
- printf OFILE " </node>\n";
- printf OFILE "\n";
+
+ # set hba path, target path, bay path, and attachment point
+ $hpath = sprintf("/pci\@%x,0/pci1022,7458\@%x/pci11ab,11ab\@1",
+ $p0, $p1);
+ $tpath = sprintf("/disk\@%x,0", $target);
+ $apoint = sprintf(":%d", $target);
+# X4500: platform specific end
+
+ printf OFILE "\n <node instance='%d'>\n\n", $bay;
+
+ printf OFILE
+ " <propgroup name='protocol' version='1' " .
+ "name-stability='Private' data-stability='Private' >\n";
+ printf OFILE
+ " <propval name='label' type='string' " .
+ "value='%s%d' />\n",
+ $sys_supported->{"bay_label"}, $bay;
+ printf OFILE
+ " </propgroup>\n";
+
+ printf OFILE
+ " <propgroup name='io' version='1' " .
+ "name-stability='Private' data-stability='Private' >\n";
+ printf OFILE
+ " <propval name='ap-path' type='string' " .
+ "value='/devices%s%s' />\n", $hpath, $apoint;
+ printf OFILE
+ " </propgroup>\n";
+
+# platform specific LED support
+ calc_sfx_prop($sys_supported->{"prop_name"}, $bay, $sid);
+
+ printf OFILE
+ " <propgroup name='binding' version='1' " .
+ "name-stability='Private' data-stability='Private' >\n";
+ printf OFILE
+ " <propval name='occupant-path' type='string' " .
+ "value='%s%s' />\n", $hpath, $tpath;
+ printf OFILE
+ " </propgroup>\n";
+
+ printf OFILE "\n </node>\n\n";
}
}
@@ -170,7 +168,7 @@ $ok = getopts("p:i:o:h", \%options);
if ($options{'h'}) {
Usage();
exit (1);
-}
+}
$platform = $options{'p'};
$input_file = $options{'i'};
@@ -184,8 +182,10 @@ if (!$platform || !$input_file || !$output_file) {
open(IFILE, "< $input_file") || die("$input_file cannot be opened.");
open(OFILE, "> $output_file") || die("$output_file cannot be opened.");
my $in_chassis_range = 0;
+
while ($line = <IFILE>) {
chomp($line);
+
if ($line =~ /range\s+name\s?=\s?\Wchassis\W/) {
$in_chassis_range = 1;
}
@@ -195,19 +195,20 @@ while ($line = <IFILE>) {
print OFILE "$line\n";
}
}
-print OFILE " <!--xml-gen internal storage-->\n";
-printf OFILE " <range name='bay' min='0' max='%d'>\n", $sys_supported->{"num_bays"};
+
+print OFILE " <!--xml-gen internal storage-->\n";
+printf OFILE " <range name='bay' min='0' max='%d'>\n",
+ $sys_supported->{"num_bays"}-1;
+
calc_nodes(0);
-printf OFILE " <dependents grouping='children'>\n";
-printf OFILE " <range name='disk' min='0'";
-printf OFILE " max='1'>\n";
-printf OFILE " <enum-method name='disk'";
-printf OFILE " version='1' />\n";
-printf OFILE " </range>\n";
-printf OFILE " </dependents>\n";
-printf OFILE "\n";
-printf OFILE " </range>\n";
+printf OFILE " <dependents grouping='children'>\n";
+printf OFILE " <range name='disk' min='0' max='0'>\n";
+printf OFILE " <enum-method name='disk' version='1' />\n";
+printf OFILE " </range>\n";
+printf OFILE " </dependents>\n\n";
+printf OFILE " </range>\n";
+
print OFILE "$line\n";
while ($line = <IFILE>) {
print OFILE $line;
diff --git a/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4540/Sun-Fire-X4540-hc-topology.xmlgen b/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4540/Sun-Fire-X4540-hc-topology.xmlgen
index 0d49a3c83a..1d1c8a8250 100644
--- a/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4540/Sun-Fire-X4540-hc-topology.xmlgen
+++ b/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-X4540/Sun-Fire-X4540-hc-topology.xmlgen
@@ -23,154 +23,143 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
+#pragma ident "%Z%%M% %I% %E% SMI"
#
use Getopt::Std;
-
-my $sys_supported = {"name" => "Sun-Fire-X4540",
- "prop_name" => "sfx4500",
- "num_bays" => "48"};
-
+# X4540: platform specific begin
+my $sys_supported = { "name" => "Sun-Fire-X4540",
+ "prop_name" => "sfx4500",
+ "num_bays" => "48",
+ "bay_label" => "HD_ID_"};
+# X4540: platform specific end
$IFILE = "filehandle";
$OFILE = "filehandle";
sub Usage()
{
- print STDERR "Usage: xml-gen -p <platform> -i <input_xml_file> -o <output_xml_file>\n";
+ print STDERR "Usage: xml-gen -p <platform> " .
+ "-i <input_xml_file> -o <output_xml_file>\n";
}
+# Define properties associated with LED manipulation.
+# We have three LEDs per disk: Present (PRSNT), OK-to-remove (OK2RM), and fault.
+# We track the following states (absent present configured unconfigured) via
+# the PRSNT/OK2RM LEDs (FAULT LED is maintained separately).
sub calc_sfx_prop
{
my $name = shift;
- my $hdd = shift;
+ my $bay = shift;
my $sid = shift;
- printf OFILE "\n";
- printf OFILE " <propgroup name='%s-properties'", $name;
- printf OFILE " version='1' name-stability='Private'";
- printf OFILE " data-stability='Private' >\n";
- printf OFILE " <propval name='fru-update-action'";
- printf OFILE " type='string' value='ipmi:fru gid=3 hdd=%d' />\n", $hdd;
- printf OFILE " <propval name='indicator-name-0'";
- printf OFILE " type='string' value='+PRSNT' />\n";
- printf OFILE " <propval name='indicator-action-0'";
- printf OFILE " type='string' value='ipmi:state sid=%d amask=0x0001' />\n",
- $sid;
- printf OFILE " <propval name='indicator-name-1'";
- printf OFILE " type='string' value='-PRSNT' />\n";
- printf OFILE " <propval name='indicator-action-1'";
- printf OFILE " type='string' value='ipmi:state sid=%d dmask=0x0001' />\n",
- $sid;
- printf OFILE " <propval name='indicator-name-2'";
- printf OFILE " type='string' value='+OK2RM' />\n";
- printf OFILE " <propval name='indicator-action-2'";
- printf OFILE " type='string' value='ipmi:state sid=%d amask=0x0008' />\n",
- $sid;
- printf OFILE " <propval name='indicator-name-3'";
- printf OFILE " type='string' value='-OK2RM' />\n";
- printf OFILE " <propval name='indicator-action-3'";
- printf OFILE " type='string' value='ipmi:state sid=%d dmask=0x0008' />\n",
- $sid;
- printf OFILE " <propval name='indicator-name-4'";
- printf OFILE " type='string' value='+FAULT' />\n";
- printf OFILE " <propval name='indicator-action-4'";
- printf OFILE " type='string' value='ipmi:state sid=%d amask=0x0002' />\n",
- $sid;
- printf OFILE " <propval name='indicator-name-5'";
- printf OFILE " type='string' value='-FAULT' />\n";
- printf OFILE " <propval name='indicator-action-5'";
- printf OFILE " type='string' value='ipmi:state sid=%d dmask=0x0002' />\n",
- $sid;
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "states-0' type='string' value='absent>present' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "actions-0' type='string' value='+PRSNT&amp;+OK2RM' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "states-1' type='string' value='present>configured' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "actions-1' type='string' value='+PRSNT&amp;-OK2RM' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "states-2' type='string' value='configured>unconfigured' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "actions-2' type='string' value='+OK2RM' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "states-3' type='string' value='unconfigured>configured' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "actions-3' type='string' value='-OK2RM' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "states-4' type='string' value='unconfigured>absent' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "actions-4' type='string' value='-OK2RM&amp;-PRSNT' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "states-5' type='string' value='configured>absent' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "actions-5' type='string' value='-OK2RM&amp;-PRSNT' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "states-6' type='string' value='present>absent' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "actions-6' type='string' value='-OK2RM&amp;-PRSNT' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "states-7' type='string' value='absent>configured' />\n";
- printf OFILE " <propval name='indicator-rule-";
- printf OFILE "actions-7' type='string' value='-OK2RM&amp;+PRSNT' />\n";
- printf OFILE " </propgroup>\n";
- printf OFILE "\n";
+ my @names = (
+ "+PRSNT", "-PRSNT",
+ "+OK2RM", "-OK2RM",
+ "+FAULT", "-FAULT");
+ my @masks = (
+ "amask=0x0001", "dmask=0x0001",
+ "amask=0x0008", "dmask=0x0008",
+ "amask=0x0002", "dmask=0x0002");
+ my @states = (
+ "absent>present", "present>configured",
+ "configured>unconfigured", "unconfigured>configured",
+ "unconfigured>absent", "configured>absent",
+ "present>absent", "absent>configured");
+ my @actions = (
+ "+PRSNT&amp;+OK2RM", "+PRSNT&amp;-OK2RM",
+ "+OK2RM", "-OK2RM",
+ "-OK2RM&amp;-PRSNT", "-OK2RM&amp;-PRSNT",
+ "-OK2RM&amp;-PRSNT", "-OK2RM&amp;+PRSNT");
+
+ printf OFILE "\n";
+ printf OFILE
+ " <propgroup name='%s-properties' version='1' " .
+ "name-stability='Private' data-stability='Private' >\n", $name;
+ printf OFILE
+ " <propval name='fru-update-action' type='string' " .
+ "value='ipmi:fru gid=3 hdd=%d' />\n", $bay;
+
+ for ($i = 0; $i < 6; $i++) {
+ printf OFILE
+ " <propval name='indicator-name-%d' type='string' " .
+ "value='%s' />\n", $i, $names[$i];
+ printf OFILE
+ " <propval name='indicator-action-%d' " .
+ "type='string' value='ipmi:state sid=%d %s' />\n",
+ $i, $sid, $masks[$i];
+ }
+
+ for ($i = 0; $i < 8; $i++) {
+ printf OFILE
+ " <propval name='indicator-rule-states-%d' " .
+ "type='string' value='%s' />\n", $i, $states[$i];
+ printf OFILE
+ " <propval name='indicator-rule-actions-%d' " .
+ "type='string' value='%s' />\n", $i, $actions[$i];
+ }
+ printf OFILE
+ " </propgroup>\n\n";
}
-sub calc_nodes
+sub calc_nodes
{
+
+# X4540: platform specific begin
my @pci0=(0, 0, 0, 0x3c, 0x3c, 0x3c);
my @pci1=(0x377, 0x375, 0x376, 0x377, 0x375, 0x376);
my @pci2=(0xa, 0xb, 0xf, 0xa, 0xb, 0xf);
+# X4540: platform specific end
for ($bay = 0; $bay < $sys_supported->{"num_bays"}; $bay++) {
- $controller = $bay / 8;
- $target = $bay % 8 ;
+# X4540: platform specific begin
$sid = 90 + $bay;
+ $target = $bay % 8;
+ $controller = $bay / 8;
- $physdev = "/pci\@" . sprintf("%x", $pci0[$controller]) .
- ",0/pci10de," . sprintf("%x", $pci1[$controller]) .
- "\@" . sprintf("%x", $pci2[$controller]) .
- "/pci1000,1000\@0";
-
- printf OFILE "\n";
- printf OFILE " <node instance='%d'>\n", $bay;
- printf OFILE "\n";
- printf OFILE " <propgroup name='protocol'";
- printf OFILE " version='1' name-stability='Private'";
- printf OFILE " data-stability='Private' >\n";
- printf OFILE " <propval name='ASRU' ";
- printf OFILE "type='fmri' value=";
- printf OFILE "'dev:///" . $physdev . "' />\n";
- printf OFILE " <propval name='label'";
- printf OFILE " type='string' value='bay%d' />\n", $bay;
- printf OFILE " </propgroup>\n";
-
- printf OFILE " <propgroup name='io'";
- printf OFILE " version='1' name-stability='Private'";
- printf OFILE " data-stability='Private' >\n";
- printf OFILE " <propval name='ap-path'";
- printf OFILE " type='string'";
- printf OFILE " value='/devices" . $physdev;
- printf OFILE ":scsi::dsk/c%dt%dd0", $controller + 1, $target;
- printf OFILE "' />\n";
- printf OFILE " </propgroup>\n";
-
+ # set hba path, target path, bay path, and attachment point
+ $hpath = sprintf("/pci\@%x,0/pci10de,%x\@%x/pci1000,1000\@0",
+ $pci0[$controller], $pci1[$controller], $pci2[$controller]);
+ $tpath = sprintf("/sd\@%x,0", $target);
+ $apoint = sprintf(":scsi::dsk/c%dt%dd0",
+ $controller + 1, $target);
+# X4540: platform specific end
+
+ printf OFILE "\n <node instance='%d'>\n\n", $bay;
+
+ printf OFILE
+ " <propgroup name='protocol' version='1' " .
+ "name-stability='Private' data-stability='Private' >\n";
+ printf OFILE
+ " <propval name='label' type='string' " .
+ "value='%s%d' />\n",
+ $sys_supported->{"bay_label"}, $bay;
+ printf OFILE
+ " </propgroup>\n";
+
+ printf OFILE
+ " <propgroup name='io' version='1' " .
+ "name-stability='Private' data-stability='Private' >\n";
+ printf OFILE
+ " <propval name='ap-path' type='string' " .
+ "value='/devices%s%s' />\n", $hpath, $apoint;
+ printf OFILE
+ " </propgroup>\n";
+
+# platform specific LED support
calc_sfx_prop($sys_supported->{"prop_name"}, $bay, $sid);
- printf OFILE " <propgroup name='binding'";
- printf OFILE " version='1' name-stability='Private'";
- printf OFILE " data-stability='Private' >\n";
- printf OFILE " <propval name='occupant-path'";
- printf OFILE " type='string'";
- printf OFILE " value='" . $physdev . "/sd\@%d,0", $target;
- printf OFILE "' />\n";
- printf OFILE " </propgroup>\n";
- printf OFILE "\n";
- printf OFILE " </node>\n";
- printf OFILE "\n";
+
+ printf OFILE
+ " <propgroup name='binding' version='1' " .
+ "name-stability='Private' data-stability='Private' >\n";
+ printf OFILE
+ " <propval name='occupant-path' type='string' " .
+ "value='%s%s' />\n", $hpath, $tpath;
+ printf OFILE
+ " </propgroup>\n";
+
+ printf OFILE "\n </node>\n\n";
}
}
@@ -178,7 +167,7 @@ $ok = getopts("p:i:o:h", \%options);
if ($options{'h'}) {
Usage();
exit (1);
-}
+}
$platform = $options{'p'};
$input_file = $options{'i'};
@@ -192,30 +181,33 @@ if (!$platform || !$input_file || !$output_file) {
open(IFILE, "< $input_file") || die("$input_file cannot be opened.");
open(OFILE, "> $output_file") || die("$output_file cannot be opened.");
my $in_chassis_range = 0;
+
while ($line = <IFILE>) {
chomp($line);
+
if ($line =~ /range\s+name\s?=\s?\Wchassis\W/) {
$in_chassis_range = 1;
}
- if ($in_chassis_range && ($line =~ /\/dependents/)) {
+ if ($in_chassis_range && ($line =~ /<\/dependents>/)) {
last;
} else {
print OFILE "$line\n";
}
}
-print OFILE " <!--xml-gen internal storage-->\n";
-printf OFILE " <range name='bay' min='0' max='%d'>\n", $sys_supported->{"num_bays"};
+
+print OFILE " <!--xml-gen internal storage-->\n";
+printf OFILE " <range name='bay' min='0' max='%d'>\n",
+ $sys_supported->{"num_bays"}-1;
+
calc_nodes(0);
-printf OFILE " <dependents grouping='children'>\n";
-printf OFILE " <range name='disk' min='0'";
-printf OFILE " max='1'>\n";
-printf OFILE " <enum-method name='disk'";
-printf OFILE " version='1' />\n";
-printf OFILE " </range>\n";
-printf OFILE " </dependents>\n";
-printf OFILE "\n";
-printf OFILE " </range>\n";
+printf OFILE " <dependents grouping='children'>\n";
+printf OFILE " <range name='disk' min='0' max='0'>\n";
+printf OFILE " <enum-method name='disk' version='1' />\n";
+printf OFILE " </range>\n";
+printf OFILE " </dependents>\n\n";
+printf OFILE " </range>\n";
+
print OFILE "$line\n";
while ($line = <IFILE>) {
print OFILE $line;
diff --git a/usr/src/lib/fm/topo/modules/Makefile.plugin b/usr/src/lib/fm/topo/modules/Makefile.plugin
index fd459b0bb5..9ceaf85f45 100644
--- a/usr/src/lib/fm/topo/modules/Makefile.plugin
+++ b/usr/src/lib/fm/topo/modules/Makefile.plugin
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -37,9 +37,11 @@ include ../../../../../Makefile.lib
# Set PROG and OBJS based on the values of MODULE and SRCS. We expect that
# these macros to be defined by the Makefile that is including this file.
#
-SRCS = $(MODULESRCS:%.c=%.c)
+# SHAREDSRCS is used to share sources between multiple libtopo modules.
+#
+SRCS = $(MODULESRCS:%.c=%.c) $(SHAREDSRCS:%.c=../../common/$(SHAREDMODULE)/%.c)
PROG = $(MODULE:%=%.so)
-OBJS = $(SRCS:%.c=%.o)
+OBJS = $(MODULESRCS:%.c=%.o) $(SHAREDSRCS:%.c=%.o)
#
# Set ROOTPROG and ROOTCONF based on the values of MODULE, CLASS, and PLATFORMS
@@ -84,6 +86,10 @@ $(PROG): $(OBJS) $(APIMAP)
$(COMPILE.c) $<
$(CTFCONVERT_O)
+%.o: ../../common/$(SHAREDMODULE)/%.c
+ $(COMPILE.c) $<
+ $(CTFCONVERT_O)
+
%.o: %.c
$(COMPILE.c) $<
$(CTFCONVERT_O)
diff --git a/usr/src/lib/fm/topo/modules/common/disk/Makefile b/usr/src/lib/fm/topo/modules/common/disk/Makefile
index 49002147c7..b4821a6a82 100644
--- a/usr/src/lib/fm/topo/modules/common/disk/Makefile
+++ b/usr/src/lib/fm/topo/modules/common/disk/Makefile
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -27,7 +27,7 @@
MODULE = disk
CLASS = common
-MODULESRCS = disk.c
+MODULESRCS = disk.c disk_common.c
include ../../Makefile.plugin
diff --git a/usr/src/lib/fm/topo/modules/common/disk/disk.c b/usr/src/lib/fm/topo/modules/common/disk/disk.c
index 8253eabb9c..c248e90553 100644
--- a/usr/src/lib/fm/topo/modules/common/disk/disk.c
+++ b/usr/src/lib/fm/topo/modules/common/disk/disk.c
@@ -18,9 +18,8 @@
*
* CDDL HEADER END
*/
-
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -37,667 +36,103 @@
#include <sys/fm/protocol.h>
#include "disk.h"
-static int disk_status(topo_mod_t *, tnode_t *, topo_version_t,
- nvlist_t *, nvlist_t **);
-
-/*
- * Given a /devices path for a whole disk, appending this extension gives the
- * path to a raw device that can be opened.
- */
-#if defined(__i386) || defined(__amd64)
-#define PHYS_EXTN ":q,raw"
-#elif defined(__sparc) || defined(__sparcv9)
-#define PHYS_EXTN ":c,raw"
-#else
-#error Unknown architecture
-#endif
-
static int disk_enum(topo_mod_t *, tnode_t *, const char *,
topo_instance_t, topo_instance_t, void *, void *);
static const topo_modops_t disk_ops =
{ disk_enum, NULL };
-const topo_modinfo_t disk_info =
+static const topo_modinfo_t disk_info =
{DISK, FM_FMRI_SCHEME_HC, DISK_VERSION, &disk_ops};
-static const topo_pgroup_info_t io_pgroup =
- { TOPO_PGROUP_IO, TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
-
-static const topo_pgroup_info_t disk_auth_pgroup = {
- FM_FMRI_AUTHORITY,
- TOPO_STABILITY_PRIVATE,
- TOPO_STABILITY_PRIVATE,
-};
-
-static const topo_pgroup_info_t storage_pgroup = {
- TOPO_STORAGE_PGROUP,
- TOPO_STABILITY_PRIVATE,
- TOPO_STABILITY_PRIVATE,
- 1
-};
-
-/*
- * Methods for disks. This is used by the disk-transport module to
- * generate ereports based off SCSI disk status.
- */
-static const topo_method_t disk_methods[] = {
- { TOPO_METH_DISK_STATUS, TOPO_METH_DISK_STATUS_DESC,
- TOPO_METH_DISK_STATUS_VERSION, TOPO_STABILITY_INTERNAL,
- disk_status },
- { NULL }
-};
-static di_devlink_handle_t devlink_hdl = NULL;
-
-/* disk node information */
-typedef struct disk_di_node {
- topo_list_t ddn_list;
- int ddn_instance;
- char *ddn_devid;
- di_node_t ddn_node;
- char *ddn_lpath; /* logical path */
- char *ddn_dpath; /* device path */
-}disk_di_node_t;
-
-typedef struct disk_di_nodes {
- pthread_mutex_t disk_di_nodes_lock;
- topo_list_t disk_di_nodes_list;
-}disk_di_nodes_t;
-
-/* list of devices */
-static disk_di_nodes_t disk_di_nodes;
-
-/* given a device find it in the global device list */
-static disk_di_node_t *
-disk_di_node_match_device(char *device)
-{
- disk_di_node_t *dnode;
-
- (void) pthread_mutex_lock(&disk_di_nodes.disk_di_nodes_lock);
- for (dnode = topo_list_next(&(disk_di_nodes.disk_di_nodes_list));
- dnode != NULL; dnode = topo_list_next(dnode)) {
- if (dnode->ddn_devid != NULL &&
- strcmp(device,
- dnode->ddn_dpath) == 0) {
- (void) pthread_mutex_unlock(
- &disk_di_nodes.disk_di_nodes_lock);
- return (dnode);
- }
- }
- (void) pthread_mutex_unlock(&disk_di_nodes.disk_di_nodes_lock);
- return (NULL);
-}
-
-/* get the disk storage group information */
-static void
-disk_storage_info(topo_mod_t *mod, disk_di_node_t *dnode,
- char **model, char **manuf, char **serial, char **firm, char **cap)
-{
- char *entry;
- di_node_t node = dnode->ddn_node;
- int64_t *nblocksp;
- uint64_t nblocks;
- int *dblksizep;
- uint_t dblksize;
- char lentry[MAXPATHLEN];
-
- if (di_prop_lookup_strings(DDI_DEV_T_ANY, node,
- INQUIRY_VENDOR_ID, &entry) > 0) {
- *manuf = topo_mod_strdup(mod, entry);
- }
- if (di_prop_lookup_strings(DDI_DEV_T_ANY, node,
- INQUIRY_PRODUCT_ID, &entry) > 0) {
- *model = topo_mod_strdup(mod, entry);
- }
- if (di_prop_lookup_strings(DDI_DEV_T_ANY, node,
- INQUIRY_REVISION_ID, &entry) > 0) {
- *firm = topo_mod_strdup(mod, entry);
- }
- if (di_prop_lookup_strings(DDI_DEV_T_ANY, node,
- INQUIRY_SERIAL_NO, &entry) > 0) {
- *serial = topo_mod_strdup(mod, entry);
- }
- if (di_prop_lookup_int64(DDI_DEV_T_ANY, node,
- "device-nblocks", &nblocksp) > 0) {
- nblocks = (uint64_t)*nblocksp;
- /*
- * To save kernel memory, the driver may not
- * define "device-dblksize" when its value is
- * the default DEV_BSIZE value.
- */
- if (di_prop_lookup_ints(DDI_DEV_T_ANY, node,
- "device-dblksize", &dblksizep) > 0)
- dblksize = (uint_t)*dblksizep;
- else
- dblksize = DEV_BSIZE; /* default value */
- (void) snprintf(lentry, sizeof (lentry),
- "%" PRIu64, nblocks * dblksize);
- *cap = topo_mod_strdup(mod, lentry);
- }
-}
-
-/* populate the protocol group properties */
-static void
-disk_set_proto_props(topo_mod_t *mod, tnode_t *dtn, int pinst)
-{
- int err;
- nvlist_t *asru = NULL;
- char label[32];
- char *func = "disk_set_proto_props";
- nvlist_t *fmri;
- disk_di_node_t *dnode;
-
- /* set the asru */
- dnode = topo_node_getspecific(dtn);
- asru = topo_mod_devfmri(mod, FM_DEV_SCHEME_VERSION,
- dnode->ddn_dpath, dnode->ddn_devid);
- if (topo_node_asru_set(dtn, asru, 0, &err) != 0) {
- topo_mod_dprintf(mod,
- "%s: topo_node_asru_set error %d\n",
- func, err);
- nvlist_free(asru);
- (void) topo_mod_seterrno(mod, err);
- return;
- }
- nvlist_free(asru);
-
- (void) snprintf(label, sizeof (label), "HD_ID_%d", pinst);
- if (topo_node_label_set(dtn, label, &err) != 0) {
- topo_mod_dprintf(mod, "%s: label error %s\n", func,
- topo_strerror(err));
- (void) topo_mod_seterrno(mod, err);
- return;
- }
-
- /* get the resource property */
- if (topo_node_resource(dtn, &fmri, &err) != 0) {
- topo_mod_dprintf(mod,
- "%s: topo_node_resource error: %s\n", func,
- topo_strerror(err));
- (void) topo_mod_seterrno(mod, err);
- return;
- }
-
- /* set the child fru to the same as the resource */
- if (topo_node_fru_set(dtn, fmri, 0, &err) != 0) {
- topo_mod_dprintf(mod,
- "%s: topo_node_fru_set error: %s\n", func,
- topo_strerror(err));
- (void) topo_mod_seterrno(mod, err);
- nvlist_free(fmri);
- return;
- }
- nvlist_free(fmri);
-}
-
-
-/*
- * Set the properties of the disk node which include:
- * group: protocol properties: resource, asru, label, fru
- * group: authority properties: product-id, chasis-id, server-id
- * group: io properties: devfs-path
- * group: storage properties:
- * - logical-disk, disk-model, disk-manufacturer, serial-number
- * - firmware-revision, capacity-in-bytes
- */
-static void
-disk_set_props(tnode_t *dtn, tnode_t *parent, char *model, char *manuf,
- char *serial, char *firm, char *cap, int *err, topo_mod_t *mod)
-{
- char *device;
- char *ptr, *ptr1;
- int inst = topo_node_instance(parent);
- disk_di_node_t *dnode;
-
- dnode = topo_node_getspecific(dtn);
-
- /* set the protocol group properties */
- disk_set_proto_props(mod, dtn, inst);
-
- /* create/set the authority group */
- if (topo_pgroup_create(dtn, &disk_auth_pgroup, err) == 0) {
- (void) topo_prop_inherit(dtn, FM_FMRI_AUTHORITY,
- FM_FMRI_AUTH_PRODUCT, err);
- (void) topo_prop_inherit(dtn, FM_FMRI_AUTHORITY,
- FM_FMRI_AUTH_CHASSIS, err);
- (void) topo_prop_inherit(dtn, FM_FMRI_AUTHORITY,
- FM_FMRI_AUTH_SERVER, err);
- }
-
- /* create/set the devfs-path in the io group */
- (void) topo_pgroup_create(dtn, &io_pgroup, err);
-
- if (topo_prop_get_string(parent, TOPO_BINDING_PGROUP,
- TOPO_BINDING_OCCUPANT, &device, err) == 0) {
- (void) topo_prop_set_string(dtn, TOPO_PGROUP_IO,
- TOPO_IO_DEV_PATH, TOPO_PROP_IMMUTABLE, device, err);
-
- topo_mod_strfree(mod, device);
- }
-
- /* create the storage group */
- (void) topo_pgroup_create(dtn, &storage_pgroup, err);
-
- /* set the storage group properties */
- ptr = strrchr(dnode->ddn_lpath, '/');
- ptr1 = strchr(ptr, 's');
- if (ptr1)
- *ptr1 = '\0';
- (void) topo_prop_set_string(dtn, TOPO_STORAGE_PGROUP,
- TOPO_STORAGE_LOGICAL_DISK_NAME, TOPO_PROP_IMMUTABLE,
- ptr+1, err);
- if (ptr1)
- *ptr1 = 's';
-
-
- /* populate the storage group properties */
- if (model) {
- (void) topo_prop_set_string(dtn, TOPO_STORAGE_PGROUP,
- TOPO_STORAGE_MODEL, TOPO_PROP_IMMUTABLE, model, err);
- }
- if (manuf) {
- (void) topo_prop_set_string(dtn, TOPO_STORAGE_PGROUP,
- TOPO_STORAGE_MANUFACTURER, TOPO_PROP_IMMUTABLE, manuf,
- err);
- }
- if (serial) {
- (void) topo_prop_set_string(dtn, TOPO_STORAGE_PGROUP,
- TOPO_STORAGE_SERIAL_NUM, TOPO_PROP_IMMUTABLE, serial, err);
- }
- if (firm) {
- (void) topo_prop_set_string(dtn, TOPO_STORAGE_PGROUP,
- TOPO_STORAGE_FIRMWARE_REV, TOPO_PROP_IMMUTABLE, firm, err);
- }
- if (cap) {
- (void) topo_prop_set_string(dtn, TOPO_STORAGE_PGROUP,
- TOPO_STORAGE_CAPACITY, TOPO_PROP_IMMUTABLE, cap, err);
- }
-}
-
-/* create the disk topo node */
-/*ARGSUSED*/
-static tnode_t *
-disk_tnode_create(topo_mod_t *mod, tnode_t *parent,
- const char *name, topo_instance_t i, char *model, char *manuf,
- char *serial, char *firm, char *cap, void *priv)
-{
- int err, len = 0;
- nvlist_t *fmri;
- tnode_t *dtn;
- char *mm = NULL;
- char *s;
- nvlist_t *auth = topo_mod_auth(mod, parent);
-
- if ((s = strchr(model, ' ')) != NULL) {
- *s = '-';
- }
- len = strlen(manuf) + strlen(model) + 2;
- if ((mm = topo_mod_alloc(mod, len)) != NULL)
- (void) snprintf(mm, len, "%s-%s", manuf, model);
- else
- mm = model;
-
- fmri = topo_mod_hcfmri(mod, parent, FM_HC_SCHEME_VERSION, name, i,
- NULL, auth, mm, firm, serial);
-
- nvlist_free(auth);
-
- if (mm != model)
- topo_mod_free(mod, mm, len);
- else if (*s != NULL)
- *s = ' ';
-
- if (fmri == NULL) {
- topo_mod_dprintf(mod,
- "Unable to make nvlist for %s bind: %s.\n",
- name, topo_mod_errmsg(mod));
- return (NULL);
- }
-
- if ((dtn = topo_node_bind(mod, parent, name, i, fmri)) == 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(dtn, priv);
-
- /* add the properties of the disk */
- disk_set_props(dtn, parent, model, manuf, serial, firm, cap,
- &err, mod);
-
- return (dtn);
-}
-
-/*ARGSUSED*/
-static tnode_t *
-disk_declare(tnode_t *parent, const char *name, topo_instance_t i,
- void *priv, topo_mod_t *mod)
-{
- tnode_t *dtn;
- int err;
- char *func = "disk_declare";
- char *model = NULL, *manuf = NULL, *serial = NULL;
- char *cap = NULL, *firm = NULL;
- disk_di_node_t *dnode = (disk_di_node_t *)priv;
- nvlist_t *fmri;
-
- disk_storage_info(mod, dnode,
- &model, &manuf, &serial, &firm, &cap);
-
- /* create the node */
- dtn = disk_tnode_create(mod, parent,
- name, i, model, manuf, serial, firm, cap, priv);
-
- topo_mod_strfree(mod, model);
- topo_mod_strfree(mod, manuf);
- topo_mod_strfree(mod, serial);
- topo_mod_strfree(mod, firm);
- topo_mod_strfree(mod, cap);
-
- if (dtn == NULL) {
- return (NULL);
- }
-
- /* set the parent fru */
- if (topo_node_resource(parent, &fmri, &err) != 0) {
- topo_mod_dprintf(mod,
- "%s: topo_node_resource error: %s\n", func,
- topo_strerror(err));
- topo_node_unbind(dtn);
- return (NULL);
- }
- if (topo_node_fru_set(parent, fmri, 0, &err) != 0) {
- topo_mod_dprintf(mod, "%s topo_node_fru error: %s\n",
- func, topo_strerror(err));
- nvlist_free(fmri);
- topo_node_unbind(dtn);
- return (NULL);
- }
-
- if (topo_method_register(mod, dtn, disk_methods) != 0) {
- topo_mod_dprintf(mod,
- "topo_method_register failed: %s\n",
- topo_strerror(topo_mod_errno(mod)));
- nvlist_free(fmri);
- topo_node_unbind(dtn);
- return (NULL);
- }
-
- nvlist_free(fmri);
-
- return (dtn);
-}
-
/*ARGSUSED*/
static int
-disk_enum(topo_mod_t *mod, tnode_t *rnode, const char *name,
- topo_instance_t min, topo_instance_t max, void *arg, void *notused)
+disk_enum(topo_mod_t *mod, tnode_t *baynode,
+ const char *name, topo_instance_t min, topo_instance_t max,
+ void *arg, void *notused)
{
- tnode_t *diskn;
char *device;
int err;
- disk_di_node_t *dnode;
+ nvlist_t *fmri;
+ topo_list_t *dlistp = topo_mod_getspecific(mod);
if (strcmp(name, DISK) != 0) {
- topo_mod_dprintf(mod,
- "Currently only know how to enumerate %s components.\n",
- DISK);
+ topo_mod_dprintf(mod, "disk_enum: "
+ "only know how to enumerate %s components.\n", DISK);
return (-1);
}
- if (topo_prop_get_string(rnode, TOPO_BINDING_PGROUP,
- TOPO_BINDING_OCCUPANT, &device, &err) != 0)
- return (-1);
-
- if ((dnode = disk_di_node_match_device(device)) == NULL) {
- topo_mod_dprintf(mod,
- "No occupant found for bay=%d.\n",
- topo_node_instance(rnode));
- topo_mod_strfree(mod, device);
+ /* set the parent fru */
+ if (topo_node_resource(baynode, &fmri, &err) != 0) {
+ topo_mod_dprintf(mod, "disk_enum: "
+ "topo_node_resource error %s\n", topo_strerror(err));
return (-1);
}
-
- diskn = disk_declare(rnode, name, 0, dnode, mod);
- if (diskn == NULL) {
- topo_mod_dprintf(mod, "Enumeration of %s failed: %s\n",
- DISK, topo_strerror(topo_mod_errno(mod)));
- topo_mod_strfree(mod, device);
- return (-1); /* mod_errno already set */
+ if (topo_node_fru_set(baynode, fmri, 0, &err) != 0) {
+ topo_mod_dprintf(mod, "disk_enum: "
+ "topo_node_fru error %s\n", topo_strerror(err));
+ nvlist_free(fmri);
+ return (-1);
}
- topo_mod_strfree(mod, device);
- return (0);
-}
-
-/*
- * Query the current disk status. If successful, the disk status is returned as
- * an nvlist consisting of at least the following members:
- *
- * protocol string Supported protocol (currently "scsi")
- *
- * status nvlist Arbitrary protocol-specific information
- * about the current state of the disk.
- *
- * faults nvlist A list of supported faults. Each
- * element of this list is a boolean value.
- * An element's existence indicates that
- * the drive supports detecting this fault,
- * and the value indicates the current
- * state of the fault.
- *
- * <fault-name> nvlist For each fault named in 'faults', a
- * nvlist describing protocol-specific
- * attributes of the fault.
- *
- * This method relies on the libdiskstatus library to query this information.
- */
-static int
-disk_status(topo_mod_t *mod, tnode_t *nodep, topo_version_t vers,
- nvlist_t *in_nvl, nvlist_t **out_nvl)
-{
- disk_status_t *dsp;
- char *devpath, *fullpath;
- size_t pathlen;
- int err;
- nvlist_t *status;
- *out_nvl = NULL;
-
- if (vers != TOPO_METH_DISK_STATUS_VERSION)
- return (topo_mod_seterrno(mod, EMOD_VER_NEW));
+ nvlist_free(fmri);
/*
- * If the caller specifies the "path" parameter, then this indicates
- * that we should use this instead of deriving it from the topo node
- * itself.
+ * For internal storage, get the path to the occupant from the
+ * binding group of the bay node
*/
- if (nvlist_lookup_string(in_nvl, "path", &fullpath) == 0) {
- devpath = NULL;
- } else {
- /*
- * Get the /devices path and attempt to open the disk status
- * handle.
- */
- if (topo_prop_get_string(nodep, TOPO_PGROUP_IO,
- TOPO_IO_DEV_PATH, &devpath, &err) != 0)
- return (topo_mod_seterrno(mod, EMOD_METHOD_NOTSUP));
-
- /*
- * Note that sizeof(string) includes the terminating NULL byte
- */
- pathlen = strlen(devpath) + sizeof ("/devices") +
- sizeof (PHYS_EXTN) - 1;
-
- if ((fullpath = topo_mod_alloc(mod, pathlen)) == NULL)
- return (topo_mod_seterrno(mod, EMOD_NOMEM));
-
- (void) snprintf(fullpath, pathlen, "/devices%s%s", devpath,
- PHYS_EXTN);
-
- topo_mod_strfree(mod, devpath);
- }
-
- if ((dsp = disk_status_open(fullpath, &err)) == NULL) {
- if (devpath)
- topo_mod_free(mod, fullpath, pathlen);
- return (topo_mod_seterrno(mod, err == EDS_NOMEM ?
- EMOD_NOMEM : EMOD_METHOD_NOTSUP));
- }
-
- if (devpath)
- topo_mod_free(mod, fullpath, pathlen);
-
- if ((status = disk_status_get(dsp)) == NULL) {
- err = (disk_status_errno(dsp) == EDS_NOMEM ?
- EMOD_NOMEM : EMOD_METHOD_NOTSUP);
- disk_status_close(dsp);
- return (topo_mod_seterrno(mod, err));
- }
-
- *out_nvl = status;
- disk_status_close(dsp);
- return (0);
-}
-
-/* di_devlink callback for disk_drvinst2devpath */
-static int
-disk_drvinst2devpath_devlink_callback(di_devlink_t dl, void *arg)
-{
- char **devpathp = (char **)arg;
- char *devpath = (char *)di_devlink_path(dl);
-
- *devpathp = strdup(devpath);
- return (DI_WALK_TERMINATE);
-}
-
-static disk_di_node_t *
-disk_di_node_add(int *instancep, char *devid, di_node_t node, topo_mod_t *mod)
-{
- int mlen;
- char *devpath, *minorpath;
- char *extn = ":a";
- disk_di_node_t *dnode;
-
- (void) pthread_mutex_lock(&(disk_di_nodes.disk_di_nodes_lock));
- for (dnode = topo_list_next(&(disk_di_nodes.disk_di_nodes_list));
- dnode != NULL; dnode = topo_list_next(dnode)) {
- if (strcmp(dnode->ddn_devid, devid) == 0) {
- topo_mod_dprintf(mod,
- "disk_node_add - already there %s\n", devid);
- (void) pthread_mutex_unlock(
- &disk_di_nodes.disk_di_nodes_lock);
- return (dnode); /* return existing node */
- }
- }
-
- if ((dnode = topo_mod_alloc(mod, sizeof (disk_di_node_t))) == NULL) {
- topo_mod_dprintf(mod,
- "disk_node_add - topo_mod_alloc failed\n");
- (void) pthread_mutex_unlock(&disk_di_nodes.disk_di_nodes_lock);
- return (NULL); /* return existing node */
+ if (topo_prop_get_string(baynode, TOPO_PGROUP_BINDING,
+ TOPO_BINDING_OCCUPANT, &device, &err) != 0) {
+ topo_mod_dprintf(mod, "disk_enum: "
+ "binding error %s\n", topo_strerror(err));
+ return (-1);
}
- dnode->ddn_devid = strdup(devid);
- dnode->ddn_instance = *instancep;
- dnode->ddn_node = node;
- dnode->ddn_dpath = di_devfs_path(node);
-
- mlen = strlen(dnode->ddn_dpath) + strlen(extn) + 1;
- minorpath = topo_mod_alloc(mod, mlen);
- (void) snprintf(minorpath, mlen, "%s%s", dnode->ddn_dpath,
- extn);
- /* walk devlink looking for node that maps to /device path */
- devpath = NULL;
- (void) di_devlink_walk(devlink_hdl, "^dsk/",
- minorpath, DI_PRIMARY_LINK,
- (void *)&devpath, disk_drvinst2devpath_devlink_callback);
- topo_mod_free(mod, minorpath, mlen);
- dnode->ddn_lpath = devpath;
-
- topo_list_append(&disk_di_nodes.disk_di_nodes_list, (void *)dnode);
- (void) pthread_mutex_unlock(&disk_di_nodes.disk_di_nodes_lock);
-
- topo_mod_dprintf(mod,
- "disk_node_add - adding %s inst: %d\n",
- dnode->ddn_devid, *instancep);
- *instancep = (*instancep) + 1;
- return (dnode);
-}
-
-/*ARGSUSED*/
-static int
-disk_walk_di_nodes(di_node_t node, void *arg)
-{
- ddi_devid_t devid = NULL;
- char *devidstr;
- static int instance_devid = 0;
- topo_mod_t *mod = (topo_mod_t *)arg;
- /* only interested in nodes that have devids */
- devid = (ddi_devid_t)di_devid(node);
- if (devid == NULL)
- return (DI_WALK_CONTINUE);
+ /* locate and topo enumerate the disk with that path */
+ err = disk_declare_path(mod, baynode, dlistp, device);
- /* ... with a string representation of the devid */
- devidstr = devid_str_encode(devid, NULL);
- if (devidstr == NULL)
- return (DI_WALK_CONTINUE);
-
- /* create/find the devid scsi topology node */
- (void) disk_di_node_add(&instance_devid, devidstr, node, mod);
- devid_str_free(devidstr);
- return (DI_WALK_CONTINUE);
+ topo_mod_strfree(mod, device);
+ return (err);
}
/*ARGSUSED*/
int
_topo_init(topo_mod_t *mod, topo_version_t version)
{
- di_node_t devtree;
+ topo_list_t *dlistp;
/*
* Turn on module debugging output
*/
if (getenv("TOPODISKDEBUG") != NULL)
topo_mod_setdebug(mod);
- topo_mod_dprintf(mod, "initializing %s enumerator\n", DISK);
+ topo_mod_dprintf(mod, "_topo_init: "
+ "initializing %s enumerator\n", DISK);
if (topo_mod_register(mod, &disk_info, TOPO_VERSION) != 0) {
- topo_mod_dprintf(mod, "%s registration failed: %s\n",
- DISK, topo_mod_errmsg(mod));
- return (-1); /* mod errno already set */
+ topo_mod_dprintf(mod, "_topo_init: "
+ "%s registration failed: %s\n", DISK, topo_mod_errmsg(mod));
+ return (-1); /* mod errno already set */
}
- (void) pthread_mutex_init(&disk_di_nodes.disk_di_nodes_lock, NULL);
- disk_di_nodes.disk_di_nodes_list.l_next = NULL;
- disk_di_nodes.disk_di_nodes_list.l_prev = NULL;
-
- devtree = di_init("/", DINFOCACHE);
- /* we don't get all the nodes with topo_mod_devinfo */
- if (devtree == NULL) {
- topo_mod_unregister(mod);
- (void) pthread_mutex_destroy(&disk_di_nodes.disk_di_nodes_lock);
- topo_mod_dprintf(mod, "topo_mod_devinfo init failed.");
+ if ((dlistp = topo_mod_zalloc(mod, sizeof (topo_list_t))) == NULL) {
+ topo_mod_dprintf(mod, "_topo_inti: failed to allocate "
+ "disk list");
return (-1);
}
- /* walk the tree to get the devids */
- devlink_hdl = di_devlink_init(NULL, 0);
- if (devlink_hdl == DI_NODE_NIL) {
+
+ if (disk_list_gather(mod, dlistp) != 0) {
topo_mod_unregister(mod);
- (void) pthread_mutex_destroy(&disk_di_nodes.disk_di_nodes_lock);
- topo_mod_dprintf(mod, "di_devlink init failed.");
+ topo_mod_free(mod, dlistp, sizeof (topo_list_t));
+ topo_mod_dprintf(mod, "_topo_init: "
+ "failed to locate disks");
return (-1);
}
- (void) di_walk_node(devtree, DI_WALK_CLDFIRST, mod,
- disk_walk_di_nodes);
- if (devlink_hdl != NULL)
- (void) di_devlink_fini(&devlink_hdl);
+ topo_mod_dprintf(mod, "_topo_init: "
+ "%s enumerator initialized\n", DISK);
- topo_mod_dprintf(mod, "%s enumerator initialized\n", DISK);
+ topo_mod_setspecific(mod, dlistp);
return (0);
}
@@ -705,19 +140,10 @@ _topo_init(topo_mod_t *mod, topo_version_t version)
void
_topo_fini(topo_mod_t *mod)
{
- disk_di_node_t *dnode;
-
- (void) pthread_mutex_lock(&disk_di_nodes.disk_di_nodes_lock);
- while ((dnode = topo_list_next(&(disk_di_nodes.disk_di_nodes_list)))
- != NULL) {
- free(dnode->ddn_lpath);
- free(dnode->ddn_dpath);
- free(dnode->ddn_devid);
- topo_list_delete(&(disk_di_nodes.disk_di_nodes_list),
- (void *)dnode);
- topo_mod_free(mod, dnode, sizeof (disk_di_node_t));
- }
- (void) pthread_mutex_unlock(&disk_di_nodes.disk_di_nodes_lock);
- (void) pthread_mutex_destroy(&disk_di_nodes.disk_di_nodes_lock);
+ topo_list_t *dlistp = topo_mod_getspecific(mod);
+ disk_list_free(mod, dlistp);
+ topo_mod_free(mod, dlistp, sizeof (topo_list_t));
topo_mod_unregister(mod);
+ topo_mod_dprintf(mod, "_topo_fini: "
+ "%s enumerator uninitialized\n", DISK);
}
diff --git a/usr/src/lib/fm/topo/modules/common/disk/disk.h b/usr/src/lib/fm/topo/modules/common/disk/disk.h
index 2968c3663a..8596945b26 100644
--- a/usr/src/lib/fm/topo/modules/common/disk/disk.h
+++ b/usr/src/lib/fm/topo/modules/common/disk/disk.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -29,6 +29,9 @@
#pragma ident "%Z%%M% %I% %E% SMI"
+#include <fm/topo_mod.h>
+#include <libdevinfo.h>
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -39,12 +42,8 @@ extern "C" {
/* Max. number of devices for thumper */
#define DEVID_MAX 48
-/* Properties for binding group */
-#define TOPO_BINDING_PGROUP "binding"
-#define TOPO_BINDING_OCCUPANT "occupant-path"
-
/* Properties added to the "storage" pgroup: */
-#define TOPO_STORAGE_PGROUP "storage"
+#define TOPO_PGROUP_STORAGE "storage"
#define TOPO_STORAGE_LOGICAL_DISK_NAME "logical-disk"
#define TOPO_STORAGE_MODEL "model"
#define TOPO_STORAGE_MANUFACTURER "manufacturer"
@@ -52,6 +51,23 @@ extern "C" {
#define TOPO_STORAGE_FIRMWARE_REV "firmware-revision"
#define TOPO_STORAGE_CAPACITY "capacity-in-bytes"
+/*
+ * Properties for binding group: The binding group required in platform
+ * specific xml that describes 'bay' nodes containing internal disks.
+ */
+#define TOPO_PGROUP_BINDING "binding"
+#define TOPO_BINDING_OCCUPANT "occupant-path"
+
+struct topo_list;
+
+/* Methods shared with the ses module (disk_common.c) */
+extern int disk_list_gather(topo_mod_t *, struct topo_list *);
+extern void disk_list_free(topo_mod_t *, struct topo_list *);
+extern int disk_declare_path(topo_mod_t *, tnode_t *,
+ struct topo_list *, const char *);
+extern int disk_declare_addr(topo_mod_t *, tnode_t *,
+ struct topo_list *, const char *);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/fm/topo/modules/common/disk/disk_common.c b/usr/src/lib/fm/topo/modules/common/disk/disk_common.c
new file mode 100644
index 0000000000..3cc6651d7e
--- /dev/null
+++ b/usr/src/lib/fm/topo/modules/common/disk/disk_common.c
@@ -0,0 +1,868 @@
+/*
+ * 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 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Functions in this file are shared between the disk and ses enumerators.
+ *
+ * A topo_list_t of all disks is returned by a successful disk_list_gather()
+ * call, and the list is freed by a disk_list_free(). To create a 'disk' topo
+ * node below a specific 'bay' parent node either disk_declare_path() or
+ * disk_declare_addr() are called. The caller determines which 'disk' is
+ * in which 'bay'. A disk's 'label' and 'authority' information come from
+ * its parent 'bay' node.
+ */
+
+#include <strings.h>
+#include <libdevinfo.h>
+#include <devid.h>
+#include <sys/libdevid.h>
+#include <pthread.h>
+#include <inttypes.h>
+#include <sys/dkio.h>
+#include <sys/scsi/scsi_types.h>
+#include <fm/topo_mod.h>
+#include <fm/topo_list.h>
+#include <fm/libdiskstatus.h>
+#include <sys/fm/protocol.h>
+#include "disk.h"
+
+/*
+ * disk node information.
+ */
+typedef struct disk_di_node {
+ topo_list_t ddn_list; /* list of disks */
+
+ /* the following two fields are always defined */
+ char *ddn_devid; /* devid of disk */
+ char *ddn_dpath; /* path to devinfo (may be vhci) */
+ char **ddn_ppath; /* physical path to device (phci) */
+ int ddn_ppath_count;
+
+ char *ddn_lpath; /* logical path (public /dev name) */
+
+ char *ddn_mfg; /* misc information about device */
+ char *ddn_model;
+ char *ddn_serial;
+ char *ddn_firm;
+ char *ddn_cap;
+
+ char **ddn_target_port;
+ int ddn_target_port_count;
+} disk_di_node_t;
+
+/* common callback information for di_walk_node() and di_devlink_walk */
+typedef struct disk_cbdata {
+ topo_mod_t *dcb_mod;
+ topo_list_t *dcb_list;
+
+ di_devlink_handle_t dcb_devhdl;
+ disk_di_node_t *dcb_dnode; /* for di_devlink_walk only */
+} disk_cbdata_t;
+
+/*
+ * Given a /devices path for a whole disk, appending this extension gives the
+ * path to a raw device that can be opened.
+ */
+#if defined(__i386) || defined(__amd64)
+#define PHYS_EXTN ":q,raw"
+#elif defined(__sparc) || defined(__sparcv9)
+#define PHYS_EXTN ":c,raw"
+#else
+#error Unknown architecture
+#endif
+
+/*
+ * Methods for disks. This is used by the disk-transport module to
+ * generate ereports based off SCSI disk status.
+ */
+static int disk_status(topo_mod_t *, tnode_t *, topo_version_t,
+ nvlist_t *, nvlist_t **);
+
+static const topo_method_t disk_methods[] = {
+ { TOPO_METH_DISK_STATUS, TOPO_METH_DISK_STATUS_DESC,
+ TOPO_METH_DISK_STATUS_VERSION, TOPO_STABILITY_INTERNAL,
+ disk_status },
+ { 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 disk_auth_pgroup = {
+ FM_FMRI_AUTHORITY,
+ TOPO_STABILITY_PRIVATE,
+ TOPO_STABILITY_PRIVATE,
+ 1
+};
+
+static const topo_pgroup_info_t storage_pgroup = {
+ TOPO_PGROUP_STORAGE,
+ TOPO_STABILITY_PRIVATE,
+ TOPO_STABILITY_PRIVATE,
+ 1
+};
+
+/*
+ * Set the properties of the disk node, from disk_di_node_t data.
+ * Properties include:
+ * group: protocol properties: resource, asru, label, fru
+ * group: authority properties: product-id, chasis-id, server-id
+ * group: io properties: devfs-path, devid
+ * group: storage properties:
+ * - logical-disk, disk-model, disk-manufacturer, serial-number
+ * - firmware-revision, capacity-in-bytes
+ */
+static int
+disk_set_props(topo_mod_t *mod, tnode_t *parent,
+ tnode_t *dtn, disk_di_node_t *dnode)
+{
+ nvlist_t *asru = NULL;
+ char *label = NULL;
+ nvlist_t *fmri = NULL;
+ int err;
+
+ /* form and set the asru */
+ if ((asru = topo_mod_devfmri(mod, FM_DEV_SCHEME_VERSION,
+ dnode->ddn_dpath, dnode->ddn_devid)) == NULL) {
+ err = ETOPO_FMRI_UNKNOWN;
+ topo_mod_dprintf(mod, "disk_set_props: "
+ "asru error %s\n", topo_strerror(err));
+ goto error;
+ }
+ if (topo_node_asru_set(dtn, asru, 0, &err) != 0) {
+ topo_mod_dprintf(mod, "disk_set_props: "
+ "asru_set error %s\n", topo_strerror(err));
+ goto error;
+ }
+
+ /* pull the label property down from our parent 'bay' node */
+ if (topo_node_label(parent, &label, &err) != 0) {
+ topo_mod_dprintf(mod, "disk_set_props: "
+ "label error %s\n", topo_strerror(err));
+ goto error;
+ }
+ if (topo_node_label_set(dtn, label, &err) != 0) {
+ topo_mod_dprintf(mod, "disk_set_props: "
+ "label_set error %s\n", topo_strerror(err));
+ goto error;
+ }
+
+ /* get the resource fmri, and use it as the fru */
+ if (topo_node_resource(dtn, &fmri, &err) != 0) {
+ topo_mod_dprintf(mod, "disk_set_props: "
+ "resource error: %s\n", topo_strerror(err));
+ goto error;
+ }
+ if (topo_node_fru_set(dtn, fmri, 0, &err) != 0) {
+ topo_mod_dprintf(mod, "disk_set_props: "
+ "fru_set error: %s\n", topo_strerror(err));
+ goto error;
+ }
+
+ /* create/set the authority group */
+ if ((topo_pgroup_create(dtn, &disk_auth_pgroup, &err) != 0) &&
+ (err != ETOPO_PROP_DEFD)) {
+ topo_mod_dprintf(mod, "disk_set_props: "
+ "create disk_auth error %s\n", topo_strerror(err));
+ goto error;
+ }
+
+ /* create/set the devfs-path and devid in the io group */
+ if (topo_pgroup_create(dtn, &io_pgroup, &err) != 0) {
+ topo_mod_dprintf(mod, "disk_set_props: "
+ "create io error %s\n", topo_strerror(err));
+ goto error;
+ }
+
+ if (topo_prop_set_string(dtn, TOPO_PGROUP_IO, TOPO_IO_DEV_PATH,
+ TOPO_PROP_IMMUTABLE, dnode->ddn_dpath, &err) != 0) {
+ topo_mod_dprintf(mod, "disk_set_props: "
+ "set dev error %s\n", topo_strerror(err));
+ goto error;
+ }
+
+ if (topo_prop_set_string(dtn, TOPO_PGROUP_IO, TOPO_IO_DEVID,
+ TOPO_PROP_IMMUTABLE, dnode->ddn_devid, &err) != 0) {
+ topo_mod_dprintf(mod, "disk_set_props: "
+ "set devid error %s\n", topo_strerror(err));
+ goto error;
+ }
+
+ if (dnode->ddn_ppath_count != 0 &&
+ topo_prop_set_string_array(dtn, TOPO_PGROUP_IO, TOPO_IO_PHYS_PATH,
+ TOPO_PROP_IMMUTABLE, (const char **)dnode->ddn_ppath,
+ dnode->ddn_ppath_count, &err) != 0) {
+ topo_mod_dprintf(mod, "disk_set_props: "
+ "set phys-path error %s\n", topo_strerror(err));
+ goto error;
+ }
+
+ /* create the storage group */
+ if (topo_pgroup_create(dtn, &storage_pgroup, &err) != 0) {
+ topo_mod_dprintf(mod, "disk_set_props: "
+ "create storage error %s\n", topo_strerror(err));
+ goto error;
+ }
+
+ /* set the storage group public /dev name */
+ if (topo_prop_set_string(dtn, TOPO_PGROUP_STORAGE,
+ TOPO_STORAGE_LOGICAL_DISK_NAME, TOPO_PROP_IMMUTABLE,
+ dnode->ddn_lpath, &err) != 0) {
+ topo_mod_dprintf(mod, "disk_set_props: "
+ "set disk_name error %s\n", topo_strerror(err));
+ goto error;
+ }
+
+ /* populate other misc storage group properties */
+ if (dnode->ddn_mfg && (topo_prop_set_string(dtn, TOPO_PGROUP_STORAGE,
+ TOPO_STORAGE_MANUFACTURER, TOPO_PROP_IMMUTABLE,
+ dnode->ddn_mfg, &err) != 0)) {
+ topo_mod_dprintf(mod, "disk_set_props: "
+ "set mfg error %s\n", topo_strerror(err));
+ goto error;
+ }
+ if (dnode->ddn_model && (topo_prop_set_string(dtn, TOPO_PGROUP_STORAGE,
+ TOPO_STORAGE_MODEL, TOPO_PROP_IMMUTABLE,
+ dnode->ddn_model, &err) != 0)) {
+ topo_mod_dprintf(mod, "disk_set_props: "
+ "set model error %s\n", topo_strerror(err));
+ goto error;
+ }
+ if (dnode->ddn_serial && (topo_prop_set_string(dtn, TOPO_PGROUP_STORAGE,
+ TOPO_STORAGE_SERIAL_NUM, TOPO_PROP_IMMUTABLE,
+ dnode->ddn_serial, &err) != 0)) {
+ topo_mod_dprintf(mod, "disk_set_props: "
+ "set serial error %s\n", topo_strerror(err));
+ goto error;
+ }
+ if (dnode->ddn_firm && (topo_prop_set_string(dtn, TOPO_PGROUP_STORAGE,
+ TOPO_STORAGE_FIRMWARE_REV, TOPO_PROP_IMMUTABLE,
+ dnode->ddn_firm, &err) != 0)) {
+ topo_mod_dprintf(mod, "disk_set_props: "
+ "set firm error %s\n", topo_strerror(err));
+ goto error;
+ }
+ if (dnode->ddn_cap && (topo_prop_set_string(dtn, TOPO_PGROUP_STORAGE,
+ TOPO_STORAGE_CAPACITY, TOPO_PROP_IMMUTABLE,
+ dnode->ddn_cap, &err) != 0)) {
+ topo_mod_dprintf(mod, "disk_set_props: "
+ "set cap error %s\n", topo_strerror(err));
+ goto error;
+ }
+ err = 0;
+
+out: if (fmri)
+ nvlist_free(fmri);
+ if (label)
+ topo_mod_strfree(mod, label);
+ if (asru)
+ nvlist_free(asru);
+ return (err);
+
+error: err = topo_mod_seterrno(mod, err);
+ goto out;
+}
+
+/* create the disk topo node */
+static tnode_t *
+disk_tnode_create(topo_mod_t *mod, tnode_t *parent,
+ disk_di_node_t *dnode, const char *name, topo_instance_t i)
+{
+ int len;
+ nvlist_t *fmri;
+ tnode_t *dtn;
+ char *part = NULL;
+ char *b = NULL;
+ nvlist_t *auth;
+
+ /* form 'part=' of fmri as "<mfg>-<model>" */
+ if (dnode->ddn_mfg && dnode->ddn_model) {
+ /* XXX replace first ' ' in the model with a '-' */
+ if ((b = strchr(dnode->ddn_model, ' ')) != NULL)
+ *b = '-';
+ len = strlen(dnode->ddn_mfg) + 1 + strlen(dnode->ddn_model) + 1;
+ if ((part = topo_mod_alloc(mod, len)) != NULL)
+ (void) snprintf(part, len, "%s-%s",
+ dnode->ddn_mfg, dnode->ddn_model);
+ }
+
+ auth = topo_mod_auth(mod, parent);
+ fmri = topo_mod_hcfmri(mod, parent, FM_HC_SCHEME_VERSION, name, i, NULL,
+ auth, part ? part : dnode->ddn_model, dnode->ddn_firm,
+ dnode->ddn_serial);
+ nvlist_free(auth);
+
+ if (part && (part != dnode->ddn_model))
+ topo_mod_free(mod, part, len);
+ else if (b)
+ *b = ' '; /* restore blank */
+
+ if (fmri == NULL) {
+ topo_mod_dprintf(mod, "disk_tnode_create: "
+ "hcfmri (%s%d/%s%d) error %s\n",
+ topo_node_name(parent), topo_node_instance(parent),
+ name, i, topo_strerror(topo_mod_errno(mod)));
+ return (NULL);
+ }
+
+ if ((dtn = topo_node_bind(mod, parent, name, i, fmri)) == NULL) {
+ topo_mod_dprintf(mod, "disk_tnode_create: "
+ "bind (%s%d/%s%d) error %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);
+
+ /* add the properties of the disk */
+ if (disk_set_props(mod, parent, dtn, dnode) != 0) {
+ topo_mod_dprintf(mod, "disk_tnode_create: "
+ "disk_set_props (%s%d/%s%d) error %s\n",
+ topo_node_name(parent), topo_node_instance(parent),
+ name, i, topo_strerror(topo_mod_errno(mod)));
+ topo_node_unbind(dtn);
+ return (NULL);
+ }
+ return (dtn);
+}
+
+static int
+disk_declare(topo_mod_t *mod, tnode_t *parent, disk_di_node_t *dnode)
+{
+ tnode_t *dtn;
+
+ /* create the disk topo node: one disk per 'bay' */
+ dtn = disk_tnode_create(mod, parent, dnode, DISK, 0);
+ if (dtn == NULL) {
+ topo_mod_dprintf(mod, "disk_declare: "
+ "disk_tnode_create error %s\n",
+ topo_strerror(topo_mod_errno(mod)));
+ return (-1);
+ }
+
+ /* register disk_methods against the disk topo node */
+ if (topo_method_register(mod, dtn, disk_methods) != 0) {
+ topo_mod_dprintf(mod, "disk_declare: "
+ "topo_method_register error %s\n",
+ topo_strerror(topo_mod_errno(mod)));
+ topo_node_unbind(dtn);
+ return (-1);
+ }
+ return (0);
+}
+
+int
+disk_declare_path(topo_mod_t *mod, tnode_t *parent, topo_list_t *listp,
+ const char *path)
+{
+ disk_di_node_t *dnode;
+ int i;
+
+ /*
+ * Check for match using physical phci (ddn_ppath). Use
+ * di_devfs_path_match so generic.vs.non-generic names match.
+ */
+ for (dnode = topo_list_next(listp); dnode != NULL;
+ dnode = topo_list_next(dnode)) {
+ if (dnode->ddn_ppath == NULL)
+ continue;
+
+ for (i = 0; i < dnode->ddn_ppath_count; i++) {
+ if (di_devfs_path_match(dnode->ddn_ppath[0], path))
+ return (disk_declare(mod, parent, dnode));
+ }
+ }
+
+ topo_mod_dprintf(mod, "disk_declare_path: "
+ "failed to find disk matching path %s", path);
+ return (0);
+}
+
+int
+disk_declare_addr(topo_mod_t *mod, tnode_t *parent, topo_list_t *listp,
+ const char *addr)
+{
+ disk_di_node_t *dnode;
+ int i;
+
+ /* Check for match using addr. */
+ for (dnode = topo_list_next(listp); dnode != NULL;
+ dnode = topo_list_next(dnode)) {
+ if (dnode->ddn_target_port == NULL)
+ continue;
+
+ for (i = 0; i < dnode->ddn_target_port_count; i++) {
+ if (strncmp(dnode->ddn_target_port[i], addr,
+ strcspn(dnode->ddn_target_port[i], ":")) == 0)
+ return (disk_declare(mod, parent, dnode));
+ }
+ }
+
+ topo_mod_dprintf(mod, "disk_declare_addr: "
+ "failed to find disk matching addr %s", addr);
+ return (0);
+}
+
+/* di_devlink callback for disk_di_node_add */
+static int
+disk_devlink_callback(di_devlink_t dl, void *arg)
+{
+ disk_cbdata_t *cbp = (disk_cbdata_t *)arg;
+ topo_mod_t *mod = cbp->dcb_mod;
+ disk_di_node_t *dnode = cbp->dcb_dnode;
+ const char *devpath;
+ char *ctds, *slice;
+
+ devpath = di_devlink_path(dl);
+ if ((dnode == NULL) || (devpath == NULL))
+ return (DI_WALK_TERMINATE);
+
+ /* trim the slice off the public name */
+ if (((ctds = strrchr(devpath, '/')) != NULL) &&
+ ((slice = strchr(ctds, 's')) != NULL))
+ *slice = '\0';
+
+ /* Establish the public /dev name (no slice) */
+ dnode->ddn_lpath = topo_mod_strdup(mod, ctds ? ctds + 1 : devpath);
+
+ if (ctds && slice)
+ *slice = 's';
+ return (DI_WALK_TERMINATE);
+}
+
+static void
+disk_di_node_free(topo_mod_t *mod, disk_di_node_t *dnode)
+{
+ int i;
+
+ /* free the stuff we point to */
+ topo_mod_strfree(mod, dnode->ddn_devid);
+ for (i = 0; i < dnode->ddn_ppath_count; i++)
+ topo_mod_strfree(mod, dnode->ddn_ppath[i]);
+ topo_mod_free(mod, dnode->ddn_ppath,
+ dnode->ddn_ppath_count * sizeof (uintptr_t));
+ topo_mod_strfree(mod, dnode->ddn_dpath);
+ topo_mod_strfree(mod, dnode->ddn_lpath);
+
+ topo_mod_strfree(mod, dnode->ddn_mfg);
+ topo_mod_strfree(mod, dnode->ddn_model);
+ topo_mod_strfree(mod, dnode->ddn_serial);
+ topo_mod_strfree(mod, dnode->ddn_firm);
+ topo_mod_strfree(mod, dnode->ddn_cap);
+
+ for (i = 0; i < dnode->ddn_target_port_count; i++)
+ topo_mod_strfree(mod, dnode->ddn_target_port[i]);
+ topo_mod_free(mod, dnode->ddn_target_port,
+ dnode->ddn_target_port_count * sizeof (uintptr_t));
+
+ /* free self */
+ topo_mod_free(mod, dnode, sizeof (disk_di_node_t));
+}
+
+static int
+disk_di_node_add(di_node_t node, char *devid, disk_cbdata_t *cbp)
+{
+ topo_mod_t *mod = cbp->dcb_mod;
+ disk_di_node_t *dnode;
+ di_path_t pnode;
+ char *path;
+ int mlen;
+ char *minorpath;
+ char *extn = ":a";
+ char *s;
+ int64_t *nblocksp;
+ uint64_t nblocks;
+ int *dblksizep;
+ uint_t dblksize;
+ char lentry[MAXPATHLEN];
+ int pathcount, portcount;
+ int ret, i;
+
+ /* check for list duplicate using devid search */
+ for (dnode = topo_list_next(cbp->dcb_list);
+ dnode != NULL; dnode = topo_list_next(dnode)) {
+ if (devid_str_compare(dnode->ddn_devid, devid) == 0) {
+ topo_mod_dprintf(mod, "disk_di_node_add: "
+ "already there %s\n", devid);
+ return (0);
+ }
+ }
+
+ if ((dnode = topo_mod_zalloc(mod, sizeof (disk_di_node_t))) == NULL)
+ return (-1);
+
+ /* Establish the devid. */
+ dnode->ddn_devid = topo_mod_strdup(mod, devid);
+ if (dnode->ddn_devid == NULL)
+ goto error;
+
+ /* Establish the devinfo dpath */
+ if ((path = di_devfs_path(node)) == NULL) {
+ topo_mod_seterrno(mod, errno);
+ goto error;
+ }
+
+ dnode->ddn_dpath = topo_mod_strdup(mod, path);
+ di_devfs_path_free(path);
+ if (dnode->ddn_dpath == NULL)
+ goto error;
+
+ /*
+ * Establish the physical ppath and target ports. If the device is
+ * non-mpxio then dpath and ppath are the same, and the target port is a
+ * property of the device node.
+ *
+ * If dpath is a client node under scsi_vhci, then iterate over all
+ * paths and get their physical paths and target port properrties.
+ * di_path_client_next_path call below will
+ * return non-NULL, and ppath is set to the physical path to the first
+ * pathinfo node.
+ *
+ * NOTE: It is possible to get a generic.vs.non-generic path
+ * for di_devfs_path.vs.di_path_devfs_path like:
+ * xml: /pci@7b,0/pci1022,7458@11/pci1000,3060@2/sd@2,0
+ * pnode: /pci@7b,0/pci1022,7458@11/pci1000,3060@2/disk@2,0
+ * To resolve this issue disk_declare_path() needs to use the
+ * special di_devfs_path_match() interface.
+ */
+ pathcount = portcount = 0;
+ pnode = NULL;
+ while ((pnode = di_path_client_next_path(node, pnode)) != NULL) {
+ if ((ret = di_path_prop_lookup_strings(pnode,
+ "target-port", &s)) > 0)
+ portcount += ret;
+ pathcount++;
+ }
+
+ if (pathcount == 0) {
+ if ((dnode->ddn_ppath =
+ topo_mod_zalloc(mod, sizeof (uintptr_t))) == NULL)
+ goto error;
+
+ dnode->ddn_ppath_count = 1;
+ if ((dnode->ddn_ppath[0] = topo_mod_strdup(mod,
+ dnode->ddn_dpath)) == NULL)
+ goto error;
+
+ if ((ret = di_prop_lookup_strings(DDI_DEV_T_ANY, node,
+ "target-port", &s)) > 0) {
+ if ((dnode->ddn_target_port = topo_mod_zalloc(mod,
+ ret * sizeof (uintptr_t))) == NULL)
+ goto error;
+
+ dnode->ddn_target_port_count = ret;
+
+ for (i = 0; i < ret; i++) {
+ if ((dnode->ddn_target_port[i] =
+ topo_mod_strdup(mod, s)) == NULL)
+ goto error;
+
+ s += strlen(s) + 1;
+ }
+ }
+ } else {
+ if ((dnode->ddn_ppath = topo_mod_zalloc(mod,
+ pathcount * sizeof (uintptr_t))) == NULL)
+ goto error;
+
+ dnode->ddn_ppath_count = pathcount;
+
+ if (portcount != 0 &&
+ ((dnode->ddn_target_port = topo_mod_zalloc(mod,
+ portcount * sizeof (uintptr_t)))) == NULL)
+ goto error;
+
+ dnode->ddn_target_port_count = portcount;
+
+ pnode = NULL;
+ pathcount = portcount = 0;
+ while ((pnode = di_path_client_next_path(node,
+ pnode)) != NULL) {
+ if ((path = di_path_devfs_path(pnode)) == NULL) {
+ topo_mod_seterrno(mod, errno);
+ goto error;
+ }
+
+ dnode->ddn_ppath[pathcount] =
+ topo_mod_strdup(mod, path);
+ di_devfs_path_free(path);
+ if (dnode->ddn_ppath[pathcount] == NULL)
+ goto error;
+
+ if ((ret = di_path_prop_lookup_strings(pnode,
+ "target-port", &s)) > 0) {
+ for (i = 0; i < ret; i++) {
+ if ((dnode->ddn_target_port[portcount] =
+ topo_mod_strdup(mod, s)) == NULL)
+ goto error;
+
+ portcount++;
+ s += strlen(s) + 1;
+ }
+ }
+
+ pathcount++;
+ }
+ }
+
+ /*
+ * Find the public /dev name by adding a minor name and using
+ * di_devlink interface for reverse translation (use devinfo path).
+ */
+ mlen = strlen(dnode->ddn_dpath) + strlen(extn) + 1;
+ if ((minorpath = topo_mod_alloc(mod, mlen)) == NULL)
+ goto error;
+ (void) snprintf(minorpath, mlen, "%s%s", dnode->ddn_dpath, extn);
+ cbp->dcb_dnode = dnode;
+ (void) di_devlink_walk(cbp->dcb_devhdl, "^dsk/", minorpath,
+ DI_PRIMARY_LINK, cbp, disk_devlink_callback);
+ topo_mod_free(mod, minorpath, mlen);
+ if (dnode->ddn_lpath == NULL) {
+ topo_mod_dprintf(mod, "disk_di_node_add: "
+ "failed to determine logical path");
+ goto error;
+ }
+
+ /* cache various bits of optional information about the disk */
+ if (di_prop_lookup_strings(DDI_DEV_T_ANY, node,
+ INQUIRY_VENDOR_ID, &s) > 0) {
+ if ((dnode->ddn_mfg = topo_mod_strdup(mod, s)) == NULL)
+ goto error;
+ }
+ if (di_prop_lookup_strings(DDI_DEV_T_ANY, node,
+ INQUIRY_PRODUCT_ID, &s) > 0) {
+ if ((dnode->ddn_model = topo_mod_strdup(mod, s)) == NULL)
+ goto error;
+ }
+ if (di_prop_lookup_strings(DDI_DEV_T_ANY, node,
+ INQUIRY_REVISION_ID, &s) > 0) {
+ if ((dnode->ddn_firm = topo_mod_strdup(mod, s)) == NULL)
+ goto error;
+ }
+ if (di_prop_lookup_strings(DDI_DEV_T_ANY, node,
+ INQUIRY_SERIAL_NO, &s) > 0) {
+ if ((dnode->ddn_serial = topo_mod_strdup(mod, s)) == NULL)
+ goto error;
+ }
+ if (di_prop_lookup_int64(DDI_DEV_T_ANY, node,
+ "device-nblocks", &nblocksp) > 0) {
+ nblocks = (uint64_t)*nblocksp;
+ /*
+ * To save kernel memory, the driver may not define
+ * "device-dblksize" when its value is default DEV_BSIZE.
+ */
+ if (di_prop_lookup_ints(DDI_DEV_T_ANY, node,
+ "device-dblksize", &dblksizep) > 0)
+ dblksize = (uint_t)*dblksizep;
+ else
+ dblksize = DEV_BSIZE; /* default value */
+ (void) snprintf(lentry, sizeof (lentry),
+ "%" PRIu64, nblocks * dblksize);
+ if ((dnode->ddn_cap = topo_mod_strdup(mod, lentry)) == NULL)
+ goto error;
+ }
+
+ topo_mod_dprintf(mod, "disk_di_node_add: "
+ "adding %s\n", dnode->ddn_devid);
+ topo_mod_dprintf(mod, " "
+ " %s\n", dnode->ddn_dpath);
+ for (i = 0; i < dnode->ddn_ppath_count; i++) {
+ topo_mod_dprintf(mod, " "
+ " %s\n", dnode->ddn_ppath[i]);
+ }
+ topo_list_append(cbp->dcb_list, dnode);
+ return (0);
+
+error:
+ disk_di_node_free(mod, dnode);
+ return (-1);
+}
+
+/* di_walk_node callback for disk_list_gather */
+static int
+disk_walk_di_nodes(di_node_t node, void *arg)
+{
+ ddi_devid_t devid = NULL;
+ char *devidstr;
+
+ /* only interested in nodes that have devids */
+ devid = (ddi_devid_t)di_devid(node);
+ if (devid == NULL)
+ return (DI_WALK_CONTINUE);
+
+ /* ... with a string representation of the devid */
+ devidstr = devid_str_encode(devid, NULL);
+ if (devidstr == NULL)
+ return (DI_WALK_CONTINUE);
+
+ /* create/find the devid scsi topology node */
+ (void) disk_di_node_add(node, devidstr, arg);
+ devid_str_free(devidstr);
+ return (DI_WALK_CONTINUE);
+}
+
+int
+disk_list_gather(topo_mod_t *mod, topo_list_t *listp)
+{
+ di_node_t devtree;
+ di_devlink_handle_t devhdl;
+ disk_cbdata_t dcb;
+
+ if ((devtree = di_init("/", DINFOCACHE)) == DI_NODE_NIL) {
+ topo_mod_dprintf(mod, "disk_list_gather: "
+ "di_init failed");
+ return (-1);
+ }
+
+ if ((devhdl = di_devlink_init(NULL, 0)) == DI_NODE_NIL) {
+ topo_mod_dprintf(mod, "disk_list_gather: "
+ "di_devlink_init failed");
+ di_fini(devtree);
+ return (-1);
+ }
+
+ dcb.dcb_mod = mod;
+ dcb.dcb_list = listp;
+ dcb.dcb_devhdl = devhdl;
+
+ /* walk the devinfo snapshot looking for nodes with devids */
+ (void) di_walk_node(devtree, DI_WALK_CLDFIRST, &dcb,
+ disk_walk_di_nodes);
+
+ (void) di_devlink_fini(&devhdl);
+ di_fini(devtree);
+
+ return (0);
+}
+
+void
+disk_list_free(topo_mod_t *mod, topo_list_t *listp)
+{
+ disk_di_node_t *dnode;
+
+ while ((dnode = topo_list_next(listp)) != NULL) {
+ /* order of delete/free is important */
+ topo_list_delete(listp, dnode);
+ disk_di_node_free(mod, dnode);
+ }
+}
+
+/*
+ * Query the current disk status. If successful, the disk status is returned
+ * as an nvlist consisting of at least the following members:
+ *
+ * protocol string Supported protocol (currently "scsi")
+ *
+ * status nvlist Arbitrary protocol-specific information
+ * about the current state of the disk.
+ *
+ * faults nvlist A list of supported faults. Each
+ * element of this list is a boolean value.
+ * An element's existence indicates that
+ * the drive supports detecting this fault,
+ * and the value indicates the current
+ * state of the fault.
+ *
+ * <fault-name> nvlist For each fault named in 'faults', a
+ * nvlist describing protocol-specific
+ * attributes of the fault.
+ *
+ * This method relies on the libdiskstatus library to query this information.
+ */
+static int
+disk_status(topo_mod_t *mod, tnode_t *nodep, topo_version_t vers,
+ nvlist_t *in_nvl, nvlist_t **out_nvl)
+{
+ disk_status_t *dsp;
+ char *devpath, *fullpath;
+ size_t pathlen;
+ nvlist_t *status;
+ int err;
+
+ *out_nvl = NULL;
+
+ if (vers != TOPO_METH_DISK_STATUS_VERSION)
+ return (topo_mod_seterrno(mod, EMOD_VER_NEW));
+
+ /*
+ * If the caller specifies the "path" parameter, then this indicates
+ * that we should use this instead of deriving it from the topo node
+ * itself.
+ */
+ if (nvlist_lookup_string(in_nvl, "path", &fullpath) == 0) {
+ devpath = NULL;
+ } else {
+ /*
+ * Get the /devices path and attempt to open the disk status
+ * handle.
+ */
+ if (topo_prop_get_string(nodep, TOPO_PGROUP_IO,
+ TOPO_IO_DEV_PATH, &devpath, &err) != 0)
+ return (topo_mod_seterrno(mod, EMOD_METHOD_NOTSUP));
+
+ /*
+ * Note that sizeof(string) includes the terminating NULL byte
+ */
+ pathlen = strlen(devpath) + sizeof ("/devices") +
+ sizeof (PHYS_EXTN) - 1;
+
+ if ((fullpath = topo_mod_alloc(mod, pathlen)) == NULL)
+ return (topo_mod_seterrno(mod, EMOD_NOMEM));
+
+ (void) snprintf(fullpath, pathlen, "/devices%s%s", devpath,
+ PHYS_EXTN);
+
+ topo_mod_strfree(mod, devpath);
+ }
+
+ if ((dsp = disk_status_open(fullpath, &err)) == NULL) {
+ if (devpath)
+ topo_mod_free(mod, fullpath, pathlen);
+ return (topo_mod_seterrno(mod, err == EDS_NOMEM ?
+ EMOD_NOMEM : EMOD_METHOD_NOTSUP));
+ }
+
+ if (devpath)
+ topo_mod_free(mod, fullpath, pathlen);
+
+ if ((status = disk_status_get(dsp)) == NULL) {
+ err = (disk_status_errno(dsp) == EDS_NOMEM ?
+ EMOD_NOMEM : EMOD_METHOD_NOTSUP);
+ disk_status_close(dsp);
+ return (topo_mod_seterrno(mod, err));
+ }
+
+ *out_nvl = status;
+ disk_status_close(dsp);
+ return (0);
+}
diff --git a/usr/src/lib/libdevinfo/devinfo.c b/usr/src/lib/libdevinfo/devinfo.c
index 8c103d2f7a..582aad2156 100644
--- a/usr/src/lib/libdevinfo/devinfo.c
+++ b/usr/src/lib/libdevinfo/devinfo.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -855,12 +855,12 @@ int
di_walk_minor(di_node_t root, const char *minor_type, uint_t flag, void *arg,
int (*minor_callback)(di_node_t, di_minor_t, void *))
{
- struct node_list *head; /* node_list for tree walk */
+ struct node_list *head; /* node_list for tree walk */
#ifdef DEBUG
- char *path = di_devfs_path(root);
- DPRINTF((DI_INFO, "walking minor nodes under %s\n", path));
- di_devfs_path_free(path);
+ char *devfspath = di_devfs_path(root);
+ DPRINTF((DI_INFO, "walking minor nodes under %s\n", devfspath));
+ di_devfs_path_free(devfspath);
#endif
if (root == NULL) {
@@ -877,7 +877,7 @@ di_walk_minor(di_node_t root, const char *minor_type, uint_t flag, void *arg,
head->node = root;
DPRINTF((DI_INFO, "Start minor walking from node %s\n",
- di_node_name(root)));
+ di_node_name(root)));
while (head != NULL)
walk_one_minor_list(&head, minor_type, flag, arg,
@@ -931,7 +931,7 @@ di_compatible_names(di_node_t node, char **names)
}
*names = (caddr_t)node +
- DI_NODE(node)->compat_names - DI_NODE(node)->self;
+ DI_NODE(node)->compat_names - DI_NODE(node)->self;
c = *names;
len = DI_NODE(node)->compat_length;
@@ -1130,7 +1130,7 @@ char *
di_devfs_minor_path(di_minor_t minor)
{
di_node_t node;
- char *full_path, *name, *path;
+ char *full_path, *name, *devfspath;
int full_path_len;
if (minor == DI_MINOR_NIL) {
@@ -1140,20 +1140,72 @@ di_devfs_minor_path(di_minor_t minor)
name = di_minor_name(minor);
node = di_minor_devinfo(minor);
- path = di_devfs_path(node);
- if (path == NULL)
+ devfspath = di_devfs_path(node);
+ if (devfspath == NULL)
return (NULL);
/* make the full path to the device minor node */
- full_path_len = strlen(path) + strlen(name) + 2;
+ full_path_len = strlen(devfspath) + strlen(name) + 2;
full_path = (char *)calloc(1, full_path_len);
if (full_path != NULL)
- (void) snprintf(full_path, full_path_len, "%s:%s", path, name);
+ (void) snprintf(full_path, full_path_len, "%s:%s",
+ devfspath, name);
+
+ di_devfs_path_free(devfspath);
+ return (full_path);
+}
+
+/*
+ * Produce a string representation of path to di_path_t (pathinfo node). This
+ * string is identical to di_devfs_path had the device been enumerated under
+ * the pHCI: it has a base path to pHCI, then uses node_name of client, and
+ * device unit-address of pathinfo node.
+ */
+char *
+di_path_devfs_path(di_path_t path)
+{
+ di_node_t phci_node;
+ char *phci_path, *path_name, *path_addr;
+ char *full_path;
+ int full_path_len;
+
+ if (path == DI_PATH_NIL) {
+ errno = EINVAL;
+ return (NULL);
+ }
- di_devfs_path_free(path);
+ /* get name@addr for path */
+ path_name = di_path_node_name(path);
+ path_addr = di_path_bus_addr(path);
+ if ((path_name == NULL) || (path_addr == NULL))
+ return (NULL);
+
+ /* base path to pHCI devinfo node */
+ phci_node = di_path_phci_node(path);
+ if (phci_node == NULL)
+ return (NULL);
+ phci_path = di_devfs_path(phci_node);
+ if (phci_path == NULL)
+ return (NULL);
+
+ /* make the full string representation of path */
+ full_path_len = strlen(phci_path) + 1 + strlen(path_name) +
+ 1 + strlen(path_addr) + 1;
+ full_path = (char *)calloc(1, full_path_len);
+
+ if (full_path != NULL)
+ (void) snprintf(full_path, full_path_len, "%s/%s@%s",
+ phci_path, path_name, path_addr);
+ di_devfs_path_free(phci_path);
return (full_path);
}
+char *
+di_path_client_devfs_path(di_path_t path)
+{
+ return (di_devfs_path(di_path_client_node(path)));
+}
+
void
di_devfs_path_free(char *buf)
{
@@ -1165,6 +1217,128 @@ di_devfs_path_free(char *buf)
free(buf);
}
+/*
+ * Return 1 if name is a IEEE-1275 generic name. If new generic
+ * names are defined, they should be added to this table
+ */
+static int
+is_generic(const char *name, int len)
+{
+ const char **gp;
+
+ /* from IEEE-1275 recommended practices section 3 */
+ static const char *generic_names[] = {
+ "atm",
+ "disk",
+ "display",
+ "dma-controller",
+ "ethernet",
+ "fcs",
+ "fdc",
+ "fddi",
+ "fibre-channel",
+ "ide",
+ "interrupt-controller",
+ "isa",
+ "keyboard",
+ "memory",
+ "mouse",
+ "nvram",
+ "pc-card",
+ "pci",
+ "printer",
+ "rtc",
+ "sbus",
+ "scanner",
+ "scsi",
+ "serial",
+ "sound",
+ "ssa",
+ "tape",
+ "timer",
+ "token-ring",
+ "vme",
+ 0
+ };
+
+ for (gp = generic_names; *gp; gp++) {
+ if ((strncmp(*gp, name, len) == 0) &&
+ (strlen(*gp) == len))
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * Determine if two paths below /devices refer to the same device, ignoring
+ * any generic .vs. non-generic 'name' issues in "[[/]name[@addr[:minor]]]*".
+ * Return 1 if the paths match.
+ */
+int
+di_devfs_path_match(const char *dp1, const char *dp2)
+{
+ const char *p1, *p2;
+ const char *ec1, *ec2;
+ const char *at1, *at2;
+ char nc;
+ int g1, g2;
+
+ /* progress through both strings */
+ for (p1 = dp1, p2 = dp2; (*p1 == *p2) && *p1; p1++, p2++) {
+ /* require match until the start of a component */
+ if (*p1 != '/')
+ continue;
+
+ /* advance p1 and p2 to start of 'name' in component */
+ nc = *(p1 + 1);
+ if ((nc == '\0') || (nc == '/'))
+ continue; /* skip trash */
+ p1++;
+ p2++;
+
+ /*
+ * Both p1 and p2 point to beginning of 'name' in component.
+ * Determine where current component ends: next '/' or '\0'.
+ */
+ ec1 = strchr(p1, '/');
+ if (ec1 == NULL)
+ ec1 = p1 + strlen(p1);
+ ec2 = strchr(p2, '/');
+ if (ec2 == NULL)
+ ec2 = p2 + strlen(p2);
+
+ /* Determine where name ends based on whether '@' exists */
+ at1 = strchr(p1, '@');
+ at2 = strchr(p2, '@');
+ if (at1 && (at1 < ec1))
+ ec1 = at1;
+ if (at2 && (at2 < ec2))
+ ec2 = at2;
+
+ /*
+ * At this point p[12] point to beginning of name and
+ * ec[12] point to character past the end of name. Determine
+ * if the names are generic.
+ */
+ g1 = is_generic(p1, ec1 - p1);
+ g2 = is_generic(p2, ec2 - p2);
+
+ if (g1 != g2) {
+ /*
+ * one generic and one non-generic
+ * skip past the names in the match.
+ */
+ p1 = ec1;
+ p2 = ec2;
+ } else {
+ if (*p1 != *p2)
+ break;
+ }
+ }
+
+ return ((*p1 == *p2) ? 1 : 0);
+}
+
/* minor data access */
di_minor_t
di_minor_next(di_node_t node, di_minor_t minor)
@@ -1245,7 +1419,7 @@ dev_t
di_minor_devt(di_minor_t minor)
{
return (makedev(DI_MINOR(minor)->dev_major,
- DI_MINOR(minor)->dev_minor));
+ DI_MINOR(minor)->dev_minor));
}
int
@@ -1261,7 +1435,7 @@ di_minor_nodetype(di_minor_t minor)
return (NULL);
return ((caddr_t)minor -
- DI_MINOR(minor)->self + DI_MINOR(minor)->node_type);
+ DI_MINOR(minor)->self + DI_MINOR(minor)->node_type);
}
/*
@@ -1712,7 +1886,7 @@ di_prop_rawdata(di_prop_t prop, uchar_t **prop_data)
* Consolidation private interfaces for accessing I/O multipathing data
*/
di_path_t
-di_path_next_client(di_node_t node, di_path_t path)
+di_path_phci_next_path(di_node_t node, di_path_t path)
{
caddr_t pa;
@@ -1733,7 +1907,8 @@ di_path_next_client(di_node_t node, di_path_t path)
* Path is NIL; the caller is asking for the first path info node
*/
if (DI_NODE(node)->multipath_phci != 0) {
- DPRINTF((DI_INFO, "phci: returning %p\n", ((caddr_t)node -
+ DPRINTF((DI_INFO, "phci_next_path: returning %p\n",
+ ((caddr_t)node -
DI_NODE(node)->self + DI_NODE(node)->multipath_phci)));
return (DI_PATH((caddr_t)node - DI_NODE(node)->self +
DI_NODE(node)->multipath_phci));
@@ -1753,7 +1928,7 @@ di_path_next_client(di_node_t node, di_path_t path)
}
di_path_t
-di_path_next_phci(di_node_t node, di_path_t path)
+di_path_client_next_path(di_node_t node, di_path_t path)
{
caddr_t pa;
@@ -1774,7 +1949,8 @@ di_path_next_phci(di_node_t node, di_path_t path)
* Path is NIL; the caller is asking for the first path info node
*/
if (DI_NODE(node)->multipath_client != 0) {
- DPRINTF((DI_INFO, "client: returning %p\n", ((caddr_t)node -
+ DPRINTF((DI_INFO, "client_next_path: returning %p\n",
+ ((caddr_t)node -
DI_NODE(node)->self + DI_NODE(node)->multipath_client)));
return (DI_PATH((caddr_t)node - DI_NODE(node)->self +
DI_NODE(node)->multipath_client));
@@ -1794,8 +1970,21 @@ di_path_next_phci(di_node_t node, di_path_t path)
}
/*
- * XXX Obsolete wrapper to be removed. Won't work under multilevel.
+ * XXX Remove the private di_path_(addr,next,next_phci,next_client) interfaces
+ * below after NWS consolidation switches to using di_path_bus_addr,
+ * di_path_phci_next_path, and di_path_client_next_path per CR6638521.
*/
+char *
+di_path_addr(di_path_t path, char *buf)
+{
+ caddr_t pa; /* starting address of map */
+
+ pa = (caddr_t)path - DI_PATH(path)->self;
+
+ (void) strncpy(buf, (char *)(pa + DI_PATH(path)->path_addr),
+ MAXPATHLEN);
+ return (buf);
+}
di_path_t
di_path_next(di_node_t node, di_path_t path)
{
@@ -1805,9 +1994,9 @@ di_path_next(di_node_t node, di_path_t path)
}
if (DI_NODE(node)->multipath_client) {
- return (di_path_next_phci(node, path));
+ return (di_path_client_next_path(node, path));
} else if (DI_NODE(node)->multipath_phci) {
- return (di_path_next_client(node, path));
+ return (di_path_phci_next_path(node, path));
} else {
/*
* The node had multipathing data but didn't appear to be a
@@ -1817,6 +2006,19 @@ di_path_next(di_node_t node, di_path_t path)
return (DI_PATH_NIL);
}
}
+di_path_t
+di_path_next_phci(di_node_t node, di_path_t path)
+{
+ return (di_path_client_next_path(node, path));
+}
+di_path_t
+di_path_next_client(di_node_t node, di_path_t path)
+{
+ return (di_path_phci_next_path(node, path));
+}
+
+
+
di_path_state_t
di_path_state(di_path_t path)
@@ -1825,15 +2027,31 @@ di_path_state(di_path_t path)
}
char *
-di_path_addr(di_path_t path, char *buf)
+di_path_node_name(di_path_t path)
{
- caddr_t pa; /* starting address of map */
+ di_node_t client_node;
- pa = (caddr_t)path - DI_PATH(path)->self;
+ /* pathinfo gets node_name from client */
+ if ((client_node = di_path_client_node(path)) == NULL)
+ return (NULL);
+ return (di_node_name(client_node));
+}
- (void) strncpy(buf, (char *)(pa + DI_PATH(path)->path_addr),
- MAXPATHLEN);
- return (buf);
+char *
+di_path_bus_addr(di_path_t path)
+{
+ caddr_t pa = (caddr_t)path - DI_PATH(path)->self;
+
+ if (DI_PATH(path)->path_addr == 0)
+ return (NULL);
+
+ return ((char *)(pa + DI_PATH(path)->path_addr));
+}
+
+int
+di_path_instance(di_path_t path)
+{
+ return (DI_PATH(path)->path_instance);
}
di_node_t
@@ -2472,7 +2690,7 @@ di_prom_prop_next(di_prom_handle_t ph, di_node_t node, di_prom_prop_t prom_prop)
struct di_prom_handle *p = (struct di_prom_handle *)ph;
DPRINTF((DI_TRACE1, "Search next prop for node 0x%p with ph 0x%p\n",
- node, p));
+ node, p));
/*
* paranoid check
@@ -2656,7 +2874,7 @@ di_prom_prop_lookup_ints(di_prom_handle_t ph, di_node_t node,
}
len = di_prop_decode_common((void *)&prop->data, prop->len,
- DI_PROP_TYPE_INT, 1);
+ DI_PROP_TYPE_INT, 1);
*prom_prop_data = (int *)((void *)prop->data);
return (len);
@@ -2905,6 +3123,18 @@ di_node_private_get(di_node_t node)
}
void
+di_path_private_set(di_path_t path, void *data)
+{
+ DI_PATH(path)->user_private_data = (uintptr_t)data;
+}
+
+void *
+di_path_private_get(di_path_t path)
+{
+ return ((void *)(uintptr_t)DI_PATH(path)->user_private_data);
+}
+
+void
di_lnode_private_set(di_lnode_t lnode, void *data)
{
DI_LNODE(lnode)->user_private_data = (uintptr_t)data;
@@ -3028,24 +3258,24 @@ di_link_next_by_lnode(di_lnode_t lnode, di_link_t link, uint_t endpoint)
if (DI_LNODE(lnode)->link_out == NULL)
return (DI_LINK_NIL);
return (DI_LINK((caddr_t)di_all +
- DI_LNODE(lnode)->link_out));
+ DI_LNODE(lnode)->link_out));
} else {
if (DI_LINK(link)->src_link_next == NULL)
return (DI_LINK_NIL);
return (DI_LINK((caddr_t)di_all +
- DI_LINK(link)->src_link_next));
+ DI_LINK(link)->src_link_next));
}
} else {
if (link == DI_LINK_NIL) {
if (DI_LNODE(lnode)->link_in == NULL)
return (DI_LINK_NIL);
return (DI_LINK((caddr_t)di_all +
- DI_LNODE(lnode)->link_in));
+ DI_LNODE(lnode)->link_in));
} else {
if (DI_LINK(link)->tgt_link_next == NULL)
return (DI_LINK_NIL);
return (DI_LINK((caddr_t)di_all +
- DI_LINK(link)->tgt_link_next));
+ DI_LINK(link)->tgt_link_next));
}
}
/* NOTREACHED */
@@ -3084,10 +3314,10 @@ di_walk_link(di_node_t root, uint_t flag, uint_t endpoint, void *arg,
struct node_list *head; /* node_list for tree walk */
#ifdef DEBUG
- char *path = di_devfs_path(root);
+ char *devfspath = di_devfs_path(root);
DPRINTF((DI_INFO, "walking %s link data under %s\n",
- (endpoint == DI_LINK_SRC) ? "src" : "tgt", path));
- di_devfs_path_free(path);
+ (endpoint == DI_LINK_SRC) ? "src" : "tgt", devfspath));
+ di_devfs_path_free(devfspath);
#endif
/*
@@ -3108,7 +3338,7 @@ di_walk_link(di_node_t root, uint_t flag, uint_t endpoint, void *arg,
head->node = root;
DPRINTF((DI_INFO, "Start link data walking from node %s\n",
- di_node_name(root)));
+ di_node_name(root)));
while (head != NULL)
walk_one_link(&head, endpoint, arg, link_callback);
@@ -3149,9 +3379,9 @@ di_walk_lnode(di_node_t root, uint_t flag, void *arg,
struct node_list *head; /* node_list for tree walk */
#ifdef DEBUG
- char *path = di_devfs_path(root);
- DPRINTF((DI_INFO, "walking lnode data under %s\n", path));
- di_devfs_path_free(path);
+ char *devfspath = di_devfs_path(root);
+ DPRINTF((DI_INFO, "walking lnode data under %s\n", devfspath));
+ di_devfs_path_free(devfspath);
#endif
/*
@@ -3171,7 +3401,7 @@ di_walk_lnode(di_node_t root, uint_t flag, void *arg,
head->node = root;
DPRINTF((DI_INFO, "Start lnode data walking from node %s\n",
- di_node_name(root)));
+ di_node_name(root)));
while (head != NULL)
walk_one_lnode(&head, arg, lnode_callback);
@@ -3180,18 +3410,17 @@ di_walk_lnode(di_node_t root, uint_t flag, void *arg,
}
di_node_t
-di_lookup_node(di_node_t root, char *path)
+di_lookup_node(di_node_t root, char *devfspath)
{
struct di_all *dap;
di_node_t node;
- char copy[MAXPATHLEN];
- char *slash, *pname, *paddr;
+ char *copy, *slash, *pname, *paddr;
/*
* Path must be absolute and musn't have duplicate slashes
*/
- if (*path != '/' || strstr(path, "//")) {
- DPRINTF((DI_ERR, "Invalid path: %s\n", path));
+ if (*devfspath != '/' || strstr(devfspath, "//")) {
+ DPRINTF((DI_ERR, "Invalid path: %s\n", devfspath));
return (DI_NODE_NIL);
}
@@ -3206,15 +3435,15 @@ di_lookup_node(di_node_t root, char *path)
return (DI_NODE_NIL);
}
- if (strlcpy(copy, path, sizeof (copy)) >= sizeof (copy)) {
- DPRINTF((DI_ERR, "path too long: %s\n", path));
+ if ((copy = strdup(devfspath)) == NULL) {
+ DPRINTF((DI_ERR, "strdup failed on: %s\n", devfspath));
return (DI_NODE_NIL);
}
for (slash = copy, node = root; slash; ) {
/*
- * Handle path = "/" case as well as trailing '/'
+ * Handle devfspath = "/" case as well as trailing '/'
*/
if (*(slash + 1) == '\0')
break;
@@ -3259,14 +3488,72 @@ di_lookup_node(di_node_t root, char *path)
*/
if (node == DI_NODE_NIL) {
DPRINTF((DI_ERR, "%s@%s: no node\n", pname, paddr));
+ free(copy);
return (DI_NODE_NIL);
}
}
assert(node != DI_NODE_NIL);
+ free(copy);
return (node);
}
+di_path_t
+di_lookup_path(di_node_t root, char *devfspath)
+{
+ di_node_t phci_node;
+ di_path_t path = DI_PATH_NIL;
+ char *copy, *lastslash;
+ char *pname, *paddr;
+ char *path_name, *path_addr;
+
+ if ((copy = strdup(devfspath)) == NULL) {
+ DPRINTF((DI_ERR, "strdup failed on: %s\n", devfspath));
+ return (DI_NODE_NIL);
+ }
+
+ if ((lastslash = strrchr(copy, '/')) == NULL) {
+ DPRINTF((DI_ERR, "failed to find component: %s\n", devfspath));
+ goto out;
+ }
+
+ /* stop at pHCI and find the node for the phci */
+ *lastslash = '\0';
+ phci_node = di_lookup_node(root, copy);
+ if (phci_node == NULL) {
+ DPRINTF((DI_ERR, "failed to find component: %s\n", devfspath));
+ goto out;
+ }
+
+ /* set up pname and paddr for last component */
+ pname = lastslash + 1;
+ if ((paddr = strchr(pname, '@')) == NULL) {
+ DPRINTF((DI_ERR, "failed to find unit-addr: %s\n", devfspath));
+ goto out;
+ }
+ *paddr++ = '\0';
+
+ /* walk paths below phci looking for match */
+ for (path = di_path_phci_next_path(phci_node, DI_PATH_NIL);
+ path != DI_PATH_NIL;
+ path = di_path_phci_next_path(phci_node, path)) {
+
+ /* get name@addr of path */
+ path_name = di_path_node_name(path);
+ path_addr = di_path_bus_addr(path);
+ if ((path_name == NULL) || (path_addr == NULL))
+ continue;
+
+ /* break on match */
+ if ((strcmp(pname, path_name) == 0) &&
+ (strcmp(paddr, path_addr) == 0))
+ break;
+ }
+
+out: free(copy);
+ return (path);
+}
+
static char *
msglevel2str(di_debug_t msglevel)
{
diff --git a/usr/src/lib/libdevinfo/libdevinfo.h b/usr/src/lib/libdevinfo/libdevinfo.h
index 2314ee1c9c..ca745b3b31 100644
--- a/usr/src/lib/libdevinfo/libdevinfo.h
+++ b/usr/src/lib/libdevinfo/libdevinfo.h
@@ -100,31 +100,32 @@ extern "C" {
((type) == DI_PROP_TYPE_INT64))
/* opaque handles */
-
-typedef struct di_node *di_node_t; /* opaque handle to node */
-typedef struct di_minor *di_minor_t; /* opaque handle to minor node */
-typedef struct di_prop *di_prop_t; /* opaque handle to property */
-typedef struct di_prom_prop *di_prom_prop_t; /* opaque handle to prom prop */
-typedef struct di_prom_handle *di_prom_handle_t; /* opaque handle */
-typedef struct di_path *di_path_t; /* opaque handle */
-typedef struct di_path_prop *di_path_prop_t; /* opaque handle */
-
+typedef struct di_node *di_node_t; /* node */
+typedef struct di_minor *di_minor_t; /* minor_node */
+typedef struct di_path *di_path_t; /* path_node */
+typedef struct di_link *di_link_t; /* link */
+typedef struct di_lnode *di_lnode_t; /* endpoint */
+typedef struct di_devlink *di_devlink_t; /* devlink */
+
+typedef struct di_prop *di_prop_t; /* node property */
+typedef struct di_path_prop *di_path_prop_t; /* path property */
+typedef struct di_prom_prop *di_prom_prop_t; /* prom property */
+
+typedef struct di_prom_handle *di_prom_handle_t; /* prom snapshot */
typedef struct di_devlink_handle *di_devlink_handle_t; /* devlink snapshot */
-typedef struct di_devlink *di_devlink_t; /* opaque handle to devlink */
-typedef struct di_link *di_link_t; /* opaque handle to link */
-typedef struct di_lnode *di_lnode_t; /* opaque handle to endpoint */
+
/*
* Null handles to make handles really opaque
*/
-#define DI_NODE_NIL NULL
-#define DI_LINK_NIL NULL
-#define DI_LNODE_NIL NULL
-#define DI_MINOR_NIL NULL
-#define DI_PROP_NIL NULL
+#define DI_NODE_NIL NULL
+#define DI_MINOR_NIL NULL
+#define DI_PATH_NIL NULL
+#define DI_LINK_NIL NULL
+#define DI_LNODE_NIL NULL
+#define DI_PROP_NIL NULL
#define DI_PROM_PROP_NIL NULL
#define DI_PROM_HANDLE_NIL NULL
-#define DI_PATH_NIL NULL
/*
* IEEE 1275 properties and other standardized property names
@@ -138,92 +139,76 @@ typedef struct di_lnode *di_lnode_t; /* opaque handle to endpoint */
#define DI_PROP_REG "reg"
#define DI_PROP_AP_NAMES "ap-names"
-
/* Interface Prototypes */
/*
* Snapshot initialization and cleanup
*/
-extern di_node_t di_init(const char *phys_path, uint_t flag);
-extern void di_fini(di_node_t root);
+extern di_node_t di_init(const char *phys_path, uint_t flag);
+extern void di_fini(di_node_t root);
/*
- * tree traversal
+ * node: traversal, data access, and parameters
*/
-extern di_node_t di_parent_node(di_node_t node);
-extern di_node_t di_sibling_node(di_node_t node);
-extern di_node_t di_child_node(di_node_t node);
-extern di_node_t di_drv_first_node(const char *drv_name, di_node_t root);
-extern di_node_t di_drv_next_node(di_node_t node);
-extern di_node_t di_vhci_first_node(di_node_t root);
-extern di_node_t di_vhci_next_node(di_node_t node);
-extern di_node_t di_phci_first_node(di_node_t vhci_node);
-extern di_node_t di_phci_next_node(di_node_t node);
+extern int di_walk_node(di_node_t root, uint_t flag, void *arg,
+ int (*node_callback)(di_node_t node, void *arg));
-/*
- * tree walking assistants
- */
-extern int di_walk_node(di_node_t root, uint_t flag, void *arg,
- int (*node_callback)(di_node_t node, void *arg));
-extern int di_walk_minor(di_node_t root, const char *minortype, uint_t flag,
- void *arg, int (*minor_callback)(di_node_t node, di_minor_t minor,
- void *arg));
-extern int di_walk_link(di_node_t root, uint_t flag, uint_t endpoint,
- void *arg, int (*link_callback)(di_link_t link, void *arg));
-extern int di_walk_lnode(di_node_t root, uint_t flag,
- void *arg, int (*lnode_callback)(di_lnode_t lnode, void *arg));
+extern di_node_t di_drv_first_node(const char *drv_name, di_node_t root);
+extern di_node_t di_drv_next_node(di_node_t node);
-extern void di_node_private_set(di_node_t node, void *data);
-extern void *di_node_private_get(di_node_t node);
-extern void di_minor_private_set(di_minor_t minor, void *data);
-extern void *di_minor_private_get(di_minor_t minor);
-extern void di_lnode_private_set(di_lnode_t lnode, void *data);
-extern void *di_lnode_private_get(di_lnode_t lnode);
-extern void di_link_private_set(di_link_t link, void *data);
-extern void *di_link_private_get(di_link_t link);
+extern di_node_t di_parent_node(di_node_t node);
+extern di_node_t di_sibling_node(di_node_t node);
+extern di_node_t di_child_node(di_node_t node);
-/*
- * generic node parameters
- */
-extern char *di_node_name(di_node_t node);
-extern char *di_bus_addr(di_node_t node);
-extern char *di_binding_name(di_node_t node);
-extern int di_compatible_names(di_node_t, char **names);
-extern int di_instance(di_node_t node);
-extern int di_nodeid(di_node_t node);
-extern int di_driver_major(di_node_t node);
-extern uint_t di_state(di_node_t node);
-extern ddi_node_state_t di_node_state(di_node_t node);
-extern ddi_devid_t di_devid(di_node_t node);
-
-extern char *di_driver_name(di_node_t node);
-extern uint_t di_driver_ops(di_node_t node);
+extern char *di_node_name(di_node_t node);
+extern char *di_bus_addr(di_node_t node);
+extern char *di_binding_name(di_node_t node);
+extern int di_compatible_names(di_node_t, char **names);
+extern int di_instance(di_node_t node);
+extern int di_nodeid(di_node_t node);
+extern int di_driver_major(di_node_t node);
+extern uint_t di_state(di_node_t node);
+extern ddi_node_state_t di_node_state(di_node_t node);
+extern ddi_devid_t di_devid(di_node_t node);
+extern char *di_driver_name(di_node_t node);
+extern uint_t di_driver_ops(di_node_t node);
-extern char *di_devfs_path(di_node_t node);
-extern char *di_devfs_minor_path(di_minor_t minor);
+extern void di_node_private_set(di_node_t node, void *data);
+extern void *di_node_private_get(di_node_t node);
-extern void di_devfs_path_free(char *path_buf);
+extern char *di_devfs_path(di_node_t node);
+extern char *di_devfs_minor_path(di_minor_t minor);
+extern void di_devfs_path_free(char *path_buf);
/*
- * layering data access
+ * path_node: traversal, data access, and parameters
*/
-extern di_link_t di_link_next_by_node(di_node_t node,
- di_link_t link, uint_t endpoint);
-extern di_link_t di_link_next_by_lnode(di_lnode_t lnode,
- di_link_t link, uint_t endpoint);
-extern di_lnode_t di_link_to_lnode(di_link_t link, uint_t endpoint);
+extern di_path_t di_path_phci_next_path(di_node_t node, di_path_t);
+extern di_path_t di_path_client_next_path(di_node_t node, di_path_t);
-extern di_lnode_t di_lnode_next(di_node_t node, di_lnode_t lnode);
-extern char *di_lnode_name(di_lnode_t lnode);
-extern di_node_t di_lnode_devinfo(di_lnode_t lnode);
-extern int di_lnode_devt(di_lnode_t lnode, dev_t *devt);
+extern di_node_t di_path_phci_node(di_path_t path);
+extern di_node_t di_path_client_node(di_path_t path);
-extern int di_link_spectype(di_link_t link);
+extern char *di_path_node_name(di_path_t path);
+extern char *di_path_bus_addr(di_path_t path);
+extern int di_path_instance(di_path_t path);
+extern di_path_state_t di_path_state(di_path_t path);
+
+extern char *di_path_devfs_path(di_path_t path);
+extern char *di_path_client_devfs_path(di_path_t path);
+
+extern void di_path_private_set(di_path_t path, void *data);
+extern void *di_path_private_get(di_path_t path);
/*
- * minor data access
+ * minor_node: traversal, data access, and parameters
*/
+extern int di_walk_minor(di_node_t root, const char *minortype,
+ uint_t flag, void *arg,
+ int (*minor_callback)(di_node_t node,
+ di_minor_t minor, void *arg));
extern di_minor_t di_minor_next(di_node_t node, di_minor_t minor);
+
extern di_node_t di_minor_devinfo(di_minor_t minor);
extern ddi_minor_type di_minor_type(di_minor_t minor);
extern char *di_minor_name(di_minor_t minor);
@@ -231,44 +216,109 @@ extern dev_t di_minor_devt(di_minor_t minor);
extern int di_minor_spectype(di_minor_t minor);
extern char *di_minor_nodetype(di_minor_t node);
+extern void di_minor_private_set(di_minor_t minor, void *data);
+extern void *di_minor_private_get(di_minor_t minor);
+
+/*
+ * node: property access
+ */
+extern di_prop_t di_prop_next(di_node_t node, di_prop_t prop);
+
+extern char *di_prop_name(di_prop_t prop);
+extern int di_prop_type(di_prop_t prop);
+extern dev_t di_prop_devt(di_prop_t prop);
+
+extern int di_prop_ints(di_prop_t prop, int **prop_data);
+extern int di_prop_int64(di_prop_t prop, int64_t **prop_data);
+extern int di_prop_strings(di_prop_t prop, char **prop_data);
+extern int di_prop_bytes(di_prop_t prop, uchar_t **prop_data);
+
+extern int di_prop_lookup_bytes(dev_t dev, di_node_t node,
+ const char *prop_name, uchar_t **prop_data);
+extern int di_prop_lookup_ints(dev_t dev, di_node_t node,
+ const char *prop_name, int **prop_data);
+extern int di_prop_lookup_int64(dev_t dev, di_node_t node,
+ const char *prop_name, int64_t **prop_data);
+extern int di_prop_lookup_strings(dev_t dev, di_node_t node,
+ const char *prop_name, char **prop_data);
+
/*
- * Software property access
+ * prom_node: property access
*/
-extern di_prop_t di_prop_next(di_node_t node, di_prop_t prop);
-extern dev_t di_prop_devt(di_prop_t prop);
-extern char *di_prop_name(di_prop_t prop);
-extern int di_prop_type(di_prop_t prop);
-extern int di_prop_ints(di_prop_t prop, int **prop_data);
-extern int di_prop_int64(di_prop_t prop, int64_t **prop_data);
-extern int di_prop_strings(di_prop_t prop, char **prop_data);
-extern int di_prop_bytes(di_prop_t prop, uchar_t **prop_data);
-extern int di_prop_lookup_ints(dev_t dev, di_node_t node,
- const char *prop_name, int **prop_data);
-extern int di_prop_lookup_int64(dev_t dev, di_node_t node,
- const char *prop_name, int64_t **prop_data);
-extern int di_prop_lookup_strings(dev_t dev, di_node_t node,
- const char *prop_name, char **prop_data);
-extern int di_prop_lookup_bytes(dev_t dev, di_node_t node,
- const char *prop_name, uchar_t **prop_data);
+extern di_prom_handle_t di_prom_init(void);
+extern void di_prom_fini(di_prom_handle_t ph);
+
+extern di_prom_prop_t di_prom_prop_next(di_prom_handle_t ph, di_node_t node,
+ di_prom_prop_t prom_prop);
+
+extern char *di_prom_prop_name(di_prom_prop_t prom_prop);
+extern int di_prom_prop_data(di_prom_prop_t prop,
+ uchar_t **prom_prop_data);
+
+extern int di_prom_prop_lookup_ints(di_prom_handle_t prom,
+ di_node_t node, const char *prom_prop_name,
+ int **prom_prop_data);
+extern int di_prom_prop_lookup_strings(di_prom_handle_t prom,
+ di_node_t node, const char *prom_prop_name,
+ char **prom_prop_data);
+extern int di_prom_prop_lookup_bytes(di_prom_handle_t prom,
+ di_node_t node, const char *prom_prop_name,
+ uchar_t **prom_prop_data);
/*
- * PROM property access
+ * path_node: property access
*/
-extern di_prom_handle_t di_prom_init(void);
-extern void di_prom_fini(di_prom_handle_t ph);
+extern di_path_prop_t di_path_prop_next(di_path_t path, di_path_prop_t prop);
+
+extern char *di_path_prop_name(di_path_prop_t prop);
+extern int di_path_prop_type(di_path_prop_t prop);
+extern int di_path_prop_len(di_path_prop_t prop);
+
+extern int di_path_prop_bytes(di_path_prop_t prop,
+ uchar_t **prop_data);
+extern int di_path_prop_ints(di_path_prop_t prop,
+ int **prop_data);
+extern int di_path_prop_int64s(di_path_prop_t prop,
+ int64_t **prop_data);
+extern int di_path_prop_strings(di_path_prop_t prop,
+ char **prop_data);
+
+extern int di_path_prop_lookup_bytes(di_path_t path,
+ const char *prop_name, uchar_t **prop_data);
+extern int di_path_prop_lookup_ints(di_path_t path,
+ const char *prop_name, int **prop_data);
+extern int di_path_prop_lookup_int64s(di_path_t path,
+ const char *prop_name, int64_t **prop_data);
+extern int di_path_prop_lookup_strings(di_path_t path,
+ const char *prop_name, char **prop_data);
+
+/*
+ * layering link/lnode: traversal, data access, and parameters
+ */
+extern int di_walk_link(di_node_t root, uint_t flag,
+ uint_t endpoint, void *arg,
+ int (*link_callback)(di_link_t link, void *arg));
+extern int di_walk_lnode(di_node_t root, uint_t flag, void *arg,
+ int (*lnode_callback)(di_lnode_t lnode, void *arg));
+
+extern di_link_t di_link_next_by_node(di_node_t node,
+ di_link_t link, uint_t endpoint);
+extern di_link_t di_link_next_by_lnode(di_lnode_t lnode,
+ di_link_t link, uint_t endpoint);
+extern di_lnode_t di_lnode_next(di_node_t node, di_lnode_t lnode);
+extern char *di_lnode_name(di_lnode_t lnode);
-extern di_prom_prop_t di_prom_prop_next(di_prom_handle_t ph, di_node_t node,
- di_prom_prop_t prom_prop);
+extern int di_link_spectype(di_link_t link);
+extern di_lnode_t di_link_to_lnode(di_link_t link, uint_t endpoint);
+
+extern di_node_t di_lnode_devinfo(di_lnode_t lnode);
+extern int di_lnode_devt(di_lnode_t lnode, dev_t *devt);
-extern char *di_prom_prop_name(di_prom_prop_t prom_prop);
-extern int di_prom_prop_data(di_prom_prop_t prop, uchar_t **prom_prop_data);
+extern void di_link_private_set(di_link_t link, void *data);
+extern void *di_link_private_get(di_link_t link);
+extern void di_lnode_private_set(di_lnode_t lnode, void *data);
+extern void *di_lnode_private_get(di_lnode_t lnode);
-extern int di_prom_prop_lookup_ints(di_prom_handle_t prom, di_node_t node,
- const char *prom_prop_name, int **prom_prop_data);
-extern int di_prom_prop_lookup_strings(di_prom_handle_t prom, di_node_t node,
- const char *prom_prop_name, char **prom_prop_data);
-extern int di_prom_prop_lookup_bytes(di_prom_handle_t prom, di_node_t node,
- const char *prom_prop_name, uchar_t **prom_prop_data);
/*
* Private interfaces
@@ -276,12 +326,17 @@ extern int di_prom_prop_lookup_bytes(di_prom_handle_t prom, di_node_t node,
* The interfaces and structures below are private to this implementation
* of Solaris and are subject to change at any time without notice.
*
- * Applications and drivers using these interfaces will fail
+ * Applications and drivers using these interfaces may fail
* to run on future releases.
*/
-
extern di_prop_t di_prop_find(dev_t match_dev, di_node_t node,
const char *name);
+extern int di_devfs_path_match(const char *dp1, const char *dp2);
+
+extern di_node_t di_vhci_first_node(di_node_t root);
+extern di_node_t di_vhci_next_node(di_node_t node);
+extern di_node_t di_phci_first_node(di_node_t vhci_node);
+extern di_node_t di_phci_next_node(di_node_t node);
/*
* Interfaces for handling IEEE 1275 and other standardized properties
@@ -305,35 +360,14 @@ extern int di_prom_prop_lookup_slot_names(di_prom_handle_t ph, di_node_t node,
di_slot_name_t **prop_data);
/*
- * Interfaces for accessing I/O multipathing data
+ * XXX Remove the private di_path_(addr,next,next_phci,next_client) interfaces
+ * below after NWS consolidation switches to using di_path_bus_addr,
+ * di_path_phci_next_path, and di_path_client_next_path per CR6638521.
*/
-/* XXX remove di_path_next() after updating NWS consolidation */
+extern char *di_path_addr(di_path_t path, char *buf);
extern di_path_t di_path_next(di_node_t node, di_path_t path);
extern di_path_t di_path_next_phci(di_node_t node, di_path_t path);
extern di_path_t di_path_next_client(di_node_t node, di_path_t path);
-extern di_path_state_t di_path_state(di_path_t path);
-extern char *di_path_addr(di_path_t path, char *buf);
-extern di_node_t di_path_client_node(di_path_t path);
-extern void di_path_client_path(di_path_t path, char *buf);
-extern di_node_t di_path_phci_node(di_path_t path);
-extern void di_path_phci_path(di_path_t path, char *buf);
-extern di_path_prop_t di_path_prop_next(di_path_t path, di_path_prop_t prop);
-extern char *di_path_prop_name(di_path_prop_t prop);
-extern int di_path_prop_type(di_path_prop_t prop);
-extern int di_path_prop_len(di_path_prop_t prop);
-extern int di_path_prop_bytes(di_path_prop_t prop, uchar_t **prop_data);
-extern int di_path_prop_ints(di_path_prop_t prop, int **prop_data);
-extern int di_path_prop_int64s(di_path_prop_t prop, int64_t **prop_data);
-extern int di_path_prop_strings(di_path_prop_t prop, char **prop_data);
-extern int di_path_prop_lookup_bytes(di_path_t path, const char *prop_name,
- uchar_t **prop_data);
-extern int di_path_prop_lookup_ints(di_path_t path, const char *prop_name,
- int **prop_data);
-extern int di_path_prop_lookup_int64s(di_path_t path, const char *prop_name,
- int64_t **prop_data);
-extern int di_path_prop_lookup_strings(di_path_t path, const char *prop_name,
- char **prop_data);
-
/*
* Interfaces for private data
@@ -436,11 +470,12 @@ extern int di_devperm_login(const char *, uid_t, gid_t, void (*)(char *));
extern int di_devperm_logout(const char *);
/*
- * Private interface for looking up a node in a snapshot
+ * Private interface for looking up, by path string, a node/path/minor
+ * in a snapshot.
*/
+extern di_path_t di_lookup_path(di_node_t root, char *path);
extern di_node_t di_lookup_node(di_node_t root, char *path);
-
/*
* Private hotplug interfaces to be used between cfgadm pci plugin and
* devfsadm link generator.
diff --git a/usr/src/lib/libdevinfo/mapfile-vers b/usr/src/lib/libdevinfo/mapfile-vers
index aa49121009..581729d3e6 100644
--- a/usr/src/lib/libdevinfo/mapfile-vers
+++ b/usr/src/lib/libdevinfo/mapfile-vers
@@ -25,6 +25,34 @@
# ident "%Z%%M% %I% %E% SMI"
#
+SUNW_1.4 {
+ global:
+ di_path_bus_addr;
+ di_path_client_devfs_path;
+ di_path_client_next_path;
+ di_path_client_node;
+ di_path_devfs_path;
+ di_path_instance;
+ di_path_node_name;
+ di_path_phci_next_path;
+ di_path_phci_node;
+ di_path_private_get;
+ di_path_private_set;
+ di_path_prop_bytes;
+ di_path_prop_int64s;
+ di_path_prop_ints;
+ di_path_prop_len;
+ di_path_prop_lookup_bytes;
+ di_path_prop_lookup_int64s;
+ di_path_prop_lookup_ints;
+ di_path_prop_lookup_strings;
+ di_path_prop_name;
+ di_path_prop_next;
+ di_path_prop_strings;
+ di_path_prop_type;
+ di_path_state;
+} SUNW_1.3;
+
SUNW_1.3 {
global:
di_devfs_minor_path;
@@ -80,8 +108,8 @@ SUNW_1.1 {
di_minor_nodetype;
di_minor_spectype;
di_minor_type;
- di_nodeid;
di_node_name;
+ di_nodeid;
di_parent_node;
di_prom_fini;
di_prom_init;
@@ -123,11 +151,15 @@ SUNWprivate_1.1 {
devfs_get_prom_names;
devfs_install2target;
devfs_load_minor_perm;
+ devfs_parse_binding_file;
devfs_path_to_drv;
devfs_read_minor_perm;
devfs_resolve_aliases;
devfs_rm_minor_perm;
devfs_target2install;
+ devfs_walk_minor_nodes;
+ device_exists;
+ di_devfs_path_match;
di_devlink_add_link;
di_devlink_cache_walk;
di_devlink_close;
@@ -143,42 +175,34 @@ SUNWprivate_1.1 {
di_devlink_type;
di_devlink_update;
di_devlink_walk;
- di_devperm_login;
- di_devperm_logout;
- di_devname_get_mapinfo;
- di_devname_get_mapent;
di_devname_action_on_key;
+ di_devname_get_mapent;
+ di_devname_get_mapinfo;
di_devname_print_mapinfo;
- di_driver_private_data;
+ di_devperm_login;
+ di_devperm_logout;
di_dim_fini;
di_dim_init;
di_dim_path_dev;
di_dim_path_devices;
+ di_dli_close;
+ di_dli_name;
+ di_dli_openr;
+ di_dli_openw;
+ di_driver_private_data;
+ di_flags;
di_init_driver;
di_init_impl;
di_lookup_node;
+ di_lookup_path;
di_minor_devinfo;
di_node_state;
di_parent_private_data;
+# XXX remove: di_path_(addr,next,next_client,next_phci)
di_path_addr;
- di_path_client_node;
di_path_next;
di_path_next_client;
di_path_next_phci;
- di_path_phci_node;
- di_path_prop_bytes;
- di_path_prop_int64s;
- di_path_prop_ints;
- di_path_prop_len;
- di_path_prop_lookup_bytes;
- di_path_prop_lookup_int64s;
- di_path_prop_lookup_ints;
- di_path_prop_lookup_strings;
- di_path_prop_name;
- di_path_prop_next;
- di_path_prop_strings;
- di_path_prop_type;
- di_path_state;
di_phci_first_node;
di_phci_next_node;
di_prof_add_dev;
@@ -186,37 +210,29 @@ SUNWprivate_1.1 {
di_prof_add_map;
di_prof_add_symlink;
di_prof_commit;
- di_prof_init;
di_prof_fini;
+ di_prof_init;
+ di_prom_prop_lookup_slot_names;
+ di_prom_prop_slot_names;
di_prop_drv_next;
+ di_prop_find;
di_prop_global_next;
di_prop_hw_next;
+ di_prop_lookup_slot_names;
di_prop_rawdata;
+ di_prop_slot_names;
di_prop_sys_next;
+ di_retire_device;
+ di_retired;
+ di_slot_names_decode;
+ di_slot_names_free;
+ di_unretire_device;
di_vhci_first_node;
di_vhci_next_node;
- di_dli_name;
- di_dli_openr;
- di_dli_openw;
- di_dli_close;
- di_slot_names_free;
- di_slot_names_decode;
- di_prop_slot_names;
- di_prom_prop_slot_names;
- di_prop_lookup_slot_names;
- di_prom_prop_lookup_slot_names;
- di_prop_find;
- device_exists;
finddev_close;
finddev_emptydir;
finddev_next;
finddev_readdir;
- di_flags;
- di_retire_device;
- di_unretire_device;
- di_retired;
- devfs_parse_binding_file;
- devfs_walk_minor_nodes;
local:
*;
};
diff --git a/usr/src/lib/libdiskmgt/common/findevs.c b/usr/src/lib/libdiskmgt/common/findevs.c
index 076281693d..81230e6323 100644
--- a/usr/src/lib/libdiskmgt/common/findevs.c
+++ b/usr/src/lib/libdiskmgt/common/findevs.c
@@ -688,7 +688,7 @@ add_disk2controller(disk_t *diskp, struct search_args *args)
/* note: mpxio di_path stuff is all consolidation private */
di_path_t pi = DI_PATH_NIL;
- while ((pi = di_path_next_phci(node, pi)) != DI_PATH_NIL) {
+ while ((pi = di_path_client_next_path(node, pi)) != DI_PATH_NIL) {
int cnt;
uchar_t *bytes;
char str[MAXPATHLEN];
@@ -770,7 +770,8 @@ add_int2array(int p, int **parray)
cnt = 0;
if (pa != NULL) {
- for (; pa[cnt] != -1; cnt++);
+ for (; pa[cnt] != -1; cnt++)
+ ;
}
new_array = (int *)calloc(cnt + 2, sizeof (int *));
@@ -804,7 +805,8 @@ add_ptr2array(void *p, void ***parray)
cnt = 0;
if (pa != NULL) {
- for (; pa[cnt]; cnt++);
+ for (; pa[cnt]; cnt++)
+ ;
}
new_array = (void **)calloc(cnt + 2, sizeof (void *));
diff --git a/usr/src/lib/libnvpair/Makefile.com b/usr/src/lib/libnvpair/Makefile.com
index 532a1032cc..4439415f03 100644
--- a/usr/src/lib/libnvpair/Makefile.com
+++ b/usr/src/lib/libnvpair/Makefile.com
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -50,6 +50,10 @@ LIBS = $(DYNLIB) $(LINTLIB)
# turn off ptr-cast warnings
LINTFLAGS64 += -erroff=E_BAD_PTR_CAST_ALIGN
+# turn off warning caused by lint bug: not understanding SCNi8 "hhi"
+LINTFLAGS += -erroff=E_BAD_FORMAT_STR2
+LINTFLAGS64 += -erroff=E_BAD_FORMAT_STR2
+
CFLAGS += $(CCVERBOSE)
CPPFLAGS += -D_REENTRANT
diff --git a/usr/src/lib/libnvpair/libnvpair.c b/usr/src/lib/libnvpair/libnvpair.c
index 58a47f1f06..664a3fff6f 100644
--- a/usr/src/lib/libnvpair/libnvpair.c
+++ b/usr/src/lib/libnvpair/libnvpair.c
@@ -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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -28,6 +27,8 @@
#include <unistd.h>
#include <strings.h>
+#include <sys/types.h>
+#include <sys/inttypes.h>
#include "libnvpair.h"
/*
@@ -264,3 +265,347 @@ nvlist_print(FILE *fp, nvlist_t *nvl)
{
nvlist_print_with_indent(fp, nvl, 0);
}
+
+/*
+ * Determine if string 'value' matches 'nvp' value. The 'value' string is
+ * converted, depending on the type of 'nvp', prior to match. For numeric
+ * types, a radix independent sscanf conversion of 'value' is used. If 'nvp'
+ * is an array type, 'ai' is the index into the array against which we are
+ * checking for match. If nvp is of DATA_TYPE_STRING*, the caller can pass
+ * in a regex_t compilation of value in 'value_regex' to trigger regular
+ * expression string match instead of simple strcmp().
+ *
+ * Return 1 on match, 0 on no-match, and -1 on error. If the error is
+ * related to value syntax error and 'ep' is non-NULL, *ep will point into
+ * the 'value' string at the location where the error exists.
+ *
+ * NOTE: It may be possible to move the non-regex_t version of this into
+ * common code used by library/kernel/boot.
+ */
+int
+nvpair_value_match_regex(nvpair_t *nvp, int ai,
+ char *value, regex_t *value_regex, char **ep)
+{
+ char *evalue;
+ uint_t a_len;
+ int sr;
+
+ if (ep)
+ *ep = NULL;
+
+ if ((nvp == NULL) || (value == NULL))
+ return (-1); /* error fail match - invalid args */
+
+ /* make sure array and index combination make sense */
+ if ((nvpair_type_is_array(nvp) && (ai < 0)) ||
+ (!nvpair_type_is_array(nvp) && (ai >= 0)))
+ return (-1); /* error fail match - bad index */
+
+ /* non-string values should be single 'chunk' */
+ if ((nvpair_type(nvp) != DATA_TYPE_STRING) &&
+ (nvpair_type(nvp) != DATA_TYPE_STRING_ARRAY)) {
+ value += strspn(value, " \t");
+ evalue = value + strcspn(value, " \t");
+ if (*evalue) {
+ if (ep)
+ *ep = evalue;
+ return (-1); /* error fail match - syntax */
+ }
+ }
+
+ sr = EOF;
+ switch (nvpair_type(nvp)) {
+ case DATA_TYPE_STRING: {
+ char *val;
+
+ /* check string value for match */
+ if (nvpair_value_string(nvp, &val) == 0) {
+ if (value_regex) {
+ if (regexec(value_regex, val,
+ (size_t)0, NULL, 0) == 0)
+ return (1); /* match */
+ } else {
+ if (strcmp(value, val) == 0)
+ return (1); /* match */
+ }
+ }
+ break;
+ }
+ case DATA_TYPE_STRING_ARRAY: {
+ char **val_array;
+
+ /* check indexed string value of array for match */
+ if ((nvpair_value_string_array(nvp, &val_array, &a_len) == 0) &&
+ (ai < a_len)) {
+ if (value_regex) {
+ if (regexec(value_regex, val_array[ai],
+ (size_t)0, NULL, 0) == 0)
+ return (1);
+ } else {
+ if (strcmp(value, val_array[ai]) == 0)
+ return (1);
+ }
+ }
+ break;
+ }
+ case DATA_TYPE_BYTE: {
+ uchar_t val, val_arg;
+
+ /* scanf uchar_t from value and check for match */
+ sr = sscanf(value, "%c", &val_arg);
+ if ((sr == 1) && (nvpair_value_byte(nvp, &val) == 0) &&
+ (val == val_arg))
+ return (1);
+ break;
+ }
+ case DATA_TYPE_BYTE_ARRAY: {
+ uchar_t *val_array, val_arg;
+
+
+ /* check indexed value of array for match */
+ sr = sscanf(value, "%c", &val_arg);
+ if ((sr == 1) &&
+ (nvpair_value_byte_array(nvp, &val_array, &a_len) == 0) &&
+ (ai < a_len) &&
+ (val_array[ai] == val_arg))
+ return (1);
+ break;
+ }
+ case DATA_TYPE_INT8: {
+ int8_t val, val_arg;
+
+ /* scanf int8_t from value and check for match */
+ sr = sscanf(value, "%"SCNi8, &val_arg);
+ if ((sr == 1) &&
+ (nvpair_value_int8(nvp, &val) == 0) &&
+ (val == val_arg))
+ return (1);
+ break;
+ }
+ case DATA_TYPE_INT8_ARRAY: {
+ int8_t *val_array, val_arg;
+
+ /* check indexed value of array for match */
+ sr = sscanf(value, "%"SCNi8, &val_arg);
+ if ((sr == 1) &&
+ (nvpair_value_int8_array(nvp, &val_array, &a_len) == 0) &&
+ (ai < a_len) &&
+ (val_array[ai] == val_arg))
+ return (1);
+ break;
+ }
+ case DATA_TYPE_UINT8: {
+ uint8_t val, val_arg;
+
+ /* scanf uint8_t from value and check for match */
+ sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg);
+ if ((sr == 1) &&
+ (nvpair_value_uint8(nvp, &val) == 0) &&
+ (val == val_arg))
+ return (1);
+ break;
+ }
+ case DATA_TYPE_UINT8_ARRAY: {
+ uint8_t *val_array, val_arg;
+
+ /* check indexed value of array for match */
+ sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg);
+ if ((sr == 1) &&
+ (nvpair_value_uint8_array(nvp, &val_array, &a_len) == 0) &&
+ (ai < a_len) &&
+ (val_array[ai] == val_arg))
+ return (1);
+ break;
+ }
+ case DATA_TYPE_INT16: {
+ int16_t val, val_arg;
+
+ /* scanf int16_t from value and check for match */
+ sr = sscanf(value, "%"SCNi16, &val_arg);
+ if ((sr == 1) &&
+ (nvpair_value_int16(nvp, &val) == 0) &&
+ (val == val_arg))
+ return (1);
+ break;
+ }
+ case DATA_TYPE_INT16_ARRAY: {
+ int16_t *val_array, val_arg;
+
+ /* check indexed value of array for match */
+ sr = sscanf(value, "%"SCNi16, &val_arg);
+ if ((sr == 1) &&
+ (nvpair_value_int16_array(nvp, &val_array, &a_len) == 0) &&
+ (ai < a_len) &&
+ (val_array[ai] == val_arg))
+ return (1);
+ break;
+ }
+ case DATA_TYPE_UINT16: {
+ uint16_t val, val_arg;
+
+ /* scanf uint16_t from value and check for match */
+ sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg);
+ if ((sr == 1) &&
+ (nvpair_value_uint16(nvp, &val) == 0) &&
+ (val == val_arg))
+ return (1);
+ break;
+ }
+ case DATA_TYPE_UINT16_ARRAY: {
+ uint16_t *val_array, val_arg;
+
+ /* check indexed value of array for match */
+ sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg);
+ if ((sr == 1) &&
+ (nvpair_value_uint16_array(nvp, &val_array, &a_len) == 0) &&
+ (ai < a_len) &&
+ (val_array[ai] == val_arg))
+ return (1);
+ break;
+ }
+ case DATA_TYPE_INT32: {
+ int32_t val, val_arg;
+
+ /* scanf int32_t from value and check for match */
+ sr = sscanf(value, "%"SCNi32, &val_arg);
+ if ((sr == 1) &&
+ (nvpair_value_int32(nvp, &val) == 0) &&
+ (val == val_arg))
+ return (1);
+ break;
+ }
+ case DATA_TYPE_INT32_ARRAY: {
+ int32_t *val_array, val_arg;
+
+ /* check indexed value of array for match */
+ sr = sscanf(value, "%"SCNi32, &val_arg);
+ if ((sr == 1) &&
+ (nvpair_value_int32_array(nvp, &val_array, &a_len) == 0) &&
+ (ai < a_len) &&
+ (val_array[ai] == val_arg))
+ return (1);
+ break;
+ }
+ case DATA_TYPE_UINT32: {
+ uint32_t val, val_arg;
+
+ /* scanf uint32_t from value and check for match */
+ sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg);
+ if ((sr == 1) &&
+ (nvpair_value_uint32(nvp, &val) == 0) &&
+ (val == val_arg))
+ return (1);
+ break;
+ }
+ case DATA_TYPE_UINT32_ARRAY: {
+ uint32_t *val_array, val_arg;
+
+ /* check indexed value of array for match */
+ sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg);
+ if ((sr == 1) &&
+ (nvpair_value_uint32_array(nvp, &val_array, &a_len) == 0) &&
+ (ai < a_len) &&
+ (val_array[ai] == val_arg))
+ return (1);
+ break;
+ }
+ case DATA_TYPE_INT64: {
+ int64_t val, val_arg;
+
+ /* scanf int64_t from value and check for match */
+ sr = sscanf(value, "%"SCNi64, &val_arg);
+ if ((sr == 1) &&
+ (nvpair_value_int64(nvp, &val) == 0) &&
+ (val == val_arg))
+ return (1);
+ break;
+ }
+ case DATA_TYPE_INT64_ARRAY: {
+ int64_t *val_array, val_arg;
+
+ /* check indexed value of array for match */
+ sr = sscanf(value, "%"SCNi64, &val_arg);
+ if ((sr == 1) &&
+ (nvpair_value_int64_array(nvp, &val_array, &a_len) == 0) &&
+ (ai < a_len) &&
+ (val_array[ai] == val_arg))
+ return (1);
+ break;
+ }
+ case DATA_TYPE_UINT64: {
+ uint64_t val_arg, val;
+
+ /* scanf uint64_t from value and check for match */
+ sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg);
+ if ((sr == 1) &&
+ (nvpair_value_uint64(nvp, &val) == 0) &&
+ (val == val_arg))
+ return (1);
+ break;
+ }
+ case DATA_TYPE_UINT64_ARRAY: {
+ uint64_t *val_array, val_arg;
+
+ /* check indexed value of array for match */
+ sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg);
+ if ((sr == 1) &&
+ (nvpair_value_uint64_array(nvp, &val_array, &a_len) == 0) &&
+ (ai < a_len) &&
+ (val_array[ai] == val_arg))
+ return (1);
+ break;
+ }
+ case DATA_TYPE_BOOLEAN_VALUE: {
+ boolean_t val, val_arg;
+
+ /* scanf boolean_t from value and check for match */
+ sr = sscanf(value, "%"SCNi32, &val_arg);
+ if ((sr == 1) &&
+ (nvpair_value_boolean_value(nvp, &val) == 0) &&
+ (val == val_arg))
+ return (1);
+ break;
+ }
+ case DATA_TYPE_BOOLEAN_ARRAY: {
+ boolean_t *val_array, val_arg;
+
+ /* check indexed value of array for match */
+ sr = sscanf(value, "%"SCNi32, &val_arg);
+ if ((sr == 1) &&
+ (nvpair_value_boolean_array(nvp,
+ &val_array, &a_len) == 0) &&
+ (ai < a_len) &&
+ (val_array[ai] == val_arg))
+ return (1);
+ break;
+ }
+ case DATA_TYPE_HRTIME:
+ case DATA_TYPE_NVLIST:
+ case DATA_TYPE_NVLIST_ARRAY:
+ case DATA_TYPE_BOOLEAN:
+ case DATA_TYPE_UNKNOWN:
+ default:
+ /*
+ * unknown/unsupported data type
+ */
+ return (-1); /* error fail match */
+ }
+
+ /*
+ * check to see if sscanf failed conversion, return approximate
+ * pointer to problem
+ */
+ if (sr != 1) {
+ if (ep)
+ *ep = value;
+ return (-1); /* error fail match - syntax */
+ }
+
+ return (0); /* fail match */
+}
+
+int
+nvpair_value_match(nvpair_t *nvp, int ai, char *value, char **ep)
+{
+ return (nvpair_value_match_regex(nvp, ai, value, NULL, ep));
+}
diff --git a/usr/src/lib/libnvpair/libnvpair.h b/usr/src/lib/libnvpair/libnvpair.h
index d1d25ea70e..e655e0d406 100644
--- a/usr/src/lib/libnvpair/libnvpair.h
+++ b/usr/src/lib/libnvpair/libnvpair.h
@@ -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 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -32,12 +31,15 @@
#include <sys/nvpair.h>
#include <stdlib.h>
#include <stdio.h>
+#include <regex.h>
#ifdef __cplusplus
extern "C" {
#endif
void nvlist_print(FILE *, nvlist_t *);
+int nvpair_value_match(nvpair_t *, int, char *, char **);
+int nvpair_value_match_regex(nvpair_t *, int, char *, regex_t *, char **);
#ifdef __cplusplus
}
diff --git a/usr/src/lib/libnvpair/mapfile-vers b/usr/src/lib/libnvpair/mapfile-vers
index 50252d220f..fb80a984b1 100644
--- a/usr/src/lib/libnvpair/mapfile-vers
+++ b/usr/src/lib/libnvpair/mapfile-vers
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -147,6 +147,10 @@ SUNWprivate_1.1 {
nvlist_lookup_hrtime;
nvlist_print;
nvpair_value_hrtime;
+ nvpair_type_is_array;
+ nvlist_lookup_nvpair_embedded_index;
+ nvpair_value_match;
+ nvpair_value_match_regex;
local:
*;
};