summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreschrock <none@none>2008-03-28 17:41:18 -0700
committereschrock <none@none>2008-03-28 17:41:18 -0700
commit275c9da86e89f8abf71135cf63d9fc23671b2e60 (patch)
treec00ea3adc6cc1d4140ca524271718bab19f96d6f
parenta4e703601c0d75298c6e1fb6c2617c37ec86bf33 (diff)
downloadillumos-joyent-275c9da86e89f8abf71135cf63d9fc23671b2e60.tar.gz
PSARC 2008/146 sgen(7d) multiple opens
PSARC 2008/196 libscsi and libses 6667022 sgen should support multiple concurrent opens 6667023 ses mishandles uscsi requests 6667024 want a generic SCSI library 6667025 want a generic SES library
-rw-r--r--usr/src/Makefile.lint1
-rw-r--r--usr/src/Targetdirs3
-rw-r--r--usr/src/cmd/Makefile2
-rw-r--r--usr/src/cmd/scsi/Makefile32
-rw-r--r--usr/src/cmd/scsi/Makefile.subdirs43
-rw-r--r--usr/src/cmd/scsi/sestopo/Makefile29
-rw-r--r--usr/src/cmd/scsi/sestopo/Makefile.com69
-rw-r--r--usr/src/cmd/scsi/sestopo/common/sestopo.c98
-rw-r--r--usr/src/cmd/scsi/sestopo/i386/Makefile28
-rw-r--r--usr/src/cmd/scsi/sestopo/sparc/Makefile28
-rw-r--r--usr/src/lib/Makefile3
-rw-r--r--usr/src/lib/scsi/Makefile41
-rw-r--r--usr/src/lib/scsi/Makefile.defs35
-rw-r--r--usr/src/lib/scsi/Makefile.rootdirs69
-rw-r--r--usr/src/lib/scsi/Makefile.subdirs44
-rw-r--r--usr/src/lib/scsi/libscsi/Makefile61
-rw-r--r--usr/src/lib/scsi/libscsi/Makefile.com71
-rw-r--r--usr/src/lib/scsi/libscsi/amd64/Makefile31
-rw-r--r--usr/src/lib/scsi/libscsi/common/libscsi.h182
-rw-r--r--usr/src/lib/scsi/libscsi/common/libscsi_impl.h100
-rw-r--r--usr/src/lib/scsi/libscsi/common/mkerrno.sh88
-rw-r--r--usr/src/lib/scsi/libscsi/common/scsi_engine.c621
-rw-r--r--usr/src/lib/scsi/libscsi/common/scsi_status.c723
-rw-r--r--usr/src/lib/scsi/libscsi/common/scsi_subr.c351
-rw-r--r--usr/src/lib/scsi/libscsi/i386/Makefile30
-rw-r--r--usr/src/lib/scsi/libscsi/libscsi_api.map49
-rw-r--r--usr/src/lib/scsi/libscsi/llib-lscsi32
-rw-r--r--usr/src/lib/scsi/libscsi/mapfile-vers72
-rw-r--r--usr/src/lib/scsi/libscsi/sparc/Makefile30
-rw-r--r--usr/src/lib/scsi/libscsi/sparcv9/Makefile31
-rw-r--r--usr/src/lib/scsi/libses/Makefile61
-rw-r--r--usr/src/lib/scsi/libses/Makefile.com40
-rw-r--r--usr/src/lib/scsi/libses/Makefile.defs60
-rw-r--r--usr/src/lib/scsi/libses/Makefile.defs.6428
-rw-r--r--usr/src/lib/scsi/libses/Makefile.targ42
-rw-r--r--usr/src/lib/scsi/libses/amd64/Makefile36
-rw-r--r--usr/src/lib/scsi/libses/common/libses.h132
-rw-r--r--usr/src/lib/scsi/libses/common/libses_plugin.h161
-rw-r--r--usr/src/lib/scsi/libses/common/mkerrno.sh86
-rw-r--r--usr/src/lib/scsi/libses/common/ses_enclosure.c293
-rw-r--r--usr/src/lib/scsi/libses/common/ses_impl.h170
-rw-r--r--usr/src/lib/scsi/libses/common/ses_node.c399
-rw-r--r--usr/src/lib/scsi/libses/common/ses_plugin.c398
-rw-r--r--usr/src/lib/scsi/libses/common/ses_snap.c700
-rw-r--r--usr/src/lib/scsi/libses/common/ses_subr.c376
-rw-r--r--usr/src/lib/scsi/libses/i386/Makefile36
-rw-r--r--usr/src/lib/scsi/libses/libses_api.map69
-rw-r--r--usr/src/lib/scsi/libses/llib-lses32
-rw-r--r--usr/src/lib/scsi/libses/mapfile-vers77
-rw-r--r--usr/src/lib/scsi/libses/sparc/Makefile36
-rw-r--r--usr/src/lib/scsi/libses/sparcv9/Makefile36
-rw-r--r--usr/src/lib/scsi/plugins/Makefile36
-rw-r--r--usr/src/lib/scsi/plugins/scsi/Makefile35
-rw-r--r--usr/src/lib/scsi/plugins/scsi/engines/Makefile32
-rw-r--r--usr/src/lib/scsi/plugins/scsi/engines/Makefile.engine76
-rw-r--r--usr/src/lib/scsi/plugins/scsi/engines/Makefile.targ82
-rw-r--r--usr/src/lib/scsi/plugins/scsi/engines/uscsi/Makefile51
-rw-r--r--usr/src/lib/scsi/plugins/scsi/engines/uscsi/Makefile.com31
-rw-r--r--usr/src/lib/scsi/plugins/scsi/engines/uscsi/amd64/Makefile33
-rw-r--r--usr/src/lib/scsi/plugins/scsi/engines/uscsi/i386/Makefile32
-rw-r--r--usr/src/lib/scsi/plugins/scsi/engines/uscsi/sparc/Makefile32
-rw-r--r--usr/src/lib/scsi/plugins/scsi/engines/uscsi/sparcv9/Makefile33
-rw-r--r--usr/src/lib/scsi/plugins/scsi/engines/uscsi/uscsi.c235
-rw-r--r--usr/src/lib/scsi/plugins/ses/Makefile37
-rw-r--r--usr/src/lib/scsi/plugins/ses/Makefile.lib75
-rw-r--r--usr/src/lib/scsi/plugins/ses/Makefile.plugin59
-rw-r--r--usr/src/lib/scsi/plugins/ses/Makefile.targ82
-rw-r--r--usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/Makefile32
-rw-r--r--usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/Makefile.com33
-rw-r--r--usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/amd64/Makefile33
-rw-r--r--usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/common/riverwalk.c211
-rw-r--r--usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/i386/Makefile32
-rw-r--r--usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/sparc/Makefile32
-rw-r--r--usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/sparcv9/Makefile33
-rw-r--r--usr/src/lib/scsi/plugins/ses/libses/Makefile32
-rw-r--r--usr/src/lib/scsi/plugins/ses/libses/Makefile.com39
-rw-r--r--usr/src/lib/scsi/plugins/ses/libses/amd64/Makefile33
-rw-r--r--usr/src/lib/scsi/plugins/ses/libses/common/libses.c93
-rw-r--r--usr/src/lib/scsi/plugins/ses/libses/common/libses.h72
-rw-r--r--usr/src/lib/scsi/plugins/ses/libses/common/libses_impl.h42
-rw-r--r--usr/src/lib/scsi/plugins/ses/libses/common/mkelemtype.sh69
-rw-r--r--usr/src/lib/scsi/plugins/ses/libses/i386/Makefile32
-rw-r--r--usr/src/lib/scsi/plugins/ses/libses/sparc/Makefile32
-rw-r--r--usr/src/lib/scsi/plugins/ses/libses/sparcv9/Makefile33
-rw-r--r--usr/src/lib/scsi/plugins/ses/ses2/Makefile32
-rw-r--r--usr/src/lib/scsi/plugins/ses/ses2/Makefile.com39
-rw-r--r--usr/src/lib/scsi/plugins/ses/ses2/amd64/Makefile33
-rw-r--r--usr/src/lib/scsi/plugins/ses/ses2/common/ses2.c137
-rw-r--r--usr/src/lib/scsi/plugins/ses/ses2/common/ses2.h528
-rw-r--r--usr/src/lib/scsi/plugins/ses/ses2/common/ses2_element.c1008
-rw-r--r--usr/src/lib/scsi/plugins/ses/ses2/common/ses2_element_ctl.c1856
-rw-r--r--usr/src/lib/scsi/plugins/ses/ses2/common/ses2_enclosure.c328
-rw-r--r--usr/src/lib/scsi/plugins/ses/ses2/common/ses2_enclosure_ctl.c330
-rw-r--r--usr/src/lib/scsi/plugins/ses/ses2/common/ses2_impl.h1549
-rw-r--r--usr/src/lib/scsi/plugins/ses/ses2/common/ses2_pages.c462
-rw-r--r--usr/src/lib/scsi/plugins/ses/ses2/i386/Makefile32
-rw-r--r--usr/src/lib/scsi/plugins/ses/ses2/sparc/Makefile32
-rw-r--r--usr/src/lib/scsi/plugins/ses/ses2/sparcv9/Makefile33
-rw-r--r--usr/src/pkgdefs/Makefile1
-rw-r--r--usr/src/pkgdefs/SUNWarc/prototype_com5
-rw-r--r--usr/src/pkgdefs/SUNWarc/prototype_i3863
-rw-r--r--usr/src/pkgdefs/SUNWarc/prototype_sparc3
-rw-r--r--usr/src/pkgdefs/SUNWcsl/prototype_com14
-rw-r--r--usr/src/pkgdefs/SUNWcsl/prototype_i38610
-rw-r--r--usr/src/pkgdefs/SUNWcsl/prototype_sparc11
-rw-r--r--usr/src/pkgdefs/SUNWhea/prototype_com12
-rw-r--r--usr/src/pkgdefs/SUNWiotu/prototype_com10
-rw-r--r--usr/src/pkgdefs/SUNWscsip/Makefile36
-rw-r--r--usr/src/pkgdefs/SUNWscsip/depend45
-rw-r--r--usr/src/pkgdefs/SUNWscsip/pkginfo.tmpl52
-rw-r--r--usr/src/pkgdefs/SUNWscsip/prototype_com41
-rw-r--r--usr/src/pkgdefs/SUNWscsip/prototype_i38632
-rw-r--r--usr/src/pkgdefs/SUNWscsip/prototype_sparc32
-rw-r--r--usr/src/tools/scripts/check_rtime.pl1
-rw-r--r--usr/src/uts/common/io/scsi/targets/ses.c123
-rw-r--r--usr/src/uts/common/io/scsi/targets/sgen.c69
-rw-r--r--usr/src/uts/common/sys/Makefile1
-rw-r--r--usr/src/uts/common/sys/scsi/impl/commands.h125
-rw-r--r--usr/src/uts/common/sys/scsi/impl/spc3_types.h1045
-rw-r--r--usr/src/uts/common/sys/scsi/targets/sgendef.h10
120 files changed, 16067 insertions, 122 deletions
diff --git a/usr/src/Makefile.lint b/usr/src/Makefile.lint
index 6ed5c8ab98..702b14089d 100644
--- a/usr/src/Makefile.lint
+++ b/usr/src/Makefile.lint
@@ -403,6 +403,7 @@ COMMON_SUBDIRS = \
lib/pkcs11 \
lib/print \
lib/raidcfg_plugins \
+ lib/scsi \
lib/smbsrv \
lib/fm \
lib/udapl \
diff --git a/usr/src/Targetdirs b/usr/src/Targetdirs
index e038856497..102f1648cb 100644
--- a/usr/src/Targetdirs
+++ b/usr/src/Targetdirs
@@ -246,6 +246,7 @@ ROOT.BIN= \
/usr/include/libmilter \
/usr/include/libpolkit \
/usr/include/sasl \
+ /usr/include/scsi \
/usr/include/tsol \
/usr/include/security \
/usr/lib \
@@ -288,6 +289,7 @@ ROOT.BIN= \
/usr/lib/sasl \
/usr/lib/secure \
/usr/lib/security \
+ /usr/lib/scsi \
/usr/lib/smbsrv \
/usr/lib/term \
/usr/lib/vscan \
@@ -361,6 +363,7 @@ ROOT.BIN64= \
/usr/lib/sasl/$(MACH64) \
/usr/lib/secure/$(MACH64) \
/usr/lib/security/$(MACH64) \
+ /usr/lib/scsi/$(MACH64) \
/usr/lib/smbsrv/$(MACH64) \
/usr/lib/abi/$(MACH64) \
/usr/sbin/$(MACH64) \
diff --git a/usr/src/cmd/Makefile b/usr/src/cmd/Makefile
index 6402d952e2..2ba780c0d2 100644
--- a/usr/src/cmd/Makefile
+++ b/usr/src/cmd/Makefile
@@ -339,6 +339,7 @@ COMMON_SUBDIRS= \
saf \
savecore \
script \
+ scsi \
sdiff \
sdpadm \
sendmail \
@@ -653,6 +654,7 @@ MSGSUBDIRS= \
rmvolmgr \
scadm \
script \
+ scsi \
sdiff \
sdpadm \
sgs \
diff --git a/usr/src/cmd/scsi/Makefile b/usr/src/cmd/scsi/Makefile
new file mode 100644
index 0000000000..1f48541baa
--- /dev/null
+++ b/usr/src/cmd/scsi/Makefile
@@ -0,0 +1,32 @@
+#
+# 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.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+SUBDIRS = \
+ sestopo
+
+_msg:
+
+include ./Makefile.subdirs
diff --git a/usr/src/cmd/scsi/Makefile.subdirs b/usr/src/cmd/scsi/Makefile.subdirs
new file mode 100644
index 0000000000..12ac2c721d
--- /dev/null
+++ b/usr/src/cmd/scsi/Makefile.subdirs
@@ -0,0 +1,43 @@
+#
+# 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.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+.KEEP_STATE:
+
+all := TARGET += all
+clean := TARGET += clean
+clobber := TARGET += clobber
+install := TARGET += install
+install_h := TARGET += install_h
+lint := TARGET += lint
+_msg := TARGET += _msg
+check := TARGET += check
+
+all clean clobber install install_h lint: $(SUBDIRS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; VERSION='$(VERSION)' $(MAKE) $(TARGET)
+
+FRC:
diff --git a/usr/src/cmd/scsi/sestopo/Makefile b/usr/src/cmd/scsi/sestopo/Makefile
new file mode 100644
index 0000000000..d53cbbfdbf
--- /dev/null
+++ b/usr/src/cmd/scsi/sestopo/Makefile
@@ -0,0 +1,29 @@
+#
+# 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.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+SUBDIRS = $(MACH)
+
+include ../Makefile.subdirs
diff --git a/usr/src/cmd/scsi/sestopo/Makefile.com b/usr/src/cmd/scsi/sestopo/Makefile.com
new file mode 100644
index 0000000000..8fdbbb6ab5
--- /dev/null
+++ b/usr/src/cmd/scsi/sestopo/Makefile.com
@@ -0,0 +1,69 @@
+#
+# 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.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+.KEEP_STATE:
+.SUFFIXES:
+
+PROG = sestopo
+SRCS = $(PROG:%=../common/%.c)
+OBJS = $(PROG:%=%.o)
+
+include ../../../Makefile.cmd
+
+ROOTLIBSCSI = $(ROOT)/usr/lib/scsi
+ROOTPROG = $(ROOTLIBSCSI)/$(PROG)
+
+$(NOT_RELEASE_BUILD)CPPFLAGS += -DDEBUG
+CPPFLAGS += -I. -I../common
+CFLAGS += $(CTF_FLAGS) $(CCVERBOSE) $(XSTRCONST)
+LDLIBS += -L$(ROOT)/usr/lib/scsi -lses -lnvpair
+LDFLAGS += -R/usr/lib/scsi
+
+all: $(PROG)
+
+$(PROG): $(OBJS)
+ $(LINK.c) $(OBJS) -o $@ $(LDLIBS)
+ $(CTFMERGE) -L VERSION -o $@ $(OBJS)
+ $(POST_PROCESS)
+
+%.o: ../common/%.c
+ $(COMPILE.c) $<
+ $(CTFCONVERT_O)
+
+clean:
+ $(RM) $(OBJS)
+
+lint: lint_SRCS
+
+$(ROOTLIBSCSI)/%: %
+ $(INS.file)
+
+install_h:
+
+install: all $(ROOTPROG)
+
+include ../../../Makefile.targ
diff --git a/usr/src/cmd/scsi/sestopo/common/sestopo.c b/usr/src/cmd/scsi/sestopo/common/sestopo.c
new file mode 100644
index 0000000000..e4c59e0365
--- /dev/null
+++ b/usr/src/cmd/scsi/sestopo/common/sestopo.c
@@ -0,0 +1,98 @@
+/*
+ * 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"
+
+#include <libnvpair.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <scsi/libses.h>
+
+static void fatal(int, const char *, ...) __NORETURN;
+
+static void
+fatal(int err, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ (void) vfprintf(stderr, fmt, ap);
+ va_end(ap);
+
+ (void) fprintf(stderr, "\n");
+ (void) fflush(stderr);
+
+ _exit(err);
+}
+
+/*ARGSUSED*/
+static ses_walk_action_t
+node(ses_node_t *np, void *arg)
+{
+ ses_node_type_t type;
+ uint64_t val;
+ nvlist_t *props;
+ char *t;
+
+ type = ses_node_type(np);
+ (void) printf("Node Type: %d\n", type);
+ if ((props = ses_node_props(np)) == NULL) {
+ (void) printf("No properties\n");
+ return (SES_WALK_ACTION_CONTINUE);
+ }
+ if (type == SES_NODE_ELEMENT || type == SES_NODE_AGGREGATE) {
+ (void) nvlist_lookup_uint64(props, SES_PROP_ELEMENT_TYPE, &val);
+ if (nvlist_lookup_string(props, LIBSES_PROP_ELEMENT_TYPE_NAME,
+ &t) != 0)
+ t = NULL;
+ (void) printf("Element Type: %s\n", t ? t : "<unknown>");
+ }
+ nvlist_print(stdout, props);
+
+ return (SES_WALK_ACTION_CONTINUE);
+}
+
+int
+main(int argc, char *argv[])
+{
+ ses_target_t *tp;
+ ses_snap_t *sp;
+
+ if (argc != 2)
+ fatal(1, "Usage: %s <device>", argv[0]);
+
+ if ((tp = ses_open(LIBSES_VERSION, argv[1])) == NULL)
+ fatal(-1, "failed to open %s: %s", argv[1], ses_errmsg());
+
+ sp = ses_snap_hold(tp);
+
+ (void) ses_walk(sp, node, NULL);
+
+ ses_snap_rele(sp);
+ ses_close(tp);
+
+ return (0);
+}
diff --git a/usr/src/cmd/scsi/sestopo/i386/Makefile b/usr/src/cmd/scsi/sestopo/i386/Makefile
new file mode 100644
index 0000000000..16356f9dd8
--- /dev/null
+++ b/usr/src/cmd/scsi/sestopo/i386/Makefile
@@ -0,0 +1,28 @@
+#
+# 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.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../../../Makefile.cmd
+include ../Makefile.com
diff --git a/usr/src/cmd/scsi/sestopo/sparc/Makefile b/usr/src/cmd/scsi/sestopo/sparc/Makefile
new file mode 100644
index 0000000000..16356f9dd8
--- /dev/null
+++ b/usr/src/cmd/scsi/sestopo/sparc/Makefile
@@ -0,0 +1,28 @@
+#
+# 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.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../../../Makefile.cmd
+include ../Makefile.com
diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile
index f7acd48612..cd2dd14e2a 100644
--- a/usr/src/lib/Makefile
+++ b/usr/src/lib/Makefile
@@ -238,6 +238,7 @@ SUBDIRS += \
libexacct/demo \
libvscan \
smbsrv \
+ scsi \
$($(MACH)_SUBDIRS)
sparc_SUBDIRS= .WAIT \
@@ -432,6 +433,7 @@ HDRSUBDIRS= \
libidmap \
libvscan \
smbsrv \
+ scsi \
$($(MACH)_HDRSUBDIRS)
$(CLOSED_BUILD)HDRSUBDIRS += \
@@ -561,6 +563,7 @@ libtsalarm: libpcp
smbsrv: libsocket libnsl libmd libxnet libpthread librt \
libshare libidmap pkcs11 libsqlite
libvscan: libscf
+scsi: libnvpair
#
# The reason this rule checks for the existence of the
diff --git a/usr/src/lib/scsi/Makefile b/usr/src/lib/scsi/Makefile
new file mode 100644
index 0000000000..18c7ae7c2c
--- /dev/null
+++ b/usr/src/lib/scsi/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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+SUBDIRS = \
+ libscsi \
+ libses \
+ plugins
+
+.KEEP_STATE:
+
+.PARALLEL:
+
+libses: libscsi
+
+plugins: libscsi libses
+
+include Makefile.subdirs
diff --git a/usr/src/lib/scsi/Makefile.defs b/usr/src/lib/scsi/Makefile.defs
new file mode 100644
index 0000000000..5e6b48caf3
--- /dev/null
+++ b/usr/src/lib/scsi/Makefile.defs
@@ -0,0 +1,35 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+SCSILIBDIR = /usr/lib/scsi
+ROOTSCSILIBDIR = $(ROOT)/usr/lib/scsi
+SCSIHDRDIR = /usr/include/scsi
+ROOTSCSIHDRDIR = $(ROOT)/usr/include/scsi
+
+PLUGINLIBDIR = $(SCSILIBDIR)/plugins
+ROOTPLUGINLIBDIR = $(ROOTSCSILIBDIR)/plugins
+PLUGINHDRDIR = $(SCSIHDRDIR)/plugins
+ROOTPLUGINHDRDIR = $(ROOTSCSIHDRDIR)/plugins
diff --git a/usr/src/lib/scsi/Makefile.rootdirs b/usr/src/lib/scsi/Makefile.rootdirs
new file mode 100644
index 0000000000..c92390410c
--- /dev/null
+++ b/usr/src/lib/scsi/Makefile.rootdirs
@@ -0,0 +1,69 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+#
+# Define the transitive set of rules to create a common module's install dir
+# within the proto area.
+#
+
+$(ROOTPLUGINLIBDIR):
+ $(INS.dir)
+
+$(ROOTPLUGINLIBDIR)/scsi: $(ROOTPLUGINLIBDIR)
+ $(INS.dir)
+
+$(ROOTPLUGINLIBDIR)/scsi/engines: $(ROOTPLUGINLIBDIR)/scsi
+ $(INS.dir)
+
+$(ROOTPLUGINLIBDIR)/scsi/engines/$(MACH64): $(ROOTPLUGINLIBDIR)/scsi/engines
+ $(INS.dir)
+
+$(ROOTPLUGINLIBDIR)/ses: $(ROOTPLUGINLIBDIR)
+ $(INS.dir)
+
+$(ROOTPLUGINLIBDIR)/ses/framework: $(ROOTPLUGINLIBDIR)/ses
+ $(INS.dir)
+
+$(ROOTPLUGINLIBDIR)/ses/framework/$(MACH64): $(ROOTPLUGINLIBDIR)/ses/framework
+ $(INS.dir)
+
+$(ROOTPLUGINLIBDIR)/ses/vendor: $(ROOTPLUGINLIBDIR)/ses
+ $(INS.dir)
+
+$(ROOTPLUGINLIBDIR)/ses/vendor/$(MACH64): $(ROOTPLUGINLIBDIR)/ses/vendor
+ $(INS.dir)
+
+$(ROOTPLUGINHDRDIR):
+ $(INS.dir)
+
+$(ROOTPLUGINHDRDIR)/ses: $(ROOTPLUGINHDRDIR)
+ $(INS.dir)
+
+$(ROOTPLUGINHDRDIR)/ses/framework: $(ROOTPLUGINHDRDIR)/ses
+ $(INS.dir)
+
+$(ROOTPLUGINHDRDIR)/ses/vendor: $(ROOTPLUGINHDRDIR)/ses
+ $(INS.dir)
diff --git a/usr/src/lib/scsi/Makefile.subdirs b/usr/src/lib/scsi/Makefile.subdirs
new file mode 100644
index 0000000000..246da18969
--- /dev/null
+++ b/usr/src/lib/scsi/Makefile.subdirs
@@ -0,0 +1,44 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+.KEEP_STATE:
+
+all := TARGET += all
+check := TARGET += check
+clean := TARGET += clean
+clobber := TARGET += clobber
+install := TARGET += install
+install_h := TARGET += install_h
+lint := TARGET += lint
+_msg := TARGET += _msg
+
+all check clean clobber install install_h lint: $(SUBDIRS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; VERSION='$(VERSION)' $(MAKE) $(TARGET)
+
+FRC:
diff --git a/usr/src/lib/scsi/libscsi/Makefile b/usr/src/lib/scsi/libscsi/Makefile
new file mode 100644
index 0000000000..c21f8e06fd
--- /dev/null
+++ b/usr/src/lib/scsi/libscsi/Makefile
@@ -0,0 +1,61 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+include ../../Makefile.lib
+include ../Makefile.defs
+
+HDRS = libscsi.h
+ROOTHDRDIR = $(ROOTSCSIHDRDIR)
+ROOTHDRS = $(HDRS:%=$(ROOTHDRDIR)/%)
+CHECKDIRS = $(HDRS:%.h=%.check)
+HDRDIR = common
+
+SUBDIRS = $(MACH)
+$(BUILD64)SUBDIRS += $(MACH64)
+
+all := TARGET= all
+clean := TARGET= clean
+clobber := TARGET= clobber
+install := TARGET= install
+lint := TARGET= lint
+install_h:= TARGET = install_h
+
+.KEEP_STATE:
+
+all install clean clobber lint: $(SUBDIRS)
+
+install_h: $(ROOTHDRS)
+
+check: $(CHECKHDRS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+include ../Makefile.rootdirs
+include ../../Makefile.targ
diff --git a/usr/src/lib/scsi/libscsi/Makefile.com b/usr/src/lib/scsi/libscsi/Makefile.com
new file mode 100644
index 0000000000..88e3f7fa4c
--- /dev/null
+++ b/usr/src/lib/scsi/libscsi/Makefile.com
@@ -0,0 +1,71 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+LIBRARY = libscsi.a
+VERS = .1
+
+OBJECTS = \
+ scsi_engine.o \
+ scsi_errno.o \
+ scsi_status.o \
+ scsi_subr.o
+
+include ../../../Makefile.lib
+include ../../Makefile.defs
+
+SRCS = $(OBJECTS:%.o=../common/%.c)
+C99MODE = $(C99_ENABLE)
+CPPFLAGS += -I../common -I. -D_REENTRANT
+$(NOT_RELEASE_BUILD)CPPFLAGS += -DDEBUG
+CFLAGS += $(CCVERBOSE)
+LDLIBS += \
+ -lumem \
+ -lc
+LIBS = $(DYNLIB) $(LINTLIB)
+ROOTLIBDIR = $(ROOTSCSILIBDIR)
+ROOTLIBDIR64 = $(ROOTSCSILIBDIR)/$(MACH64)
+
+CLEANFILES += \
+ ../common/scsi_errno.c
+
+$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC)
+
+.KEEP_STATE:
+
+all : $(LIBS)
+
+lint : lintcheck
+
+../common/scsi_errno.c: ../common/mkerrno.sh ../common/libscsi.h
+ sh ../common/mkerrno.sh < ../common/libscsi.h > $@
+
+pics/%.o: ../common/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+include ../../../Makefile.targ
+include ../../Makefile.rootdirs
diff --git a/usr/src/lib/scsi/libscsi/amd64/Makefile b/usr/src/lib/scsi/libscsi/amd64/Makefile
new file mode 100644
index 0000000000..e3fab7e838
--- /dev/null
+++ b/usr/src/lib/scsi/libscsi/amd64/Makefile
@@ -0,0 +1,31 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+include ../../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
diff --git a/usr/src/lib/scsi/libscsi/common/libscsi.h b/usr/src/lib/scsi/libscsi/common/libscsi.h
new file mode 100644
index 0000000000..748913ee1e
--- /dev/null
+++ b/usr/src/lib/scsi/libscsi/common/libscsi.h
@@ -0,0 +1,182 @@
+/*
+ * 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.
+ */
+
+#ifndef _LIBSCSI_H
+#define _LIBSCSI_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <sys/sysmacros.h>
+#include <sys/scsi/impl/spc3_types.h>
+#include <stdarg.h>
+
+#define LIBSCSI_VERSION 1
+#define LIBSCSI_STATUS_INVALID ((sam4_status_t)-1)
+#define LIBSCSI_DEFAULT_ENGINE_PATH "/usr/lib/scsi/plugins/scsi/engines"
+#define LIBSCSI_DEFAULT_ENGINE "uscsi"
+
+/*
+ * Flags for action creation. Selected to avoid overlap with the uscsi
+ * flags with similar or identical meaning.
+ */
+#define LIBSCSI_AF_READ 0x80000000
+#define LIBSCSI_AF_WRITE 0x40000000
+#define LIBSCSI_AF_SILENT 0x20000000
+#define LIBSCSI_AF_DIAGNOSE 0x10000000
+#define LIBSCSI_AF_ISOLATE 0x08000000
+#define LIBSCSI_AF_RQSENSE 0x04000000
+
+typedef enum libscsi_errno {
+ ESCSI_NONE, /* no error */
+ ESCSI_NOMEM, /* no memory */
+ ESCSI_ZERO_LENGTH, /* zero-length allocation requested */
+ ESCSI_VERSION, /* library version mismatch */
+ ESCSI_BADTARGET, /* invalid target specification */
+ ESCSI_BADCMD, /* invalid SCSI command */
+ ESCSI_BADENGINE, /* engine library corrupt */
+ ESCSI_NOENGINE, /* engine library not found */
+ ESCSI_ENGINE_INIT, /* engine initialization failed */
+ ESCSI_ENGINE_VER, /* engine version mismatch */
+ ESCSI_ENGINE_BADPATH, /* engine path contains no usable components */
+ ESCSI_BADFLAGS, /* incorrect action flags */
+ ESCSI_BOGUSFLAGS, /* unknown flag value */
+ ESCSI_BADLENGTH, /* buffer length overflow */
+ ESCSI_NEEDBUF, /* missing required buffer */
+ ESCSI_IO, /* I/O operation failed */
+ ESCSI_SYS, /* system call failed */
+ ESCSI_PERM, /* insufficient permissions */
+ ESCSI_RANGE, /* parameter outside valid range */
+ ESCSI_NOTSUP, /* operation not supported */
+ ESCSI_UNKNOWN, /* error of unknown type */
+ ESCSI_INQUIRY_FAILED, /* initial inquiry command failed */
+ ESCSI_MAX /* maximum libscsi errno value */
+} libscsi_errno_t;
+
+struct libscsi_hdl;
+typedef struct libscsi_hdl libscsi_hdl_t;
+
+struct libscsi_target;
+typedef struct libscsi_target libscsi_target_t;
+
+typedef struct libscsi_status {
+ uint64_t lss_status; /* SCSI status of this command */
+ size_t lss_sense_len; /* Length in bytes of sense data */
+ uint8_t *lss_sense_data; /* Pointer to sense data */
+} libscsi_status_t;
+
+struct libscsi_action;
+typedef struct libscsi_action libscsi_action_t;
+
+struct libscsi_result;
+typedef struct libscsi_result libscsi_result_t;
+
+typedef struct libscsi_engine_ops {
+ void *(*lseo_open)(libscsi_hdl_t *, const void *);
+ void (*lseo_close)(libscsi_hdl_t *, void *);
+ int (*lseo_exec)(libscsi_hdl_t *, void *, libscsi_action_t *);
+ void (*lseo_target_name)(libscsi_hdl_t *, void *, char *, size_t);
+} libscsi_engine_ops_t;
+
+typedef struct libscsi_engine {
+ const char *lse_name;
+ uint_t lse_libversion;
+ const libscsi_engine_ops_t *lse_ops;
+} libscsi_engine_t;
+
+extern libscsi_hdl_t *libscsi_init(uint_t, libscsi_errno_t *);
+extern void libscsi_fini(libscsi_hdl_t *);
+
+extern libscsi_target_t *libscsi_open(libscsi_hdl_t *, const char *,
+ const void *);
+extern void libscsi_close(libscsi_hdl_t *, libscsi_target_t *);
+extern libscsi_hdl_t *libscsi_get_handle(libscsi_target_t *);
+
+extern const char *libscsi_vendor(libscsi_target_t *);
+extern const char *libscsi_product(libscsi_target_t *);
+extern const char *libscsi_revision(libscsi_target_t *);
+
+extern libscsi_errno_t libscsi_errno(libscsi_hdl_t *);
+extern const char *libscsi_errmsg(libscsi_hdl_t *);
+extern const char *libscsi_strerror(libscsi_errno_t);
+extern const char *libscsi_errname(libscsi_errno_t);
+extern libscsi_errno_t libscsi_errcode(const char *);
+
+extern libscsi_action_t *libscsi_action_alloc(libscsi_hdl_t *, spc3_cmd_t,
+ uint_t, void *, size_t);
+extern sam4_status_t libscsi_action_get_status(const libscsi_action_t *);
+extern void libscsi_action_set_timeout(libscsi_action_t *, uint32_t);
+extern uint32_t libscsi_action_get_timeout(const libscsi_action_t *);
+extern uint_t libscsi_action_get_flags(const libscsi_action_t *);
+extern uint8_t *libscsi_action_get_cdb(const libscsi_action_t *);
+extern int libscsi_action_get_buffer(const libscsi_action_t *,
+ uint8_t **, size_t *, size_t *);
+extern int libscsi_action_get_sense(const libscsi_action_t *,
+ uint8_t **, size_t *, size_t *);
+extern int libscsi_action_parse_sense(const libscsi_action_t *, uint64_t *,
+ uint64_t *, uint64_t *, diskaddr_t *);
+extern void libscsi_action_set_status(libscsi_action_t *, sam4_status_t);
+extern int libscsi_action_set_datalen(libscsi_action_t *, size_t);
+extern int libscsi_action_set_senselen(libscsi_action_t *, size_t);
+extern int libscsi_exec(libscsi_action_t *, libscsi_target_t *);
+extern void libscsi_action_free(libscsi_action_t *);
+
+extern const char *libscsi_sense_key_name(uint64_t);
+extern const char *libscsi_sense_code_name(uint64_t, uint64_t);
+
+/*
+ * Interfaces for engine providers
+ */
+extern void *libscsi_alloc(libscsi_hdl_t *, size_t);
+extern void *libscsi_zalloc(libscsi_hdl_t *, size_t);
+extern char *libscsi_strdup(libscsi_hdl_t *, const char *);
+extern void libscsi_free(libscsi_hdl_t *, void *);
+extern libscsi_status_t *libscsi_status_alloc(libscsi_hdl_t *, size_t);
+extern int libscsi_status_fill(libscsi_hdl_t *, libscsi_status_t *,
+ uint16_t, size_t);
+extern void libscsi_status_free(libscsi_hdl_t *, libscsi_status_t *);
+
+extern int libscsi_set_errno(libscsi_hdl_t *, libscsi_errno_t);
+extern int libscsi_verror(libscsi_hdl_t *, libscsi_errno_t, const char *,
+ va_list);
+extern int libscsi_error(libscsi_hdl_t *, libscsi_errno_t, const char *, ...);
+
+typedef const libscsi_engine_t *(*libscsi_engine_init_f)(libscsi_hdl_t *);
+
+/*
+ * Generic SCSI utility functions.
+ */
+extern size_t libscsi_cmd_cdblen(libscsi_hdl_t *, uint8_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBSCSI_H */
diff --git a/usr/src/lib/scsi/libscsi/common/libscsi_impl.h b/usr/src/lib/scsi/libscsi/common/libscsi_impl.h
new file mode 100644
index 0000000000..c34879dab4
--- /dev/null
+++ b/usr/src/lib/scsi/libscsi/common/libscsi_impl.h
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+
+#ifndef _LIBSCSI_IMPL_H
+#define _LIBSCSI_IMPL_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <libscsi.h>
+
+#define LIBSCSI_ENGINE_EXT ".so"
+
+#define LIBSCSI_ERRMSGLEN 512
+
+typedef struct libscsi_engine_impl {
+ const libscsi_engine_t *lsei_engine;
+ void *lsei_dl_hdl;
+ struct libscsi_engine_impl *lsei_next;
+} libscsi_engine_impl_t;
+
+typedef struct libscsi_action_impl {
+ libscsi_hdl_t *lsai_hdl;
+ uint_t lsai_flags;
+ uint32_t lsai_timeout;
+ uint8_t *lsai_cdb;
+ size_t lsai_cdb_len;
+ size_t lsai_data_len;
+ size_t lsai_data_alloc;
+ uint8_t *lsai_data;
+ sam4_status_t lsai_status;
+ size_t lsai_sense_len;
+ uint8_t *lsai_sense_data;
+ uint8_t lsai_buf[1];
+} libscsi_action_impl_t;
+
+struct libscsi_hdl {
+ uint_t lsh_version;
+ libscsi_errno_t lsh_errno;
+ char lsh_errmsg[LIBSCSI_ERRMSGLEN];
+ libscsi_engine_impl_t *lsh_engines;
+ uint_t lsh_targets;
+};
+
+struct libscsi_target {
+ const libscsi_engine_t *lst_engine;
+ char *lst_vendor;
+ char *lst_product;
+ char *lst_revision;
+ void *lst_priv;
+ uint_t lst_mtbf_cdb;
+ uint_t lst_mtbf_read;
+ uint_t lst_mtbf_write;
+ struct libscsi_hdl *lst_hdl;
+};
+
+#define VERIFY(x) ((void)((x) || libscsi_assert(#x, __FILE__, __LINE__)))
+
+#ifdef DEBUG
+#define ASSERT(x) VERIFY(x)
+#else
+#define ASSERT(x)
+#endif
+
+#define LXOR(l, r) (((l) != 0) ^ ((r) != 0))
+
+extern int libscsi_assert(const char *, const char *, int);
+extern int libscsi_get_inquiry(struct libscsi_hdl *, struct libscsi_target *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBSCSI_IMPL_H */
diff --git a/usr/src/lib/scsi/libscsi/common/mkerrno.sh b/usr/src/lib/scsi/libscsi/common/mkerrno.sh
new file mode 100644
index 0000000000..604c63e643
--- /dev/null
+++ b/usr/src/lib/scsi/libscsi/common/mkerrno.sh
@@ -0,0 +1,88 @@
+#!/bin/sh
+#
+# 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.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+echo "\
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident\t\"%Z%%M%\t%I%\t%E%\tSMI\"
+
+#include <strings.h>
+#include <scsi/libscsi.h>
+
+static const struct {
+\tchar *name;\t\t/* error name */
+\tchar *msg;\t\t/* error message */
+} _libscsi_errstr[] = {"
+
+pattern='^ \(ESCSI_[A-Z0-9_]*\),*'
+replace=' { "\1",'
+open=' \/\* '
+openrepl='"'
+close=' \*\/$'
+closerepl='" },'
+
+( sed -n "s/$pattern/$replace/p" | sed -n "s/$open/$openrepl/p" |
+ sed -n "s/$close/$closerepl/p" ) || exit 1
+
+echo "\
+};\n\
+\n\
+static int _libscsi_nerrno = sizeof (_libscsi_errstr) /\n\
+ sizeof (_libscsi_errstr[0]);\n\
+\n\
+const char *
+libscsi_strerror(libscsi_errno_t err)
+{
+ return (err < 0 || err >= _libscsi_nerrno ? \"unknown error\" :
+ _libscsi_errstr[err].msg);
+}
+
+const char *
+libscsi_errname(libscsi_errno_t err)
+{
+ return (err < 0 || err >= _libscsi_nerrno ? NULL :
+ _libscsi_errstr[err].name);
+}
+
+libscsi_errno_t
+libscsi_errcode(const char *name)
+{
+ libscsi_errno_t err;
+
+ for (err = 0; err < _libscsi_nerrno; err++) {
+ if (strcmp(name, _libscsi_errstr[err].name) == 0)
+ return (err);
+ }
+
+ return (ESCSI_UNKNOWN);
+}"
+
+exit 0
diff --git a/usr/src/lib/scsi/libscsi/common/scsi_engine.c b/usr/src/lib/scsi/libscsi/common/scsi_engine.c
new file mode 100644
index 0000000000..df221eea55
--- /dev/null
+++ b/usr/src/lib/scsi/libscsi/common/scsi_engine.c
@@ -0,0 +1,621 @@
+/*
+ * 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"
+
+#include <sys/types.h>
+#include <sys/isa_defs.h>
+#include <sys/systeminfo.h>
+#include <sys/scsi/generic/commands.h>
+#include <sys/scsi/impl/commands.h>
+#include <sys/scsi/impl/uscsi.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <limits.h>
+
+#include <scsi/libscsi.h>
+#include "libscsi_impl.h"
+
+static const libscsi_engine_t *
+get_engine(libscsi_hdl_t *hp, const char *name)
+{
+ libscsi_engine_impl_t *eip;
+ const libscsi_engine_t *ep;
+ const char *engine_path, *p, *q;
+ char engine_dir[MAXPATHLEN];
+ char engine_lib[MAXPATHLEN];
+ char init_name[MAXPATHLEN];
+ void *dl_hdl;
+ libscsi_engine_init_f init;
+ boolean_t found_lib = B_FALSE, found_init = B_FALSE;
+ int dirs_tried = 0;
+ char isa[257];
+
+ for (eip = hp->lsh_engines; eip != NULL; eip = eip->lsei_next) {
+ if (strcmp(eip->lsei_engine->lse_name, name) == 0)
+ return (eip->lsei_engine);
+ }
+
+ if ((engine_path = getenv("LIBSCSI_ENGINE_PATH")) == NULL)
+ engine_path = LIBSCSI_DEFAULT_ENGINE_PATH;
+
+#if defined(_LP64)
+ if (sysinfo(SI_ARCHITECTURE_64, isa, sizeof (isa)) < 0)
+ isa[0] = '\0';
+#else
+ isa[0] = '\0';
+#endif
+
+ for (p = engine_path, q = strchr(p, ':'); p != NULL; p = q) {
+ if (q != NULL) {
+ ptrdiff_t len = q - p;
+ (void) strncpy(engine_dir, p, len);
+ engine_dir[len] = '\0';
+ while (*q == ':')
+ ++q;
+ if (*q == '\0')
+ q = NULL;
+ if (len == 0)
+ continue;
+ } else {
+ (void) strcpy(engine_dir, p);
+ }
+ if (engine_dir[0] != '/')
+ continue;
+
+ ++dirs_tried;
+
+ (void) snprintf(engine_lib, MAXPATHLEN, "%s/%s/%s%s",
+ engine_dir, isa, name, LIBSCSI_ENGINE_EXT);
+
+ dl_hdl = dlopen(engine_lib,
+ RTLD_LOCAL | RTLD_LAZY | RTLD_PARENT);
+ if (dl_hdl == NULL) {
+ if (!found_lib)
+ (void) libscsi_error(hp, ESCSI_NOENGINE,
+ "unable to dlopen %s: %s", engine_lib,
+ dlerror());
+ continue;
+ }
+ found_lib = B_TRUE;
+ (void) snprintf(init_name, MAXPATHLEN, "libscsi_%s_init", name);
+ init = (libscsi_engine_init_f)dlsym(dl_hdl, init_name);
+ if (init == NULL) {
+ if (!found_init)
+ (void) libscsi_error(hp, ESCSI_NOENGINE,
+ "failed to find %s in %s: %s", init_name,
+ engine_lib, dlerror());
+ (void) dlclose(dl_hdl);
+ continue;
+ }
+ if ((ep = init(hp)) == NULL) {
+ (void) dlclose(dl_hdl);
+ /*
+ * libscsi errno set by init.
+ */
+ return (NULL);
+ }
+ if (ep->lse_libversion != hp->lsh_version) {
+ (void) dlclose(dl_hdl);
+ (void) libscsi_error(hp, ESCSI_ENGINE_VER, "engine "
+ "%s version %u does not match library version %u",
+ engine_lib, ep->lse_libversion, hp->lsh_version);
+ return (NULL);
+ }
+
+ eip = libscsi_zalloc(hp, sizeof (libscsi_engine_impl_t));
+ if (eip == NULL) {
+ (void) dlclose(dl_hdl);
+ return (NULL);
+ }
+ eip->lsei_engine = ep;
+ eip->lsei_dl_hdl = dl_hdl;
+ eip->lsei_next = hp->lsh_engines;
+ hp->lsh_engines = eip;
+
+ return (ep);
+ }
+
+ if (dirs_tried == 0)
+ (void) libscsi_error(hp, ESCSI_ENGINE_BADPATH, "no valid "
+ "directories found in engine path %s", engine_path);
+
+ return (NULL);
+}
+
+static void
+scsi_parse_mtbf(const char *envvar, uint_t *intp)
+{
+ const char *strval;
+ int intval;
+
+ if ((strval = getenv(envvar)) != NULL &&
+ (intval = atoi(strval)) > 0) {
+ srand48(gethrtime());
+ *intp = intval;
+ }
+}
+
+libscsi_target_t *
+libscsi_open(libscsi_hdl_t *hp, const char *engine, const void *target)
+{
+ const libscsi_engine_t *ep;
+ libscsi_target_t *tp;
+ void *private;
+
+ if (engine == NULL) {
+ if ((engine = getenv("LIBSCSI_DEFAULT_ENGINE")) == NULL)
+ engine = LIBSCSI_DEFAULT_ENGINE;
+ }
+
+ if ((ep = get_engine(hp, engine)) == NULL)
+ return (NULL);
+
+ if ((tp = libscsi_zalloc(hp, sizeof (libscsi_target_t))) == NULL)
+ return (NULL);
+
+ if ((private = ep->lse_ops->lseo_open(hp, target)) == NULL) {
+ libscsi_free(hp, tp);
+ return (NULL);
+ }
+
+ scsi_parse_mtbf("LIBSCSI_MTBF_CDB", &tp->lst_mtbf_cdb);
+ scsi_parse_mtbf("LIBSCSI_MTBF_READ", &tp->lst_mtbf_read);
+ scsi_parse_mtbf("LIBSCSI_MTBF_WRITE", &tp->lst_mtbf_write);
+
+ tp->lst_hdl = hp;
+ tp->lst_engine = ep;
+ tp->lst_priv = private;
+
+ ++hp->lsh_targets;
+
+ if (libscsi_get_inquiry(hp, tp) != 0) {
+ libscsi_close(hp, tp);
+ return (NULL);
+ }
+
+ return (tp);
+}
+
+libscsi_hdl_t *
+libscsi_get_handle(libscsi_target_t *tp)
+{
+ return (tp->lst_hdl);
+}
+
+void
+libscsi_close(libscsi_hdl_t *hp, libscsi_target_t *tp)
+{
+ tp->lst_engine->lse_ops->lseo_close(hp, tp->lst_priv);
+ libscsi_free(hp, tp->lst_vendor);
+ libscsi_free(hp, tp->lst_product);
+ libscsi_free(hp, tp->lst_revision);
+ libscsi_free(hp, tp);
+ --hp->lsh_targets;
+}
+
+sam4_status_t
+libscsi_action_get_status(const libscsi_action_t *ap)
+{
+ const libscsi_action_impl_t *aip = (const libscsi_action_impl_t *)ap;
+
+ return (aip->lsai_status);
+}
+
+/*
+ * Set the timeout in seconds for this action. If no timeout is specified
+ * or if the timeout is set to 0, an implementation-specific timeout will be
+ * used (which may vary based on the target, command or other variables).
+ * Not all engines support all timeout values. Setting the timeout to a value
+ * not supported by the engine will cause engine-defined behavior when the
+ * action is executed.
+ */
+void
+libscsi_action_set_timeout(libscsi_action_t *ap, uint32_t timeout)
+{
+ libscsi_action_impl_t *aip = (libscsi_action_impl_t *)ap;
+
+ aip->lsai_timeout = timeout;
+}
+
+/*
+ * Obtain the timeout setting for this action.
+ */
+uint32_t
+libscsi_action_get_timeout(const libscsi_action_t *ap)
+{
+ const libscsi_action_impl_t *aip = (const libscsi_action_impl_t *)ap;
+
+ return (aip->lsai_timeout);
+}
+
+/*
+ * Returns the flags associated with this action. Never fails.
+ */
+uint_t
+libscsi_action_get_flags(const libscsi_action_t *ap)
+{
+ const libscsi_action_impl_t *aip = (const libscsi_action_impl_t *)ap;
+
+ return (aip->lsai_flags);
+}
+
+/*
+ * Returns the address of the action's CDB. The CDB buffer is guaranteed to
+ * be large enough to hold the complete CDB for the command specified when the
+ * action was allocated. Therefore, changing the command/opcode portion of
+ * the CDB has undefined effects. The remainder of the CDB may be modified.
+ */
+uint8_t *
+libscsi_action_get_cdb(const libscsi_action_t *ap)
+{
+ const libscsi_action_impl_t *aip = (const libscsi_action_impl_t *)ap;
+
+ return (aip->lsai_cdb);
+}
+
+/*
+ * Places the address of the action buffer in the location pointed to by bp,
+ * if bp is not NULL. If ap is not NULL, it will contain the allocated size
+ * of the buffer itself. If vp is not NULL, it will contain the number of
+ * bytes of valid data currently stored in the buffer.
+ *
+ * If the action has LIBSCSI_AF_WRITE set and it has not yet been executed
+ * successfully, the entire buffer is assumed to contain valid data.
+ *
+ * If the action has LIBSCSI_AF_READ set and it has not yet been executed
+ * successfully, the amount of valid data is 0.
+ *
+ * If both LIBSCSI_AF_READ and LIBSCSI_AF_WRITE are clear, this function
+ * fails with ESCSI_BADFLAGS to indicate that the action flags are
+ * incompatible with the action data buffer.
+ */
+int
+libscsi_action_get_buffer(const libscsi_action_t *ap, uint8_t **bp,
+ size_t *sp, size_t *vp)
+{
+ const libscsi_action_impl_t *aip = (const libscsi_action_impl_t *)ap;
+
+ if ((aip->lsai_flags & (LIBSCSI_AF_READ | LIBSCSI_AF_WRITE)) == 0)
+ return (libscsi_error(aip->lsai_hdl, ESCSI_BADFLAGS,
+ "data buffer not supported for actions with both "
+ "LIBSCSI_AF_READ and LIBSCSI_AF_WRITE clear"));
+
+ if ((aip->lsai_flags & LIBSCSI_AF_WRITE) &&
+ aip->lsai_status == LIBSCSI_STATUS_INVALID) {
+ if (bp != NULL)
+ *bp = aip->lsai_data;
+ if (sp != NULL)
+ *sp = aip->lsai_data_alloc;
+ if (vp != NULL)
+ *vp = aip->lsai_data_alloc;
+
+ return (0);
+ }
+
+ if ((aip->lsai_flags & LIBSCSI_AF_READ) &&
+ aip->lsai_status != LIBSCSI_STATUS_INVALID) {
+ if (bp != NULL)
+ *bp = aip->lsai_data;
+ if (sp != NULL)
+ *sp = aip->lsai_data_alloc;
+ if (vp != NULL)
+ *vp = aip->lsai_data_len;
+
+ return (0);
+ }
+
+ if (aip->lsai_flags & LIBSCSI_AF_WRITE) {
+ if (bp != NULL)
+ *bp = NULL;
+ if (sp != NULL)
+ *sp = NULL;
+ if (vp != NULL)
+ *vp = 0;
+ } else {
+ if (bp != NULL)
+ *bp = aip->lsai_data;
+ if (sp != NULL)
+ *sp = aip->lsai_data_alloc;
+ if (vp != NULL)
+ *vp = 0;
+ }
+
+ return (0);
+}
+
+/*
+ * Obtain a pointer to the sense buffer for this action, if any, along with
+ * the size of the sense buffer and the amount of valid data it contains.
+ */
+int
+libscsi_action_get_sense(const libscsi_action_t *ap, uint8_t **bp,
+ size_t *sp, size_t *vp)
+{
+ const libscsi_action_impl_t *aip = (const libscsi_action_impl_t *)ap;
+
+ if (!(aip->lsai_flags & LIBSCSI_AF_RQSENSE))
+ return (libscsi_error(aip->lsai_hdl, ESCSI_BADFLAGS,
+ "sense data unavailable: LIBSCSI_AF_RQSENSE is clear"));
+
+ if (vp != NULL) {
+ if (aip->lsai_status == LIBSCSI_STATUS_INVALID)
+ *vp = 0;
+ else
+ *vp = aip->lsai_sense_len;
+ }
+
+ if (bp != NULL) {
+ ASSERT(aip->lsai_sense_data != NULL);
+ *bp = aip->lsai_sense_data;
+ }
+
+ if (sp != NULL)
+ *sp = UINT8_MAX;
+
+ return (0);
+}
+
+/*
+ * Set the SCSI status of the action.
+ *
+ * Engines only.
+ */
+void
+libscsi_action_set_status(libscsi_action_t *ap, sam4_status_t status)
+{
+ libscsi_action_impl_t *aip = (libscsi_action_impl_t *)ap;
+
+ ASSERT(aip->lsai_status == LIBSCSI_STATUS_INVALID);
+
+ aip->lsai_status = status;
+}
+
+/*
+ * Set the length of valid data returned by a READ action. If the action is
+ * not a READ action, or the length exceeds the size of the buffer, an error
+ * results.
+ *
+ * Engines only.
+ */
+int
+libscsi_action_set_datalen(libscsi_action_t *ap, size_t len)
+{
+ libscsi_action_impl_t *aip = (libscsi_action_impl_t *)ap;
+
+ if ((aip->lsai_flags & LIBSCSI_AF_READ) == 0)
+ return (libscsi_error(aip->lsai_hdl, ESCSI_BADFLAGS,
+ "data cannot be returned for actions with LIBSCSI_AF_READ "
+ "clear"));
+ if (len > aip->lsai_data_alloc)
+ return (libscsi_error(aip->lsai_hdl, ESCSI_BADLENGTH,
+ "data length %lu exceeds allocated buffer capacity %lu",
+ (ulong_t)len, (ulong_t)aip->lsai_data_alloc));
+
+ ASSERT(aip->lsai_data_len == 0);
+ aip->lsai_data_len = len;
+
+ return (0);
+}
+
+/*
+ * Set the length of the valid sense data returned following the command, if
+ * LIBSCSI_AF_RQSENSE is set for this action. Otherwise, fail.
+ *
+ * Engines only.
+ */
+int
+libscsi_action_set_senselen(libscsi_action_t *ap, size_t len)
+{
+ libscsi_action_impl_t *aip = (libscsi_action_impl_t *)ap;
+
+ if (!(aip->lsai_flags & LIBSCSI_AF_RQSENSE))
+ return (libscsi_error(aip->lsai_hdl, ESCSI_BADFLAGS,
+ "sense data not supported: LIBSCSI_AF_RQSENSE is clear"));
+
+ if (len > UINT8_MAX)
+ return (libscsi_error(aip->lsai_hdl, ESCSI_BADLENGTH,
+ "sense length %lu exceeds allocated buffer capacity %lu",
+ (ulong_t)len, (ulong_t)UINT8_MAX));
+
+ ASSERT(aip->lsai_sense_len == 0);
+ aip->lsai_sense_len = len;
+
+ return (0);
+}
+
+/*
+ * Allocate an action object. The object will contain a CDB area sufficiently
+ * large to hold a CDB for the given command, and the CDB's opcode will be
+ * filled in. A pointer to this CDB, the contents of which may be modified by
+ * the caller, may be obtained by a subsequent call to libscsi_action_cdb().
+ *
+ * If flags includes LIBSCSI_AF_READ or LIBSCSI_AF_WRITE, buflen must be
+ * greater than zero. Otherwise, buflen must be 0 and buf must be NULL.
+ * If buflen is nonzero but buf is NULL, a suitably-sized buffer will be
+ * allocated; otherwise, the specified buffer will be used. In either case,
+ * a pointer to the buffer may be obtained via a subsequent call to
+ * libscsi_action_buffer().
+ *
+ * If flags includes LIBSCSI_AF_RQSENSE, a REQUEST SENSE command will be
+ * issued immediately following the termination of the specified command.
+ * A buffer will be allocated to receive this sense data. Following successful
+ * execution of the action, a pointer to this buffer and the length of
+ * valid sense data may be obtained by a call to libscsi_action_sense().
+ * If cmd is SPC3_CMD_REQUEST_SENSE, this flag must be clear.
+ */
+libscsi_action_t *
+libscsi_action_alloc(libscsi_hdl_t *hp, spc3_cmd_t cmd, uint_t flags,
+ void *buf, size_t buflen)
+{
+ libscsi_action_impl_t *aip;
+ size_t cdbsz, sz;
+ ptrdiff_t off;
+
+ /*
+ * If there's no buffer, it makes no sense to try to read or write
+ * data. Likewise, if we're neither reading nor writing data, we
+ * should not have a buffer. Both of these are programmer error.
+ */
+ if (buflen == 0 && (flags & (LIBSCSI_AF_READ | LIBSCSI_AF_WRITE))) {
+ (void) libscsi_error(hp, ESCSI_NEEDBUF, "a buffer is "
+ "required when reading or writing");
+ return (NULL);
+ }
+ if (buflen > 0 && !(flags & (LIBSCSI_AF_READ | LIBSCSI_AF_WRITE))) {
+ (void) libscsi_error(hp, ESCSI_BADFLAGS, "one of "
+ "LIBSCSI_AF_READ and LIBSCSI_AF_WRITE must be specified "
+ "in order to use a buffer");
+ return (NULL);
+ }
+ if (cmd == SPC3_CMD_REQUEST_SENSE && (flags & LIBSCSI_AF_RQSENSE)) {
+ (void) libscsi_error(hp, ESCSI_BADFLAGS, "request sense "
+ "flag not allowed for request sense command");
+ return (NULL);
+ }
+
+ if ((sz = cdbsz = libscsi_cmd_cdblen(hp, cmd)) == 0)
+ return (NULL);
+
+ /*
+ * If the caller has asked for a buffer but has not provided one, we
+ * will allocate it in our internal buffer along with the CDB and
+ * request sense space (if requested).
+ */
+ if (buf == NULL)
+ sz += buflen;
+
+ if (flags & LIBSCSI_AF_RQSENSE)
+ sz += UINT8_MAX;
+
+ sz += offsetof(libscsi_action_impl_t, lsai_buf[0]);
+
+ if ((aip = libscsi_zalloc(hp, sz)) == NULL)
+ return (NULL);
+
+ aip->lsai_hdl = hp;
+ aip->lsai_flags = flags;
+
+ off = 0;
+
+ aip->lsai_cdb = aip->lsai_buf + off;
+ aip->lsai_cdb_len = cdbsz;
+ off += cdbsz;
+ aip->lsai_cdb[0] = (uint8_t)cmd;
+
+ if (buflen > 0) {
+ if (buf != NULL) {
+ aip->lsai_data = buf;
+ } else {
+ aip->lsai_data = aip->lsai_buf + off;
+ off += buflen;
+ }
+ aip->lsai_data_alloc = buflen;
+ if (flags & LIBSCSI_AF_WRITE)
+ aip->lsai_data_len = buflen;
+ }
+
+ if (flags & LIBSCSI_AF_RQSENSE) {
+ aip->lsai_sense_data = aip->lsai_buf + off;
+ off += UINT8_MAX;
+ }
+
+ aip->lsai_status = LIBSCSI_STATUS_INVALID;
+
+ return ((libscsi_action_t *)aip);
+}
+
+void
+libscsi_action_free(libscsi_action_t *ap)
+{
+ libscsi_action_impl_t *aip = (libscsi_action_impl_t *)ap;
+
+ libscsi_free(aip->lsai_hdl, aip);
+}
+
+/*
+ * For testing purposes, we allow data to be corrupted via an environment
+ * variable setting. This helps ensure that higher level software can cope with
+ * arbitrarily broken targets. The mtbf value represents the number of bytes we
+ * will see, on average, in between each failure. Therefore, for each N bytes,
+ * we would expect to see (N / mtbf) bytes of corruption.
+ */
+static void
+scsi_inject_errors(void *data, size_t len, uint_t mtbf)
+{
+ char *buf = data;
+ double prob;
+ size_t index;
+
+ if (len == 0)
+ return;
+
+ prob = (double)len / mtbf;
+
+ while (prob > 1) {
+ index = lrand48() % len;
+ buf[index] = (lrand48() % 256);
+ prob -= 1;
+ }
+
+ if (drand48() <= prob) {
+ index = lrand48() % len;
+ buf[index] = (lrand48() % 256);
+ }
+}
+
+int
+libscsi_exec(libscsi_action_t *ap, libscsi_target_t *tp)
+{
+ libscsi_action_impl_t *aip = (libscsi_action_impl_t *)ap;
+ libscsi_hdl_t *hp = aip->lsai_hdl;
+ int ret;
+
+ if (tp->lst_mtbf_write != 0 &&
+ (aip->lsai_flags & LIBSCSI_AF_WRITE)) {
+ scsi_inject_errors(aip->lsai_data, aip->lsai_data_len,
+ tp->lst_mtbf_write);
+ }
+
+ if (tp->lst_mtbf_cdb != 0) {
+ scsi_inject_errors(aip->lsai_cdb, aip->lsai_cdb_len,
+ tp->lst_mtbf_cdb);
+ }
+
+ ret = tp->lst_engine->lse_ops->lseo_exec(hp, tp->lst_priv, ap);
+
+ if (ret == 0 && tp->lst_mtbf_read != 0 &&
+ (aip->lsai_flags & LIBSCSI_AF_READ)) {
+ scsi_inject_errors(aip->lsai_data, aip->lsai_data_len,
+ tp->lst_mtbf_read);
+ }
+
+ return (ret);
+}
diff --git a/usr/src/lib/scsi/libscsi/common/scsi_status.c b/usr/src/lib/scsi/libscsi/common/scsi_status.c
new file mode 100644
index 0000000000..ab6b23b72b
--- /dev/null
+++ b/usr/src/lib/scsi/libscsi/common/scsi_status.c
@@ -0,0 +1,723 @@
+/*
+ * 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"
+
+#include <sys/types.h>
+#include <sys/scsi/generic/sense.h>
+#include <sys/scsi/generic/status.h>
+
+#include <stddef.h>
+#include <stdio.h>
+
+#include <scsi/libscsi.h>
+#include "libscsi_impl.h"
+
+typedef struct slist {
+ char *str;
+ int value;
+} slist_t;
+
+static slist_t sensekey_strings[] = {
+ { "No sense error", KEY_NO_SENSE },
+ { "Recoverable error", KEY_RECOVERABLE_ERROR },
+ { "Not ready error", KEY_NOT_READY },
+ { "Medium error", KEY_MEDIUM_ERROR },
+ { "Hardware error", KEY_HARDWARE_ERROR },
+ { "Illegal request", KEY_ILLEGAL_REQUEST },
+ { "Unit attention error", KEY_UNIT_ATTENTION },
+ { "Write protect error", KEY_WRITE_PROTECT },
+ { "Blank check error", KEY_BLANK_CHECK },
+ { "Vendor unique error", KEY_VENDOR_UNIQUE },
+ { "Copy aborted error", KEY_COPY_ABORTED },
+ { "Aborted command", KEY_ABORTED_COMMAND },
+ { "Equal error", KEY_EQUAL },
+ { "Volume overflow", KEY_VOLUME_OVERFLOW },
+ { "Miscompare error", KEY_MISCOMPARE },
+ { "Reserved error", KEY_RESERVED },
+ { NULL, 0 }
+};
+
+static struct asq_key_strings {
+ uint_t asc;
+ uint_t ascq;
+ const char *message;
+} extended_sense_list[] = {
+ { 0x00, 0x00, "no additional sense info" },
+ { 0x00, 0x01, "filemark detected" },
+ { 0x00, 0x02, "end of partition/medium detected" },
+ { 0x00, 0x03, "setmark detected" },
+ { 0x00, 0x04, "begining of partition/medium detected" },
+ { 0x00, 0x05, "end of data detected" },
+ { 0x00, 0x06, "i/o process terminated" },
+ { 0x00, 0x11, "audio play operation in progress" },
+ { 0x00, 0x12, "audio play operation paused" },
+ { 0x00, 0x13, "audio play operation successfully completed" },
+ { 0x00, 0x14, "audio play operation stopped due to error" },
+ { 0x00, 0x15, "no current audio status to return" },
+ { 0x00, 0x16, "operation in progress" },
+ { 0x00, 0x17, "cleaning requested" },
+ { 0x00, 0x18, "erase operation in progress" },
+ { 0x00, 0x19, "locate operation in progress" },
+ { 0x00, 0x1A, "rewind operation in progress" },
+ { 0x00, 0x1B, "set capacity operation in progress" },
+ { 0x00, 0x1C, "verify operation in progress" },
+ { 0x01, 0x00, "no index/sector signal" },
+ { 0x02, 0x00, "no seek complete" },
+ { 0x03, 0x00, "peripheral device write fault" },
+ { 0x03, 0x01, "no write current" },
+ { 0x03, 0x02, "excessive write errors" },
+ { 0x04, 0x00, "LUN not ready" },
+ { 0x04, 0x01, "LUN is becoming ready" },
+ { 0x04, 0x02, "LUN initializing command required" },
+ { 0x04, 0x03, "LUN not ready intervention required" },
+ { 0x04, 0x04, "LUN not ready format in progress" },
+ { 0x04, 0x05, "LUN not ready, rebuild in progress" },
+ { 0x04, 0x06, "LUN not ready, recalculation in progress" },
+ { 0x04, 0x07, "LUN not ready, operation in progress" },
+ { 0x04, 0x08, "LUN not ready, long write in progress" },
+ { 0x04, 0x09, "LUN not ready, self-test in progress" },
+ { 0x04, 0x0A, "LUN not accessible, asymmetric access state "
+ "transition" },
+ { 0x04, 0x0B, "LUN not accessible, target port in standby state" },
+ { 0x04, 0x0C, "LUN not accessible, target port in unavailable state" },
+ { 0x04, 0x10, "LUN not ready, auxiliary memory not accessible" },
+ { 0x05, 0x00, "LUN does not respond to selection" },
+ { 0x06, 0x00, "reference position found" },
+ { 0x07, 0x00, "multiple peripheral devices selected" },
+ { 0x08, 0x00, "LUN communication failure" },
+ { 0x08, 0x01, "LUN communication time-out" },
+ { 0x08, 0x02, "LUN communication parity error" },
+ { 0x08, 0x03, "LUN communication crc error (ultra-DMA/32)" },
+ { 0x08, 0x04, "unreachable copy target" },
+ { 0x09, 0x00, "track following error" },
+ { 0x09, 0x01, "tracking servo failure" },
+ { 0x09, 0x02, "focus servo failure" },
+ { 0x09, 0x03, "spindle servo failure" },
+ { 0x09, 0x04, "head select fault" },
+ { 0x0a, 0x00, "error log overflow" },
+ { 0x0b, 0x00, "warning" },
+ { 0x0b, 0x01, "warning - specified temperature exceeded" },
+ { 0x0b, 0x02, "warning - enclosure degraded" },
+ { 0x0c, 0x00, "write error" },
+ { 0x0c, 0x01, "write error - recovered with auto reallocation" },
+ { 0x0c, 0x02, "write error - auto reallocation failed" },
+ { 0x0c, 0x03, "write error - recommend reassignment" },
+ { 0x0c, 0x04, "compression check miscompare error" },
+ { 0x0c, 0x05, "data expansion occurred during compression" },
+ { 0x0c, 0x06, "block not compressible" },
+ { 0x0c, 0x07, "write error - recovery needed" },
+ { 0x0c, 0x08, "write error - recovery failed" },
+ { 0x0c, 0x09, "write error - loss of streaming" },
+ { 0x0c, 0x0a, "write error - padding blocks added" },
+ { 0x0c, 0x0b, "auxiliary memory write error" },
+ { 0x0c, 0x0c, "write error - unexpected unsolicited data" },
+ { 0x0c, 0x0d, "write error - not enough unsolicited data" },
+ { 0x0d, 0x00, "error detected by third party temporary initiator" },
+ { 0x0d, 0x01, "third party device failure" },
+ { 0x0d, 0x02, "copy target device not reachable" },
+ { 0x0d, 0x03, "incorrect copy target device type" },
+ { 0x0d, 0x04, "copy target device data underrun" },
+ { 0x0d, 0x05, "copy target device data overrun" },
+ { 0x0e, 0x00, "invalid information unit" },
+ { 0x0e, 0x01, "information unit too short" },
+ { 0x0e, 0x02, "information unit too long" },
+ { 0x10, 0x00, "ID CRC or ECC error" },
+ { 0x11, 0x00, "unrecovered read error" },
+ { 0x11, 0x01, "read retries exhausted" },
+ { 0x11, 0x02, "error too long to correct" },
+ { 0x11, 0x03, "multiple read errors" },
+ { 0x11, 0x04, "unrecovered read error - auto reallocate failed" },
+ { 0x11, 0x05, "L-EC uncorrectable error" },
+ { 0x11, 0x06, "CIRC unrecovered error" },
+ { 0x11, 0x07, "data re-synchronization error" },
+ { 0x11, 0x08, "incomplete block read" },
+ { 0x11, 0x09, "no gap found" },
+ { 0x11, 0x0a, "miscorrected error" },
+ { 0x11, 0x0b, "unrecovered read error - recommend reassignment" },
+ { 0x11, 0x0c, "unrecovered read error - recommend rewrite the data" },
+ { 0x11, 0x0d, "de-compression crc error" },
+ { 0x11, 0x0e, "cannot decompress using declared algorithm" },
+ { 0x11, 0x0f, "error reading UPC/EAN number" },
+ { 0x11, 0x10, "error reading ISRC number" },
+ { 0x11, 0x11, "read error - loss of streaming" },
+ { 0x11, 0x12, "auxiliary memory read error" },
+ { 0x11, 0x13, "read error - failed retransmission request" },
+ { 0x12, 0x00, "address mark not found for ID field" },
+ { 0x13, 0x00, "address mark not found for data field" },
+ { 0x14, 0x00, "recorded entity not found" },
+ { 0x14, 0x01, "record not found" },
+ { 0x14, 0x02, "filemark or setmark not found" },
+ { 0x14, 0x03, "end-of-data not found" },
+ { 0x14, 0x04, "block sequence error" },
+ { 0x14, 0x05, "record not found - recommend reassignment" },
+ { 0x14, 0x06, "record not found - data auto-reallocated" },
+ { 0x14, 0x07, "locate operation failure" },
+ { 0x15, 0x00, "random positioning error" },
+ { 0x15, 0x01, "mechanical positioning error" },
+ { 0x15, 0x02, "positioning error detected by read of medium" },
+ { 0x16, 0x00, "data sync mark error" },
+ { 0x16, 0x01, "data sync error - data rewritten" },
+ { 0x16, 0x02, "data sync error - recommend rewrite" },
+ { 0x16, 0x03, "data sync error - data auto-reallocated" },
+ { 0x16, 0x04, "data sync error - recommend reassignment" },
+ { 0x17, 0x00, "recovered data with no error correction" },
+ { 0x17, 0x01, "recovered data with retries" },
+ { 0x17, 0x02, "recovered data with positive head offset" },
+ { 0x17, 0x03, "recovered data with negative head offset" },
+ { 0x17, 0x04, "recovered data with retries and/or CIRC applied" },
+ { 0x17, 0x05, "recovered data using previous sector id" },
+ { 0x17, 0x06, "recovered data without ECC - data auto-reallocated" },
+ { 0x17, 0x07, "recovered data without ECC - recommend reassignment" },
+ { 0x17, 0x08, "recovered data without ECC - recommend rewrite" },
+ { 0x17, 0x09, "recovered data without ECC - data rewritten" },
+ { 0x18, 0x00, "recovered data with error correction" },
+ { 0x18, 0x01, "recovered data with error corr. & retries applied" },
+ { 0x18, 0x02, "recovered data - data auto-reallocated" },
+ { 0x18, 0x03, "recovered data with CIRC" },
+ { 0x18, 0x04, "recovered data with L-EC" },
+ { 0x18, 0x05, "recovered data - recommend reassignment" },
+ { 0x18, 0x06, "recovered data - recommend rewrite" },
+ { 0x18, 0x07, "recovered data with ECC - data rewritten" },
+ { 0x18, 0x08, "recovered data with linking" },
+ { 0x19, 0x00, "defect list error" },
+ { 0x1a, 0x00, "parameter list length error" },
+ { 0x1b, 0x00, "synchronous data xfer error" },
+ { 0x1c, 0x00, "defect list not found" },
+ { 0x1c, 0x01, "primary defect list not found" },
+ { 0x1c, 0x02, "grown defect list not found" },
+ { 0x1d, 0x00, "miscompare during verify" },
+ { 0x1e, 0x00, "recovered ID with ECC" },
+ { 0x1f, 0x00, "partial defect list transfer" },
+ { 0x20, 0x00, "invalid command operation code" },
+ { 0x20, 0x01, "access denied - initiator pending-enrolled" },
+ { 0x20, 0x02, "access denied - no access rights" },
+ { 0x20, 0x03, "access denied - invalid mgmt id key" },
+ { 0x20, 0x04, "illegal command while in write capable state" },
+ { 0x20, 0x06, "illegal command while in explicit address mode" },
+ { 0x20, 0x07, "illegal command while in implicit address mode" },
+ { 0x20, 0x08, "access denied - enrollment conflict" },
+ { 0x20, 0x09, "access denied - invalid lu identifier" },
+ { 0x20, 0x0a, "access denied - invalid proxy token" },
+ { 0x20, 0x0b, "access denied - ACL LUN conflict" },
+ { 0x21, 0x00, "logical block address out of range" },
+ { 0x21, 0x01, "invalid element address" },
+ { 0x21, 0x02, "invalid address for write" },
+ { 0x22, 0x00, "illegal function" },
+ { 0x24, 0x00, "invalid field in cdb" },
+ { 0x24, 0x01, "cdb decryption error" },
+ { 0x25, 0x00, "LUN not supported" },
+ { 0x26, 0x00, "invalid field in param list" },
+ { 0x26, 0x01, "parameter not supported" },
+ { 0x26, 0x02, "parameter value invalid" },
+ { 0x26, 0x03, "threshold parameters not supported" },
+ { 0x26, 0x04, "invalid release of persistent reservation" },
+ { 0x26, 0x05, "data decryption error" },
+ { 0x26, 0x06, "too many target descriptors" },
+ { 0x26, 0x07, "unsupported target descriptor type code" },
+ { 0x26, 0x08, "too many segment descriptors" },
+ { 0x26, 0x09, "unsupported segment descriptor type code" },
+ { 0x26, 0x0a, "unexpected inexact segment" },
+ { 0x26, 0x0b, "inline data length exceeded" },
+ { 0x26, 0x0c, "invalid operation for copy source or destination" },
+ { 0x26, 0x0d, "copy segment granularity violation" },
+ { 0x27, 0x00, "write protected" },
+ { 0x27, 0x01, "hardware write protected" },
+ { 0x27, 0x02, "LUN software write protected" },
+ { 0x27, 0x03, "associated write protect" },
+ { 0x27, 0x04, "persistent write protect" },
+ { 0x27, 0x05, "permanent write protect" },
+ { 0x27, 0x06, "conditional write protect" },
+ { 0x28, 0x00, "medium may have changed" },
+ { 0x28, 0x01, "import or export element accessed" },
+ { 0x29, 0x00, "power on, reset, or bus reset occurred" },
+ { 0x29, 0x01, "power on occurred" },
+ { 0x29, 0x02, "scsi bus reset occurred" },
+ { 0x29, 0x03, "bus device reset message occurred" },
+ { 0x29, 0x04, "device internal reset" },
+ { 0x29, 0x05, "transceiver mode changed to single-ended" },
+ { 0x29, 0x06, "transceiver mode changed to LVD" },
+ { 0x29, 0x07, "i_t nexus loss occurred" },
+ { 0x2a, 0x00, "parameters changed" },
+ { 0x2a, 0x01, "mode parameters changed" },
+ { 0x2a, 0x02, "log parameters changed" },
+ { 0x2a, 0x03, "reservations preempted" },
+ { 0x2a, 0x04, "reservations released" },
+ { 0x2a, 0x05, "registrations preempted" },
+ { 0x2a, 0x06, "asymmetric access state changed" },
+ { 0x2a, 0x07, "implicit asymmetric access state transition failed" },
+ { 0x2b, 0x00, "copy cannot execute since host cannot disconnect" },
+ { 0x2c, 0x00, "command sequence error" },
+ { 0x2c, 0x03, "current program area is not empty" },
+ { 0x2c, 0x04, "current program area is empty" },
+ { 0x2c, 0x06, "persistent prevent conflict" },
+ { 0x2c, 0x07, "previous busy status" },
+ { 0x2c, 0x08, "previous task set full status" },
+ { 0x2c, 0x09, "previous reservation conflict status" },
+ { 0x2d, 0x00, "overwrite error on update in place" },
+ { 0x2e, 0x00, "insufficient time for operation" },
+ { 0x2f, 0x00, "commands cleared by another initiator" },
+ { 0x30, 0x00, "incompatible medium installed" },
+ { 0x30, 0x01, "cannot read medium - unknown format" },
+ { 0x30, 0x02, "cannot read medium - incompatible format" },
+ { 0x30, 0x03, "cleaning cartridge installed" },
+ { 0x30, 0x04, "cannot write medium - unknown format" },
+ { 0x30, 0x05, "cannot write medium - incompatible format" },
+ { 0x30, 0x06, "cannot format medium - incompatible medium" },
+ { 0x30, 0x07, "cleaning failure" },
+ { 0x30, 0x08, "cannot write - application code mismatch" },
+ { 0x30, 0x09, "current session not fixated for append" },
+ { 0x30, 0x10, "medium not formatted" },
+ { 0x31, 0x00, "medium format corrupted" },
+ { 0x31, 0x01, "format command failed" },
+ { 0x31, 0x02, "zoned formatting failed due to spare linking" },
+ { 0x32, 0x00, "no defect spare location available" },
+ { 0x32, 0x01, "defect list update failure" },
+ { 0x33, 0x00, "tape length error" },
+ { 0x34, 0x00, "enclosure failure" },
+ { 0x35, 0x00, "enclosure services failure" },
+ { 0x35, 0x01, "unsupported enclosure function" },
+ { 0x35, 0x02, "enclosure services unavailable" },
+ { 0x35, 0x03, "enclosure services transfer failure" },
+ { 0x35, 0x04, "enclosure services transfer refused" },
+ { 0x36, 0x00, "ribbon, ink, or toner failure" },
+ { 0x37, 0x00, "rounded parameter" },
+ { 0x39, 0x00, "saving parameters not supported" },
+ { 0x3a, 0x00, "medium not present" },
+ { 0x3a, 0x01, "medium not present - tray closed" },
+ { 0x3a, 0x02, "medium not present - tray open" },
+ { 0x3a, 0x03, "medium not present - loadable" },
+ { 0x3a, 0x04, "medium not present - medium auxiliary memory "
+ "accessible" },
+ { 0x3b, 0x00, "sequential positioning error" },
+ { 0x3b, 0x01, "tape position error at beginning-of-medium" },
+ { 0x3b, 0x02, "tape position error at end-of-medium" },
+ { 0x3b, 0x08, "reposition error" },
+ { 0x3b, 0x0c, "position past beginning of medium" },
+ { 0x3b, 0x0d, "medium destination element full" },
+ { 0x3b, 0x0e, "medium source element empty" },
+ { 0x3b, 0x0f, "end of medium reached" },
+ { 0x3b, 0x11, "medium magazine not accessible" },
+ { 0x3b, 0x12, "medium magazine removed" },
+ { 0x3b, 0x13, "medium magazine inserted" },
+ { 0x3b, 0x14, "medium magazine locked" },
+ { 0x3b, 0x15, "medium magazine unlocked" },
+ { 0x3b, 0x16, "mechanical positioning or changer error" },
+ { 0x3d, 0x00, "invalid bits in indentify message" },
+ { 0x3e, 0x00, "LUN has not self-configured yet" },
+ { 0x3e, 0x01, "LUN failure" },
+ { 0x3e, 0x02, "timeout on LUN" },
+ { 0x3e, 0x03, "LUN failed self-test" },
+ { 0x3e, 0x04, "LUN unable to update self-test log" },
+ { 0x3f, 0x00, "target operating conditions have changed" },
+ { 0x3f, 0x01, "microcode has been changed" },
+ { 0x3f, 0x02, "changed operating definition" },
+ { 0x3f, 0x03, "inquiry data has changed" },
+ { 0x3f, 0x04, "component device attached" },
+ { 0x3f, 0x05, "device identifier changed" },
+ { 0x3f, 0x06, "redundancy group created or modified" },
+ { 0x3f, 0x07, "redundancy group deleted" },
+ { 0x3f, 0x08, "spare created or modified" },
+ { 0x3f, 0x09, "spare deleted" },
+ { 0x3f, 0x0a, "volume set created or modified" },
+ { 0x3f, 0x0b, "volume set deleted" },
+ { 0x3f, 0x0c, "volume set deassigned" },
+ { 0x3f, 0x0d, "volume set reassigned" },
+ { 0x3f, 0x0e, "reported LUNs data has changed" },
+ { 0x3f, 0x0f, "echo buffer overwritten" },
+ { 0x3f, 0x10, "medium loadable" },
+ { 0x3f, 0x11, "medium auxiliary memory accessible" },
+ { 0x40, 0x00, "ram failure" },
+ { 0x41, 0x00, "data path failure" },
+ { 0x42, 0x00, "power-on or self-test failure" },
+ { 0x43, 0x00, "message error" },
+ { 0x44, 0x00, "internal target failure" },
+ { 0x45, 0x00, "select or reselect failure" },
+ { 0x46, 0x00, "unsuccessful soft reset" },
+ { 0x47, 0x00, "scsi parity error" },
+ { 0x47, 0x01, "data phase crc error detected" },
+ { 0x47, 0x02, "scsi parity error detected during st data phase" },
+ { 0x47, 0x03, "information unit iucrc error detected" },
+ { 0x47, 0x04, "asynchronous information protection error detected" },
+ { 0x47, 0x05, "protocol service crc error" },
+ { 0x47, 0x7f, "some commands cleared by iscsi protocol event" },
+ { 0x48, 0x00, "initiator detected error message received" },
+ { 0x49, 0x00, "invalid message error" },
+ { 0x4a, 0x00, "command phase error" },
+ { 0x4b, 0x00, "data phase error" },
+ { 0x4b, 0x01, "invalid target port transfer tag received" },
+ { 0x4b, 0x02, "too much write data" },
+ { 0x4b, 0x03, "ack/nak timeout" },
+ { 0x4b, 0x04, "nak received" },
+ { 0x4b, 0x05, "data offset error" },
+ { 0x4c, 0x00, "logical unit failed self-configuration" },
+ { 0x4d, 0x00, "tagged overlapped commands (ASCQ = queue tag)" },
+ { 0x4e, 0x00, "overlapped commands attempted" },
+ { 0x50, 0x00, "write append error" },
+ { 0x51, 0x00, "erase failure" },
+ { 0x52, 0x00, "cartridge fault" },
+ { 0x53, 0x00, "media load or eject failed" },
+ { 0x53, 0x01, "unload tape failure" },
+ { 0x53, 0x02, "medium removal prevented" },
+ { 0x54, 0x00, "scsi to host system interface failure" },
+ { 0x55, 0x00, "system resource failure" },
+ { 0x55, 0x01, "system buffer full" },
+ { 0x55, 0x02, "insufficient reservation resources" },
+ { 0x55, 0x03, "insufficient resources" },
+ { 0x55, 0x04, "insufficient registration resources" },
+ { 0x55, 0x05, "insufficient access control resources" },
+ { 0x55, 0x06, "auxiliary memory out of space" },
+ { 0x57, 0x00, "unable to recover TOC" },
+ { 0x58, 0x00, "generation does not exist" },
+ { 0x59, 0x00, "updated block read" },
+ { 0x5a, 0x00, "operator request or state change input" },
+ { 0x5a, 0x01, "operator medium removal request" },
+ { 0x5a, 0x02, "operator selected write protect" },
+ { 0x5a, 0x03, "operator selected write permit" },
+ { 0x5b, 0x00, "log exception" },
+ { 0x5b, 0x01, "threshold condition met" },
+ { 0x5b, 0x02, "log counter at maximum" },
+ { 0x5b, 0x03, "log list codes exhausted" },
+ { 0x5c, 0x00, "RPL status change" },
+ { 0x5c, 0x01, "spindles synchronized" },
+ { 0x5c, 0x02, "spindles not synchronized" },
+ { 0x5d, 0x00, "drive operation marginal, service immediately"
+ " (failure prediction threshold exceeded)" },
+ { 0x5d, 0x01, "media failure prediction threshold exceeded" },
+ { 0x5d, 0x02, "LUN failure prediction threshold exceeded" },
+ { 0x5d, 0x03, "spare area exhaustion prediction threshold exceeded" },
+ { 0x5d, 0x10, "hardware impending failure general hard drive failure" },
+ { 0x5d, 0x11, "hardware impending failure drive error rate too high" },
+ { 0x5d, 0x12, "hardware impending failure data error rate too high" },
+ { 0x5d, 0x13, "hardware impending failure seek error rate too high" },
+ { 0x5d, 0x14, "hardware impending failure too many block reassigns" },
+ { 0x5d, 0x15, "hardware impending failure access times too high" },
+ { 0x5d, 0x16, "hardware impending failure start unit times too high" },
+ { 0x5d, 0x17, "hardware impending failure channel parametrics" },
+ { 0x5d, 0x18, "hardware impending failure controller detected" },
+ { 0x5d, 0x19, "hardware impending failure throughput performance" },
+ { 0x5d, 0x1a, "hardware impending failure seek time performance" },
+ { 0x5d, 0x1b, "hardware impending failure spin-up retry count" },
+ { 0x5d, 0x1c, "hardware impending failure drive calibration retry "
+ "count" },
+ { 0x5d, 0x20, "controller impending failure general hard drive "
+ "failure" },
+ { 0x5d, 0x21, "controller impending failure drive error rate too "
+ "high" },
+ { 0x5d, 0x22, "controller impending failure data error rate too high" },
+ { 0x5d, 0x23, "controller impending failure seek error rate too high" },
+ { 0x5d, 0x24, "controller impending failure too many block reassigns" },
+ { 0x5d, 0x25, "controller impending failure access times too high" },
+ { 0x5d, 0x26, "controller impending failure start unit times too "
+ "high" },
+ { 0x5d, 0x27, "controller impending failure channel parametrics" },
+ { 0x5d, 0x28, "controller impending failure controller detected" },
+ { 0x5d, 0x29, "controller impending failure throughput performance" },
+ { 0x5d, 0x2a, "controller impending failure seek time performance" },
+ { 0x5d, 0x2b, "controller impending failure spin-up retry count" },
+ { 0x5d, 0x2c, "controller impending failure drive calibration retry "
+ "cnt" },
+ { 0x5d, 0x30, "data channel impending failure general hard drive "
+ "failure" },
+ { 0x5d, 0x31, "data channel impending failure drive error rate too "
+ "high" },
+ { 0x5d, 0x32, "data channel impending failure data error rate too "
+ "high" },
+ { 0x5d, 0x33, "data channel impending failure seek error rate too "
+ "high" },
+ { 0x5d, 0x34, "data channel impending failure too many block "
+ "reassigns" },
+ { 0x5d, 0x35, "data channel impending failure access times too high" },
+ { 0x5d, 0x36, "data channel impending failure start unit times too "
+ "high" },
+ { 0x5d, 0x37, "data channel impending failure channel parametrics" },
+ { 0x5d, 0x38, "data channel impending failure controller detected" },
+ { 0x5d, 0x39, "data channel impending failure throughput performance" },
+ { 0x5d, 0x3a, "data channel impending failure seek time performance" },
+ { 0x5d, 0x3b, "data channel impending failure spin-up retry count" },
+ { 0x5d, 0x3c, "data channel impending failure drive calibrate retry "
+ "cnt" },
+ { 0x5d, 0x40, "servo impending failure general hard drive failure" },
+ { 0x5d, 0x41, "servo impending failure drive error rate too high" },
+ { 0x5d, 0x42, "servo impending failure data error rate too high" },
+ { 0x5d, 0x43, "servo impending failure seek error rate too high" },
+ { 0x5d, 0x44, "servo impending failure too many block reassigns" },
+ { 0x5d, 0x45, "servo impending failure access times too high" },
+ { 0x5d, 0x46, "servo impending failure start unit times too high" },
+ { 0x5d, 0x47, "servo impending failure channel parametrics" },
+ { 0x5d, 0x48, "servo impending failure controller detected" },
+ { 0x5d, 0x49, "servo impending failure throughput performance" },
+ { 0x5d, 0x4a, "servo impending failure seek time performance" },
+ { 0x5d, 0x4b, "servo impending failure spin-up retry count" },
+ { 0x5d, 0x4c, "servo impending failure drive calibration retry count" },
+ { 0x5d, 0x50, "spindle impending failure general hard drive failure" },
+ { 0x5d, 0x51, "spindle impending failure drive error rate too high" },
+ { 0x5d, 0x52, "spindle impending failure data error rate too high" },
+ { 0x5d, 0x53, "spindle impending failure seek error rate too high" },
+ { 0x5d, 0x54, "spindle impending failure too many block reassigns" },
+ { 0x5d, 0x55, "spindle impending failure access times too high" },
+ { 0x5d, 0x56, "spindle impending failure start unit times too high" },
+ { 0x5d, 0x57, "spindle impending failure channel parametrics" },
+ { 0x5d, 0x58, "spindle impending failure controller detected" },
+ { 0x5d, 0x59, "spindle impending failure throughput performance" },
+ { 0x5d, 0x5a, "spindle impending failure seek time performance" },
+ { 0x5d, 0x5b, "spindle impending failure spin-up retry count" },
+ { 0x5d, 0x5c, "spindle impending failure drive calibration retry "
+ "count" },
+ { 0x5d, 0x60, "firmware impending failure general hard drive failure" },
+ { 0x5d, 0x61, "firmware impending failure drive error rate too high" },
+ { 0x5d, 0x62, "firmware impending failure data error rate too high" },
+ { 0x5d, 0x63, "firmware impending failure seek error rate too high" },
+ { 0x5d, 0x64, "firmware impending failure too many block reassigns" },
+ { 0x5d, 0x65, "firmware impending failure access times too high" },
+ { 0x5d, 0x66, "firmware impending failure start unit times too high" },
+ { 0x5d, 0x67, "firmware impending failure channel parametrics" },
+ { 0x5d, 0x68, "firmware impending failure controller detected" },
+ { 0x5d, 0x69, "firmware impending failure throughput performance" },
+ { 0x5d, 0x6a, "firmware impending failure seek time performance" },
+ { 0x5d, 0x6b, "firmware impending failure spin-up retry count" },
+ { 0x5d, 0x6c, "firmware impending failure drive calibration retry "
+ "count" },
+ { 0x5d, 0xff, "failure prediction threshold exceeded (false)" },
+ { 0x5e, 0x00, "low power condition active" },
+ { 0x5e, 0x01, "idle condition activated by timer" },
+ { 0x5e, 0x02, "standby condition activated by timer" },
+ { 0x5e, 0x03, "idle condition activated by command" },
+ { 0x5e, 0x04, "standby condition activated by command" },
+ { 0x60, 0x00, "lamp failure" },
+ { 0x61, 0x00, "video aquisition error" },
+ { 0x62, 0x00, "scan head positioning error" },
+ { 0x63, 0x00, "end of user area encountered on this track" },
+ { 0x63, 0x01, "packet does not fit in available space" },
+ { 0x64, 0x00, "illegal mode for this track" },
+ { 0x64, 0x01, "invalid packet size" },
+ { 0x65, 0x00, "voltage fault" },
+ { 0x66, 0x00, "automatic document feeder cover up" },
+ { 0x67, 0x00, "configuration failure" },
+ { 0x67, 0x01, "configuration of incapable LUNs failed" },
+ { 0x67, 0x02, "add LUN failed" },
+ { 0x67, 0x03, "modification of LUN failed" },
+ { 0x67, 0x04, "exchange of LUN failed" },
+ { 0x67, 0x05, "remove of LUN failed" },
+ { 0x67, 0x06, "attachment of LUN failed" },
+ { 0x67, 0x07, "creation of LUN failed" },
+ { 0x67, 0x08, "assign failure occurred" },
+ { 0x67, 0x09, "multiply assigned LUN" },
+ { 0x67, 0x0a, "set target port groups command failed" },
+ { 0x68, 0x00, "logical unit not configured" },
+ { 0x69, 0x00, "data loss on logical unit" },
+ { 0x69, 0x01, "multiple LUN failures" },
+ { 0x69, 0x02, "parity/data mismatch" },
+ { 0x6a, 0x00, "informational, refer to log" },
+ { 0x6b, 0x00, "state change has occured" },
+ { 0x6b, 0x01, "redundancy level got better" },
+ { 0x6b, 0x02, "redundancy level got worse" },
+ { 0x6c, 0x00, "rebuild failure occured" },
+ { 0x6d, 0x00, "recalculate failure occured" },
+ { 0x6e, 0x00, "command to logical unit failed" },
+ { 0x6f, 0x00, "copy protect key exchange failure authentication "
+ "failure" },
+ { 0x6f, 0x01, "copy protect key exchange failure key not present" },
+ { 0x6f, 0x02, "copy protect key exchange failure key not established" },
+ { 0x6f, 0x03, "read of scrambled sector without authentication" },
+ { 0x6f, 0x04, "media region code is mismatched to LUN region" },
+ { 0x6f, 0x05, "drive region must be permanent/region reset count "
+ "error" },
+ { 0x70, 0xffff, "decompression exception short algorithm id of ASCQ" },
+ { 0x71, 0x00, "decompression exception long algorithm id" },
+ { 0x72, 0x00, "session fixation error" },
+ { 0x72, 0x01, "session fixation error writing lead-in" },
+ { 0x72, 0x02, "session fixation error writing lead-out" },
+ { 0x72, 0x03, "session fixation error - incomplete track in session" },
+ { 0x72, 0x04, "empty or partially written reserved track" },
+ { 0x72, 0x05, "no more track reservations allowed" },
+ { 0x73, 0x00, "cd control error" },
+ { 0x73, 0x01, "power calibration area almost full" },
+ { 0x73, 0x02, "power calibration area is full" },
+ { 0x73, 0x03, "power calibration area error" },
+ { 0x73, 0x04, "program memory area update failure" },
+ { 0x73, 0x05, "program memory area is full" },
+ { 0x73, 0x06, "rma/pma is almost full" },
+ { 0xffff, 0xffff, NULL }
+};
+
+static const char *
+find_string(slist_t *slist, int match_value)
+{
+ for (; slist->str != NULL; slist++) {
+ if (slist->value == match_value) {
+ return (slist->str);
+ }
+ }
+
+ return (NULL);
+}
+
+const char *
+libscsi_sense_key_name(uint64_t key)
+{
+ return (find_string(sensekey_strings, (int)key));
+}
+
+/*
+ * Given an asc (Additional Sense Code) and ascq (Additional Sense Code
+ * Qualifier), return a string describing the error information.
+ */
+const char *
+libscsi_sense_code_name(uint64_t asc, uint64_t ascq)
+{
+ int i = 0;
+
+ while (extended_sense_list[i].asc != 0xffff) {
+ if ((asc == extended_sense_list[i].asc) &&
+ ((ascq == extended_sense_list[i].ascq) ||
+ (extended_sense_list[i].ascq == 0xffff))) {
+ return ((char *)extended_sense_list[i].message);
+ }
+ i++;
+ }
+
+ return (NULL);
+}
+
+/*
+ * Retrieve "information" field from descriptor format sense data. Iterates
+ * through each sense descriptor looking for the information descriptor and
+ * returns the information field from that descriptor.
+ */
+static diskaddr_t
+scsi_extract_sense_info_descr(struct scsi_descr_sense_hdr *sdsp, size_t len)
+{
+ diskaddr_t result;
+ uint8_t *descr_offset;
+ size_t valid_sense_length;
+ struct scsi_information_sense_descr *isd;
+
+ /*
+ * Initialize result to -1 indicating there is no information
+ * descriptor
+ */
+ result = (diskaddr_t)-1;
+
+ /*
+ * The first descriptor will immediately follow the header
+ */
+ descr_offset = (uint8_t *)(sdsp+1);
+
+ /*
+ * Calculate the amount of valid sense data
+ */
+ valid_sense_length =
+ MIN((sizeof (struct scsi_descr_sense_hdr) +
+ sdsp->ds_addl_sense_length), len);
+
+ /*
+ * Iterate through the list of descriptors, stopping when we run out of
+ * sense data
+ */
+ while ((descr_offset + sizeof (struct scsi_information_sense_descr)) <=
+ (uint8_t *)sdsp + valid_sense_length) {
+ /*
+ * Check if this is an information descriptor. We can use the
+ * scsi_information_sense_descr structure as a template since
+ * the first two fields are always the same
+ */
+ isd = (struct scsi_information_sense_descr *)descr_offset;
+ if (isd->isd_descr_type == DESCR_INFORMATION) {
+ /*
+ * Found an information descriptor. Copy the
+ * information field. There will only be one
+ * information descriptor so we can stop looking.
+ */
+ result =
+ (((diskaddr_t)isd->isd_information[0] << 56) |
+ ((diskaddr_t)isd->isd_information[1] << 48) |
+ ((diskaddr_t)isd->isd_information[2] << 40) |
+ ((diskaddr_t)isd->isd_information[3] << 32) |
+ ((diskaddr_t)isd->isd_information[4] << 24) |
+ ((diskaddr_t)isd->isd_information[5] << 16) |
+ ((diskaddr_t)isd->isd_information[6] << 8) |
+ ((diskaddr_t)isd->isd_information[7]));
+ break;
+ }
+
+ /*
+ * Get pointer to the next descriptor. The "additional length"
+ * field holds the length of the descriptor except for the
+ * "type" and "additional length" fields, so we need to add 2 to
+ * get the total length.
+ */
+ descr_offset += (isd->isd_addl_length + 2);
+ }
+
+ return (result);
+}
+
+int
+libscsi_action_parse_sense(const libscsi_action_t *ap, uint64_t *keyp,
+ uint64_t *ascp, uint64_t *ascqp, diskaddr_t *blkp)
+{
+ struct scsi_extended_sense *xsp;
+ struct scsi_descr_sense_hdr *sdsp;
+ size_t len;
+
+ if (libscsi_action_get_sense(ap, (uint8_t **)&xsp, NULL, &len) != 0)
+ return (-1);
+
+ sdsp = (struct scsi_descr_sense_hdr *)xsp;
+
+ if (keyp != NULL)
+ *keyp = (uint64_t)xsp->es_key;
+
+ switch (xsp->es_code) {
+ case CODE_FMT_DESCR_CURRENT:
+ case CODE_FMT_DESCR_DEFERRED:
+ if (blkp != NULL)
+ *blkp = (diskaddr_t)
+ scsi_extract_sense_info_descr(sdsp, len);
+ if (ascp != NULL)
+ *ascp = (uint64_t)sdsp->ds_add_code;
+ if (ascqp != NULL)
+ *ascqp = (uint64_t)sdsp->ds_qual_code;
+ break;
+ case CODE_FMT_FIXED_CURRENT:
+ case CODE_FMT_FIXED_DEFERRED:
+ default:
+ if (xsp->es_valid && blkp != NULL)
+ *blkp = (diskaddr_t)
+ ((xsp->es_info_1 << 24) | (xsp->es_info_2 << 16) |
+ (xsp->es_info_3 << 8) | xsp->es_info_4);
+ if (xsp->es_add_len >= 6) {
+ if (ascp != NULL)
+ *ascp = (uint64_t)xsp->es_add_code;
+ if (ascqp != NULL)
+ *ascqp = (uint64_t)xsp->es_qual_code;
+ }
+ break;
+ }
+
+ return (0);
+}
diff --git a/usr/src/lib/scsi/libscsi/common/scsi_subr.c b/usr/src/lib/scsi/libscsi/common/scsi_subr.c
new file mode 100644
index 0000000000..fb9a4eb650
--- /dev/null
+++ b/usr/src/lib/scsi/libscsi/common/scsi_subr.c
@@ -0,0 +1,351 @@
+/*
+ * 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"
+
+#include <sys/types.h>
+#include <sys/scsi/generic/commands.h>
+#include <sys/scsi/impl/spc3_types.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <alloca.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <dlfcn.h>
+
+#include <scsi/libscsi.h>
+#include "libscsi_impl.h"
+
+int
+libscsi_assert(const char *expr, const char *file, int line)
+{
+ char *msg;
+ size_t len;
+
+ len = snprintf(NULL, 0,
+ "ABORT: \"%s\", line %d: assertion failed: %s\n", file, line, expr);
+
+ msg = alloca(len + 1);
+
+ (void) snprintf(msg, len + 1,
+ "ABORT: \"%s\", line %d: assertion failed: %s\n", file, line, expr);
+
+ (void) write(STDERR_FILENO, msg, strlen(msg));
+
+ abort();
+ _exit(1);
+
+ /*NOTREACHED*/
+ return (0);
+}
+
+int
+libscsi_set_errno(libscsi_hdl_t *hp, libscsi_errno_t err)
+{
+ hp->lsh_errno = err;
+ hp->lsh_errmsg[0] = '\0';
+
+ return (-1);
+}
+
+/*
+ * Internal routine for setting both _ue_errno and _ue_errmsg. We save
+ * and restore the UNIX errno across this routing so the caller can use either
+ * libscsi_set_errno(), libscsi_error(), or libscsi_verror() without this value
+ * changing.
+ */
+int
+libscsi_verror(libscsi_hdl_t *hp, libscsi_errno_t err, const char *fmt,
+ va_list ap)
+{
+ size_t n;
+ char *errmsg;
+
+ /*
+ * To allow the existing error message to itself be used in an error
+ * message, we put the new error message into a buffer on the stack,
+ * and then copy it into lsh_errmsg. We also need to set the errno,
+ * but because the call to libscsi_set_errno() is destructive to
+ * lsh_errmsg, we do this after we print into our temporary buffer
+ * (in case _libscsi_errmsg is part of the error message) and before we
+ * copy the temporary buffer on to _libscsi_errmsg (to prevent our new
+ * message from being nuked by the call to libscsi_set_errno()).
+ */
+ errmsg = alloca(sizeof (hp->lsh_errmsg));
+ (void) vsnprintf(errmsg, sizeof (hp->lsh_errmsg), fmt, ap);
+ (void) libscsi_set_errno(hp, err);
+
+ n = strlen(errmsg);
+
+ if (n != 0 && errmsg[n - 1] == '\n')
+ errmsg[n - 1] = '\0';
+
+ bcopy(errmsg, hp->lsh_errmsg, n + 1);
+
+ return (-1);
+}
+
+/*PRINTFLIKE3*/
+int
+libscsi_error(libscsi_hdl_t *hp, libscsi_errno_t err, const char *fmt, ...)
+{
+ va_list ap;
+
+ if (fmt == NULL)
+ return (libscsi_set_errno(hp, err));
+
+ va_start(ap, fmt);
+ err = libscsi_verror(hp, err, fmt, ap);
+ va_end(ap);
+
+ return (err);
+}
+
+libscsi_errno_t
+libscsi_errno(libscsi_hdl_t *hp)
+{
+ return (hp->lsh_errno);
+}
+
+const char *
+libscsi_errmsg(libscsi_hdl_t *hp)
+{
+ if (hp->lsh_errmsg[0] == '\0')
+ (void) strlcpy(hp->lsh_errmsg, libscsi_strerror(hp->lsh_errno),
+ sizeof (hp->lsh_errmsg));
+
+ return (hp->lsh_errmsg);
+}
+
+void *
+libscsi_alloc(libscsi_hdl_t *hp, size_t size)
+{
+ void *mem;
+
+ if (size == 0) {
+ (void) libscsi_set_errno(hp, ESCSI_ZERO_LENGTH);
+ return (NULL);
+ }
+
+ if ((mem = malloc(size)) == NULL)
+ (void) libscsi_set_errno(hp, ESCSI_NOMEM);
+
+ return (mem);
+}
+
+void *
+libscsi_zalloc(libscsi_hdl_t *hp, size_t size)
+{
+ void *mem;
+
+ if ((mem = libscsi_alloc(hp, size)) == NULL)
+ return (NULL);
+
+ bzero(mem, size);
+
+ return (mem);
+}
+
+char *
+libscsi_strdup(libscsi_hdl_t *hp, const char *str)
+{
+ size_t len = strlen(str);
+ char *dup = libscsi_alloc(hp, len + 1);
+
+ if (dup == NULL)
+ return (NULL);
+
+ return (strcpy(dup, str));
+}
+
+/*ARGSUSED*/
+void
+libscsi_free(libscsi_hdl_t *hp, void *ptr)
+{
+ free(ptr);
+}
+
+libscsi_hdl_t *
+libscsi_init(uint_t version, libscsi_errno_t *errp)
+{
+ libscsi_hdl_t *hp;
+
+ if ((hp = malloc(sizeof (libscsi_hdl_t))) == NULL) {
+ if (errp != NULL)
+ *errp = ESCSI_NOMEM;
+ return (NULL);
+ }
+
+ bzero(hp, sizeof (libscsi_hdl_t));
+ hp->lsh_version = version;
+
+ return (hp);
+}
+
+void
+libscsi_fini(libscsi_hdl_t *hp)
+{
+ libscsi_engine_impl_t *eip, *neip;
+
+ if (hp == NULL)
+ return;
+
+ ASSERT(hp->lsh_targets == 0);
+
+ for (eip = hp->lsh_engines; eip != NULL; eip = neip) {
+ neip = eip->lsei_next;
+ (void) dlclose(eip->lsei_dl_hdl);
+ libscsi_free(hp, eip);
+ }
+
+ free(hp);
+}
+
+size_t
+libscsi_cmd_cdblen(libscsi_hdl_t *hp, uint8_t cmd)
+{
+ size_t sz;
+
+ switch (CDB_GROUPID(cmd)) {
+ case CDB_GROUPID_0:
+ sz = CDB_GROUP0;
+ break;
+ case CDB_GROUPID_1:
+ sz = CDB_GROUP1;
+ break;
+ case CDB_GROUPID_2:
+ sz = CDB_GROUP2;
+ break;
+ case CDB_GROUPID_3:
+ sz = CDB_GROUP3;
+ break;
+ case CDB_GROUPID_4:
+ sz = CDB_GROUP4;
+ break;
+ case CDB_GROUPID_5:
+ sz = CDB_GROUP5;
+ break;
+ case CDB_GROUPID_6:
+ sz = CDB_GROUP6;
+ break;
+ case CDB_GROUPID_7:
+ sz = CDB_GROUP7;
+ break;
+ default:
+ sz = 0;
+ }
+
+ if (sz == 0)
+ (void) libscsi_error(hp, ESCSI_BADCMD,
+ "unknown or unsupported command %u", cmd);
+
+ return (sz);
+}
+
+static char *
+libscsi_process_inquiry_string(libscsi_hdl_t *hp, const char *raw, size_t len)
+{
+ char *buf;
+
+ buf = alloca(len + 1);
+ bcopy(raw, buf, len);
+
+ for (; len > 0; len--) {
+ if (buf[len - 1] != ' ')
+ break;
+ }
+
+ buf[len] = '\0';
+
+ return (libscsi_strdup(hp, buf));
+}
+
+/*
+ * As part of basic initialization, we always retrieve the INQUIRY information
+ * to have the vendor/product/revision information available for all consumers.
+ */
+int
+libscsi_get_inquiry(libscsi_hdl_t *hp, libscsi_target_t *tp)
+{
+ libscsi_action_t *ap;
+ spc3_inquiry_cdb_t *cp;
+ spc3_inquiry_data_t data;
+ size_t len;
+
+ if ((ap = libscsi_action_alloc(hp, SPC3_CMD_INQUIRY,
+ LIBSCSI_AF_READ | LIBSCSI_AF_SILENT | LIBSCSI_AF_DIAGNOSE, &data,
+ sizeof (data))) == NULL)
+ return (-1);
+
+ cp = (spc3_inquiry_cdb_t *)libscsi_action_get_cdb(ap);
+
+ SCSI_WRITE16(&cp->ic_allocation_length, sizeof (data));
+
+ if (libscsi_exec(ap, tp) != 0 ||
+ libscsi_action_get_status(ap) != 0) {
+ libscsi_action_free(ap);
+ return (libscsi_set_errno(hp, ESCSI_INQUIRY_FAILED));
+ }
+
+ (void) libscsi_action_get_buffer(ap, NULL, NULL, &len);
+ libscsi_action_free(ap);
+
+ if (len < offsetof(spc3_inquiry_data_t, id_vs_36))
+ return (libscsi_set_errno(hp, ESCSI_INQUIRY_FAILED));
+
+ if ((tp->lst_vendor = libscsi_process_inquiry_string(hp,
+ data.id_vendor_id, sizeof (data.id_vendor_id))) == NULL ||
+ (tp->lst_product = libscsi_process_inquiry_string(hp,
+ data.id_product_id, sizeof (data.id_product_id))) == NULL ||
+ (tp->lst_revision = libscsi_process_inquiry_string(hp,
+ data.id_product_revision,
+ sizeof (data.id_product_revision))) == NULL) {
+ return (-1);
+ }
+
+ return (0);
+}
+
+const char *
+libscsi_vendor(libscsi_target_t *tp)
+{
+ return (tp->lst_vendor);
+}
+
+const char *
+libscsi_product(libscsi_target_t *tp)
+{
+ return (tp->lst_product);
+}
+
+const char *
+libscsi_revision(libscsi_target_t *tp)
+{
+ return (tp->lst_revision);
+}
diff --git a/usr/src/lib/scsi/libscsi/i386/Makefile b/usr/src/lib/scsi/libscsi/i386/Makefile
new file mode 100644
index 0000000000..b68583c86f
--- /dev/null
+++ b/usr/src/lib/scsi/libscsi/i386/Makefile
@@ -0,0 +1,30 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/scsi/libscsi/libscsi_api.map b/usr/src/lib/scsi/libscsi/libscsi_api.map
new file mode 100644
index 0000000000..8fbb5ef1ca
--- /dev/null
+++ b/usr/src/lib/scsi/libscsi/libscsi_api.map
@@ -0,0 +1,49 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+{
+ libscsi_strerror = FUNCTION extern;
+ libscsi_errname = FUNCTION extern;
+ libscsi_errcode = FUNCTION extern;
+ libscsi_alloc = FUNCTION extern;
+ libscsi_zalloc = FUNCTION extern;
+ libscsi_strdup = FUNCTION extern;
+ libscsi_free = FUNCTION extern;
+ libscsi_set_errno = FUNCTION extern;
+ libscsi_verror = FUNCTION extern;
+ libscsi_error = FUNCTION extern;
+ libscsi_cmd_cdblen = FUNCTION extern;
+ libscsi_action_get_timeout = FUNCTION extern;
+ libscsi_action_get_flags = FUNCTION extern;
+ libscsi_action_get_cdb = FUNCTION extern;
+ libscsi_action_get_buffer = FUNCTION extern;
+ libscsi_action_get_sense = FUNCTION extern;
+ libscsi_action_set_status = FUNCTION extern;
+ libscsi_action_set_datalen = FUNCTION extern;
+ libscsi_action_set_senselen = FUNCTION extern;
+ libscsi_assert = FUNCTION extern;
+};
diff --git a/usr/src/lib/scsi/libscsi/llib-lscsi b/usr/src/lib/scsi/libscsi/llib-lscsi
new file mode 100644
index 0000000000..2c7111c8d1
--- /dev/null
+++ b/usr/src/lib/scsi/libscsi/llib-lscsi
@@ -0,0 +1,32 @@
+/*
+ * 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"
+
+/*LINTLIBRARY*/
+/*PROTOLIB1*/
+
+#include <scsi/libscsi.h>
diff --git a/usr/src/lib/scsi/libscsi/mapfile-vers b/usr/src/lib/scsi/libscsi/mapfile-vers
new file mode 100644
index 0000000000..d35f144f08
--- /dev/null
+++ b/usr/src/lib/scsi/libscsi/mapfile-vers
@@ -0,0 +1,72 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+SUNWprivate_1.1 {
+ global:
+ libscsi_init;
+ libscsi_fini;
+ libscsi_open;
+ libscsi_close;
+ libscsi_action_alloc;
+ libscsi_action_get_status;
+ libscsi_action_set_status;
+ libscsi_action_get_timeout;
+ libscsi_action_set_timeout;
+ libscsi_action_get_cdb;
+ libscsi_action_get_flags;
+ libscsi_action_get_buffer;
+ libscsi_action_get_sense;
+ libscsi_action_set_datalen;
+ libscsi_action_set_senselen;
+ libscsi_action_parse_sense;
+ libscsi_sense_key_name;
+ libscsi_sense_code_name;
+ libscsi_action_free;
+ libscsi_exec;
+ libscsi_errno;
+ libscsi_errmsg;
+ libscsi_strerror;
+ libscsi_errname;
+ libscsi_errcode;
+ libscsi_assert;
+ libscsi_cmd_cdblen;
+ libscsi_vendor;
+ libscsi_product;
+ libscsi_revision;
+ libscsi_get_handle;
+
+ libscsi_alloc;
+ libscsi_zalloc;
+ libscsi_strdup;
+ libscsi_free;
+ libscsi_set_errno;
+ libscsi_verror;
+ libscsi_error;
+
+ local:
+ *;
+};
diff --git a/usr/src/lib/scsi/libscsi/sparc/Makefile b/usr/src/lib/scsi/libscsi/sparc/Makefile
new file mode 100644
index 0000000000..b68583c86f
--- /dev/null
+++ b/usr/src/lib/scsi/libscsi/sparc/Makefile
@@ -0,0 +1,30 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/scsi/libscsi/sparcv9/Makefile b/usr/src/lib/scsi/libscsi/sparcv9/Makefile
new file mode 100644
index 0000000000..e3fab7e838
--- /dev/null
+++ b/usr/src/lib/scsi/libscsi/sparcv9/Makefile
@@ -0,0 +1,31 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+include ../../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
diff --git a/usr/src/lib/scsi/libses/Makefile b/usr/src/lib/scsi/libses/Makefile
new file mode 100644
index 0000000000..abb400b621
--- /dev/null
+++ b/usr/src/lib/scsi/libses/Makefile
@@ -0,0 +1,61 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+include ../../Makefile.lib
+include ../Makefile.defs
+
+HDRS = libses.h libses_plugin.h
+ROOTHDRDIR = $(ROOTSCSIHDRDIR)
+ROOTHDRS = $(HDRS:%=$(ROOTHDRDIR)/%)
+CHECKDIRS = $(HDRS:%.h=%.check)
+HDRDIR = common
+
+SUBDIRS = $(MACH)
+$(BUILD64)SUBDIRS += $(MACH64)
+
+all := TARGET= all
+clean := TARGET= clean
+clobber := TARGET= clobber
+install := TARGET= install
+lint := TARGET= lint
+install_h:= TARGET = install_h
+
+.KEEP_STATE:
+
+all install clean clobber lint: $(SUBDIRS)
+
+install_h: $(ROOTHDRS)
+
+check: $(CHECKHDRS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+include ../Makefile.rootdirs
+include ../../Makefile.targ
diff --git a/usr/src/lib/scsi/libses/Makefile.com b/usr/src/lib/scsi/libses/Makefile.com
new file mode 100644
index 0000000000..8b27f96d60
--- /dev/null
+++ b/usr/src/lib/scsi/libses/Makefile.com
@@ -0,0 +1,40 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+LIBRARY = libses.a
+VERS = .1
+
+OBJECTS = \
+ ses_enclosure.o \
+ ses_errno.o \
+ ses_node.o \
+ ses_plugin.o \
+ ses_snap.o \
+ ses_subr.o
+
+include ../../Makefile.defs
+include ../../../Makefile.lib
diff --git a/usr/src/lib/scsi/libses/Makefile.defs b/usr/src/lib/scsi/libses/Makefile.defs
new file mode 100644
index 0000000000..96f5872fba
--- /dev/null
+++ b/usr/src/lib/scsi/libses/Makefile.defs
@@ -0,0 +1,60 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+SRCS = $(OBJECTS:%.o=../common/%.c)
+C99MODE = $(C99_ENABLE)
+CPPFLAGS += -I../common -I. -D_REENTRANT
+$(NOT_RELEASE_BUILD)CPPFLAGS += -DDEBUG
+CFLAGS += $(CCVERBOSE)
+
+ROOTLIBDIR = $(ROOTSCSILIBDIR)
+ROOTLIBDIR64 = $(ROOTSCSILIBDIR)/$(MACH64)
+
+DYNFLAGS32 += -R$(SCSILIBDIR)
+DYNFLAGS64 += -R$(SCSILIBDIR)/$(MACH64)
+
+LDLIBS32 += -L$(ROOTSCSILIBDIR)
+LDLIBS64 += -L$(ROOTSCSILIBDIR)/$(MACH64)
+
+LDLIBS += \
+ -lnvpair \
+ -lscsi \
+ -lc
+
+LIBS = $(DYNLIB) $(LINTLIB)
+
+CLEANFILES += \
+ ../common/ses_errno.c
+
+#
+# On SPARC, gcc emits DWARF assembler directives for TLS data that are not
+# understood by the Sun assembler. Until this problem is fixed, we turn down
+# the amount of generated debugging information, which seems to do the trick.
+#
+$(SPARC_BLD)CTF_FLAGS += -_gcc=-g1
+
+$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC)
diff --git a/usr/src/lib/scsi/libses/Makefile.defs.64 b/usr/src/lib/scsi/libses/Makefile.defs.64
new file mode 100644
index 0000000000..a6fe3b77dd
--- /dev/null
+++ b/usr/src/lib/scsi/libses/Makefile.defs.64
@@ -0,0 +1,28 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+DYNFLAGS += -R/usr/lib/scsi/$(MACH64)
diff --git a/usr/src/lib/scsi/libses/Makefile.targ b/usr/src/lib/scsi/libses/Makefile.targ
new file mode 100644
index 0000000000..a73a46eae4
--- /dev/null
+++ b/usr/src/lib/scsi/libses/Makefile.targ
@@ -0,0 +1,42 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+.KEEP_STATE:
+
+all : $(LIBS)
+
+lint : lintcheck
+
+../common/ses_errno.c: ../common/mkerrno.sh ../common/libses.h
+ sh ../common/mkerrno.sh < $(ROOTSCSIHDRDIR)/libses.h > $@
+
+pics/%.o: ../common/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+include ../../../Makefile.targ
+
diff --git a/usr/src/lib/scsi/libses/amd64/Makefile b/usr/src/lib/scsi/libses/amd64/Makefile
new file mode 100644
index 0000000000..aaa948e5ae
--- /dev/null
+++ b/usr/src/lib/scsi/libses/amd64/Makefile
@@ -0,0 +1,36 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+include ../../../Makefile.lib
+include ../../../Makefile.lib.64
+include ../Makefile.defs
+include ../Makefile.defs.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
+
+include ../Makefile.targ
diff --git a/usr/src/lib/scsi/libses/common/libses.h b/usr/src/lib/scsi/libses/common/libses.h
new file mode 100644
index 0000000000..7e95cb4b3a
--- /dev/null
+++ b/usr/src/lib/scsi/libses/common/libses.h
@@ -0,0 +1,132 @@
+/*
+ * 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.
+ */
+
+#ifndef _LIBSES_H
+#define _LIBSES_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+
+#include <stdarg.h>
+#include <libnvpair.h>
+#include <pthread.h>
+
+#include <scsi/libscsi.h>
+#include <scsi/plugins/ses/framework/ses2.h>
+#include <scsi/plugins/ses/framework/libses.h>
+
+#define LIBSES_VERSION 1
+
+typedef enum ses_node_type {
+ SES_NODE_NONE = 0x0,
+ SES_NODE_TARGET = 0x1,
+ SES_NODE_ENCLOSURE = 0x2,
+ SES_NODE_AGGREGATE = 0x4,
+ SES_NODE_ELEMENT = 0x8
+} ses_node_type_t;
+
+typedef enum ses_errno {
+ ESES_NONE, /* no error */
+ ESES_NOMEM, /* no memory */
+ ESES_ZERO_LENGTH, /* zero-length allocation requested */
+ ESES_VERSION, /* library version mismatch */
+ ESES_NVL, /* nvlist manipulation error */
+ ESES_BAD_NODE, /* bad node */
+ ESES_INVALID_OP, /* invalid operation */
+ ESES_RANGE, /* value out of range */
+ ESES_INVALID_PROP, /* nonexistent or immutable property */
+ ESES_BAD_TYPE, /* incorrect property type */
+ ESES_BAD_PAGE, /* bad page number */
+ ESES_BAD_RESPONSE, /* bad response from target */
+ ESES_BUSY, /* target busy */
+ ESES_TOOMUCHCHANGE, /* target configuration changing too rapidly */
+ ESES_LIBSCSI, /* SCSI error */
+ ESES_NOTSUP, /* operation not supported */
+ ESES_UNKNOWN, /* error of unknown type */
+ ESES_CHANGED, /* generation count has changed */
+ ESES_PLUGIN, /* invalid or missing plugin */
+ ESES_MAX /* maximum libses errno value */
+} ses_errno_t;
+
+struct ses_target;
+typedef struct ses_target ses_target_t;
+
+struct ses_snap;
+typedef struct ses_snap ses_snap_t;
+
+struct ses_node;
+typedef struct ses_node ses_node_t;
+
+extern ses_target_t *ses_open(uint_t, const char *);
+extern ses_target_t *ses_open_scsi(uint_t, libscsi_target_t *);
+extern void ses_close(ses_target_t *);
+
+extern libscsi_target_t *ses_scsi_target(ses_target_t *);
+
+typedef enum ses_walk_action {
+ SES_WALK_ACTION_CONTINUE,
+ SES_WALK_ACTION_PRUNE,
+ SES_WALK_ACTION_TERMINATE
+} ses_walk_action_t;
+
+typedef ses_walk_action_t (*ses_walk_f)(ses_node_t *, void *);
+
+extern uint64_t ses_node_id(ses_node_t *);
+extern ses_node_t *ses_node_lookup(ses_snap_t *, uint64_t);
+
+extern ses_node_t *ses_root_node(ses_snap_t *);
+extern ses_node_t *ses_node_sibling(ses_node_t *);
+extern ses_node_t *ses_node_prev_sibling(ses_node_t *);
+extern ses_node_t *ses_node_child(ses_node_t *);
+extern ses_node_t *ses_node_parent(ses_node_t *);
+extern int ses_walk(ses_snap_t *, ses_walk_f, void *);
+
+extern ses_snap_t *ses_snap_hold(ses_target_t *);
+extern void ses_snap_rele(ses_snap_t *);
+extern ses_snap_t *ses_snap_new(ses_target_t *);
+extern uint32_t ses_snap_generation(ses_snap_t *);
+
+extern ses_node_type_t ses_node_type(ses_node_t *);
+extern nvlist_t *ses_node_props(ses_node_t *);
+extern int ses_node_ctl(ses_node_t *, const char *, nvlist_t *);
+extern ses_snap_t *ses_node_snapshot(ses_node_t *);
+extern ses_target_t *ses_node_target(ses_node_t *);
+
+extern ses_errno_t ses_errno(void);
+extern const char *ses_errmsg(void);
+extern const char *ses_strerror(ses_errno_t);
+extern const char *ses_nv_error_member(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBSES_H */
diff --git a/usr/src/lib/scsi/libses/common/libses_plugin.h b/usr/src/lib/scsi/libses/common/libses_plugin.h
new file mode 100644
index 0000000000..7156da7bdf
--- /dev/null
+++ b/usr/src/lib/scsi/libses/common/libses_plugin.h
@@ -0,0 +1,161 @@
+/*
+ * 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.
+ */
+
+#ifndef _LIBSES_PLUGIN_H
+#define _LIBSES_PLUGIN_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LIBSES_PLUGIN_VERSION 1
+
+/*
+ * These are the primary APIs for plugins to interact with libses.
+ */
+
+struct ses_plugin;
+typedef struct ses_plugin ses_plugin_t;
+
+typedef enum {
+ SES_PAGE_DIAG,
+ SES_PAGE_CTL
+} ses_pagetype_t;
+
+typedef struct ses_pagedesc {
+ int spd_pagenum;
+ size_t (*spd_ctl_len)(uint_t, int, size_t);
+ void *(*spd_ctl_fill)(ses_plugin_t *, void *, size_t,
+ ses_node_t *);
+ void *(*spd_index)(ses_plugin_t *, ses_node_t *,
+ void *, size_t, size_t *);
+ int spd_gcoff;
+} ses_pagedesc_t;
+
+typedef struct ses_plugin_config {
+ ses_pagedesc_t *spc_pages;
+ int (*spc_node_parse)(ses_plugin_t *, ses_node_t *);
+ int (*spc_node_ctl)(ses_plugin_t *, ses_node_t *,
+ const char *, nvlist_t *);
+} ses_plugin_config_t;
+
+extern int ses_plugin_register(ses_plugin_t *, int, ses_plugin_config_t *);
+
+extern void *ses_plugin_page_lookup(ses_plugin_t *, ses_snap_t *, int,
+ ses_node_t *, size_t *);
+
+extern void *ses_plugin_ctlpage_lookup(ses_plugin_t *, ses_snap_t *, int,
+ size_t, ses_node_t *, boolean_t);
+
+extern void ses_plugin_setspecific(ses_plugin_t *, void *);
+extern void *ses_plugin_getspecific(ses_plugin_t *);
+
+/*
+ * The following are support functions provided by libses.
+ */
+
+extern int ses_assert(const char *, const char *, int);
+
+#define VERIFY(x) ((void)((x) || ses_assert(#x, __FILE__, __LINE__)))
+
+#ifdef DEBUG
+#define ASSERT(x) VERIFY(x)
+#else
+#define ASSERT(x)
+#endif
+
+#define SES_NV_ADD(_t, _e, _l, _n, ...) \
+ if (((_e) = nvlist_add_##_t((_l), (_n), __VA_ARGS__)) != 0) \
+ return (ses_set_nverrno((_e), (_n)))
+
+#define SES_NV_ADD_OR_FREE(_t, _e, _l, _n, ...) \
+ if (((_e) = nvlist_add_##_t((_l), (_n), __VA_ARGS__)) != 0) { \
+ nvlist_free(_l); return (ses_set_nverrno((_e), (_n))); }
+
+#define SES_NV_ADD_FS(_e, _l, _name, _buf) \
+ SES_NV_ADD(fixed_string, (_e), (_l), (_name), (_buf), sizeof (_buf))
+
+#define SES_NV_ADD_FS_TRUNC(_e, _l, _name, _buf) \
+ SES_NV_ADD(fixed_string_trunc, (_e), (_l), (_name), (_buf), \
+ sizeof (_buf))
+
+#define SES_NV_CTLBOOL(_l, _n, _b) \
+ { \
+ boolean_t v = B_FALSE; \
+ (void) nvlist_lookup_boolean_value((_l), (_n), &v); \
+ (_b) = v; \
+ }
+
+#define SES_NV_CTLBOOL_INVERT(_l, _n, _b) \
+ { \
+ boolean_t v = B_FALSE; \
+ (void) nvlist_lookup_boolean_value((_l), (_n), &v); \
+ (_b) = !v; \
+ }
+
+#define SES_NV_CTL64(_l, _n, _v) \
+ { \
+ uint64_t v = 0; \
+ (void) nvlist_lookup_uint64((_l), (_n), &v); \
+ (_v) = v; \
+ }
+
+#define SES_NV_CTL16(_l, _n, _v) \
+ { \
+ uint16_t v = 0; \
+ (void) nvlist_lookup_uint16((_l), (_n), &v); \
+ SCSI_WRITE16(&(_v), v); \
+ }
+
+extern void *ses_alloc(size_t);
+extern void *ses_zalloc(size_t);
+extern char *ses_strdup(const char *);
+extern void *ses_realloc(void *, size_t);
+extern void ses_free(void *);
+
+extern int ses_set_errno(ses_errno_t);
+extern int ses_set_nverrno(int, const char *);
+extern int ses_error(ses_errno_t, const char *, ...);
+extern int ses_nverror(int, const char *, const char *, ...);
+extern void ses_panic(const char *, ...) __NORETURN;
+
+extern int nvlist_add_fixed_string(nvlist_t *, const char *,
+ const char *, size_t);
+extern int nvlist_add_fixed_string_trunc(nvlist_t *, const char *,
+ const char *, size_t);
+
+#define SES_WITHIN_PAGE(sp, size, data, len) \
+ ((char *)(sp) <= (char *)(data) + (len) - (size))
+#define SES_WITHIN_PAGE_STRUCT(sp, data, len) \
+ SES_WITHIN_PAGE((sp), sizeof (*(sp)), (data), (len))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBSES_PLUGIN_H */
diff --git a/usr/src/lib/scsi/libses/common/mkerrno.sh b/usr/src/lib/scsi/libses/common/mkerrno.sh
new file mode 100644
index 0000000000..a796ddee67
--- /dev/null
+++ b/usr/src/lib/scsi/libses/common/mkerrno.sh
@@ -0,0 +1,86 @@
+#!/bin/sh
+#
+# 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"
+
+echo "/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident\t\"%Z%%M%\t%I%\t%E% SMI\"
+
+#include <strings.h>
+#include <scsi/libses.h>
+
+static const struct {
+\tchar *se_name;\t\t/* error name */
+\tchar *se_msg;\t\t/* error message */
+} _ses_errstr[] = {"
+
+pattern='^ \(ESES_[A-Z0-9_]*\),*'
+replace=' { "\1",'
+open=' \/\* '
+openrepl='"'
+close=' \*\/$'
+closerepl='" },'
+
+( sed -n "s/$pattern/$replace/p" | sed -n "s/$open/$openrepl/p" |
+ sed -n "s/$close/$closerepl/p" ) || exit 1
+
+echo "\
+};\n\
+\n\
+static int _ses_nerrno = sizeof (_ses_errstr) / sizeof (_ses_errstr[0]);\n\
+\n\
+const char *
+ses_strerror(ses_errno_t err)
+{
+ return (err < 0 || err >= _ses_nerrno ? \"unknown error\" :
+ _ses_errstr[err].se_msg);
+}
+
+const char *
+ses_errname(ses_errno_t err)
+{
+ return (err < 0 || err >= _ses_nerrno ? NULL :
+ _ses_errstr[err].se_name);
+}
+
+ses_errno_t
+ses_errcode(const char *name)
+{
+ ses_errno_t err;
+
+ for (err = 0; err < _ses_nerrno; err++) {
+ if (strcmp(name, _ses_errstr[err].se_name) == 0)
+ return (err);
+ }
+
+ return (ESES_UNKNOWN);
+}"
+
+exit 0
diff --git a/usr/src/lib/scsi/libses/common/ses_enclosure.c b/usr/src/lib/scsi/libses/common/ses_enclosure.c
new file mode 100644
index 0000000000..4d2af5cc55
--- /dev/null
+++ b/usr/src/lib/scsi/libses/common/ses_enclosure.c
@@ -0,0 +1,293 @@
+/*
+ * 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"
+
+#include <scsi/libses.h>
+#include "ses_impl.h"
+
+int
+enc_parse_td(ses2_td_hdr_impl_t *tip, const char *tp, nvlist_t *nvl)
+{
+ int nverr;
+
+ if (tp != NULL)
+ SES_NV_ADD(fixed_string, nverr, nvl, SES_PROP_CLASS_DESCRIPTION,
+ tp, tip->sthi_text_len);
+
+ return (0);
+}
+
+static int
+enc_eid(const ses2_ed_impl_t *tp, nvlist_t *nvl, const char *name)
+{
+ int nverr;
+
+ SES_NV_ADD(uint64, nverr, nvl, name, tp->st_hdr.sehi_subenclosure_id);
+
+ return (0);
+}
+
+static int
+enc_espid(const ses2_ed_impl_t *tp, nvlist_t *nvl, const char *name)
+{
+ int nverr;
+
+ SES_NV_ADD(uint64, nverr, nvl, name, tp->st_hdr.sehi_rel_esp_id);
+
+ return (0);
+}
+
+static int
+enc_nesp(const ses2_ed_impl_t *tp, nvlist_t *nvl, const char *name)
+{
+ int nverr;
+
+ SES_NV_ADD(uint64, nverr, nvl, name, tp->st_hdr.sehi_n_esps);
+
+ return (0);
+}
+
+static int
+enc_lid(const ses2_ed_impl_t *tp, nvlist_t *nvl, const char *name)
+{
+ nvlist_t *lid;
+ int nverr;
+
+ if ((nverr = nvlist_alloc(&lid, NV_UNIQUE_NAME, 0)) != 0)
+ return (ses_set_nverrno(nverr, NULL));
+
+ SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_INT,
+ SCSI_READ64(&tp->st_logical_id));
+
+ switch (tp->st_logical_id.sni8i_naa) {
+ case NAA_IEEE_EXT:
+ SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_ID_TYPE,
+ NAA_IEEE_EXT);
+ SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_COMPANY_ID,
+ NAA_IEEE_EXT_COMPANY_ID(&tp->st_logical_id.sni8i_ext_id));
+ SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_VS_A,
+ NAA_IEEE_EXT_VENDOR_A(&tp->st_logical_id.sni8i_ext_id));
+ SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_VS_B,
+ NAA_IEEE_EXT_VENDOR_B(&tp->st_logical_id.sni8i_ext_id));
+ break;
+ case NAA_IEEE_REG:
+ SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_ID_TYPE,
+ NAA_IEEE_REG);
+ SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_COMPANY_ID,
+ NAA_IEEE_REG_COMPANY_ID(&tp->st_logical_id.sni8i_reg_id));
+ SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_VS_A,
+ NAA_IEEE_REG_VENDOR_ID(&tp->st_logical_id.sni8i_reg_id));
+ break;
+ default:
+ break;
+ }
+
+ if ((nverr = nvlist_add_nvlist(nvl, name, lid)) != 0) {
+ nvlist_free(lid);
+ return (ses_set_nverrno(nverr, name));
+ }
+
+ nvlist_free(lid);
+
+ return (0);
+}
+
+static int
+enc_vid(const ses2_ed_impl_t *tp, nvlist_t *nvl,
+ const char *name)
+{
+ int nverr;
+
+ SES_NV_ADD_FS_TRUNC(nverr, nvl, name, tp->st_vendor_id);
+
+ return (0);
+}
+
+static int
+enc_pid(const ses2_ed_impl_t *tp, nvlist_t *nvl,
+ const char *name)
+{
+ int nverr;
+
+ SES_NV_ADD_FS_TRUNC(nverr, nvl, name, tp->st_product_id);
+
+ return (0);
+}
+
+static int
+enc_rev(const ses2_ed_impl_t *tp, nvlist_t *nvl,
+ const char *name)
+{
+ int nverr;
+
+ SES_NV_ADD_FS_TRUNC(nverr, nvl, name, tp->st_product_revision);
+
+ return (0);
+}
+
+static int
+enc_vs(const ses2_ed_impl_t *tp, nvlist_t *nvl, const char *name)
+{
+ int nverr;
+
+ SES_NV_ADD(byte_array, nverr, nvl, name, (uchar_t *)tp->st_priv,
+ tp->st_hdr.sehi_ed_len - offsetof(ses2_ed_impl_t, st_priv[0]));
+
+ return (0);
+}
+
+/* LINTED - unused */
+static const ses2_ed_impl_t __ed = { 0 };
+
+#define ED_REQ_LEN(member) \
+ (offsetof(ses2_ed_impl_t, member) - sizeof (ses2_ed_hdr_impl_t) + \
+ sizeof (__ed.member))
+
+static const struct config_member {
+ const char *name;
+ size_t minsz;
+ int (*func)(const ses2_ed_impl_t *, nvlist_t *, const char *);
+} config_members[] = {
+ { SES_EN_PROP_EID, 0, enc_eid },
+ { SES_EN_PROP_ESPID, 0, enc_espid },
+ { SES_EN_PROP_NESP, 0, enc_nesp },
+ { SES_EN_PROP_LID, ED_REQ_LEN(st_logical_id), enc_lid },
+ { SES_EN_PROP_VID, ED_REQ_LEN(st_vendor_id), enc_vid },
+ { SES_EN_PROP_PID, ED_REQ_LEN(st_product_id), enc_pid },
+ { SES_EN_PROP_REV, ED_REQ_LEN(st_product_revision), enc_rev },
+ { SES_EN_PROP_VS, ED_REQ_LEN(st_priv), enc_vs },
+ { NULL, 0, NULL }
+};
+
+int
+enc_parse_ed(ses2_ed_impl_t *tp, nvlist_t *nvl)
+{
+ const struct config_member *mp;
+ int err;
+
+ if (tp == NULL)
+ return (0);
+
+ for (mp = &config_members[0]; mp->name != NULL; mp++) {
+ if (mp->func != NULL && tp->st_hdr.sehi_ed_len >= mp->minsz) {
+ err = mp->func(tp, nvl, mp->name);
+ if (err != 0)
+ return (err);
+ }
+ }
+
+ return (0);
+}
+
+ses_target_t *
+ses_open_scsi(uint_t version, libscsi_target_t *stp)
+{
+ ses_target_t *tp;
+ ses_snap_t *sp;
+
+ if (version != LIBSES_VERSION) {
+ (void) ses_set_errno(ESES_VERSION);
+ return (NULL);
+ }
+
+ if ((tp = ses_zalloc(sizeof (ses_target_t))) == NULL)
+ return (NULL);
+
+ tp->st_target = stp;
+ tp->st_scsi_hdl = libscsi_get_handle(stp);
+ tp->st_truncate = (getenv("LIBSES_TRUNCATE") != NULL);
+ if (tp->st_truncate)
+ srand48(gethrtime());
+
+ (void) pthread_mutex_init(&tp->st_lock, NULL);
+
+ if (ses_plugin_load(tp) != 0) {
+ ses_close(tp);
+ return (NULL);
+ }
+
+ if ((sp = ses_snap_new(tp)) == NULL) {
+ ses_close(tp);
+ return (NULL);
+ }
+
+ ses_snap_rele(sp);
+
+ return (tp);
+}
+
+ses_target_t *
+ses_open(uint_t version, const char *target)
+{
+ ses_target_t *tp;
+ libscsi_errno_t serr;
+ libscsi_target_t *stp;
+ libscsi_hdl_t *hp;
+
+ if ((hp = libscsi_init(LIBSCSI_VERSION, &serr)) == NULL) {
+ (void) ses_error(ESES_LIBSCSI, "failed to initialize "
+ "libscsi: %s", libscsi_strerror(serr));
+ return (NULL);
+ }
+
+ if ((stp = libscsi_open(hp, NULL, target)) == NULL) {
+ (void) ses_libscsi_error(hp, "failed to open SES target");
+ libscsi_fini(hp);
+ return (NULL);
+ }
+
+ if ((tp = ses_open_scsi(version, stp)) == NULL) {
+ libscsi_close(hp, stp);
+ libscsi_fini(hp);
+ return (NULL);
+ }
+
+ tp->st_closescsi = B_TRUE;
+
+ return (tp);
+}
+
+libscsi_target_t *
+ses_scsi_target(ses_target_t *tp)
+{
+ return (tp->st_target);
+}
+
+void
+ses_close(ses_target_t *tp)
+{
+ if (tp->st_snapshots != NULL)
+ ses_snap_rele(tp->st_snapshots);
+ if (tp->st_snapshots != NULL)
+ ses_panic("attempt to close SES target with active snapshots");
+ ses_plugin_unload(tp);
+ if (tp->st_closescsi) {
+ libscsi_close(tp->st_scsi_hdl, tp->st_target);
+ libscsi_fini(tp->st_scsi_hdl);
+ }
+ ses_free(tp);
+}
diff --git a/usr/src/lib/scsi/libses/common/ses_impl.h b/usr/src/lib/scsi/libses/common/ses_impl.h
new file mode 100644
index 0000000000..a820f31787
--- /dev/null
+++ b/usr/src/lib/scsi/libses/common/ses_impl.h
@@ -0,0 +1,170 @@
+/*
+ * 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.
+ */
+
+#ifndef _SES_IMPL_H
+#define _SES_IMPL_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <alloca.h>
+#include <errno.h>
+#include <assert.h>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <limits.h>
+#include <pthread.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <libnvpair.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/sysmacros.h>
+#include <sys/systeminfo.h>
+
+#include <scsi/libscsi.h>
+#include <scsi/libses_plugin.h>
+#include <scsi/plugins/ses/framework/ses2_impl.h>
+
+#define LIBSES_ERRMSGLEN 512
+
+#define LIBSES_DEFAULT_PLUGINDIR "/usr/lib/scsi/plugins/ses"
+#define LIBSES_PLUGIN_FRAMEWORK "framework"
+#define LIBSES_PLUGIN_VENDOR "vendor"
+
+#define LIBSES_PLUGIN_EXT ".so"
+
+struct ses_plugin {
+ struct ses_plugin *sp_next; /* next plugin in list */
+ struct ses_plugin *sp_prev; /* previous plugin in list */
+ uint64_t sp_priority; /* plugin priority */
+ struct ses_target *sp_target; /* corresponding target */
+ void *sp_object; /* shared object */
+ void *sp_data; /* module-specific data */
+ boolean_t sp_initialized; /* successfully initialized */
+ ses_pagedesc_t *sp_pages; /* pages */
+ int (*sp_init)(ses_plugin_t *); /* plugin init */
+ void (*sp_fini)(ses_plugin_t *); /* plugin fini */
+ int (*sp_node_parse)(ses_plugin_t *, ses_node_t *); /* parse node */
+ int (*sp_node_ctl)(ses_plugin_t *, ses_node_t *, const char *,
+ nvlist_t *); /* node control */
+};
+
+struct ses_target {
+ libscsi_hdl_t *st_scsi_hdl;
+ libscsi_target_t *st_target;
+ struct ses_plugin *st_plugin_first;
+ struct ses_plugin *st_plugin_last;
+ struct ses_snap *st_snapshots;
+ boolean_t st_closescsi;
+ boolean_t st_truncate;
+ pthread_mutex_t st_lock;
+};
+
+/*
+ * Maximum number of snapshot retries triggered by generation count changes
+ */
+#define LIBSES_MAX_GC_RETRIES 10
+
+/*
+ * Maximum number of Enclosure Busy retries
+ */
+#define LIBSES_MAX_BUSY_RETRIES 3
+
+typedef struct ses_snap_page {
+ ses2_diag_page_t ssp_num;
+ boolean_t ssp_control;
+ boolean_t ssp_initialized;
+ size_t ssp_alloc;
+ size_t ssp_len;
+ void *ssp_page;
+ char *ssp_mmap_base;
+ size_t ssp_mmap_len;
+ struct ses_snap_page *ssp_next;
+ struct ses_snap_page *ssp_unique;
+} ses_snap_page_t;
+
+struct ses_snap {
+ struct ses_target *ss_target;
+ uint32_t ss_generation;
+ hrtime_t ss_time;
+ struct ses_node *ss_root;
+ size_t ss_n_elem;
+ ses_snap_page_t *ss_pages;
+ size_t ss_n_nodes;
+ struct ses_node **ss_nodes;
+ struct ses_snap *ss_next;
+ struct ses_snap *ss_prev;
+ uint32_t ss_refcnt;
+};
+
+struct ses_node {
+ ses_node_type_t sn_type;
+ uint64_t sn_rootidx; /* Relative index for enclosure/aggregate */
+ size_t sn_id; /* Unique global ID */
+ uint64_t sn_enc_num;
+ struct ses_snap *sn_snapshot;
+ struct ses_node *sn_parent;
+ struct ses_node *sn_next_sibling;
+ struct ses_node *sn_prev_sibling;
+ struct ses_node *sn_first_child;
+ struct ses_node *sn_last_child;
+ nvlist_t *sn_props;
+};
+
+extern int ses_fill_snap(ses_snap_t *);
+extern void ses_node_teardown(ses_node_t *);
+extern ses_snap_page_t *ses_snap_find_page(ses_snap_t *, ses2_diag_page_t,
+ boolean_t);
+extern ses_snap_page_t *ses_snap_ctl_page(ses_snap_t *,
+ ses2_diag_page_t, size_t, boolean_t);
+extern int ses_snap_do_ctl(ses_snap_t *);
+
+extern int ses_libscsi_error(libscsi_hdl_t *, const char *, ...);
+extern int ses_scsi_error(libscsi_action_t *, const char *, ...);
+
+extern int ses_plugin_load(ses_target_t *);
+extern void ses_plugin_unload(ses_target_t *);
+
+extern ses_pagedesc_t *ses_get_pagedesc(ses_target_t *, int, ses_pagetype_t);
+extern int ses_fill_node(ses_node_t *);
+
+extern int enc_parse_ed(ses2_ed_impl_t *, nvlist_t *);
+extern int enc_parse_td(ses2_td_hdr_impl_t *, const char *, nvlist_t *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SES_IMPL_H */
diff --git a/usr/src/lib/scsi/libses/common/ses_node.c b/usr/src/lib/scsi/libses/common/ses_node.c
new file mode 100644
index 0000000000..6e08a20874
--- /dev/null
+++ b/usr/src/lib/scsi/libses/common/ses_node.c
@@ -0,0 +1,399 @@
+/*
+ * 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"
+
+#include <scsi/libses.h>
+#include "ses_impl.h"
+
+#define NEXT_ED(eip) \
+ ((ses2_ed_impl_t *)((uint8_t *)(eip) + \
+ ((eip)->st_hdr.sehi_ed_len + sizeof (ses2_ed_hdr_impl_t))))
+
+static ses_node_t *
+ses_find_enclosure(ses_snap_t *sp, uint64_t number)
+{
+ ses_node_t *np;
+
+ for (np = sp->ss_root->sn_first_child; np != NULL;
+ np = np->sn_next_sibling) {
+ ASSERT(np->sn_type == SES_NODE_ENCLOSURE);
+ if (np->sn_enc_num == number)
+ return ((ses_node_t *)np);
+ }
+
+ return (NULL);
+}
+
+void
+ses_node_teardown(ses_node_t *np)
+{
+ ses_node_t *rp;
+
+ if (np == NULL)
+ return;
+
+ for (; np != NULL; np = rp) {
+ ses_node_teardown(np->sn_first_child);
+ rp = np->sn_next_sibling;
+ nvlist_free(np->sn_props);
+ ses_free(np);
+ }
+}
+
+static ses_node_t *
+ses_node_alloc(ses_snap_t *sp, ses_node_t *pnp)
+{
+ ses_node_t *np;
+
+ np = ses_zalloc(sizeof (ses_node_t));
+ if (np == NULL)
+ goto fail;
+ if (nvlist_alloc(&np->sn_props, NV_UNIQUE_NAME, 0) != 0)
+ goto fail;
+
+ np->sn_snapshot = sp;
+ np->sn_id = sp->ss_n_nodes++;
+
+ if (pnp == NULL) {
+ ASSERT(sp->ss_root == NULL);
+ sp->ss_root = np;
+ } else {
+ np->sn_parent = pnp;
+ np->sn_prev_sibling = pnp->sn_last_child;
+
+ if (pnp->sn_first_child == NULL)
+ pnp->sn_first_child = np;
+ else
+ pnp->sn_last_child->sn_next_sibling = np;
+
+ pnp->sn_last_child = np;
+ }
+
+ return (np);
+
+fail:
+ ses_free(np);
+ ses_node_teardown(sp->ss_root);
+ sp->ss_root = NULL;
+ return (NULL);
+}
+
+/*
+ * Parse element type descriptor.
+ */
+static int
+elem_parse_td(ses2_td_hdr_impl_t *tip, const char *tp, nvlist_t *nvl)
+{
+ int nverr;
+
+ if (tp != NULL)
+ SES_NV_ADD(fixed_string, nverr, nvl, SES_PROP_CLASS_DESCRIPTION,
+ tp, tip->sthi_text_len);
+
+ return (0);
+}
+
+
+/*
+ * Build a skeleton tree of nodes in the given snapshot. This is the heart of
+ * libses, and is responsible for parsing the config page into a tree and
+ * populating nodes with data from the config page.
+ */
+static int
+ses_build_snap_skel(ses_snap_t *sp)
+{
+ ses2_ed_impl_t *eip;
+ ses2_td_hdr_impl_t *tip, *ftip;
+ ses_node_t *np, *pnp, *cnp, *root;
+ ses_snap_page_t *pp;
+ ses2_config_page_impl_t *pip;
+ int i, j, n_etds = 0;
+ off_t toff;
+ char *tp, *text;
+ int err;
+ uint64_t idx;
+
+ pp = ses_snap_find_page(sp, SES2_DIAGPAGE_CONFIG, B_FALSE);
+ if (pp == NULL)
+ return (ses_error(ESES_BAD_RESPONSE, "target does not support "
+ "configuration diagnostic page"));
+ pip = (ses2_config_page_impl_t *)pp->ssp_page;
+
+ if (pp->ssp_len < offsetof(ses2_config_page_impl_t, scpi_data))
+ return (ses_error(ESES_BAD_RESPONSE, "no enclosure "
+ "descriptors found"));
+
+ /*
+ * Start with the root of the tree, which is a target node, containing
+ * just the SCSI inquiry properties.
+ */
+ if ((root = ses_node_alloc(sp, sp->ss_root)) == NULL)
+ return (-1);
+
+ root->sn_type = SES_NODE_TARGET;
+ SES_NV_ADD(string, err, root->sn_props, SCSI_PROP_VENDOR,
+ libscsi_vendor(sp->ss_target->st_target));
+ SES_NV_ADD(string, err, root->sn_props, SCSI_PROP_PRODUCT,
+ libscsi_product(sp->ss_target->st_target));
+ SES_NV_ADD(string, err, root->sn_props, SCSI_PROP_REVISION,
+ libscsi_revision(sp->ss_target->st_target));
+
+ for (eip = (ses2_ed_impl_t *)pip->scpi_data, i = 0;
+ i < pip->scpi_n_subenclosures + 1;
+ i++, eip = NEXT_ED(eip)) {
+ if (!SES_WITHIN_PAGE_STRUCT(eip, pp->ssp_page, pp->ssp_len))
+ break;
+
+ n_etds += eip->st_hdr.sehi_n_etd_hdrs;
+ }
+ ftip = (ses2_td_hdr_impl_t *)eip;
+
+ /*
+ * There should really be only one Enclosure element possible for a
+ * give subenclosure ID. The standard never comes out and says this,
+ * but it does describe this element as "managing the enclosure itself"
+ * which implies rather strongly that the subenclosure ID field is that
+ * of, well, the enclosure itself. Since an enclosure can't contain
+ * itself, it follows logically that each subenclosure has at most one
+ * Enclosure type descriptor elements matching its ID. Of course, some
+ * enclosure firmware is buggy, so this may not always work out; in
+ * this case we just ignore all but the first Enclosure-type element
+ * with our subenclosure ID.
+ */
+ for (eip = (ses2_ed_impl_t *)pip->scpi_data, i = 0;
+ i < pip->scpi_n_subenclosures + 1;
+ i++, eip = NEXT_ED(eip)) {
+ if (!SES_WITHIN_PAGE_STRUCT(eip, pp->ssp_page, pp->ssp_len))
+ break;
+
+ if ((np = ses_node_alloc(sp, root)) == NULL)
+ return (-1);
+
+ np->sn_type = SES_NODE_ENCLOSURE;
+ np->sn_enc_num = eip->st_hdr.sehi_subenclosure_id;
+
+ if (!SES_WITHIN_PAGE(eip, eip->st_hdr.sehi_ed_len +
+ sizeof (ses2_ed_hdr_impl_t),
+ pp->ssp_page, pp->ssp_len))
+ break;
+
+ if (enc_parse_ed(eip, np->sn_props) != 0)
+ return (-1);
+ }
+
+ if (root->sn_first_child == NULL)
+ return (ses_error(ESES_BAD_RESPONSE, "no enclosure "
+ "descriptors found"));
+
+ tp = (char *)(ftip + n_etds);
+
+ for (i = 0, toff = 0, idx = 0; i < n_etds; i++) {
+ tip = ftip + i;
+
+ if (!SES_WITHIN_PAGE_STRUCT(tip, pp->ssp_page, pp->ssp_len))
+ break;
+
+ pnp = ses_find_enclosure(sp,
+ tip->sthi_subenclosure_id);
+ if (pnp == NULL) {
+ idx += tip->sthi_max_elements + 1;
+ toff += tip->sthi_text_len;
+ continue;
+ }
+
+ if (tip->sthi_element_type == SES_ET_ENCLOSURE) {
+ if (tip->sthi_max_elements == 0) {
+ SES_NV_ADD(uint64, err, pnp->sn_props,
+ SES_PROP_ELEMENT_INDEX, idx);
+ pnp->sn_rootidx = idx;
+ } else {
+ SES_NV_ADD(uint64, err, pnp->sn_props,
+ SES_PROP_ELEMENT_INDEX, idx + 1);
+ pnp->sn_rootidx = idx + 1;
+ }
+
+ if (tip->sthi_text_len > 0 &&
+ SES_WITHIN_PAGE(tp + toff, tip->sthi_text_len,
+ pp->ssp_page, pp->ssp_len)) {
+ text = tp + toff;
+ toff += tip->sthi_text_len;
+ } else {
+ text = NULL;
+ }
+
+ SES_NV_ADD(uint64, err, pnp->sn_props,
+ SES_PROP_ELEMENT_TYPE, SES_ET_ENCLOSURE);
+ if (enc_parse_td(tip, text, pnp->sn_props) != 0)
+ return (-1);
+
+ idx += tip->sthi_max_elements + 1;
+ continue;
+ }
+
+ if ((np = ses_node_alloc(sp, pnp)) == NULL)
+ return (-1);
+
+ np->sn_type = SES_NODE_AGGREGATE;
+ np->sn_enc_num = tip->sthi_subenclosure_id;
+ np->sn_parent = pnp;
+ np->sn_rootidx = idx;
+
+ SES_NV_ADD(uint64, err, np->sn_props,
+ SES_PROP_ELEMENT_INDEX, idx);
+ SES_NV_ADD(uint64, err, np->sn_props,
+ SES_PROP_ELEMENT_TYPE, tip->sthi_element_type);
+
+ if (tip->sthi_text_len > 0 &&
+ SES_WITHIN_PAGE(tp + toff, tip->sthi_text_len,
+ pp->ssp_page, pp->ssp_len)) {
+ text = tp + toff;
+ toff += tip->sthi_text_len;
+ } else {
+ text = NULL;
+ }
+
+ if (elem_parse_td(tip, text, np->sn_props) != 0)
+ return (-1);
+
+ idx += tip->sthi_max_elements + 1;
+
+ if (tip->sthi_max_elements == 0)
+ continue;
+
+ for (j = 0; j < tip->sthi_max_elements; j++) {
+ cnp = ses_node_alloc(sp, np);
+ if (cnp == NULL)
+ return (-1);
+
+ cnp->sn_type = SES_NODE_ELEMENT;
+ SES_NV_ADD(uint64, err, cnp->sn_props,
+ SES_PROP_ELEMENT_INDEX, np->sn_rootidx + j + 1);
+ SES_NV_ADD(uint64, err, cnp->sn_props,
+ SES_PROP_ELEMENT_CLASS_INDEX, j);
+ SES_NV_ADD(uint64, err, cnp->sn_props,
+ SES_PROP_ELEMENT_TYPE, tip->sthi_element_type);
+ }
+ }
+
+ np->sn_snapshot->ss_n_elem = idx;
+
+ return (0);
+}
+
+static int
+ses_fill_tree(ses_node_t *np)
+{
+ if (np == NULL)
+ return (0);
+
+ for (; np != NULL; np = np->sn_next_sibling) {
+ if (ses_fill_node(np) != 0)
+ return (-1);
+ if (ses_fill_tree(np->sn_first_child) != 0)
+ return (-1);
+ }
+
+ return (0);
+}
+
+int
+ses_fill_snap(ses_snap_t *sp)
+{
+ if (ses_build_snap_skel(sp) != 0)
+ return (-1);
+
+ if (ses_fill_tree(sp->ss_root) != 0)
+ return (-1);
+
+ return (0);
+}
+
+ses_node_t *
+ses_root_node(ses_snap_t *sp)
+{
+ return (sp->ss_root);
+}
+
+ses_node_t *
+ses_node_sibling(ses_node_t *np)
+{
+ return (np->sn_next_sibling);
+}
+
+ses_node_t *
+ses_node_prev_sibling(ses_node_t *np)
+{
+ return (np->sn_prev_sibling);
+}
+
+ses_node_t *
+ses_node_parent(ses_node_t *np)
+{
+ return (np->sn_parent);
+}
+
+ses_node_t *
+ses_node_child(ses_node_t *np)
+{
+ return (np->sn_first_child);
+}
+
+ses_node_type_t
+ses_node_type(ses_node_t *np)
+{
+ return (np->sn_type);
+}
+
+ses_snap_t *
+ses_node_snapshot(ses_node_t *np)
+{
+ return ((ses_snap_t *)np->sn_snapshot);
+}
+
+ses_target_t *
+ses_node_target(ses_node_t *np)
+{
+ return (np->sn_snapshot->ss_target);
+}
+
+nvlist_t *
+ses_node_props(ses_node_t *np)
+{
+ return (np->sn_props);
+}
+
+/*
+ * A node identifier is a (generation, index) tuple that can be used to lookup a
+ * node within this target at a later point. This will be valid across
+ * snapshots, though it will return failure if the generation count has changed.
+ */
+uint64_t
+ses_node_id(ses_node_t *np)
+{
+ return (((uint64_t)np->sn_snapshot->ss_generation << 32) |
+ np->sn_id);
+}
diff --git a/usr/src/lib/scsi/libses/common/ses_plugin.c b/usr/src/lib/scsi/libses/common/ses_plugin.c
new file mode 100644
index 0000000000..e419a74475
--- /dev/null
+++ b/usr/src/lib/scsi/libses/common/ses_plugin.c
@@ -0,0 +1,398 @@
+/*
+ * 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"
+
+#include <scsi/libses.h>
+#include "ses_impl.h"
+
+static boolean_t ses_plugin_dlclose;
+
+/*ARGSUSED*/
+void *
+ses_plugin_ctlpage_lookup(ses_plugin_t *sp, ses_snap_t *snap, int pagenum,
+ size_t len, ses_node_t *np, boolean_t unique)
+{
+ ses_target_t *tp = snap->ss_target;
+ ses_snap_page_t *pp;
+ ses_pagedesc_t *dp;
+
+ if ((pp = ses_snap_ctl_page(snap, pagenum, len, unique)) == NULL)
+ return (NULL);
+
+ if ((dp = ses_get_pagedesc(tp, pagenum, SES_PAGE_CTL)) == NULL)
+ return (NULL);
+
+ if (dp->spd_ctl_fill != NULL) {
+ return (dp->spd_ctl_fill(sp, pp->ssp_page,
+ pp->ssp_len, np));
+ } else {
+ return (pp->ssp_page);
+ }
+}
+
+int
+ses_fill_node(ses_node_t *np)
+{
+ ses_target_t *tp = np->sn_snapshot->ss_target;
+ ses_plugin_t *sp;
+
+ for (sp = tp->st_plugin_first; sp != NULL; sp = sp->sp_next) {
+ if (sp->sp_node_parse == NULL)
+ continue;
+
+ if (sp->sp_node_parse(sp, np) != 0)
+ return (-1);
+ }
+
+ return (0);
+}
+
+int
+ses_node_ctl(ses_node_t *np, const char *op, nvlist_t *arg)
+{
+ ses_target_t *tp = np->sn_snapshot->ss_target;
+ ses_plugin_t *sp;
+ nvlist_t *nvl;
+ nvpair_t *nvp;
+ int ret;
+
+ if (nvlist_dup(arg, &nvl, 0) != 0)
+ return (ses_set_errno(ESES_NOMEM));
+
+ /*
+ * Technically we could get away with a per-snapshot lock while we fill
+ * the control page contents, but this doesn't take much time and we
+ * want actual control operations to be protected per-target, so we just
+ * take the target lock.
+ */
+ (void) pthread_mutex_lock(&tp->st_lock);
+
+ /*
+ * We walk the list of plugins backwards, so that a product-specific
+ * plugin can rewrite the nvlist to control operations in terms of the
+ * standard mechanisms, if desired.
+ */
+ for (sp = tp->st_plugin_first; sp != NULL; sp = sp->sp_next) {
+ if (sp->sp_node_ctl == NULL)
+ continue;
+
+ if (sp->sp_node_ctl(sp, np, op, nvl) != 0) {
+ nvlist_free(nvl);
+ (void) pthread_mutex_unlock(&tp->st_lock);
+ return (-1);
+ }
+ }
+
+ if ((nvp = nvlist_next_nvpair(nvl, NULL)) != NULL) {
+ (void) ses_error(ESES_NOTSUP, "property '%s' invalid for "
+ "this node", nvpair_name(nvp));
+ nvlist_free(nvl);
+ (void) pthread_mutex_unlock(&tp->st_lock);
+ return (-1);
+ }
+
+ nvlist_free(nvl);
+
+ ret = ses_snap_do_ctl(np->sn_snapshot);
+ (void) pthread_mutex_unlock(&tp->st_lock);
+
+ return (ret);
+}
+
+/*ARGSUSED*/
+void *
+ses_plugin_page_lookup(ses_plugin_t *sp, ses_snap_t *snap, int pagenum,
+ ses_node_t *np, size_t *lenp)
+{
+ ses_snap_page_t *pp;
+ ses_target_t *tp = sp->sp_target;
+ ses_pagedesc_t *dp;
+
+ if ((dp = ses_get_pagedesc(tp, pagenum, SES_PAGE_DIAG)) == NULL)
+ return (NULL);
+
+ if ((pp = ses_snap_find_page(snap, pagenum, B_FALSE)) == NULL)
+ return (NULL);
+
+ if (dp->spd_index != NULL) {
+ return (dp->spd_index(sp, np, pp->ssp_page, pp->ssp_len,
+ lenp));
+ } else {
+ *lenp = pp->ssp_len;
+ return (pp->ssp_page);
+ }
+}
+
+ses_pagedesc_t *
+ses_get_pagedesc(ses_target_t *tp, int pagenum, ses_pagetype_t type)
+{
+ ses_plugin_t *sp;
+ ses_pagedesc_t *dp;
+
+ for (sp = tp->st_plugin_first; sp != NULL; sp = sp->sp_next) {
+ if (sp->sp_pages == NULL)
+ continue;
+
+ for (dp = &sp->sp_pages[0]; dp->spd_pagenum != -1;
+ dp++) {
+ if ((type == SES_PAGE_CTL && dp->spd_ctl_len == NULL) ||
+ (type == SES_PAGE_DIAG && dp->spd_ctl_len != NULL))
+ continue;
+
+ if (dp->spd_pagenum == pagenum)
+ return (dp);
+ }
+ }
+
+ (void) ses_error(ESES_BAD_PAGE, "failed to find page 0x%x", pagenum);
+ return (NULL);
+}
+
+int
+ses_plugin_register(ses_plugin_t *sp, int version, ses_plugin_config_t *scp)
+{
+ if (version != LIBSES_PLUGIN_VERSION)
+ return (ses_set_errno(ESES_VERSION));
+
+ sp->sp_pages = scp->spc_pages;
+ sp->sp_node_parse = scp->spc_node_parse;
+ sp->sp_node_ctl = scp->spc_node_ctl;
+
+ return (0);
+}
+
+void
+ses_plugin_setspecific(ses_plugin_t *sp, void *data)
+{
+ sp->sp_data = data;
+}
+
+void *
+ses_plugin_getspecific(ses_plugin_t *sp)
+{
+ return (sp->sp_data);
+}
+
+static void
+ses_plugin_cleanstr(char *s)
+{
+ while (*s != '\0') {
+ if (*s == ' ' || *s == '/')
+ *s = '-';
+ s++;
+ }
+}
+
+static void
+ses_plugin_destroy(ses_plugin_t *sp)
+{
+ if (sp->sp_initialized && sp->sp_fini != NULL)
+ sp->sp_fini(sp);
+
+ if (!ses_plugin_dlclose)
+ (void) dlclose(sp->sp_object);
+
+ ses_free(sp);
+}
+
+static int
+ses_plugin_loadone(ses_target_t *tp, const char *path, uint32_t pass)
+{
+ ses_plugin_t *sp, **loc;
+ void *obj;
+ int (*ses_priority)(void);
+
+ if ((obj = dlopen(path, RTLD_PARENT | RTLD_LOCAL | RTLD_LAZY)) == NULL)
+ return (0);
+
+ if ((sp = ses_zalloc(sizeof (ses_plugin_t))) == NULL) {
+ (void) dlclose(obj);
+ return (-1);
+ }
+
+ sp->sp_object = obj;
+ sp->sp_init = (int (*)())dlsym(obj, "_ses_init");
+ sp->sp_fini = (void (*)())dlsym(obj, "_ses_fini");
+ sp->sp_target = tp;
+
+ if (sp->sp_init == NULL) {
+ ses_plugin_destroy(sp);
+ return (0);
+ }
+
+ /*
+ * Framework modules can establish an explicit prioritying by declaring
+ * the '_ses_priority' symbol, which returns an integer used to create
+ * an explicit ordering between plugins.
+ */
+ if ((ses_priority = (int (*)())dlsym(obj, "_ses_priority")) != NULL)
+ sp->sp_priority = ses_priority();
+
+ sp->sp_priority |= (uint64_t)pass << 32;
+
+ for (loc = &tp->st_plugin_first; *loc != NULL; loc = &(*loc)->sp_next) {
+ if ((*loc)->sp_priority > sp->sp_priority)
+ break;
+ }
+
+ if (*loc != NULL)
+ (*loc)->sp_prev = sp;
+ else
+ tp->st_plugin_last = sp;
+
+ sp->sp_next = *loc;
+ *loc = sp;
+
+ if (sp->sp_init(sp) != 0)
+ return (-1);
+ sp->sp_initialized = B_TRUE;
+
+ return (0);
+}
+
+static int
+ses_plugin_load_dir(ses_target_t *tp, const char *pluginroot)
+{
+ char path[PATH_MAX];
+ DIR *dirp;
+ struct dirent64 *dp;
+ char *vendor, *product, *revision;
+ char isa[257];
+
+ (void) snprintf(path, sizeof (path), "%s/%s",
+ pluginroot, LIBSES_PLUGIN_FRAMEWORK);
+
+#if defined(_LP64)
+ if (sysinfo(SI_ARCHITECTURE_64, isa, sizeof (isa)) < 0)
+ isa[0] = '\0';
+#else
+ isa[0] = '\0';
+#endif
+
+ if ((dirp = opendir(path)) != NULL) {
+ while ((dp = readdir64(dirp)) != NULL) {
+ if (strcmp(dp->d_name, ".") == 0 ||
+ strcmp(dp->d_name, "..") == 0)
+ continue;
+
+ (void) snprintf(path, sizeof (path), "%s/%s/%s/%s",
+ pluginroot, LIBSES_PLUGIN_FRAMEWORK,
+ isa, dp->d_name);
+
+ if (ses_plugin_loadone(tp, path, 0) != 0) {
+ (void) closedir(dirp);
+ return (-1);
+ }
+ }
+
+ (void) closedir(dirp);
+ }
+
+ /*
+ * Create a local copy of the vendor/product/revision, strip out any
+ * questionable characters, and then attempt to load each plugin.
+ */
+ vendor = alloca(strlen(libscsi_vendor(tp->st_target)) + 1);
+ product = alloca(strlen(libscsi_product(tp->st_target)) + 1);
+ revision = alloca(strlen(libscsi_revision(tp->st_target)) + 1);
+ (void) strcpy(vendor, libscsi_vendor(tp->st_target));
+ (void) strcpy(product, libscsi_product(tp->st_target));
+ (void) strcpy(revision, libscsi_revision(tp->st_target));
+
+ ses_plugin_cleanstr(vendor);
+ ses_plugin_cleanstr(product);
+ ses_plugin_cleanstr(revision);
+
+ (void) snprintf(path, sizeof (path), "%s/%s/%s/%s%s", pluginroot,
+ LIBSES_PLUGIN_VENDOR, isa, vendor,
+ LIBSES_PLUGIN_EXT);
+ if (ses_plugin_loadone(tp, path, 1) != 0)
+ return (-1);
+
+ (void) snprintf(path, sizeof (path), "%s/%s/%s/%s-%s%s", pluginroot,
+ LIBSES_PLUGIN_VENDOR, isa, vendor, product,
+ LIBSES_PLUGIN_EXT);
+ if (ses_plugin_loadone(tp, path, 2) != 0)
+ return (-1);
+
+ (void) snprintf(path, sizeof (path), "%s/%s/%s/%s-%s-%s%s", pluginroot,
+ LIBSES_PLUGIN_VENDOR, isa, vendor, product,
+ revision, LIBSES_PLUGIN_EXT);
+ if (ses_plugin_loadone(tp, path, 3) != 0)
+ return (-1);
+
+ return (0);
+}
+
+int
+ses_plugin_load(ses_target_t *tp)
+{
+ char pluginroot[PATH_MAX];
+ const char *pluginpath, *p, *q;
+
+ if ((pluginpath = getenv("SES_PLUGINPATH")) == NULL)
+ pluginpath = LIBSES_DEFAULT_PLUGINDIR;
+ ses_plugin_dlclose = (getenv("SES_NODLCLOSE") == NULL);
+
+ for (p = pluginpath, q = strchr(p, ':'); p != NULL; p = q) {
+ if (q != NULL) {
+ ptrdiff_t len = q - p;
+ (void) strncpy(pluginroot, p, len);
+ pluginroot[len] = '\0';
+ while (*q == ':')
+ ++q;
+ if (*q == '\0')
+ q = NULL;
+ if (len == 0)
+ continue;
+ } else {
+ (void) strcpy(pluginroot, p);
+ }
+
+ if (pluginroot[0] != '/')
+ continue;
+
+ if (ses_plugin_load_dir(tp, pluginpath) != 0)
+ return (-1);
+ }
+
+ if (tp->st_plugin_first == NULL)
+ return (ses_error(ESES_PLUGIN, "no plugins found"));
+
+ return (0);
+}
+
+void
+ses_plugin_unload(ses_target_t *tp)
+{
+ ses_plugin_t *sp;
+
+ while ((sp = tp->st_plugin_first) != NULL) {
+ tp->st_plugin_first = sp->sp_next;
+ ses_plugin_destroy(sp);
+ }
+}
diff --git a/usr/src/lib/scsi/libses/common/ses_snap.c b/usr/src/lib/scsi/libses/common/ses_snap.c
new file mode 100644
index 0000000000..78e7927061
--- /dev/null
+++ b/usr/src/lib/scsi/libses/common/ses_snap.c
@@ -0,0 +1,700 @@
+/*
+ * 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"
+
+#include <scsi/libses.h>
+#include "ses_impl.h"
+
+ses_snap_page_t *
+ses_snap_find_page(ses_snap_t *sp, ses2_diag_page_t page, boolean_t ctl)
+{
+ ses_snap_page_t *pp;
+
+ for (pp = sp->ss_pages; pp != NULL; pp = pp->ssp_next)
+ if (pp->ssp_num == page && pp->ssp_control == ctl &&
+ (pp->ssp_len > 0 || pp->ssp_control))
+ return (pp);
+
+ return (NULL);
+}
+
+static int
+grow_snap_page(ses_snap_page_t *pp, size_t min)
+{
+ uint8_t *newbuf;
+
+ if (min == 0 || min < pp->ssp_alloc)
+ min = pp->ssp_alloc * 2;
+
+ if ((newbuf = ses_realloc(pp->ssp_page, min)) == NULL)
+ return (-1);
+
+ pp->ssp_page = newbuf;
+ pp->ssp_alloc = min;
+
+ bzero(newbuf + pp->ssp_len, pp->ssp_alloc - pp->ssp_len);
+
+ return (0);
+}
+
+static ses_snap_page_t *
+alloc_snap_page(void)
+{
+ ses_snap_page_t *pp;
+
+ if ((pp = ses_zalloc(sizeof (ses_snap_page_t))) == NULL)
+ return (NULL);
+
+ if ((pp->ssp_page = ses_zalloc(SES2_MIN_DIAGPAGE_ALLOC)) == NULL) {
+ ses_free(pp);
+ return (NULL);
+ }
+
+ pp->ssp_num = -1;
+ pp->ssp_alloc = SES2_MIN_DIAGPAGE_ALLOC;
+
+ return (pp);
+}
+
+static void
+free_snap_page(ses_snap_page_t *pp)
+{
+ if (pp == NULL)
+ return;
+
+ if (pp->ssp_mmap_base)
+ (void) munmap(pp->ssp_mmap_base, pp->ssp_mmap_len);
+ else
+ ses_free(pp->ssp_page);
+ ses_free(pp);
+}
+
+static void
+free_all_snap_pages(ses_snap_t *sp)
+{
+ ses_snap_page_t *pp, *np;
+
+ for (pp = sp->ss_pages; pp != NULL; pp = np) {
+ np = pp->ssp_next;
+ free_snap_page(pp);
+ }
+
+ sp->ss_pages = NULL;
+}
+
+/*
+ * Grow (if needed) the control page buffer, fill in the page code, page
+ * length, and generation count, and return a pointer to the page. The
+ * caller is responsible for filling in the rest of the page data. If 'unique'
+ * is specified, then a new page instance is created instead of sharing the
+ * current one.
+ */
+ses_snap_page_t *
+ses_snap_ctl_page(ses_snap_t *sp, ses2_diag_page_t page, size_t dlen,
+ boolean_t unique)
+{
+ ses_target_t *tp = sp->ss_target;
+ spc3_diag_page_impl_t *pip;
+ ses_snap_page_t *pp, *up, **loc;
+ ses_pagedesc_t *dp;
+ size_t len;
+
+ pp = ses_snap_find_page(sp, page, B_TRUE);
+ if (pp == NULL) {
+ (void) ses_set_errno(ESES_NOTSUP);
+ return (NULL);
+ }
+
+ if (pp->ssp_initialized && !unique)
+ return (pp);
+
+ if (unique) {
+ /*
+ * The user has requested a unique instance of the page. Create
+ * a new ses_snap_page_t instance and chain it off the
+ * 'ssp_instances' list of the master page. These must be
+ * appended to the end of the chain, as the order of operations
+ * may be important (i.e. microcode download).
+ */
+ if ((up = alloc_snap_page()) == NULL)
+ return (NULL);
+
+ up->ssp_num = pp->ssp_num;
+ up->ssp_control = B_TRUE;
+
+ for (loc = &pp->ssp_unique; *loc != NULL;
+ loc = &(*loc)->ssp_next)
+ ;
+
+ *loc = up;
+ pp = up;
+ }
+
+ dp = ses_get_pagedesc(tp, page, SES_PAGE_CTL);
+ ASSERT(dp != NULL);
+
+ len = dp->spd_ctl_len(sp->ss_n_elem, page, dlen);
+ if (pp->ssp_alloc < dlen && grow_snap_page(pp, len) != 0)
+ return (NULL);
+ pp->ssp_len = len;
+ bzero(pp->ssp_page, len);
+ pp->ssp_initialized = B_TRUE;
+
+ pip = (spc3_diag_page_impl_t *)pp->ssp_page;
+ pip->sdpi_page_code = (uint8_t)page;
+ SCSI_WRITE16(&pip->sdpi_page_length,
+ len - offsetof(spc3_diag_page_impl_t, sdpi_data[0]));
+ if (dp->spd_gcoff != -1)
+ SCSI_WRITE32((uint8_t *)pip + dp->spd_gcoff, sp->ss_generation);
+
+ return (pp);
+}
+
+static int
+read_status_page(ses_snap_t *sp, ses2_diag_page_t page)
+{
+ libscsi_action_t *ap;
+ ses_snap_page_t *pp;
+ ses_target_t *tp;
+ spc3_diag_page_impl_t *pip;
+ spc3_receive_diagnostic_results_cdb_t *cp;
+ uint_t flags;
+ uint8_t *buf;
+ size_t alloc;
+ uint_t retries = 0;
+ ses2_diag_page_t retpage;
+
+ for (pp = sp->ss_pages; pp != NULL; pp = pp->ssp_next)
+ if (pp->ssp_num == page && !pp->ssp_control)
+ break;
+
+ /*
+ * No matching page. Since the page number is not under consumer or
+ * device control, this must be a bug.
+ */
+ ASSERT(pp != NULL);
+
+ tp = sp->ss_target;
+
+ flags = LIBSCSI_AF_READ | LIBSCSI_AF_SILENT | LIBSCSI_AF_DIAGNOSE |
+ LIBSCSI_AF_RQSENSE;
+
+again:
+ ap = libscsi_action_alloc(tp->st_scsi_hdl,
+ SPC3_CMD_RECEIVE_DIAGNOSTIC_RESULTS, flags, pp->ssp_page,
+ pp->ssp_alloc);
+
+ if (ap == NULL)
+ return (ses_libscsi_error(tp->st_scsi_hdl, "failed to "
+ "allocate SCSI action"));
+
+ cp = (spc3_receive_diagnostic_results_cdb_t *)
+ libscsi_action_get_cdb(ap);
+
+ cp->rdrc_page_code = pp->ssp_num;
+ cp->rdrc_pcv = 1;
+ SCSI_WRITE16(&cp->rdrc_allocation_length,
+ MIN(pp->ssp_alloc, UINT16_MAX));
+
+ if (libscsi_exec(ap, tp->st_target) != 0) {
+ libscsi_action_free(ap);
+ return (ses_libscsi_error(tp->st_scsi_hdl,
+ "receive diagnostic results failed"));
+ }
+
+ if (libscsi_action_get_status(ap) != 0) {
+ (void) ses_scsi_error(ap,
+ "receive diagnostic results failed");
+ libscsi_action_free(ap);
+ return (-1);
+ }
+
+ (void) libscsi_action_get_buffer(ap, &buf, &alloc, &pp->ssp_len);
+ libscsi_action_free(ap);
+
+ ASSERT(buf == pp->ssp_page);
+ ASSERT(alloc == pp->ssp_alloc);
+
+ if (pp->ssp_len == pp->ssp_alloc && pp->ssp_alloc < UINT16_MAX) {
+ bzero(pp->ssp_page, pp->ssp_len);
+ pp->ssp_len = 0;
+ if (grow_snap_page(pp, 0) != 0)
+ return (-1);
+ goto again;
+ }
+
+ pip = (spc3_diag_page_impl_t *)buf;
+
+ if (pip->sdpi_page_code == page)
+ return (0);
+
+ retpage = pip->sdpi_page_code;
+
+ bzero(pp->ssp_page, pp->ssp_len);
+ pp->ssp_len = 0;
+
+ if (retpage == SES2_DIAGPAGE_ENCLOSURE_BUSY) {
+ if (++retries > LIBSES_MAX_BUSY_RETRIES)
+ return (ses_error(ESES_BUSY, "too many "
+ "enclosure busy responses for page 0x%x", page));
+ goto again;
+ }
+
+ return (ses_error(ESES_BAD_RESPONSE, "target returned page 0x%x "
+ "instead of the requested page 0x%x", retpage, page));
+}
+
+static int
+send_control_page(ses_snap_t *sp, ses_snap_page_t *pp)
+{
+ ses_target_t *tp;
+ libscsi_action_t *ap;
+ spc3_send_diagnostic_cdb_t *cp;
+ uint_t flags;
+
+ tp = sp->ss_target;
+
+ flags = LIBSCSI_AF_WRITE | LIBSCSI_AF_SILENT | LIBSCSI_AF_DIAGNOSE |
+ LIBSCSI_AF_RQSENSE;
+
+ ap = libscsi_action_alloc(tp->st_scsi_hdl, SPC3_CMD_SEND_DIAGNOSTIC,
+ flags, pp->ssp_page, pp->ssp_len);
+
+ if (ap == NULL)
+ return (ses_libscsi_error(tp->st_scsi_hdl, "failed to "
+ "allocate SCSI action"));
+
+ cp = (spc3_send_diagnostic_cdb_t *)libscsi_action_get_cdb(ap);
+
+ cp->sdc_pf = 1;
+ SCSI_WRITE16(&cp->sdc_parameter_list_length, pp->ssp_len);
+
+ if (libscsi_exec(ap, tp->st_target) != 0) {
+ libscsi_action_free(ap);
+ return (ses_libscsi_error(tp->st_scsi_hdl,
+ "SEND DIAGNOSTIC command failed for page 0x%x",
+ pp->ssp_num));
+ }
+
+ if (libscsi_action_get_status(ap) != 0) {
+ (void) ses_scsi_error(ap, "SEND DIAGNOSTIC command "
+ "failed for page 0x%x", pp->ssp_num);
+ libscsi_action_free(ap);
+ return (-1);
+ }
+
+ libscsi_action_free(ap);
+
+ return (0);
+}
+
+static int
+pages_skel_create(ses_snap_t *sp)
+{
+ ses_snap_page_t *pp, *np;
+ ses_target_t *tp = sp->ss_target;
+ ses2_supported_ses_diag_page_impl_t *pip;
+ ses2_diag_page_t page;
+ size_t npages;
+ size_t pagelen;
+ off_t i;
+
+ ASSERT(sp->ss_pages == NULL);
+
+ if ((pp = alloc_snap_page()) == NULL)
+ return (-1);
+
+ pp->ssp_num = SES2_DIAGPAGE_SUPPORTED_PAGES;
+ pp->ssp_control = B_FALSE;
+ sp->ss_pages = pp;
+
+ if (read_status_page(sp, SES2_DIAGPAGE_SUPPORTED_PAGES) != 0) {
+ free_snap_page(pp);
+ sp->ss_pages = NULL;
+ return (-1);
+ }
+
+ pip = pp->ssp_page;
+ pagelen = pp->ssp_len;
+
+ npages = SCSI_READ16(&pip->sssdpi_page_length);
+
+ for (i = 0; i < npages; i++) {
+ if (!SES_WITHIN_PAGE(pip->sssdpi_pages + i, 1, pip,
+ pagelen))
+ break;
+
+ page = (ses2_diag_page_t)pip->sssdpi_pages[i];
+ /*
+ * Skip the page we already added during the bootstrap.
+ */
+ if (page == SES2_DIAGPAGE_SUPPORTED_PAGES)
+ continue;
+ /*
+ * The end of the page list may be padded with zeros; ignore
+ * them all.
+ */
+ if (page == 0 && i > 0)
+ break;
+ if ((np = alloc_snap_page()) == NULL) {
+ free_all_snap_pages(sp);
+ return (-1);
+ }
+ np->ssp_num = page;
+ pp->ssp_next = np;
+ pp = np;
+
+ /*
+ * Allocate a control page as well, if we can use it.
+ */
+ if (ses_get_pagedesc(tp, page, SES_PAGE_CTL) != NULL) {
+ if ((np = alloc_snap_page()) == NULL) {
+ free_all_snap_pages(sp);
+ return (-1);
+ }
+ np->ssp_num = page;
+ np->ssp_control = B_TRUE;
+ pp->ssp_next = np;
+ pp = np;
+ }
+ }
+
+ return (0);
+}
+
+static void
+ses_snap_free(ses_snap_t *sp)
+{
+ free_all_snap_pages(sp);
+ ses_node_teardown(sp->ss_root);
+ ses_free(sp->ss_nodes);
+ ses_free(sp);
+}
+
+static void
+ses_snap_rele_unlocked(ses_snap_t *sp)
+{
+ ses_target_t *tp = sp->ss_target;
+
+ if (--sp->ss_refcnt != 0)
+ return;
+
+ if (sp->ss_next != NULL)
+ sp->ss_next->ss_prev = sp->ss_prev;
+
+ if (sp->ss_prev != NULL)
+ sp->ss_prev->ss_next = sp->ss_next;
+ else
+ tp->st_snapshots = sp->ss_next;
+
+ ses_snap_free(sp);
+}
+
+ses_snap_t *
+ses_snap_hold(ses_target_t *tp)
+{
+ ses_snap_t *sp;
+
+ (void) pthread_mutex_lock(&tp->st_lock);
+ sp = tp->st_snapshots;
+ sp->ss_refcnt++;
+ (void) pthread_mutex_unlock(&tp->st_lock);
+
+ return (sp);
+}
+
+void
+ses_snap_rele(ses_snap_t *sp)
+{
+ ses_target_t *tp = sp->ss_target;
+
+ (void) pthread_mutex_lock(&tp->st_lock);
+ ses_snap_rele_unlocked(sp);
+ (void) pthread_mutex_unlock(&tp->st_lock);
+}
+
+ses_snap_t *
+ses_snap_new(ses_target_t *tp)
+{
+ ses_snap_t *sp;
+ ses_snap_page_t *pp;
+ uint32_t gc;
+ uint_t retries = 0;
+ ses_pagedesc_t *dp;
+ size_t pages, pagesize, pagelen;
+ char *scratch;
+
+ if ((sp = ses_zalloc(sizeof (ses_snap_t))) == NULL)
+ return (NULL);
+
+ sp->ss_target = tp;
+
+again:
+ free_all_snap_pages(sp);
+
+ if (pages_skel_create(sp) != 0) {
+ free(sp);
+ return (NULL);
+ }
+
+ sp->ss_generation = (uint32_t)-1;
+ sp->ss_time = gethrtime();
+
+ for (pp = sp->ss_pages; pp != NULL; pp = pp->ssp_next) {
+ /*
+ * We skip all of:
+ *
+ * - Control pages
+ * - Pages we've already filled in
+ * - Pages we don't understand (those with no descriptor)
+ */
+ if (pp->ssp_len > 0 || pp->ssp_control)
+ continue;
+ if ((dp = ses_get_pagedesc(tp, pp->ssp_num,
+ SES_PAGE_DIAG)) == NULL)
+ continue;
+
+ if (read_status_page(sp, pp->ssp_num) != 0)
+ continue;
+
+ /*
+ * If the generation code has changed, we don't have a valid
+ * snapshot. Start over.
+ */
+ if (dp->spd_gcoff != -1 &&
+ dp->spd_gcoff + 4 <= pp->ssp_len) {
+ gc = SCSI_READ32((uint8_t *)pp->ssp_page +
+ dp->spd_gcoff);
+ if (sp->ss_generation == (uint32_t)-1) {
+ sp->ss_generation = gc;
+ } else if (sp->ss_generation != gc) {
+ if (++retries > LIBSES_MAX_GC_RETRIES) {
+ (void) ses_error(ESES_TOOMUCHCHANGE,
+ "too many generation count "
+ "mismatches: page 0x%x gc %u "
+ "previous page %u", dp->spd_gcoff,
+ gc, sp->ss_generation);
+ ses_snap_free((ses_snap_t *)sp);
+ return (NULL);
+ }
+ goto again;
+ }
+ }
+ }
+
+ /*
+ * The LIBSES_TRUNCATE environment variable is a debugging tool which,
+ * if set, randomly truncates all pages (except
+ * SES2_DIAGPAGE_SUPPORTED_PAGES). In order to be truly evil, we
+ * mmap() each page with enough space after it so we can move the data
+ * up to the end of a page and unmap the following page so that any
+ * attempt to read past the end of the page results in a segfault.
+ */
+ if (sp->ss_target->st_truncate) {
+ pagesize = PAGESIZE;
+
+ /*
+ * Count the maximum number of pages we will need and allocate
+ * the necessary space.
+ */
+ pages = 0;
+ for (pp = sp->ss_pages; pp != NULL; pp = pp->ssp_next) {
+ if (pp->ssp_control || pp->ssp_len == 0)
+ continue;
+
+ pages += (P2ROUNDUP(pp->ssp_len, pagesize) /
+ pagesize) + 1;
+ }
+
+ if ((scratch = mmap(NULL, pages * pagesize,
+ PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE,
+ -1, 0)) == MAP_FAILED) {
+ (void) ses_error(ESES_NOMEM,
+ "failed to mmap() pages for truncation");
+ ses_snap_free(sp);
+ return (NULL);
+ }
+
+ for (pp = sp->ss_pages; pp != NULL; pp = pp->ssp_next) {
+ if (pp->ssp_control || pp->ssp_len == 0)
+ continue;
+
+ pages = P2ROUNDUP(pp->ssp_len, pagesize) / pagesize;
+ pp->ssp_mmap_base = scratch;
+ pp->ssp_mmap_len = pages * pagesize;
+
+ pagelen = lrand48() % pp->ssp_len;
+ (void) memcpy(pp->ssp_mmap_base + pp->ssp_mmap_len -
+ pagelen, pp->ssp_page, pagelen);
+ ses_free(pp->ssp_page);
+ pp->ssp_page = pp->ssp_mmap_base + pp->ssp_mmap_len -
+ pagelen;
+ pp->ssp_len = pagelen;
+
+ (void) munmap(pp->ssp_mmap_base + pages * pagesize,
+ pagesize);
+ scratch += (pages + 1) * pagesize;
+ }
+ }
+
+
+ if (ses_fill_snap(sp) != 0) {
+ ses_snap_free(sp);
+ return (NULL);
+ }
+
+ (void) pthread_mutex_lock(&tp->st_lock);
+ if (tp->st_snapshots != NULL)
+ ses_snap_rele_unlocked(tp->st_snapshots);
+ sp->ss_next = tp->st_snapshots;
+ if (tp->st_snapshots != NULL)
+ tp->st_snapshots->ss_prev = sp;
+ tp->st_snapshots = sp;
+ sp->ss_refcnt = 2;
+ (void) pthread_mutex_unlock(&tp->st_lock);
+
+ return (sp);
+}
+
+int
+ses_snap_do_ctl(ses_snap_t *sp)
+{
+ ses_snap_page_t *pp, *up;
+ int ret = -1;
+
+ for (pp = sp->ss_pages; pp != NULL; pp = pp->ssp_next) {
+ if (!pp->ssp_control)
+ continue;
+
+ if (pp->ssp_initialized && send_control_page(sp, pp) != 0)
+ goto error;
+
+ for (up = pp->ssp_unique; up != NULL; up = up->ssp_next) {
+ if (send_control_page(sp, up) != 0)
+ goto error;
+ }
+ }
+
+ ret = 0;
+error:
+ for (pp = sp->ss_pages; pp != NULL; pp = pp->ssp_next) {
+ if (!pp->ssp_control)
+ continue;
+
+ pp->ssp_initialized = B_FALSE;
+ while ((up = pp->ssp_unique) != NULL) {
+ pp->ssp_unique = up->ssp_next;
+ free_snap_page(up);
+ }
+ }
+
+
+ return (ret);
+}
+
+uint32_t
+ses_snap_generation(ses_snap_t *sp)
+{
+ return (sp->ss_generation);
+}
+
+static ses_walk_action_t
+ses_walk_node(ses_node_t *np, ses_walk_f func, void *arg)
+{
+ ses_walk_action_t action;
+
+ for (; np != NULL; np = ses_node_sibling(np)) {
+ action = func(np, arg);
+ if (action == SES_WALK_ACTION_TERMINATE)
+ return (SES_WALK_ACTION_TERMINATE);
+ if (action == SES_WALK_ACTION_PRUNE ||
+ ses_node_child(np) == NULL)
+ continue;
+ if (ses_walk_node(ses_node_child(np), func, arg) ==
+ SES_WALK_ACTION_TERMINATE)
+ return (SES_WALK_ACTION_TERMINATE);
+ }
+
+ return (SES_WALK_ACTION_CONTINUE);
+}
+
+int
+ses_walk(ses_snap_t *sp, ses_walk_f func, void *arg)
+{
+ (void) ses_walk_node(ses_root_node(sp), func, arg);
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static ses_walk_action_t
+ses_fill_nodes(ses_node_t *np, void *unused)
+{
+ np->sn_snapshot->ss_nodes[np->sn_id] = np;
+
+ return (SES_WALK_ACTION_CONTINUE);
+}
+
+/*
+ * Given an ID returned by ses_node_id(), lookup and return the corresponding
+ * node in the snapshot. If the snapshot generation count has changed, then
+ * return failure.
+ */
+ses_node_t *
+ses_node_lookup(ses_snap_t *sp, uint64_t id)
+{
+ uint32_t gen = (id >> 32);
+ uint32_t idx = (id & 0xFFFFFFFF);
+
+ if (sp->ss_generation != gen) {
+ (void) ses_set_errno(ESES_CHANGED);
+ return (NULL);
+ }
+
+ if (idx >= sp->ss_n_nodes) {
+ (void) ses_error(ESES_BAD_NODE,
+ "no such node in snapshot");
+ return (NULL);
+ }
+
+ /*
+ * If this is our first lookup attempt, construct the array for fast
+ * lookups.
+ */
+ if (sp->ss_nodes == NULL) {
+ if ((sp->ss_nodes = ses_zalloc(
+ sp->ss_n_nodes * sizeof (void *))) == NULL)
+ return (NULL);
+
+ (void) ses_walk(sp, ses_fill_nodes, NULL);
+ }
+
+ if (sp->ss_nodes[idx] == NULL)
+ (void) ses_error(ESES_BAD_NODE,
+ "no such node in snapshot");
+ return (sp->ss_nodes[idx]);
+}
diff --git a/usr/src/lib/scsi/libses/common/ses_subr.c b/usr/src/lib/scsi/libses/common/ses_subr.c
new file mode 100644
index 0000000000..aa1013e678
--- /dev/null
+++ b/usr/src/lib/scsi/libses/common/ses_subr.c
@@ -0,0 +1,376 @@
+/*
+ * 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"
+
+#include <scsi/libses.h>
+#include "ses_impl.h"
+
+__thread ses_errno_t _ses_errno;
+__thread char _ses_errmsg[1024];
+__thread char _ses_nverr_member[256];
+
+static void ses_vpanic(const char *, va_list) __NORETURN;
+
+static void
+ses_vpanic(const char *fmt, va_list ap)
+{
+ int oserr = errno;
+ char msg[BUFSIZ];
+ size_t len;
+
+ (void) snprintf(msg, sizeof (msg), "ABORT: ");
+ len = strlen(msg);
+ (void) vsnprintf(msg + len, sizeof (msg) - len, fmt, ap);
+
+ if (strchr(fmt, '\n') == NULL) {
+ len = strlen(msg);
+ (void) snprintf(msg + len, sizeof (msg) - len, ": %s\n",
+ strerror(oserr));
+ }
+
+ (void) write(STDERR_FILENO, msg, strlen(msg));
+
+abort:
+ abort();
+ _exit(1);
+}
+
+/*PRINTFLIKE1*/
+void
+ses_panic(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ ses_vpanic(fmt, ap);
+ va_end(ap);
+}
+
+int
+ses_assert(const char *expr, const char *file, int line)
+{
+ ses_panic("\"%s\", line %d: assertion failed: %s\n", file, line, expr);
+
+ /*NOTREACHED*/
+ return (0);
+}
+
+int
+nvlist_add_fixed_string(nvlist_t *nvl, const char *name,
+ const char *buf, size_t len)
+{
+ char *str = alloca(len + 1);
+ bcopy(buf, str, len);
+ str[len] = '\0';
+
+ return (nvlist_add_string(nvl, name, str));
+}
+
+/*
+ * Like fixed_string, but clears any leading or trailing spaces.
+ */
+int
+nvlist_add_fixed_string_trunc(nvlist_t *nvl, const char *name,
+ const char *buf, size_t len)
+{
+ while (buf[0] == ' ' && len > 0) {
+ buf++;
+ len--;
+ }
+
+ while (len > 0 && buf[len - 1] == ' ')
+ len--;
+
+ return (nvlist_add_fixed_string(nvl, name, buf, len));
+}
+
+ses_errno_t
+ses_errno(void)
+{
+ return (_ses_errno);
+}
+
+const char *
+ses_errmsg(void)
+{
+ if (_ses_errmsg[0] == '\0')
+ (void) snprintf(_ses_errmsg, sizeof (_ses_errmsg), "%s",
+ ses_strerror(_ses_errno));
+
+ return (_ses_errmsg);
+}
+
+const char *
+ses_nv_error_member(void)
+{
+ if (_ses_nverr_member[0] != '\0')
+ return (_ses_nverr_member);
+ else
+ return (NULL);
+}
+
+static int
+__ses_set_errno(ses_errno_t err, const char *nvm)
+{
+ if (nvm == NULL) {
+ _ses_nverr_member[0] = '\0';
+ } else {
+ (void) strlcpy(_ses_nverr_member, nvm,
+ sizeof (_ses_nverr_member));
+ }
+ _ses_errmsg[0] = '\0';
+ _ses_errno = err;
+
+ return (-1);
+}
+
+int
+ses_set_errno(ses_errno_t err)
+{
+ return (__ses_set_errno(err, NULL));
+}
+
+int
+ses_set_nverrno(int err, const char *member)
+{
+ ses_errno_t se = (err == ENOMEM || err == EAGAIN) ?
+ ESES_NOMEM : ESES_NVL;
+
+ /*
+ * If the error is ESES_NVL, then we should always have a member
+ * available. The only time 'member' is NULL is when nvlist_alloc()
+ * fails, which should only be possible if memory allocation fails.
+ */
+ assert(se == ESES_NOMEM || member != NULL);
+
+ return (__ses_set_errno(se, member));
+}
+
+static int
+ses_verror(ses_errno_t err, const char *fmt, va_list ap)
+{
+ int syserr = errno;
+ size_t n;
+ char *errmsg;
+
+ errmsg = alloca(sizeof (_ses_errmsg));
+ (void) vsnprintf(errmsg, sizeof (_ses_errmsg), fmt, ap);
+ (void) ses_set_errno(err);
+
+ n = strlen(errmsg);
+
+ while (n != 0 && errmsg[n - 1] == '\n')
+ errmsg[--n] = '\0';
+
+ bcopy(errmsg, _ses_errmsg, sizeof (_ses_errmsg));
+ errno = syserr;
+
+ return (-1);
+}
+
+static int
+ses_vnverror(int err, const char *member, const char *fmt,
+ va_list ap)
+{
+ int syserr = errno;
+ size_t n;
+ char *errmsg;
+
+ errmsg = alloca(sizeof (_ses_errmsg));
+ (void) vsnprintf(errmsg, sizeof (_ses_errmsg), fmt, ap);
+ (void) ses_set_nverrno(err, member);
+
+ n = strlen(errmsg);
+
+ while (n != 0 && errmsg[n - 1] == '\n')
+ errmsg[--n] = '\0';
+
+ (void) snprintf(errmsg + n, sizeof (_ses_errmsg) - n, ": %s",
+ strerror(err));
+
+ bcopy(errmsg, _ses_errmsg, sizeof (_ses_errmsg));
+ errno = syserr;
+
+ return (-1);
+}
+
+int
+ses_error(ses_errno_t err, const char *fmt, ...)
+{
+ va_list ap;
+ int rv;
+
+ va_start(ap, fmt);
+ rv = ses_verror(err, fmt, ap);
+ va_end(ap);
+
+ return (rv);
+}
+
+int
+ses_nverror(int err, const char *member, const char *fmt, ...)
+{
+ va_list ap;
+ int rv;
+
+ va_start(ap, fmt);
+ rv = ses_vnverror(err, member, fmt, ap);
+ va_end(ap);
+
+ return (rv);
+}
+
+int
+ses_libscsi_error(libscsi_hdl_t *shp, const char *fmt, ...)
+{
+ va_list ap;
+ char errmsg[LIBSES_ERRMSGLEN];
+ libscsi_errno_t se = libscsi_errno(shp);
+ ses_errno_t e;
+
+ switch (se) {
+ case ESCSI_NONE:
+ return (0);
+ case ESCSI_NOMEM:
+ e = ESES_NOMEM;
+ break;
+ case ESCSI_NOTSUP:
+ e = ESES_NOTSUP;
+ break;
+ case ESCSI_ZERO_LENGTH:
+ case ESCSI_VERSION:
+ case ESCSI_BADFLAGS:
+ case ESCSI_BOGUSFLAGS:
+ case ESCSI_BADLENGTH:
+ case ESCSI_NEEDBUF:
+ va_start(ap, fmt);
+ (void) vsnprintf(errmsg, sizeof (errmsg), fmt, ap);
+ va_end(ap);
+ ses_panic("%s: unexpected libscsi error %s: %s", errmsg,
+ libscsi_errname(se), libscsi_errmsg(shp));
+ break;
+ case ESCSI_UNKNOWN:
+ e = ESES_UNKNOWN;
+ break;
+ default:
+ e = ESES_LIBSCSI;
+ break;
+ }
+
+ va_start(ap, fmt);
+ (void) vsnprintf(errmsg, sizeof (errmsg), fmt, ap);
+ va_end(ap);
+
+ return (ses_error(e, "%s: %s", errmsg, libscsi_errmsg(shp)));
+}
+
+int
+ses_scsi_error(libscsi_action_t *ap, const char *fmt, ...)
+{
+ va_list args;
+ char errmsg[LIBSES_ERRMSGLEN];
+ uint64_t asc = 0, ascq = 0, key = 0;
+ const char *code, *keystr;
+
+ va_start(args, fmt);
+ (void) vsnprintf(errmsg, sizeof (errmsg), fmt, args);
+ va_end(args);
+
+ if (libscsi_action_parse_sense(ap, &key, &asc, &ascq, NULL) != 0)
+ return (ses_error(ESES_LIBSCSI,
+ "%s: SCSI status %d (no sense data available)", errmsg,
+ libscsi_action_get_status(ap)));
+
+ code = libscsi_sense_code_name(asc, ascq);
+ keystr = libscsi_sense_key_name(key);
+
+ return (ses_error(ESES_LIBSCSI, "%s: SCSI status %d sense key %llu "
+ "(%s) additional sense code 0x%llx/0x%llx (%s)", errmsg,
+ libscsi_action_get_status(ap), key, keystr ? keystr : "<unknown>",
+ asc, ascq, code ? code : "<unknown>"));
+}
+
+void *
+ses_alloc(size_t sz)
+{
+ void *p;
+
+ if (sz == 0)
+ ses_panic("attempted zero-length allocation");
+
+ if ((p = malloc(sz)) == NULL)
+ (void) ses_set_errno(ESES_NOMEM);
+
+ return (p);
+}
+
+void *
+ses_zalloc(size_t sz)
+{
+ void *p;
+
+ if ((p = ses_alloc(sz)) != NULL)
+ bzero(p, sz);
+
+ return (p);
+}
+
+char *
+ses_strdup(const char *s)
+{
+ char *p;
+ size_t len;
+
+ if (s == NULL)
+ ses_panic("attempted zero-length allocation");
+
+ len = strlen(s) + 1;
+
+ if ((p = ses_alloc(len)) != NULL)
+ bcopy(s, p, len);
+
+ return (p);
+}
+
+void *
+ses_realloc(void *p, size_t sz)
+{
+ if (sz == 0)
+ ses_panic("attempted zero-length allocation");
+
+ if ((p = realloc(p, sz)) == NULL)
+ (void) ses_set_errno(ESES_NOMEM);
+
+ return (p);
+}
+
+/*ARGSUSED*/
+void
+ses_free(void *p)
+{
+ free(p);
+}
diff --git a/usr/src/lib/scsi/libses/i386/Makefile b/usr/src/lib/scsi/libses/i386/Makefile
new file mode 100644
index 0000000000..b2454048f0
--- /dev/null
+++ b/usr/src/lib/scsi/libses/i386/Makefile
@@ -0,0 +1,36 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+include ../../../Makefile.lib
+include ../Makefile.defs
+
+DYNFLAGS += $(DYNFLAGS32)
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
+
+include ../Makefile.targ
diff --git a/usr/src/lib/scsi/libses/libses_api.map b/usr/src/lib/scsi/libses/libses_api.map
new file mode 100644
index 0000000000..a66e641061
--- /dev/null
+++ b/usr/src/lib/scsi/libses/libses_api.map
@@ -0,0 +1,69 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+{
+ ses_close = FUNCTION extern;
+ ses_errno = FUNCTION extern;
+ ses_errmsg = FUNCTION extern;
+ ses_node_child = FUNCTION extern;
+ ses_node_id = FUNCTION extern;
+ ses_node_lookup = FUNCTION extern;
+ ses_node_parent = FUNCTION extern;
+ ses_node_props = FUNCTION extern;
+ ses_node_prev_sibling = FUNCTION extern;
+ ses_node_sibling = FUNCTION extern;
+ ses_node_snapshot = FUNCTION extern;
+ ses_node_target = FUNCTION extern;
+ ses_node_type = FUNCTION extern;
+ ses_open = FUNCTION extern;
+ ses_root_node = FUNCTION extern;
+ ses_scsi_target = FUNCTION extern;
+ ses_snap_generation = FUNCTION extern;
+ ses_strerror = FUNCTION extern;
+ ses_walk = FUNCTION extern;
+
+ nvlist_add_fixed_string = FUNCTION extern;
+ nvlist_add_fixed_string_trunc = FUNCTION extern;
+
+ ses_alloc = FUNCTION extern;
+ ses_assert = FUNCTION extern;
+ ses_error = FUNCTION extern;
+ ses_free = FUNCTION extern;
+ ses_nverror = FUNCTION extern;
+ ses_panic = FUNCTION extern;
+ ses_realloc = FUNCTION extern;
+ ses_set_nverrno = FUNCTION extern;
+ ses_set_errno = FUNCTION extern;
+ ses_strdup = FUNCTION extern;
+ ses_zalloc = FUNCTION extern;
+
+ ses_plugin_ctlpage_lookup = FUNCTION extern;
+ ses_plugin_page_lookup = FUNCTION extern;
+ ses_plugin_register = FUNCTION extern;
+ ses_plugin_setspecific = FUNCTION extern;
+ ses_plugin_getspecific = FUNCTION extern;
+};
diff --git a/usr/src/lib/scsi/libses/llib-lses b/usr/src/lib/scsi/libses/llib-lses
new file mode 100644
index 0000000000..c274b8ad3b
--- /dev/null
+++ b/usr/src/lib/scsi/libses/llib-lses
@@ -0,0 +1,32 @@
+/*
+ * 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"
+
+/*LINTLIBRARY*/
+/*PROTOLIB1*/
+
+#include <scsi/libses.h>
diff --git a/usr/src/lib/scsi/libses/mapfile-vers b/usr/src/lib/scsi/libses/mapfile-vers
new file mode 100644
index 0000000000..9048c11068
--- /dev/null
+++ b/usr/src/lib/scsi/libses/mapfile-vers
@@ -0,0 +1,77 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+SUNWprivate_1.1 {
+ global:
+ ses_close;
+ ses_errno;
+ ses_errmsg;
+ ses_node_child;
+ ses_node_ctl;
+ ses_node_id;
+ ses_node_lookup;
+ ses_node_parent;
+ ses_node_props;
+ ses_node_prev_sibling;
+ ses_node_sibling;
+ ses_node_snapshot;
+ ses_node_target;
+ ses_node_type;
+ ses_open;
+ ses_open_scsi;
+ ses_root_node;
+ ses_scsi_target;
+ ses_snap_generation;
+ ses_snap_hold;
+ ses_snap_new;
+ ses_snap_rele;
+ ses_strerror;
+ ses_walk;
+
+ nvlist_add_fixed_string;
+ nvlist_add_fixed_string_trunc;
+
+ ses_alloc;
+ ses_assert;
+ ses_error;
+ ses_free;
+ ses_nverror;
+ ses_panic;
+ ses_realloc;
+ ses_set_errno;
+ ses_set_nverrno;
+ ses_strdup;
+ ses_zalloc;
+
+ ses_plugin_ctlpage_lookup;
+ ses_plugin_page_lookup;
+ ses_plugin_register;
+ ses_plugin_setspecific;
+ ses_plugin_getspecific;
+ local:
+ *;
+};
diff --git a/usr/src/lib/scsi/libses/sparc/Makefile b/usr/src/lib/scsi/libses/sparc/Makefile
new file mode 100644
index 0000000000..b2454048f0
--- /dev/null
+++ b/usr/src/lib/scsi/libses/sparc/Makefile
@@ -0,0 +1,36 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+include ../../../Makefile.lib
+include ../Makefile.defs
+
+DYNFLAGS += $(DYNFLAGS32)
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
+
+include ../Makefile.targ
diff --git a/usr/src/lib/scsi/libses/sparcv9/Makefile b/usr/src/lib/scsi/libses/sparcv9/Makefile
new file mode 100644
index 0000000000..aaa948e5ae
--- /dev/null
+++ b/usr/src/lib/scsi/libses/sparcv9/Makefile
@@ -0,0 +1,36 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+include ../../../Makefile.lib
+include ../../../Makefile.lib.64
+include ../Makefile.defs
+include ../Makefile.defs.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
+
+include ../Makefile.targ
diff --git a/usr/src/lib/scsi/plugins/Makefile b/usr/src/lib/scsi/plugins/Makefile
new file mode 100644
index 0000000000..3541ca3744
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/Makefile
@@ -0,0 +1,36 @@
+#
+# 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.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+SUBDIRS = \
+ scsi \
+ ses
+
+.KEEP_STATE:
+
+.PARALLEL:
+
+include ../Makefile.subdirs
diff --git a/usr/src/lib/scsi/plugins/scsi/Makefile b/usr/src/lib/scsi/plugins/scsi/Makefile
new file mode 100644
index 0000000000..cc22333827
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/scsi/Makefile
@@ -0,0 +1,35 @@
+#
+# 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.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+SUBDIRS = \
+ engines
+
+.KEEP_STATE:
+
+.PARALLEL:
+
+include ../../Makefile.subdirs
diff --git a/usr/src/lib/scsi/plugins/scsi/engines/Makefile b/usr/src/lib/scsi/plugins/scsi/engines/Makefile
new file mode 100644
index 0000000000..ffde5cc3ed
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/scsi/engines/Makefile
@@ -0,0 +1,32 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+SUBDIRS = \
+ uscsi
+
+include ../../../Makefile.subdirs
diff --git a/usr/src/lib/scsi/plugins/scsi/engines/Makefile.engine b/usr/src/lib/scsi/plugins/scsi/engines/Makefile.engine
new file mode 100644
index 0000000000..f48357fef2
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/scsi/engines/Makefile.engine
@@ -0,0 +1,76 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+.KEEP_STATE:
+.SUFFIXES:
+
+include ../../../../../../../cmd/Makefile.cmd
+include ../../../../../Makefile.defs
+
+#
+# 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.
+#
+PROG = $(MODULE:%=%.so)
+YOBJS = $(YSRCS:%.y=%.o)
+OBJS = $(YOBJS) $(SRCS:%.c=%.o)
+
+#
+# A module may set DMOD and DMOD_SRCS if it has a mdb proc module.
+# DMOD, if set, must match PROG above (for mdb autoloading) so it will
+# be built in a subdirectory.
+#
+ROOTDMOD = $(DMOD:%.so=$(ROOT)/usr/lib/mdb/proc/%.so)
+ROOTDMOD64 = $(DMOD:%.so=$(ROOT)/usr/lib/mdb/proc/$(MACH64)/%.so)
+DMODPROG = $(DMOD:%=dmod/%)
+DMOD_OBJS = $(DMOD_SRCS:%.c=%.o)
+
+ROOTPROG = $(ROOTPLUGINLIBDIR)/scsi/engines/$(PROG)
+ROOTPROG64 = $(ROOTPLUGINLIBDIR)/scsi/engines/$(MACH64)/$(PROG)
+
+LINTFLAGS += -mu
+LINTFILES = $(SRCS:%.c=%.ln)
+
+DMODLINTTGT = $(DMOD:%=lint_dmod)
+DMODLINTFILES = $(DMOD_SRCS:%.c=%.ln)
+
+APIMAP = ../../../../../libscsi/libscsi_api.map
+
+C99MODE = $(C99_ENABLE)
+CFLAGS += $(CTF_FLAGS) $(CCVERBOSE) $(XSTRCONST) $(CC_PICFLAGS)
+CFLAGS += -G $(XREGSFLAG)
+CFLAGS64 += $(CTF_FLAGS) $(CCVERBOSE) $(XSTRCONST) $(CC_PICFLAGS)
+CFLAGS64 += -G $(XREGSFLAG)
+CPPFLAGS += -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT
+CPPFLAGS += -I../../../../../libscsi/common
+$(NOT_RELEASE_BUILD)CPPFLAGS += -DDEBUG
+LDFLAGS += $(ZTEXT) $(ZCOMBRELOC) $(ZIGNORE)
+
+$(PROG) := LDFLAGS += $(ZDEFS) -M$(APIMAP)
+$(PROG) := LDLIBS += -lc
+
+$(DMODPROG) := LDFLAGS += $(ZNODEFS)
diff --git a/usr/src/lib/scsi/plugins/scsi/engines/Makefile.targ b/usr/src/lib/scsi/plugins/scsi/engines/Makefile.targ
new file mode 100644
index 0000000000..69a1ce2a30
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/scsi/engines/Makefile.targ
@@ -0,0 +1,82 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+all: $(PROG) $(DMODPROG)
+
+.NO_PARALLEL:
+.PARALLEL: $(OBJS) $(LINTFILES) $(DMOD_OBJS) $(DMODLINTFILES)
+
+$(PROG): $(OBJS) $(APIMAP)
+ $(LINK.c) $(OBJS) -o $@ $(LDLIBS)
+ $(CTFMERGE) -L VERSION -o $@ $(OBJS)
+ $(POST_PROCESS_SO)
+
+$(DMODPROG): $(DMOD_OBJS)
+ -@mkdir -p $(@D)
+ $(LINK.c) $(DMOD_OBJS) -o $@
+ $(POST_PROCESS)
+
+%.o: %.c
+ $(COMPILE.c) $<
+ $(CTFCONVERT_O)
+
+%.o: ../%.c
+ $(COMPILE.c) $<
+ $(CTFCONVERT_O)
+
+clean:
+ $(RM) $(OBJS) $(DMOD_OBJS) $(LINTFILES) $(DMODLINTFILES) $(CLEANFILES)
+
+clobber: clean
+ $(RM) $(PROG) $(DMODPROG)
+
+%.ln: %.c
+ $(LINT.c) -c $<
+
+%.ln: ../%.c
+ $(LINT.c) -c $<
+
+lint_prog: $(LINTFILES)
+ $(LINT) $(LINTFLAGS) $(LINTFILES) $(LDLIBS)
+
+lint_dmod: $(DMODLINTFILES)
+ $(LINT) $(LINTFLAGS) $(DMODLINTFILES) $(LDLIBS)
+
+lint: lint_prog $(DMODLINTTGT)
+
+install_h:
+
+$(ROOTPROG): $$(@D) $(PROG)
+ $(RM) $@; $(INS) -s -m 0755 -f $(@D) $(PROG)
+
+$(ROOTPROG64): $$(@D) $(PROG)
+ $(RM) $@; $(INS) -s -m 0755 -f $(@D) $(PROG)
+
+$(ROOTDMOD): $$(@D) $(DMODPROG)
+ $(RM) $@; $(INS) -s -m 0755 -f $(@D) $(DMODPROG)
+
+include ../../../../../Makefile.rootdirs
diff --git a/usr/src/lib/scsi/plugins/scsi/engines/uscsi/Makefile b/usr/src/lib/scsi/plugins/scsi/engines/uscsi/Makefile
new file mode 100644
index 0000000000..ae7db6b449
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/scsi/engines/uscsi/Makefile
@@ -0,0 +1,51 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+include $(SRC)/Makefile.master
+
+SUBDIRS = $(MACH)
+$(BUILD64)SUBDIRS += $(MACH64)
+
+all := TARGET= all
+clean := TARGET= clean
+clobber := TARGET= clobber
+install := TARGET= install
+lint := TARGET= lint
+install_h:= TARGET = install_h
+
+.KEEP_STATE:
+
+all install clean clobber lint: $(SUBDIRS)
+
+install_h check:
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+include ../../../../../Makefile.targ
diff --git a/usr/src/lib/scsi/plugins/scsi/engines/uscsi/Makefile.com b/usr/src/lib/scsi/plugins/scsi/engines/uscsi/Makefile.com
new file mode 100644
index 0000000000..ed98d38b11
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/scsi/engines/uscsi/Makefile.com
@@ -0,0 +1,31 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+MODULE = uscsi
+SRCS = uscsi.c
+
+include ../../Makefile.engine
diff --git a/usr/src/lib/scsi/plugins/scsi/engines/uscsi/amd64/Makefile b/usr/src/lib/scsi/plugins/scsi/engines/uscsi/amd64/Makefile
new file mode 100644
index 0000000000..79a0acb9a2
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/scsi/engines/uscsi/amd64/Makefile
@@ -0,0 +1,33 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+include $(SRC)/Makefile.master.64
+
+install: all $(ROOTPROG64)
+
+include ../../Makefile.targ
diff --git a/usr/src/lib/scsi/plugins/scsi/engines/uscsi/i386/Makefile b/usr/src/lib/scsi/plugins/scsi/engines/uscsi/i386/Makefile
new file mode 100644
index 0000000000..9dd4af0d55
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/scsi/engines/uscsi/i386/Makefile
@@ -0,0 +1,32 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+
+install: all $(ROOTPROG)
+
+include ../../Makefile.targ
diff --git a/usr/src/lib/scsi/plugins/scsi/engines/uscsi/sparc/Makefile b/usr/src/lib/scsi/plugins/scsi/engines/uscsi/sparc/Makefile
new file mode 100644
index 0000000000..9dd4af0d55
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/scsi/engines/uscsi/sparc/Makefile
@@ -0,0 +1,32 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+
+install: all $(ROOTPROG)
+
+include ../../Makefile.targ
diff --git a/usr/src/lib/scsi/plugins/scsi/engines/uscsi/sparcv9/Makefile b/usr/src/lib/scsi/plugins/scsi/engines/uscsi/sparcv9/Makefile
new file mode 100644
index 0000000000..79a0acb9a2
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/scsi/engines/uscsi/sparcv9/Makefile
@@ -0,0 +1,33 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+include $(SRC)/Makefile.master.64
+
+install: all $(ROOTPROG64)
+
+include ../../Makefile.targ
diff --git a/usr/src/lib/scsi/plugins/scsi/engines/uscsi/uscsi.c b/usr/src/lib/scsi/plugins/scsi/engines/uscsi/uscsi.c
new file mode 100644
index 0000000000..06cdb0b339
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/scsi/engines/uscsi/uscsi.c
@@ -0,0 +1,235 @@
+/*
+ * 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"
+
+#include <sys/types.h>
+#include <sys/scsi/impl/uscsi.h>
+#include <sys/scsi/generic/commands.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <strings.h>
+#include <stdio.h>
+#include <limits.h>
+
+#include <scsi/libscsi.h>
+#include "libscsi_impl.h"
+
+struct uscsi_dev {
+ int fd;
+ char *dev;
+};
+
+static void *
+uscsi_open(libscsi_hdl_t *hp, const void *target)
+{
+ struct uscsi_dev *dp;
+ const char *target_name = (const char *)target;
+
+ if ((dp = libscsi_zalloc(hp, sizeof (struct uscsi_dev))) == NULL)
+ return (NULL);
+
+ if ((dp->dev = libscsi_strdup(hp, target_name)) == NULL) {
+ libscsi_free(hp, dp);
+ return (NULL);
+ }
+
+ if ((dp->fd = open(target_name, O_RDONLY)) < 0) {
+ (void) libscsi_error(hp, ESCSI_BADTARGET, "failed to open %s "
+ "for reading: %s", target_name, strerror(errno));
+ libscsi_free(hp, dp->dev);
+ libscsi_free(hp, dp);
+ return (NULL);
+ }
+
+ return (dp);
+}
+
+static void
+uscsi_close(libscsi_hdl_t *hp, void *private)
+{
+ struct uscsi_dev *dp = (struct uscsi_dev *)private;
+
+ if (dp == NULL)
+ return;
+
+ if (dp->fd > 0)
+ (void) close(dp->fd);
+
+ libscsi_free(hp, dp->dev);
+ libscsi_free(hp, dp);
+}
+
+static int
+xlate_flags(libscsi_hdl_t *hp, uint_t flags, int *uf)
+{
+ uint_t f;
+ int i;
+
+ f = 0;
+
+ for (i = 0; i < sizeof (flags) * 8; i++) {
+ switch (flags & (1 << i)) {
+ case 0:
+ continue;
+ case LIBSCSI_AF_READ:
+ f |= USCSI_READ;
+ break;
+ case LIBSCSI_AF_WRITE:
+ f |= USCSI_WRITE;
+ break;
+ case LIBSCSI_AF_SILENT:
+ f |= USCSI_SILENT;
+ break;
+ case LIBSCSI_AF_DIAGNOSE:
+ f |= USCSI_DIAGNOSE;
+ break;
+ case LIBSCSI_AF_ISOLATE:
+ f = USCSI_ISOLATE;
+ break;
+ case LIBSCSI_AF_RQSENSE:
+ f = USCSI_RQENABLE;
+ break;
+ default:
+ return (libscsi_error(hp, ESCSI_BOGUSFLAGS,
+ "flag 0x%x is unknown", 1 << i));
+ }
+ }
+
+ *uf = f;
+
+ return (0);
+}
+
+static int
+uscsi_exec(libscsi_hdl_t *hp, void *private, libscsi_action_t *ap)
+{
+ struct uscsi_dev *dp = (struct uscsi_dev *)private;
+ struct uscsi_cmd cmd;
+ size_t data_a, data_v;
+ uint8_t *cp;
+ uint_t flags;
+
+ bzero(&cmd, sizeof (cmd));
+
+ cp = libscsi_action_get_cdb(ap);
+ if (cp == NULL)
+ return (-1);
+
+ flags = libscsi_action_get_flags(ap);
+ if (xlate_flags(hp, flags, &cmd.uscsi_flags) != 0)
+ return (-1);
+
+ cmd.uscsi_status = (short)-1;
+ cmd.uscsi_timeout = (short)libscsi_action_get_timeout(ap);
+
+ cmd.uscsi_cdb = (caddr_t)cp;
+ cmd.uscsi_cdblen = libscsi_cmd_cdblen(hp, *cp);
+ if (cmd.uscsi_cdblen == 0)
+ return (-1);
+
+ if (flags & (LIBSCSI_AF_READ | LIBSCSI_AF_WRITE)) {
+ if (libscsi_action_get_buffer(ap,
+ (uint8_t **)&cmd.uscsi_bufaddr, &data_a, &data_v) != 0)
+ return (-1);
+ if (flags & LIBSCSI_AF_READ)
+ cmd.uscsi_buflen = data_a;
+ else
+ cmd.uscsi_buflen = data_v;
+ }
+ if (flags & LIBSCSI_AF_RQSENSE) {
+ if (libscsi_action_get_sense(ap, (uint8_t **)&cmd.uscsi_rqbuf,
+ &data_a, NULL) != 0)
+ return (-1);
+ if (data_a > UCHAR_MAX)
+ data_a = UCHAR_MAX;
+ cmd.uscsi_rqlen = (uchar_t)data_a;
+ cmd.uscsi_rqstatus = (uchar_t)-1;
+ }
+
+ if (ioctl(dp->fd, USCSICMD, &cmd) < 0) {
+ ASSERT(errno != EFAULT);
+ switch (errno) {
+ case EINVAL:
+ return (libscsi_error(hp, ESCSI_BADCMD, "internal "
+ "uscsi error"));
+ case EPERM:
+ return (libscsi_error(hp, ESCSI_PERM, "insufficient "
+ "privileges "));
+ case EIO:
+ /* Command never executed at all */
+ if (cmd.uscsi_status == (short)-1)
+ return (libscsi_error(hp, ESCSI_IO, "I/O "
+ "error", strerror(errno)));
+ break;
+ default:
+ return (libscsi_error(hp, ESCSI_SYS, "uscsi ioctl "
+ "failed: %s", strerror(errno)));
+ }
+ }
+
+ libscsi_action_set_status(ap, cmd.uscsi_status);
+ if ((flags & LIBSCSI_AF_READ) && libscsi_action_set_datalen(ap,
+ cmd.uscsi_buflen - cmd.uscsi_resid) != 0)
+ return (-1);
+ if ((flags & LIBSCSI_AF_RQSENSE) && libscsi_action_set_senselen(ap,
+ cmd.uscsi_rqlen - cmd.uscsi_rqresid) != 0)
+ return (-1);
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static void
+uscsi_target_name(libscsi_hdl_t *hp, void *private, char *buf, size_t len)
+{
+ struct uscsi_dev *dp = (struct uscsi_dev *)private;
+
+ (void) snprintf(buf, len, "%s", dp->dev);
+}
+
+static const libscsi_engine_ops_t uscsi_ops = {
+ .lseo_open = uscsi_open,
+ .lseo_close = uscsi_close,
+ .lseo_exec = uscsi_exec,
+ .lseo_target_name = uscsi_target_name
+};
+
+static const libscsi_engine_t uscsi_engine = {
+ .lse_name = "uscsi",
+ .lse_libversion = LIBSCSI_VERSION,
+ .lse_ops = &uscsi_ops
+};
+
+/*ARGSUSED*/
+const libscsi_engine_t *
+libscsi_uscsi_init(libscsi_hdl_t *hp)
+{
+ return (&uscsi_engine);
+}
diff --git a/usr/src/lib/scsi/plugins/ses/Makefile b/usr/src/lib/scsi/plugins/ses/Makefile
new file mode 100644
index 0000000000..d89a1ee090
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/Makefile
@@ -0,0 +1,37 @@
+#
+# 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.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+SUBDIRS = \
+ libses \
+ ses2 \
+ SUN-StorageTek-J4400
+
+.KEEP_STATE:
+
+.PARALLEL:
+
+include ../../Makefile.subdirs
diff --git a/usr/src/lib/scsi/plugins/ses/Makefile.lib b/usr/src/lib/scsi/plugins/ses/Makefile.lib
new file mode 100644
index 0000000000..a2831198fc
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/Makefile.lib
@@ -0,0 +1,75 @@
+#
+# 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.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+.KEEP_STATE:
+.SUFFIXES:
+
+include ../../../../../../cmd/Makefile.cmd
+include ../../../../Makefile.defs
+
+#
+# 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.
+#
+PROG = $(MODULE:%=%.so)
+YOBJS = $(YSRCS:%.y=%.o)
+OBJS = $(YOBJS) $(SRCS:%.c=%.o)
+
+#
+# A module may set DMOD and DMOD_SRCS if it has a mdb proc module.
+# DMOD, if set, must match PROG above (for mdb autoloading) so it will
+# be built in a subdirectory.
+#
+ROOTDMOD = $(DMOD:%.so=$(ROOT)/usr/lib/mdb/proc/%.so)
+ROOTDMOD64 = $(DMOD:%.so=$(ROOT)/usr/lib/mdb/proc/$(MACH64)/%.so)
+DMODPROG = $(DMOD:%=dmod/%)
+DMOD_OBJS = $(DMOD_SRCS:%.c=%.o)
+
+ROOTPROG = $(ROOTPLUGINLIBDIR)/ses/$(PLUGINTYPE)/$(PROG)
+ROOTPROG64 = $(ROOTPLUGINLIBDIR)/ses/$(PLUGINTYPE)/$(MACH64)/$(PROG)
+
+LINTFLAGS += -mu
+LINTFILES = $(SRCS:%.c=%.ln)
+
+DMODLINTTGT = $(DMOD:%=lint_dmod)
+DMODLINTFILES = $(DMOD_SRCS:%.c=%.ln)
+
+APIMAP = ../../../../libses/libses_api.map
+
+C99MODE = $(C99_ENABLE)
+CFLAGS += $(CTF_FLAGS) $(CCVERBOSE) $(XSTRCONST) $(CC_PICFLAGS)
+CFLAGS += -G $(XREGSFLAG)
+CFLAGS64 += $(CTF_FLAGS) $(CCVERBOSE) $(XSTRCONST) $(CC_PICFLAGS)
+CFLAGS64 += -G $(XREGSFLAG)
+CPPFLAGS += -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT
+$(NOT_RELEASE_BUILD)CPPFLAGS += -DDEBUG
+LDFLAGS += $(ZTEXT) $(ZCOMBRELOC) $(ZIGNORE)
+
+$(PROG) := LDFLAGS += $(ZDEFS) -M$(APIMAP)
+$(PROG) := LDLIBS += -lc -lnvpair
+
+$(DMODPROG) := LDFLAGS += $(ZNODEFS)
diff --git a/usr/src/lib/scsi/plugins/ses/Makefile.plugin b/usr/src/lib/scsi/plugins/ses/Makefile.plugin
new file mode 100644
index 0000000000..fe0f796fd2
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/Makefile.plugin
@@ -0,0 +1,59 @@
+#
+# 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.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include $(SRC)/Makefile.master
+
+SUBDIRS = $(MACH)
+$(BUILD64)SUBDIRS += $(MACH64)
+
+include ../../../Makefile.defs
+
+ROOTHDRDIR = $(ROOTPLUGINHDRDIR)/ses/$(PLUGINTYPE)
+ROOTHDRS = $(HDRS:%=$(ROOTHDRDIR)/%)
+
+all := TARGET= all
+clean := TARGET= clean
+clobber := TARGET= clobber
+install := TARGET= install
+lint := TARGET= lint
+install_h:= TARGET = install_h
+
+.KEEP_STATE:
+
+all install clean clobber lint: $(SUBDIRS)
+
+install_h: $(ROOTHDRDIR) $(ROOTHDRS)
+
+check:
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+include ../../../Makefile.rootdirs
+include ../../../../Makefile.targ
diff --git a/usr/src/lib/scsi/plugins/ses/Makefile.targ b/usr/src/lib/scsi/plugins/ses/Makefile.targ
new file mode 100644
index 0000000000..c8d0dab5b0
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/Makefile.targ
@@ -0,0 +1,82 @@
+#
+# 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.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+all: $(PROG) $(DMODPROG)
+
+.NO_PARALLEL:
+.PARALLEL: $(OBJS) $(LINTFILES) $(DMOD_OBJS) $(DMODLINTFILES)
+
+$(PROG): $(OBJS) $(APIMAP)
+ $(LINK.c) $(OBJS) -o $@ $(LDLIBS)
+ $(CTFMERGE) -L VERSION -o $@ $(OBJS)
+ $(POST_PROCESS_SO)
+
+$(DMODPROG): $(DMOD_OBJS)
+ -@mkdir -p $(@D)
+ $(LINK.c) $(DMOD_OBJS) -o $@
+ $(POST_PROCESS)
+
+%.o: %.c
+ $(COMPILE.c) $<
+ $(CTFCONVERT_O)
+
+%.o: $(SRCDIR)/%.c
+ $(COMPILE.c) $<
+ $(CTFCONVERT_O)
+
+clean:
+ $(RM) $(OBJS) $(DMOD_OBJS) $(LINTFILES) $(DMODLINTFILES) $(CLEANFILES)
+
+clobber: clean
+ $(RM) $(PROG) $(DMODPROG)
+
+%.ln: %.c
+ $(LINT.c) -c $<
+
+%.ln: $(SRCDIR)/%.c
+ $(LINT.c) -c $<
+
+lint_prog: $(LINTFILES)
+ $(LINT) $(LINTFLAGS) $(LINTFILES) $(LDLIBS)
+
+lint_dmod: $(DMODLINTFILES)
+ $(LINT) $(LINTFLAGS) $(DMODLINTFILES) $(LDLIBS)
+
+lint: lint_prog $(DMODLINTTGT)
+
+install_h:
+
+$(ROOTPROG): $$(@D) $(PROG)
+ $(RM) $@; $(INS) -s -m 0755 -f $(@D) $(PROG)
+
+$(ROOTPROG64): $$(@D) $(PROG)
+ $(RM) $@; $(INS) -s -m 0755 -f $(@D) $(PROG)
+
+$(ROOTDMOD): $$(@D) $(DMODPROG)
+ $(RM) $@; $(INS) -s -m 0755 -f $(@D) $(DMODPROG)
+
+include ../../../../Makefile.rootdirs
diff --git a/usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/Makefile b/usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/Makefile
new file mode 100644
index 0000000000..b39b55f14b
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/Makefile
@@ -0,0 +1,32 @@
+#
+# 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.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+HDRS =
+HDRDIR = common
+PLUGINTYPE = vendor
+
+include ../Makefile.plugin
diff --git a/usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/Makefile.com b/usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/Makefile.com
new file mode 100644
index 0000000000..d6f6a781e5
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/Makefile.com
@@ -0,0 +1,33 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+MODULE = SUN-StorageTek-J4400
+SRCS = riverwalk.c
+SRCDIR = ../common
+PLUGINTYPE = vendor
+
+include ../../Makefile.lib
diff --git a/usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/amd64/Makefile b/usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/amd64/Makefile
new file mode 100644
index 0000000000..fbf98db77f
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/amd64/Makefile
@@ -0,0 +1,33 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+include $(SRC)/Makefile.master.64
+
+install: all $(ROOTPROG64)
+
+include ../../Makefile.targ
diff --git a/usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/common/riverwalk.c b/usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/common/riverwalk.c
new file mode 100644
index 0000000000..bdfe61b737
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/common/riverwalk.c
@@ -0,0 +1,211 @@
+/*
+ * 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"
+
+#include <string.h>
+#include <strings.h>
+
+#include <scsi/libses.h>
+#include <scsi/libses_plugin.h>
+
+#pragma pack(1)
+
+typedef struct ses_riverwalk_stringin {
+ uint8_t rws_download_status;
+ uint8_t rws_descriptor_start;
+ uint16_t rws_descriptor_length;
+ char rws_sim0_id[4];
+ char rws_sim0_pn[15];
+ char rws_sim0_sn[20];
+ char rws_sim1_id[4];
+ char rws_sim1_pn[15];
+ char rws_sim1_sn[20];
+ char rws_mid_id[4];
+ char rws_mid_pn[15];
+ char rws_mid_sn[20];
+ char rws_ps0_id[4];
+ char rws_ps0_pn[15];
+ char rws_ps0_sn[20];
+ char rws_ps1_id[4];
+ char rws_ps1_pn[15];
+ char rws_ps1_sn[20];
+ char __reserved1[29];
+ uint8_t rws_diag_start;
+ uint8_t rws_eid;
+ uint16_t rws_diag_length;
+ uint8_t rws_sim_id;
+ uint8_t rws_numport;
+ uint16_t __reserved2;
+ uint8_t rws_sasaddr[8];
+ uint8_t rws_sys_sn[8];
+ char rws_port0[16];
+ char rws_port1[16];
+ char rws_port2[16];
+} ses_riverwalk_stringin_t;
+
+#pragma pack()
+
+/*ARGSUSED*/
+static int
+sun_riverwalk_parse_node(ses_plugin_t *sp, ses_node_t *np)
+{
+ nvlist_t *props = ses_node_props(np);
+ int nverr;
+ ses_riverwalk_stringin_t *strp;
+ char buf[32];
+ uint64_t type, index;
+ char *pn, *sn;
+ ses_node_t *encp;
+ nvlist_t *encprops;
+ uint8_t *stringin;
+ uint_t len;
+
+ if (ses_node_type(np) != SES_NODE_ENCLOSURE &&
+ ses_node_type(np) != SES_NODE_ELEMENT)
+ return (0);
+
+ /*
+ * Find the containing enclosure node and extract the STRING IN
+ * information.
+ */
+ for (encp = np; ses_node_type(encp) != SES_NODE_ENCLOSURE;
+ encp = ses_node_parent(encp))
+ ;
+
+ encprops = ses_node_props(encp);
+ if (nvlist_lookup_byte_array(encprops, SES_EN_PROP_STRING,
+ &stringin, &len) != 0)
+ return (0);
+
+ if (len < sizeof (ses_riverwalk_stringin_t))
+ return (0);
+
+ strp = (ses_riverwalk_stringin_t *)stringin;
+
+ switch (ses_node_type(np)) {
+ case SES_NODE_ELEMENT:
+ /*
+ * We can get part and serial information for power supplies and
+ * the SIM cards (ESC_ELECTRONICS elements).
+ */
+ VERIFY(nvlist_lookup_uint64(props, SES_PROP_ELEMENT_TYPE,
+ &type) == 0);
+ VERIFY(nvlist_lookup_uint64(props, SES_PROP_ELEMENT_CLASS_INDEX,
+ &index) == 0);
+
+ sn = pn = NULL;
+ switch (type) {
+ case SES_ET_POWER_SUPPLY:
+ switch (index) {
+ case 0:
+ if (strncmp(strp->rws_ps0_id, "SPS0", 4) != 0)
+ break;
+
+ pn = strp->rws_ps0_pn;
+ sn = strp->rws_ps0_sn;
+ break;
+
+ case 1:
+ if (strncmp(strp->rws_ps1_id, "SPS1", 4) != 0)
+ break;
+
+ pn = strp->rws_ps1_pn;
+ sn = strp->rws_ps1_sn;
+ break;
+ }
+ break;
+
+ case SES_ET_ESC_ELECTRONICS:
+ switch (index) {
+ case 0:
+ if (strncmp(strp->rws_sim0_id, "SIM0", 4) != 0)
+ break;
+
+ pn = strp->rws_sim0_pn;
+ sn = strp->rws_sim0_sn;
+ break;
+
+ case 1:
+ if (strncmp(strp->rws_sim1_id, "SIM1", 4) != 0)
+ break;
+
+ pn = strp->rws_sim1_pn;
+ sn = strp->rws_sim1_sn;
+ break;
+ }
+ break;
+ }
+
+ if (pn == NULL)
+ return (0);
+
+ if (pn[0] != '\0') {
+ (void) bcopy(pn, buf, sizeof (strp->rws_ps0_pn));
+ buf[sizeof (strp->rws_ps0_pn)] = '\0';
+ SES_NV_ADD(string, nverr, props, LIBSES_PROP_PART,
+ buf);
+ }
+
+ if (sn[0] != '\0') {
+ (void) bcopy(sn, buf, sizeof (strp->rws_ps0_sn));
+ buf[sizeof (strp->rws_ps0_sn)] = '\0';
+ SES_NV_ADD(string, nverr, props, LIBSES_PROP_SERIAL,
+ sn);
+ }
+
+ break;
+
+ case SES_NODE_ENCLOSURE:
+ /*
+ * The chassis serial number is derived from the MID FRU
+ * descriptor.
+ */
+ if (strncmp(strp->rws_mid_id, "MID ", 4) == 0 &&
+ strp->rws_mid_sn[0] != '\0') {
+ (void) bcopy(strp->rws_mid_sn, buf,
+ sizeof (strp->rws_mid_sn));
+ buf[sizeof (strp->rws_mid_sn)] = '\0';
+ SES_NV_ADD(string, nverr, props, LIBSES_EN_PROP_CSN,
+ buf);
+ }
+
+ break;
+ }
+
+ return (0);
+}
+
+int
+_ses_init(ses_plugin_t *sp)
+{
+ ses_plugin_config_t config = {
+ .spc_node_parse = sun_riverwalk_parse_node
+ };
+
+ return (ses_plugin_register(sp, LIBSES_PLUGIN_VERSION,
+ &config) != 0);
+}
diff --git a/usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/i386/Makefile b/usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/i386/Makefile
new file mode 100644
index 0000000000..447a346278
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/i386/Makefile
@@ -0,0 +1,32 @@
+#
+# 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.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+
+install: all $(ROOTPROG)
+
+include ../../Makefile.targ
diff --git a/usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/sparc/Makefile b/usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/sparc/Makefile
new file mode 100644
index 0000000000..447a346278
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/sparc/Makefile
@@ -0,0 +1,32 @@
+#
+# 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.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+
+install: all $(ROOTPROG)
+
+include ../../Makefile.targ
diff --git a/usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/sparcv9/Makefile b/usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/sparcv9/Makefile
new file mode 100644
index 0000000000..fbf98db77f
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/SUN-StorageTek-J4400/sparcv9/Makefile
@@ -0,0 +1,33 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+include $(SRC)/Makefile.master.64
+
+install: all $(ROOTPROG64)
+
+include ../../Makefile.targ
diff --git a/usr/src/lib/scsi/plugins/ses/libses/Makefile b/usr/src/lib/scsi/plugins/ses/libses/Makefile
new file mode 100644
index 0000000000..fbee544774
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/libses/Makefile
@@ -0,0 +1,32 @@
+#
+# 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.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+HDRS = libses.h
+HDRDIR = common
+PLUGINTYPE = framework
+
+include ../Makefile.plugin
diff --git a/usr/src/lib/scsi/plugins/ses/libses/Makefile.com b/usr/src/lib/scsi/plugins/ses/libses/Makefile.com
new file mode 100644
index 0000000000..104909fce5
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/libses/Makefile.com
@@ -0,0 +1,39 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+MODULE = libses
+SRCS = libses.c \
+ libses_elemtype.c
+SRCDIR = ../common
+PLUGINTYPE = framework
+
+include ../../Makefile.lib
+
+SES2HDR = $(ROOTPLUGINHDRDIR)/ses/framework/ses2.h
+
+../common/libses_elemtype.c: ../common/mkelemtype.sh $(SES2HDR)
+ sh ../common/mkelemtype.sh < $(SES2HDR) > $@
diff --git a/usr/src/lib/scsi/plugins/ses/libses/amd64/Makefile b/usr/src/lib/scsi/plugins/ses/libses/amd64/Makefile
new file mode 100644
index 0000000000..fbf98db77f
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/libses/amd64/Makefile
@@ -0,0 +1,33 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+include $(SRC)/Makefile.master.64
+
+install: all $(ROOTPROG64)
+
+include ../../Makefile.targ
diff --git a/usr/src/lib/scsi/plugins/ses/libses/common/libses.c b/usr/src/lib/scsi/plugins/ses/libses/common/libses.c
new file mode 100644
index 0000000000..28b1b80f60
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/libses/common/libses.c
@@ -0,0 +1,93 @@
+/*
+ * 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"
+
+#include <scsi/libses.h>
+#include <scsi/libses_plugin.h>
+
+#include "libses_impl.h"
+
+/*ARGSUSED*/
+static int
+libses_parse_node(ses_plugin_t *sp, ses_node_t *np)
+{
+ nvlist_t *lid;
+ nvlist_t *props;
+ uint64_t id, type;
+ char csn[17];
+ const char *name;
+ int nverr;
+
+ props = ses_node_props(np);
+
+ if (nvlist_lookup_uint64(props, SES_PROP_ELEMENT_TYPE,
+ &type) == 0 &&
+ (name = ses_element_type_name(type)) != NULL) {
+ /*
+ * Add a standard human-readable name for the element type.
+ */
+ SES_NV_ADD(string, nverr, props,
+ LIBSES_PROP_ELEMENT_TYPE_NAME, name);
+ }
+
+ if (ses_node_type(np) != SES_NODE_ENCLOSURE)
+ return (0);
+
+ /*
+ * The only thing we do for all targets is fill in the default chassis
+ * number from the enclosure logical ID.
+ */
+ if (nvlist_lookup_nvlist(props, SES_EN_PROP_LID, &lid) != 0)
+ return (0);
+
+ VERIFY(nvlist_lookup_uint64(lid, SPC3_NAA_INT, &id) == 0);
+
+ (void) snprintf(csn, sizeof (csn), "%llx", id);
+ SES_NV_ADD(string, nverr, props, LIBSES_EN_PROP_CSN, csn);
+
+ return (0);
+}
+
+int
+_ses_init(ses_plugin_t *sp)
+{
+ ses_plugin_config_t config = {
+ .spc_node_parse = libses_parse_node
+ };
+
+ return (ses_plugin_register(sp, LIBSES_PLUGIN_VERSION,
+ &config) != 0);
+}
+
+/*
+ * libses must be loaded after ses2.
+ */
+int
+_ses_priority(void)
+{
+ return (1);
+}
diff --git a/usr/src/lib/scsi/plugins/ses/libses/common/libses.h b/usr/src/lib/scsi/plugins/ses/libses/common/libses.h
new file mode 100644
index 0000000000..081bb94e5e
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/libses/common/libses.h
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+#ifndef _FRAMEWORK_LIBSES_H
+#define _FRAMEWORK_LIBSES_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * These are properties attached to the root target node of the enclosure, and
+ * represent the SCSI inquiry data.
+ */
+#define SCSI_PROP_VENDOR "scsi-inquiry-vendor"
+#define SCSI_PROP_PRODUCT "scsi-inquiry-product"
+#define SCSI_PROP_REVISION "scsi-inquiry-revision"
+
+/*
+ * This property provides a human-readable name for the element type. This is
+ * constant, and not derived from the enclosure data.
+ */
+#define LIBSES_PROP_ELEMENT_TYPE_NAME "libses-element-type-name"
+
+/*
+ * The following properties can be added to any node. There is no provision in
+ * the specification for these properties, but they can be derived from vendor
+ * specific data for some enclosures.
+ */
+#define LIBSES_PROP_PART "libses-part-number"
+#define LIBSES_PROP_SERIAL "libses-serial-number"
+
+/*
+ * The chassis serial number is a pseudo property that doesn't exist in SES
+ * spec. A single physical chassis may present several logically different SES
+ * targets that are connected to the same or different elements. These targets
+ * can extract the chassis serial number in a vendor-specific way so that
+ * consumers know these SES targets refer to the same device. This defaults to
+ * to the logical-id, and is always present.
+ */
+#define LIBSES_EN_PROP_CSN "libses-chassis-serial"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FRAMEWORK_LIBSES_H */
diff --git a/usr/src/lib/scsi/plugins/ses/libses/common/libses_impl.h b/usr/src/lib/scsi/plugins/ses/libses/common/libses_impl.h
new file mode 100644
index 0000000000..a3fe7af480
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/libses/common/libses_impl.h
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+#ifndef _PLUGIN_LIBSES_IMPL_H
+#define _PLUGIN_LIBSES_IMPL_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const char *ses_element_type_name(uint64_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PLUGIN_LIBSES_IMPL_H */
diff --git a/usr/src/lib/scsi/plugins/ses/libses/common/mkelemtype.sh b/usr/src/lib/scsi/plugins/ses/libses/common/mkelemtype.sh
new file mode 100644
index 0000000000..f9f294d69b
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/libses/common/mkelemtype.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+
+echo "/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident\t\"@(#)mkelemtype.sh\t1.1\t07/01/19 SMI\"
+
+#include <sys/types.h>
+#include <string.h>
+#include <scsi/libses.h>
+
+static const struct {
+\tses2_element_type_t se_type;\t/* element type */
+\tconst char *se_name;\t\t/* element type name */
+} _ses_elemtypestr[] = {"
+
+pattern='^ \(SES_ET_\([A-Z0-9_]*\)\).*'
+replace=' { \1, "\2" },'
+
+( sed -n "s/$pattern/$replace/p" ) || exit 1
+
+echo "\
+};\n\
+\n\
+static uint_t _ses_nelemtypes =\n\
+ sizeof (_ses_elemtypestr) / sizeof (_ses_elemtypestr[0]);\n\
+\n\
+const char *
+ses_element_type_name(uint64_t type)
+{
+ uint_t t;
+
+ for (t = 0; t < _ses_nelemtypes; t++) {
+ if (_ses_elemtypestr[t].se_type == type)
+ return (_ses_elemtypestr[t].se_name);
+ }
+
+ return (NULL);
+}"
+
+exit 0
diff --git a/usr/src/lib/scsi/plugins/ses/libses/i386/Makefile b/usr/src/lib/scsi/plugins/ses/libses/i386/Makefile
new file mode 100644
index 0000000000..447a346278
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/libses/i386/Makefile
@@ -0,0 +1,32 @@
+#
+# 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.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+
+install: all $(ROOTPROG)
+
+include ../../Makefile.targ
diff --git a/usr/src/lib/scsi/plugins/ses/libses/sparc/Makefile b/usr/src/lib/scsi/plugins/ses/libses/sparc/Makefile
new file mode 100644
index 0000000000..447a346278
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/libses/sparc/Makefile
@@ -0,0 +1,32 @@
+#
+# 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.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+
+install: all $(ROOTPROG)
+
+include ../../Makefile.targ
diff --git a/usr/src/lib/scsi/plugins/ses/libses/sparcv9/Makefile b/usr/src/lib/scsi/plugins/ses/libses/sparcv9/Makefile
new file mode 100644
index 0000000000..fbf98db77f
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/libses/sparcv9/Makefile
@@ -0,0 +1,33 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+include $(SRC)/Makefile.master.64
+
+install: all $(ROOTPROG64)
+
+include ../../Makefile.targ
diff --git a/usr/src/lib/scsi/plugins/ses/ses2/Makefile b/usr/src/lib/scsi/plugins/ses/ses2/Makefile
new file mode 100644
index 0000000000..7c713b4077
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/ses2/Makefile
@@ -0,0 +1,32 @@
+#
+# 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.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+HDRS = ses2.h ses2_impl.h
+HDRDIR = common
+PLUGINTYPE = framework
+
+include ../Makefile.plugin
diff --git a/usr/src/lib/scsi/plugins/ses/ses2/Makefile.com b/usr/src/lib/scsi/plugins/ses/ses2/Makefile.com
new file mode 100644
index 0000000000..2f020ac65a
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/ses2/Makefile.com
@@ -0,0 +1,39 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+MODULE = ses2
+SRCS = ses2.c \
+ ses2_element.c \
+ ses2_element_ctl.c \
+ ses2_enclosure.c \
+ ses2_enclosure_ctl.c \
+ ses2_pages.c
+
+SRCDIR = ../common
+PLUGINTYPE = framework
+
+include ../../Makefile.lib
diff --git a/usr/src/lib/scsi/plugins/ses/ses2/amd64/Makefile b/usr/src/lib/scsi/plugins/ses/ses2/amd64/Makefile
new file mode 100644
index 0000000000..fbf98db77f
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/ses2/amd64/Makefile
@@ -0,0 +1,33 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+include $(SRC)/Makefile.master.64
+
+install: all $(ROOTPROG64)
+
+include ../../Makefile.targ
diff --git a/usr/src/lib/scsi/plugins/ses/ses2/common/ses2.c b/usr/src/lib/scsi/plugins/ses/ses2/common/ses2.c
new file mode 100644
index 0000000000..e7d00dfc88
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/ses2/common/ses2.c
@@ -0,0 +1,137 @@
+/*
+ * 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"
+
+#include <scsi/libses.h>
+#include <scsi/libses_plugin.h>
+#include <string.h>
+#include <strings.h>
+
+#include "ses2_impl.h"
+
+/*
+ * Given an nvlist of properties and an array of property handlers, invoke the
+ * appropriate handler for all supported properties.
+ */
+int
+ses2_setprop(ses_plugin_t *sp, ses_node_t *np,
+ const ses2_ctl_prop_t *ctlprops, nvlist_t *props)
+{
+ const ses2_ctl_prop_t *cpp;
+ nvpair_t *nvp;
+
+ for (nvp = nvlist_next_nvpair(props, NULL); nvp != NULL;
+ nvp = nvlist_next_nvpair(props, nvp)) {
+ for (cpp = ctlprops; cpp->scp_name != NULL; cpp++)
+ if (strcmp(cpp->scp_name, nvpair_name(nvp)) == 0)
+ break;
+ if (cpp == NULL)
+ continue;
+
+ if (cpp->scp_setprop(sp, np, cpp->scp_num, nvp) != 0)
+ return (-1);
+
+ (void) nvlist_remove(props, nvpair_name(nvp),
+ nvpair_type(nvp));
+ }
+
+ return (0);
+}
+
+int
+ses2_ctl_common_setprop(ses_plugin_t *sp, ses_node_t *np, ses2_diag_page_t page,
+ nvpair_t *nvp)
+{
+ ses2_cmn_elem_ctl_impl_t *eip;
+ const char *name;
+ boolean_t v;
+
+ ASSERT(page == SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS);
+
+ if ((eip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ page, 0, np, B_FALSE)) == NULL)
+ return (-1);
+
+ name = nvpair_name(nvp);
+ (void) nvpair_value_boolean_value(nvp, &v);
+
+ if (strcmp(name, SES_PROP_SWAP) == 0)
+ eip->seci_rst_swap = !v;
+ else if (strcmp(name, SES_PROP_DISABLED) == 0)
+ eip->seci_disable = v;
+ else if (strcmp(name, SES_PROP_PRDFAIL) == 0)
+ eip->seci_prdfail = v;
+ else
+ ses_panic("Bad property %s", name);
+
+ return (0);
+}
+
+static int
+ses2_node_parse(ses_plugin_t *sp, ses_node_t *np)
+{
+ switch (ses_node_type(np)) {
+ case SES_NODE_ENCLOSURE:
+ return (ses2_fill_enclosure_node(sp, np));
+
+ case SES_NODE_AGGREGATE:
+ case SES_NODE_ELEMENT:
+ return (ses2_fill_element_node(sp, np));
+
+ default:
+ return (0);
+ }
+}
+
+static int
+ses2_node_ctl(ses_plugin_t *sp, ses_node_t *np, const char *op,
+ nvlist_t *nvl)
+{
+ switch (ses_node_type(np)) {
+ case SES_NODE_ENCLOSURE:
+ return (ses2_enclosure_ctl(sp, np, op, nvl));
+
+ case SES_NODE_AGGREGATE:
+ case SES_NODE_ELEMENT:
+ return (ses2_element_ctl(sp, np, op, nvl));
+ }
+
+ return (0);
+}
+
+int
+_ses_init(ses_plugin_t *sp)
+{
+ ses_plugin_config_t config = {
+ .spc_pages = ses2_pages,
+ .spc_node_parse = ses2_node_parse,
+ .spc_node_ctl = ses2_node_ctl
+ };
+
+ return (ses_plugin_register(sp, LIBSES_PLUGIN_VERSION,
+ &config) != 0);
+}
diff --git a/usr/src/lib/scsi/plugins/ses/ses2/common/ses2.h b/usr/src/lib/scsi/plugins/ses/ses2/common/ses2.h
new file mode 100644
index 0000000000..f1ddd0dc1a
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/ses2/common/ses2.h
@@ -0,0 +1,528 @@
+/*
+ * 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.
+ */
+
+#ifndef _FRAMEWORK_SES_H
+#define _FRAMEWORK_SES_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Node properties
+ */
+#define SES_PROP_ELEMENT_TYPE "ses-element-type"
+typedef enum ses2_element_type {
+ SES_ET_UNSPECIFIED = 0,
+ SES_ET_DEVICE = 0x1,
+ SES_ET_POWER_SUPPLY = 0x2,
+ SES_ET_COOLING = 0x3,
+ SES_ET_TEMPERATURE_SENSOR = 0x4,
+ SES_ET_DOOR_LOCK = 0x5,
+ SES_ET_AUDIBLE_ALARM = 0x6,
+ SES_ET_ESC_ELECTRONICS = 0x7,
+ SES_ET_SCC_ELECTRONICS = 0x8,
+ SES_ET_NONVOLATILE_CACHE = 0x9,
+ SES_ET_INVALID_OPERATION_REASON = 0xa,
+ SES_ET_UPS = 0xb,
+ SES_ET_DISPLAY = 0xc,
+ SES_ET_KEY_PAD_ENTRY = 0xd,
+ SES_ET_ENCLOSURE = 0xe,
+ SES_ET_SCSI_PORT_XCVR = 0xf,
+ SES_ET_LANGUAGE = 0x10,
+ SES_ET_COMMUNICATION_PORT = 0x11,
+ SES_ET_VOLTAGE_SENSOR = 0x12,
+ SES_ET_CURRENT_SENSOR = 0x13,
+ SES_ET_SCSI_TARGET_PORT = 0x14,
+ SES_ET_SCSI_INITIATOR_PORT = 0x15,
+ SES_ET_SIMPLE_SUBENCLOSURE = 0x16,
+ SES_ET_ARRAY_DEVICE = 0x17,
+ SES_ET_SAS_EXPANDER = 0x18,
+ SES_ET_SAS_CONNECTOR = 0x19
+} ses2_element_type_t;
+
+#define SES_PROP_STATUS_CODE "ses-status-code"
+typedef enum ses_element_status_code {
+ SES_ESC_UNSUPPORTED = 0,
+ SES_ESC_OK = 1,
+ SES_ESC_CRITICAL = 2,
+ SES_ESC_NONCRITICAL = 3,
+ SES_ESC_UNRECOVERABLE = 4,
+ SES_ESC_NOT_INSTALLED = 5,
+ SES_ESC_UNKNOWN = 6,
+ SES_ESC_UNAVAIL = 7,
+ SES_ESC_NO_ACCESS = 8
+} ses_element_status_code_t;
+
+#define SES_PROP_ELEMENT_CLASS_INDEX "ses-element-class-index" /* U64 */
+#define SES_PROP_ELEMENT_INDEX "ses-element-index" /* U64 */
+#define SES_PROP_BAY_NUMBER "ses-bay-number" /* U64 */
+#define SES_PROP_PRDFAIL "ses-failure-predicted"
+#define SES_PROP_SWAP "ses-swapped"
+#define SES_PROP_DISABLED "ses-disabled"
+#define SES_PROP_IDENT "ses-identify"
+#define SES_PROP_WARN "ses-warning"
+#define SES_PROP_FAIL "ses-failed"
+#define SES_PROP_WARN_REQ "ses-warning-indicator-requested"
+#define SES_PROP_FAIL_REQ "ses-failure-indicator-requested"
+#define SES_PROP_REPORT "ses-reported-via"
+#define SES_PROP_RMV "ses-ready-to-remove"
+#define SES_PROP_OFF "ses-off"
+#define SES_PROP_REQUESTED_ON "ses-requested-on"
+#define SES_PROP_CLASS_DESCRIPTION "ses-class-description" /* S */
+#define SES_PROP_DESCRIPTION "ses-description" /* S */
+#define SES_PROP_HOT_SWAP "ses-hot-swappable"
+
+#define SES_FC_PROP_NODE_NAME "ses-fc-node-name" /* U64 */
+#define SES_FC_PROP_LOOP_POS "ses-fc-loop-position" /* U64 */
+#define SES_FC_PROP_REQ_HARDADDR "ses-fc-requested-hard-address"
+#define SES_FC_PROP_N_PORT_ID "ses-fc-n_port-identifier" /* U64 */
+#define SES_FC_PROP_N_PORT_NAME "ses-fc-n_port-name" /* U64 */
+#define SES_FC_PROP_PORTS "ses-fc-ports" /* NVA */
+
+#define SES_SAS_PROP_DEVICE_TYPE "ses-sas-device-type" /* U64 */
+/*
+ * SAS2r11 7.8.2 Table 123
+ */
+typedef enum sas_device_type {
+ SAS_DT_END_DEVICE = 0x01,
+ SAS_DT_EXPANDER = 0x02,
+ SAS_DT_LEGACY_EXPANDER = 0x3
+} sas_device_type_t;
+
+#define SES_SAS_PROP_SMPI_PORT "ses-sas-smp-initiator-port"
+#define SES_SAS_PROP_STPI_PORT "ses-sas-stp-initiator-port"
+#define SES_SAS_PROP_SSPI_PORT "ses-sas-ssp-initiator-port"
+#define SES_SAS_PROP_SATA_DEVICE "ses-sas-sata-device"
+#define SES_SAS_PROP_SMPT_PORT "ses-sas-smp-target-port"
+#define SES_SAS_PROP_STPT_PORT "ses-sas-stp-target-port"
+#define SES_SAS_PROP_SSPT_PORT "ses-sas-ssp-target-port"
+#define SES_SAS_PROP_ATT_ADDR "ses-sas-attached-address" /* U64 */
+#define SES_SAS_PROP_ADDR "ses-sas-address" /* U64 */
+#define SES_SAS_PROP_PHY_ID "ses-sas-phy-identifier" /* U64 */
+#define SES_SAS_PROP_PHYS "ses-sas-phys" /* NVA */
+#define SES_PROP_CE_IDX "ses-connector-element-index" /* U64 */
+#define SES_PROP_OE_IDX "ses-other-element-index" /* U64 */
+
+#define SES_PROP_THRESH_CRIT_HI "ses-high-critical-threshold" /* U64 */
+#define SES_PROP_THRESH_WARN_HI "ses-high-warning-threshold" /* U64 */
+#define SES_PROP_THRESH_CRIT_LO "ses-low-critical-threshold" /* U64 */
+#define SES_PROP_THRESH_WARN_LO "ses-low-warning-threshold" /* U64 */
+
+/*
+ * Audible Alarm properties
+ */
+#define SES_ALARM_PROP_UNRECOV "ses-indicating-unrecoverable"
+#define SES_ALARM_PROP_CRIT "ses-indicating-critical"
+#define SES_ALARM_PROP_NONCRIT "ses-indicating-noncritical"
+#define SES_ALARM_PROP_INFO "ses-indicating-informational"
+#define SES_ALARM_PROP_REMIND "ses-reminder-mode"
+#define SES_ALARM_PROP_MUTED "ses-muted"
+#define SES_ALARM_PROP_RQST_MUTE "ses-mute-requested"
+
+/*
+ * Nonvolatile Cache properties
+ */
+#define SES_CACHE_PROP_SIZE "ses-cache-size" /* U64 */
+
+/*
+ * Cooling Element properties
+ */
+#define SES_COOLING_PROP_FAN_SPEED "ses-fan-speed" /* U64 */
+#define SES_COOLING_PROP_SPEED_CODE "ses-fan-speed-code" /* U64 */
+typedef enum ses_cooling_fan_speed {
+ SES_COOLING_FAN_SPEED_STOPPED = 0,
+ SES_COOLING_FAN_SPEED_LOWEST = 1,
+ SES_COOLING_FAN_SPEED_LOWER = 2,
+ SES_COOLING_FAN_SPEED_LOW = 3,
+ SES_COOLING_FAN_SPEED_INTERMEDIATE = 4,
+ SES_COOLING_FAN_SPEED_HIGH = 5,
+ SES_COOLING_FAN_SPEED_HIGHER = 6,
+ SES_COOLING_FAN_SPEED_HIGHEST = 7
+} ses_cooling_fan_speed_t;
+
+/*
+ * Device/Array Device properties
+ */
+#define SES_DEV_PROP_SLOT_ADDR "ses-slot-address" /* U64 */
+#define SES_DEV_PROP_PRDFAIL "ses-failure-predicted"
+#define SES_DEV_PROP_READY_TO_INSERT "ses-ready-to-insert"
+#define SES_DEV_PROP_ENC_BYP_A "ses-enclosure-bypassed-a"
+#define SES_DEV_PROP_ENC_BYP_B "ses-enclosure-bypassed-b"
+#define SES_DEV_PROP_DO_NOT_REMOVE "ses-do-not-remove"
+#define SES_DEV_PROP_APP_BYP_A "ses-app-client-bypassed-a"
+#define SES_DEV_PROP_APP_BYP_B "ses-app-client-bypassed-b"
+#define SES_DEV_PROP_DEV_BYP_A "ses-device-bypassed-a"
+#define SES_DEV_PROP_DEV_BYP_B "ses-device-bypassed-b"
+#define SES_DEV_PROP_BYP_A "ses-bypassed-a"
+#define SES_DEV_PROP_BYP_B "ses-bypassed-b"
+#define SES_DEV_PROP_FAULT_RQSTD "ses-fault-requested"
+#define SES_DEV_PROP_FAULT_SENSED "ses-fault-sensed"
+#define SES_DEV_PROP_SAS_NOT_ALL_PHYS "ses-sas-not-all-phys"
+
+/* Control only */
+#define SES_DEV_PROP_REQ_MISSING "ses-request-missing"
+#define SES_DEV_PROP_REQ_ACTIVE "ses-request-activity"
+
+#define SES_AD_PROP_RR_ABORT "ses-remap-rebuild-abort"
+#define SES_AD_PROP_REBUILD "ses-remap-rebuild"
+#define SES_AD_PROP_IN_FAILED_ARRAY "ses-in-failed-array"
+#define SES_AD_PROP_IN_CRIT_ARRAY "ses-in-critical-array"
+#define SES_AD_PROP_CONS_CHK "ses-consistency-check"
+#define SES_AD_PROP_HOT_SPARE "ses-hot-spare"
+#define SES_AD_PROP_RSVD_DEVICE "ses-reserved-device"
+#define SES_AD_PROP_OK "ses-ok"
+
+/*
+ * Display Element properties
+ */
+#define SES_DPY_PROP_CHAR "ses-displayed-character" /* U16 */
+#define SES_DPY_PROP_MODE "ses-display-mode" /* U64 */
+/*
+ * SES-2r17 Table 96, 7.3.14
+ */
+typedef enum ses_display_mode_ctl {
+ SES_DISPLAY_MC_NOCHG = 0,
+ SES_DISPLAY_MC_ESP = 1,
+ SES_DISPLAY_MC_SET = 2
+} ses_display_mode_ctl_t;
+
+typedef enum ses2_display_mode_status {
+ SES_DISPLAY_MS_NOTSUP = 0,
+ SES_DISPLAY_MS_ESP = 1,
+ SES_DISPLAY_MS_SET = 2
+} ses_display_mode_status_t;
+
+/*
+ * Current Sensor properties
+ */
+#define SES_CS_PROP_CRIT_OVER "ses-overcurrent-critical"
+#define SES_CS_PROP_WARN_OVER "ses-overcurrent-warning"
+#define SES_CS_PROP_CURRENT_MA "ses-current" /* I64 */
+
+/*
+ * Door Lock properties
+ */
+#define SES_LOCK_PROP_UNLOCKED "ses-unlocked"
+
+/*
+ * SCSI Initiator or Target Port properties
+ */
+#define SES_ITP_PROP_ENABLED "ses-enabled"
+
+/*
+ * Language Module properties
+ */
+#define SES_LANG_PROP_LANGCODE "ses-language-code" /* U64 */
+
+/*
+ * SCSI Port/Transceiver properties
+ */
+#define SES_PX_PROP_XMIT_FAIL "ses-transmitter-failure"
+#define SES_PX_PROP_LOL "ses-loss-of-link"
+
+/*
+ * Power Supply properties
+ */
+#define SES_PSU_PROP_DC_OVER_CURRENT "ses-dc-over-current"
+#define SES_PSU_PROP_DC_UNDER_VOLTAGE "ses-dc-under-voltage"
+#define SES_PSU_PROP_DC_OVER_VOLTAGE "ses-dc-over-voltage"
+#define SES_PSU_PROP_DC_FAIL "ses-dc-fail"
+#define SES_PSU_PROP_AC_FAIL "ses-ac-fail"
+#define SES_PSU_PROP_TEMP_WARN "ses-temperature-warning" /* I64 */
+#define SES_PSU_PROP_OVERTEMP_FAIL "ses-overtemperature-failure"
+
+/*
+ * SAS Expander properties
+ */
+#define SES_EXP_PROP_SAS_ADDR "ses-expander-sas-address" /* U64 */
+
+/*
+ * SAS Connector properties
+ */
+#define SES_SC_PROP_PHYSICAL_LINK "ses-sas-physical-link" /* U64 */
+#define SES_SC_PROP_CONNECTOR_TYPE "ses-sas-connector-type" /* U64 */
+/*
+ * SES2r17 Table 122, 7.3.26
+ */
+typedef enum ses_sasconn_type {
+ SES_SASCONN_T_UNKNOWN = 0,
+ SES_SASCONN_T_SFF_8470 = 0x1,
+ SES_SASCONN_T_SFF_8088 = 0x2,
+ SES_SASCONN_T_VENDOR_EXT = 0xf,
+ SES_SASCONN_T_SFF_8484 = 0x10,
+ SES_SASCONN_T_SFF_8087 = 0x11,
+ SES_SASCONN_T_SFF_8482_R = 0x20,
+ SES_SASCONN_T_SATA_HOST = 0x21,
+ SES_SASCONN_T_SFF_8482_P = 0x22,
+ SES_SASCONN_T_SATA_DEV = 0x23,
+ SES_SASCONN_T_VIRTUAL = 0x2f,
+ SES_SASCONN_T_VENDOR_INT = 0x3f,
+ SES_SASCONN_T_VENDOR_70 = 0x70,
+ SES_SASCONN_T_VENDOR_71 = 0x71,
+ SES_SASCONN_T_VENDOR_72 = 0x72,
+ SES_SASCONN_T_VENDOR_73 = 0x73,
+ SES_SASCONN_T_VENDOR_74 = 0x74,
+ SES_SASCONN_T_VENDOR_75 = 0x75,
+ SES_SASCONN_T_VENDOR_76 = 0x76,
+ SES_SASCONN_T_VENDOR_77 = 0x77,
+ SES_SASCONN_T_VENDOR_78 = 0x78,
+ SES_SASCONN_T_VENDOR_79 = 0x79,
+ SES_SASCONN_T_VENDOR_7A = 0x7a,
+ SES_SASCONN_T_VENDOR_7B = 0x7b,
+ SES_SASCONN_T_VENDOR_7C = 0x7c,
+ SES_SASCONN_T_VENDOR_7D = 0x7d,
+ SES_SASCONN_T_VENDOR_7E = 0x7e,
+ SES_SASCONN_T_VENDOR_7F = 0x7f
+} ses_sasconn_type_t;
+
+/*
+ * Simple Subenclosure properties
+ */
+#define SES_SS_PROP_SHORT_STATUS "ses-short-status" /* U64 */
+
+/*
+ * Temperature Sensor properties
+ */
+#define SES_TEMP_PROP_TEMP "ses-temperature" /* I64 */
+#define SES_TEMP_PROP_UNDERTEMP_WARN "ses-undertemperature-warning"
+#define SES_TEMP_PROP_UNDERTEMP_FAIL "ses-undertemperature-failure"
+#define SES_TEMP_PROP_OVERTEMP_WARN "ses-overtemperature-warning"
+#define SES_TEMP_PROP_OVERTEMP_FAIL "ses-overtemperature-failure"
+
+/*
+ * Uninterruptible Power Supply properties
+ */
+#define SES_UPS_PROP_TIMELEFT "ses-battery-time-remaining" /* U64 */
+#define SES_UPS_PROP_INTF_FAIL "ses-interface-failure"
+#define SES_UPS_PROP_WARN "ses-low-battery-warning"
+#define SES_UPS_PROP_UPS_FAIL "ses-ups-failure"
+#define SES_UPS_PROP_DC_FAIL "ses-dc-failure"
+#define SES_UPS_PROP_AC_FAIL "ses-ac-failure"
+#define SES_UPS_PROP_AC_QUAL "ses-ac-quality-exception"
+#define SES_UPS_PROP_AC_HI "ses-ac-overvoltage-exception"
+#define SES_UPS_PROP_AC_LO "ses-ac-undervoltage-exception"
+#define SES_UPS_PROP_BPF "ses-battery-failure-predicted"
+#define SES_UPS_PROP_BATT_FAIL "ses-battery-failure"
+
+/*
+ * Voltage Sensor properties
+ */
+#define SES_VS_PROP_CRIT_UNDER "ses-undervoltage-critical"
+#define SES_VS_PROP_CRIT_OVER "ses-overvoltage-critical"
+#define SES_VS_PROP_WARN_UNDER "ses-undervoltage-warning"
+#define SES_VS_PROP_WARN_OVER "ses-overvoltage-warning"
+#define SES_VS_PROP_VOLTAGE_MV "ses-voltage" /* I64 */
+
+/*
+ * Enclosure Services Controller properties (Control only)
+ */
+#define SES_ESC_PROP_SELECT "ses-select-element"
+
+/*
+ * Primary/Subenclosure properties
+ */
+#define SES_EN_PROP_EID "ses-enclosure-id" /* U64 */
+#define SES_EN_PROP_ESPID "ses-enclosure-service-proc-id"
+#define SES_EN_PROP_NESP "ses-enclosure-service-proc-count"
+#define SES_EN_PROP_LID "ses-logical-id" /* NV */
+#define SES_EN_PROP_VID "ses-vendor-id" /* S */
+#define SES_EN_PROP_PID "ses-product-id" /* S */
+#define SES_EN_PROP_REV "ses-product-revision" /* S */
+#define SES_EN_PROP_VS "ses-product-vendor-specific" /* BA */
+
+#define SES_EN_PROP_UNRECOV "ses-status-unrecoverable"
+#define SES_EN_PROP_CRIT "ses-status-critical"
+#define SES_EN_PROP_NONCRIT "ses-status-noncritical"
+#define SES_EN_PROP_INFO "ses-status-informational"
+#define SES_EN_PROP_INVOP "ses-status-invalid-operation"
+#define SES_EN_PROP_HELP "ses-help-text" /* S */
+#define SES_EN_PROP_STRING "ses-string-in-data" /* BA */
+#define SES_EN_PROP_SHORT "ses-short-status" /* U64 */
+#define SES_EN_PROP_UCODE "ses-microcode-dl-status" /* U64 */
+typedef enum ses2_dl_ucode_status {
+ SES2_DLUCODE_S_NOP = 0,
+ SES2_DLUCODE_S_INPROGRESS = 0x1,
+ SES2_DLUCODE_S_SAVING = 0x2,
+ SES2_DLUCODE_S_INTERIM_3 = 0x3,
+ SES2_DLUCODE_S_INTERIM_4 = 0x4,
+ SES2_DLUCODE_S_INTERIM_5 = 0x5,
+ SES2_DLUCODE_S_INTERIM_6 = 0x6,
+ SES2_DLUCODE_S_INTERIM_7 = 0x7,
+ SES2_DLUCODE_S_INTERIM_8 = 0x8,
+ SES2_DLUCODE_S_INTERIM_9 = 0x9,
+ SES2_DLUCODE_S_INTERIM_A = 0xa,
+ SES2_DLUCODE_S_INTERIM_B = 0xb,
+ SES2_DLUCODE_S_INTERIM_C = 0xc,
+ SES2_DLUCODE_S_INTERIM_D = 0xd,
+ SES2_DLUCODE_S_INTERIM_E = 0xe,
+ SES2_DLUCODE_S_INTERIM_F = 0xf,
+ SES2_DLUCODE_S_COMPLETE_NOW = 0x10,
+ SES2_DLUCODE_S_COMPLETE_AT_RESET = 0x11,
+ SES2_DLUCODE_S_COMPLETE_AT_POWERON = 0x12,
+ SES2_DLUCODE_S_VENDOR_70 = 0x70,
+ SES2_DLUCODE_S_VENDOR_71 = 0x71,
+ SES2_DLUCODE_S_VENDOR_72 = 0x72,
+ SES2_DLUCODE_S_VENDOR_73 = 0x73,
+ SES2_DLUCODE_S_VENDOR_74 = 0x74,
+ SES2_DLUCODE_S_VENDOR_75 = 0x75,
+ SES2_DLUCODE_S_VENDOR_76 = 0x76,
+ SES2_DLUCODE_S_VENDOR_77 = 0x77,
+ SES2_DLUCODE_S_VENDOR_78 = 0x78,
+ SES2_DLUCODE_S_VENDOR_79 = 0x79,
+ SES2_DLUCODE_S_VENDOR_7A = 0x7a,
+ SES2_DLUCODE_S_VENDOR_7B = 0x7b,
+ SES2_DLUCODE_S_VENDOR_7C = 0x7c,
+ SES2_DLUCODE_S_VENDOR_7D = 0x7d,
+ SES2_DLUCODE_S_VENDOR_7E = 0x7e,
+ SES2_DLUCODE_S_VENDOR_7F = 0x7f,
+ SES2_DLUCODE_S_PAGE_ERR = 0x80,
+ SES2_DLUCODE_S_IMAGE_ERR = 0x81,
+ SES2_DLUCODE_S_TIMEOUT = 0x82,
+ SES2_DLUCODE_S_INTERNAL_NEEDIMAGE = 0x83,
+ SES2_DLUCODE_S_INTERNAL_SAFE = 0x84,
+ SES2_DLUCODE_S_VENDOR_ERR_F0 = 0xf0,
+ SES2_DLUCODE_S_VENDOR_ERR_F1 = 0xf1,
+ SES2_DLUCODE_S_VENDOR_ERR_F2 = 0xf2,
+ SES2_DLUCODE_S_VENDOR_ERR_F3 = 0xf3,
+ SES2_DLUCODE_S_VENDOR_ERR_F4 = 0xf4,
+ SES2_DLUCODE_S_VENDOR_ERR_F5 = 0xf5,
+ SES2_DLUCODE_S_VENDOR_ERR_F6 = 0xf6,
+ SES2_DLUCODE_S_VENDOR_ERR_F7 = 0xf7,
+ SES2_DLUCODE_S_VENDOR_ERR_F8 = 0xf8,
+ SES2_DLUCODE_S_VENDOR_ERR_F9 = 0xf9,
+ SES2_DLUCODE_S_VENDOR_ERR_FA = 0xfa,
+ SES2_DLUCODE_S_VENDOR_ERR_FB = 0xfb,
+ SES2_DLUCODE_S_VENDOR_ERR_FC = 0xfc,
+ SES2_DLUCODE_S_VENDOR_ERR_FD = 0xfd,
+ SES2_DLUCODE_S_VENDOR_ERR_FE = 0xfe,
+ SES2_DLUCODE_S_VENDOR_ERR_FF = 0xff
+} ses2_dl_ucode_status_t;
+
+typedef enum ses_dl_ucode_mode {
+ SES_DLUCODE_M_WITH_OFFS = 6,
+ SES_DLUCODE_M_WITH_OFFS_SAVE = 7
+} ses_dl_ucode_mode_t;
+
+#define SES_EN_PROP_UCODE_A "ses-microcode-dl-addl-status" /* U64 */
+#define SES_EN_PROP_UCODE_SZ "ses-microcode-maximum-size" /* U64 */
+#define SES_EN_PROP_UCODE_BUF "ses-microcode-buffer-id" /* U64 */
+#define SES_EN_PROP_UCODE_OFF "ses-microcode-buffer-offset" /* U64 */
+
+#define SES_EN_PROP_NICK "ses-nickname" /* S */
+#define SES_EN_PROP_NICK_STATUS "ses-nickname-status" /* U64 */
+typedef enum ses_subnick_status {
+ SES_SNS_NO_ERROR = 0x0,
+ SES_SNS_ERR_PAGE = 0x80,
+ SES_SNS_ERR_INT_NICKLOST = 0x81,
+ SES_SNS_ERR_INT_PRESERVED = 0x82
+} ses_subnick_status_t;
+
+#define SES_EN_PROP_NICK_ADDL_STATUS "ses-nickname-additional-status"
+#define SES_EN_PROP_NICK_LANG "ses-nickname-language" /* U64 */
+
+#define SES_EN_PROP_POWER_DELAY "ses-power-cycle-delay" /* U64 */
+#define SES_EN_PROP_POWER_DURATION "ses-power-cycle-duration" /* U64 */
+#define SES_EN_PROP_POWER_REQUEST "ses-power-cycle-request" /* U64 */
+
+typedef enum ses_power_delay {
+ SES_PDL_NONE = 0x0,
+ SES_PDL_IMMEDIATE = 0x3f
+} ses_power_delay_t;
+
+typedef enum ses_power_duration {
+ SES_PDR_NONE = 0x0,
+ SES_PDR_MANUAL = 0x3f
+} ses_power_duration_t;
+
+typedef enum ses_power_request {
+ SES_PRQ_NONE = 0x0,
+ SES_PRQ_SET = 0x1,
+ SES_PRQ_CANCEL = 0x2
+} ses_power_request_t;
+
+/*
+ * IEEE logical IDs (for SES_EN_PROP_LID)
+ */
+#define SPC3_NAA_INT "naa-id-integer" /* U64 */
+#define SPC3_NAA_ID_TYPE "naa-id-type" /* U64 */
+#define SPC3_NAA_COMPANY_ID "naa-company-id" /* U64 */
+#define SPC3_NAA_VS_A "naa-vendor-specific-a" /* U64 */
+#define SPC3_NAA_VS_B "naa-vendor-specific-b" /* U64 */
+
+/*
+ * SES-2 Diagnostic page codes (Table 5, 6.1.1). The set of exported pages
+ * constitutes an inter-plugin interface and is therefore part of the public
+ * header file.
+ */
+typedef enum ses2_diag_page {
+ SES2_DIAGPAGE_SUPPORTED_PAGES = 0x00,
+ SES2_DIAGPAGE_CONFIG = 0x01,
+ SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS = 0x02,
+ SES2_DIAGPAGE_HELP_TEXT = 0x03,
+ SES2_DIAGPAGE_STRING_IO = 0x04,
+ SES2_DIAGPAGE_THRESHOLD_IO = 0x05,
+ SES2_DIAGPAGE_ELEMENT_DESC = 0x07,
+ SES2_DIAGPAGE_SHORT_STATUS = 0x08,
+ SES2_DIAGPAGE_ENCLOSURE_BUSY = 0x09,
+ SES2_DIAGPAGE_ADDL_ELEM_STATUS = 0x0a,
+ SES2_DIAGPAGE_SUBENCLOSURE_HELP_TEXT = 0x0b,
+ SES2_DIAGPAGE_SUBENCLOSURE_STRING_IO = 0x0c,
+ SES2_DIAGPAGE_SUPPORTED_SES_PAGES = 0x0d,
+ SES2_DIAGPAGE_DL_MICROCODE_CTL_STATUS = 0x0e,
+ SES2_DIAGPAGE_SUBENCLOSURE_NICKNAME_CTL_STATUS = 0x0f,
+ SES2_DIAGPAGE_VENDOR_0 = 0x10,
+ SES2_DIAGPAGE_VENDOR_1 = 0x11,
+ SES2_DIAGPAGE_VENDOR_2 = 0x12,
+ SES2_DIAGPAGE_VENDOR_3 = 0x13,
+ SES2_DIAGPAGE_VENDOR_4 = 0x14,
+ SES2_DIAGPAGE_VENDOR_5 = 0x15,
+ SES2_DIAGPAGE_VENDOR_6 = 0x16,
+ SES2_DIAGPAGE_VENDOR_7 = 0x17,
+ SES2_DIAGPAGE_VENDOR_8 = 0x18,
+ SES2_DIAGPAGE_VENDOR_9 = 0x19,
+ SES2_DIAGPAGE_VENDOR_A = 0x1a,
+ SES2_DIAGPAGE_VENDOR_B = 0x1b,
+ SES2_DIAGPAGE_VENDOR_C = 0x1c,
+ SES2_DIAGPAGE_VENDOR_D = 0x1d,
+ SES2_DIAGPAGE_VENDOR_E = 0x1e,
+ SES2_DIAGPAGE_VENDOR_F = 0x1f
+} ses2_diag_page_t;
+
+#define SES_CTL_OP_SETPROP "ses-ctl-setprop"
+#define SES_CTL_OP_DL_UCODE "ses-ctl-dl-ucode"
+
+#define SES_CTL_PROP_UCODE_DATA "ses-ctl-ucode-data"
+#define SES_CTL_PROP_UCODE_BUFID "ses-ctl-ucode-bufid"
+#define SES_CTL_PROP_UCODE_MODE "ses-ctl-ucode-mode"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FRAMEWORK_SES_H */
diff --git a/usr/src/lib/scsi/plugins/ses/ses2/common/ses2_element.c b/usr/src/lib/scsi/plugins/ses/ses2/common/ses2_element.c
new file mode 100644
index 0000000000..b0fe97d6d5
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/ses2/common/ses2_element.c
@@ -0,0 +1,1008 @@
+/*
+ * 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"
+
+#include <sys/types.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <libnvpair.h>
+
+#include <scsi/libses.h>
+#include "ses2_impl.h"
+
+static int
+elem_parse_device(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
+{
+ ses2_device_status_impl_t *dip = (ses2_device_status_impl_t *)esip;
+ int nverr;
+
+ SES_NV_ADD(uint64, nverr, nvl, SES_DEV_PROP_SLOT_ADDR,
+ dip->sdsi_slot_addr);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_REPORT,
+ dip->sdsi_report);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT,
+ dip->sdsi_ident);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_RMV, dip->sdsi_rmv);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_READY_TO_INSERT,
+ dip->sdsi_ready_to_insert);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_ENC_BYP_B,
+ dip->sdsi_enclosure_bypassed_b);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_ENC_BYP_A,
+ dip->sdsi_enclosure_bypassed_a);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_DO_NOT_REMOVE,
+ dip->sdsi_do_not_remove);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_APP_BYP_A,
+ dip->sdsi_app_client_bypassed_a);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_DEV_BYP_B,
+ dip->sdsi_device_bypassed_b);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_DEV_BYP_A,
+ dip->sdsi_device_bypassed_a);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_BYP_B,
+ dip->sdsi_bypassed_b);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_BYP_A,
+ dip->sdsi_bypassed_a);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_OFF,
+ dip->sdsi_device_off);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_FAULT_RQSTD,
+ dip->sdsi_fault_reqstd);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_FAULT_SENSED,
+ dip->sdsi_fault_sensed);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_APP_BYP_B,
+ dip->sdsi_app_client_bypassed_b);
+
+ return (0);
+}
+
+static int
+elem_parse_psu(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
+{
+ ses2_psu_status_impl_t *pip = (ses2_psu_status_impl_t *)esip;
+ int nverr;
+
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT,
+ pip->spsi_ident);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PSU_PROP_DC_OVER_CURRENT,
+ pip->spsi_dc_over_current);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PSU_PROP_DC_UNDER_VOLTAGE,
+ pip->spsi_dc_under_voltage);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PSU_PROP_DC_OVER_VOLTAGE,
+ pip->spsi_dc_over_voltage);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PSU_PROP_DC_FAIL,
+ pip->spsi_dc_fail);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PSU_PROP_AC_FAIL,
+ pip->spsi_ac_fail);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PSU_PROP_TEMP_WARN,
+ pip->spsi_temp_warn);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PSU_PROP_OVERTEMP_FAIL,
+ pip->spsi_overtmp_fail);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_OFF, pip->spsi_off);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_REQUESTED_ON,
+ pip->spsi_rqsted_on);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, pip->spsi_fail);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_HOT_SWAP,
+ pip->spsi_hot_swap);
+
+ return (0);
+}
+
+static int
+elem_parse_cooling(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
+{
+ ses2_cooling_status_impl_t *cip = (ses2_cooling_status_impl_t *)esip;
+ int nverr;
+
+ SES_NV_ADD(uint64, nverr, nvl, SES_COOLING_PROP_FAN_SPEED,
+ SES2_ES_COOLING_ST_FAN_SPEED(cip));
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT,
+ cip->scsi_ident);
+ SES_NV_ADD(uint64, nverr, nvl, SES_COOLING_PROP_SPEED_CODE,
+ cip->scsi_actual_speed_code);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_OFF, cip->scsi_off);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_REQUESTED_ON,
+ cip->scsi_requested_on);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, cip->scsi_fail);
+
+ return (0);
+}
+
+static int
+elem_parse_temp(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
+{
+ ses2_temp_status_impl_t *tip = (ses2_temp_status_impl_t *)esip;
+ int nverr;
+
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, tip->stsi_ident);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, tip->stsi_fail);
+ SES_NV_ADD(int64, nverr, nvl, SES_TEMP_PROP_TEMP,
+ SES2_ES_TEMP_ST_TEMPERATURE(tip));
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_TEMP_PROP_UNDERTEMP_WARN,
+ tip->stsi_ut_warn);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_TEMP_PROP_UNDERTEMP_FAIL,
+ tip->stsi_ut_fail);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_TEMP_PROP_OVERTEMP_WARN,
+ tip->stsi_ot_warn);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_TEMP_PROP_OVERTEMP_FAIL,
+ tip->stsi_ot_fail);
+
+ return (0);
+}
+
+static int
+elem_parse_lock(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
+{
+ ses2_lock_status_impl_t *lip = (ses2_lock_status_impl_t *)esip;
+ int nverr;
+
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL,
+ lip->slsi_fail);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT,
+ lip->slsi_ident);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_LOCK_PROP_UNLOCKED,
+ lip->slsi_unlocked);
+
+ return (0);
+}
+
+static int
+elem_parse_alarm(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
+{
+ ses2_alarm_status_impl_t *aip = (ses2_alarm_status_impl_t *)esip;
+ int nverr;
+
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, aip->sasi_fail);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT,
+ aip->sasi_ident);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_ALARM_PROP_UNRECOV,
+ aip->sasi_unrecov);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_ALARM_PROP_CRIT,
+ aip->sasi_crit);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_ALARM_PROP_NONCRIT,
+ aip->sasi_noncrit);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_ALARM_PROP_INFO,
+ aip->sasi_info);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_ALARM_PROP_REMIND,
+ aip->sasi_remind);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_ALARM_PROP_MUTED,
+ aip->sasi_muted);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_ALARM_PROP_RQST_MUTE,
+ aip->sasi_rqst_mute);
+
+ return (0);
+}
+
+static int
+elem_parse_esc(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
+{
+ ses2_controller_status_impl_t *cip =
+ (ses2_controller_status_impl_t *)esip;
+ int nverr;
+
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, cip->scsi_fail);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, cip->scsi_ident);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_REPORT,
+ cip->scsi_report);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_HOT_SWAP,
+ cip->scsi_hot_swap);
+
+ return (0);
+}
+
+static int
+elem_parse_scc(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
+{
+ ses2_scc_status_impl_t *sip = (ses2_scc_status_impl_t *)esip;
+ int nverr;
+
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, sip->sss_fail);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, sip->sss_ident);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_REPORT,
+ sip->sss_report);
+
+ return (0);
+}
+
+static int
+elem_parse_cache(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
+{
+ ses2_nvcache_status_impl_t *np = (ses2_nvcache_status_impl_t *)esip;
+ int nverr;
+
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, np->snsi_fail);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT,
+ np->snsi_ident);
+ SES_NV_ADD(uint64, nverr, nvl, SES_CACHE_PROP_SIZE,
+ SES2_NVCACHE_SIZE(np));
+
+ return (0);
+}
+
+static int
+elem_parse_ups(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
+{
+ ses2_ups_status_impl_t *uip = (ses2_ups_status_impl_t *)esip;
+ int nverr;
+
+ SES_NV_ADD(uint64, nverr, nvl, SES_UPS_PROP_TIMELEFT,
+ uip->susi_battery_status);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_UPS_PROP_INTF_FAIL,
+ uip->susi_intf_fail);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_UPS_PROP_WARN,
+ uip->susi_warn);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_UPS_PROP_UPS_FAIL,
+ uip->susi_ups_fail);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_UPS_PROP_DC_FAIL,
+ uip->susi_dc_fail);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_UPS_PROP_AC_FAIL,
+ uip->susi_ac_fail);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_UPS_PROP_AC_QUAL,
+ uip->susi_ac_qual);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_UPS_PROP_AC_HI,
+ uip->susi_ac_hi);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_UPS_PROP_AC_LO,
+ uip->susi_ac_lo);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_UPS_PROP_BPF, uip->susi_bpf);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_UPS_PROP_BATT_FAIL,
+ uip->susi_batt_fail);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, uip->susi_fail);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, uip->susi_ident);
+
+ return (0);
+}
+
+static int
+elem_parse_display(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
+{
+ ses2_display_status_impl_t *dip = (ses2_display_status_impl_t *)esip;
+ int nverr;
+
+ SES_NV_ADD(uint64, nverr, nvl, SES_DPY_PROP_MODE,
+ dip->sdsi_display_mode_status);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, dip->sdsi_fail);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, dip->sdsi_ident);
+ SES_NV_ADD(uint16, nverr, nvl, SES_DPY_PROP_CHAR,
+ dip->sdsi_display_character_status);
+
+ return (0);
+}
+
+static int
+elem_parse_keypad(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
+{
+ ses2_keypad_status_impl_t *kip = (ses2_keypad_status_impl_t *)esip;
+ int nverr;
+
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, kip->sksi_fail);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, kip->sksi_ident);
+
+ return (0);
+}
+
+static int
+elem_parse_px(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
+{
+ ses2_port_status_impl_t *pip = (ses2_port_status_impl_t *)esip;
+ int nverr;
+
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, pip->spsi_fail);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, pip->spsi_ident);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_REPORT,
+ pip->spsi_report);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PX_PROP_XMIT_FAIL,
+ pip->spsi_xmit_fail);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PX_PROP_LOL, pip->spsi_lol);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_DISABLED,
+ pip->spsi_disabled);
+
+ return (0);
+}
+
+static int
+elem_parse_lang(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
+{
+ ses2_lang_status_impl_t *lip = (ses2_lang_status_impl_t *)esip;
+ int nverr;
+
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT,
+ lip->slsi_ident);
+ SES_NV_ADD(uint64, nverr, nvl, SES_LANG_PROP_LANGCODE,
+ SCSI_READ16(&lip->slsi_language_code));
+
+ return (0);
+}
+
+static int
+elem_parse_comm(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
+{
+ ses2_comm_status_impl_t *cip = (ses2_comm_status_impl_t *)esip;
+ int nverr;
+
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, cip->scsi_fail);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT,
+ cip->scsi_ident);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_DISABLED,
+ cip->scsi_disabled);
+
+ return (0);
+}
+
+static int
+elem_parse_voltage(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
+{
+ ses2_voltage_status_impl_t *vip = (ses2_voltage_status_impl_t *)esip;
+ int nverr;
+
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_VS_PROP_CRIT_UNDER,
+ vip->svsi_crit_under);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_VS_PROP_CRIT_OVER,
+ vip->svsi_crit_over);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_VS_PROP_WARN_UNDER,
+ vip->svsi_warn_under);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_VS_PROP_WARN_OVER,
+ vip->svsi_warn_over);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, vip->svsi_fail);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, vip->svsi_ident);
+ SES_NV_ADD(int64, nverr, nvl, SES_VS_PROP_VOLTAGE_MV,
+ SCSI_READ16(&vip->svsi_voltage));
+
+ return (0);
+}
+
+static int
+elem_parse_current(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
+{
+ ses2_current_status_impl_t *cip = (ses2_current_status_impl_t *)esip;
+ int nverr;
+
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_CS_PROP_CRIT_OVER,
+ cip->scsi_crit_over);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_CS_PROP_WARN_OVER,
+ cip->scsi_warn_over);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, cip->scsi_fail);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, cip->scsi_ident);
+ SES_NV_ADD(int64, nverr, nvl, SES_CS_PROP_CURRENT_MA,
+ SCSI_READ16(&cip->scsi_current));
+
+ return (0);
+}
+
+static int
+elem_parse_itp(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
+{
+ ses2_itp_status_impl_t *iip = (ses2_itp_status_impl_t *)esip;
+ int nverr;
+
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, iip->sisi_fail);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT,
+ iip->sisi_ident);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_REPORT,
+ iip->sisi_report);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_ITP_PROP_ENABLED,
+ iip->sisi_enabled);
+
+ return (0);
+}
+
+static int
+elem_parse_sse(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
+{
+ ses2_ss_status_impl_t *sip = (ses2_ss_status_impl_t *)esip;
+ int nverr;
+
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, sip->sss_fail);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, sip->sss_ident);
+ SES_NV_ADD(uint64, nverr, nvl, SES_SS_PROP_SHORT_STATUS,
+ sip->sss_short_status);
+
+ return (0);
+}
+
+static int
+elem_parse_arraydev(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
+{
+ ses2_array_device_status_impl_t *aip =
+ (ses2_array_device_status_impl_t *)esip;
+ int nverr;
+
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_AD_PROP_RR_ABORT,
+ aip->sadsi_rr_abort);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_AD_PROP_REBUILD,
+ aip->sadsi_rebuild);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_AD_PROP_IN_FAILED_ARRAY,
+ aip->sadsi_in_failed_array);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_AD_PROP_IN_CRIT_ARRAY,
+ aip->sadsi_in_crit_array);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_AD_PROP_CONS_CHK,
+ aip->sadsi_cons_chk);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_AD_PROP_HOT_SPARE,
+ aip->sadsi_hot_spare);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_AD_PROP_RSVD_DEVICE,
+ aip->sadsi_rsvd_device);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_AD_PROP_OK, aip->sadsi_ok);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_REPORT,
+ aip->sadsi_report);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, aip->sadsi_ident);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_RMV, aip->sadsi_rmv);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_READY_TO_INSERT,
+ aip->sadsi_ready_to_insert);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_ENC_BYP_B,
+ aip->sadsi_enclosure_bypassed_b);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_ENC_BYP_A,
+ aip->sadsi_enclosure_bypassed_a);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_DO_NOT_REMOVE,
+ aip->sadsi_do_not_remove);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_APP_BYP_A,
+ aip->sadsi_app_client_bypassed_a);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_DEV_BYP_B,
+ aip->sadsi_device_bypassed_b);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_DEV_BYP_A,
+ aip->sadsi_device_bypassed_a);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_BYP_B,
+ aip->sadsi_bypassed_b);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_BYP_A,
+ aip->sadsi_bypassed_a);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_OFF,
+ aip->sadsi_device_off);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_FAULT_RQSTD,
+ aip->sadsi_fault_reqstd);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_FAULT_SENSED,
+ aip->sadsi_fault_sensed);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_APP_BYP_B,
+ aip->sadsi_app_client_bypassed_b);
+
+ return (0);
+}
+
+static int
+elem_parse_expander(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
+{
+ ses2_expander_status_impl_t *eip = (ses2_expander_status_impl_t *)esip;
+ int nverr;
+
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, eip->sesi_fail);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, eip->sesi_ident);
+
+ return (0);
+}
+
+static int
+elem_parse_sasconn(const ses2_elem_status_impl_t *esip, nvlist_t *nvl)
+{
+ ses2_sasconn_status_impl_t *sip = (ses2_sasconn_status_impl_t *)esip;
+ int nverr;
+
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, sip->sss_fail);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, sip->sss_ident);
+ SES_NV_ADD(uint64, nverr, nvl, SES_SC_PROP_CONNECTOR_TYPE,
+ sip->sss_connector_type);
+ SES_NV_ADD(uint64, nverr, nvl, SES_SC_PROP_PHYSICAL_LINK,
+ sip->sss_connector_physical_link);
+
+ return (0);
+}
+
+static const struct status_parser {
+ ses2_element_type_t type;
+ int (*func)(const ses2_elem_status_impl_t *, nvlist_t *);
+} status_parsers[] = {
+ { SES_ET_DEVICE, elem_parse_device },
+ { SES_ET_POWER_SUPPLY, elem_parse_psu },
+ { SES_ET_COOLING, elem_parse_cooling },
+ { SES_ET_TEMPERATURE_SENSOR, elem_parse_temp },
+ { SES_ET_DOOR_LOCK, elem_parse_lock },
+ { SES_ET_AUDIBLE_ALARM, elem_parse_alarm },
+ { SES_ET_ESC_ELECTRONICS, elem_parse_esc },
+ { SES_ET_SCC_ELECTRONICS, elem_parse_scc },
+ { SES_ET_NONVOLATILE_CACHE, elem_parse_cache },
+ { SES_ET_UPS, elem_parse_ups },
+ { SES_ET_DISPLAY, elem_parse_display },
+ { SES_ET_KEY_PAD_ENTRY, elem_parse_keypad },
+ { SES_ET_SCSI_PORT_XCVR, elem_parse_px },
+ { SES_ET_LANGUAGE, elem_parse_lang },
+ { SES_ET_COMMUNICATION_PORT, elem_parse_comm },
+ { SES_ET_VOLTAGE_SENSOR, elem_parse_voltage },
+ { SES_ET_CURRENT_SENSOR, elem_parse_current },
+ { SES_ET_SCSI_TARGET_PORT, elem_parse_itp },
+ { SES_ET_SCSI_INITIATOR_PORT, elem_parse_itp },
+ { SES_ET_SIMPLE_SUBENCLOSURE, elem_parse_sse },
+ { SES_ET_ARRAY_DEVICE, elem_parse_arraydev },
+ { SES_ET_SAS_EXPANDER, elem_parse_expander },
+ { SES_ET_SAS_CONNECTOR, elem_parse_sasconn },
+ { (ses2_element_type_t)-1, NULL }
+};
+
+static int
+elem_parse_sd(ses_plugin_t *spp, ses_node_t *np)
+{
+ ses2_elem_status_impl_t *esip;
+ const struct status_parser *sp;
+ nvlist_t *nvl = ses_node_props(np);
+ size_t len;
+ int nverr;
+ uint64_t type;
+
+ if ((esip = ses_plugin_page_lookup(spp,
+ ses_node_snapshot(np), SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ np, &len)) == NULL)
+ return (0);
+
+ VERIFY(nvlist_lookup_uint64(nvl, SES_PROP_ELEMENT_TYPE,
+ &type) == 0);
+
+ SES_NV_ADD(uint64, nverr, nvl, SES_PROP_STATUS_CODE,
+ esip->sesi_common.sesi_status_code);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_SWAP,
+ esip->sesi_common.sesi_swap);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_DISABLED,
+ esip->sesi_common.sesi_disabled);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_PRDFAIL,
+ esip->sesi_common.sesi_prdfail);
+
+ for (sp = &status_parsers[0]; sp->type != (ses2_element_type_t)-1; sp++)
+ if (sp->type == type && sp->func != NULL)
+ return (sp->func(esip, nvl));
+
+ return (0);
+}
+
+static int
+elem_parse_descr(ses_plugin_t *sp, ses_node_t *np)
+{
+ char *desc;
+ size_t len;
+ nvlist_t *props = ses_node_props(np);
+ int nverr;
+
+ if ((desc = ses_plugin_page_lookup(sp, ses_node_snapshot(np),
+ SES2_DIAGPAGE_ELEMENT_DESC, np, &len)) == NULL)
+ return (0);
+
+ SES_NV_ADD(fixed_string, nverr, props, SES_PROP_DESCRIPTION,
+ desc, len);
+
+ return (0);
+}
+
+static int
+elem_parse_aes_fc(const ses2_aes_descr_fc_eip_impl_t *fp,
+ nvlist_t *nvl, size_t len)
+{
+ int nverr, i;
+ nvlist_t **nva;
+ int nports;
+
+ if (len < offsetof(ses2_aes_descr_fc_eip_impl_t,
+ sadfi_ports))
+ return (0);
+
+ SES_NV_ADD(uint64, nverr, nvl, SES_PROP_BAY_NUMBER,
+ fp->sadfi_bay_number);
+ SES_NV_ADD(uint64, nverr, nvl, SES_FC_PROP_NODE_NAME,
+ SCSI_READ64(&fp->sadfi_node_name));
+
+ nports = MIN(fp->sadfi_n_ports,
+ (len - offsetof(ses2_aes_descr_fc_eip_impl_t,
+ sadfi_ports)) / sizeof (ses2_aes_port_descr_impl_t));
+
+ if (nports == 0)
+ return (0);
+
+ nva = ses_zalloc(nports * sizeof (nvlist_t *));
+ if (nva == NULL)
+ return (-1);
+
+ for (i = 0; i < nports; i++) {
+ if ((nverr = nvlist_alloc(&nva[i], NV_UNIQUE_NAME, 0)) != 0)
+ goto fail;
+ if ((nverr = nvlist_add_uint64(nva[i], SES_FC_PROP_LOOP_POS,
+ fp->sadfi_ports[i].sapdi_port_loop_position)) != 0)
+ goto fail;
+ if ((nverr = nvlist_add_uint64(nva[i], SES_FC_PROP_REQ_HARDADDR,
+ fp->sadfi_ports[i].sapdi_port_requested_hard_address)) != 0)
+ goto fail;
+ nverr = nvlist_add_uint64(nva[i], SES_FC_PROP_N_PORT_ID,
+ SCSI_READ24(fp->sadfi_ports[i].sapdi_n_port_identifier));
+ if (nverr != 0)
+ goto fail;
+ if ((nverr = nvlist_add_uint64(nva[i], SES_FC_PROP_N_PORT_NAME,
+ SCSI_READ64(&fp->sadfi_ports[i].sapdi_n_port_name))) != 0)
+ goto fail;
+ }
+
+ if ((nverr = nvlist_add_nvlist_array(nvl, SES_FC_PROP_PORTS,
+ nva, nports)) != 0)
+ goto fail;
+
+ for (i = 0; i < nports && nva[i] != NULL; i++)
+ nvlist_free(nva[i]);
+ ses_free(nva);
+ return (0);
+
+fail:
+ for (i = 0; i < nports && nva[i] != NULL; i++)
+ nvlist_free(nva[i]);
+ ses_free(nva);
+ return (ses_set_nverrno(nverr, NULL));
+}
+
+static int
+elem_parse_aes_device(const ses2_aes_descr_eip_impl_t *dep, nvlist_t *nvl,
+ size_t len)
+{
+ ses2_aes_descr_fc_eip_impl_t *fp;
+ ses2_aes_descr_sas0_eip_impl_t *s0ep;
+ ses2_aes_descr_sas0_impl_t *s0p;
+ ses2_aes_descr_impl_t *dip;
+ nvlist_t **nva;
+ int nverr, i;
+ size_t nphy;
+
+ if (dep->sadei_eip) {
+ s0ep = (ses2_aes_descr_sas0_eip_impl_t *)
+ dep->sadei_protocol_specific;
+ s0p = (ses2_aes_descr_sas0_impl_t *)
+ dep->sadei_protocol_specific;
+ } else {
+ dip = (ses2_aes_descr_impl_t *)dep;
+ s0ep = NULL;
+ s0p = (ses2_aes_descr_sas0_impl_t *)
+ dip->sadei_protocol_specific;
+ }
+
+ if (dep->sadei_invalid)
+ return (0);
+
+ if (dep->sadei_protocol_identifier == SPC4_PROTO_FIBRE_CHANNEL) {
+ fp = (ses2_aes_descr_fc_eip_impl_t *)
+ dep->sadei_protocol_specific;
+
+ if (!SES_WITHIN_PAGE_STRUCT(fp, dep, len))
+ return (0);
+
+ return (elem_parse_aes_fc(fp, nvl, len -
+ offsetof(ses2_aes_descr_eip_impl_t,
+ sadei_protocol_specific)));
+ } else if (dep->sadei_protocol_identifier != SPC4_PROTO_SAS) {
+ return (0);
+ }
+
+ if (s0p->sadsi_descriptor_type != SES2_AESD_SAS_DEVICE)
+ return (0);
+
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_DEV_PROP_SAS_NOT_ALL_PHYS,
+ s0p->sadsi_not_all_phys);
+ if (s0ep != NULL) {
+ SES_NV_ADD(uint64, nverr, nvl, SES_PROP_BAY_NUMBER,
+ s0ep->sadsi_bay_number);
+ nphy = MIN(s0ep->sadsi_n_phy_descriptors,
+ (len - offsetof(ses2_aes_descr_sas0_eip_impl_t,
+ sadsi_phys)) / sizeof (ses2_aes_phy0_descr_impl_t));
+ } else {
+ nphy = MIN(s0p->sadsi_n_phy_descriptors,
+ (len - offsetof(ses2_aes_descr_sas0_impl_t,
+ sadsi_phys)) / sizeof (ses2_aes_phy0_descr_impl_t));
+ }
+
+ if (nphy == 0)
+ return (0);
+
+ nva = ses_zalloc(nphy * sizeof (nvlist_t *));
+ if (nva == NULL)
+ return (-1);
+
+ for (i = 0; i < nphy; i++) {
+ ses2_aes_phy0_descr_impl_t *pp;
+ pp = s0ep != NULL ? &s0ep->sadsi_phys[i] : &s0p->sadsi_phys[i];
+ if ((nverr = nvlist_alloc(&nva[i], NV_UNIQUE_NAME, 0)) != 0)
+ goto fail;
+ if ((nverr = nvlist_add_uint64(nva[i], SES_SAS_PROP_DEVICE_TYPE,
+ pp->sapdi_device_type)) != 0)
+ goto fail;
+ if ((nverr = nvlist_add_boolean_value(nva[i],
+ SES_SAS_PROP_SMPI_PORT, pp->sapdi_smp_initiator_port)) != 0)
+ goto fail;
+ if ((nverr = nvlist_add_boolean_value(nva[i],
+ SES_SAS_PROP_STPI_PORT, pp->sapdi_stp_initiator_port)) != 0)
+ goto fail;
+ if ((nverr = nvlist_add_boolean_value(nva[i],
+ SES_SAS_PROP_SSPI_PORT, pp->sapdi_ssp_initiator_port)) != 0)
+ goto fail;
+ if ((nverr = nvlist_add_boolean_value(nva[i],
+ SES_SAS_PROP_SATA_DEVICE, pp->sapdi_sata_device)) != 0)
+ goto fail;
+ if ((nverr = nvlist_add_boolean_value(nva[i],
+ SES_SAS_PROP_SMPT_PORT, pp->sapdi_smp_target_port)) != 0)
+ goto fail;
+ if ((nverr = nvlist_add_boolean_value(nva[i],
+ SES_SAS_PROP_STPT_PORT, pp->sapdi_stp_target_port)) != 0)
+ goto fail;
+ if ((nverr = nvlist_add_boolean_value(nva[i],
+ SES_SAS_PROP_SSPT_PORT, pp->sapdi_ssp_target_port)) != 0)
+ goto fail;
+ nverr = nvlist_add_uint64(nva[i], SES_SAS_PROP_ATT_ADDR,
+ SCSI_READ64(&pp->sapdi_attached_sas_address));
+ if (nverr != 0)
+ goto fail;
+ nverr = nvlist_add_uint64(nva[i], SES_SAS_PROP_ADDR,
+ SCSI_READ64(&pp->sapdi_sas_address));
+ if (nverr != 0)
+ goto fail;
+ if ((nverr = nvlist_add_uint64(nva[i], SES_SAS_PROP_PHY_ID,
+ pp->sapdi_phy_identifier)) != 0)
+ goto fail;
+ }
+
+ if ((nverr = nvlist_add_nvlist_array(nvl, SES_SAS_PROP_PHYS,
+ nva, nphy)) != 0)
+ goto fail;
+
+ for (i = 0; i < nphy && nva[i] != NULL; i++)
+ nvlist_free(nva[i]);
+ ses_free(nva);
+ return (0);
+
+fail:
+ for (i = 0; i < nphy && nva[i] != NULL; i++)
+ nvlist_free(nva[i]);
+ ses_free(nva);
+ return (ses_set_nverrno(nverr, NULL));
+}
+
+static int
+elem_parse_aes_expander(const ses2_aes_descr_eip_impl_t *dep, nvlist_t *nvl,
+ size_t len)
+{
+ ses2_aes_descr_exp_impl_t *sep;
+ nvlist_t **nva;
+ int nverr, i;
+ size_t nphy;
+
+ if (dep->sadei_invalid)
+ return (0);
+
+ /*
+ * This should never happen; no current SAS expander can have any
+ * other kind of ports. But maybe someday - one could envision a
+ * SAS expander with iSCSI target ports, for example.
+ */
+ if (dep->sadei_protocol_identifier != SPC4_PROTO_SAS)
+ return (0);
+
+ sep = (ses2_aes_descr_exp_impl_t *)dep->sadei_protocol_specific;
+ if (sep->sadei_descriptor_type != SES2_AESD_SAS_OTHER)
+ return (0);
+
+ SES_NV_ADD(uint64, nverr, nvl, SES_EXP_PROP_SAS_ADDR,
+ SCSI_READ64(&sep->sadei_sas_address));
+
+ nphy = MIN(sep->sadei_n_exp_phy_descriptors,
+ (len - offsetof(ses2_aes_descr_exp_impl_t,
+ sadei_phys)) / sizeof (ses2_aes_exp_phy_descr_impl_t));
+
+ if (nphy == 0)
+ return (0);
+
+ nva = ses_zalloc(nphy * sizeof (nvlist_t *));
+ if (nva == NULL)
+ return (-1);
+
+ for (i = 0; i < nphy; i++) {
+ if ((nverr = nvlist_alloc(&nva[i], NV_UNIQUE_NAME, 0)) != 0)
+ goto fail;
+ if ((nverr = nvlist_add_uint64(nva[i], SES_PROP_CE_IDX,
+ sep->sadei_phys[i].saepdi_connector_element_index)) != 0)
+ goto fail;
+ if ((nverr = nvlist_add_uint64(nva[i], SES_PROP_OE_IDX,
+ sep->sadei_phys[i].saepdi_other_element_index)) != 0)
+ goto fail;
+ }
+
+ if ((nverr = nvlist_add_nvlist_array(nvl, SES_SAS_PROP_PHYS,
+ nva, nphy)) != 0)
+ goto fail;
+
+ for (i = 0; i < nphy && nva[i] != NULL; i++)
+ nvlist_free(nva[i]);
+ ses_free(nva);
+ return (0);
+
+fail:
+ for (i = 0; i < nphy && nva[i] != NULL; i++)
+ nvlist_free(nva[i]);
+ ses_free(nva);
+ return (ses_set_nverrno(nverr, NULL));
+}
+
+static int
+elem_parse_aes_misc(const ses2_aes_descr_eip_impl_t *dep, nvlist_t *nvl,
+ size_t len)
+{
+ ses2_aes_descr_fc_eip_impl_t *fp;
+ ses2_aes_descr_sas1_impl_t *s1p;
+ nvlist_t **nva;
+ int nverr, i;
+ size_t nphy;
+
+ if (dep->sadei_invalid)
+ return (0);
+
+ if (dep->sadei_protocol_identifier == SPC4_PROTO_FIBRE_CHANNEL) {
+ fp = (ses2_aes_descr_fc_eip_impl_t *)
+ dep->sadei_protocol_specific;
+
+ if (!SES_WITHIN_PAGE_STRUCT(fp, dep, len))
+ return (0);
+
+ return (elem_parse_aes_fc(fp, nvl, len -
+ offsetof(ses2_aes_descr_eip_impl_t,
+ sadei_protocol_specific)));
+ } else if (dep->sadei_protocol_identifier != SPC4_PROTO_SAS) {
+ return (0);
+ }
+
+ s1p = (ses2_aes_descr_sas1_impl_t *)dep->sadei_protocol_specific;
+ if (s1p->sadsi_descriptor_type == SES2_AESD_SAS_DEVICE)
+ return (0);
+
+ nphy = MIN(s1p->sadsi_n_phy_descriptors,
+ (len - offsetof(ses2_aes_descr_sas1_impl_t,
+ sadsi_phys)) / sizeof (ses2_aes_phy1_descr_impl_t));
+
+ nva = ses_zalloc(nphy * sizeof (nvlist_t *));
+ if (nva == NULL)
+ return (-1);
+
+ for (i = 0; i < nphy; i++) {
+ if ((nverr = nvlist_alloc(&nva[i], NV_UNIQUE_NAME, 0)) != 0)
+ goto fail;
+ if ((nverr = nvlist_add_uint64(nva[i], SES_PROP_CE_IDX,
+ s1p->sadsi_phys[i].sapdi_connector_element_index)) != 0)
+ goto fail;
+ if ((nverr = nvlist_add_uint64(nva[i], SES_PROP_OE_IDX,
+ s1p->sadsi_phys[i].sapdi_other_element_index)) != 0)
+ goto fail;
+ if ((nverr = nvlist_add_uint64(nva[i], SES_SAS_PROP_ADDR,
+ SCSI_READ64(&s1p->sadsi_phys[i].sapdi_sas_address))) != 0)
+ goto fail;
+ }
+
+ if ((nverr = nvlist_add_nvlist_array(nvl, SES_SAS_PROP_PHYS,
+ nva, nphy)) != 0)
+ goto fail;
+
+ for (i = 0; i < nphy && nva[i] != NULL; i++)
+ nvlist_free(nva[i]);
+
+ ses_free(nva);
+ return (0);
+
+fail:
+ for (i = 0; i < nphy && nva[i] != NULL; i++)
+ nvlist_free(nva[i]);
+ ses_free(nva);
+ return (nverr);
+}
+
+static const struct aes_parser {
+ ses2_element_type_t type;
+ int (*func)(const ses2_aes_descr_eip_impl_t *, nvlist_t *, size_t);
+} aes_parsers[] = {
+ { SES_ET_DEVICE, elem_parse_aes_device },
+ { SES_ET_SCSI_TARGET_PORT, elem_parse_aes_misc },
+ { SES_ET_SCSI_INITIATOR_PORT, elem_parse_aes_misc },
+ { SES_ET_ESC_ELECTRONICS, elem_parse_aes_misc },
+ { SES_ET_ARRAY_DEVICE, elem_parse_aes_device },
+ { SES_ET_SAS_EXPANDER, elem_parse_aes_expander },
+ { (ses2_element_type_t)-1, NULL }
+};
+
+static int
+elem_parse_aes(ses_plugin_t *sp, ses_node_t *np)
+{
+ ses2_aes_descr_eip_impl_t *dep;
+ nvlist_t *props = ses_node_props(np);
+ const struct aes_parser *app;
+ uint64_t type;
+ size_t len;
+
+ if (ses_node_type(np) == SES_NODE_AGGREGATE)
+ return (0);
+
+ VERIFY(nvlist_lookup_uint64(props, SES_PROP_ELEMENT_TYPE,
+ &type) == 0);
+
+ for (app = &aes_parsers[0]; app->func != NULL; app++)
+ if (app->type == type)
+ break;
+ if (app->func == NULL)
+ return (0);
+
+ if ((dep = ses_plugin_page_lookup(sp, ses_node_snapshot(np),
+ SES2_DIAGPAGE_ADDL_ELEM_STATUS, np, &len)) == NULL)
+ return (0);
+
+ return (app->func(dep, props, len));
+}
+
+static int
+elem_parse_threshold(ses_plugin_t *sp, ses_node_t *np)
+{
+ ses_snap_t *snap = ses_node_snapshot(np);
+ ses2_threshold_impl_t *tp;
+ nvlist_t *nvl = ses_node_props(np);
+ int nverr;
+ uint64_t type;
+ size_t len;
+
+ VERIFY(nvlist_lookup_uint64(nvl, SES_PROP_ELEMENT_TYPE,
+ &type) == 0);
+
+ switch (type) {
+ case SES_ET_TEMPERATURE_SENSOR:
+ case SES_ET_UPS:
+ case SES_ET_VOLTAGE_SENSOR:
+ case SES_ET_CURRENT_SENSOR:
+ break;
+ default:
+ return (0);
+ }
+
+ if ((tp = ses_plugin_page_lookup(sp, snap,
+ SES2_DIAGPAGE_THRESHOLD_IO, np, &len)) == NULL)
+ return (0);
+
+ SES_NV_ADD(uint64, nverr, nvl, SES_PROP_THRESH_CRIT_HI,
+ tp->sti_high_crit);
+ SES_NV_ADD(uint64, nverr, nvl, SES_PROP_THRESH_WARN_HI,
+ tp->sti_high_warn);
+ SES_NV_ADD(uint64, nverr, nvl, SES_PROP_THRESH_CRIT_LO,
+ tp->sti_low_crit);
+ SES_NV_ADD(uint64, nverr, nvl, SES_PROP_THRESH_WARN_LO,
+ tp->sti_low_warn);
+
+ return (0);
+}
+
+int
+ses2_fill_element_node(ses_plugin_t *sp, ses_node_t *np)
+{
+ int err;
+
+ if ((err = elem_parse_sd(sp, np)) != 0)
+ return (err);
+
+ if ((err = elem_parse_descr(sp, np)) != 0)
+ return (err);
+
+ if ((err = elem_parse_aes(sp, np)) != 0)
+ return (err);
+
+ if ((err = elem_parse_threshold(sp, np)) != 0)
+ return (err);
+
+ return (0);
+}
diff --git a/usr/src/lib/scsi/plugins/ses/ses2/common/ses2_element_ctl.c b/usr/src/lib/scsi/plugins/ses/ses2/common/ses2_element_ctl.c
new file mode 100644
index 0000000000..6868f0ea7f
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/ses2/common/ses2_element_ctl.c
@@ -0,0 +1,1856 @@
+/*
+ * 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"
+
+#include <sys/types.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <libnvpair.h>
+
+#include <scsi/libses.h>
+#include "ses2_impl.h"
+
+static int
+elem_setprop_device(ses_plugin_t *sp, ses_node_t *np, ses2_diag_page_t page,
+ nvpair_t *nvp)
+{
+ ses2_device_ctl_impl_t *dip;
+ const char *name;
+ boolean_t v;
+
+ if ((dip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ page, 0, np, B_FALSE)) == NULL)
+ return (-1);
+
+ name = nvpair_name(nvp);
+ (void) nvpair_value_boolean_value(nvp, &v);
+
+ if (strcmp(name, SES_PROP_IDENT) == 0)
+ dip->sdci_rqst_ident = v;
+ else if (strcmp(name, SES_PROP_RMV) == 0)
+ dip->sdci_rqst_remove = v;
+ else if (strcmp(name, SES_DEV_PROP_READY_TO_INSERT) == 0)
+ dip->sdci_rqst_insert = v;
+ else if (strcmp(name, SES_DEV_PROP_REQ_MISSING) == 0)
+ dip->sdci_rqst_missing = v;
+ else if (strcmp(name, SES_DEV_PROP_DO_NOT_REMOVE) == 0)
+ dip->sdci_do_not_remove = v;
+ else if (strcmp(name, SES_DEV_PROP_REQ_ACTIVE) == 0)
+ dip->sdci_rqst_active = v;
+ else if (strcmp(name, SES_DEV_PROP_BYP_B) == 0)
+ dip->sdci_enable_byp_b = v;
+ else if (strcmp(name, SES_DEV_PROP_BYP_A) == 0)
+ dip->sdci_enable_byp_a = v;
+ else if (strcmp(name, SES_PROP_OFF) == 0)
+ dip->sdci_device_off = v;
+ else if (strcmp(name, SES_DEV_PROP_FAULT_RQSTD) == 0)
+ dip->sdci_rqst_fault = v;
+ else
+ ses_panic("Bad property %s", name);
+
+ return (0);
+}
+
+static int
+elem_setprop_psu(ses_plugin_t *sp, ses_node_t *np, ses2_diag_page_t page,
+ nvpair_t *nvp)
+{
+ ses2_psu_ctl_impl_t *pip;
+ const char *name;
+ boolean_t v;
+
+ if ((pip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ page, 0, np, B_FALSE)) == NULL)
+ return (-1);
+
+ name = nvpair_name(nvp);
+ (void) nvpair_value_boolean_value(nvp, &v);
+
+ if (strcmp(name, SES_PROP_IDENT) == 0)
+ pip->spci_rqst_ident = v;
+ else if (strcmp(name, SES_PROP_REQUESTED_ON) == 0)
+ pip->spci_rqst_on = v;
+ else if (strcmp(name, SES_PROP_FAIL) == 0)
+ pip->spci_rqst_fail = v;
+ else
+ ses_panic("Bad property %s", name);
+
+ return (0);
+}
+
+static int
+elem_setprop_cooling(ses_plugin_t *sp, ses_node_t *np, ses2_diag_page_t page,
+ nvpair_t *nvp)
+{
+ ses2_cooling_ctl_impl_t *cip;
+ const char *name;
+ boolean_t v1;
+ uint64_t v64;
+
+ if ((cip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ page, 0, np, B_FALSE)) == NULL)
+ return (-1);
+
+ name = nvpair_name(nvp);
+
+ if (strcmp(name, SES_COOLING_PROP_SPEED_CODE) == 0) {
+ (void) nvpair_value_uint64(nvp, &v64);
+ cip->scci_requested_speed_code = v64;
+ return (0);
+ }
+
+ (void) nvpair_value_boolean_value(nvp, &v1);
+
+ if (strcmp(name, SES_PROP_IDENT) == 0)
+ cip->scci_rqst_ident = v1;
+ else if (strcmp(name, SES_PROP_REQUESTED_ON) == 0)
+ cip->scci_rqst_on = v1;
+ else if (strcmp(name, SES_PROP_FAIL) == 0)
+ cip->scci_rqst_fail = v1;
+ else
+ ses_panic("Bad property %s", name);
+
+ return (0);
+}
+
+static int
+elem_setprop_temp(ses_plugin_t *sp, ses_node_t *np, ses2_diag_page_t page,
+ nvpair_t *nvp)
+{
+ ses2_temp_ctl_impl_t *tip;
+ const char *name;
+ boolean_t v;
+
+ if ((tip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ page, 0, np, B_FALSE)) == NULL)
+ return (-1);
+
+ name = nvpair_name(nvp);
+ (void) nvpair_value_boolean_value(nvp, &v);
+
+ if (strcmp(name, SES_PROP_FAIL) == 0)
+ tip->stci_rqst_fail = v;
+ else if (strcmp(name, SES_PROP_IDENT) == 0)
+ tip->stci_rqst_ident = v;
+ else
+ ses_panic("Bad property %s", name);
+
+ return (0);
+}
+
+static int
+elem_setprop_lock(ses_plugin_t *sp, ses_node_t *np, ses2_diag_page_t page,
+ nvpair_t *nvp)
+{
+ ses2_lock_ctl_impl_t *lip;
+ const char *name;
+ boolean_t v;
+
+ if ((lip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ page, 0, np, B_FALSE)) == NULL)
+ return (-1);
+
+ name = nvpair_name(nvp);
+ (void) nvpair_value_boolean_value(nvp, &v);
+
+ if (strcmp(name, SES_PROP_FAIL) == 0)
+ lip->slci_rqst_fail = v;
+ else if (strcmp(name, SES_PROP_IDENT) == 0)
+ lip->slci_rqst_ident = v;
+ else if (strcmp(name, SES_LOCK_PROP_UNLOCKED) == 0)
+ lip->slci_unlock = v;
+ else
+ ses_panic("Bad property %s", name);
+
+ return (0);
+}
+
+static int
+elem_setprop_alarm(ses_plugin_t *sp, ses_node_t *np, ses2_diag_page_t page,
+ nvpair_t *nvp)
+{
+ ses2_alarm_ctl_impl_t *aip;
+ const char *name;
+ boolean_t v;
+
+ if ((aip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ page, 0, np, B_FALSE)) == NULL)
+ return (-1);
+
+ name = nvpair_name(nvp);
+ (void) nvpair_value_boolean_value(nvp, &v);
+
+ if (strcmp(name, SES_PROP_FAIL) == 0)
+ aip->saci_rqst_fail = v;
+ else if (strcmp(name, SES_PROP_IDENT) == 0)
+ aip->saci_rqst_ident = v;
+ else if (strcmp(name, SES_ALARM_PROP_UNRECOV) == 0)
+ aip->saci_unrecov = v;
+ else if (strcmp(name, SES_ALARM_PROP_CRIT) == 0)
+ aip->saci_crit = v;
+ else if (strcmp(name, SES_ALARM_PROP_NONCRIT) == 0)
+ aip->saci_noncrit = v;
+ else if (strcmp(name, SES_ALARM_PROP_INFO) == 0)
+ aip->saci_info = v;
+ else if (strcmp(name, SES_ALARM_PROP_REMIND) == 0)
+ aip->saci_set_remind = v;
+ else if (strcmp(name, SES_ALARM_PROP_MUTED) == 0)
+ aip->saci_set_mute = v;
+ else
+ ses_panic("Bad property %s", name);
+
+ return (0);
+}
+
+static int
+elem_setprop_esc(ses_plugin_t *sp, ses_node_t *np, ses2_diag_page_t page,
+ nvpair_t *nvp)
+{
+ ses2_controller_ctl_impl_t *cip;
+ const char *name;
+ boolean_t v;
+
+ if ((cip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ page, 0, np, B_FALSE)) == NULL)
+ return (-1);
+
+ name = nvpair_name(nvp);
+ (void) nvpair_value_boolean_value(nvp, &v);
+
+ if (strcmp(name, SES_PROP_FAIL) == 0)
+ cip->scci_rqst_fail = v;
+ else if (strcmp(name, SES_PROP_IDENT) == 0)
+ cip->scci_rqst_ident = v;
+ else if (strcmp(name, SES_ESC_PROP_SELECT) == 0)
+ cip->scci_select_element = v;
+ else
+ ses_panic("Bad property %s", name);
+
+ return (0);
+}
+
+static int
+elem_setprop_scc(ses_plugin_t *sp, ses_node_t *np, ses2_diag_page_t page,
+ nvpair_t *nvp)
+{
+ ses2_scc_ctl_impl_t *sip;
+ const char *name;
+ boolean_t v;
+
+ if ((sip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ page, 0, np, B_FALSE)) == NULL)
+ return (-1);
+
+ name = nvpair_name(nvp);
+ (void) nvpair_value_boolean_value(nvp, &v);
+
+ if (strcmp(name, SES_PROP_FAIL) == 0)
+ sip->ssci_rqst_fail = v;
+ else if (strcmp(name, SES_PROP_IDENT) == 0)
+ sip->ssci_rqst_ident = v;
+ else
+ ses_panic("Bad property %s", name);
+
+ return (0);
+}
+
+static int
+elem_setprop_ups(ses_plugin_t *sp, ses_node_t *np, ses2_diag_page_t page,
+ nvpair_t *nvp)
+{
+ ses2_ups_ctl_impl_t *uip;
+ const char *name;
+ boolean_t v;
+
+ if ((uip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ page, 0, np, B_FALSE)) == NULL)
+ return (-1);
+
+ name = nvpair_name(nvp);
+ (void) nvpair_value_boolean_value(nvp, &v);
+
+ if (strcmp(name, SES_PROP_FAIL) == 0)
+ uip->suci_rqst_fail = v;
+ else if (strcmp(name, SES_PROP_IDENT) == 0)
+ uip->suci_rqst_ident = v;
+ else
+ ses_panic("Bad property %s", name);
+
+ return (0);
+}
+
+static int
+elem_setprop_cache(ses_plugin_t *sp, ses_node_t *np, ses2_diag_page_t page,
+ nvpair_t *nvp)
+{
+ ses2_nvcache_ctl_impl_t *cip;
+ const char *name;
+ boolean_t v;
+
+ if ((cip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ page, 0, np, B_FALSE)) == NULL)
+ return (-1);
+
+ name = nvpair_name(nvp);
+ (void) nvpair_value_boolean_value(nvp, &v);
+
+ if (strcmp(name, SES_PROP_FAIL) == 0)
+ cip->snci_rqst_fail = v;
+ else if (strcmp(name, SES_PROP_IDENT) == 0)
+ cip->snci_rqst_ident = v;
+ else
+ ses_panic("Bad property %s", name);
+
+ return (0);
+}
+
+static int
+elem_setprop_keypad(ses_plugin_t *sp, ses_node_t *np, ses2_diag_page_t page,
+ nvpair_t *nvp)
+{
+ ses2_keypad_ctl_impl_t *kip;
+ const char *name;
+ boolean_t v;
+
+ if ((kip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ page, 0, np, B_FALSE)) == NULL)
+ return (-1);
+
+ name = nvpair_name(nvp);
+ (void) nvpair_value_boolean_value(nvp, &v);
+
+ if (strcmp(name, SES_PROP_FAIL) == 0)
+ kip->skci_rqst_fail = v;
+ else if (strcmp(name, SES_PROP_IDENT) == 0)
+ kip->skci_rqst_ident = v;
+ else
+ ses_panic("Bad property %s", name);
+
+ return (0);
+}
+
+static int
+elem_setprop_display(ses_plugin_t *sp, ses_node_t *np, ses2_diag_page_t page,
+ nvpair_t *nvp)
+{
+ ses2_display_ctl_impl_t *dip;
+ const char *name;
+ boolean_t v1;
+ uint16_t v16;
+ uint64_t v64;
+
+ if ((dip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ page, 0, np, B_FALSE)) == NULL)
+ return (-1);
+
+
+ name = nvpair_name(nvp);
+
+ if (strcmp(name, SES_DPY_PROP_MODE) == 0) {
+ (void) nvpair_value_uint64(nvp, &v64);
+ dip->sdci_display_mode = v64;
+ return (0);
+ } else if (strcmp(name, SES_DPY_PROP_CHAR) == 0) {
+ (void) nvpair_value_uint16(nvp, &v16);
+ SCSI_WRITE16(&dip->sdci_display_character, v16);
+ return (0);
+ }
+
+ (void) nvpair_value_boolean_value(nvp, &v1);
+
+ if (strcmp(name, SES_PROP_FAIL) == 0)
+ dip->sdci_rqst_fail = v1;
+ else if (strcmp(name, SES_PROP_IDENT) == 0)
+ dip->sdci_rqst_ident = v1;
+ else
+ ses_panic("Bad property %s", name);
+ return (0);
+}
+
+static int
+elem_setprop_px(ses_plugin_t *sp, ses_node_t *np, ses2_diag_page_t page,
+ nvpair_t *nvp)
+{
+ ses2_port_ctl_impl_t *pip;
+ const char *name;
+ boolean_t v;
+
+ if ((pip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ page, 0, np, B_FALSE)) == NULL)
+ return (-1);
+
+ name = nvpair_name(nvp);
+
+ (void) nvpair_value_boolean_value(nvp, &v);
+
+ if (strcmp(name, SES_PROP_FAIL) == 0)
+ pip->spci_rqst_fail = v;
+ else if (strcmp(name, SES_PROP_IDENT) == 0)
+ pip->spci_rqst_ident = v;
+ else if (strcmp(name, SES_PROP_DISABLED) == 0)
+ pip->spci_disable = v;
+ else
+ ses_panic("Bad property %s", name);
+
+ return (0);
+}
+
+static int
+elem_setprop_lang(ses_plugin_t *sp, ses_node_t *np, ses2_diag_page_t page,
+ nvpair_t *nvp)
+{
+ ses2_lang_ctl_impl_t *lip;
+ const char *name;
+ boolean_t v1;
+ uint64_t v64;
+
+ if ((lip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ page, 0, np, B_FALSE)) == NULL)
+ return (-1);
+
+ name = nvpair_name(nvp);
+
+ if (strcmp(name, SES_LANG_PROP_LANGCODE) == 0) {
+ (void) nvpair_value_uint64(nvp, &v64);
+ SCSI_WRITE16(&lip->slci_language_code, v64);
+ return (0);
+ }
+
+ (void) nvpair_value_boolean_value(nvp, &v1);
+
+ if (strcmp(name, SES_PROP_IDENT) == 0)
+ lip->slci_rqst_ident = v1;
+ else
+ ses_panic("Bad property %s", name);
+
+ return (0);
+}
+
+static int
+elem_setprop_comm(ses_plugin_t *sp, ses_node_t *np, ses2_diag_page_t page,
+ nvpair_t *nvp)
+{
+ ses2_comm_ctl_impl_t *cip;
+ const char *name;
+ boolean_t v;
+
+ if ((cip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ page, 0, np, B_FALSE)) == NULL)
+ return (-1);
+
+ name = nvpair_name(nvp);
+ (void) nvpair_value_boolean_value(nvp, &v);
+
+ if (strcmp(name, SES_PROP_FAIL) == 0)
+ cip->scci_rqst_fail = v;
+ else if (strcmp(name, SES_PROP_IDENT) == 0)
+ cip->scci_rqst_ident = v;
+ else if (strcmp(name, SES_PROP_DISABLED) == 0)
+ cip->scci_disable = v;
+ else
+ ses_panic("Bad property %s", name);
+
+ return (0);
+}
+
+static int
+elem_setprop_voltage(ses_plugin_t *sp, ses_node_t *np, ses2_diag_page_t page,
+ nvpair_t *nvp)
+{
+ ses2_voltage_ctl_impl_t *vip;
+ const char *name;
+ boolean_t v;
+
+ if ((vip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ page, 0, np, B_FALSE)) == NULL)
+ return (-1);
+
+ name = nvpair_name(nvp);
+ (void) nvpair_value_boolean_value(nvp, &v);
+
+ if (strcmp(name, SES_PROP_FAIL) == 0)
+ vip->svci_rqst_fail = v;
+ else if (strcmp(name, SES_PROP_IDENT) == 0)
+ vip->svci_rqst_ident = v;
+ else
+ ses_panic("Bad property %s", name);
+
+ return (0);
+}
+
+static int
+elem_setprop_current(ses_plugin_t *sp, ses_node_t *np, ses2_diag_page_t page,
+ nvpair_t *nvp)
+{
+ ses2_current_ctl_impl_t *cip;
+ const char *name;
+ boolean_t v;
+
+ if ((cip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ page, 0, np, B_FALSE)) == NULL)
+ return (-1);
+
+ name = nvpair_name(nvp);
+ (void) nvpair_value_boolean_value(nvp, &v);
+
+ if (strcmp(name, SES_PROP_FAIL) == 0)
+ cip->scci_rqst_fail = v;
+ else if (strcmp(name, SES_PROP_IDENT) == 0)
+ cip->scci_rqst_ident = v;
+ else
+ ses_panic("Bad property %s", name);
+
+ return (0);
+}
+
+static int
+elem_setprop_itp(ses_plugin_t *sp, ses_node_t *np, ses2_diag_page_t page,
+ nvpair_t *nvp)
+{
+ ses2_itp_ctl_impl_t *iip;
+ const char *name;
+ boolean_t v;
+
+ if ((iip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ page, 0, np, B_FALSE)) == NULL)
+ return (-1);
+
+ name = nvpair_name(nvp);
+ (void) nvpair_value_boolean_value(nvp, &v);
+
+ if (strcmp(name, SES_PROP_FAIL) == 0)
+ iip->sici_rqst_fail = v;
+ else if (strcmp(name, SES_PROP_IDENT) == 0)
+ iip->sici_rqst_ident = v;
+ else if (strcmp(name, SES_ITP_PROP_ENABLED) == 0)
+ iip->sici_enable = v;
+ else
+ ses_panic("Bad property %s", name);
+
+ return (0);
+}
+
+static int
+elem_setprop_sse(ses_plugin_t *sp, ses_node_t *np, ses2_diag_page_t page,
+ nvpair_t *nvp)
+{
+ ses2_ss_ctl_impl_t *sip;
+ const char *name;
+ boolean_t v;
+
+ if ((sip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ page, 0, np, B_FALSE)) == NULL)
+ return (-1);
+
+ name = nvpair_name(nvp);
+ (void) nvpair_value_boolean_value(nvp, &v);
+
+ if (strcmp(name, SES_PROP_FAIL) == 0)
+ sip->ssci_rqst_fail = v;
+ else if (strcmp(name, SES_PROP_IDENT) == 0)
+ sip->ssci_rqst_ident = v;
+ else
+ ses_panic("Bad property %s", name);
+
+ return (0);
+}
+
+static int
+elem_setprop_arraydev(ses_plugin_t *sp, ses_node_t *np, ses2_diag_page_t page,
+ nvpair_t *nvp)
+{
+ ses2_array_device_ctl_impl_t *aip;
+ const char *name;
+ boolean_t v;
+
+ if ((aip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ page, 0, np, B_FALSE)) == NULL)
+ return (-1);
+
+ name = nvpair_name(nvp);
+ (void) nvpair_value_boolean_value(nvp, &v);
+
+ if (strcmp(name, SES_AD_PROP_RR_ABORT) == 0)
+ aip->sadci_rqst_rr_abort = v;
+ else if (strcmp(name, SES_AD_PROP_REBUILD) == 0)
+ aip->sadci_rqst_rebuild = v;
+ else if (strcmp(name, SES_AD_PROP_IN_FAILED_ARRAY) == 0)
+ aip->sadci_rqst_in_failed_array = v;
+ else if (strcmp(name, SES_AD_PROP_IN_CRIT_ARRAY) == 0)
+ aip->sadci_rqst_in_crit_array = v;
+ else if (strcmp(name, SES_AD_PROP_CONS_CHK) == 0)
+ aip->sadci_rqst_cons_check = v;
+ else if (strcmp(name, SES_AD_PROP_HOT_SPARE) == 0)
+ aip->sadci_rqst_hot_spare = v;
+ else if (strcmp(name, SES_AD_PROP_RSVD_DEVICE) == 0)
+ aip->sadci_rqst_rsvd_device = v;
+ else if (strcmp(name, SES_PROP_IDENT) == 0)
+ aip->sadci_rqst_ident = v;
+ else if (strcmp(name, SES_PROP_RMV) == 0)
+ aip->sadci_rqst_remove = v;
+ else if (strcmp(name, SES_DEV_PROP_READY_TO_INSERT) == 0)
+ aip->sadci_rqst_insert = v;
+ else if (strcmp(name, SES_DEV_PROP_REQ_MISSING) == 0)
+ aip->sadci_rqst_missing = v;
+ else if (strcmp(name, SES_DEV_PROP_DO_NOT_REMOVE) == 0)
+ aip->sadci_do_not_remove = v;
+ else if (strcmp(name, SES_DEV_PROP_REQ_ACTIVE) == 0)
+ aip->sadci_rqst_active = v;
+ else if (strcmp(name, SES_DEV_PROP_BYP_B) == 0)
+ aip->sadci_enable_byp_b = v;
+ else if (strcmp(name, SES_DEV_PROP_BYP_A) == 0)
+ aip->sadci_enable_byp_a = v;
+ else if (strcmp(name, SES_PROP_OFF) == 0)
+ aip->sadci_device_off = v;
+ else if (strcmp(name, SES_DEV_PROP_FAULT_RQSTD) == 0)
+ aip->sadci_rqst_fault = v;
+ else
+ ses_panic("Bad property %s", name);
+
+ return (0);
+}
+
+static int
+elem_setprop_expander(ses_plugin_t *sp, ses_node_t *np, ses2_diag_page_t page,
+ nvpair_t *nvp)
+{
+ ses2_expander_ctl_impl_t *eip;
+ const char *name;
+ boolean_t v;
+
+ if ((eip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ page, 0, np, B_FALSE)) == NULL)
+ return (-1);
+
+ name = nvpair_name(nvp);
+ (void) nvpair_value_boolean_value(nvp, &v);
+
+ if (strcmp(name, SES_PROP_FAIL) == 0)
+ eip->seci_rqst_fail = v;
+ else if (strcmp(name, SES_PROP_IDENT) == 0)
+ eip->seci_rqst_ident = v;
+ else
+ ses_panic("Bad property %s", name);
+
+ return (0);
+}
+
+static int
+elem_setprop_sasconn(ses_plugin_t *sp, ses_node_t *np, ses2_diag_page_t page,
+ nvpair_t *nvp)
+{
+ ses2_sasconn_ctl_impl_t *sip;
+ const char *name;
+ boolean_t v;
+
+ if ((sip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ page, 0, np, B_FALSE)) == NULL)
+ return (-1);
+
+ name = nvpair_name(nvp);
+ (void) nvpair_value_boolean_value(nvp, &v);
+
+ if (strcmp(name, SES_PROP_IDENT) == 0)
+ sip->ssci_rqst_ident = v;
+ else if (strcmp(name, SES_PROP_FAIL) == 0)
+ sip->ssci_rqst_fail = v;
+ else
+ ses_panic("Bad property %s", name);
+
+ return (0);
+}
+
+static int
+elem_common_setprop_threshold(ses_plugin_t *sp, ses_node_t *np,
+ ses2_diag_page_t page, nvpair_t *nvp)
+{
+ ses2_threshold_impl_t *tip;
+ const char *name;
+ uint64_t v;
+
+ ASSERT(page == SES2_DIAGPAGE_THRESHOLD_IO);
+
+ if ((tip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ page, 0, np, B_FALSE)) == NULL)
+ return (-1);
+
+ name = nvpair_name(nvp);
+ (void) nvpair_value_uint64(nvp, &v);
+
+ if (strcmp(name, SES_PROP_THRESH_CRIT_HI) == 0)
+ tip->sti_high_crit = v;
+ else if (strcmp(name, SES_PROP_THRESH_CRIT_LO) == 0)
+ tip->sti_low_crit = v;
+ else if (strcmp(name, SES_PROP_THRESH_WARN_HI) == 0)
+ tip->sti_high_warn = v;
+ else if (strcmp(name, SES_PROP_THRESH_WARN_LO) == 0)
+ tip->sti_low_warn = v;
+ else
+ ses_panic("Bad property %s", name);
+
+ return (0);
+}
+
+#define SES_THRESHOLD_CTL_PROPS \
+{ \
+ .scp_name = SES_PROP_THRESH_CRIT_HI, \
+ .scp_type = DATA_TYPE_UINT64, \
+ .scp_num = SES2_DIAGPAGE_THRESHOLD_IO, \
+ .scp_setprop = elem_common_setprop_threshold \
+}, \
+{ \
+ .scp_name = SES_PROP_THRESH_WARN_HI, \
+ .scp_type = DATA_TYPE_UINT64, \
+ .scp_num = SES2_DIAGPAGE_THRESHOLD_IO, \
+ .scp_setprop = elem_common_setprop_threshold \
+}, \
+{ \
+ .scp_name = SES_PROP_THRESH_CRIT_LO, \
+ .scp_type = DATA_TYPE_UINT64, \
+ .scp_num = SES2_DIAGPAGE_THRESHOLD_IO, \
+ .scp_setprop = elem_common_setprop_threshold \
+}, \
+{ \
+ .scp_name = SES_PROP_THRESH_WARN_LO, \
+ .scp_type = DATA_TYPE_UINT64, \
+ .scp_num = SES2_DIAGPAGE_THRESHOLD_IO, \
+ .scp_setprop = elem_common_setprop_threshold \
+}
+
+static const ses2_ctl_prop_t device_props[] = {
+ SES_COMMON_CTL_PROPS,
+{
+ .scp_name = SES_PROP_IDENT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_device,
+},
+{
+ .scp_name = SES_PROP_RMV,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_device,
+},
+{
+ .scp_name = SES_DEV_PROP_READY_TO_INSERT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_device,
+},
+{
+ .scp_name = SES_DEV_PROP_REQ_MISSING,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_device,
+},
+{
+ .scp_name = SES_DEV_PROP_DO_NOT_REMOVE,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_device,
+},
+{
+ .scp_name = SES_DEV_PROP_REQ_ACTIVE,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_device,
+},
+{
+ .scp_name = SES_DEV_PROP_BYP_B,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_device,
+},
+{
+ .scp_name = SES_DEV_PROP_BYP_A,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_device,
+},
+{
+ .scp_name = SES_PROP_OFF,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_device,
+},
+{
+ .scp_name = SES_DEV_PROP_FAULT_RQSTD,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_device,
+},
+{
+ NULL
+}
+};
+
+static const ses2_ctl_prop_t psu_props[] = {
+ SES_COMMON_CTL_PROPS,
+{
+ .scp_name = SES_PROP_IDENT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_psu
+},
+{
+ .scp_name = SES_PROP_REQUESTED_ON,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_psu
+},
+{
+ .scp_name = SES_PROP_FAIL,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_psu
+},
+{
+ NULL
+}
+};
+
+static const ses2_ctl_prop_t cooling_props[] = {
+ SES_COMMON_CTL_PROPS,
+{
+ .scp_name = SES_PROP_IDENT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_cooling
+},
+{
+ .scp_name = SES_COOLING_PROP_SPEED_CODE,
+ .scp_type = DATA_TYPE_UINT64,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_cooling
+},
+{
+ .scp_name = SES_PROP_REQUESTED_ON,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_cooling
+},
+{
+ .scp_name = SES_PROP_FAIL,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_cooling
+},
+{
+ NULL
+}
+};
+
+static const ses2_ctl_prop_t temp_props[] = {
+ SES_COMMON_CTL_PROPS,
+ SES_THRESHOLD_CTL_PROPS,
+{
+ .scp_name = SES_PROP_FAIL,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_temp
+},
+{
+ .scp_name = SES_PROP_IDENT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_temp
+},
+{
+ NULL
+}
+};
+
+static const ses2_ctl_prop_t lock_props[] = {
+ SES_COMMON_CTL_PROPS,
+{
+ .scp_name = SES_PROP_FAIL,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_lock
+},
+{
+ .scp_name = SES_PROP_IDENT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_lock
+},
+{
+ .scp_name = SES_LOCK_PROP_UNLOCKED,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_lock
+},
+{
+ NULL
+}
+};
+
+static const ses2_ctl_prop_t alarm_props[] = {
+ SES_COMMON_CTL_PROPS,
+{
+ .scp_name = SES_PROP_FAIL,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_alarm
+},
+{
+ .scp_name = SES_PROP_IDENT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_alarm
+},
+{
+ .scp_name = SES_ALARM_PROP_UNRECOV,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_alarm
+},
+{
+ .scp_name = SES_ALARM_PROP_CRIT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_alarm
+},
+{
+ .scp_name = SES_ALARM_PROP_NONCRIT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_alarm
+},
+{
+ .scp_name = SES_ALARM_PROP_INFO,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_alarm
+},
+{
+ .scp_name = SES_ALARM_PROP_REMIND,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_alarm
+},
+{
+ .scp_name = SES_ALARM_PROP_MUTED,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_alarm
+},
+{
+ NULL
+}
+};
+
+static const ses2_ctl_prop_t esc_props[] = {
+ SES_COMMON_CTL_PROPS,
+{
+ .scp_name = SES_PROP_FAIL,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_esc
+},
+{
+ .scp_name = SES_PROP_IDENT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_esc
+},
+{
+ .scp_name = SES_ESC_PROP_SELECT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_esc
+},
+{
+ NULL
+}
+};
+
+static const ses2_ctl_prop_t scc_props[] = {
+ SES_COMMON_CTL_PROPS,
+{
+ .scp_name = SES_PROP_FAIL,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_scc
+},
+{
+ .scp_name = SES_PROP_IDENT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_scc
+},
+{
+ NULL
+}
+};
+
+static const ses2_ctl_prop_t cache_props[] = {
+ SES_COMMON_CTL_PROPS,
+{
+ .scp_name = SES_PROP_FAIL,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_cache
+},
+{
+ .scp_name = SES_PROP_IDENT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_cache
+},
+{
+ NULL
+}
+};
+
+static const ses2_ctl_prop_t ups_props[] = {
+ SES_COMMON_CTL_PROPS,
+ SES_THRESHOLD_CTL_PROPS,
+{
+ .scp_name = SES_PROP_FAIL,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_ups
+},
+{
+ .scp_name = SES_PROP_IDENT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_ups
+},
+{
+ NULL
+}
+};
+
+static const ses2_ctl_prop_t display_props[] = {
+ SES_COMMON_CTL_PROPS,
+{
+ .scp_name = SES_DPY_PROP_MODE,
+ .scp_type = DATA_TYPE_UINT64,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_display
+},
+{
+ .scp_name = SES_PROP_FAIL,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_display
+},
+{
+ .scp_name = SES_PROP_IDENT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_display
+},
+{
+ .scp_name = SES_DPY_PROP_CHAR,
+ .scp_type = DATA_TYPE_UINT16,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_display
+},
+{
+ NULL
+}
+};
+
+static const ses2_ctl_prop_t keypad_props[] = {
+ SES_COMMON_CTL_PROPS,
+{
+ .scp_name = SES_PROP_FAIL,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_keypad
+},
+{
+ .scp_name = SES_PROP_IDENT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_keypad
+},
+{
+ NULL
+}
+};
+
+static const ses2_ctl_prop_t px_props[] = {
+ SES_COMMON_CTL_PROPS,
+{
+ .scp_name = SES_PROP_FAIL,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_px
+},
+{
+ .scp_name = SES_PROP_IDENT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_px
+},
+{
+ .scp_name = SES_PROP_DISABLED,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_px
+},
+{
+ NULL
+}
+};
+
+static const ses2_ctl_prop_t lang_props[] = {
+ SES_COMMON_CTL_PROPS,
+{
+ .scp_name = SES_PROP_IDENT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_lang
+},
+{
+ .scp_name = SES_LANG_PROP_LANGCODE,
+ .scp_type = DATA_TYPE_UINT64,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_lang
+},
+{
+ NULL
+}
+};
+
+static const ses2_ctl_prop_t comm_props[] = {
+ SES_COMMON_CTL_PROPS,
+{
+ .scp_name = SES_PROP_FAIL,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_comm
+},
+{
+ .scp_name = SES_PROP_IDENT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_comm
+},
+{
+ .scp_name = SES_PROP_DISABLED,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_comm
+},
+{
+ NULL
+}
+};
+
+static const ses2_ctl_prop_t voltage_props[] = {
+ SES_COMMON_CTL_PROPS,
+ SES_THRESHOLD_CTL_PROPS,
+{
+ .scp_name = SES_PROP_FAIL,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_voltage
+},
+{
+ .scp_name = SES_PROP_IDENT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_voltage
+},
+{
+ NULL
+}
+};
+
+static const ses2_ctl_prop_t current_props[] = {
+ SES_COMMON_CTL_PROPS,
+ SES_THRESHOLD_CTL_PROPS,
+{
+ .scp_name = SES_PROP_FAIL,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_current
+},
+{
+ .scp_name = SES_PROP_IDENT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_current
+},
+{
+ NULL
+}
+};
+
+static const ses2_ctl_prop_t itp_props[] = {
+ SES_COMMON_CTL_PROPS,
+{
+ .scp_name = SES_PROP_FAIL,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_itp
+},
+{
+ .scp_name = SES_PROP_IDENT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_itp
+},
+{
+ .scp_name = SES_ITP_PROP_ENABLED,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_itp
+},
+{
+ NULL
+}
+};
+
+static const ses2_ctl_prop_t sse_props[] = {
+ SES_COMMON_CTL_PROPS,
+{
+ .scp_name = SES_PROP_FAIL,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_sse
+},
+{
+ .scp_name = SES_PROP_IDENT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_sse
+},
+{
+ NULL
+}
+};
+
+static const ses2_ctl_prop_t arraydev_props[] = {
+ SES_COMMON_CTL_PROPS,
+{
+ .scp_name = SES_AD_PROP_RR_ABORT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_arraydev
+},
+{
+ .scp_name = SES_AD_PROP_REBUILD,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_arraydev
+},
+{
+ .scp_name = SES_AD_PROP_IN_FAILED_ARRAY,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_arraydev
+},
+{
+ .scp_name = SES_AD_PROP_IN_CRIT_ARRAY,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_arraydev
+},
+{
+ .scp_name = SES_AD_PROP_CONS_CHK,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_arraydev
+},
+{
+ .scp_name = SES_AD_PROP_HOT_SPARE,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_arraydev
+},
+{
+ .scp_name = SES_AD_PROP_RSVD_DEVICE,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_arraydev
+},
+{
+ .scp_name = SES_AD_PROP_OK,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_arraydev
+},
+{
+ .scp_name = SES_PROP_IDENT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_arraydev
+},
+{
+ .scp_name = SES_PROP_RMV,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_arraydev
+},
+{
+ .scp_name = SES_DEV_PROP_READY_TO_INSERT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_arraydev
+},
+{
+ .scp_name = SES_DEV_PROP_REQ_MISSING,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_arraydev
+},
+{
+ .scp_name = SES_DEV_PROP_DO_NOT_REMOVE,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_arraydev
+},
+{
+ .scp_name = SES_DEV_PROP_REQ_ACTIVE,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_arraydev
+},
+{
+ .scp_name = SES_DEV_PROP_BYP_B,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_arraydev
+},
+{
+ .scp_name = SES_DEV_PROP_BYP_A,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_arraydev
+},
+{
+ .scp_name = SES_PROP_OFF,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_arraydev
+},
+{
+ .scp_name = SES_DEV_PROP_FAULT_RQSTD,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_arraydev
+},
+{
+ NULL
+}
+};
+
+static const ses2_ctl_prop_t expander_props[] = {
+ SES_COMMON_CTL_PROPS,
+{
+ .scp_name = SES_PROP_FAIL,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_expander
+},
+{
+ .scp_name = SES_PROP_IDENT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_expander
+},
+{
+ NULL
+}
+};
+
+static const ses2_ctl_prop_t sasconn_props[] = {
+ SES_COMMON_CTL_PROPS,
+{
+ .scp_name = SES_PROP_IDENT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_sasconn
+},
+{
+ .scp_name = SES_PROP_FAIL,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = elem_setprop_sasconn
+},
+{
+ NULL
+}
+};
+
+/*ARGSUSED*/
+static int
+elem_setdef_threshold(ses_node_t *np, ses2_diag_page_t page, void *data)
+{
+ ses2_threshold_impl_t *tip = data;
+ nvlist_t *props = ses_node_props(np);
+
+ SES_NV_CTL64(props, SES_PROP_THRESH_CRIT_HI, tip->sti_high_crit);
+ SES_NV_CTL64(props, SES_PROP_THRESH_CRIT_LO, tip->sti_low_crit);
+ SES_NV_CTL64(props, SES_PROP_THRESH_WARN_HI, tip->sti_high_warn);
+ SES_NV_CTL64(props, SES_PROP_THRESH_WARN_LO, tip->sti_low_warn);
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+elem_setdef_device(ses_node_t *np, ses2_diag_page_t page, void *data)
+{
+ ses2_device_ctl_impl_t *dip = data;
+ nvlist_t *props = ses_node_props(np);
+
+ SES_NV_CTLBOOL(props, SES_PROP_IDENT, dip->sdci_rqst_ident);
+ SES_NV_CTLBOOL(props, SES_PROP_RMV, dip->sdci_rqst_remove);
+ SES_NV_CTLBOOL(props, SES_DEV_PROP_READY_TO_INSERT,
+ dip->sdci_rqst_insert);
+ SES_NV_CTLBOOL(props, SES_DEV_PROP_REQ_MISSING,
+ dip->sdci_rqst_missing);
+ SES_NV_CTLBOOL(props, SES_DEV_PROP_DO_NOT_REMOVE,
+ dip->sdci_do_not_remove);
+ SES_NV_CTLBOOL(props, SES_DEV_PROP_REQ_ACTIVE,
+ dip->sdci_rqst_active);
+ SES_NV_CTLBOOL(props, SES_DEV_PROP_BYP_B, dip->sdci_enable_byp_b);
+ SES_NV_CTLBOOL(props, SES_DEV_PROP_BYP_A, dip->sdci_enable_byp_a);
+ SES_NV_CTLBOOL(props, SES_PROP_OFF, dip->sdci_device_off);
+ SES_NV_CTLBOOL(props, SES_DEV_PROP_FAULT_RQSTD,
+ dip->sdci_rqst_fault);
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+elem_setdef_psu(ses_node_t *np, ses2_diag_page_t page, void *data)
+{
+ ses2_psu_ctl_impl_t *pip = data;
+ nvlist_t *props = ses_node_props(np);
+
+ SES_NV_CTLBOOL(props, SES_PROP_IDENT, pip->spci_rqst_ident);
+ SES_NV_CTLBOOL(props, SES_PROP_REQUESTED_ON, pip->spci_rqst_on);
+ SES_NV_CTLBOOL(props, SES_PROP_FAIL, pip->spci_rqst_fail);
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+elem_setdef_cooling(ses_node_t *np, ses2_diag_page_t page, void *data)
+{
+ ses2_cooling_ctl_impl_t *cip = data;
+ nvlist_t *props = ses_node_props(np);
+
+ SES_NV_CTLBOOL(props, SES_PROP_IDENT, cip->scci_rqst_ident);
+ SES_NV_CTL64(props, SES_COOLING_PROP_SPEED_CODE,
+ cip->scci_requested_speed_code);
+ SES_NV_CTLBOOL(props, SES_PROP_REQUESTED_ON, cip->scci_rqst_on);
+ SES_NV_CTLBOOL(props, SES_PROP_FAIL, cip->scci_rqst_fail);
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+elem_setdef_temp(ses_node_t *np, ses2_diag_page_t page, void *data)
+{
+ ses2_temp_ctl_impl_t *tip = data;
+ nvlist_t *props = ses_node_props(np);
+
+ if (page == SES2_DIAGPAGE_THRESHOLD_IO)
+ return (elem_setdef_threshold(np, page, data));
+
+ SES_NV_CTLBOOL(props, SES_PROP_FAIL, tip->stci_rqst_fail);
+ SES_NV_CTLBOOL(props, SES_PROP_IDENT, tip->stci_rqst_ident);
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+elem_setdef_lock(ses_node_t *np, ses2_diag_page_t page, void *data)
+{
+ ses2_lock_ctl_impl_t *lip = data;
+ nvlist_t *props = ses_node_props(np);
+
+ SES_NV_CTLBOOL(props, SES_PROP_FAIL, lip->slci_rqst_fail);
+ SES_NV_CTLBOOL(props, SES_PROP_IDENT, lip->slci_rqst_ident);
+ SES_NV_CTLBOOL(props, SES_LOCK_PROP_UNLOCKED, lip->slci_unlock);
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+elem_setdef_alarm(ses_node_t *np, ses2_diag_page_t page, void *data)
+{
+ ses2_alarm_ctl_impl_t *aip = data;
+ nvlist_t *props = ses_node_props(np);
+
+ SES_NV_CTLBOOL(props, SES_PROP_FAIL, aip->saci_rqst_fail);
+ SES_NV_CTLBOOL(props, SES_PROP_IDENT, aip->saci_rqst_ident);
+ SES_NV_CTLBOOL(props, SES_ALARM_PROP_UNRECOV, aip->saci_unrecov);
+ SES_NV_CTLBOOL(props, SES_ALARM_PROP_CRIT, aip->saci_crit);
+ SES_NV_CTLBOOL(props, SES_ALARM_PROP_NONCRIT, aip->saci_noncrit);
+ SES_NV_CTLBOOL(props, SES_ALARM_PROP_INFO, aip->saci_info);
+ SES_NV_CTLBOOL(props, SES_ALARM_PROP_REMIND, aip->saci_set_remind);
+ SES_NV_CTLBOOL(props, SES_ALARM_PROP_MUTED, aip->saci_set_mute);
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+elem_setdef_esc(ses_node_t *np, ses2_diag_page_t page, void *data)
+{
+ ses2_controller_ctl_impl_t *cip = data;
+ nvlist_t *props = ses_node_props(np);
+
+ SES_NV_CTLBOOL(props, SES_PROP_FAIL, cip->scci_rqst_fail);
+ SES_NV_CTLBOOL(props, SES_PROP_IDENT, cip->scci_rqst_ident);
+ SES_NV_CTLBOOL(props, SES_ESC_PROP_SELECT,
+ cip->scci_select_element);
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+elem_setdef_scc(ses_node_t *np, ses2_diag_page_t page, void *data)
+{
+ ses2_scc_ctl_impl_t *sip = data;
+ nvlist_t *props = ses_node_props(np);
+
+ SES_NV_CTLBOOL(props, SES_PROP_FAIL, sip->ssci_rqst_fail);
+ SES_NV_CTLBOOL(props, SES_PROP_IDENT, sip->ssci_rqst_ident);
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+elem_setdef_cache(ses_node_t *np, ses2_diag_page_t page, void *data)
+{
+ ses2_nvcache_ctl_impl_t *cip = data;
+ nvlist_t *props = ses_node_props(np);
+
+ SES_NV_CTLBOOL(props, SES_PROP_FAIL, cip->snci_rqst_fail);
+ SES_NV_CTLBOOL(props, SES_PROP_IDENT, cip->snci_rqst_ident);
+
+ return (0);
+}
+
+static int
+elem_setdef_ups(ses_node_t *np, ses2_diag_page_t page, void *data)
+{
+ ses2_ups_ctl_impl_t *uip = data;
+ nvlist_t *props = ses_node_props(np);
+
+ if (page == SES2_DIAGPAGE_THRESHOLD_IO)
+ return (elem_setdef_threshold(np, page, data));
+
+ SES_NV_CTLBOOL(props, SES_PROP_FAIL, uip->suci_rqst_fail);
+ SES_NV_CTLBOOL(props, SES_PROP_IDENT, uip->suci_rqst_ident);
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+elem_setdef_display(ses_node_t *np, ses2_diag_page_t page, void *data)
+{
+ ses2_display_ctl_impl_t *dip = data;
+ nvlist_t *props = ses_node_props(np);
+
+ SES_NV_CTL64(props, SES_DPY_PROP_MODE, dip->sdci_display_mode);
+ SES_NV_CTLBOOL(props, SES_PROP_FAIL, dip->sdci_rqst_fail);
+ SES_NV_CTLBOOL(props, SES_PROP_IDENT, dip->sdci_rqst_ident);
+ SES_NV_CTL16(props, SES_DPY_PROP_CHAR,
+ dip->sdci_display_character);
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+elem_setdef_keypad(ses_node_t *np, ses2_diag_page_t page, void *data)
+{
+ ses2_keypad_ctl_impl_t *kip = data;
+ nvlist_t *props = ses_node_props(np);
+
+ SES_NV_CTLBOOL(props, SES_PROP_FAIL, kip->skci_rqst_fail);
+ SES_NV_CTLBOOL(props, SES_PROP_IDENT, kip->skci_rqst_ident);
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+elem_setdef_px(ses_node_t *np, ses2_diag_page_t page, void *data)
+{
+ ses2_port_ctl_impl_t *pip = data;
+ nvlist_t *props = ses_node_props(np);
+
+ SES_NV_CTLBOOL(props, SES_PROP_FAIL, pip->spci_rqst_fail);
+ SES_NV_CTLBOOL(props, SES_PROP_IDENT, pip->spci_rqst_ident);
+ SES_NV_CTLBOOL(props, SES_PROP_DISABLED, pip->spci_disable);
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+elem_setdef_lang(ses_node_t *np, ses2_diag_page_t page, void *data)
+{
+ ses2_lang_ctl_impl_t *lip = data;
+ nvlist_t *props = ses_node_props(np);
+
+ SES_NV_CTLBOOL(props, SES_PROP_IDENT, lip->slci_rqst_ident);
+ SES_NV_CTL16(props, SES_LANG_PROP_LANGCODE,
+ lip->slci_language_code);
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+elem_setdef_comm(ses_node_t *np, ses2_diag_page_t page, void *data)
+{
+ ses2_comm_ctl_impl_t *cip = data;
+ nvlist_t *props = ses_node_props(np);
+
+ SES_NV_CTLBOOL(props, SES_PROP_FAIL, cip->scci_rqst_fail);
+ SES_NV_CTLBOOL(props, SES_PROP_IDENT, cip->scci_rqst_ident);
+ SES_NV_CTLBOOL(props, SES_PROP_DISABLED, cip->scci_disable);
+
+ return (0);
+}
+
+static int
+elem_setdef_voltage(ses_node_t *np, ses2_diag_page_t page, void *data)
+{
+ ses2_voltage_ctl_impl_t *vip = data;
+ nvlist_t *props = ses_node_props(np);
+
+ if (page == SES2_DIAGPAGE_THRESHOLD_IO)
+ return (elem_setdef_threshold(np, page, data));
+
+ SES_NV_CTLBOOL(props, SES_PROP_FAIL, vip->svci_rqst_fail);
+ SES_NV_CTLBOOL(props, SES_PROP_IDENT, vip->svci_rqst_ident);
+
+ return (0);
+}
+
+static int
+elem_setdef_current(ses_node_t *np, ses2_diag_page_t page, void *data)
+{
+ ses2_current_ctl_impl_t *cip = data;
+ nvlist_t *props = ses_node_props(np);
+
+ if (page == SES2_DIAGPAGE_THRESHOLD_IO)
+ return (elem_setdef_threshold(np, page, data));
+
+ SES_NV_CTLBOOL(props, SES_PROP_FAIL, cip->scci_rqst_fail);
+ SES_NV_CTLBOOL(props, SES_PROP_IDENT, cip->scci_rqst_ident);
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+elem_setdef_itp(ses_node_t *np, ses2_diag_page_t page, void *data)
+{
+ ses2_itp_ctl_impl_t *iip = data;
+ nvlist_t *props = ses_node_props(np);
+
+ SES_NV_CTLBOOL(props, SES_PROP_FAIL, iip->sici_rqst_fail);
+ SES_NV_CTLBOOL(props, SES_PROP_IDENT, iip->sici_rqst_ident);
+ SES_NV_CTLBOOL(props, SES_ITP_PROP_ENABLED, iip->sici_enable);
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+elem_setdef_sse(ses_node_t *np, ses2_diag_page_t page, void *data)
+{
+ ses2_ss_ctl_impl_t *sip = data;
+ nvlist_t *props = ses_node_props(np);
+
+ SES_NV_CTLBOOL(props, SES_PROP_FAIL, sip->ssci_rqst_fail);
+ SES_NV_CTLBOOL(props, SES_PROP_IDENT, sip->ssci_rqst_ident);
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+elem_setdef_arraydev(ses_node_t *np, ses2_diag_page_t page, void *data)
+{
+ ses2_array_device_ctl_impl_t *aip = data;
+ nvlist_t *props = ses_node_props(np);
+
+ SES_NV_CTLBOOL(props, SES_AD_PROP_RR_ABORT,
+ aip->sadci_rqst_rr_abort);
+ SES_NV_CTLBOOL(props, SES_AD_PROP_REBUILD,
+ aip->sadci_rqst_rebuild);
+ SES_NV_CTLBOOL(props, SES_AD_PROP_IN_FAILED_ARRAY,
+ aip->sadci_rqst_in_failed_array);
+ SES_NV_CTLBOOL(props, SES_AD_PROP_IN_CRIT_ARRAY,
+ aip->sadci_rqst_in_crit_array);
+ SES_NV_CTLBOOL(props, SES_AD_PROP_CONS_CHK,
+ aip->sadci_rqst_cons_check);
+ SES_NV_CTLBOOL(props, SES_AD_PROP_HOT_SPARE,
+ aip->sadci_rqst_hot_spare);
+ SES_NV_CTLBOOL(props, SES_AD_PROP_RSVD_DEVICE,
+ aip->sadci_rqst_rsvd_device);
+
+ SES_NV_CTLBOOL(props, SES_PROP_IDENT, aip->sadci_rqst_ident);
+ SES_NV_CTLBOOL(props, SES_PROP_RMV, aip->sadci_rqst_remove);
+ SES_NV_CTLBOOL(props, SES_DEV_PROP_READY_TO_INSERT,
+ aip->sadci_rqst_insert);
+ SES_NV_CTLBOOL(props, SES_DEV_PROP_REQ_MISSING,
+ aip->sadci_rqst_missing);
+ SES_NV_CTLBOOL(props, SES_DEV_PROP_DO_NOT_REMOVE,
+ aip->sadci_do_not_remove);
+ SES_NV_CTLBOOL(props, SES_DEV_PROP_REQ_ACTIVE,
+ aip->sadci_rqst_active);
+
+ SES_NV_CTLBOOL(props, SES_DEV_PROP_BYP_B, aip->sadci_enable_byp_b);
+ SES_NV_CTLBOOL(props, SES_DEV_PROP_BYP_A, aip->sadci_enable_byp_a);
+ SES_NV_CTLBOOL(props, SES_PROP_OFF, aip->sadci_device_off);
+ SES_NV_CTLBOOL(props, SES_DEV_PROP_FAULT_RQSTD,
+ aip->sadci_rqst_fault);
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+elem_setdef_expander(ses_node_t *np, ses2_diag_page_t page, void *data)
+{
+ ses2_expander_ctl_impl_t *eip = data;
+ nvlist_t *props = ses_node_props(np);
+
+ SES_NV_CTLBOOL(props, SES_PROP_FAIL, eip->seci_rqst_fail);
+ SES_NV_CTLBOOL(props, SES_PROP_IDENT, eip->seci_rqst_ident);
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+elem_setdef_sasconn(ses_node_t *np, ses2_diag_page_t page, void *data)
+{
+ ses2_sasconn_ctl_impl_t *sip = data;
+ nvlist_t *props = ses_node_props(np);
+
+ SES_NV_CTLBOOL(props, SES_PROP_IDENT, sip->ssci_rqst_ident);
+ SES_NV_CTLBOOL(props, SES_PROP_FAIL, sip->ssci_rqst_fail);
+
+ return (0);
+}
+
+#define CTL_DESC(_e, _n) \
+ { \
+ .scd_et = _e, \
+ .scd_props = _n##_props, \
+ .scd_setdef = elem_setdef_##_n \
+ }
+
+static const ses2_ctl_desc_t ctl_descs[] = {
+ CTL_DESC(SES_ET_DEVICE, device),
+ CTL_DESC(SES_ET_POWER_SUPPLY, psu),
+ CTL_DESC(SES_ET_COOLING, cooling),
+ CTL_DESC(SES_ET_TEMPERATURE_SENSOR, temp),
+ CTL_DESC(SES_ET_DOOR_LOCK, lock),
+ CTL_DESC(SES_ET_AUDIBLE_ALARM, alarm),
+ CTL_DESC(SES_ET_ESC_ELECTRONICS, esc),
+ CTL_DESC(SES_ET_SCC_ELECTRONICS, scc),
+ CTL_DESC(SES_ET_NONVOLATILE_CACHE, cache),
+ CTL_DESC(SES_ET_UPS, ups),
+ CTL_DESC(SES_ET_DISPLAY, display),
+ CTL_DESC(SES_ET_KEY_PAD_ENTRY, keypad),
+ CTL_DESC(SES_ET_SCSI_PORT_XCVR, px),
+ CTL_DESC(SES_ET_LANGUAGE, lang),
+ CTL_DESC(SES_ET_COMMUNICATION_PORT, comm),
+ CTL_DESC(SES_ET_VOLTAGE_SENSOR, voltage),
+ CTL_DESC(SES_ET_CURRENT_SENSOR, current),
+ CTL_DESC(SES_ET_SCSI_TARGET_PORT, itp),
+ CTL_DESC(SES_ET_SCSI_INITIATOR_PORT, itp),
+ CTL_DESC(SES_ET_SIMPLE_SUBENCLOSURE, sse),
+ CTL_DESC(SES_ET_ARRAY_DEVICE, arraydev),
+ CTL_DESC(SES_ET_SAS_EXPANDER, expander),
+ CTL_DESC(SES_ET_SAS_CONNECTOR, sasconn),
+ { .scd_et = -1 }
+};
+
+int
+ses2_element_ctl(ses_plugin_t *sp, ses_node_t *np, const char *op,
+ nvlist_t *nvl)
+{
+ const ses2_ctl_desc_t *dp;
+ nvlist_t *props = ses_node_props(np);
+ uint64_t type;
+
+ if (strcmp(op, SES_CTL_OP_SETPROP) != 0)
+ return (0);
+
+ VERIFY(nvlist_lookup_uint64(props, SES_PROP_ELEMENT_TYPE,
+ &type) == 0);
+
+ for (dp = &ctl_descs[0]; dp->scd_et != -1; dp++)
+ if (dp->scd_et == type)
+ break;
+
+ if (dp->scd_et == -1)
+ return (0);
+
+ return (ses2_setprop(sp, np, dp->scd_props, nvl));
+}
+
+int
+ses2_element_setdef(ses_node_t *np, ses2_diag_page_t page, void *data)
+{
+ const ses2_ctl_desc_t *dp;
+ nvlist_t *props = ses_node_props(np);
+ uint64_t type;
+
+ VERIFY(nvlist_lookup_uint64(props, SES_PROP_ELEMENT_TYPE, &type) == 0);
+
+ for (dp = &ctl_descs[0]; dp->scd_et != -1; dp++)
+ if (dp->scd_et == type)
+ break;
+
+ if (dp->scd_et == -1)
+ return (0);
+
+ if (dp->scd_setdef(np, page, data) != 0)
+ return (-1);
+
+ return (0);
+}
diff --git a/usr/src/lib/scsi/plugins/ses/ses2/common/ses2_enclosure.c b/usr/src/lib/scsi/plugins/ses/ses2/common/ses2_enclosure.c
new file mode 100644
index 0000000000..099d1a5777
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/ses2/common/ses2_enclosure.c
@@ -0,0 +1,328 @@
+/*
+ * 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"
+
+#include <stddef.h>
+#include <string.h>
+#include <strings.h>
+#include <libnvpair.h>
+
+#include <scsi/libses.h>
+#include <scsi/plugins/ses/framework/ses2_impl.h>
+
+static int
+enc_parse_sd(ses2_elem_status_impl_t *esip, nvlist_t *nvl)
+{
+ ses2_enclosure_status_impl_t *sdp;
+ int nverr;
+
+ sdp = (ses2_enclosure_status_impl_t *)esip;
+
+ SES_NV_ADD(uint64, nverr, nvl, SES_PROP_STATUS_CODE,
+ sdp->sesi_common.sesi_status_code);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_SWAP,
+ sdp->sesi_common.sesi_swap);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_DISABLED,
+ sdp->sesi_common.sesi_disabled);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_PRDFAIL,
+ sdp->sesi_common.sesi_prdfail);
+
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, sdp->sesi_ident);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_WARN,
+ sdp->sesi_warning_indication);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL,
+ sdp->sesi_failure_indication);
+ SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_POWER_DELAY,
+ sdp->sesi_power_delay);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_WARN_REQ,
+ sdp->sesi_warning_requested);
+ SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL_REQ,
+ sdp->sesi_warning_requested);
+ SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_POWER_DURATION,
+ sdp->sesi_power_duration);
+
+ return (0);
+}
+
+static int
+enc_parse_help(ses_plugin_t *sp, ses_node_t *np)
+{
+ ses_snap_t *snap = ses_node_snapshot(np);
+ ses2_help_page_impl_t *hpip;
+ ses2_subhelp_page_impl_t *shpip;
+ ses2_subhelp_text_impl_t *tip;
+ nvlist_t *nvl = ses_node_props(np);
+ uint64_t eid;
+ size_t len;
+ off_t pos;
+ int nverr;
+
+ if (nvlist_lookup_uint64(nvl, SES_EN_PROP_EID, &eid) != 0)
+ return (0);
+
+ if ((shpip = ses_plugin_page_lookup(sp, snap,
+ SES2_DIAGPAGE_SUBENCLOSURE_HELP_TEXT, np, &len)) != NULL) {
+ pos = 0;
+ for (tip = (ses2_subhelp_text_impl_t *)shpip->sspi_data;
+ pos < SCSI_READ16(&shpip->sspi_page_length);
+ pos += SES2_SUBHELP_LEN(tip),
+ tip = (ses2_subhelp_text_impl_t *)((uint8_t *)tip + pos)) {
+ if (!SES_WITHIN_PAGE_STRUCT(tip, shpip, len))
+ break;
+
+ if (tip->ssti_subenclosure_identifier != eid)
+ continue;
+
+ if (!SES_WITHIN_PAGE(tip->ssti_subenclosure_help_text,
+ tip->ssti_subenclosure_help_text_length, shpip,
+ len))
+ break;
+
+ SES_NV_ADD(fixed_string, nverr, nvl, SES_EN_PROP_HELP,
+ tip->ssti_subenclosure_help_text,
+ tip->ssti_subenclosure_help_text_length);
+ return (0);
+ }
+ }
+
+ if (eid == 0 && (hpip = ses_plugin_page_lookup(sp, snap,
+ SES2_DIAGPAGE_HELP_TEXT, np, &len)) != NULL) {
+ if (!SES_WITHIN_PAGE_STRUCT(hpip, hpip, len))
+ return (0);
+
+ if (!SES_WITHIN_PAGE(hpip->shpi_help_text,
+ SCSI_READ16(&hpip->shpi_page_length), hpip, len))
+ return (0);
+
+ SES_NV_ADD(fixed_string, nverr, nvl, SES_EN_PROP_HELP,
+ hpip->shpi_help_text, SCSI_READ16(&hpip->shpi_page_length));
+ }
+
+ return (0);
+}
+
+static int
+enc_parse_string_in(ses_plugin_t *sp, ses_node_t *np)
+{
+ ses_snap_t *snap = ses_node_snapshot(np);
+ ses2_string_in_page_impl_t *sip;
+ ses2_substring_in_page_impl_t *ssip;
+ ses2_substring_in_data_impl_t *dip;
+ nvlist_t *nvl = ses_node_props(np);
+ uint64_t eid;
+ off_t pos;
+ size_t len, textlen;
+ int nverr;
+
+ if (nvlist_lookup_uint64(nvl, SES_EN_PROP_EID, &eid) != 0)
+ return (0);
+
+ if ((ssip = ses_plugin_page_lookup(sp, snap,
+ SES2_DIAGPAGE_SUBENCLOSURE_STRING_IO, np, &len)) != NULL) {
+ pos = 0;
+ for (dip = (ses2_substring_in_data_impl_t *)ssip->ssipi_data;
+ pos < SCSI_READ16(&ssip->ssipi_page_length);
+ pos += SES2_SUBSTR_LEN(dip),
+ dip = (ses2_substring_in_data_impl_t *)
+ ((uint8_t *)dip + pos)) {
+ if (!SES_WITHIN_PAGE_STRUCT(dip, ssip, len))
+ break;
+
+ if (dip->ssidi_subenclosure_identifier != eid)
+ continue;
+
+ if (!SES_WITHIN_PAGE(dip->ssidi_data,
+ dip->ssidi_substring_data_length, ssip, len))
+ break;
+
+ SES_NV_ADD(fixed_string, nverr, nvl, SES_EN_PROP_STRING,
+ (char *)dip->ssidi_data,
+ dip->ssidi_substring_data_length);
+ return (0);
+ }
+ }
+
+ if (eid == 0 && (sip = ses_plugin_page_lookup(sp, snap,
+ SES2_DIAGPAGE_STRING_IO, np, &len)) != NULL) {
+ if (!SES_WITHIN_PAGE_STRUCT(sip, sip, len))
+ return (0);
+
+ textlen = SCSI_READ16(&sip->ssipi_page_length);
+
+ if (!SES_WITHIN_PAGE(sip->ssipi_data, textlen, sip, len))
+ return (0);
+
+ SES_NV_ADD(byte_array, nverr, nvl, SES_EN_PROP_STRING,
+ sip->ssipi_data, textlen);
+ }
+
+ return (0);
+}
+
+static int
+enc_parse_descr(ses_plugin_t *sp, ses_node_t *np)
+{
+ char *desc;
+ nvlist_t *props = ses_node_props(np);
+ int nverr;
+ size_t len;
+
+ if ((desc = ses_plugin_page_lookup(sp, ses_node_snapshot(np),
+ SES2_DIAGPAGE_ELEMENT_DESC, np, &len)) == NULL)
+ return (0);
+
+ SES_NV_ADD(fixed_string, nverr, props, SES_PROP_DESCRIPTION,
+ desc, len);
+
+ return (0);
+}
+
+static int
+enc_parse_dlucode(ses_plugin_t *sp, ses_node_t *np)
+{
+ ses_snap_t *snap = ses_node_snapshot(np);
+ ses2_ucode_status_page_impl_t *upip;
+ ses2_ucode_status_descr_impl_t *dip;
+ nvlist_t *nvl = ses_node_props(np);
+ int nverr, i;
+ size_t len;
+ uint64_t eid;
+
+ if ((upip = ses_plugin_page_lookup(sp, snap,
+ SES2_DIAGPAGE_DL_MICROCODE_CTL_STATUS, np, &len)) == NULL)
+ return (0);
+
+ if (nvlist_lookup_uint64(nvl, SES_EN_PROP_EID, &eid) != 0)
+ return (0);
+
+ if (!SES_WITHIN_PAGE_STRUCT(upip, upip, len))
+ return (0);
+
+ /*
+ * The number of subenclosures excludes the primary subenclosure, which
+ * is always part of the response.
+ */
+ for (dip = &upip->suspi_descriptors[0], i = 0;
+ i <= upip->suspi_n_subenclosures;
+ i++, dip++) {
+ if (!SES_WITHIN_PAGE_STRUCT(dip, upip, len))
+ break;
+
+ if (dip->susdi_subenclosure_identifier != eid)
+ continue;
+ SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_UCODE,
+ dip->susdi_subenclosure_dl_status);
+ SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_UCODE_A,
+ dip->susdi_subenclosure_dl_addl_status);
+ SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_UCODE_SZ,
+ SCSI_READ32(&dip->susdi_subenclosure_dl_max_size));
+ SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_UCODE_BUF,
+ dip->susdi_subenclosure_dl_buffer_id);
+ SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_UCODE_OFF,
+ dip->susdi_subenclosure_dl_buffer_offset);
+ break;
+ }
+
+ return (0);
+}
+
+static int
+enc_parse_subnick(ses_plugin_t *sp, ses_node_t *np)
+{
+ ses_snap_t *snap = ses_node_snapshot(np);
+ ses2_subnick_status_page_impl_t *spip;
+ ses2_subnick_descr_impl_t *dip;
+ nvlist_t *nvl = ses_node_props(np);
+ int nverr, i;
+ size_t len;
+ uint64_t eid;
+
+ if (nvlist_lookup_uint64(nvl, SES_EN_PROP_EID, &eid) != 0)
+ return (0);
+
+ if ((spip = ses_plugin_page_lookup(sp, snap,
+ SES2_DIAGPAGE_SUBENCLOSURE_NICKNAME_CTL_STATUS,
+ np, &len)) == NULL)
+ return (0);
+
+ if (!SES_WITHIN_PAGE_STRUCT(spip, spip, len))
+ return (0);
+
+ for (dip = &spip->sspci_subnicks[0], i = 0;
+ i < spip->sspci_n_subenclosures;
+ i++, dip++) {
+ if (!SES_WITHIN_PAGE_STRUCT(dip, spip, len))
+ break;
+
+ if (dip->ssdi_subenclosure_identifier != eid)
+ continue;
+ SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_NICK_STATUS,
+ dip->ssdi_subenclosure_nick_status);
+ SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_NICK_ADDL_STATUS,
+ dip->ssdi_subenclosure_nick_addl_status);
+ SES_NV_ADD_FS(nverr, nvl, SES_EN_PROP_NICK,
+ dip->ssdi_subenclosure_nickname);
+ SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_NICK_LANG,
+ dip->ssdi_subenclosure_nick_lang_code);
+ break;
+ }
+
+ return (0);
+}
+
+int
+ses2_fill_enclosure_node(ses_plugin_t *sp, ses_node_t *np)
+{
+ ses_snap_t *snap = ses_node_snapshot(np);
+ nvlist_t *props = ses_node_props(np);
+ ses2_elem_status_impl_t *esip;
+ int err;
+ size_t len;
+
+ if ((esip = ses_plugin_page_lookup(sp, snap,
+ SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS, np, &len)) != NULL) {
+ if ((err = enc_parse_sd(esip, props)) != 0)
+ return (err);
+ }
+
+ if ((err = enc_parse_help(sp, np)) != 0)
+ return (err);
+
+ if ((err = enc_parse_string_in(sp, np)) != 0)
+ return (err);
+
+ if ((err = enc_parse_descr(sp, np)) != 0)
+ return (err);
+
+ if ((err = enc_parse_dlucode(sp, np)) != 0)
+ return (err);
+
+ if ((err = enc_parse_subnick(sp, np)) != 0)
+ return (err);
+
+ return (0);
+}
diff --git a/usr/src/lib/scsi/plugins/ses/ses2/common/ses2_enclosure_ctl.c b/usr/src/lib/scsi/plugins/ses/ses2/common/ses2_enclosure_ctl.c
new file mode 100644
index 0000000000..8b162e11e3
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/ses2/common/ses2_enclosure_ctl.c
@@ -0,0 +1,330 @@
+/*
+ * 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.
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <libnvpair.h>
+
+#include <scsi/libses.h>
+#include "ses2_impl.h"
+
+#define SES_UCODE_CHUNK_SIZE (32 * 1024)
+
+/*ARGSUSED*/
+static int
+enc_do_ucode(ses_plugin_t *sp, ses_node_t *np, nvlist_t *nvl)
+{
+ nvlist_t *props = ses_node_props(np);
+ uint64_t maxlen, bufid = 0;
+ uint8_t *data;
+ ses2_ucode_ctl_page_impl_t *uip;
+ size_t offset, len, pagelen;
+ uint_t datalen;
+ uint64_t mode;
+
+ /*
+ * Get the data and check the length.
+ */
+ if (nvlist_lookup_byte_array(nvl, SES_CTL_PROP_UCODE_DATA,
+ &data, &datalen) != 0)
+ return (ses_error(ESES_INVALID_PROP,
+ "missing or invalid %s property", SES_CTL_PROP_UCODE_DATA));
+
+ if (nvlist_lookup_uint64(nvl, SES_CTL_PROP_UCODE_MODE,
+ &mode) != 0)
+ return (ses_error(ESES_INVALID_PROP,
+ "missing or invalid %s property", SES_CTL_PROP_UCODE_MODE));
+
+ if (nvlist_lookup_uint64(props, SES_EN_PROP_UCODE_SZ,
+ &maxlen) != 0 || datalen > maxlen)
+ return (ses_error(ESES_RANGE,
+ "microcode image length (%u) exceeds maximum length (%llu)",
+ datalen, maxlen));
+
+ /*
+ * Get the expected buffer ID, but allow the user to override it.
+ */
+ (void) nvlist_lookup_uint64(props, SES_EN_PROP_UCODE_BUF,
+ &bufid);
+
+ if (bufid == 0xFF)
+ bufid = 0;
+
+ (void) nvlist_lookup_uint64(nvl, SES_CTL_PROP_UCODE_BUFID, &bufid);
+
+ for (offset = 0; offset < datalen; offset += SES_UCODE_CHUNK_SIZE) {
+
+ len = MIN(datalen - offset, SES_UCODE_CHUNK_SIZE);
+ if (len & 0x3)
+ pagelen = (len + 4) & 0x3;
+ else
+ pagelen = len;
+
+ if ((uip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ SES2_DIAGPAGE_DL_MICROCODE_CTL_STATUS, pagelen,
+ np, B_TRUE)) == NULL)
+ return (-1);
+
+ uip->sucpi_buffer_id = (uint8_t)bufid;
+ uip->sucpi_dl_ucode_mode = mode;
+ SCSI_WRITE32(&uip->sucpi_buffer_offset, offset);
+ SCSI_WRITE32(&uip->sucpi_ucode_image_length, datalen);
+ SCSI_WRITE32(&uip->sucpi_ucode_data_length, len);
+
+ bcopy(data + offset, &uip->sucpi_ucode_data[0],
+ len);
+
+ if (len != pagelen)
+ bzero(&uip->sucpi_ucode_data[0] + len,
+ pagelen - len);
+ }
+
+ (void) nvlist_remove_all(nvl, SES_CTL_PROP_UCODE_DATA);
+ (void) nvlist_remove_all(nvl, SES_CTL_PROP_UCODE_MODE);
+ (void) nvlist_remove_all(nvl, SES_CTL_PROP_UCODE_BUFID);
+
+ return (0);
+}
+
+static int
+enc_ctl_common(ses_plugin_t *sp, ses_node_t *np, ses2_diag_page_t page,
+ nvpair_t *nvp)
+{
+ ses2_enclosure_ctl_impl_t *tp;
+ const char *name;
+ boolean_t boolval;
+ uint64_t intval;
+
+ ASSERT(page == SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS);
+
+ if ((tp = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ page, 0, np, B_FALSE)) == NULL)
+ return (-1);
+
+ name = nvpair_name(nvp);
+ (void) nvpair_value_boolean_value(nvp, &boolval);
+ (void) nvpair_value_uint64(nvp, &intval);
+
+ if (strcmp(name, SES_PROP_IDENT) == 0)
+ tp->seci_rqst_ident = boolval;
+ else if (strcmp(name, SES_PROP_WARN_REQ) == 0)
+ tp->seci_request_warning = boolval;
+ else if (strcmp(name, SES_PROP_FAIL_REQ) == 0)
+ tp->seci_request_failure = boolval;
+ else if (strcmp(name, SES_EN_PROP_POWER_DELAY) == 0)
+ tp->seci_power_cycle_delay = intval;
+ else if (strcmp(name, SES_EN_PROP_POWER_REQUEST) == 0)
+ tp->seci_power_cycle_request = intval;
+ else if (strcmp(name, SES_EN_PROP_POWER_DURATION) == 0)
+ tp->seci_power_off_duration = intval;
+ else
+ ses_panic("bad property %s", name);
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+enc_ctl_string(ses_plugin_t *sp, ses_node_t *np, ses2_diag_page_t page,
+ nvpair_t *nvp)
+{
+ ses2_substring_out_page_impl_t *spip;
+ ses2_string_out_page_impl_t *pip;
+ const uint8_t *data;
+ size_t datalen;
+ uint_t nvlen;
+ nvlist_t *props = ses_node_props(np);
+ uint64_t eid;
+
+ ASSERT(strcmp(nvpair_name(nvp), SES_EN_PROP_STRING) == 0);
+
+ VERIFY(nvlist_lookup_uint64(props, SES_EN_PROP_EID, &eid) == 0);
+
+ (void) nvpair_value_byte_array(nvp, (uint8_t **)&data, &nvlen);
+ datalen = (size_t)nvlen;
+
+ if ((spip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ SES2_DIAGPAGE_SUBENCLOSURE_STRING_IO, datalen, np,
+ B_FALSE)) != NULL) {
+ spip->ssopi_subenclosure_identifier = eid;
+ bcopy(data, spip->ssopi_data, datalen);
+ } else {
+ if (eid != 0)
+ return (ses_error(ESES_NOTSUP, "target does not "
+ "support string data for secondary subenclosures"));
+
+ if ((pip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ SES2_DIAGPAGE_STRING_IO, datalen, np, B_FALSE)) == NULL)
+ return (-1);
+
+ bcopy(data, pip->ssopi_data, datalen);
+ }
+
+ return (0);
+}
+
+static int
+enc_ctl_nick(ses_plugin_t *sp, ses_node_t *np, ses2_diag_page_t page,
+ nvpair_t *nvp)
+{
+ /* LINTED - dummy variable for sizeof */
+ ses2_subnick_ctl_page_impl_t *pip, dummy;
+ const char *nick;
+ size_t len, max;
+ nvlist_t *props = ses_node_props(np);
+ uint64_t eid;
+
+ ASSERT(strcmp(nvpair_name(nvp), SES_EN_PROP_NICK) == 0);
+ ASSERT(page == SES2_DIAGPAGE_SUBENCLOSURE_NICKNAME_CTL_STATUS);
+
+ (void) nvpair_value_string(nvp, (char **)&nick);
+ len = strlen(nick);
+
+ VERIFY(nvlist_lookup_uint64(props, SES_EN_PROP_EID, &eid) == 0);
+
+ max = sizeof (dummy.sspci_subenclosure_nickname);
+ if (len > max)
+ return (ses_error(ESES_RANGE, "nickname '%s' exceeds "
+ "maximum length %lu", nick, max));
+
+ if ((pip = ses_plugin_ctlpage_lookup(sp, ses_node_snapshot(np),
+ page, len, np, B_FALSE)) == NULL)
+ return (-1);
+
+ pip->sspci_subenclosure_identifier = eid;
+ bcopy(nick, pip->sspci_subenclosure_nickname, len);
+
+ return (0);
+}
+
+static const ses2_ctl_prop_t enc_props[] = {
+ SES_COMMON_CTL_PROPS,
+{
+ .scp_name = SES_PROP_IDENT,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = enc_ctl_common
+},
+{
+ .scp_name = SES_PROP_WARN_REQ,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = enc_ctl_common
+},
+{
+ .scp_name = SES_PROP_FAIL_REQ,
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = enc_ctl_common
+},
+{
+ .scp_name = SES_EN_PROP_POWER_DELAY,
+ .scp_type = DATA_TYPE_UINT64,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = enc_ctl_common
+},
+{
+ .scp_name = SES_EN_PROP_POWER_DURATION,
+ .scp_type = DATA_TYPE_UINT64,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = enc_ctl_common
+},
+{
+ .scp_name = SES_EN_PROP_POWER_REQUEST,
+ .scp_type = DATA_TYPE_UINT64,
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .scp_setprop = enc_ctl_common
+},
+{
+ .scp_name = SES_EN_PROP_STRING,
+ .scp_type = DATA_TYPE_BYTE_ARRAY,
+ .scp_num = -1,
+ .scp_setprop = enc_ctl_string
+},
+{
+ .scp_name = SES_EN_PROP_NICK,
+ .scp_type = DATA_TYPE_STRING,
+ .scp_num = SES2_DIAGPAGE_SUBENCLOSURE_NICKNAME_CTL_STATUS,
+ .scp_setprop = enc_ctl_nick
+},
+{
+ NULL
+}
+};
+
+static int
+enc_setdef_one(ses_node_t *np, ses2_diag_page_t page, void *data)
+{
+ ses2_enclosure_ctl_impl_t *tp = data;
+ nvlist_t *props = ses_node_props(np);
+
+ if (page != SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS)
+ return (0);
+
+ SES_NV_CTLBOOL(props, SES_PROP_IDENT, tp->seci_rqst_ident);
+ SES_NV_CTLBOOL(props, SES_PROP_WARN_REQ,
+ tp->seci_request_warning);
+ SES_NV_CTLBOOL(props, SES_PROP_FAIL_REQ,
+ tp->seci_request_failure);
+
+ return (0);
+}
+
+int
+ses2_enclosure_ctl(ses_plugin_t *sp, ses_node_t *np, const char *op,
+ nvlist_t *nvl)
+{
+ if (strcmp(op, SES_CTL_OP_SETPROP) == 0)
+ return (ses2_setprop(sp, np, enc_props, nvl));
+ else if (strcmp(op, SES_CTL_OP_DL_UCODE) == 0)
+ return (enc_do_ucode(sp, np, nvl));
+
+ return (0);
+}
+
+int
+ses2_enclosure_setdef(ses_node_t *np, ses2_diag_page_t page, void *data)
+{
+ nvlist_t *props = ses_node_props(np);
+ uint64_t type;
+
+ VERIFY(nvlist_lookup_uint64(props, SES_PROP_ELEMENT_TYPE, &type) == 0);
+
+ if (type == SES_ET_ENCLOSURE &&
+ enc_setdef_one(np, page, data) != 0)
+ return (-1);
+
+ return (0);
+}
diff --git a/usr/src/lib/scsi/plugins/ses/ses2/common/ses2_impl.h b/usr/src/lib/scsi/plugins/ses/ses2/common/ses2_impl.h
new file mode 100644
index 0000000000..11f6d5739a
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/ses2/common/ses2_impl.h
@@ -0,0 +1,1549 @@
+/*
+ * 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.
+ */
+
+#ifndef _PLUGIN_SES_IMPL_H
+#define _PLUGIN_SES_IMPL_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <sys/sysmacros.h>
+#include <sys/scsi/impl/uscsi.h>
+#include <sys/scsi/generic/commands.h>
+#include <sys/scsi/impl/spc3_types.h>
+#include <sys/ccompile.h>
+#include <stdarg.h>
+#include <libnvpair.h>
+
+#include <scsi/libscsi.h>
+#include <scsi/libses_plugin.h>
+
+#pragma pack(1)
+
+/*
+ * Generic IO timeout in seconds, from <sys/scsi/targets/ses.h>.
+ */
+#define SES2_TIMEOUT 60
+
+/*
+ * SES-2 Enclosure Descriptor Header (Table 8, 6.1.2.2)
+ */
+typedef struct ses2_ed_hdr_impl {
+ DECL_BITFIELD4(
+ sehi_n_esps :3,
+ _reserved1 :1,
+ sehi_rel_esp_id :3,
+ _reserved2 :1);
+ uint8_t sehi_subenclosure_id;
+ uint8_t sehi_n_etd_hdrs;
+ uint8_t sehi_ed_len;
+} ses2_ed_hdr_impl_t;
+
+/*
+ * SES-2 Enclosure Descriptor (Table 8, 6.1.2.2)
+ */
+typedef struct ses2_ed_impl {
+ ses2_ed_hdr_impl_t st_hdr;
+ spc3_naa_id_8_impl_t st_logical_id;
+ char st_vendor_id[8];
+ char st_product_id[16];
+ char st_product_revision[4];
+ uint8_t st_priv[1];
+} ses2_ed_impl_t;
+
+/*
+ * SES-2 Type Descriptor Header (Table 9, 6.1.2.3)
+ */
+typedef struct ses2_td_hdr_impl {
+ uint8_t sthi_element_type;
+ uint8_t sthi_max_elements;
+ uint8_t sthi_subenclosure_id;
+ uint8_t sthi_text_len;
+} ses2_td_hdr_impl_t;
+
+/*
+ * SES-2 Configuration diagnostic page (Table 7, 6.1.2.1)
+ */
+typedef struct ses2_config_page_impl {
+ uint8_t scpi_page_code;
+ uint8_t scpi_n_subenclosures;
+ uint16_t scpi_page_length;
+ uint32_t scpi_generation_code;
+ uint8_t scpi_data[1];
+} ses2_config_page_impl_t;
+
+/*
+ * Logically we should be able to use 4 or 8 bytes for a minimum allocation;
+ * however, it seems at least some devices will fail the request in that case.
+ */
+#define SES2_MIN_DIAGPAGE_ALLOC 512
+
+/*
+ * SES-2 Element Control and Overall Control fields (Table 59, 7.2.2)
+ */
+typedef struct ses2_cmn_elem_ctl_impl {
+ DECL_BITFIELD5(
+ _reserved1 :4,
+ seci_rst_swap :1,
+ seci_disable :1,
+ seci_prdfail :1,
+ seci_select :1);
+} ses2_cmn_elem_ctl_impl_t;
+
+typedef struct ses2_elem_ctl_impl {
+ ses2_cmn_elem_ctl_impl_t seci_common;
+ uint8_t seci_data[3];
+} ses2_elem_ctl_impl_t;
+
+/*
+ * SES-2 Element Status and Overall Status fields (Table 60, 7.2.3)
+ */
+typedef struct ses2_cmn_elem_status_impl {
+ DECL_BITFIELD5(
+ sesi_status_code :4,
+ sesi_swap :1,
+ sesi_disabled :1,
+ sesi_prdfail :1,
+ _reserved1 :1);
+} ses2_cmn_elem_status_impl_t;
+
+typedef struct ses2_elem_status_impl {
+ ses2_cmn_elem_status_impl_t sesi_common;
+ uint8_t sesi_data[3];
+} ses2_elem_status_impl_t;
+
+/*
+ * SES-2 Device element for the Enclosure Control diagnostic page.
+ */
+typedef struct ses2_device_ctl_impl {
+ ses2_cmn_elem_ctl_impl_t sdci_common;
+ uint8_t _reserved1;
+ DECL_BITFIELD8(
+ _reserved2 :1,
+ sdci_rqst_ident :1,
+ sdci_rqst_remove :1,
+ sdci_rqst_insert :1,
+ sdci_rqst_missing :1,
+ _reserved3 :1,
+ sdci_do_not_remove :1,
+ sdci_rqst_active :1);
+ DECL_BITFIELD6(
+ _reserved4 :2,
+ sdci_enable_byp_b :1,
+ sdci_enable_byp_a :1,
+ sdci_device_off :1,
+ sdci_rqst_fault :1,
+ _reserved5 :2);
+} ses2_device_ctl_impl_t;
+
+/*
+ * SES-2 Device element for the Enclosure Status diagnostic page
+ * (Table 64, 7.3.2).
+ */
+typedef struct ses2_device_status_impl {
+ ses2_cmn_elem_status_impl_t sdsi_common;
+ uint8_t sdsi_slot_addr;
+ DECL_BITFIELD8(
+ sdsi_report :1,
+ sdsi_ident :1,
+ sdsi_rmv :1,
+ sdsi_ready_to_insert :1,
+ sdsi_enclosure_bypassed_b :1,
+ sdsi_enclosure_bypassed_a :1,
+ sdsi_do_not_remove :1,
+ sdsi_app_client_bypassed_a :1);
+ DECL_BITFIELD8(
+ sdsi_device_bypassed_b :1,
+ sdsi_device_bypassed_a :1,
+ sdsi_bypassed_b :1,
+ sdsi_bypassed_a :1,
+ sdsi_device_off :1,
+ sdsi_fault_reqstd :1,
+ sdsi_fault_sensed :1,
+ sdsi_app_client_bypassed_b :1);
+} ses2_device_status_impl_t;
+
+typedef struct ses2_array_device_ctl_impl {
+ ses2_cmn_elem_ctl_impl_t sadci_common;
+ DECL_BITFIELD8(
+ sadci_rqst_rr_abort :1,
+ sadci_rqst_rebuild :1,
+ sadci_rqst_in_failed_array :1,
+ sadci_rqst_in_crit_array :1,
+ sadci_rqst_cons_check :1,
+ sadci_rqst_hot_spare :1,
+ sadci_rqst_rsvd_device :1,
+ sadci_rqst_ok :1);
+ DECL_BITFIELD8(
+ _reserved1 :1,
+ sadci_rqst_ident :1,
+ sadci_rqst_remove :1,
+ sadci_rqst_insert :1,
+ sadci_rqst_missing :1,
+ _reserved2 :1,
+ sadci_do_not_remove :1,
+ sadci_rqst_active :1);
+ DECL_BITFIELD6(
+ _reserved3 :2,
+ sadci_enable_byp_b :1,
+ sadci_enable_byp_a :1,
+ sadci_device_off :1,
+ sadci_rqst_fault :1,
+ _reserved4 :2);
+} ses2_array_device_ctl_impl_t;
+
+/*
+ * SES-2 Array Device element for the Enclosure Status diagnostic page
+ * (Table 66, 7.3.3)
+ */
+typedef struct ses2_array_device_status_impl {
+ ses2_cmn_elem_status_impl_t sadsi_common;
+ DECL_BITFIELD8(
+ sadsi_rr_abort :1,
+ sadsi_rebuild :1,
+ sadsi_in_failed_array :1,
+ sadsi_in_crit_array :1,
+ sadsi_cons_chk :1,
+ sadsi_hot_spare :1,
+ sadsi_rsvd_device :1,
+ sadsi_ok :1);
+ DECL_BITFIELD8(
+ sadsi_report :1,
+ sadsi_ident :1,
+ sadsi_rmv :1,
+ sadsi_ready_to_insert :1,
+ sadsi_enclosure_bypassed_b :1,
+ sadsi_enclosure_bypassed_a :1,
+ sadsi_do_not_remove :1,
+ sadsi_app_client_bypassed_a :1);
+ DECL_BITFIELD8(
+ sadsi_device_bypassed_b :1,
+ sadsi_device_bypassed_a :1,
+ sadsi_bypassed_b :1,
+ sadsi_bypassed_a :1,
+ sadsi_device_off :1,
+ sadsi_fault_reqstd :1,
+ sadsi_fault_sensed :1,
+ sadsi_app_client_bypassed_b :1);
+} ses2_array_device_status_impl_t;
+
+/*
+ * SES-2 Power Supply element for control-type diagnostic pages (T68).
+ */
+typedef struct ses2_psu_ctl_impl {
+ ses2_cmn_elem_ctl_impl_t spci_common;
+ DECL_BITFIELD2(
+ _reserved1 :7,
+ spci_rqst_ident :1);
+ uint8_t _reserved2;
+ DECL_BITFIELD4(
+ _reserved3 :5,
+ spci_rqst_on :1,
+ spci_rqst_fail :1,
+ _reserved4 :1);
+} ses2_psu_ctl_impl_t;
+
+/*
+ * SES-2 Power Supply element for status-type diagnostic pages (Table 69, 7.3.4)
+ */
+typedef struct ses2_psu_status_impl {
+ ses2_cmn_elem_status_impl_t spsi_common;
+ DECL_BITFIELD2(
+ _reserved1 :7,
+ spsi_ident :1);
+ DECL_BITFIELD5(
+ _reserved2 :1,
+ spsi_dc_over_current :1,
+ spsi_dc_under_voltage :1,
+ spsi_dc_over_voltage :1,
+ _reserved3 :4);
+ DECL_BITFIELD8(
+ spsi_dc_fail :1,
+ spsi_ac_fail :1,
+ spsi_temp_warn :1,
+ spsi_overtmp_fail :1,
+ spsi_off :1,
+ spsi_rqsted_on :1,
+ spsi_fail :1,
+ spsi_hot_swap :1);
+} ses2_psu_status_impl_t;
+
+/*
+ * SES-2 Cooling element for control-type diagnostic pages (Table 70).
+ */
+typedef struct ses2_cooling_ctl_impl {
+ ses2_cmn_elem_ctl_impl_t scci_common;
+ DECL_BITFIELD2(
+ _reserved1 :7,
+ scci_rqst_ident :1);
+ uint8_t _reserved2;
+ DECL_BITFIELD5(
+ scci_requested_speed_code :3,
+ _reserved3 :2,
+ scci_rqst_on :1,
+ scci_rqst_fail :1,
+ _reserved4 :1);
+} ses2_cooling_ctl_impl_t;
+
+/*
+ * SES-2 Cooling element for status-type diagnostic pages (Table 71, 7.3.5)
+ */
+typedef struct ses2_cooling_status_impl {
+ ses2_cmn_elem_status_impl_t scsi_common;
+ DECL_BITFIELD3(
+ scsi_fan_speed_ms3 :3,
+ _reserved1 :4,
+ scsi_ident :1);
+ uint8_t scsi_fan_speed_lsb;
+ DECL_BITFIELD6(
+ scsi_actual_speed_code :3,
+ _reserved2 :1,
+ scsi_off :1,
+ scsi_requested_on :1,
+ scsi_fail :1,
+ _reserved3 :1);
+} ses2_cooling_status_impl_t;
+
+/*
+ * The fan_speed fields are multiplied by this factor to obtain the actual
+ * number of RPMs.
+ */
+#define SES2_ES_COOLING_SPEED_FACTOR 10
+
+#define SES2_ES_COOLING_ST_FAN_SPEED(csip) \
+ (((((uint16_t)(csip)->scsi_fan_speed_ms3) << 8) | \
+ ((uint16_t)(csip)->scsi_fan_speed_lsb)) * \
+ (uint16_t)SES2_ES_COOLING_SPEED_FACTOR)
+
+/*
+ * SES-2 Temperature Sensor element for control-type diagnostic pages (T74).
+ */
+typedef struct ses2_temp_ctl_impl {
+ ses2_cmn_elem_ctl_impl_t stci_common;
+ DECL_BITFIELD3(
+ _reserved1 :6,
+ stci_rqst_fail :1,
+ stci_rqst_ident :1);
+ uint8_t _reserved2[2];
+} ses2_temp_ctl_impl_t;
+
+/*
+ * SES-2 Temperature Sensor element for status-type diagnostic pages
+ * (Table 74, 7.3.6)
+ */
+typedef struct ses2_temp_status_impl {
+ ses2_cmn_elem_status_impl_t stsi_common;
+ DECL_BITFIELD3(
+ _reserved1 :6,
+ stsi_fail :1,
+ stsi_ident :1);
+ uint8_t stsi_temperature;
+ DECL_BITFIELD4(
+ stsi_ut_warn :1,
+ stsi_ut_fail :1,
+ stsi_ot_warn :1,
+ stsi_ot_fail :1);
+} ses2_temp_status_impl_t;
+
+#define SES2_ES_TEMP_OFFSET (-20)
+
+#define SES2_ES_TEMP_ST_TEMPERATURE(tsip) \
+ ((tsip)->stsi_temperature + SES2_ES_TEMP_OFFSET)
+
+/*
+ * SES-2 Door Lock element for control-type diagnostic pages (T76).
+ */
+typedef struct ses2_lock_ctl_impl {
+ ses2_cmn_elem_ctl_impl_t slci_common;
+ DECL_BITFIELD3(
+ _reserved1 :6,
+ slci_rqst_fail :1,
+ slci_rqst_ident :1);
+ uint8_t _reserved2;
+ DECL_BITFIELD2(
+ slci_unlock :1,
+ _reserved3 :7);
+} ses2_lock_ctl_impl_t;
+
+/*
+ * SES-2 Door Lock element for status-type diagnostic pages (Table 77, 7.3.7)
+ */
+typedef struct ses2_lock_status_impl {
+ ses2_cmn_elem_status_impl_t slsi_common;
+ DECL_BITFIELD3(
+ _reserved1 :6,
+ slsi_fail :1,
+ slsi_ident :1);
+ uint8_t _reserved2;
+ DECL_BITFIELD2(
+ slsi_unlocked :1,
+ _reserved3 :7);
+} ses2_lock_status_impl_t;
+
+/*
+ * SES-2 Audible Alarm element for control-type diagnostic pages (T78).
+ */
+typedef struct ses2_alarm_ctl_impl {
+ ses2_cmn_elem_ctl_impl_t saci_common;
+ DECL_BITFIELD3(
+ _reserved1 :6,
+ saci_rqst_fail :1,
+ saci_rqst_ident :1);
+ uint8_t _reserved2;
+ DECL_BITFIELD8(
+ saci_unrecov :1,
+ saci_crit :1,
+ saci_noncrit :1,
+ saci_info :1,
+ saci_set_remind :1,
+ _reserved3 :1,
+ saci_set_mute :1,
+ _reserved4 :1);
+} ses2_alarm_ctl_impl_t;
+
+/*
+ * SES-2 Audible Alarm element for status-type diagnostic pages
+ * (Table 79, 7.3.8)
+ */
+typedef struct ses2_alarm_status_impl {
+ ses2_cmn_elem_status_impl_t sasi_common;
+ DECL_BITFIELD3(
+ _reserved1 :6,
+ sasi_fail :1,
+ sasi_ident :1);
+ uint8_t _reserved2;
+ DECL_BITFIELD8(
+ sasi_unrecov :1,
+ sasi_crit :1,
+ sasi_noncrit :1,
+ sasi_info :1,
+ sasi_remind :1,
+ _reserved3 :1,
+ sasi_muted :1,
+ sasi_rqst_mute :1);
+} ses2_alarm_status_impl_t;
+
+/*
+ * SES-2 Enclosure Services Controller Electronics element for control-type
+ * diagnostic pages (Table 80, 7.3.9).
+ */
+typedef struct ses2_controller_ctl_impl {
+ ses2_cmn_elem_ctl_impl_t scci_common;
+ DECL_BITFIELD3(
+ _reserved1 :6,
+ scci_rqst_fail :1,
+ scci_rqst_ident :1);
+ DECL_BITFIELD2(
+ scci_select_element :1,
+ _reserved2 :7);
+ uint8_t _reserved3;
+} ses2_controller_ctl_impl_t;
+
+/*
+ * SES-2 Enclosure Services Controller Electronics element for status-type
+ * diagnostic pages (Table 81, 7.3.9),
+ */
+typedef struct ses2_controller_status_impl {
+ ses2_cmn_elem_status_impl_t scsi_common;
+ DECL_BITFIELD3(
+ _reserved1 :6,
+ scsi_fail :1,
+ scsi_ident :1);
+ DECL_BITFIELD2(
+ scsi_report :1,
+ _reserved2 :7);
+ DECL_BITFIELD2(
+ _reserved3 :7,
+ scsi_hot_swap :1);
+} ses2_controller_status_impl_t;
+
+/*
+ * SES-2 SCC Controller Electronics element for control-type diagnostic pages
+ * (Table 82, 7.3.10).
+ */
+typedef struct ses2_scc_ctl_impl {
+ ses2_cmn_elem_ctl_impl_t ssci_common;
+ DECL_BITFIELD3(
+ _reserved1 :6,
+ ssci_rqst_fail :1,
+ ssci_rqst_ident :1);
+ uint8_t _reserved2[2];
+} ses2_scc_ctl_impl_t;
+
+/*
+ * SES-2 SCC Controller Electronics element for status-type diagnostic pages
+ * (Table 83, 7.3.10)
+ */
+typedef struct ses2_scc_status_impl {
+ ses2_cmn_elem_status_impl_t sss_common;
+ DECL_BITFIELD3(
+ _reserved1 :6,
+ sss_fail :1,
+ sss_ident :1);
+ DECL_BITFIELD2(
+ sss_report :1,
+ _reserved2 :7);
+ uint8_t _reserved3;
+} ses2_scc_status_impl_t;
+
+/*
+ * SES-2 Nonvolatile Cache element for control-type diagnostic pages
+ * (Table 84, 7.3.11).
+ */
+typedef struct ses2_nvcache_ctl_impl {
+ ses2_cmn_elem_ctl_impl_t snci_common;
+ DECL_BITFIELD3(
+ _reserved1 :6,
+ snci_rqst_fail :1,
+ snci_rqst_ident :1);
+ uint8_t _reserved2[2];
+} ses2_nvcache_ctl_impl_t;
+
+/*
+ * SES-2 Nonvolatile Cache element for status-type diagnostic pages (Table 85,
+ * 7.3.11)
+ */
+typedef struct ses2_nvcache_status_impl {
+ ses2_cmn_elem_status_impl_t snsi_common;
+ DECL_BITFIELD4(
+ snsi_size_multiplier :2,
+ _reserved1 :4,
+ snsi_fail :1,
+ snsi_ident :1);
+ uint16_t snsi_nvcache_size;
+} ses2_nvcache_status_impl_t;
+
+/*
+ * Ibid., Table 86 defines the size multipliers as follows:
+ *
+ * 00b - bytes
+ * 01b - 1<<10 bytes
+ * 10b - 1<<20 bytes
+ * 11b - 1<<30 bytes
+ *
+ * We will calculate the actual size in bytes by doing
+ *
+ * nvcache_size << (SES2_NVCACHE_SHIFT * multiplier)
+ */
+#define SES2_NVCACHE_SHIFT 10
+#define SES2_NVCACHE_SIZE(nsip) \
+ ((uint64_t)SCSI_READ16(&(nsip)->snsi_nvcache_size) << \
+ (SES2_NVCACHE_SHIFT * (nsip)->snsi_size_multiplier))
+
+/*
+ * SES-2 Invalid Operation Reason element for status-type diagnostic pages
+ * (Table 88, 7.3.12)
+ */
+typedef struct ses2_invop_reason_status_impl {
+ ses2_cmn_elem_status_impl_t sirsi_common;
+ DECL_BITFIELD2(
+ sirsi_priv_ms6 :6,
+ sirsi_invop_type :2);
+ uint8_t sirsi_priv[2];
+} ses2_invop_reason_status_impl_t;
+
+/*
+ * Ibid., Invop Type values (Table 89)
+ */
+typedef enum ses2_invop_type {
+ SES2_INVOP_SEND_PAGE_CODE = 0x0,
+ SES2_INVOP_SEND_PAGE_FORMAT = 0x1,
+ SES2_INVOP_VENDOR_SPECIFIC = 0x3
+} ses2_invop_type_t;
+
+/*
+ * Ibid., Invalid Operation Reason element for status-type diagnostic pages
+ * with Invop Type of 00b (Table 90)
+ */
+typedef struct ses2_invop_code_status_impl {
+ ses2_cmn_elem_status_impl_t sicsi_common;
+ DECL_BITFIELD3(
+ sicsi_page_not_supported :1,
+ _reserved1 :5,
+ sicsi_invop_type :2);
+ uint8_t _reserved2[2];
+} ses2_invop_code_status_impl_t;
+
+/*
+ * Ibid., Invalid Operation Reason element for status-type diagnostic pages
+ * with Invop Type of 01b (Table 91)
+ */
+typedef struct ses2_invop_format_status_impl {
+ ses2_cmn_elem_status_impl_t sifsi_common;
+ DECL_BITFIELD3(
+ sifsi_bit_number :3,
+ _reserved1 :3,
+ sifsi_invop_type :2);
+ uint16_t sifsi_byte_offset[2];
+} ses2_invop_format_status_impl_t;
+
+/*
+ * SES-2 Uninterruptible Power Supply element for control-type diagnostic
+ * pages (Table 93, 7.3.13)
+ */
+typedef struct ses2_ups_ctl_impl {
+ ses2_cmn_elem_ctl_impl_t suci_common;
+ uint8_t _reserved1[2];
+ DECL_BITFIELD3(
+ _reserved2 :6,
+ suci_rqst_fail :1,
+ suci_rqst_ident :1);
+} ses2_ups_ctl_impl_t;
+
+/*
+ * SES-2 Uninterruptible Power Supply element for status-type diagnostic pages
+ * (Table 94, 7.3.13)
+ */
+typedef struct ses2_ups_status_impl {
+ ses2_cmn_elem_status_impl_t susi_common;
+ uint8_t susi_battery_status; /* Time remaining in minutes */
+ DECL_BITFIELD8(
+ susi_intf_fail :1,
+ susi_warn :1,
+ susi_ups_fail :1,
+ susi_dc_fail :1,
+ susi_ac_fail :1,
+ susi_ac_qual :1,
+ susi_ac_hi :1,
+ susi_ac_lo :1);
+ DECL_BITFIELD5(
+ susi_bpf :1,
+ susi_batt_fail :1,
+ _reserved1 :4,
+ susi_fail :1,
+ susi_ident :1);
+} ses2_ups_status_impl_t;
+
+/*
+ * SES-2 Display element for control-type diagnostic pages (Table 95, 7.3.14)
+ */
+typedef struct ses2_display_ctl_impl {
+ ses2_cmn_elem_ctl_impl_t sdci_common;
+ DECL_BITFIELD4(
+ sdci_display_mode :2,
+ _reserved1 :4,
+ sdci_rqst_fail :1,
+ sdci_rqst_ident :1);
+ uint16_t sdci_display_character;
+} ses2_display_ctl_impl_t;
+
+/*
+ * SES-2 Display element for status-type diagnostic pages (Table 97, 7.3.14)
+ */
+typedef struct ses2_display_status_impl {
+ ses2_cmn_elem_status_impl_t sdsi_common;
+ DECL_BITFIELD4(
+ sdsi_display_mode_status :2,
+ _reserved1 :3,
+ sdsi_fail :1,
+ sdsi_ident :1);
+ uint16_t sdsi_display_character_status;
+} ses2_display_status_impl_t;
+
+/*
+ * SES-2 Key Pad Entry element for control-type diagnostic pages (Table 99).
+ */
+typedef struct ses2_keypad_ctl_impl {
+ ses2_cmn_elem_ctl_impl_t skci_common;
+ DECL_BITFIELD3(
+ _reserved1 :6,
+ skci_rqst_fail :1,
+ skci_rqst_ident :1);
+ uint8_t _reserved2[2];
+} ses2_keypad_ctl_impl_t;
+
+/*
+ * SES-2 Key Pad Entry element for status-type diagnostic pages (Table 100,
+ * 7.3.15)
+ */
+typedef struct ses2_keypad_status_impl {
+ ses2_cmn_elem_status_impl_t sksi_common;
+ DECL_BITFIELD3(
+ _reserved1 :6,
+ sksi_fail :1,
+ sksi_ident :1);
+ uint8_t _reserved2[2];
+} ses2_keypad_status_impl_t;
+
+/*
+ * SES-2 Enclosure element for control-type diagnostic pages (Table 101).
+ */
+typedef struct ses2_enclosure_ctl_impl {
+ ses2_cmn_elem_ctl_impl_t seci_common;
+ DECL_BITFIELD2(
+ _reserved1 :7,
+ seci_rqst_ident :1);
+ DECL_BITFIELD2(
+ seci_power_cycle_delay :6,
+ seci_power_cycle_request :2);
+ DECL_BITFIELD3(
+ seci_request_warning :1,
+ seci_request_failure :1,
+ seci_power_off_duration :6);
+} ses2_enclosure_ctl_impl_t;
+
+/*
+ * SES-2 Enclosure element for status-type diagnostic pages (Table 101, 7.3.16)
+ */
+typedef struct ses2_enclosure_status_impl {
+ ses2_cmn_elem_status_impl_t sesi_common;
+ DECL_BITFIELD2(
+ _reserved1 :7,
+ sesi_ident :1);
+ DECL_BITFIELD3(
+ sesi_warning_indication :1,
+ sesi_failure_indication :1,
+ sesi_power_delay :6);
+ DECL_BITFIELD3(
+ sesi_warning_requested :1,
+ sesi_failure_requested :1,
+ sesi_power_duration :6);
+} ses2_enclosure_status_impl_t;
+
+/*
+ * SES-2 SCSI Port/Transceiver element for control-type diagnostic pages (T103)
+ */
+typedef struct ses2_port_ctl_impl {
+ ses2_cmn_elem_ctl_impl_t spci_common;
+ DECL_BITFIELD3(
+ _reserved1 :6,
+ spci_rqst_fail :1,
+ spci_rqst_ident :1);
+ uint8_t _reserved2;
+ DECL_BITFIELD3(
+ _reserved3 :4,
+ spci_disable :1,
+ _reserved4 :3);
+} ses2_port_ctl_impl_t;
+
+/*
+ * SES-2 SCSI Port/Transceiver element for status-type diagnostic pages
+ * (Table 104, 7.3.17)
+ */
+typedef struct ses2_port_status_impl {
+ ses2_cmn_elem_status_impl_t spsi_common;
+ DECL_BITFIELD3(
+ _reserved1 :6,
+ spsi_fail :1,
+ spsi_ident :1);
+ DECL_BITFIELD2(
+ spsi_report :1,
+ _reserved2 :7);
+ DECL_BITFIELD5(
+ spsi_xmit_fail :1,
+ spsi_lol :1,
+ _reserved3 :2,
+ spsi_disabled :1,
+ _reserved4 :3);
+} ses2_port_status_impl_t;
+
+/*
+ * SES-2 Language element for control-type diagnostic pages (T105)
+ */
+typedef struct ses2_lang_ctl_impl {
+ ses2_cmn_elem_ctl_impl_t slci_common;
+ DECL_BITFIELD2(
+ _reserved1 :7,
+ slci_rqst_ident :1);
+ uint16_t slci_language_code;
+} ses2_lang_ctl_impl_t;
+
+/*
+ * SES-2 Language element for status-type diagnostic pages (Table 105, 7.3.18)
+ */
+typedef struct ses2_lang_status_impl {
+ ses2_cmn_elem_status_impl_t slsi_common;
+ DECL_BITFIELD2(
+ _reserved1 :7,
+ slsi_ident :1);
+ uint16_t slsi_language_code;
+} ses2_lang_status_impl_t;
+
+/*
+ * SES-2 Communication Port element for control-type diagnostic pages
+ * (Table 107, 7.3.19).
+ */
+typedef struct ses2_comm_ctl_impl {
+ ses2_cmn_elem_ctl_impl_t scci_common;
+ DECL_BITFIELD3(
+ _reserved1 :6,
+ scci_rqst_fail :1,
+ scci_rqst_ident :1);
+ uint8_t _reserved2;
+ DECL_BITFIELD2(
+ scci_disable :1,
+ _reserved3 :7);
+} ses2_comm_ctl_impl_t;
+
+/*
+ * SES-2 Communication Port element for status-type diagnostic pages
+ * (Table 108, 7.3.19)
+ */
+typedef struct ses2_comm_status_impl {
+ ses2_cmn_elem_status_impl_t scsi_common;
+ DECL_BITFIELD3(
+ _reserved1 :6,
+ scsi_fail :1,
+ scsi_ident :1);
+ uint8_t _reserved2;
+ DECL_BITFIELD2(
+ scsi_disabled :1,
+ _reserved3 :7);
+} ses2_comm_status_impl_t;
+
+/*
+ * SES-2 Voltage Sensor element for control-type diagnostic pages
+ * (Table 109, 7.3.20).
+ */
+typedef struct ses2_voltage_ctl_impl {
+ ses2_cmn_elem_ctl_impl_t svci_common;
+ DECL_BITFIELD3(
+ _reserved1 :6,
+ svci_rqst_fail :1,
+ svci_rqst_ident :1);
+ uint8_t _reserved2[2];
+} ses2_voltage_ctl_impl_t;
+
+/*
+ * SES-2 Voltage Sensor element for status-type diagnostic pages
+ * (Table 110, 7.3.20).
+ */
+typedef struct ses2_voltage_status_impl {
+ ses2_cmn_elem_status_impl_t svsi_common;
+ DECL_BITFIELD7(
+ svsi_crit_under :1,
+ svsi_crit_over :1,
+ svsi_warn_under :1,
+ svsi_warn_over :1,
+ _reserved1 :2,
+ svsi_fail :1,
+ svsi_ident :1);
+ uint16_t svsi_voltage;
+} ses2_voltage_status_impl_t;
+
+/*
+ * Ibid. defines the svsi_voltage field as a 16-bit signed 2's complement
+ * integer, represented in units of 10 mV. AC voltages are RMS.
+ */
+#define SES2_VOLTAGE_MULTIPLIER (0.01)
+#define SES2_VOLTAGE(vsip) \
+ (SCSI_READ16(&(vsip)->svsi_voltage) * SES2_VOLTAGE_MULTIPLIER)
+
+/*
+ * SES-2 Current Sensor element for control-type diagnostic pages
+ * (Table 111, 7.3.21).
+ */
+typedef struct ses2_current_ctl_impl {
+ ses2_cmn_elem_ctl_impl_t scci_common;
+ DECL_BITFIELD3(
+ _reserved1 :6,
+ scci_rqst_fail :1,
+ scci_rqst_ident :1);
+ uint8_t _reserved2[2];
+} ses2_current_ctl_impl_t;
+
+/*
+ * SES-2 Current Sensor element for status-type diagnostic pages
+ * (Table 112, 7.3.21)
+ */
+typedef struct ses2_current_status_impl {
+ ses2_cmn_elem_status_impl_t scsi_common;
+ DECL_BITFIELD7(
+ _reserved1 :1,
+ scsi_crit_over :1,
+ _reserved2 :1,
+ scsi_warn_over :1,
+ _reserved3 :2,
+ scsi_fail :1,
+ scsi_ident :1);
+ uint16_t scsi_current;
+} ses2_current_status_impl_t;
+
+/*
+ * Ibid. defines the scsi_voltage field in the same way as for voltage above.
+ * Units here are 10 mA. AC amperages are RMS.
+ */
+#define SES2_CURRENT_MULTIPLIER (0.01)
+#define SES2_CURRENT(csip) \
+ (SCSI_READ16(&(csip)->scsi_current) * SES2_CURRENT_MULTIPLIER)
+
+/*
+ * SES-2 SCSI Target Port element for control-type diagnostic pages
+ * (Table 113, 7.3.22), SCSI Initiator Port element for control-type
+ * diagnostic pages (Table 115, 7.3.23).
+ */
+typedef struct ses2_itp_ctl_impl {
+ ses2_cmn_elem_ctl_impl_t sici_common;
+ DECL_BITFIELD3(
+ _reserved1 :6,
+ sici_rqst_fail :1,
+ sici_rqst_ident :1);
+ uint8_t _reserved2;
+ DECL_BITFIELD2(
+ sici_enable :1,
+ _reserved3 :7);
+} ses2_itp_ctl_impl_t;
+
+/*
+ * SES-2 SCSI Target Port element for status-type diagnostic pages (Table 114,
+ * 7.3.22), SCSI Initiator Port element for status-type diagnostic pages
+ * (Table 116, 7.3.23)
+ */
+typedef struct ses2_itp_status_impl {
+ ses2_cmn_elem_status_impl_t sisi_common;
+ DECL_BITFIELD3(
+ _reserved1 :6,
+ sisi_fail :1,
+ sisi_ident :1);
+ DECL_BITFIELD2(
+ sisi_report :1,
+ _reserved2 :7);
+ DECL_BITFIELD2(
+ sisi_enabled :1,
+ _reserved3 :7);
+} ses2_itp_status_impl_t;
+
+/*
+ * SES-2 Simple Subenclosure element for control-type diagnostic pages
+ * (Table 117, 7.3.24).
+ */
+typedef struct ses2_ss_ctl_impl {
+ ses2_cmn_elem_ctl_impl_t ssci_common;
+ DECL_BITFIELD3(
+ _reserved1 :6,
+ ssci_rqst_fail :1,
+ ssci_rqst_ident :1);
+ uint8_t _reserved2[2];
+} ses2_ss_ctl_impl_t;
+
+/*
+ * SES-2 Simple Subenclosure element for status-type diagnostic pages
+ * (Table 117, 7.3.24)
+ */
+typedef struct ses2_ss_status_impl {
+ ses2_cmn_elem_status_impl_t sss_common;
+ DECL_BITFIELD3(
+ _reserved1 :6,
+ sss_fail :1,
+ sss_ident :1);
+ uint8_t _reserved2;
+ uint8_t sss_short_status;
+} ses2_ss_status_impl_t;
+
+/*
+ * SES-2 SAS Expander element for control-type diagnostic pages
+ * (Table 119, 7.3.25).
+ */
+typedef struct ses2_expander_ctl_impl {
+ ses2_cmn_elem_ctl_impl_t seci_common;
+ DECL_BITFIELD3(
+ _reserved1 :6,
+ seci_rqst_fail :1,
+ seci_rqst_ident :1);
+ uint8_t _reserved2[2];
+} ses2_expander_ctl_impl_t;
+
+/*
+ * SES-2 SAS Expander element for status-type diagnostic pages (Table 120,
+ * 7.3.25)
+ */
+typedef struct ses2_expander_status_impl {
+ ses2_cmn_elem_status_impl_t sesi_common;
+ DECL_BITFIELD3(
+ _reserved1 :6,
+ sesi_fail :1,
+ sesi_ident :1);
+ uint8_t _reserved2[2];
+} ses2_expander_status_impl_t;
+
+/*
+ * SES-2 SAS Connector element for control-type diagnostic pages (Table 121,
+ * 7.3.26).
+ */
+typedef struct ses2_sasconn_ctl_impl {
+ ses2_cmn_elem_ctl_impl_t ssci_common;
+ DECL_BITFIELD2(
+ _reserved1 :7,
+ ssci_rqst_ident :1);
+ uint8_t _reserved2;
+ DECL_BITFIELD3(
+ _reserved3 :6,
+ ssci_rqst_fail :1,
+ _reserved4 :1);
+} ses2_sasconn_ctl_impl_t;
+
+/*
+ * SES-2 SAS Connector element for status-type diagnostic pages (Table 122,
+ * 7.3.26)
+ */
+typedef struct ses2_sasconn_status_impl {
+ ses2_cmn_elem_status_impl_t sss_common;
+ DECL_BITFIELD2(
+ sss_connector_type :7,
+ sss_ident :1);
+ uint8_t sss_connector_physical_link;
+ DECL_BITFIELD3(
+ _reserved1 :6,
+ sss_fail :1,
+ _reserved2 :1);
+} ses2_sasconn_status_impl_t;
+
+/*
+ * SES-2 Enclosure Control diagnostic page (Table 10, 6.1.3)
+ */
+typedef struct ses2_control_page_impl {
+ uint8_t scpi_page_code;
+ DECL_BITFIELD5(
+ scpi_unrecov :1,
+ scpi_crit :1,
+ scpi_noncrit :1,
+ scpi_info :1,
+ _reserved1 :4);
+ uint16_t scpi_page_length;
+ uint32_t scpi_generation_code;
+ ses2_elem_ctl_impl_t scpi_data[1];
+} ses2_control_page_impl_t;
+
+/*
+ * SES-2 Enclosure Status (Table 11, 6.1.4)
+ */
+typedef struct ses2_status_page_impl {
+ uint8_t sspi_page_code;
+ DECL_BITFIELD6(
+ sspi_unrecov :1,
+ sspi_crit :1,
+ sspi_noncrit :1,
+ sspi_info :1,
+ sspi_invop :1,
+ _reserved1 :3);
+ uint16_t sspi_page_length;
+ uint32_t sspi_generation_code;
+ uint8_t sspi_data[1];
+} ses2_status_page_impl_t;
+
+/*
+ * SES-2 Help Text diagnostic page (Table 13, 6.1.5).
+ */
+typedef struct ses2_help_page_impl {
+ uint8_t shpi_page_code;
+ uint8_t _reserved1;
+ uint16_t shpi_page_length;
+ char shpi_help_text[1];
+} ses2_help_page_impl_t;
+
+/*
+ * SES-2 String Out diagnostic page (Table 14, 6.1.6).
+ */
+typedef struct ses2_string_out_page_impl {
+ uint8_t ssopi_page_code;
+ uint8_t _reserved1;
+ uint16_t ssopi_page_length;
+ uint8_t ssopi_data[1];
+} ses2_string_out_page_impl_t;
+
+/*
+ * SES-2 String In diagnostic page (Table 15, 6.1.7).
+ */
+typedef struct ses2_string_in_page_impl {
+ uint8_t ssipi_page_code;
+ uint8_t _reserved1;
+ uint16_t ssipi_page_length;
+ uint8_t ssipi_data[1];
+} ses2_string_in_page_impl_t;
+
+/*
+ * SES-2 Threshold fields - (Table 17, 6.1.8), (Table 19, 6.1.9).
+ */
+typedef struct ses2_threshold_impl {
+ uint8_t sti_high_crit;
+ uint8_t sti_high_warn;
+ uint8_t sti_low_warn;
+ uint8_t sti_low_crit;
+} ses2_threshold_impl_t;
+
+/*
+ * SES-2 Threshold Out diagnostic page (Table 16, 6.1.8).
+ */
+typedef struct ses2_threshold_out_page_impl {
+ uint8_t stopi_page_code;
+ uint8_t _reserved1;
+ uint16_t stopi_page_length;
+ uint32_t stopi_generation_code;
+ ses2_threshold_impl_t stopi_thresholds[1];
+} ses2_threshold_out_page_impl_t;
+
+/*
+ * SES-2 Threshold In diagnostic page (Table 18, 6.1.9).
+ */
+typedef struct ses2_threshold_in_page_impl {
+ uint8_t stipi_page_code;
+ DECL_BITFIELD3(
+ _reserved1 :4,
+ stipi_invop :1,
+ _reserved2 :3);
+ uint16_t stipi_page_length;
+ uint32_t stipi_generation_code;
+ ses2_threshold_impl_t stipi_thresholds[1];
+} ses2_threshold_in_page_impl_t;
+
+/*
+ * SES-2 Element Descriptor diagnostic page (Table 20, 6.1.10).
+ */
+typedef struct ses2_elem_desc_page_impl {
+ uint8_t sedpi_page_code;
+ uint8_t _reserved1;
+ uint16_t sedpi_page_length;
+ uint32_t sedpi_generation_code;
+ uint8_t sedpi_data[1];
+} ses2_elem_desc_page_impl_t;
+
+/*
+ * SES-2 Overall/element descriptor format (Table 22, 6.1.10).
+ */
+typedef struct ses2_elem_descriptor_impl {
+ uint8_t _reserved1[2];
+ uint16_t sedi_descriptor_length;
+ char sedi_descriptor[1];
+} ses2_elem_descriptor_impl_t;
+
+/*
+ * SES-2 Short Enclosure Status diagnostic page (Table 23, 6.1.11).
+ */
+typedef struct ses2_short_status_page_impl {
+ uint8_t ssspi_page_code;
+ uint8_t ssspi_short_status;
+ uint16_t ssspi_page_length;
+} ses2_short_status_page_impl_t;
+
+/*
+ * SES-2 Enclosure Busy diagnostic page (Table 24, 6.1.12).
+ */
+typedef struct ses2_enclosure_busy_page_impl {
+ uint8_t sebpi_page_code;
+ DECL_BITFIELD2(
+ sebpi_busy :1,
+ sebpi_vs_1_1 :7);
+ uint16_t sebpi_page_length;
+} ses2_enclosure_busy_page_impl_t;
+
+/*
+ * SES-2 Additional Element Status diagnostic page (Table 25, 6.1.13).
+ */
+typedef struct ses2_aes_page_impl {
+ uint8_t sapi_page_code;
+ uint8_t _reserved1;
+ uint16_t sapi_page_length;
+ uint32_t sapi_generation_code;
+ uint8_t sapi_data[1];
+} ses2_aes_page_impl_t;
+
+/*
+ * SES-2 Additional Element Status descriptor (EIP == 1) (Table 26, 6.1.13).
+ */
+typedef struct ses2_aes_descr_eip_impl {
+ DECL_BITFIELD4(
+ sadei_protocol_identifier :4,
+ sadei_eip :1,
+ _reserved1 :2,
+ sadei_invalid :1);
+ uint8_t sadei_length;
+ uint8_t _reserved2;
+ uint8_t sadei_element_index;
+ uint8_t sadei_protocol_specific[1];
+} ses2_aes_descr_eip_impl_t;
+
+/*
+ * SES-2 Additional Element Status descriptor (EIP == 0) (Table 27, 6.1.13).
+ */
+typedef struct ses2_aes_descr_impl {
+ DECL_BITFIELD4(
+ sadei_protocol_identifier :4,
+ sadei_eip :1,
+ _reserved1 :2,
+ sadei_invalid :1);
+ uint8_t sadei_length;
+ uint8_t sadei_protocol_specific[1];
+} ses2_aes_descr_impl_t;
+
+/*
+ * SES-2 Port descriptor (Table 30, 6.1.13.2).
+ */
+typedef struct ses2_aes_port_descr_impl {
+ uint8_t sapdi_port_loop_position;
+ uint8_t _reserved1[3];
+ uint8_t sapdi_port_requested_hard_address;
+ uint8_t sapdi_n_port_identifier[3];
+ uint64_t sapdi_n_port_name;
+} ses2_aes_port_descr_impl_t;
+
+/*
+ * SES-2 Additional Element Status descriptor for FC (Table 28, 6.1.13.2).
+ */
+typedef struct ses2_aes_descr_fc_eip_impl {
+ uint8_t sadfi_n_ports;
+ uint8_t _reserved1[2];
+ uint8_t sadfi_bay_number;
+ uint64_t sadfi_node_name;
+ ses2_aes_port_descr_impl_t sadfi_ports[1];
+} ses2_aes_descr_fc_eip_impl_t;
+
+/*
+ * SES-2 Additional Element Status descriptor for FC (EIP == 0)
+ * (Table 29, 6.1.13.2).
+ */
+typedef struct ses2_aes_descr_fc_impl {
+ uint8_t sadfi_n_ports;
+ uint8_t _reserved1;
+ uint64_t sadfi_node_name;
+ ses2_aes_port_descr_impl_t sadfi_ports[1];
+} ses2_aes_descr_fc_impl_t;
+
+/*
+ * SES-2 Additional Element Status descriptor for SAS (Table 31, 6.1.13.3).
+ */
+typedef struct ses2_aes_descr_sas_impl {
+ uint8_t _specific1;
+ DECL_BITFIELD2(
+ _specific2 :6,
+ sadsi_descriptor_type :2);
+ uint8_t _specific3[1];
+} ses2_aes_descr_sas_impl_t;
+
+typedef enum ses2_aes_descr_sas_type {
+ SES2_AESD_SAS_DEVICE = 0,
+ SES2_AESD_SAS_OTHER = 1
+} ses2_aes_descr_sas_type_t;
+
+typedef struct ses2_aes_phy0_descr_impl {
+ DECL_BITFIELD3(
+ _reserved1 :4,
+ sapdi_device_type :3,
+ _reserved2 :1);
+ uint8_t _reserved3;
+ DECL_BITFIELD5(
+ _reserved4 :1,
+ sapdi_smp_initiator_port :1,
+ sapdi_stp_initiator_port :1,
+ sapdi_ssp_initiator_port :1,
+ _reserved5 :4);
+ DECL_BITFIELD6(
+ sapdi_sata_device :1,
+ sapdi_smp_target_port :1,
+ sapdi_stp_target_port :1,
+ sapdi_ssp_target_port :1,
+ _reserved6 :3,
+ sapdi_sata_port_selector :1);
+ uint64_t sapdi_attached_sas_address;
+ uint64_t sapdi_sas_address;
+ uint8_t sapdi_phy_identifier;
+ uint8_t _reserved7[7];
+} ses2_aes_phy0_descr_impl_t;
+
+typedef struct ses2_aes_descr_sas0_eip_impl {
+ uint8_t sadsi_n_phy_descriptors;
+ DECL_BITFIELD3(
+ sadsi_not_all_phys :1,
+ _reserved1 :5,
+ sadsi_descriptor_type :2);
+ uint8_t _reserved2;
+ uint8_t sadsi_bay_number;
+ ses2_aes_phy0_descr_impl_t sadsi_phys[1];
+} ses2_aes_descr_sas0_eip_impl_t;
+
+typedef struct ses2_aes_descr_sas0_impl {
+ uint8_t sadsi_n_phy_descriptors;
+ DECL_BITFIELD3(
+ sadsi_not_all_phys :1,
+ _reserved1 :5,
+ sadsi_descriptor_type :2);
+ ses2_aes_phy0_descr_impl_t sadsi_phys[1];
+} ses2_aes_descr_sas0_impl_t;
+
+/*
+ * SES-2 Additional Element Status for SAS Expander elements
+ * (Table 36, 6.1.13.3.3).
+ */
+typedef struct ses2_aes_exp_phy_descr_impl {
+ uint8_t saepdi_connector_element_index;
+ uint8_t saepdi_other_element_index;
+} ses2_aes_exp_phy_descr_impl_t;
+
+typedef struct ses2_aes_descr_exp_impl {
+ uint8_t sadei_n_exp_phy_descriptors;
+ DECL_BITFIELD2(
+ _reserved1 :6,
+ sadei_descriptor_type :2);
+ uint8_t _reserved2[2];
+ uint64_t sadei_sas_address;
+ ses2_aes_exp_phy_descr_impl_t sadei_phys[1];
+} ses2_aes_descr_exp_impl_t;
+
+/*
+ * SES-2 Additional Element Status for SCSI Initiator/Target Port and
+ * Enclosure Services Controller Electronics elements (Table 38, 6.1.13.3.4).
+ */
+typedef struct ses2_aes_phy1_descr_impl {
+ uint8_t sapdi_phy_identifier;
+ uint8_t _reserved1;
+ uint8_t sapdi_connector_element_index;
+ uint8_t sapdi_other_element_index;
+ uint64_t sapdi_sas_address;
+} ses2_aes_phy1_descr_impl_t;
+
+typedef struct ses2_aes_descr_sas1_impl {
+ uint8_t sadsi_n_phy_descriptors;
+ DECL_BITFIELD2(
+ _reserved1 :6,
+ sadsi_descriptor_type :2);
+ uint8_t _reserved2[2];
+ ses2_aes_phy1_descr_impl_t sadsi_phys[1];
+} ses2_aes_descr_sas1_impl_t;
+
+/*
+ * SES-2 Subenclosure Help Text diagnostic page (Table 40, 6.1.14).
+ */
+typedef struct ses2_subhelp_page_impl {
+ uint8_t sspi_page_code;
+ uint8_t sspi_n_subenclosures;
+ uint16_t sspi_page_length;
+ uint32_t sspi_generation_code;
+ uint8_t sspi_data[1];
+} ses2_subhelp_page_impl_t;
+
+/*
+ * SES-2 Subenclosure help text format (Table 41, 6.1.14).
+ */
+typedef struct ses2_subhelp_text_impl {
+ uint8_t _reserved1;
+ uint8_t ssti_subenclosure_identifier;
+ uint16_t ssti_subenclosure_help_text_length;
+ char ssti_subenclosure_help_text[1];
+} ses2_subhelp_text_impl_t;
+
+#define SES2_SUBHELP_LEN(stip) \
+ ((stip)->ssti_subenclosure_help_text_length + \
+ offsetof(ses2_subhelp_text_impl_t, ssti_subenclosure_help_text[0]))
+/*
+ * SES-2 Subenclosure String Out diagnostic page (Table 42, 6.1.15).
+ */
+typedef struct ses2_substring_out_page_impl {
+ uint8_t ssopi_page_code;
+ uint8_t ssopi_subenclosure_identifier;
+ uint16_t ssopi_page_length;
+ uint32_t ssopi_generation_code;
+ uint8_t ssopi_data[1];
+} ses2_substring_out_page_impl_t;
+
+/*
+ * SES-2 Subenclosure String In diagnostic page (Table 43, 6.1.16).
+ */
+typedef struct ses2_substring_in_page_impl {
+ uint8_t ssipi_page_code;
+ uint8_t ssipi_n_subenclosures;
+ uint16_t ssipi_page_length;
+ uint32_t ssipi_generation_code;
+ uint8_t ssipi_data[1];
+} ses2_substring_in_page_impl_t;
+
+/*
+ * SES-2 Subenclosure string in data format (Table 44, 6.1.16).
+ */
+typedef struct ses2_substring_in_data_impl {
+ uint8_t _reserved1;
+ uint8_t ssidi_subenclosure_identifier;
+ uint16_t ssidi_substring_data_length;
+ uint8_t ssidi_data[1];
+} ses2_substring_in_data_impl_t;
+
+#define SES2_SUBSTR_LEN(sdip) \
+ ((sdip)->ssidi_substring_data_length + \
+ offsetof(ses2_substring_in_data_impl_t, ssidi_data[0]))
+
+/*
+ * SES-2 Supported SES Diagnostic Pages diagnostic page (Table 45, 6.1.17).
+ */
+typedef struct ses2_supported_ses_diag_page_impl {
+ uint8_t sssdpi_page_code;
+ uint8_t _reserved1;
+ uint16_t sssdpi_page_length;
+ uint8_t sssdpi_pages[1];
+} ses2_supported_ses_diag_page_impl_t;
+
+/*
+ * SES-2 Download Microcode Control diagnostic page (Table 46, 6.1.18).
+ */
+typedef struct ses2_ucode_ctl_page_impl {
+ uint8_t sucpi_page_code;
+ uint8_t sucpi_subenclosure_identifier;
+ uint16_t sucpi_page_length;
+ uint32_t sucpi_generation_code;
+ uint8_t sucpi_dl_ucode_mode;
+ uint8_t _reserved1[2];
+ uint8_t sucpi_buffer_id;
+ uint32_t sucpi_buffer_offset;
+ uint32_t sucpi_ucode_image_length;
+ uint32_t sucpi_ucode_data_length;
+ uint8_t sucpi_ucode_data[1];
+} ses2_ucode_ctl_page_impl_t;
+
+/*
+ * SES-2 Download Microcode Status diagnostic page (Table 48-49, 6.1.19).
+ */
+typedef struct ses2_ucode_status_descr_impl {
+ uint8_t _reserved1;
+ uint8_t susdi_subenclosure_identifier;
+ uint8_t susdi_subenclosure_dl_status;
+ uint8_t susdi_subenclosure_dl_addl_status;
+ uint32_t susdi_subenclosure_dl_max_size;
+ uint8_t _reserved2[3];
+ uint8_t susdi_subenclosure_dl_buffer_id;
+ uint32_t susdi_subenclosure_dl_buffer_offset;
+} ses2_ucode_status_descr_impl_t;
+
+typedef struct ses2_ucode_status_page_impl {
+ uint8_t suspi_page_code;
+ uint8_t suspi_n_subenclosures;
+ uint16_t suspi_page_length;
+ uint32_t suspi_generation_code;
+ ses2_ucode_status_descr_impl_t suspi_descriptors[1];
+} ses2_ucode_status_page_impl_t;
+
+/*
+ * SES-2 Subenclosure Nickname Control diagnostic page (Table 51, 6.1.20).
+ */
+typedef struct ses2_subnick_ctl_page_impl {
+ uint8_t sscpi_page_code;
+ uint8_t sspci_subenclosure_identifier;
+ uint16_t sspci_page_length;
+ uint32_t sspci_generation_code;
+ char sspci_subenclosure_nickname[32];
+} ses2_subnick_ctl_page_impl_t;
+
+/*
+ * SES-2 Subenclosure Nickname Status diagnostic page (Table 52-53, 6.1.21).
+ */
+typedef struct ses2_subnick_descr_impl {
+ uint8_t _reserved1;
+ uint8_t ssdi_subenclosure_identifier;
+ uint8_t ssdi_subenclosure_nick_status;
+ uint8_t ssdi_subenclosure_nick_addl_status;
+ uint8_t _reserved2[2];
+ uint16_t ssdi_subenclosure_nick_lang_code;
+ char ssdi_subenclosure_nickname[32];
+} ses2_subnick_descr_impl_t;
+
+typedef struct ses2_subnick_status_page_impl {
+ uint8_t sspsi_page_code;
+ uint8_t sspci_n_subenclosures;
+ uint16_t sspci_page_length;
+ uint32_t sspci_generation_code;
+ ses2_subnick_descr_impl_t sspci_subnicks[1];
+} ses2_subnick_status_page_impl_t;
+
+/*
+ * SES-2 Mode page code for enclosure services devices (Table 57, 6.3.2).
+ */
+typedef struct ses2_esm_mode_page_impl {
+ DECL_BITFIELD3(
+ sempi_page_code :6,
+ _reserved1 :1,
+ sempi_ps :1);
+ uint8_t sempi_page_length;
+ uint8_t _reserved2[3];
+ DECL_BITFIELD2(
+ sempi_enbltc :1,
+ _reserved3 :7);
+ uint16_t sempi_max_task_completion_time;
+} ses2_esm_mode_page_impl_t;
+
+#pragma pack()
+
+extern ses_pagedesc_t ses2_pages[];
+
+extern int ses2_fill_element_node(ses_plugin_t *, ses_node_t *);
+extern int ses2_fill_enclosure_node(ses_plugin_t *, ses_node_t *);
+
+typedef int (*ses2_setprop_f)(ses_plugin_t *, ses_node_t *, ses2_diag_page_t,
+ nvpair_t *);
+
+typedef struct ses2_ctl_prop {
+ const char *scp_name;
+ data_type_t scp_type;
+ ses2_diag_page_t scp_num;
+ ses2_setprop_f scp_setprop;
+} ses2_ctl_prop_t;
+
+typedef int (*ses2_setdef_f)(ses_node_t *, ses2_diag_page_t, void *);
+
+extern int ses2_ctl_common_setprop(ses_plugin_t *sp, ses_node_t *,
+ ses2_diag_page_t, nvpair_t *);
+
+#define SES_COMMON_CTL_PROPS \
+{ \
+ .scp_name = SES_PROP_SWAP, \
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE, \
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS, \
+ .scp_setprop = ses2_ctl_common_setprop \
+}, \
+{ \
+ .scp_name = SES_PROP_DISABLED, \
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE, \
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS, \
+ .scp_setprop = ses2_ctl_common_setprop \
+}, \
+{ \
+ .scp_name = SES_PROP_PRDFAIL, \
+ .scp_type = DATA_TYPE_BOOLEAN_VALUE, \
+ .scp_num = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS, \
+ .scp_setprop = ses2_ctl_common_setprop \
+}
+
+typedef struct ses2_ctl_desc {
+ ses2_element_type_t scd_et;
+ const ses2_ctl_prop_t *scd_props;
+ ses2_setdef_f scd_setdef;
+} ses2_ctl_desc_t;
+
+extern int ses2_setprop(ses_plugin_t *, ses_node_t *, const ses2_ctl_prop_t *,
+ nvlist_t *);
+
+extern int ses2_element_setdef(ses_node_t *, ses2_diag_page_t, void *);
+extern int ses2_enclosure_setdef(ses_node_t *, ses2_diag_page_t, void *);
+
+extern int ses2_element_ctl(ses_plugin_t *, ses_node_t *, const char *,
+ nvlist_t *);
+extern int ses2_enclosure_ctl(ses_plugin_t *, ses_node_t *, const char *,
+ nvlist_t *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PLUGIN_SES_IMPL_H */
diff --git a/usr/src/lib/scsi/plugins/ses/ses2/common/ses2_pages.c b/usr/src/lib/scsi/plugins/ses/ses2/common/ses2_pages.c
new file mode 100644
index 0000000000..7c6d7726ba
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/ses2/common/ses2_pages.c
@@ -0,0 +1,462 @@
+/*
+ * 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"
+
+#include <stddef.h>
+#include <strings.h>
+
+#include <scsi/libses.h>
+#include <scsi/libses_plugin.h>
+#include <scsi/plugins/ses/framework/ses2.h>
+
+#include "ses2_impl.h"
+
+static int
+ses2_ctl_common_setdef(ses_node_t *np, ses2_diag_page_t page, void *data)
+{
+ ses2_cmn_elem_ctl_impl_t *eip = data;
+ nvlist_t *props = ses_node_props(np);
+
+ if (page != SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS)
+ return (0);
+
+ SES_NV_CTLBOOL_INVERT(props, SES_PROP_SWAP, eip->seci_rst_swap);
+ SES_NV_CTLBOOL(props, SES_PROP_DISABLED, eip->seci_disable);
+ SES_NV_CTLBOOL(props, SES_PROP_PRDFAIL, eip->seci_prdfail);
+
+ eip->seci_select = 1;
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static void *
+ses2_aes_index(ses_plugin_t *sp, ses_node_t *np, void *data, size_t pagelen,
+ size_t *len)
+{
+ ses2_aes_page_impl_t *apip = data;
+ uint64_t index, type;
+ nvlist_t *props = ses_node_props(np);
+ ses2_aes_descr_eip_impl_t *dep;
+ size_t desclen;
+ int i, pos;
+ ses_node_t *uncle;
+
+ VERIFY(nvlist_lookup_uint64(props, SES_PROP_ELEMENT_INDEX,
+ &index) == 0);
+ VERIFY(nvlist_lookup_uint64(props, SES_PROP_ELEMENT_TYPE,
+ &type) == 0);
+
+ if (pagelen < offsetof(ses2_aes_page_impl_t, sapi_data))
+ return (0);
+
+ /*
+ * Because, according to 6.1.13.1, the element index "does not
+ * include the OVERALL STATUS fields", we have to go recompute the
+ * index of this element each time. This, naturally, is a linear
+ * exercise as well.
+ */
+ for (uncle = ses_node_parent(np); uncle != NULL;
+ uncle = ses_node_prev_sibling(uncle))
+ --index;
+
+ for (dep = (ses2_aes_descr_eip_impl_t *)apip->sapi_data, pos = 0, i = 0;
+ pos < SCSI_READ16(&apip->sapi_page_length);
+ dep = (ses2_aes_descr_eip_impl_t *)(apip->sapi_data + pos), i++) {
+ if (!SES_WITHIN_PAGE_STRUCT(dep, data, pagelen))
+ break;
+
+ desclen = dep->sadei_length +
+ offsetof(ses2_aes_descr_eip_impl_t, sadei_length) +
+ sizeof (dep->sadei_length);
+
+ if (!SES_WITHIN_PAGE(dep, desclen, data, pagelen))
+ break;
+
+ pos += desclen;
+ if (!dep->sadei_eip &&
+ type != SES_ET_DEVICE &&
+ type != SES_ET_ARRAY_DEVICE) {
+ /*
+ * We can't really do anything with this, because
+ * while the standard requires that these descriptors
+ * be in the same order as those in the status page,
+ * some element types may optionally include AES
+ * data. This means we cannot know which element
+ * this descriptor refers to unless EIP is 1. Sadly,
+ * the standard only says that this "should" be true.
+ * It's impossible to guess what use this is supposed
+ * to have otherwise. See 6.1.13.1.
+ */
+ continue;
+ } else if (dep->sadei_eip &&
+ dep->sadei_element_index != index) {
+ continue;
+ } else if (dep->sadei_eip || i == index) {
+ *len = desclen;
+ return (dep);
+ }
+ }
+
+ return (NULL);
+}
+
+/*ARGSUSED*/
+static void *
+ses2_threshold_index(ses_plugin_t *sp, ses_node_t *np, void *data,
+ size_t pagelen, size_t *len)
+{
+ uint64_t index;
+ nvlist_t *props = ses_node_props(np);
+ ses2_threshold_in_page_impl_t *tpip = data;
+ ses2_threshold_impl_t *tp;
+
+ VERIFY(nvlist_lookup_uint64(props, SES_PROP_ELEMENT_INDEX,
+ &index) == 0);
+
+ *len = sizeof (ses2_threshold_impl_t);
+ tp = &tpip->stipi_thresholds[index];
+
+ if (!SES_WITHIN_PAGE_STRUCT(tp, data, pagelen))
+ return (NULL);
+
+ return (&tpip->stipi_thresholds[index]);
+}
+
+/*ARGSUSED*/
+static void *
+ses2_element_index(ses_plugin_t *sp, ses_node_t *np, void *data,
+ size_t pagelen, size_t *len)
+{
+ uint64_t index;
+ nvlist_t *props = ses_node_props(np);
+ ses2_elem_desc_page_impl_t *edip = data;
+ ses2_elem_descriptor_impl_t *dp;
+ int i;
+ uint16_t dlen;
+
+ if (nvlist_lookup_uint64(props, SES_PROP_ELEMENT_INDEX, &index) != 0)
+ return (NULL);
+
+ if (!SES_WITHIN_PAGE(data, sizeof (*dp), data, pagelen))
+ return (NULL);
+
+ /*
+ * This variable-length list of variable-length strings format sucks
+ * for performance; we ALWAYS have to walk the whole bloody thing to
+ * find a particular node's entry.
+ */
+ for (i = 0, dp = (ses2_elem_descriptor_impl_t *)edip->sedpi_data;
+ i < index; i++) {
+
+ if (!SES_WITHIN_PAGE_STRUCT(dp, data, pagelen))
+ return (NULL);
+
+ dlen = SCSI_READ16(&dp->sedi_descriptor_length);
+
+ dp = (ses2_elem_descriptor_impl_t *)
+ ((uint8_t *)dp->sedi_descriptor + dlen);
+ }
+
+ if (!SES_WITHIN_PAGE_STRUCT(dp, data, pagelen))
+ return (NULL);
+
+ *len = SCSI_READ16(&dp->sedi_descriptor_length);
+
+ if (!SES_WITHIN_PAGE(dp,
+ *len + offsetof(ses2_elem_descriptor_impl_t, sedi_descriptor),
+ data, pagelen))
+ return (NULL);
+
+ return (dp->sedi_descriptor);
+}
+
+/*ARGSUSED*/
+static void *
+ses2_status_index(ses_plugin_t *sp, ses_node_t *np, void *data,
+ size_t pagelen, size_t *len)
+{
+ uint64_t index;
+ nvlist_t *props = ses_node_props(np);
+ ses2_status_page_impl_t *spip = data;
+
+ if (nvlist_lookup_uint64(props, SES_PROP_ELEMENT_INDEX,
+ &index) != 0)
+ return (NULL);
+
+ if ((index + 1) * sizeof (ses2_elem_status_impl_t) +
+ offsetof(ses2_status_page_impl_t, sspi_data) > pagelen)
+ return (NULL);
+
+ *len = sizeof (ses2_elem_status_impl_t);
+ return ((ses2_elem_status_impl_t *)spip->sspi_data + index);
+}
+
+/*ARGSUSED*/
+static size_t
+ses2_ctl_len(uint_t nelem, int page, size_t datalen)
+{
+ ASSERT(page == SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS);
+
+ return (nelem * sizeof (ses2_elem_ctl_impl_t) +
+ offsetof(ses2_control_page_impl_t, scpi_data[0]));
+}
+
+/*ARGSUSED*/
+static void *
+ses2_ctl_fill(ses_plugin_t *sp, void *pagedata, size_t pagelen,
+ ses_node_t *np)
+{
+ uint64_t index;
+ nvlist_t *props = ses_node_props(np);
+ ses2_control_page_impl_t *pip = pagedata;
+ void *data;
+ ses2_diag_page_t page = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS;
+
+ if (nvlist_lookup_uint64(props, SES_PROP_ELEMENT_INDEX,
+ &index) != 0) {
+ (void) ses_error(ESES_BAD_RESPONSE, "missing element index "
+ "for enclosure node");
+ return (NULL);
+ }
+
+ data = &pip->scpi_data[index];
+
+ if (ses2_ctl_common_setdef(np, page, data) != 0 ||
+ ses2_element_setdef(np, page, data) != 0 ||
+ ses2_enclosure_setdef(np, page, data) != 0)
+ return (NULL);
+
+ return (data);
+}
+
+/*ARGSUSED*/
+static size_t
+ses2_stringout_len(uint_t nelem, int page, size_t datalen)
+{
+ ASSERT(page == SES2_DIAGPAGE_STRING_IO);
+
+ return (datalen + offsetof(ses2_string_out_page_impl_t, ssopi_data[0]));
+}
+
+/*ARGSUSED*/
+static size_t
+ses2_threshout_len(uint_t nelem, int page, size_t datalen)
+{
+ ASSERT(page == SES2_DIAGPAGE_THRESHOLD_IO);
+
+ return (nelem * sizeof (ses2_threshold_impl_t) +
+ offsetof(ses2_threshold_out_page_impl_t, stopi_thresholds[0]));
+}
+
+/*ARGSUSED*/
+static void *
+ses2_threshout_ctl_fill(ses_plugin_t *sp, void *pagedata, size_t pagelen,
+ ses_node_t *np)
+{
+ uint64_t index;
+ nvlist_t *props = ses_node_props(np);
+ ses2_threshold_out_page_impl_t *pip = pagedata;
+ ses2_diag_page_t page = SES2_DIAGPAGE_THRESHOLD_IO;
+ void *data;
+
+ VERIFY(nvlist_lookup_uint64(props, SES_PROP_ELEMENT_INDEX,
+ &index) == 0);
+
+ data = &pip[index];
+
+ if (ses2_ctl_common_setdef(np, page, data) != 0 ||
+ ses2_element_setdef(np, page, data) != 0 ||
+ ses2_enclosure_setdef(np, page, data) != 0)
+ return (NULL);
+
+ return (data);
+}
+
+/*ARGSUSED*/
+static size_t
+ses2_substrout_len(uint_t nelem, int page, size_t datalen)
+{
+ ASSERT(page == SES2_DIAGPAGE_SUBENCLOSURE_STRING_IO);
+
+ return (datalen +
+ offsetof(ses2_substring_out_page_impl_t, ssopi_data[0]));
+}
+
+/*ARGSUSED*/
+static size_t
+ses2_ucodeout_len(uint_t nelem, int page, size_t datalen)
+{
+ size_t len;
+
+ ASSERT(page == SES2_DIAGPAGE_DL_MICROCODE_CTL_STATUS);
+
+ len = datalen +
+ offsetof(ses2_ucode_ctl_page_impl_t, sucpi_ucode_data[0]);
+
+ return (P2ROUNDUP(len, 4));
+}
+
+/*ARGSUSED*/
+static void *
+ses2_ucodeout_ctl_fill(ses_plugin_t *sp, void *data, size_t pagelen,
+ ses_node_t *np)
+{
+ ses_snap_t *snap = ses_node_snapshot(np);
+ nvlist_t *props = ses_node_props(np);
+ ses2_ucode_ctl_page_impl_t *uip = data;
+ uint64_t eid;
+
+ if (ses_node_type(np) != SES_NODE_ENCLOSURE) {
+ (void) ses_error(ESES_BAD_TYPE,
+ "microcode download page only valid for enclosure "
+ "nodes");
+ return (NULL);
+ }
+
+ VERIFY(nvlist_lookup_uint64(props, SES_EN_PROP_EID, &eid) == 0);
+
+ SCSI_WRITE32(&uip->sucpi_generation_code,
+ ses_snap_generation(snap));
+ uip->sucpi_subenclosure_identifier = eid;
+
+ return (data);
+}
+
+/*ARGSUSED*/
+static size_t
+ses2_subnickout_len(uint_t nelem, int page, size_t datalen)
+{
+ ASSERT(page == SES2_DIAGPAGE_SUBENCLOSURE_NICKNAME_CTL_STATUS);
+
+ return (sizeof (ses2_subnick_ctl_page_impl_t));
+}
+
+ses_pagedesc_t ses2_pages[] = {
+{
+ .spd_pagenum = SES2_DIAGPAGE_SUPPORTED_PAGES,
+ .spd_gcoff = -1
+},
+{
+ .spd_pagenum = SES2_DIAGPAGE_CONFIG,
+ .spd_gcoff = offsetof(ses2_config_page_impl_t, scpi_generation_code)
+},
+{
+ .spd_pagenum = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .spd_index = ses2_status_index,
+ .spd_gcoff = offsetof(ses2_status_page_impl_t, sspi_generation_code)
+},
+{
+ .spd_pagenum = SES2_DIAGPAGE_HELP_TEXT,
+ .spd_gcoff = -1
+},
+{
+ .spd_pagenum = SES2_DIAGPAGE_STRING_IO,
+ .spd_gcoff = -1
+},
+{
+ .spd_pagenum = SES2_DIAGPAGE_THRESHOLD_IO,
+ .spd_index = ses2_threshold_index,
+ .spd_gcoff =
+ offsetof(ses2_threshold_in_page_impl_t, stipi_generation_code)
+},
+{
+ .spd_pagenum = SES2_DIAGPAGE_ELEMENT_DESC,
+ .spd_index = ses2_element_index,
+ .spd_gcoff = offsetof(ses2_elem_desc_page_impl_t, sedpi_generation_code)
+},
+{
+ .spd_pagenum = SES2_DIAGPAGE_ADDL_ELEM_STATUS,
+ .spd_index = ses2_aes_index,
+ .spd_gcoff = offsetof(ses2_aes_page_impl_t, sapi_generation_code)
+},
+{
+ .spd_pagenum = SES2_DIAGPAGE_SUBENCLOSURE_HELP_TEXT,
+ .spd_gcoff = offsetof(ses2_subhelp_page_impl_t, sspi_generation_code)
+},
+{
+ .spd_pagenum = SES2_DIAGPAGE_SUBENCLOSURE_STRING_IO,
+ .spd_gcoff =
+ offsetof(ses2_substring_in_page_impl_t, ssipi_generation_code)
+},
+{
+ .spd_pagenum = SES2_DIAGPAGE_SUPPORTED_SES_PAGES,
+ .spd_gcoff = -1
+},
+{
+ .spd_pagenum = SES2_DIAGPAGE_DL_MICROCODE_CTL_STATUS,
+ .spd_gcoff =
+ offsetof(ses2_ucode_status_page_impl_t, suspi_generation_code)
+},
+{
+ .spd_pagenum = SES2_DIAGPAGE_SUBENCLOSURE_NICKNAME_CTL_STATUS,
+ .spd_gcoff =
+ offsetof(ses2_subnick_status_page_impl_t, sspci_generation_code)
+},
+/* Control pages */
+{
+ .spd_pagenum = SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS,
+ .spd_ctl_len = ses2_ctl_len,
+ .spd_ctl_fill = ses2_ctl_fill,
+ .spd_gcoff = offsetof(ses2_control_page_impl_t, scpi_generation_code)
+},
+{
+ .spd_pagenum = SES2_DIAGPAGE_STRING_IO,
+ .spd_ctl_len = ses2_stringout_len,
+ .spd_gcoff = -1
+},
+{
+ .spd_pagenum = SES2_DIAGPAGE_THRESHOLD_IO,
+ .spd_ctl_len = ses2_threshout_len,
+ .spd_ctl_fill = ses2_threshout_ctl_fill,
+ .spd_gcoff =
+ offsetof(ses2_threshold_out_page_impl_t, stopi_generation_code)
+},
+{
+ .spd_pagenum = SES2_DIAGPAGE_SUBENCLOSURE_STRING_IO,
+ .spd_ctl_len = ses2_substrout_len,
+ .spd_gcoff =
+ offsetof(ses2_substring_out_page_impl_t, ssopi_generation_code)
+},
+{
+ .spd_pagenum = SES2_DIAGPAGE_DL_MICROCODE_CTL_STATUS,
+ .spd_ctl_len = ses2_ucodeout_len,
+ .spd_ctl_fill = ses2_ucodeout_ctl_fill,
+ .spd_gcoff =
+ offsetof(ses2_ucode_ctl_page_impl_t, sucpi_generation_code)
+},
+{
+ .spd_pagenum = SES2_DIAGPAGE_SUBENCLOSURE_NICKNAME_CTL_STATUS,
+ .spd_ctl_len = ses2_subnickout_len,
+ .spd_gcoff =
+ offsetof(ses2_subnick_ctl_page_impl_t, sspci_generation_code)
+},
+{
+ .spd_pagenum = -1,
+ .spd_gcoff = -1
+}
+};
diff --git a/usr/src/lib/scsi/plugins/ses/ses2/i386/Makefile b/usr/src/lib/scsi/plugins/ses/ses2/i386/Makefile
new file mode 100644
index 0000000000..447a346278
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/ses2/i386/Makefile
@@ -0,0 +1,32 @@
+#
+# 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.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+
+install: all $(ROOTPROG)
+
+include ../../Makefile.targ
diff --git a/usr/src/lib/scsi/plugins/ses/ses2/sparc/Makefile b/usr/src/lib/scsi/plugins/ses/ses2/sparc/Makefile
new file mode 100644
index 0000000000..447a346278
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/ses2/sparc/Makefile
@@ -0,0 +1,32 @@
+#
+# 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.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+
+install: all $(ROOTPROG)
+
+include ../../Makefile.targ
diff --git a/usr/src/lib/scsi/plugins/ses/ses2/sparcv9/Makefile b/usr/src/lib/scsi/plugins/ses/ses2/sparcv9/Makefile
new file mode 100644
index 0000000000..fbf98db77f
--- /dev/null
+++ b/usr/src/lib/scsi/plugins/ses/ses2/sparcv9/Makefile
@@ -0,0 +1,33 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+include $(SRC)/Makefile.master.64
+
+install: all $(ROOTPROG64)
+
+include ../../Makefile.targ
diff --git a/usr/src/pkgdefs/Makefile b/usr/src/pkgdefs/Makefile
index b007b79d2a..3445b5c3bc 100644
--- a/usr/src/pkgdefs/Makefile
+++ b/usr/src/pkgdefs/Makefile
@@ -362,6 +362,7 @@ COMMON_SUBDIRS= \
SUNWscpu \
SUNWscplp \
SUNWscsa1394 \
+ SUNWscsip \
SUNWses \
SUNWsfe \
SUNWslpr \
diff --git a/usr/src/pkgdefs/SUNWarc/prototype_com b/usr/src/pkgdefs/SUNWarc/prototype_com
index 6aa3ee7b3b..61f806d12c 100644
--- a/usr/src/pkgdefs/SUNWarc/prototype_com
+++ b/usr/src/pkgdefs/SUNWarc/prototype_com
@@ -257,3 +257,8 @@ f none usr/lib/llib-lpasswdutil 644 root bin
f none usr/lib/llib-lpasswdutil.ln 644 root bin
f none usr/lib/llib-lgss 644 root bin
f none usr/lib/llib-lgss.ln 644 root bin
+d none usr/lib/scsi 755 root bin
+f none usr/lib/scsi/llib-lscsi 644 root bin
+f none usr/lib/scsi/llib-lscsi.ln 644 root bin
+f none usr/lib/scsi/llib-lses 644 root bin
+f none usr/lib/scsi/llib-lses.ln 644 root bin
diff --git a/usr/src/pkgdefs/SUNWarc/prototype_i386 b/usr/src/pkgdefs/SUNWarc/prototype_i386
index c075cea73e..924d200125 100644
--- a/usr/src/pkgdefs/SUNWarc/prototype_i386
+++ b/usr/src/pkgdefs/SUNWarc/prototype_i386
@@ -169,3 +169,6 @@ s none usr/ccs/lib/amd64/values-Xs.o=../../../lib/amd64/values-Xs.o
s none usr/ccs/lib/amd64/values-Xt.o=../../../lib/amd64/values-Xt.o
s none usr/ccs/lib/amd64/values-xpg4.o=../../../lib/amd64/values-xpg4.o
s none usr/ccs/lib/amd64/values-xpg6.o=../../../lib/amd64/values-xpg6.o
+d none usr/lib/scsi/amd64 755 root bin
+f none usr/lib/scsi/amd64/llib-lscsi.ln 644 root bin
+f none usr/lib/scsi/amd64/llib-lses.ln 644 root bin
diff --git a/usr/src/pkgdefs/SUNWarc/prototype_sparc b/usr/src/pkgdefs/SUNWarc/prototype_sparc
index b6b1d53bdd..fe4b089836 100644
--- a/usr/src/pkgdefs/SUNWarc/prototype_sparc
+++ b/usr/src/pkgdefs/SUNWarc/prototype_sparc
@@ -165,3 +165,6 @@ s none usr/ccs/lib/sparcv9/values-Xt.o=../../../lib/sparcv9/values-Xt.o
s none usr/ccs/lib/sparcv9/values-xpg4.o=../../../lib/sparcv9/values-xpg4.o
s none usr/ccs/lib/sparcv9/values-xpg6.o=../../../lib/sparcv9/values-xpg6.o
f none usr/lib/sparcv9/llib-lpasswdutil.ln 644 root bin
+d none usr/lib/scsi/sparcv9 755 root bin
+f none usr/lib/scsi/sparcv9/llib-lscsi.ln 644 root bin
+f none usr/lib/scsi/sparcv9/llib-lses.ln 644 root bin
diff --git a/usr/src/pkgdefs/SUNWcsl/prototype_com b/usr/src/pkgdefs/SUNWcsl/prototype_com
index 6a84023a77..ba6e4109bc 100644
--- a/usr/src/pkgdefs/SUNWcsl/prototype_com
+++ b/usr/src/pkgdefs/SUNWcsl/prototype_com
@@ -360,6 +360,20 @@ f none usr/lib/security/pkcs11_kernel.so.1 755 root bin
s none usr/lib/security/pkcs11_kernel.so=./pkcs11_kernel.so.1
f none usr/lib/security/pkcs11_softtoken.so.1 755 root bin
s none usr/lib/security/pkcs11_softtoken.so=./pkcs11_softtoken.so.1
+d none usr/lib/scsi 755 root bin
+f none usr/lib/scsi/libscsi.so.1 755 root bin
+s none usr/lib/scsi/libscsi.so=./libscsi.so.1
+f none usr/lib/scsi/libses.so.1 755 root bin
+s none usr/lib/scsi/libses.so=./libses.so.1
+d none usr/lib/scsi/plugins 755 root bin
+d none usr/lib/scsi/plugins/scsi 755 root bin
+d none usr/lib/scsi/plugins/scsi/engines 755 root bin
+f none usr/lib/scsi/plugins/scsi/engines/uscsi.so 755 root bin
+d none usr/lib/scsi/plugins/ses 755 root bin
+d none usr/lib/scsi/plugins/ses/framework 755 root bin
+f none usr/lib/scsi/plugins/ses/framework/libses.so 755 root bin
+f none usr/lib/scsi/plugins/ses/framework/ses2.so 755 root bin
+d none usr/lib/scsi/plugins/ses/vendor 755 root bin
f none usr/lib/watchmalloc.so.1 755 root bin
s none usr/lib/liby.so=./liby.so.1
s none usr/ccs/lib/liby.so=../../lib/liby.so.1
diff --git a/usr/src/pkgdefs/SUNWcsl/prototype_i386 b/usr/src/pkgdefs/SUNWcsl/prototype_i386
index c03e9554f6..19e366699b 100644
--- a/usr/src/pkgdefs/SUNWcsl/prototype_i386
+++ b/usr/src/pkgdefs/SUNWcsl/prototype_i386
@@ -89,6 +89,16 @@ s none usr/lib/lwp/amd64/libthread.so.1=../../amd64/libthread.so.1
s none usr/lib/lwp/amd64/libthread_db.so.1=../../amd64/libthread_db.so.1
d none usr/lib/raidcfg/amd64 755 root bin
f none usr/lib/raidcfg/amd64/mpt.so.1 755 root bin
+d none usr/lib/scsi/amd64 755 root bin
+f none usr/lib/scsi/amd64/libscsi.so.1 755 root bin
+s none usr/lib/scsi/amd64/libscsi.so=./libscsi.so.1
+f none usr/lib/scsi/amd64/libses.so.1 755 root bin
+s none usr/lib/scsi/amd64/libses.so=./libses.so.1
+d none usr/lib/scsi/plugins/scsi/engines/amd64 755 root bin
+f none usr/lib/scsi/plugins/scsi/engines/amd64/uscsi.so 755 root bin
+d none usr/lib/scsi/plugins/ses/framework/amd64 755 root bin
+f none usr/lib/scsi/plugins/ses/framework/amd64/libses.so 755 root bin
+f none usr/lib/scsi/plugins/ses/framework/amd64/ses2.so 755 root bin
d none usr/lib/security/amd64 755 root bin
s none usr/lib/security/64=amd64
f none usr/lib/security/amd64/crypt_bsdmd5.so.1 755 root bin
diff --git a/usr/src/pkgdefs/SUNWcsl/prototype_sparc b/usr/src/pkgdefs/SUNWcsl/prototype_sparc
index 22376c5573..3452eca2cf 100644
--- a/usr/src/pkgdefs/SUNWcsl/prototype_sparc
+++ b/usr/src/pkgdefs/SUNWcsl/prototype_sparc
@@ -81,6 +81,17 @@ s none usr/lib/lwp/sparcv9/libthread.so.1=../../sparcv9/libthread.so.1
s none usr/lib/lwp/sparcv9/libthread_db.so.1=../../sparcv9/libthread_db.so.1
d none usr/lib/raidcfg/sparcv9 755 root bin
f none usr/lib/raidcfg/sparcv9/mpt.so.1 755 root bin
+d none usr/lib/scsi/sparcv9 755 root bin
+f none usr/lib/scsi/sparcv9/libscsi.so.1 755 root bin
+s none usr/lib/scsi/sparcv9/libscsi.so=./libscsi.so.1
+f none usr/lib/scsi/sparcv9/libses.so.1 755 root bin
+s none usr/lib/scsi/sparcv9/libses.so=./libses.so.1
+d none usr/lib/scsi/plugins/scsi/engines/sparcv9 755 root bin
+f none usr/lib/scsi/plugins/scsi/engines/sparcv9/uscsi.so 755 root bin
+d none usr/lib/scsi/plugins/ses/framework/sparcv9 755 root bin
+f none usr/lib/scsi/plugins/ses/framework/sparcv9/libses.so 755 root bin
+f none usr/lib/scsi/plugins/ses/framework/sparcv9/ses2.so 755 root bin
+d none usr/lib/scsi/plugins/ses/vendor/sparcv9 755 root bin
d none usr/lib/security/sparcv9 755 root bin
s none usr/lib/security/64=sparcv9
f none usr/lib/security/sparcv9/crypt_bsdmd5.so.1 755 root bin
diff --git a/usr/src/pkgdefs/SUNWhea/prototype_com b/usr/src/pkgdefs/SUNWhea/prototype_com
index f723a79fbe..cc72136ac2 100644
--- a/usr/src/pkgdefs/SUNWhea/prototype_com
+++ b/usr/src/pkgdefs/SUNWhea/prototype_com
@@ -583,6 +583,17 @@ f none usr/include/sasl/prop.h 0644 root bin
f none usr/include/sasl/sasl.h 0644 root bin
f none usr/include/sasl/saslplug.h 0644 root bin
f none usr/include/sasl/saslutil.h 0644 root bin
+d none usr/include/scsi 755 root bin
+f none usr/include/scsi/libscsi.h 644 root bin
+f none usr/include/scsi/libses.h 644 root bin
+f none usr/include/scsi/libses_plugin.h 644 root bin
+d none usr/include/scsi/plugins 755 root bin
+d none usr/include/scsi/plugins/ses 755 root bin
+d none usr/include/scsi/plugins/ses/framework 755 root bin
+f none usr/include/scsi/plugins/ses/framework/libses.h 644 root bin
+f none usr/include/scsi/plugins/ses/framework/ses2.h 644 root bin
+f none usr/include/scsi/plugins/ses/framework/ses2_impl.h 644 root bin
+d none usr/include/scsi/plugins/ses/vendor 755 root bin
f none usr/include/search.h 644 root bin
f none usr/include/secdb.h 644 root bin
d none usr/include/security 755 root bin
@@ -1162,6 +1173,7 @@ f none usr/include/sys/scsi/impl/sas_transport.h 644 root bin
f none usr/include/sys/scsi/impl/scsi_reset_notify.h 644 root bin
f none usr/include/sys/scsi/impl/sense.h 644 root bin
f none usr/include/sys/scsi/impl/services.h 644 root bin
+f none usr/include/sys/scsi/impl/spc3_types.h 644 root bin
f none usr/include/sys/scsi/impl/status.h 644 root bin
f none usr/include/sys/scsi/impl/transport.h 644 root bin
f none usr/include/sys/scsi/impl/types.h 644 root bin
diff --git a/usr/src/pkgdefs/SUNWiotu/prototype_com b/usr/src/pkgdefs/SUNWiotu/prototype_com
index 33132cb385..9df5bc06f5 100644
--- a/usr/src/pkgdefs/SUNWiotu/prototype_com
+++ b/usr/src/pkgdefs/SUNWiotu/prototype_com
@@ -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.
#
#ident "%Z%%M% %I% %E% SMI"
@@ -57,3 +56,6 @@ d none usr/share 755 root sys
d none usr/share/man 755 root bin
d none usr/share/man/man1m 755 root bin
f none usr/share/man/man1m/pcitool.1m 444 root root
+d none usr/lib 755 root bin
+d none usr/lib/scsi 755 root bin
+f none usr/lib/scsi/sestopo 555 root bin
diff --git a/usr/src/pkgdefs/SUNWscsip/Makefile b/usr/src/pkgdefs/SUNWscsip/Makefile
new file mode 100644
index 0000000000..4db50ab6fc
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWscsip/Makefile
@@ -0,0 +1,36 @@
+#
+# 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.
+#
+#ident "%Z%%M% %I% %E% SMI"
+
+include ../Makefile.com
+
+.KEEP_STATE:
+
+all: $(FILES) depend
+
+install: all pkg
+
+include ../Makefile.targ
diff --git a/usr/src/pkgdefs/SUNWscsip/depend b/usr/src/pkgdefs/SUNWscsip/depend
new file mode 100644
index 0000000000..c4222422df
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWscsip/depend
@@ -0,0 +1,45 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# This package information file defines software dependencies associated
+# with the pkg. You can define three types of pkg dependencies with this file:
+# P indicates a prerequisite for installation
+# I indicates an incompatible package
+# R indicates a reverse dependency
+# <pkg.abbr> see pkginfo(4), PKG parameter
+# <name> see pkginfo(4), NAME parameter
+# <version> see pkginfo(4), VERSION parameter
+# <arch> see pkginfo(4), ARCH parameter
+# <type> <pkg.abbr> <name>
+# (<arch>)<version>
+# (<arch>)<version>
+# ...
+# <type> <pkg.abbr> <name>
+# ...
+#
+
+P SUNWcsl Core Solaris Libraries
diff --git a/usr/src/pkgdefs/SUNWscsip/pkginfo.tmpl b/usr/src/pkgdefs/SUNWscsip/pkginfo.tmpl
new file mode 100644
index 0000000000..69c26fa4a1
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWscsip/pkginfo.tmpl
@@ -0,0 +1,52 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+#
+# This required package information file describes characteristics of the
+# package, such as package abbreviation, full package name, package version,
+# and package architecture.
+#
+PKG="SUNWscsip"
+NAME="SCSI/SES plugins"
+ARCH="ISA"
+VERSION="ONVERS,REV=0.0.0"
+SUNW_PRODNAME="SunOS"
+SUNW_PRODVERS="RELEASE/VERSION"
+SUNW_PKGTYPE="usr"
+MAXINST="1000"
+CATEGORY="system"
+DESC="Vendor specific SCSI and SES plugins"
+VENDOR="Sun Microsystems, Inc."
+HOTLINE="Please contact your local service provider"
+EMAIL=""
+CLASSES="none"
+BASEDIR=/
+SUNW_PKGVERS="1.0"
+SUNW_PKG_ALLZONES="true"
+SUNW_PKG_HOLLOW="false"
+SUNW_PKG_THISZONE="false"
diff --git a/usr/src/pkgdefs/SUNWscsip/prototype_com b/usr/src/pkgdefs/SUNWscsip/prototype_com
new file mode 100644
index 0000000000..3f0a45dbb3
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWscsip/prototype_com
@@ -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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+# packaging files
+i copyright
+i depend
+i pkginfo
+
+# SUNWscsip
+d none usr 755 root sys
+d none usr/lib 755 root bin
+d none usr/lib/scsi 755 root bin
+d none usr/lib/scsi/plugins 755 root bin
+d none usr/lib/scsi/plugins/ses 755 root bin
+d none usr/lib/scsi/plugins/ses/vendor 755 root bin
+f none usr/lib/scsi/plugins/ses/vendor/SUN-StorageTek-J4400.so 755 root bin
diff --git a/usr/src/pkgdefs/SUNWscsip/prototype_i386 b/usr/src/pkgdefs/SUNWscsip/prototype_i386
new file mode 100644
index 0000000000..2f5e6389a9
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWscsip/prototype_i386
@@ -0,0 +1,32 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+!include prototype_com
+
+d none usr/lib/scsi/plugins/ses/vendor/amd64 755 root bin
+f none usr/lib/scsi/plugins/ses/vendor/amd64/SUN-StorageTek-J4400.so 755 root bin
diff --git a/usr/src/pkgdefs/SUNWscsip/prototype_sparc b/usr/src/pkgdefs/SUNWscsip/prototype_sparc
new file mode 100644
index 0000000000..62b0826274
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWscsip/prototype_sparc
@@ -0,0 +1,32 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+!include prototype_com
+
+d none usr/lib/scsi/plugins/ses/vendor/sparcv9 755 root bin
+f none usr/lib/scsi/plugins/ses/vendor/sparcv9/SUN-StorageTek-J4400.so 755 root bin
diff --git a/usr/src/tools/scripts/check_rtime.pl b/usr/src/tools/scripts/check_rtime.pl
index 85a9cbc376..6c0aa3824e 100644
--- a/usr/src/tools/scripts/check_rtime.pl
+++ b/usr/src/tools/scripts/check_rtime.pl
@@ -129,6 +129,7 @@ $SkipUndefDirs = qr{
/lib/mdb/ | # mdb modules have callbacks
/lib/fm/fmd/plugins/ | # fmd modules have callbacks
/lib/fm/fmd/schemes/ | # fmd schemes have callbacks
+ /lib/scsi/plugins/ | # scsi plugins have callbacks
/i86pc/lib/mtst/ # mtst modules have callbacks
}x;
diff --git a/usr/src/uts/common/io/scsi/targets/ses.c b/usr/src/uts/common/io/scsi/targets/ses.c
index 7cee4787bc..d12f291d44 100644
--- a/usr/src/uts/common/io/scsi/targets/ses.c
+++ b/usr/src/uts/common/io/scsi/targets/ses.c
@@ -21,7 +21,7 @@
/*
* Enclosure Services Device target driver
*
- * 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"
@@ -255,23 +255,23 @@ ses_probe(dev_info_t *dip)
}
/* SES_LOG(NULL, SES_CE_DEBUG1, "ses_probe: OK"); */
if (ddi_dev_is_sid(dip) == DDI_SUCCESS) {
- return (DDI_PROBE_DONTCARE);
+ return (DDI_PROBE_DONTCARE);
}
devp = ddi_get_driver_private(dip);
switch (err = scsi_probe(devp, SLEEP_FUNC)) {
case SCSIPROBE_EXISTS:
- if (is_enc_dev(NULL, devp->sd_inq, SUN_INQSIZE, &ep)) {
- break;
- }
+ if (is_enc_dev(NULL, devp->sd_inq, SUN_INQSIZE, &ep)) {
+ break;
+ }
/* FALLTHROUGH */
case SCSIPROBE_NORESP:
- scsi_unprobe(devp);
- return (DDI_PROBE_FAILURE);
+ scsi_unprobe(devp);
+ return (DDI_PROBE_FAILURE);
default:
- SES_LOG(NULL, SES_CE_DEBUG9,
- "ses_probe: probe error %d", err);
- scsi_unprobe(devp);
- return (DDI_PROBE_FAILURE);
+ SES_LOG(NULL, SES_CE_DEBUG9,
+ "ses_probe: probe error %d", err);
+ scsi_unprobe(devp);
+ return (DDI_PROBE_FAILURE);
}
scsi_unprobe(devp);
return (DDI_PROBE_SUCCESS);
@@ -428,7 +428,7 @@ ses_doattach(dev_info_t *dip)
devp->sd_private = (opaque_t)ssc;
ssc->ses_devp = devp;
err = ddi_create_minor_node(dip, "0", S_IFCHR, inst,
- DDI_NT_SCSI_ENCLOSURE, NULL);
+ DDI_NT_SCSI_ENCLOSURE, NULL);
if (err == DDI_FAILURE) {
ddi_remove_minor_node(dip, NULL);
SES_LOG(ssc, CE_NOTE, "minor node creation failed");
@@ -914,6 +914,7 @@ ses_uscsi_cmd(ses_softc_t *ssc, Uscmd *Uc, int Uf)
bcopy(uscmd->uscsi_cdb, &ssc->ses_srqcdb,
(size_t)(uscmd->uscsi_cdblen));
}
+ ssc->ses_uscsicmd.uscsi_status = 0;
bp = ssc->ses_sbufp;
bp->av_back = (struct buf *)NULL;
@@ -1022,7 +1023,7 @@ ses_start(struct buf *bp)
case TRAN_BUSY:
SES_LOG(ssc, SES_CE_DEBUG2,
- "ses_start: TRANSPORT BUSY");
+ "ses_start: TRANSPORT BUSY");
SES_ENABLE_RESTART(SES_RESTART_TIME, BP_PKT(bp));
return (0);
/* break; */
@@ -1094,9 +1095,9 @@ ses_restart(void *arg)
SES_LOG(ssc, SES_CE_DEBUG1,
"RESTART %d TRANSPORT BUSY\n", ssc->ses_retries);
if (ssc->ses_retries > SES_NO_RETRY) {
- ssc->ses_retries -= SES_BUSY_RETRY;
- SES_ENABLE_RESTART(SES_RESTART_TIME, pkt);
- return;
+ ssc->ses_retries -= SES_BUSY_RETRY;
+ SES_ENABLE_RESTART(SES_RESTART_TIME, pkt);
+ return;
}
SET_BP_ERROR(bp, EBUSY);
break;
@@ -1138,11 +1139,12 @@ ses_callback(struct scsi_pkt *pkt)
if (pkt->pkt_reason == CMD_CMPLT &&
!SCBP_C(pkt) &&
!(pkt->pkt_flags & FLAG_SENSING) &&
- !pkt->pkt_resid) {
- scsi_destroy_pkt(pkt);
- SET_BP_PKT(bp, NULL);
- biodone(bp);
- return;
+ !pkt->pkt_resid &&
+ !(scmd->uscsi_flags & USCSI_READ)) {
+ scsi_destroy_pkt(pkt);
+ SET_BP_PKT(bp, NULL);
+ biodone(bp);
+ return;
}
@@ -1167,7 +1169,8 @@ CHECK_PKT:
* reset the target.
*/
if (! (pkt->pkt_statistics & HBA_RESET)) {
- (void) scsi_reset(&pkt->pkt_address, RESET_TARGET);
+ (void) scsi_reset(&pkt->pkt_address,
+ RESET_TARGET);
}
err = ETIMEDOUT;
break;
@@ -1201,7 +1204,7 @@ CHECK_PKT:
*/
if ((bp->b_bcount - pkt->pkt_resid) > 0) {
SES_LOG(ssc, SES_CE_DEBUG6,
- "ignoring overrun");
+ "ignoring overrun");
pkt->pkt_reason = CMD_CMPLT;
err = EOK;
goto CHECK_PKT;
@@ -1221,17 +1224,17 @@ CHECK_PKT:
}
if (pkt == ssc->ses_rqpkt) {
SES_LOG(ssc, CE_WARN, fail_msg,
- "Request Sense ",
- scsi_rname(pkt->pkt_reason),
- (ssc->ses_retries > 0)?
- "retrying": "giving up");
+ "Request Sense ",
+ scsi_rname(pkt->pkt_reason),
+ (ssc->ses_retries > 0)?
+ "retrying": "giving up");
pkt = (struct scsi_pkt *)bp->av_back;
action = QUE_SENSE;
} else {
SES_LOG(ssc, CE_WARN, fail_msg,
- "", scsi_rname(pkt->pkt_reason),
- (ssc->ses_retries > 0)?
- "retrying": "giving up");
+ "", scsi_rname(pkt->pkt_reason),
+ (ssc->ses_retries > 0)?
+ "retrying": "giving up");
action = QUE_COMMAND;
}
/* Device exists, allow full error recovery. */
@@ -1256,33 +1259,35 @@ CHECK_PKT:
case QUE_COMMAND_NOW:
/* SES_LOG(ssc, SES_CE_DEBUG1, "retrying cmd now"); */
if (ssc->ses_retries > SES_NO_RETRY) {
- ssc->ses_retries -= SES_CMD_RETRY;
- scmd->uscsi_status = 0;
- if (ssc->ses_arq)
- bzero(pkt->pkt_scbp, sizeof (struct scsi_arq_status));
-
- if (scsi_transport((struct scsi_pkt *)bp->av_back)
- != TRAN_ACCEPT) {
- SES_ENABLE_RESTART(SES_RESTART_TIME,
- (struct scsi_pkt *)bp->av_back);
- }
- return;
+ ssc->ses_retries -= SES_CMD_RETRY;
+ scmd->uscsi_status = 0;
+ if (ssc->ses_arq)
+ bzero(pkt->pkt_scbp,
+ sizeof (struct scsi_arq_status));
+
+ if (scsi_transport((struct scsi_pkt *)bp->av_back)
+ != TRAN_ACCEPT) {
+ SES_ENABLE_RESTART(SES_RESTART_TIME,
+ (struct scsi_pkt *)bp->av_back);
+ }
+ return;
}
break;
case QUE_COMMAND:
SES_LOG(ssc, SES_CE_DEBUG1, "retrying cmd");
if (ssc->ses_retries > SES_NO_RETRY) {
- ssc->ses_retries -=
- (err == EBUSY)? SES_BUSY_RETRY: SES_CMD_RETRY;
- scmd->uscsi_status = 0;
- if (ssc->ses_arq)
- bzero(pkt->pkt_scbp, sizeof (struct scsi_arq_status));
-
- SES_ENABLE_RESTART(
- (err == EBUSY)? SES_BUSY_TIME: SES_RESTART_TIME,
- (struct scsi_pkt *)bp->av_back);
- return;
+ ssc->ses_retries -=
+ (err == EBUSY)? SES_BUSY_RETRY: SES_CMD_RETRY;
+ scmd->uscsi_status = 0;
+ if (ssc->ses_arq)
+ bzero(pkt->pkt_scbp,
+ sizeof (struct scsi_arq_status));
+
+ SES_ENABLE_RESTART(
+ (err == EBUSY)? SES_BUSY_TIME: SES_RESTART_TIME,
+ (struct scsi_pkt *)bp->av_back);
+ return;
}
break;
@@ -1298,7 +1303,7 @@ CHECK_PKT:
SES_ENABLE_RESTART(SES_RESTART_TIME,
ssc->ses_rqpkt);
}
- return;
+ return;
}
break;
@@ -1307,9 +1312,9 @@ CHECK_PKT:
pkt = (struct scsi_pkt *)bp->av_back;
bp->b_resid = pkt->pkt_resid;
if (bp->b_resid) {
- SES_LOG(ssc, SES_CE_DEBUG6,
- "transfer residue %ld(%ld)",
- bp->b_bcount - bp->b_resid, bp->b_bcount);
+ SES_LOG(ssc, SES_CE_DEBUG6,
+ "transfer residue %ld(%ld)",
+ bp->b_bcount - bp->b_resid, bp->b_bcount);
}
break;
}
@@ -1367,7 +1372,7 @@ ses_decode_sense(struct scsi_pkt *pkt, int *err)
*/
} else if (ssc->ses_arq && pkt->pkt_state & STATE_ARQ_DONE) {
struct scsi_arq_status *arq =
- (struct scsi_arq_status *)(pkt->pkt_scbp);
+ (struct scsi_arq_status *)(pkt->pkt_scbp);
int amt = min(sizeof (arq->sts_sensedata), SENSE_LENGTH);
uchar_t *arq_status = (uchar_t *)&arq->sts_rqpkt_status;
@@ -1473,9 +1478,9 @@ ses_decode_sense(struct scsi_pkt *pkt, int *err)
break;
}
SES_LOG(ssc, SES_CE_DEBUG1,
- "cdb[0]= 0x%x %s, key=0x%x, ASC/ASCQ=0x%x/0x%x",
- scmd->uscsi_cdb[0], err_action,
- sense->es_key, sense->es_add_code, sense->es_qual_code);
+ "cdb[0]= 0x%x %s, key=0x%x, ASC/ASCQ=0x%x/0x%x",
+ scmd->uscsi_cdb[0], err_action,
+ sense->es_key, sense->es_add_code, sense->es_qual_code);
#ifdef not
/*
diff --git a/usr/src/uts/common/io/scsi/targets/sgen.c b/usr/src/uts/common/io/scsi/targets/sgen.c
index 17d60a7cd3..e4d9640aa3 100644
--- a/usr/src/uts/common/io/scsi/targets/sgen.c
+++ b/usr/src/uts/common/io/scsi/targets/sgen.c
@@ -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.
*/
@@ -133,7 +133,7 @@ static void sgen_cleanup_binddb();
*/
static int sgen_uscsi_cmd(dev_t, struct uscsi_cmd *, int);
static int sgen_start(struct buf *);
-static void sgen_hold_cmdbuf(sgen_state_t *);
+static int sgen_hold_cmdbuf(sgen_state_t *);
static void sgen_rele_cmdbuf(sgen_state_t *);
static int sgen_make_uscsi_cmd(sgen_state_t *, struct buf *);
static void sgen_restart(void *);
@@ -772,7 +772,7 @@ sgen_setup_sense(sgen_state_t *sg_state)
/*
* sgen_create_errstats()
- * create named kstats for tracking occurence of errors.
+ * create named kstats for tracking occurrence of errors.
*/
static void
sgen_create_errstats(sgen_state_t *sg_state, int instance)
@@ -1060,19 +1060,30 @@ sgen_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
mutex_enter(&sg_state->sgen_mutex);
- if (SGEN_IS_OPEN(sg_state)) {
+ /*
+ * Don't allow new opens of a suspended device until the last close has
+ * happened. This is rather simplistic, but keeps the implementation
+ * straightforward.
+ */
+ if (SGEN_IS_SUSP(sg_state)) {
+ mutex_exit(&sg_state->sgen_mutex);
+ return (EIO);
+ }
+
+ /*
+ * Enforce exclusive access.
+ */
+ if (SGEN_IS_EXCL(sg_state) ||
+ (SGEN_IS_OPEN(sg_state) && (flag & FEXCL))) {
mutex_exit(&sg_state->sgen_mutex);
return (EBUSY);
}
+ if (flag & FEXCL)
+ SGEN_SET_EXCL(sg_state);
+
SGEN_SET_OPEN(sg_state);
- /*
- * At this point, sgen cannot have the suspended bit set,
- * since each target is exclusive-access; when the previous
- * close occurred, it cleared the flag.
- */
- ASSERT(!SGEN_IS_SUSP(sg_state));
mutex_exit(&sg_state->sgen_mutex);
return (0);
@@ -1099,6 +1110,7 @@ sgen_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
mutex_enter(&sg_state->sgen_mutex);
SGEN_CLR_OPEN(sg_state);
+ SGEN_CLR_EXCL(sg_state);
SGEN_CLR_SUSP(sg_state); /* closing clears the 'I was suspended' bit */
mutex_exit(&sg_state->sgen_mutex);
@@ -1186,7 +1198,6 @@ sgen_uscsi_cmd(dev_t dev, struct uscsi_cmd *ucmd, int flag)
struct buf *bp;
sgen_state_t *sg_state;
enum uio_seg uioseg;
- int cmdbufhold = 0;
int instance;
int flags;
int err;
@@ -1199,9 +1210,19 @@ sgen_uscsi_cmd(dev_t dev, struct uscsi_cmd *ucmd, int flag)
sgen_log(sg_state, SGEN_DIAG2, "in sgen_uscsi_cmd(): instance = %d",
instance);
+ /*
+ * At this point, we start affecting state relevant to the target,
+ * so access needs to be serialized.
+ */
+ if (sgen_hold_cmdbuf(sg_state) != 0) {
+ sgen_log(sg_state, SGEN_DIAG1, "sgen_uscsi_cmd: interrupted");
+ return (EINTR);
+ }
+
err = scsi_uscsi_alloc_and_copyin((intptr_t)ucmd, flag,
&sg_state->sgen_scsiaddr, &uscmd);
if (err != 0) {
+ sgen_rele_cmdbuf(sg_state);
sgen_log(sg_state, SGEN_DIAG1, "sgen_uscsi_cmd: "
"scsi_uscsi_alloc_and_copyin failed\n");
return (err);
@@ -1218,13 +1239,6 @@ sgen_uscsi_cmd(dev_t dev, struct uscsi_cmd *ucmd, int flag)
uscmd->uscsi_flags = flags;
}
- /*
- * At this point, we start affecting state relevant to the target,
- * so access needs to be serialized.
- */
- sgen_hold_cmdbuf(sg_state); /* lock command buf for this target */
- cmdbufhold = 1;
-
if (uscmd->uscsi_cdb != NULL) {
sgen_dump_cdb(sg_state, "sgen_uscsi_cmd: ",
(union scsi_cdb *)uscmd->uscsi_cdb, uscmd->uscsi_cdblen);
@@ -1268,9 +1282,7 @@ sgen_uscsi_cmd(dev_t dev, struct uscsi_cmd *ucmd, int flag)
/*
* After this point, we can't touch per-target state.
*/
- if (cmdbufhold) {
- sgen_rele_cmdbuf(sg_state);
- }
+ sgen_rele_cmdbuf(sg_state);
sgen_log(sg_state, SGEN_DIAG2, "done sgen_uscsi_cmd()");
@@ -1279,16 +1291,23 @@ sgen_uscsi_cmd(dev_t dev, struct uscsi_cmd *ucmd, int flag)
/*
* sgen_hold_cmdbuf()
- * Aquire a lock on the command buffer for the given target.
+ * Acquire a lock on the command buffer for the given target. Returns
+ * non-zero if interrupted.
*/
-static void
+static int
sgen_hold_cmdbuf(sgen_state_t *sg_state)
{
mutex_enter(&sg_state->sgen_mutex);
- while (SGEN_IS_BUSY(sg_state))
- cv_wait(&sg_state->sgen_cmdbuf_cv, &sg_state->sgen_mutex);
+ while (SGEN_IS_BUSY(sg_state)) {
+ if (!cv_wait_sig(&sg_state->sgen_cmdbuf_cv,
+ &sg_state->sgen_mutex)) {
+ mutex_exit(&sg_state->sgen_mutex);
+ return (-1);
+ }
+ }
SGEN_SET_BUSY(sg_state);
mutex_exit(&sg_state->sgen_mutex);
+ return (0);
}
/*
diff --git a/usr/src/uts/common/sys/Makefile b/usr/src/uts/common/sys/Makefile
index 41f8b5c313..9ec961664f 100644
--- a/usr/src/uts/common/sys/Makefile
+++ b/usr/src/uts/common/sys/Makefile
@@ -843,6 +843,7 @@ SCSIIMPLHDRS= \
status.h \
transport.h \
scsi_reset_notify.h \
+ spc3_types.h \
types.h \
uscsi.h \
usmp.h
diff --git a/usr/src/uts/common/sys/scsi/impl/commands.h b/usr/src/uts/common/sys/scsi/impl/commands.h
index 227e2da724..0001a80ebb 100644
--- a/usr/src/uts/common/sys/scsi/impl/commands.h
+++ b/usr/src/uts/common/sys/scsi/impl/commands.h
@@ -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.
*/
@@ -282,50 +282,109 @@ union scsi_cdb { /* scsi command description block */
#define SCSI_READ16(Sr16_Addr) \
(((uint16_t)*((uint8_t *)(Sr16_Addr)) << 8) | \
- ((uint16_t)*((uint8_t *)((Sr16_Addr)+1))))
+ ((uint16_t)*((uint8_t *)(Sr16_Addr)+1)))
+
+#define SCSI_READ24(Sr32_Addr) \
+ (((uint32_t)*((uint8_t *)(Sr32_Addr)) << 16) | \
+ ((uint32_t)*((uint8_t *)(Sr32_Addr)+1) << 8) | \
+ ((uint32_t)*((uint8_t *)(Sr32_Addr)+2)))
#define SCSI_READ32(Sr32_Addr) \
(((uint32_t)*((uint8_t *)(Sr32_Addr)) << 24) | \
- ((uint32_t)*((uint8_t *)((Sr32_Addr)+1)) << 16) | \
- ((uint32_t)*((uint8_t *)((Sr32_Addr)+2)) << 8) | \
- ((uint32_t)*((uint8_t *)((Sr32_Addr)+3))))
+ ((uint32_t)*((uint8_t *)(Sr32_Addr)+1) << 16) | \
+ ((uint32_t)*((uint8_t *)(Sr32_Addr)+2) << 8) | \
+ ((uint32_t)*((uint8_t *)(Sr32_Addr)+3)))
+
+#define SCSI_READ40(Sr64_Addr) \
+ (((uint64_t)*((uint8_t *)(Sr64_Addr)) << 32) | \
+ ((uint64_t)*((uint8_t *)(Sr64_Addr)+1) << 24) | \
+ ((uint64_t)*((uint8_t *)(Sr64_Addr)+2) << 16) | \
+ ((uint64_t)*((uint8_t *)(Sr64_Addr)+3) << 8) | \
+ ((uint64_t)*((uint8_t *)(Sr64_Addr)+4)))
+
+#define SCSI_READ48(Sr64_Addr) \
+ (((uint64_t)*((uint8_t *)(Sr64_Addr)) << 40) | \
+ ((uint64_t)*((uint8_t *)(Sr64_Addr)+1) << 32) | \
+ ((uint64_t)*((uint8_t *)(Sr64_Addr)+2) << 24) | \
+ ((uint64_t)*((uint8_t *)(Sr64_Addr)+3) << 16) | \
+ ((uint64_t)*((uint8_t *)(Sr64_Addr)+4) << 8) | \
+ ((uint64_t)*((uint8_t *)(Sr64_Addr)+5)))
#define SCSI_READ64(Sr64_Addr) \
(((uint64_t)*((uint8_t *)(Sr64_Addr)) << 56) | \
- ((uint64_t)*((uint8_t *)((Sr64_Addr)+1)) << 48) | \
- ((uint64_t)*((uint8_t *)((Sr64_Addr)+2)) << 40) | \
- ((uint64_t)*((uint8_t *)((Sr64_Addr)+3)) << 32) | \
- ((uint64_t)*((uint8_t *)((Sr64_Addr)+4)) << 24) | \
- ((uint64_t)*((uint8_t *)((Sr64_Addr)+5)) << 16) | \
- ((uint64_t)*((uint8_t *)((Sr64_Addr)+6)) << 8) | \
- ((uint64_t)*((uint8_t *)((Sr64_Addr)+7))))
+ ((uint64_t)*((uint8_t *)(Sr64_Addr)+1) << 48) | \
+ ((uint64_t)*((uint8_t *)(Sr64_Addr)+2) << 40) | \
+ ((uint64_t)*((uint8_t *)(Sr64_Addr)+3) << 32) | \
+ ((uint64_t)*((uint8_t *)(Sr64_Addr)+4) << 24) | \
+ ((uint64_t)*((uint8_t *)(Sr64_Addr)+5) << 16) | \
+ ((uint64_t)*((uint8_t *)(Sr64_Addr)+6) << 8) | \
+ ((uint64_t)*((uint8_t *)(Sr64_Addr)+7)))
#define SCSI_WRITE16(Sr16_Addr, Sr16_Val) \
- *((uint8_t *)(Sr16_Addr)) = (((uint16_t)(Sr16_Val) >> 8) & 0xff); \
- *(((uint8_t *)(Sr16_Addr))+1) = ((uint16_t)(Sr16_Val) & 0xff);
+ *((uint8_t *)(Sr16_Addr)) = (((uint16_t)(Sr16_Val) >> 8) & 0xff), \
+ *((uint8_t *)(Sr16_Addr)+1) = ((uint16_t)(Sr16_Val) & 0xff)
+
+#define SCSI_WRITE24(Sr24_Addr, Sr24_Val) \
+ SCSI_WRITE16((Sr24_Addr), ((Sr24_Val) & 0xffff00) >> 8), \
+ *((uint8_t *)(Sr24_Addr)+2) = ((uint8_t)((Sr24_Val) & 0xff))
#define SCSI_WRITE32(Sr32_Addr, Sr32_Val) \
- *(uint8_t *)(Sr32_Addr) = (((uint32_t)(Sr32_Val) >> 24) & 0xff); \
- *(((uint8_t *)(Sr32_Addr))+1) = \
- (((uint32_t)(Sr32_Val) >> 16) & 0xff); \
- *(((uint8_t *)(Sr32_Addr))+2) = (((uint32_t)(Sr32_Val) >> 8) & 0xff); \
- *(((uint8_t *)(Sr32_Addr))+3) = (((uint32_t)(Sr32_Val)) & 0xff);
+ *(uint8_t *)(Sr32_Addr) = (((uint32_t)(Sr32_Val) >> 24) & 0xff), \
+ *((uint8_t *)(Sr32_Addr)+1) = \
+ (((uint32_t)(Sr32_Val) >> 16) & 0xff), \
+ *((uint8_t *)(Sr32_Addr)+2) = (((uint32_t)(Sr32_Val) >> 8) & 0xff), \
+ *((uint8_t *)(Sr32_Addr)+3) = (((uint32_t)(Sr32_Val)) & 0xff)
+
+#define SCSI_WRITE40(Sr40_Addr, Sr40_Val) \
+ SCSI_WRITE32((Sr40_Addr), ((Sr40_Val) & 0xffffffff00ULL) >> 8), \
+ *((uint8_t *)(Sr40_Addr)+4) = ((uint8_t)(Sr40_Val) & 0xff)
+
+#define SCSI_WRITE48(Sr48_Addr, Sr40_Val) \
+ SCSI_WRITE32((Sr48_Addr), ((Sr48_Val) & 0xffffffff0000ULL) >> 16), \
+ SCSI_WRITE16((uint8_t *)(Sr48_Addr)+4, (Sr40_Val) & 0xffff)
#define SCSI_WRITE64(Sr64_Addr, Sr64_Val) \
- *(uint8_t *)(Sr64_Addr) = (((uint64_t)(Sr64_Val) >> 56) & 0xff); \
- *(((uint8_t *)(Sr64_Addr))+1) = \
- (((uint64_t)(Sr64_Val) >> 48) & 0xff); \
- *(((uint8_t *)(Sr64_Addr))+2) = \
- (((uint64_t)(Sr64_Val) >> 40) & 0xff); \
- *(((uint8_t *)(Sr64_Addr))+3) = \
- (((uint64_t)(Sr64_Val) >> 32) & 0xff); \
- *(((uint8_t *)(Sr64_Addr))+4) = \
- (((uint64_t)(Sr64_Val) >> 24) & 0xff); \
- *(((uint8_t *)(Sr64_Addr))+5) = \
- (((uint64_t)(Sr64_Val) >> 16) & 0xff); \
- *(((uint8_t *)(Sr64_Addr))+6) = \
- (((uint64_t)(Sr64_Val) >> 8) & 0xff); \
- *(((uint8_t *)(Sr64_Addr))+7) = (((uint64_t)(Sr64_Val)) & 0xff);
+ *(uint8_t *)(Sr64_Addr) = (((uint64_t)(Sr64_Val) >> 56) & 0xff), \
+ *((uint8_t *)(Sr64_Addr)+1) = \
+ (((uint64_t)(Sr64_Val) >> 48) & 0xff), \
+ *((uint8_t *)(Sr64_Addr)+2) = \
+ (((uint64_t)(Sr64_Val) >> 40) & 0xff), \
+ *((uint8_t *)(Sr64_Addr)+3) = \
+ (((uint64_t)(Sr64_Val) >> 32) & 0xff), \
+ *((uint8_t *)(Sr64_Addr)+4) = \
+ (((uint64_t)(Sr64_Val) >> 24) & 0xff), \
+ *((uint8_t *)(Sr64_Addr)+5) = \
+ (((uint64_t)(Sr64_Val) >> 16) & 0xff), \
+ *((uint8_t *)(Sr64_Addr)+6) = \
+ (((uint64_t)(Sr64_Val) >> 8) & 0xff), \
+ *((uint8_t *)(Sr64_Addr)+7) = (((uint64_t)(Sr64_Val)) & 0xff)
+
+/*
+ * These macros deal with unaligned data that crosses a byte boundary.
+ */
+#define SCSI_MK8(ms, ls) \
+ (((uint8_t)(ms) << 4) | (uint8_t)ls)
+
+#define SCSI_MK12_4_8(ms, ls) \
+ (((uint16_t)(ms) << 8) | (uint16_t)(ls))
+#define SCSI_MK12_8_4(ms, ls) \
+ (((uint16_t)(ms) << 4) | (uint16_t)(ls))
+
+#define SCSI_MK16_4_8_4(hi, mid, lo) \
+ (((uint16_t)(hi) << 12) | ((uint16_t)(mid) << 4) | (uint16_t)(lo))
+
+#define SCSI_MK20_4_16(ms, ls) \
+ (((uint32_t)(ms) << 16) | ((uint32_t)(ls)))
+#define SCSI_MK20_16_4(ms, ls) \
+ (((uint32_t)(ms) << 4) | ((uint32_t)(ls)))
+
+#define SCSI_MK24_4_16_4(hi, mid, lo) \
+ (((uint32_t)(hi) << 20) | ((uint32_t)(mid) << 4) | (uint32_t)(lo))
+
+#define SCSI_MK36_4_32(ms, ls) \
+ (((uint64_t)(ms) << 32) | (uint64_t)(ls))
+#define SCSI_MK36_32_4(ms, ls) \
+ (((uint64_t)(ms) << 4) | (uint64_t)(ls))
/*
* defines for getting/setting fields within the various command groups
diff --git a/usr/src/uts/common/sys/scsi/impl/spc3_types.h b/usr/src/uts/common/sys/scsi/impl/spc3_types.h
new file mode 100644
index 0000000000..f8ad106d23
--- /dev/null
+++ b/usr/src/uts/common/sys/scsi/impl/spc3_types.h
@@ -0,0 +1,1045 @@
+/*
+ * 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.
+ */
+
+#ifndef _SPC3_TYPES_H
+#define _SPC3_TYPES_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <sys/cdio.h>
+#include <sys/sysmacros.h>
+#include <sys/scsi/generic/commands.h>
+#include <sys/scsi/impl/commands.h>
+
+typedef enum spc3_cmd {
+ SPC3_CMD_TEST_UNIT_READY = SCMD_TEST_UNIT_READY,
+ SPC3_CMD_REZERO_UNIT = SCMD_REZERO_UNIT,
+ SPC3_CMD_REWIND = SCMD_REWIND,
+ SPC3_CMD_VENDOR_2 = 2,
+ SPC3_CMD_REQUEST_SENSE = SCMD_REQUEST_SENSE,
+ SPC3_CMD_FORMAT_UNIT = SCMD_FORMAT,
+ SPC3_CMD_FORMAT_MEDIUM = SCMD_FORMAT,
+ SPC3_CMD_FORMAT = SCMD_FORMAT,
+ SPC3_CMD_READ_BLOCK_LIMITS = SCMD_READ_BLKLIM,
+ SPC3_CMD_VENDOR_6 = 6,
+ SPC3_CMD_REASSIGN_BLOCKS = SCMD_REASSIGN_BLOCK,
+ SPC3_CMD_INITIALIZE_ELEMENT_STATUS = SCMD_REASSIGN_BLOCK,
+ SPC3_CMD_READ = SCMD_READ,
+ SPC3_CMD_READ6 = SCMD_READ,
+ SPC3_CMD_RECEIVE = SCMD_RECEIVE,
+ SPC3_CMD_GET_MESSAGE = SCMD_READ,
+ SPC3_CMD_VENDOR_9 = 9,
+ SPC3_CMD_WRITE = SCMD_WRITE,
+ SPC3_CMD_WRITE6 = SCMD_WRITE,
+ SPC3_CMD_SEND = SCMD_SEND,
+ SPC3_CMD_SEND6 = SCMD_SEND,
+ SPC3_CMD_SEND_MESSAGE = SCMD_SEND,
+ SPC3_CMD_PRINT = SCMD_PRINT,
+ SPC3_CMD_SEEK = SCMD_SEEK,
+ SPC3_CMD_SEEK6 = SCMD_SEEK,
+ SPC3_CMD_SET_CAPACITY = SCMD_SEEK,
+ SPC3_CMD_SLEW_AND_PRINT = SCMD_SLEW_PRINT,
+ SPC3_CMD_VENDOR_C = 0xc,
+ SPC3_CMD_VENDOR_D = 0xd,
+ SPC3_CMD_VENDOR_E = 0xe,
+ SPC3_CMD_READ_REVERSE = SCMD_READ_REVERSE,
+ SPC3_CMD_READ_REVERSE6 = SCMD_READ_REVERSE,
+ SPC3_CMD_WRITE_FILEMARKS = SCMD_WRITE_FILE_MARK,
+ SPC3_CMD_WRITE_FILEMARKS6 = SCMD_WRITE_FILE_MARK,
+ SPC3_CMD_SYNCHRONIZE_BUFFER = SCMD_FLUSH_PRINT_BUF,
+ SPC3_CMD_SPACE = SCMD_SPACE,
+ SPC3_CMD_SPACE6 = SCMD_SPACE,
+ SPC3_CMD_INQUIRY = SCMD_INQUIRY,
+ SPC3_CMD_VERIFY = SCMD_VERIFY_G0,
+ SPC3_CMD_VERIFY6 = SCMD_VERIFY_G0,
+ SPC3_CMD_RECOVER_BUFFERED_DATA = SCMD_RECOVER_BUF,
+ SPC3_CMD_MODE_SELECT = SCMD_MODE_SELECT,
+ SPC3_CMD_MODE_SELECT6 = SCMD_MODE_SELECT,
+ SPC3_CMD_RESERVE = SCMD_RESERVE,
+ SPC3_CMD_RESERVE6 = SCMD_RESERVE,
+ SPC3_CMD_RESERVE_ELEMENT = SCMD_RESERVE,
+ SPC3_CMD_RESERVE_ELEMENT6 = SCMD_RESERVE,
+ SPC3_CMD_RELEASE = SCMD_RELEASE,
+ SPC3_CMD_RELEASE6 = SCMD_RELEASE,
+ SPC3_CMD_RELEASE_ELEMENT = SCMD_RELEASE,
+ SPC3_CMD_RELEASE_ELEMENT6 = SCMD_RELEASE,
+ SPC3_CMD_COPY = SCMD_COPY,
+ SPC3_CMD_ERASE = SCMD_ERASE,
+ SPC3_CMD_ERASE6 = SCMD_ERASE,
+ SPC3_CMD_MODE_SENSE = SCMD_MODE_SENSE,
+ SPC3_CMD_MODE_SENSE6 = SCMD_MODE_SENSE,
+ SPC3_CMD_START_STOP_UNIT = SCMD_START_STOP,
+ SPC3_CMD_LOAD_UNLOAD = SCMD_LOAD,
+ SPC3_CMD_SCAN = SCMD_START_STOP,
+ SPC3_CMD_STOP_PRINT = SCMD_STOP_PRINT,
+ SPC3_CMD_RECEIVE_DIAGNOSTIC_RESULTS = SCMD_GDIAG,
+ SPC3_CMD_SEND_DIAGNOSTIC = SCMD_SDIAG,
+ SPC3_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL = SCMD_DOORLOCK,
+ SPC3_CMD_VENDOR_20 = 0x20,
+ SPC3_CMD_VENDOR_21 = 0x21,
+ SPC3_CMD_VENDOR_22 = 0x22,
+ SPC3_CMD_VENDOR_23 = 0x23,
+ SPC3_CMD_SET_WINDOW = 0x24,
+ SPC3_CMD_READ_CAPACITY = SCMD_READ_CAPACITY,
+ SPC3_CMD_READ_CAPACITY10 = SCMD_READ_CAPACITY,
+ SPC3_CMD_READ_CARD_CAPACITY = SCMD_READ_CAPACITY,
+ SPC3_CMD_GET_WINDOW = SCMD_READ_CAPACITY,
+ SPC3_CMD_VENDOR_26 = 0x26,
+ SPC3_CMD_VENDOR_27 = 0x27,
+ SPC3_CMD_READ10 = SCMD_READ_G1,
+ SPC3_CMD_GET_MESSAGE10 = SCMD_READ_G1,
+ SPC3_CMD_READ_GENERATION = 0x29,
+ SPC3_CMD_WRITE10 = SCMD_WRITE_G1,
+ SPC3_CMD_SEND10 = SCMD_WRITE_G1,
+ SPC3_CMD_SEND_MESSAGE10 = SCMD_WRITE_G1,
+ SPC3_CMD_SEEK10 = SCMD_SEEK_G1,
+ SPC3_CMD_LOCATE = SCMD_LOCATE,
+ SPC3_CMD_LOCATE10 = SCMD_LOCATE,
+ SPC3_CMD_POSITION_TO_ELEMENT = SCMD_SEEK_G1,
+ SPC3_CMD_ERASE10 = 0x2c,
+ SPC3_CMD_READ_UPDATED_BLOCK = 0x2d,
+ SPC3_CMD_WRITE_AND_VERIFY = SCMD_WRITE_VERIFY,
+ SPC3_CMD_WRITE_AND_VERIFY10 = SCMD_WRITE_VERIFY,
+ SPC3_CMD_VERIFY10 = SCMD_VERIFY,
+ SPC3_CMD_SEARCH_DATA_HIGH = SCMD_SEARCH_HIGH,
+ SPC3_CMD_SEARCH_DATA_HIGH10 = SCMD_SEARCH_HIGH,
+ SPC3_CMD_SEARCH_DATA_EQUAL = SCMD_SEARCH_EQUAL,
+ SPC3_CMD_SEARCH_DATA_EQUAL10 = SCMD_SEARCH_EQUAL,
+ SPC3_CMD_OBJECT_POSITION = SCMD_SEARCH_EQUAL,
+ SPC3_CMD_SEARCH_DATA_LOW = SCMD_SEARCH_LOW,
+ SPC3_CMD_SEARCH_DATA_LOW10 = SCMD_SEARCH_LOW,
+ SPC3_CMD_SET_LIMITS = SCMD_SET_LIMITS,
+ SPC3_CMD_SET_LIMITS10 = SCMD_SET_LIMITS,
+ SPC3_CMD_PREFETCH = SCMD_READ_POSITION,
+ SPC3_CMD_PREFETCH10 = SCMD_READ_POSITION,
+ SPC3_CMD_READ_POSITION = SCMD_READ_POSITION,
+ SPC3_CMD_GET_DATA_BUFFER_STATUS = SCMD_READ_POSITION,
+ SPC3_CMD_SYNCHRONIZE_CACHE = SCMD_SYNCHRONIZE_CACHE,
+ SPC3_CMD_SYNCHRONIZE_CACHE10 = SCMD_SYNCHRONIZE_CACHE,
+ SPC3_CMD_LOCK_UNLOCK_CACHE = 0x36,
+ SPC3_CMD_READ_DEFECT_DATA = SCMD_READ_DEFECT_LIST,
+ SPC3_CMD_READ_DEFECT_DATA10 = SCMD_READ_DEFECT_LIST,
+ SPC3_CMD_INITIALIZE_ELEMENT_STATUS_WITH_RANGE = SCMD_READ_DEFECT_LIST,
+ SPC3_CMD_MEDIUM_SCAN = 0x38,
+ SPC3_CMD_COMPARE = SCMD_COMPARE,
+ SPC3_CMD_COPY_AND_VERIFY = SCMD_COPY_VERIFY,
+ SPC3_CMD_WRITE_BUFFER = SCMD_WRITE_BUFFER,
+ SPC3_CMD_READ_BUFFER = SCMD_READ_BUFFER,
+ SPC3_CMD_UPDATE_BLOCK = 0x3d,
+ SPC3_CMD_READ_LONG = SCMD_READ_LONG,
+ SPC3_CMD_READ_LONG10 = SCMD_READ_LONG,
+ SPC3_CMD_WRITE_LONG = SCMD_WRITE_LONG,
+ SPC3_CMD_WRITE_LONG10 = SCMD_WRITE_LONG,
+ SPC3_CMD_CHANGE_DEFINITION = 0x40,
+ SPC3_CMD_WRITE_SAME = 0x41,
+ SPC3_CMD_WRITE_SAME10 = 0x41,
+ SPC3_CMD_READ_SUBCHANNEL = SCMD_READ_SUBCHANNEL,
+ SPC3_CMD_READ_TOC = SCMD_READ_TOC,
+ SPC3_CMD_REPORT_DENSITY_SUPPORT = SCMD_REPORT_DENSITIES,
+ SPC3_CMD_READ_HEADER = SCMD_READ_HEADER,
+ SPC3_CMD_PLAY_AUDIO = SCMD_PLAYAUDIO10,
+ SPC3_CMD_PLAY_AUDIO10 = SCMD_PLAYAUDIO10,
+ SPC3_CMD_GET_CONFIGURATION = SCMD_GET_CONFIGURATION,
+ SPC3_CMD_PLAY_AUDIO_MSF = SCMD_PLAYAUDIO_MSF,
+ /* Not defined by SPC-3 */
+ SPC3_CMD_PLAY_AUDIO_TI = SCMD_PLAYAUDIO_TI,
+ SPC3_CMD_PLAY_TRACK_REL = SCMD_PLAYTRACK_REL10,
+ SPC3_CMD_PLAY_TRACK_REL10 = SCMD_PLAYTRACK_REL10,
+ SPC3_CMD_GET_EVENT_STATUS_NOTIFICATION = 0x4a,
+ SPC3_CMD_PAUSE_RESUME = SCMD_PAUSE_RESUME,
+ SPC3_CMD_LOG_SELECT = SCMD_LOG_SELECT_G1,
+ SPC3_CMD_LOG_SENSE = SCMD_LOG_SENSE_G1,
+ SPC3_CMD_STOP_PLAY_SCAN = 0x4e,
+ SPC3_CMD_XDWRITE = 0x50,
+ SPC3_CMD_XDWRITE10 = 0x50,
+ SPC3_CMD_XPWRITE = 0x51,
+ SPC3_CMD_XPWRITE10 = 0x51,
+ SPC3_CMD_READ_DISC_INFORMATION = 0x51,
+ SPC3_CMD_XDREAD = 0x52,
+ SPC3_CMD_XDREAD10 = 0x52,
+ SPC3_CMD_READ_TRACK_INFORMATION = 0x52,
+ SPC3_CMD_RESERVE_TRACK = 0x53,
+ SPC3_CMD_SEND_OPC_INFORMATION = 0x54,
+ SPC3_CMD_MODE_SELECT10 = SCMD_MODE_SELECT_G1,
+ SPC3_CMD_RESERVE10 = SCMD_RESERVE_G1,
+ SPC3_CMD_RESERVE_ELEMENT10 = SCMD_RESERVE_G1,
+ SPC3_CMD_RELEASE10 = SCMD_RELEASE_G1,
+ SPC3_CMD_RELEASE_ELEMENT10 = SCMD_RELEASE_G1,
+ SPC3_CMD_REPAIR_TRACK = 0x58,
+ SPC3_CMD_MODE_SENSE10 = SCMD_MODE_SENSE_G1,
+ SPC3_CMD_CLOSE_TRACK_SESSION = 0x5b,
+ SPC3_CMD_READ_BUFFER_CAPACITY = 0x5c,
+ SPC3_CMD_SEND_CUE_SHEET = 0x5d,
+ SPC3_CMD_PERSISTENT_RESERVE_IN = SCMD_PERSISTENT_RESERVE_IN,
+ SPC3_CMD_PERSISTENT_RESERVE_OUT = SCMD_PERSISTENT_RESERVE_OUT,
+ SPC3_CMD_VARIABLE_LENGTH = SCMD_VAR_LEN,
+ SPC3_CMD_XDWRITE_EXTENDED = SCMD_WRITE_FILE_MARK_G4,
+ SPC3_CMD_XDWRITE_EXTENDED16 = SCMD_WRITE_FILE_MARK_G4,
+ SPC3_CMD_WRITE_FILEMARKS16 = SCMD_WRITE_FILE_MARK_G4,
+ SPC3_CMD_REBUILD = SCMD_READ_REVERSE_G4,
+ SPC3_CMD_REBUILD16 = SCMD_READ_REVERSE_G4,
+ SPC3_CMD_READ_REVERSE16 = SCMD_READ_REVERSE_G4,
+ SPC3_CMD_REGENERATE = 0x82,
+ SPC3_CMD_REGENERATE16 = 0x82,
+ SPC3_CMD_EXTENDED_COPY = SCMD_EXTENDED_COPY,
+ SPC3_CMD_RECEIVE_COPY_RESULTS = 0x84,
+ SPC3_CMD_ATA_COMMAND_PASS_THROUGH = 0x85,
+ SPC3_CMD_ATA_COMMAND_PASS_THROUGH16 = 0x85,
+ SPC3_CMD_ACCESS_CONTROL_IN = 0x86,
+ SPC3_CMD_ACCESS_CONTROL_OUT = 0x87,
+ SPC3_CMD_READ16 = SCMD_READ_G4,
+ SPC3_CMD_WRITE16 = SCMD_WRITE_G4,
+ SPC3_CMD_READ_ATTRIBUTE = SCMD_READ_ATTRIBUTE,
+ SPC3_CMD_WRITE_ATTRIBUTE = SCMD_WRITE_ATTRIBUTE,
+ SPC3_CMD_WRITE_AND_VERIFY16 = 0x8e,
+ SPC3_CMD_VERIFY16 = SCMD_VERIFY_G4,
+ SPC3_CMD_PREFETCH16 = 0x90,
+ SPC3_CMD_SYNCHRONIZE_CACHE16 = SCMD_SPACE_G4,
+ SPC3_CMD_SPACE16 = SCMD_SPACE_G4,
+ SPC3_CMD_LOCK_UNLOCK_CACHE16 = 0x92,
+ SPC3_CMD_LOCATE16 = 0x92,
+ SPC3_CMD_WRITE_SAME16 = 0x93,
+ SPC3_CMD_ERASE16 = 0x93,
+ SPC3_CMD_SERVICE_ACTION_IN = SCMD_SVC_ACTION_IN_G4,
+ SPC3_CMD_SERVICE_ACTION_IN16 = SCMD_SVC_ACTION_IN_G4,
+ SPC3_CMD_SERVICE_ACTION_OUT = SCMD_SVC_ACTION_OUT_G4,
+ SPC3_CMD_SERVICE_ACTION_OUT16 = SCMD_SVC_ACTION_OUT_G4,
+ SPC3_CMD_REPORT_LUNS = SCMD_REPORT_LUNS,
+ SPC3_CMD_BLANK = 0xa1,
+ SPC3_CMD_ATA_COMMAND_PASS_THROUGH12 = 0xa1,
+ SPC3_CMD_SECURITY_PROTO_IN = SCMD_SECURITY_PROTO_IN,
+ SPC3_CMD_MAINTENANCE_IN = SCMD_MAINTENANCE_IN,
+ SPC3_CMD_SEND_KEY = SCMD_MAINTENANCE_IN,
+ SPC3_CMD_MAINTENANCE_OUT = SCMD_MAINTENANCE_OUT,
+ SPC3_CMD_REPORT_KEY = SCMD_MAINTENANCE_OUT,
+ SPC3_CMD_MOVE_MEDIUM = SCMD_PLAYAUDIO12,
+ SPC3_CMD_PLAY_AUDIO12 = SCMD_PLAYAUDIO12,
+ SPC3_CMD_EXCHANGE_MEDIUM = 0xa6,
+ SPC3_CMD_LOAD_UNLOAD_CD = 0xa6,
+ SPC3_CMD_MOVE_MEDIUM_ATTACHED = 0xa7,
+ SPC3_CMD_SET_READ_AHEAD = 0xa7,
+ SPC3_CMD_READ12 = SCMD_READ_G5,
+ SPC3_CMD_GET_MESSAGE12 = SCMD_READ_G5,
+ SPC3_CMD_SERVICE_ACTION_OUT12 = SCMD_SVC_ACTION_OUT_G5,
+ SPC3_CMD_PLAY_TRACK_REL12 = SCMD_PLAYTRACK_REL12,
+ SPC3_CMD_WRITE12 = SCMD_WRITE_G5,
+ SPC3_CMD_SEND_MESSAGE12 = SCMD_WRITE_G5,
+ SPC3_CMD_SERVICE_ACTION_IN12 = SCMD_SVC_ACTION_IN_G5,
+ SPC3_CMD_ERASE12 = SCMD_GET_PERFORMANCE,
+ SPC3_CMD_GET_PERFORMANCE = SCMD_GET_PERFORMANCE,
+ SPC3_CMD_READ_DVD_STRUCTURE = 0xad,
+ SPC3_CMD_WRITE_AND_VERIFY12 = 0xae,
+ SPC3_CMD_VERIFY12 = SCMD_VERIFY_G5,
+ SPC3_CMD_SEARCH_DATA_HIGH12 = 0xb0,
+ SPC3_CMD_SEARCH_DATA_EQUAL12 = 0xb1,
+ SPC3_CMD_SEARCH_DATA_LOW12 = 0xb2,
+ SPC3_CMD_SET_LIMITS12 = 0xb3,
+ SPC3_CMD_READ_ELEMENT_STATUS_ATTACHED = 0xb4,
+ SPC3_CMD_REQUEST_VOLUME_ELEMENT_ADDRESS = 0xb5,
+ SPC3_CMD_SEND_VOLUME_TAG = 0xb6,
+ SPC3_CMD_SET_STREAMING = 0xb6,
+ SPC3_CMD_READ_DEFECT_DATA12 = 0xb7,
+ SPC3_CMD_READ_ELEMENT_STATUS = 0xb8,
+ SPC3_CMD_READ_CD_MSF = 0xb9,
+ SPC3_CMD_REDUNDANCY_GROUP_IN = 0xba,
+ SPC3_CMD_SCAN12 = 0xba,
+ SPC3_CMD_REDUNDANCY_GROUP_OUT = SCMD_SET_CDROM_SPEED,
+ SPC3_CMD_SET_CD_SPEED = SCMD_SET_CDROM_SPEED,
+ SPC3_CMD_SPARE_IN = 0xbc,
+ SPC3_CMD_SPARE_OUT = 0xbd,
+ SPC3_CMD_MECHANISM_STATUS = 0xbd,
+ SPC3_CMD_VOLUME_SET_IN = SCMD_READ_CD,
+ SPC3_CMD_READ_CD = SCMD_READ_CD,
+ SPC3_CMD_VOLUME_SET_OUT = 0xbf,
+ SPC3_CMD_SEND_DVD_STRUCTURE = 0xbf
+} spc3_cmd_t;
+
+typedef enum spc3_dev_type {
+ SPC3_DEVTYPE_DIRECT = 0x00,
+ SPC3_DEVTYPE_SEQUENTIAL = 0x01,
+ SPC3_DEVTYPE_PRINTER = 0x02,
+ SPC3_DEVTYPE_PROCESSOR = 0x03,
+ SPC3_DEVTYPE_WORM = 0x04,
+ SPC3_DEVTYPE_MMC = 0x05,
+ SPC3_DEVTYPE_SCANNER = 0x06,
+ SPC3_DEVTYPE_OPTICAL = 0x07,
+ SPC3_DEVTYPE_CHANGER = 0x08,
+ SPC3_DEVTYPE_COMM = 0x09,
+ SPC3_DEVTYPE_ARRAY_CONTROLLER = 0x0c,
+ SPC3_DEVTYPE_SES = 0x0d,
+ SPC3_DEVTYPE_RBC = 0xe,
+ SPC3_DEVTYPE_OCRW = 0xf,
+ SPC3_DEVTYPE_BCC = 0x10,
+ SPC3_DEVTYPE_OSD = 0x11,
+ SPC3_DEVTYPE_ADC = 0x12
+} spc3_dev_type_t;
+
+/*
+ * SAM-4 5.3.1, Table 25
+ */
+typedef enum sam4_status {
+ SAM4_STATUS_GOOD = 0x0,
+ SAM4_STATUS_CHECK_CONDITION = 0x2,
+ SAM4_STATUS_CONDITION_MET = 0x4,
+ SAM4_STATUS_BUSY = 0x8,
+ SAM4_STATUS_RESERVATION_CONFLICT = 0x18,
+ SAM4_STATUS_TASK_SET_FULL = 0x28,
+ SAM4_STATUS_ACA_ACTIVE = 0x30,
+ SAM4_STATUS_TASK_ABORTED = 0x40
+} sam4_status_t;
+
+#pragma pack(1)
+
+typedef union spc3_control {
+ struct {
+ DECL_BITFIELD5(
+ c_link :1,
+ c_flag :1,
+ c_naca :1,
+ _reserved1 :3,
+ c_vs_6 :2);
+ } c_bits;
+ uint8_t c_byte;
+} spc3_control_t;
+
+/*
+ * SPC-3 6.2.1 CHANGE ALIASES
+ */
+typedef struct spc3_change_aliases_cdb {
+ uint8_t cac_opcode;
+ DECL_BITFIELD2(
+ cac_service_action :5,
+ _reserved1 :3);
+ uint8_t _reserved2[4];
+ uint32_t cac_parameter_list_length;
+ uint8_t _reserved3;
+ spc3_control_t cac_control;
+} spc3_change_aliases_cdb_t;
+
+typedef struct spc3_alias_entry {
+ uint64_t ae_alias_value;
+ uint8_t ae_protocol_identifier;
+ uint8_t _reserved1[2];
+ uint8_t ae_format_code;
+ uint8_t _reserved2[2];
+ uint16_t ae_designation_length;
+ uint8_t ae_designation[1]; /* Flexible */
+} spc3_alias_entry_t;
+
+typedef struct spc3_change_aliases_param_list {
+ uint32_t capl_parameter_data_length;
+ uint8_t _reserved1[4];
+ spc3_alias_entry_t capl_alias_entries[1]; /* Flexible */
+} spc3_change_aliases_param_list_t;
+
+/*
+ * SPC-3 6.4.1 INQUIRY
+ */
+typedef struct spc3_inquiry_cdb {
+ uint8_t ic_opcode;
+ DECL_BITFIELD2(
+ ic_evpd :1,
+ _reserved1 :7);
+ uint8_t ic_page_code;
+ uint16_t ic_allocation_length;
+ spc3_control_t ic_control;
+} spc3_inquiry_cdb_t;
+
+typedef struct spc3_inquiry_data {
+ DECL_BITFIELD2(
+ id_peripheral_device_type :5,
+ id_peripheral_qualifier :3);
+ DECL_BITFIELD2(
+ _reserved1 :7,
+ id_rmb :1);
+ uint8_t id_version;
+ DECL_BITFIELD4(
+ id_response_data_format :4,
+ id_hisup :1,
+ id_naca :1,
+ _reserved2 :2);
+ uint8_t additional_length;
+ DECL_BITFIELD6(
+ id_protect :1,
+ _reserved3 :2,
+ id_3pc :1,
+ id_tpgs :2,
+ id_acc :1,
+ id_sccs :1);
+ DECL_BITFIELD7(
+ id_addr16 :1,
+ _reserved4 :2,
+ id_mchanger :1,
+ id_multip :1,
+ id_vs_6_5 :1,
+ id_enc_serv :1,
+ id_b_que :1);
+ DECL_BITFIELD7(
+ id_vs_7_0 :1,
+ id_cmd_que :1,
+ _reserved5 :1,
+ id_linked :1,
+ id_sync :1,
+ id_wbus16 :1,
+ _reserved6 :2);
+ char id_vendor_id[8];
+ char id_product_id[16];
+ char id_product_revision[4];
+ uint8_t id_vs_36[20];
+ DECL_BITFIELD4(
+ id_ius :1,
+ id_qas :1,
+ id_clocking :2,
+ _reserved7 :4);
+ uint8_t _reserved8;
+ uint16_t id_version_descriptors[8];
+ uint8_t _reserved9[22];
+ uint8_t id_vs_96[1]; /* Flexible */
+} spc3_inquiry_data_t;
+
+/*
+ * SPC-3 6.5 LOG SELECT
+ */
+typedef enum spc3_log_page_control {
+ SPC3_LOG_PC_CUR_THRESHOLD = 0,
+ SPC3_LOG_PC_CUR_CUMULATIVE = 1,
+ SPC3_LOG_PC_DEF_THRESHOLD = 2,
+ SPC3_LOG_PC_DEF_CUMULATIVE = 3
+} spc3_log_page_control_t;
+
+typedef struct spc3_log_select_cdb {
+ uint8_t lsc_opcode;
+ DECL_BITFIELD3(
+ lsc_sp :1,
+ lsc_pcr :1,
+ _reserved1 :6);
+ DECL_BITFIELD2(
+ _reserved2 :6,
+ lsc_pc :2);
+ uint8_t _reserved3[4];
+ uint16_t lsc_parameter_list_length;
+ spc3_control_t lsc_control;
+} spc3_log_select_cdb_t;
+
+/*
+ * SPC-3 6.6 LOG SENSE
+ */
+typedef struct spc3_log_sense_cdb {
+ uint8_t lsc_opcode;
+ DECL_BITFIELD3(
+ lsc_sp :1,
+ lsc_ppc :1,
+ _reserved1 :6);
+ DECL_BITFIELD2(
+ lsc_page_code :6,
+ lsc_pc :2);
+ uint8_t _reserved2[2];
+ uint16_t lsc_parameter_ptr;
+ uint16_t lsc_allocation_length;
+ spc3_control_t lsc_control;
+} spc3_log_sense_cdb_t;
+
+typedef enum spc3_mode_page_control {
+ SPC3_MODE_PC_CURRENT = 0,
+ SPC3_MODE_PC_CHANGEABLE = 1,
+ SPC3_MODE_PC_DEFAULT = 2,
+ SPC3_MODE_PC_SAVED = 3
+} spc3_mode_page_control_t;
+
+typedef struct spc3_mode_param_header6 {
+ uint8_t mph_mode_data_length;
+ uint8_t mph_medium_type;
+ uint8_t mph_device_param;
+ uint8_t mph_block_descriptor_length;
+} spc3_mode_param_header6_t;
+
+typedef spc3_mode_param_header6_t spc3_mode_param_header_t;
+
+typedef struct spc3_mode_param_header10 {
+ uint16_t mph_mode_data_length;
+ uint8_t mph_medium_type;
+ uint8_t mph_device_param;
+ DECL_BITFIELD2(
+ mph_longlba :1,
+ _reserved1 :7);
+ uint8_t _reserved2;
+ uint16_t mph_block_descriptor_length;
+} spc3_mode_param_header10_t;
+
+typedef struct spc3_mode_param_block_descriptor {
+ uint8_t mpbd_density_code;
+ uint8_t mpbd_nblocks[3];
+ uint8_t _reserved1;
+ uint8_t mpbd_block_length[3];
+} spc3_mode_param_block_descriptor_t;
+
+typedef struct spc3_mode_page_0 {
+ DECL_BITFIELD3(
+ mp0_page_code :6,
+ mp0_spf :1,
+ mp0_ps :1);
+ uint8_t mp0_page_length;
+ uint8_t mp0_mode_parameters[1]; /* Flexible */
+} spc3_mode_page_0_t;
+
+typedef struct spc3_mode_subpage {
+ DECL_BITFIELD3(
+ ms_page_code :6,
+ ms_spf :1,
+ ms_ps :1);
+ uint8_t ms_subpage_code;
+ uint16_t ms_page_length;
+ uint8_t ms_mode_parameters[1]; /* Flexible */
+} spc3_mode_subpage_t;
+
+/*
+ * SPC-3 7.4.6 Table 246 - TST field
+ */
+typedef enum spc3_mode_task_set {
+ SPC3_MODE_TST_ONE = 0,
+ SPC3_MODE_TST_SEPARATE = 1
+} spc3_mode_task_set_t;
+
+/*
+ * SPC-3 7.4.6 Table 247 - Queue Algorithm Modifier field
+ */
+typedef enum spc3_mode_queue_alg_mod {
+ SPC3_MODE_QAM_RESTRICTED = 0,
+ SPC3_MODE_QAM_UNRESTRICTED = 1
+} spc3_mode_queue_alg_mod_t;
+
+/*
+ * SPC-3 7.4.6 Table 245
+ */
+typedef struct spc3_mode_params_control {
+ DECL_BITFIELD6(
+ mpc_rlec :1,
+ mpc_gltsd :1,
+ mpc_d_sense :1,
+ _reserved1 :1,
+ mpc_tmf_only :1,
+ mpc_tst :3);
+ DECL_BITFIELD4(
+ _reserved2 :1,
+ mpc_q_err :1,
+ _reserved3 :1,
+ mpc_queue_alg_mod :4);
+ DECL_BITFIELD5(
+ _reserved4 :3,
+ mpc_swp :1,
+ mpc_ua_intlck_ctrl :2,
+ mpc_rac :1,
+ mpc_vs_4_7 :1);
+ DECL_BITFIELD4(
+ mpc_autoload_mode :3,
+ _reserved5 :3,
+ mpc_tas :1,
+ mpc_ato :1);
+ uint8_t _reserved6[2];
+ uint16_t mpc_busy_timeout_period;
+ uint16_t mpc_ext_selftest_completion_time;
+} spc3_mode_page_params_control_t;
+
+/*
+ * SPC-3 7.4.7 Control Extension mode page
+ */
+typedef struct spc3_mode_params_control_ext {
+ DECL_BITFIELD4(
+ mpce_ialuae :1,
+ mpce_scsip :1,
+ mpce_tcmos :1,
+ _reserved1 :5);
+ DECL_BITFIELD2(
+ mpce_initial_priority :4,
+ _reserved2 :4);
+ uint8_t _reserved3[26];
+} spc3_mode_params_control_ext_t;
+
+/*
+ * SPC-3 7.4.8 Disconnect-Reconnect mode page
+ */
+typedef struct spc3_mode_params_dc_rc {
+ uint8_t mpdr_buffer_full_ratio;
+ uint8_t mpdr_buffer_empty_ratio;
+ uint16_t mpdr_bus_inactivity_limit;
+ uint16_t mpdr_disconnect_time_limit;
+ uint16_t mpdr_connect_time_limit;
+ uint16_t mpdr_max_burst_size;
+ DECL_BITFIELD4(
+ mpdr_dtdc :3,
+ mpdr_di_mm :1,
+ mpdr_fair_arbitration :3,
+ mpdr_emdp :1);
+ uint8_t _reserved1;
+ uint16_t mpdr_first_burst_size;
+} spc3_mode_params_dc_rc_t;
+
+typedef enum spc3_mode_mrie {
+ SPC3_MODE_MRIE_NONE = 0,
+ SPC3_MODE_MRIE_ASYNC = 1,
+ SPC3_MODE_MRIE_UNIT_ATTN = 2,
+ SPC3_MODE_MRIE_COND_REC_ERR = 3,
+ SPC3_MODE_MRIE_UNCOND_REC_ERR = 4,
+ SPC3_MODE_MRIE_NO_SENSE = 5,
+ SPC3_MODE_MRIE_REQUEST = 6
+} spc3_mode_mrie_t;
+
+/*
+ * SPC-3 7.4.11 Informational Exceptions Control mode page
+ */
+typedef struct spc3_mode_params_iec {
+ DECL_BITFIELD8(
+ mpi_log_err :1,
+ _reserved1 :1,
+ mpi_test :1,
+ mpi_d_excpt :1,
+ mpi_e_wasc :1,
+ mpi_ebf :1,
+ _reserved2 :1,
+ mpi_perf :1);
+ DECL_BITFIELD2(
+ mpi_mrie :4,
+ _reserved3 :4);
+ uint32_t mpi_interval_timer;
+ uint32_t mpi_report_count;
+} spc3_mode_params_iec_t;
+
+/*
+ * SPC-3 7.4.12 Power Condition mode page
+ */
+typedef struct spc3_mode_params_pc {
+ uint8_t _reserved1;
+ DECL_BITFIELD3(
+ mpp_standby :1,
+ mpp_idle :1,
+ _reserved2 :6);
+ uint32_t mpp_idle_condition_timer;
+ uint32_t mpp_standby_condition_timer;
+} spc3_mode_params_pc_t;
+
+/*
+ * SPC-3 6.7 MODE SELECT(6)
+ */
+typedef struct spc3_mode_select6_cdb {
+ uint8_t msc_opcode;
+ DECL_BITFIELD4(
+ msc_sp :1,
+ _reserved1 :3,
+ msc_pf :1,
+ _reserved2 :3);
+ uint8_t _reserved3[2];
+ uint8_t msc_parameter_list_length;
+ spc3_control_t msc_control;
+} spc3_mode_select6_cdb_t;
+
+typedef spc3_mode_select6_cdb_t spc3_mode_select_cdb_t;
+
+/*
+ * SPC-3 6.8 MODE SELECT(10)
+ */
+typedef struct spc3_mode_select10_cdb {
+ uint8_t msc_opcode;
+ DECL_BITFIELD4(
+ msc_sp :1,
+ _reserved1 :3,
+ msc_pf :1,
+ _reserved2 :3);
+ uint8_t _reserved3[5];
+ uint16_t msc_parameter_list_length;
+ spc3_control_t msc_control;
+} spc3_mode_select10_cdb_t;
+
+/*
+ * SPC-3 6.9 MODE SENSE(6)
+ */
+typedef struct spc3_mode_sense6_cdb {
+ uint8_t msc_opcode;
+ DECL_BITFIELD3(
+ _reserved1 :3,
+ msc_dbd :1,
+ _reserved2 :4);
+ DECL_BITFIELD2(
+ msc_page_code :6,
+ msc_pc :2);
+ uint8_t msc_subpage_code;
+ uint8_t msc_allocation_length;
+ spc3_control_t msc_control;
+} spc3_mode_sense6_cdb_t;
+
+typedef spc3_mode_sense6_cdb_t spc3_mode_sense_cdb_t;
+
+/*
+ * SPC-3 6.10 MODE SENSE(10)
+ */
+typedef struct spc3_mode_sense10_cdb {
+ uint8_t msc_opcode;
+ DECL_BITFIELD4(
+ _reserved1 :3,
+ msc_dbd :1,
+ msc_llbaa :1,
+ _reserved2 :3);
+ DECL_BITFIELD2(
+ msc_page_code :6,
+ msc_pc :2);
+ uint8_t msc_subpage_code;
+ uint8_t _reserved3[3];
+ uint16_t msc_allocation_length;
+ spc3_control_t msc_control;
+} spc3_mode_sense10_cdb_t;
+
+/*
+ * SPC-3 6.11 PERSISTENT RESERVE IN
+ */
+typedef enum spc3_persistent_reserve_in_sac {
+ SPC3_PRI_SAC_READ_KEYS = 0,
+ SPC3_PRI_SAC_READ_RESERVATION = 1,
+ SPC3_PRI_SAC_REPORT_CAPABILITIES = 2,
+ SPC3_PRI_SAC_READ_FULL_STATUS = 3
+} spc3_persistent_reserve_in_sac_t;
+
+typedef struct spc3_persistent_reserve_in_param_rk {
+ uint32_t pripr_pr_generation;
+ uint32_t pripr_additional_length;
+ uint64_t pripr_keys[1]; /* Flexible */
+} spc3_persistent_reserve_in_param_rk_t;
+
+typedef enum spc3_persistent_reserve_type {
+ SPC3_PR_TYPE_WREXCL = 1,
+ SPC3_PR_TYPE_EXCL = 3,
+ SPC3_PR_WREXCL_REG_ONLY = 5,
+ SPC3_PR_EXCL_REG_ONLY = 6,
+ SPC3_PR_WREXCL_ALL_REG = 7,
+ SPC3_PR_EXCL_ALL_REG = 8
+} spc3_persistent_reserve_type_t;
+
+typedef struct spc3_persistent_reserve_in_param_rr {
+ uint32_t pripr_pr_generation;
+ uint32_t pripr_additional_length;
+ uint64_t pripr_key;
+ uint8_t _reserved1[4];
+ uint8_t _reserved2;
+ DECL_BITFIELD2(
+ pripr_type :4,
+ pripr_scope :4);
+ uint8_t _reserved3[2];
+} spc3_persistent_reserve_in_param_rr_t;
+
+typedef struct spc3_persistent_reserve_in_param_rc {
+ uint16_t pripr_length;
+ DECL_BITFIELD6(
+ pripr_ptpl_c :1,
+ _reserved1 :1,
+ pripr_atp_c :1,
+ pripr_sip_c :1,
+ pripr_crh :1,
+ _reserved2 :3);
+ DECL_BITFIELD3(
+ pripr_ptpl_a :1,
+ _reserved3 :6,
+ pripr_tmv :1);
+ DECL_BITFIELD8(
+ _reserved4 :1,
+ pripr_wr_ex :1,
+ _reserved5 :1,
+ pripr_ex_ac :1,
+ _reserved6 :1,
+ pripr_wr_ex_ro :1,
+ pripr_ex_ac_ro :1,
+ pripr_wr_ex_ar :1);
+ DECL_BITFIELD2(
+ pripr_ex_ac_ar :1,
+ _reserved7 :7);
+ uint8_t _reserved8[2];
+} spc3_persistent_reserve_in_param_rc_t;
+
+typedef struct spc3_persistent_reserve_full_status {
+ uint64_t prfs_key;
+ uint8_t _reserved1[4];
+ DECL_BITFIELD3(
+ prfs_r_holder :1,
+ prfs_all_tg_pt :1,
+ _reserved2 :6);
+ DECL_BITFIELD2(
+ prfs_type :4,
+ prfs_scope :4);
+ uint8_t _reserved3[4];
+ uint16_t prfs_relative_target_port_identifier;
+ uint32_t prfs_additional_descriptor_length;
+ uint8_t prfs_transport_id[1]; /* Flexible */
+} spc3_persistent_reserve_full_status_t;
+
+typedef struct spc3_persistent_reserve_in_param_rfs {
+ uint32_t pripr_pr_generation;
+ uint32_t pripr_additional_length;
+ uint8_t pripr_status_descriptors[1]; /* Flexible */
+} spc3_persistent_reserve_in_param_rfs_t;
+
+typedef struct spc3_persistent_reserve_in_cdb {
+ uint8_t pric_opcode;
+ DECL_BITFIELD2(
+ pric_service_action :5,
+ _reserved1 :3);
+ uint8_t _reserved2[5];
+ uint16_t pric_allocation_length;
+ spc3_control_t pric_control;
+} spc3_persistent_reserve_in_cdb_t;
+
+/*
+ * SPC-3 6.16 READ MEDIA SERIAL NUMBER
+ */
+typedef struct spc3_read_media_serial_number_cdb {
+ uint8_t rmsnc_opcode;
+ DECL_BITFIELD2(
+ rmsnc_service_action :5,
+ _reserved1 :3);
+ uint8_t _reserved2[4];
+ uint32_t rmsnc_allocation_length;
+ uint8_t _reserved3;
+ spc3_control_t rmsnc_control;
+} spc3_read_media_serial_number_cdb_t;
+
+typedef struct spc3_read_media_serial_number_data {
+ uint32_t msnd_length;
+ uint8_t msnd_serial_number[1]; /* Flexible */
+} spc3_read_media_serial_number_data_t;
+
+/*
+ * SPC-3 6.18 RECEIVE DIAGNOSTIC RESULTS
+ */
+typedef struct spc3_receive_diagnostic_results_cdb {
+ uint8_t rdrc_opcode;
+ DECL_BITFIELD2(
+ rdrc_pcv :1,
+ _reserved1 :7);
+ uint8_t rdrc_page_code;
+ uint16_t rdrc_allocation_length;
+ spc3_control_t rdrc_control;
+} spc3_receive_diagnostic_results_cdb_t;
+
+/*
+ * SPC-3 Diagnostic page format (Table 194, 7.1.1)
+ */
+typedef struct spc3_diag_page_impl {
+ uint8_t sdpi_page_code;
+ uint8_t sdpi_specific;
+ uint16_t sdpi_page_length;
+ uint8_t sdpi_data[1];
+} spc3_diag_page_impl_t;
+
+/*
+ * SPC-3 Supported diagnostic pages (Table 196, 7.1.2)
+ */
+typedef struct spc3_supported_diag_page_impl {
+ uint8_t ssdpi_page_code;
+ uint8_t _reserved1;
+ uint16_t ssdpi_page_length;
+ uint8_t ssdpi_page_list[1];
+} spc3_supported_diag_page_impl_t;
+
+/*
+ * SPC-3 6.21 REPORT LUNS
+ */
+typedef enum spc3_report_luns_select_report {
+ SPC3_RL_SR_ADDRESSING = 0,
+ SPC3_RL_SR_WELLKNOWN = 1,
+ SPC3_RL_SR_ALL = 2
+} spc3_report_luns_select_report_t;
+
+typedef struct spc3_report_luns_cdb {
+ uint8_t rlc_opcode;
+ uint8_t _reserved1;
+ uint8_t rlc_select_report;
+ uint8_t _reserved2[3];
+ uint32_t rlc_allocation_length;
+ uint8_t _reserved3;
+ spc3_control_t rlc_control;
+} spc3_report_luns_cdb_t;
+
+typedef struct spc3_report_luns_data {
+ uint32_t rld_lun_list_length;
+ uint8_t _reserved1[4];
+ uint64_t rld_luns[1]; /* Flexible */
+} spc3_report_luns_data_t;
+
+/*
+ * SPC-3 6.27 REQUEST SENSE
+ */
+typedef struct spc3_request_sense_cdb {
+ uint8_t rsc_opcode;
+ DECL_BITFIELD2(
+ rsc_desc :1,
+ _reserved1 :7);
+ uint8_t _reserved2[2];
+ uint8_t rsc_allocation_length;
+ spc3_control_t rsc_control;
+} spc3_request_sense_cdb_t;
+
+/*
+ * SPC-3 6.28 SEND DIAGNOSTIC
+ */
+typedef struct spc3_send_diagnostic_cdb {
+ uint8_t sdc_opcode;
+ DECL_BITFIELD6(
+ sdc_unit_off_l :1,
+ sdc_dev_off_l :1,
+ sdc_self_test :1,
+ _reserved1 :1,
+ sdc_pf :1,
+ sdc_selftest_code :3);
+ uint8_t _reserved2;
+ uint16_t sdc_parameter_list_length;
+ spc3_control_t sdc_control;
+} spc3_send_diagnostic_cdb_t;
+
+/*
+ * SPC-3 6.33 TEST UNIT READY
+ */
+typedef struct spc3_test_unit_ready_cdb {
+ uint8_t tur_opcode;
+ uint8_t _reserved1[4];
+ spc3_control_t tur_control;
+} spc3_test_unit_ready_cdb_t;
+
+/*
+ * SPC-4 7.5.1 Protocol values
+ */
+typedef enum spc4_protocol_id {
+ SPC4_PROTO_FIBRE_CHANNEL = 0,
+ SPC4_PROTO_PARALLEL_SCSI = 1,
+ SPC4_PROTO_SSA = 2,
+ SPC4_PROTO_IEEE1394 = 3,
+ SPC4_PROTO_RDMA = 4,
+ SPC4_PROTO_ISCSI = 5,
+ SPC4_PROTO_SAS = 6,
+ SPC4_PROTO_ADT = 7,
+ SPC4_PROTO_ATA = 8,
+ SPC4_PROTO_NONE = 0xf
+} spc4_protocol_id_t;
+
+/*
+ * SPC-3 NAA identifier format (Table 305, 7.6.3.6.1)
+ */
+typedef struct spc3_naa_id_impl {
+ DECL_BITFIELD2(
+ snii_priv_msn :4,
+ snii_naa :4);
+ uint8_t snii_priv[1];
+} spc3_naa_id_impl_t;
+
+/*
+ * SPC-3 NAA IEEE Extended Identifier field format (Table 307, 7.6.3.6.2)
+ */
+typedef struct spc3_naa_ieee_ext_id_impl {
+ DECL_BITFIELD2(
+ snieii_vendor_id_a_msn :4,
+ snieii_naa :4);
+ uint8_t snieii_vendor_id_a_lsb;
+ uint8_t snieii_company_id[3];
+ uint8_t snieii_vendor_id_b[3];
+} spc3_naa_ieee_ext_id_impl_t;
+
+#define NAA_IEEE_EXT_VENDOR_A(idp) \
+ SCSI_MK12_4_8((idp)->snieii_vendor_id_a_msn, \
+ (idp)->snieii_vendor_id_a_lsb)
+#define NAA_IEEE_EXT_COMPANY_ID(idp) SCSI_READ24((idp)->snieii_company_id)
+#define NAA_IEEE_EXT_VENDOR_B(idp) SCSI_READ24((idp)->snieii_vendor_id_b)
+
+/*
+ * Ibid, Table 308
+ */
+typedef struct spc3_naa_ieee_reg_id_impl {
+ DECL_BITFIELD2(
+ snirii_company_id_msn :4,
+ snirii_naa :4);
+ uint16_t snirii_company_id_mid;
+ DECL_BITFIELD2(
+ snirii_vendor_id_msn :4,
+ snirii_company_id_lsn :4);
+ uint32_t snirii_vendor_id_low;
+} spc3_naa_ieee_reg_id_impl_t;
+
+#define NAA_IEEE_REG_COMPANY_ID(idp) \
+ SCSI_MK24_4_16_4((idp)->snirii_company_id_msn, \
+ SCSI_READ16(&(idp)->snirii_company_id_mid), \
+ (idp)->snirii_company_id_lsn)
+#define NAA_IEEE_REG_VENDOR_ID(idp) \
+ SCSI_MK36_4_32((idp)->snirii_vendor_id_msn, \
+ SCSI_READ32(&(idp)->snirii_vendor_id_low))
+
+/*
+ * Ibid, Table 309
+ */
+typedef struct spc3_naa_ieee_reg_ext_id_impl {
+ DECL_BITFIELD2(
+ snireii_company_id_msn :4,
+ snireii_naa :4);
+ uint16_t snireii_company_id_mid;
+ DECL_BITFIELD2(
+ snireii_vendor_id_msn :4,
+ snireii_company_id_lsn :4);
+ uint32_t snireii_vendor_id_low;
+ uint64_t snireii_vendor_id_ext;
+} spc3_naa_ieee_reg_ext_id_impl_t;
+
+#define NAA_IEEE_REG_EXT_COMPANY_ID(idp) \
+ SCSI_MK20_4_16_4((idp)->snireii_company_id_msn, \
+ SCSI_READ16(&(idp)->snireii_company_id_mid), \
+ (idp)->snireii_company_id_lsn)
+#define NAA_IEEE_REG_EXT_VENDOR_ID(idp) \
+ SCSI_MK36_4_32((idp)->snireii_vendor_id_msn, \
+ SCSI_READ32(&(idp)->snireii_vendor_id_low))
+
+typedef union spc3_naa_id_8_impl {
+ struct {
+ DECL_BITFIELD2(
+ _reserved1 :4,
+ sni8i_naa :4);
+ } sni8i_hdr;
+ spc3_naa_ieee_ext_id_impl_t sni8i_ext_id;
+ spc3_naa_ieee_reg_id_impl_t sni8i_reg_id;
+} spc3_naa_id_8_impl_t;
+
+#define sni8i_naa sni8i_hdr.sni8i_naa
+
+typedef enum naa_id {
+ NAA_IEEE_EXT = 0x2,
+ NAA_LOCAL = 0x3,
+ NAA_IEEE_REG = 0x5,
+ NAA_IEEE_REG_EXT = 0x6
+} naa_id_t;
+
+#pragma pack()
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SPC3_TYPES_H */
diff --git a/usr/src/uts/common/sys/scsi/targets/sgendef.h b/usr/src/uts/common/sys/scsi/targets/sgendef.h
index 23e29c0265..7dc7d9c5d4 100644
--- a/usr/src/uts/common/sys/scsi/targets/sgendef.h
+++ b/usr/src/uts/common/sys/scsi/targets/sgendef.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2001 by Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -98,6 +98,7 @@ typedef struct sgen_state {
#define SGEN_FL_OPEN 0x01 /* instance is open */
#define SGEN_FL_SUSP 0x02 /* instance suspended */
#define SGEN_FL_BUSY 0x04 /* command buffer busy */
+#define SGEN_FL_EXCL 0x08 /* exclusive open */
#define SGEN_SET_OPEN(stp) \
(((sgen_state_t *)(stp))->sgen_flags |= SGEN_FL_OPEN)
@@ -120,6 +121,13 @@ typedef struct sgen_state {
#define SGEN_IS_BUSY(stp) \
((((sgen_state_t *)(stp))->sgen_flags & SGEN_FL_BUSY) == SGEN_FL_BUSY)
+#define SGEN_SET_EXCL(stp) \
+ (((sgen_state_t *)(stp))->sgen_flags |= SGEN_FL_EXCL)
+#define SGEN_CLR_EXCL(stp) \
+ (((sgen_state_t *)(stp))->sgen_flags &= ~SGEN_FL_EXCL)
+#define SGEN_IS_EXCL(stp) \
+ ((((sgen_state_t *)(stp))->sgen_flags & SGEN_FL_EXCL) == SGEN_FL_EXCL)
+
/*
* These structures form the driver's database of binding information.
* Inquiry strings and device types from the inquiry-config-list and