summaryrefslogtreecommitdiff
path: root/usr/src/lib/mpapi
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/mpapi')
-rw-r--r--usr/src/lib/mpapi/Makefile48
-rw-r--r--usr/src/lib/mpapi/libmpapi/Makefile53
-rw-r--r--usr/src/lib/mpapi/libmpapi/Makefile.com63
-rw-r--r--usr/src/lib/mpapi/libmpapi/amd64/Makefile29
-rw-r--r--usr/src/lib/mpapi/libmpapi/common/llib-lMPAPI31
-rw-r--r--usr/src/lib/mpapi/libmpapi/common/mapfile-vers78
-rw-r--r--usr/src/lib/mpapi/libmpapi/common/mpapi-plugin.h291
-rw-r--r--usr/src/lib/mpapi/libmpapi/common/mpapi-sun.c75
-rw-r--r--usr/src/lib/mpapi/libmpapi/common/mpapi-sun.h71
-rw-r--r--usr/src/lib/mpapi/libmpapi/common/mpapi.c3668
-rw-r--r--usr/src/lib/mpapi/libmpapi/common/mpapi.conf32
-rw-r--r--usr/src/lib/mpapi/libmpapi/common/mpapi.h2593
-rw-r--r--usr/src/lib/mpapi/libmpapi/i386/Makefile28
-rw-r--r--usr/src/lib/mpapi/libmpapi/sparc/Makefile28
-rw-r--r--usr/src/lib/mpapi/libmpapi/sparcv9/Makefile29
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/Makefile50
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/Makefile.com74
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/amd64/Makefile29
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/Initialize.c94
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_AssignLogicalUnitToTPG.c125
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_CancelOverridePath.c45
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DeregForObjPropChangesPlugin.c88
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DeregForObjVisChangesPlugin.c89
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DisableAutoFailbackLu.c45
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DisableAutoFailbackPlugin.c113
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DisableAutoProbingLu.c45
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DisableAutoProbingPlugin.c40
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DisablePath.c112
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_EnableAutoFailbackLu.c45
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_EnableAutoFailbackPlugin.c105
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_EnableAutoProbingLu.c45
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_EnableAutoProbingPlugin.c40
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_EnablePath.c113
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetAssociatedPathOidList.c652
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetAssociatedTPGOidList.c295
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetDeviceProductOidListPlugin.c278
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetDeviceProductProperties.c140
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetInitiatorPortOidListPlugin.c193
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetInitiatorPortProperties.c124
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetMPLogicalUnitProperties.c351
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetMPLuOidListFromTPG.c508
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetMultipathLusDevProd.c320
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetMultipathLusPlugin.c198
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetPathLogicalUnitProperties.c174
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetPluginPropertiesPlugin.c147
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetProprietaryLBOidListPlugin.c287
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetProprietaryLBProp.c129
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetTargetPortGroupProperties.c137
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetTargetPortOidList.c297
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetTargetPortProperties.c121
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_RegForObjPropChangesPlugin.c95
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_RegForObjVisChangesPlugin.c94
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetFailbackPollingRateLu.c49
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetFailbackPollingRatePlugin.c45
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetLogicalUnitLoadBalanceType.c50
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetOverridePath.c49
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetPathWeight.c49
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetPluginLBTypePlugin.c45
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetProbingPollingRateLu.c49
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetProbingPollingRatePlugin.c45
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetProprietaryProperties.c54
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetTPGAccess.c207
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/Sun_MP_SendScsiCmd.c115
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/Terminate.c53
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/debug_logging.c67
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/mapfile-vers87
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/mp_utils.c675
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/common/mp_utils.h117
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/i386/Makefile28
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/sparc/Makefile28
-rw-r--r--usr/src/lib/mpapi/libmpscsi_vhci/sparcv9/Makefile29
71 files changed, 14795 insertions, 0 deletions
diff --git a/usr/src/lib/mpapi/Makefile b/usr/src/lib/mpapi/Makefile
new file mode 100644
index 0000000000..e51ae722b3
--- /dev/null
+++ b/usr/src/lib/mpapi/Makefile
@@ -0,0 +1,48 @@
+#
+# 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.
+#
+
+SUBDIRS = libmpapi libmpscsi_vhci
+HDRSUBDIRS = libmpapi
+
+all := TARGET= all
+check := TARGET= check
+clean := TARGET= clean
+clobber := TARGET= clobber
+install := TARGET= install
+install_h := TARGET= install_h
+
+.KEEP_STATE:
+
+libmpscsi_vhci: libmpapi
+
+all clean clobber install: $(SUBDIRS)
+
+check install_h: $(HDRSUBDIRS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
diff --git a/usr/src/lib/mpapi/libmpapi/Makefile b/usr/src/lib/mpapi/libmpapi/Makefile
new file mode 100644
index 0000000000..ebad6d797d
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpapi/Makefile
@@ -0,0 +1,53 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+include ../../Makefile.lib
+
+SUBDIRS = $(MACH)
+$(BUILD64)SUBDIRS += $(MACH64)
+
+all := TARGET= all
+clean := TARGET= clean
+clobber := TARGET= clobber
+install := TARGET= install
+lint := TARGET= lint
+
+HDRS = mpapi.h mpapi-sun.h
+HDRDIR = common
+
+.KEEP_STATE:
+
+all clean clobber install lint: $(SUBDIRS)
+
+install_h: $(ROOTHDRS)
+
+check:
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+include ../../Makefile.targ
diff --git a/usr/src/lib/mpapi/libmpapi/Makefile.com b/usr/src/lib/mpapi/libmpapi/Makefile.com
new file mode 100644
index 0000000000..2ae558051c
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpapi/Makefile.com
@@ -0,0 +1,63 @@
+#
+# 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.
+#
+
+LIBRARY= libMPAPI.a
+VERS= .1
+OBJECTS= mpapi.o mpapi-sun.o
+
+include ../../../Makefile.lib
+include ../../../Makefile.rootfs
+
+SRCDIR = ../common
+
+LIBS = $(DYNLIB) $(LINTLIB)
+LDLIBS += -lc
+
+$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC)
+
+CFLAGS += $(CCVERBOSE)
+CPPFLAGS += -I$(SRCDIR) -mt -v -D_POSIX_PTHREAD_SEMANTICS
+CPPFLAGS += -DBUILD_TIME='"Wed Sep 24 12:00:00 2008"'
+DYNFLAGS += -z finiarray=ExitLibrary
+DYNFLAGS += -z initarray=InitLibrary
+
+ROOTETC = $(ROOT)/etc
+CONFDIR = ../common
+CONFFILE = $(CONFDIR)/mpapi.conf
+IETCFILES = $(CONFFILE:$(CONFDIR)/%=$(ROOTETC)/%)
+$(IETCFILES) := FILEMODE = 0644
+$(IETCFILES) := OWNER = root
+$(IETCFILES) := GROUP = sys
+
+.KEEP_STATE:
+
+all: $(LIBS) $(IETCFILES)
+
+lint:
+
+$(ROOTETC)/%: $(CONFDIR)/%
+ $(INS.file)
+
+include ../../../Makefile.targ
diff --git a/usr/src/lib/mpapi/libmpapi/amd64/Makefile b/usr/src/lib/mpapi/libmpapi/amd64/Makefile
new file mode 100644
index 0000000000..bbc20fa470
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpapi/amd64/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.
+#
+
+include ../Makefile.com
+include ../../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)
diff --git a/usr/src/lib/mpapi/libmpapi/common/llib-lMPAPI b/usr/src/lib/mpapi/libmpapi/common/llib-lMPAPI
new file mode 100644
index 0000000000..5fe92023db
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpapi/common/llib-lMPAPI
@@ -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.
+ */
+
+/*LINTLIBRARY*/
+/*PROTOLIB1*/
+
+#include <mpapi.h>
+#include <mpapi-sun.h>
diff --git a/usr/src/lib/mpapi/libmpapi/common/mapfile-vers b/usr/src/lib/mpapi/libmpapi/common/mapfile-vers
new file mode 100644
index 0000000000..4f7e53bc03
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpapi/common/mapfile-vers
@@ -0,0 +1,78 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+SUNW_1.0 {
+ global:
+ MP_GetLibraryProperties;
+ MP_GetPluginOidList;
+ MP_GetPluginProperties;
+ MP_GetAssociatedPluginOid;
+ MP_GetObjectType;
+ MP_GetDeviceProductOidList;
+ MP_GetDeviceProductProperties;
+ MP_GetInitiatorPortOidList;
+ MP_GetInitiatorPortProperties;
+ MP_GetMultipathLus;
+ MP_GetMPLogicalUnitProperties;
+ MP_GetAssociatedPathOidList;
+ MP_GetPathLogicalUnitProperties;
+ MP_GetAssociatedTPGOidList;
+ MP_GetTargetPortGroupProperties;
+ MP_GetMPLuOidListFromTPG;
+ MP_GetProprietaryLoadBalanceOidList;
+ MP_GetProprietaryLoadBalanceProperties;
+ MP_GetTargetPortOidList;
+ MP_GetTargetPortProperties;
+ MP_AssignLogicalUnitToTPG;
+ MP_SetOverridePath;
+ MP_CancelOverridePath;
+ MP_EnableAutoFailback;
+ MP_DisableAutoFailback;
+ MP_EnableAutoProbing;
+ MP_DisableAutoProbing;
+ MP_EnablePath;
+ MP_DisablePath;
+ MP_SetLogicalUnitLoadBalanceType;
+ MP_SetPluginLoadBalanceType;
+ MP_SetPathWeight;
+ MP_SetFailbackPollingRate;
+ MP_SetProbingPollingRate;
+ MP_SetProprietaryProperties;
+ MP_SetTPGAccess;
+ MP_RegisterForObjectPropertyChanges;
+ MP_DeregisterForObjectPropertyChanges;
+ MP_RegisterForObjectVisibilityChanges;
+ MP_DeregisterForObjectVisibilityChanges;
+ MP_CompareOIDs;
+ MP_FreeOidList;
+ MP_RegisterPlugin;
+ MP_DeregisterPlugin;
+ MP_FreeOidList;
+ MP_RegisterPlugin;
+ MP_DeregisterPlugin;
+ Sun_MP_SendScsiCmd;
+ local:
+ *;
+};
diff --git a/usr/src/lib/mpapi/libmpapi/common/mpapi-plugin.h b/usr/src/lib/mpapi/libmpapi/common/mpapi-plugin.h
new file mode 100644
index 0000000000..e85f643635
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpapi/common/mpapi-plugin.h
@@ -0,0 +1,291 @@
+/******************************************************************************
+ *
+ * Description
+ * mpapi-plugin.h - interfaces for the MP API Version 1.0 plugin library.
+ * A compliant plugin library should implement interfaces with name without Fn
+ * suffix from function definitions below.
+ *
+ * License:
+ * The contents of this file are subject to the SNIA Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * TBD
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * The Original Code is iSCSI Management API and Multipath Management API
+ * plugin header file
+ *
+ * The Initial Developer of the Original Code is:
+ * Benjamin F. Kuo Troika Networks, Inc. (benk@troikanetworks.com)
+ * David Dillard VERITAS Software(david.dillard@veritas.com)
+ * Jeff Ding Adaptec, Inc. (jding@corp.adaptec.com)
+ * Hyon Kim Sun Microsystems(hyon.kim@sun.com)
+ *
+ * Contributor(s):
+ * Paul von Behren Sun Microsystems(paul.vonbehren@sun.com)
+ *
+ ******************************************************************************
+ *
+ * Changes:
+ * 1/15/2005 Implemented SNIA MP API specification 1.0
+ *****************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifndef MPPLUGIN_H
+#define MPPLUGIN_H
+
+/*
+ * MP API common library calls InitaizeFn as part of dynamically loading
+ * the plugins. For this version of implementation the common library
+ * passes the sequence number of the plugin oid through InitializeFn. The
+ * sequnece number will be used as the ownerId for the plugin generated OIDs.
+ */
+typedef MP_STATUS (* InitializeFn) (
+ MP_UINT32 pluginOwnerID
+ );
+
+/*
+ * MP API common library calls TerminateFn as part of dynamically unloading
+ * the plugins.
+ */
+typedef MP_STATUS (* TerminateFn) (void);
+
+/**
+ ******************************************************************************
+ *
+ * Function table for OID and properties discovery API
+ *
+ ******************************************************************************
+ */
+
+typedef MP_STATUS (* MP_GetPluginPropertiesPluginFn)(
+ MP_PLUGIN_PROPERTIES *pProps
+);
+
+typedef MP_STATUS (* MP_GetDeviceProductOidListPluginFn)(
+ MP_OID_LIST **ppList
+);
+
+typedef MP_STATUS (* MP_GetDeviceProductPropertiesFn)(
+ MP_OID oid,
+ MP_DEVICE_PRODUCT_PROPERTIES *pProps
+);
+
+typedef MP_STATUS (* MP_GetInitiatorPortOidListPluginFn)(
+ MP_OID_LIST **ppList
+);
+
+typedef MP_STATUS (* MP_GetInitiatorPortPropertiesFn)(
+ MP_OID oid,
+ MP_INITIATOR_PORT_PROPERTIES *pProps
+);
+
+typedef MP_STATUS (* MP_GetMultipathLusPluginFn)(
+ MP_OID_LIST **ppList
+);
+
+typedef MP_STATUS (* MP_GetMultipathLusDevProdFn)(
+ MP_OID oid,
+ MP_OID_LIST **ppList
+);
+
+typedef MP_STATUS (* MP_GetMPLogicalUnitPropertiesFn)(
+ MP_OID oid,
+ MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES *pProps
+);
+
+typedef MP_STATUS (* MP_GetAssociatedPathOidListFn)(
+ MP_OID oid,
+ MP_OID_LIST **ppList
+);
+
+typedef MP_STATUS (* MP_GetPathLogicalUnitPropertiesFn)(
+ MP_OID oid,
+ MP_PATH_LOGICAL_UNIT_PROPERTIES *pProps
+);
+
+typedef MP_STATUS (* MP_GetAssociatedTPGOidListFn)(
+ MP_OID oid,
+ MP_OID_LIST **ppList
+);
+
+typedef MP_STATUS (* MP_GetTargetPortGroupPropertiesFn)(
+ MP_OID oid,
+ MP_TARGET_PORT_GROUP_PROPERTIES *pProps
+);
+
+typedef MP_STATUS (* MP_GetMPLuOidListFromTPGFn)(
+ MP_OID oid,
+ MP_OID_LIST **ppList
+);
+
+typedef MP_STATUS (* MP_GetProprietaryLoadBalanceOidListPluginFn)(
+ MP_OID_LIST **ppList
+);
+
+typedef MP_STATUS (* MP_GetProprietaryLoadBalancePropertiesFn)(
+ MP_OID oid,
+ MP_PROPRIETARY_LOAD_BALANCE_PROPERTIES *pProps
+);
+
+typedef MP_STATUS (* MP_GetTargetPortOidListFn)(
+ MP_OID oid,
+ MP_OID_LIST **ppList
+);
+
+typedef MP_STATUS (* MP_GetTargetPortPropertiesFn)(
+ MP_OID oid,
+ MP_TARGET_PORT_PROPERTIES *pProps
+);
+
+/**
+ ******************************************************************************
+ *
+ * Function table for path management API
+ *
+ ******************************************************************************
+ */
+
+typedef MP_STATUS (* MP_AssignLogicalUnitToTPGFn)(
+ MP_OID tpgOid,
+ MP_OID luOid
+);
+
+typedef MP_STATUS (* MP_SetOverridePathFn)(
+ MP_OID logicalUnitOid,
+ MP_OID pathOid
+);
+
+typedef MP_STATUS (* MP_CancelOverridePathFn)(
+ MP_OID luOid
+);
+
+typedef MP_STATUS (* MP_EnableAutoFailbackPluginFn)(
+);
+
+typedef MP_STATUS (* MP_EnableAutoFailbackLuFn)(
+ MP_OID oid
+);
+
+typedef MP_STATUS (* MP_EnableAutoProbingPluginFn)(
+);
+
+typedef MP_STATUS (* MP_EnableAutoProbingLuFn)(
+ MP_OID oid
+);
+
+typedef MP_STATUS (* MP_DisableAutoFailbackPluginFn)(
+);
+
+typedef MP_STATUS (* MP_DisableAutoFailbackLuFn)(
+ MP_OID oid
+);
+
+typedef MP_STATUS (* MP_DisableAutoProbingPluginFn)(
+);
+
+typedef MP_STATUS (* MP_DisableAutoProbingLuFn)(
+ MP_OID oid
+);
+
+typedef MP_STATUS (* MP_EnablePathFn)(
+ MP_OID oid
+);
+
+typedef MP_STATUS (* MP_DisablePathFn)(
+ MP_OID oid
+);
+
+typedef MP_STATUS (* MP_SetLogicalUnitLoadBalanceTypeFn)(
+ MP_OID logicalUnitoid,
+ MP_LOAD_BALANCE_TYPE loadBalance
+);
+
+typedef MP_STATUS (* MP_SetPathWeightFn)(
+ MP_OID pathOid,
+ MP_UINT32 weight
+);
+
+typedef MP_STATUS (* MP_SetPluginLoadBalanceTypePluginFn)(
+ MP_LOAD_BALANCE_TYPE loadBalance
+);
+
+typedef MP_STATUS (* MP_SetFailbackPollingRatePluginFn)(
+ MP_UINT32 pollingRate
+);
+
+typedef MP_STATUS (* MP_SetFailbackPollingRateLuFn)(
+ MP_OID oid,
+ MP_UINT32 pollingRate
+);
+
+typedef MP_STATUS (* MP_SetProbingPollingRatePluginFn)(
+ MP_UINT32 pollingRate
+);
+
+typedef MP_STATUS (* MP_SetProbingPollingRateLuFn)(
+ MP_OID oid,
+ MP_UINT32 pollingRate
+);
+
+typedef MP_STATUS (* MP_SetProprietaryPropertiesFn)(
+ MP_OID oid,
+ MP_UINT32 count,
+ MP_PROPRIETARY_PROPERTY *pPropertyList
+);
+
+typedef MP_STATUS (* MP_SetTPGAccessFn)(
+ MP_OID luOid,
+ MP_UINT32 count,
+ MP_TPG_STATE_PAIR *pTpgStateList
+);
+
+/**
+ ******************************************************************************
+ *
+ * Function table for event support API
+ *
+ ******************************************************************************
+ */
+
+typedef MP_STATUS (* MP_RegisterForObjectPropertyChangesPluginFn)(
+ MP_OBJECT_PROPERTY_FN pClientFn,
+ MP_OBJECT_TYPE objectType,
+ void *pCallerData
+);
+
+typedef MP_STATUS (* MP_DeregisterForObjectPropertyChangesPluginFn)(
+ MP_OBJECT_PROPERTY_FN pClientFn,
+ MP_OBJECT_TYPE objectType
+);
+
+typedef MP_STATUS (* MP_RegisterForObjectVisibilityChangesPluginFn)(
+ MP_OBJECT_VISIBILITY_FN pClientFn,
+ MP_OBJECT_TYPE objectType,
+ void *pCallerData
+);
+
+typedef MP_STATUS (* MP_DeregisterForObjectVisibilityChangesPluginFn)(
+ MP_OBJECT_VISIBILITY_FN pClientFn,
+ MP_OBJECT_TYPE objectType
+);
+
+typedef MP_STATUS (* Sun_MP_SendScsiCmdFn)(
+ MP_OID oid, struct uscsi_cmd *cmd
+);
+
+#endif
+
+#ifdef __cplusplus
+};
+#endif
+
diff --git a/usr/src/lib/mpapi/libmpapi/common/mpapi-sun.c b/usr/src/lib/mpapi/libmpapi/common/mpapi-sun.c
new file mode 100644
index 0000000000..52ac002e85
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpapi/common/mpapi-sun.c
@@ -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.
+ */
+
+/*
+ * Description
+ * mpapi-sun.c - Implements the Sun Extension to the Multipath Management
+ * API Version 1.0
+ */
+
+#include <dlfcn.h>
+#include <pthread.h>
+#include "mpapi.h"
+#include "mpapi-sun.h"
+#include "mpapi-plugin.h"
+
+extern MPPLUGININFO_T plugintable[MP_MAX_NUM_PLUGINS];
+
+extern pthread_mutex_t mp_lib_mutex;
+extern MP_STATUS validate_object(MP_OID obj, MP_OBJECT_TYPE objType,
+ MP_UINT32 flag);
+
+MP_STATUS Sun_MP_SendScsiCmd(
+ MP_OID pathOid, struct uscsi_cmd *cmd)
+{
+ Sun_MP_SendScsiCmdFn PassFunc;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if ((status = validate_object(pathOid, MP_OBJECT_TYPE_PATH_LU,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = pathOid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (Sun_MP_SendScsiCmdFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "Sun_MP_SendScsiCmd");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(pathOid, cmd);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_FAILED;
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
diff --git a/usr/src/lib/mpapi/libmpapi/common/mpapi-sun.h b/usr/src/lib/mpapi/libmpapi/common/mpapi-sun.h
new file mode 100644
index 0000000000..f8f625fe0e
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpapi/common/mpapi-sun.h
@@ -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.
+ */
+
+/*
+ *
+ * Description
+ * mpapi-sun.h - general header file for Sun extension to the Multipath
+ * Management API Version 1.0 client
+ *
+ */
+
+#ifndef _MPAPI_SUN_H
+#define _MPAPI_SUN_H
+
+#include <sys/scsi/impl/uscsi.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifndef MPAPI_SUN_H
+#define MPAPI_SUN_H
+
+/**
+ ******************************************************************************
+ *
+ * The APIs for path management.
+ *
+ * - Sun_MP_SendScsiCmd
+ *
+ ******************************************************************************
+ */
+
+
+MP_STATUS Sun_MP_SendScsiCmd(
+ MP_OID pathOid,
+ struct uscsi_cmd *cmd
+);
+
+
+#endif
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* _MPAPI_SUN_H */
diff --git a/usr/src/lib/mpapi/libmpapi/common/mpapi.c b/usr/src/lib/mpapi/libmpapi/common/mpapi.c
new file mode 100644
index 0000000000..466b911884
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpapi/common/mpapi.c
@@ -0,0 +1,3668 @@
+/******************************************************************************
+ *
+ * Description
+ * mpapi.c - Implements Multipath Management API Version 1.0
+ *
+ * License:
+ * The contents of this file are subject to the SNIA Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://mp-mgmt-api.sourceforge.net
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * The Original Code is SNIA iSCSI Management API and Multipath Management
+ * API header files.
+ *
+ * The Initial Developer of the Original Code is:
+ * Benjamin F. Kuo Troika Networks, Inc. (benk@troikanetworks.com)
+ * David Dillard VERITAS Software(david.dillard@veritas.com)
+ * Jeff Ding Adaptec, Inc. (jding@corp.adaptec.com)
+ * Hyon Kim Sun Microsystems(hyon.kim@sun.com)
+ *
+ * Contributor(s):
+ * Paul von Behren Sun Microsystems(paul.vonbehren@sun.com)
+ *
+ ******************************************************************************
+ *
+ * Changes:
+ * 1/15/2005 Implemented SNIA MP API specification 1.0
+ * 10/11/2005
+ * - License location was specified in the header comment.
+ * - validate_object() routine was updated per the latest
+ * specification.
+ * - is_zero_oid() routine was added.
+ * - MP_GetObjectType() was updated with validate_object().
+ * - pplist argument checking added in MP_GetMultipathLus().
+ * - Corrected typo in MP_GetTaregetPortGroupProperties()
+ * - MP_RegisterForObjectPropertyChanges() was updated with
+ * is_zero_oid() routine.
+ * - MP_DeregisterForObjectPropertyChanges() was updated with
+ * is_zero_oid() routine.
+ * - MP_RegisterForObjectVisibilityChanges() was updated with
+ * is_zero_oid() routine.
+ * - MP_DeregisterForObjectVisibilityChanges() was updated with
+ * is_zero_oid() routine.
+ * - Added stat() check in MP_RegisterPlugin() to validate the
+ * the given plugin file name.
+ * - Made MP_DeregisterPlugin() return MP_STATUS_UNKNOWN_FN
+ * to mach the specification description.
+ ******************************************************************************
+ */
+
+#include <sys/sem.h>
+#include <dlfcn.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <time.h>
+#include <pthread.h>
+#include "mpapi.h"
+#include "mpapi-sun.h"
+#include "mpapi-plugin.h"
+
+#define LIBRARY_SUPPORTED_MP_VERSION 1
+#define LIBRARY_IMPLEMENTATION_VERSION L"1.0.0"
+#define LIBRARY_VENDOR L"Sun Microsystems Inc."
+
+#define LIBRARY_FILE_NAME "libMPAPI.so"
+
+
+MPPLUGININFO_T plugintable[MP_MAX_NUM_PLUGINS];
+pthread_mutex_t mp_lib_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static int number_of_plugins = -1;
+
+
+void InitLibrary();
+void ExitLibrary();
+static int lock_register(int fd, int cmd, int type, off_t offset, int whence,
+ off_t len);
+static int search_line(MP_CHAR *buf, size_t buflen, MP_CHAR *srch_id,
+ size_t id_len, int *write_offset, int *bytes_left);
+static int is_zero_oid(MP_OID);
+
+/**
+ ******************************************************************************
+ *
+ * Validate the oid.
+ *
+ * - Return MP_STATUS_OBJECT_NOT_FOUND when no plugin is found or the ownerId
+ * of input OID is not found.
+ * - Return MP_STATUS_INVALID_OBJECT_TYPE when no plugin is found or
+ * the type of input OID is not one of legitimate types defined SNIA
+ * Multipath Management spec.
+ * - Return MP_STATUS_INVALID_PARAMETER when the type of input OID is
+ * legitimate but its object type doesn't match with the object type
+ * argument.
+ * - Otherwise return MP_STATUS_SUCCESS.
+ *
+ ******************************************************************************
+ */
+MP_STATUS validate_object(MP_OID obj, MP_OBJECT_TYPE objType,
+ MP_UINT32 flag)
+{
+
+ if ((number_of_plugins == 0) ||
+ (obj.ownerId > number_of_plugins || obj.ownerId <= 0)) {
+ return (MP_STATUS_OBJECT_NOT_FOUND);
+ } else if (obj.objectType < 0 || obj.objectType > MP_OBJECT_TYPE_MAX) {
+ return (MP_STATUS_INVALID_OBJECT_TYPE);
+ } else if (obj.objectType == MP_OBJECT_TYPE_PLUGIN) {
+ if (obj.objectSequenceNumber != 0) {
+ return (MP_STATUS_OBJECT_NOT_FOUND);
+ }
+ }
+
+ if (flag == MP_OBJECT_TYPE_MATCH) {
+ if (obj.objectType != objType) {
+ return (MP_STATUS_INVALID_PARAMETER);
+ }
+ }
+ return (MP_STATUS_SUCCESS);
+}
+
+/**
+ ******************************************************************************
+ *
+ * Check if an oid is ZERO_OID or not.
+ *
+ * - Return 1 if the input OID is ZERO_OID
+ *
+ * - Return 0 if not.
+ *
+ ******************************************************************************
+ */
+static int is_zero_oid(MP_OID oid)
+{
+
+ if ((oid.objectType != MP_OBJECT_TYPE_UNKNOWN) || (oid.ownerId != 0) ||
+ (oid.objectSequenceNumber != 0)) {
+ return (0);
+ }
+
+ return (1);
+}
+
+/**
+ ******************************************************************************
+ *
+ * Initialize by loading plugin libraries and calling Initialize routine.
+ * Note: The build of libMPAPI.so should include a linker option to make this
+ * routine executed when it is loaded.
+ *
+ * - This routine bypasses a plugin library if it is not found.
+ * - The implementation of this routine is based on configuration file
+ * /etc/mpapi.conf that contains a list of plugin libraries.
+ *
+ ******************************************************************************
+ */
+void InitLibrary()
+{
+ FILE *mpconf;
+ int fd_mpconf;
+ MP_WCHAR fullline[MAX_LINE_SIZE]; /* line read in from mpapi.conf */
+ MP_WCHAR name[MAX_NAME_SIZE]; /* Read in from file mpapi.conf */
+ char path[MAX_NAME_SIZE]; /* Read in from file mpapi.conf */
+ char systemPath[MAX_NAME_SIZE], mpConfFilePath[MAX_NAME_SIZE];
+ MP_WCHAR *charPtr;
+ MP_WCHAR *sol;
+ struct stat stat_buf;
+
+ MP_UINT32 i = 0; /* index for plugin table */
+
+ if(number_of_plugins != -1) {
+ return;
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ number_of_plugins = 0;
+
+ /* Open configuration file from known location */
+ strncpy(mpConfFilePath, "/etc/mpapi.conf", MAX_NAME_SIZE);
+
+ if ((fd_mpconf = open(mpConfFilePath, O_RDONLY)) < 0) {
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return;
+ }
+
+ if (lock_register(fd_mpconf, F_SETLKW, F_RDLCK, 0, SEEK_SET, 0) < 0) {
+ close(fd_mpconf);
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return;
+ }
+
+ if ((mpconf = fdopen(fd_mpconf, "r")) == NULL) {
+ lock_register(fd_mpconf, F_SETLK, F_UNLCK, 0, SEEK_SET, 0);
+ close(fd_mpconf);
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return;
+ }
+
+ /* Read in each line and load library */
+ while ((mpconf != NULL) &&
+ (charPtr = fgetws(fullline, MAX_LINE_SIZE, mpconf))) {
+ if ((*charPtr != L'#') && (*charPtr != L'\n')) {
+ /* Take out the '\n' */
+ if ((charPtr = wcschr(fullline, L'\n')) != NULL)
+ *charPtr = L'\0';
+
+ charPtr = fullline;
+ /* remove leading blank or taps. */
+ while ((fullline[0] == L' ') || (fullline[0] == L'\t'))
+ charPtr++;
+
+ sol = charPtr;
+
+ /*
+ * look for first tab or space.
+ */
+ if ((charPtr = wcschr(fullline, L'\t')) == NULL)
+ charPtr = wcschr(fullline, L' ');
+
+ /* Set Null termination for library name if found */
+ if (charPtr != NULL) {
+ *charPtr++ = L'\0';
+ wcsncpy(name, sol, MAX_NAME_SIZE);
+ /* Skip space and tab until the next character found */
+ while ((*charPtr == L' ') || (*charPtr == L'\t'))
+ charPtr++;
+ } else {
+ continue; /* May be invalid entry */
+ }
+
+ /* Copy library name and path */
+ wcstombs(path, charPtr, MAX_NAME_SIZE);
+
+ /*
+ * Continue to the next line if library name or path is
+ * invalid
+ */
+ if ((wcslen(name) == 0) ||
+ (strlen(path) == 0))
+ continue;
+
+ /* Load the plugin now */
+ if (stat(path, &stat_buf) != -1) {
+ plugintable[i].hdlPlugin = dlopen(path, RTLD_LAZY);
+ } else {
+ continue;
+ }
+
+ if (plugintable[i].hdlPlugin != NULL) {
+ InitializeFn PassFunc;
+ MP_STATUS status;
+
+ wcsncpy(plugintable[i].pluginName,
+ name, MAX_NAME_SIZE);
+ strncpy(plugintable[i].pluginPath,
+ path, MAX_NAME_SIZE);
+
+ plugintable[i].ownerId = i + 1;
+
+ PassFunc = (InitializeFn)
+ dlsym(plugintable[i].hdlPlugin, "Initialize");
+ if (PassFunc != NULL) {
+ status = PassFunc(plugintable[i].ownerId);
+ }
+
+ i++;
+ }
+ }
+ }
+
+ if (lock_register(fd_mpconf, F_SETLK, F_UNLCK, 0, SEEK_SET, 0) < 0) {
+ fclose(mpconf);
+ close(fd_mpconf);
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return;
+ }
+ fclose(mpconf);
+ close(fd_mpconf);
+
+ number_of_plugins = i;
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+}
+
+/**
+ ******************************************************************************
+ *
+ * Exit by calling Terminate routine of plugin libraries.
+ *
+ * Note: The build of libMPAPI.so should include a linker option to make this
+ * routine executed when it is unloaded.
+ *
+ ******************************************************************************
+ */
+void ExitLibrary()
+{
+ MP_UINT32 i, j;
+
+ if(number_of_plugins == -1)
+ return;
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+ for (i = 0; i < number_of_plugins; i++) {
+ if (plugintable[i].hdlPlugin != NULL) {
+ TerminateFn ExitPassFunc;
+
+ ExitPassFunc = (TerminateFn)
+ dlsym(plugintable[i].hdlPlugin, "Terminate");
+
+ if (ExitPassFunc != NULL) {
+ ExitPassFunc();
+ }
+
+ /* Unload plugin from memory */
+ dlclose(plugintable[i].hdlPlugin);
+ }
+ }
+
+ number_of_plugins = -1;
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ (void) pthread_mutex_destroy(&mp_lib_mutex);
+}
+
+/**
+ ******************************************************************************
+ *
+ * Gets the properties of the MP API library that is being used.
+ *
+ * @param pProps
+ * A pointer to an @ref MP_LIBRARY_PROPERTIES structure allocated by
+ * the caller. On successful return this structure will contain the
+ * properties of the MP library.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or
+ * if an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned if the library properties were successfully returned.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER Returned if @a pProps is NULL or
+ * specifies a memory area to which data cannot be written.
+ *
+ ******************************************************************************
+ */
+MP_STATUS MP_GetLibraryProperties(
+ MP_LIBRARY_PROPERTIES *pProps)
+{
+ char mpPath[MAX_NAME_SIZE];
+
+ if(pProps == NULL) {
+ return MP_STATUS_INVALID_PARAMETER;
+ }
+
+ /* Fill in properties */
+ if (mbstowcs(pProps->buildTime, BUILD_TIME, 256) !=
+ strlen(BUILD_TIME)) {
+ return (MP_STATUS_INVALID_PARAMETER);
+ }
+ pProps->supportedMpVersion = LIBRARY_SUPPORTED_MP_VERSION;
+
+ wcsncpy(pProps->implementationVersion,
+ LIBRARY_IMPLEMENTATION_VERSION, MAX_NAME_SIZE);
+ wcsncpy(pProps->vendor, LIBRARY_VENDOR, MAX_NAME_SIZE);
+
+ snprintf(pProps->fileName, MAX_NAME_SIZE, "%s",
+ LIBRARY_FILE_NAME);
+
+ return MP_STATUS_SUCCESS;
+}
+
+
+/**
+ ******************************************************************************
+ *
+ * Gets a list of the object IDs of all currently loaded plugins.
+ *
+ * @param ppList A pointer to a pointer to an @ref MP_OID_LIST. On successful
+ * return this will contain a pointer to an @ref MP_OID_LIST
+ * which contains the object IDs of all of the plugins currently loaded
+ * by the library.
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error
+ * occurred.
+ * @retval MP_SUCCESS Returned if the plugin ID list was successfully returned.
+ * @retval MP_STATUS_INVALID_PARAMETER Returned if @a ppList is NULL or
+ * specifies a memory area to which data cannot be written.
+ *
+ ******************************************************************************
+ */
+MP_STATUS MP_GetPluginOidList(
+ MP_OID_LIST **ppList)
+{
+ MP_UINT32 i;
+
+ if (ppList == NULL)
+ return (MP_STATUS_INVALID_PARAMETER);
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ if (number_of_plugins == 0) {
+ *ppList = (MP_OID_LIST*)calloc(1, sizeof(MP_OID_LIST));
+ } else {
+ *ppList = (MP_OID_LIST*)calloc(1,
+ sizeof(MP_OID_LIST) + (number_of_plugins - 1)* sizeof(MP_OID) );
+ }
+
+ if ((*ppList) == NULL) {
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ (*ppList)->oidCount = number_of_plugins;
+
+ if (number_of_plugins != 0) {
+ for (i = 0; i < number_of_plugins; i++) {
+ (*ppList)->oids[i].objectType = MP_OBJECT_TYPE_PLUGIN;
+ (*ppList)->oids[i].ownerId = plugintable[i].ownerId;
+ (*ppList)->oids[i].objectSequenceNumber = 0;
+ }
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return MP_STATUS_SUCCESS;
+}
+
+/**
+ *******************************************************************************
+ *
+ * Gets the properties of the specified vendor plugin.
+ *
+ * @param oid
+ * The ID of the plugin whose properties are being retrieved.
+ *
+ * @param pProps
+ * A pointer to an @ref MP_PLUGIN_PROPERTIES structure allocated by
+ * the caller. On successful return this will contain the properties
+ * of the plugin specified by pluginOid.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if an
+ * error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned if the plugin properties were successfully returned.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned if oid has an owner that is not currently known to
+ * the system.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if 'pProps' is NULL or specifies a memory area to
+ * which data cannot be written.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetPluginProperties(
+ MP_OID pluginOid,
+ MP_PLUGIN_PROPERTIES *pProps)
+{
+ MP_GetPluginPropertiesPluginFn PassFunc;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if(pProps == NULL)
+ return (MP_STATUS_INVALID_PARAMETER);
+
+ if ((status = validate_object(pluginOid, MP_OBJECT_TYPE_PLUGIN,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = pluginOid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_GetPluginPropertiesPluginFn)
+ dlsym(plugintable[index].hdlPlugin, "MP_GetPluginPropertiesPlugin");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(pProps);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_FAILED;
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return status;
+}
+
+/**
+ *******************************************************************************
+ *
+ * Gets the object ID for the plugin associated with the specified object ID.
+ *
+ * @param oid
+ * The object ID of an object that has been received from a previous
+ * library call.
+ *
+ * @param pPluginOid
+ * A pointer to an MP_OID structure allocated by the caller. On
+ * successful return this will contain the object ID of the plugin
+ * associated with the object specified by @a objectId.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned if the associated plugin ID was successfully returned.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned if oid does not specify a plugin that is currently known to
+ * the system.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if 'oid' specifies an object not owned by a plugin or
+ * if pPluginOid is NULL or specifies a memory area to which data
+ * cannot be written.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if 'oid' specifies an object with an invalid type.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetAssociatedPluginOid(
+ MP_OID objectId,
+ MP_OID *pPluginId)
+{
+ MP_UINT32 i;
+ MP_STATUS status;
+
+ if (pPluginId == NULL)
+ return (MP_STATUS_INVALID_PARAMETER);
+
+ if ((status = validate_object(objectId, 0, MP_OBJECT_TYPE_ANY)) !=
+ MP_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ pPluginId->objectType = MP_OBJECT_TYPE_PLUGIN;
+ pPluginId->ownerId = objectId.ownerId;
+ pPluginId->objectSequenceNumber = 0;
+
+ return (MP_STATUS_SUCCESS);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Gets the object type of an initialized object ID.
+ *
+ * @param oid
+ * The object ID of an object that has been received from a previous
+ * library call.
+ *
+ * @param pObjectType
+ * A pointer to an MP_OBJECT_TYPE variable allocated by the caller.
+ * On successful return this will contain the object type of oid.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or
+ * if an error occurred.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned if oid has an owner that is not currently known to
+ * the system.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetObjectType(
+ MP_OID oid,
+ MP_OBJECT_TYPE *pObjectType)
+{
+ MP_STATUS status;
+
+ if (pObjectType == NULL)
+ return MP_STATUS_INVALID_PARAMETER;
+
+ if ((status = validate_object(oid, 0, MP_OBJECT_TYPE_ANY))
+ != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ *pObjectType = oid.objectType;
+ return MP_STATUS_SUCCESS;
+}
+
+/**
+ *******************************************************************************
+ *
+ * Gets a list of the object IDs of all the device product properties
+ * associated with this plugin.
+ *
+ * @param oid
+ * The object ID of plugin.
+ *
+ * @param ppList
+ * A pointer to a pointer to an MP_OID_LIST structure.
+ * On a successful return, this will contain a pointer to
+ * an MP_OID_LIST that contains the object IDs of all the device
+ * product descriptors associated with the specified plugin.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if ppList pointer passed as placeholder for holding
+ * the device product list is found to be invalid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned when the plugin for the specified oid is not found.
+ *
+ * @retval MP_STATUS_INSUFFICIENT_MEMORY
+ * Returned when memory allocation failure occurs
+ *
+ * @retval MP_STATUS_UNSUPPORTED
+ * Returned when the API is not supported.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetDeviceProductOidList(
+ MP_OID oid,
+ MP_OID_LIST **ppList)
+{
+ MP_GetDeviceProductOidListPluginFn PassFunc;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if (ppList == NULL)
+ return MP_STATUS_INVALID_PARAMETER;
+
+ if ((status = validate_object(oid, MP_OBJECT_TYPE_PLUGIN,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = oid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_GetDeviceProductOidListPluginFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_GetDeviceProductOidListPlugin");
+ if (PassFunc != NULL) {
+ status = PassFunc(ppList);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_FAILED;
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return status;
+}
+
+/**
+ *******************************************************************************
+ *
+ * Gets the device product properties of the specified plugin oid.
+ *
+ * @param oid
+ * The object ID of the plugin.
+ *
+ * @param ppProps
+ * A pointer to a pointer to an MP_DEVICE_PRODUCT_PROPERTIES structure
+ * allocated by the caller. On successful return it will contain
+ * a pointer to an MP_DEVICE_PRODUCT_PROPERTIES structure allocated
+ * by the library.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if ppProps pointer passed as placeholder for holding
+ * the device product properties is found to be invalid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned when the plugin for the specified oid is not found.
+ *
+ * @retval MP_STATUS_INSUFFICIENT_MEMORY
+ * Returned when memory allocation failure occurs
+ *
+ * @retval MP_STATUS_UNSUPPORTED
+ * Returned when the API is not supported.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetDeviceProductProperties(
+ MP_OID oid,
+ MP_DEVICE_PRODUCT_PROPERTIES *pProps)
+{
+ MP_GetDeviceProductPropertiesFn PassFunc;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if (pProps == NULL)
+ return MP_STATUS_INVALID_PARAMETER;
+
+ if ((status = validate_object(oid, MP_OBJECT_TYPE_DEVICE_PRODUCT,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = oid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_GetDeviceProductPropertiesFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_GetDeviceProductProperties");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(oid, pProps);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_FAILED;
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return status;
+}
+
+/**
+ *******************************************************************************
+ *
+ * Gets a list of the object IDs of all the initiator ports associated
+ * with this plugin.
+ *
+ * @param oid
+ * The object ID of plugin.
+ *
+ * @param ppList
+ * A pointer to a pointer to an MP_OID_LIST structure.
+ * On a successful return, this will contain a pointer to
+ * an MP_OID_LIST that contains the object IDs of all the initiator
+ * ports associated with the specified plugin.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if ppList pointer passed as placeholder for holding
+ * the initiator port list is found to be invalid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned when the plugin for the specified oid is not found.
+ *
+ * @retval MP_STATUS_INSUFFICIENT_MEMORY
+ * Returned when memory allocation failure occurs
+ *
+ * @retval MP_STATUS_UNSUPPORTED
+ * Returned when the API is not supported.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetInitiatorPortOidList(
+ MP_OID oid,
+ MP_OID_LIST **ppList)
+{
+ MP_GetInitiatorPortOidListPluginFn PassFunc;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if (ppList == NULL)
+ return MP_STATUS_INVALID_PARAMETER;
+
+ if ((status = validate_object(oid, MP_OBJECT_TYPE_PLUGIN,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = oid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_GetDeviceProductOidListPluginFn)
+ dlsym(plugintable[index].hdlPlugin, "MP_GetInitiatorPortOidListPlugin");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(ppList);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_FAILED;
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Gets the properties of the specified initiator port.
+ *
+ * @param oid
+ * The object ID of the initiator port.
+ *
+ * @param pProps
+ * A pointer to an MP_INITIATOR_PORT_PROPERTIES structure
+ * allocated by the caller. On successful return, this structure
+ * will contain the properties of the port specified by oid.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pProps is NULL or specifies a memory area to
+ * which data cannot be written.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned if oid has an owner that is not currently known to
+ * the system.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetInitiatorPortProperties(
+ MP_OID oid,
+ MP_INITIATOR_PORT_PROPERTIES *pProps)
+{
+ MP_GetInitiatorPortPropertiesFn PassFunc;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if (pProps == NULL)
+ return MP_STATUS_INVALID_PARAMETER;
+
+ if ((status = validate_object(oid, MP_OBJECT_TYPE_INITIATOR_PORT,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = oid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_GetInitiatorPortPropertiesFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_GetInitiatorPortProperties");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(oid, pProps);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_FAILED;
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return status;
+}
+
+/**
+ *******************************************************************************
+ *
+ * Gets a list of multipath logical units associated to a plugin.
+ *
+ * @param oid
+ * The object ID of plugin.
+ *
+ * @param ppList
+ * A pointer to a pointer to an MP_OID_LIST structure.
+ * On a successful return, this will contain a pointer to
+ * an MP_OID_LIST that contains the object IDs of all the multipath
+ * logical units associated with the specified plugin.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if ppList pointer passed as placeholder for holding
+ * the multipath logical unit list is found to be invalid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned when the plugin for the specified oid is not found.
+ *
+ * @retval MP_STATUS_INSUFFICIENT_MEMORY
+ * Returned when memory allocation failure occurs
+ *
+ * @retval MP_STATUS_UNSUPPORTED
+ * Returned when the API is not supported.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetMultipathLus(
+ MP_OID oid,
+ MP_OID_LIST **ppList)
+{
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if (ppList == NULL)
+ return MP_STATUS_INVALID_PARAMETER;
+
+ if (((status = validate_object(oid, MP_OBJECT_TYPE_PLUGIN,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) &&
+ ((status = validate_object(oid, MP_OBJECT_TYPE_DEVICE_PRODUCT,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS)) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = oid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ if (oid.objectType == MP_OBJECT_TYPE_PLUGIN) {
+ MP_GetMultipathLusPluginFn PassFunc;
+ PassFunc = (MP_GetMultipathLusPluginFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_GetMultipathLusPlugin");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(ppList);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else if (oid.objectType == MP_OBJECT_TYPE_DEVICE_PRODUCT) {
+ MP_GetMultipathLusDevProdFn PassFunc;
+ PassFunc = (MP_GetMultipathLusDevProdFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_GetMultipathLusDevProd");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(oid, ppList);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_INVALID_PARAMETER;
+ }
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+
+/**
+ *******************************************************************************
+ *
+ * Gets the properties of the specified logical unit.
+ *
+ * @param oid
+ * The object ID of the multipath logical unit.
+ *
+ * @param pProps
+ * A pointer to an MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES structure
+ * allocated by the caller. On successful return, this structure
+ * will contain the properties of the port specified by oid.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pProps is NULL or specifies a memory area to
+ * which data cannot be written.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned if oid has an owner that is not currently known to
+ * the system.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetMPLogicalUnitProperties(
+ MP_OID oid,
+ MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES *pProps)
+{
+ MP_GetMPLogicalUnitPropertiesFn PassFunc;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if (pProps == NULL)
+ return MP_STATUS_INVALID_PARAMETER;
+
+ if ((status = validate_object(oid, MP_OBJECT_TYPE_MULTIPATH_LU,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = oid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_GetMPLogicalUnitPropertiesFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_GetMPLogicalUnitProperties");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(oid, pProps);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_FAILED;
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Gets a list of the object IDs of all the path logical units associated
+ * with the specified multipath logical unit, initiator port, or target port.
+ *
+ * @param oid
+ * The object ID of multipath logical unit, initiator port, or
+ * target port.
+ *
+ * @param ppList
+ * A pointer to a pointer to an MP_OID_LIST structure.
+ * On a successful return, this will contain a pointer to
+ * an MP_OID_LIST that contains the object IDs of all the mp path
+ * logical units associated with the specified OID.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if ppList pointer passed as placeholder for holding
+ * the device product list is found to be invalid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned when the plugin for the specified oid is not found.
+ *
+ * @retval MP_STATUS_INSUFFICIENT_MEMORY
+ * Returned when memory allocation failure occurs
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned if oid has an owner that is not currently known to
+ * the system.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetAssociatedPathOidList(
+ MP_OID oid,
+ MP_OID_LIST **ppList)
+{
+ MP_GetAssociatedPathOidListFn PassFunc;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if (ppList == NULL)
+ return MP_STATUS_INVALID_PARAMETER;
+
+ if (((status = validate_object(oid, MP_OBJECT_TYPE_INITIATOR_PORT,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) &&
+ ((status = validate_object(oid, MP_OBJECT_TYPE_TARGET_PORT,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) &&
+ ((status = validate_object(oid, MP_OBJECT_TYPE_MULTIPATH_LU,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS)) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = oid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_GetAssociatedPathOidListFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_GetAssociatedPathOidList");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(oid, ppList);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_FAILED;
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Gets the properties of the specified path logical unit.
+ *
+ * @param oid
+ * The object ID of the path logical unit.
+ *
+ * @param pProps
+ * A pointer to an MP_PATH_LOGICAL_UNIT_PROPERTIES structure
+ * allocated by the caller. On successful return, this structure
+ * will contain the properties of the port specified by oid.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pProps is NULL or specifies a memory area to
+ * which data cannot be written.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned if oid has an owner that is not currently known to
+ * the system.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetPathLogicalUnitProperties(
+ MP_OID oid,
+ MP_PATH_LOGICAL_UNIT_PROPERTIES *pProps)
+{
+ MP_GetPathLogicalUnitPropertiesFn PassFunc;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if (pProps == NULL)
+ return MP_STATUS_INVALID_PARAMETER;
+
+ if ((status = validate_object(oid, MP_OBJECT_TYPE_PATH_LU,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = oid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_GetPathLogicalUnitPropertiesFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_GetPathLogicalUnitProperties");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(oid, pProps);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_FAILED;
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Gets a list of the object IDs of all the target port group associated
+ * with the specified multipath logical unit.
+ *
+ * @param oid
+ * The object ID of the multiple logical unit.
+ *
+ * @param ppList
+ * A pointer to a pointer to an MP_OID_LIST structure.
+ * On a successful return, this will contain a pointer to
+ * an MP_OID_LIST that contains the object IDs of all the target
+ * port group associated with the specified multipath logical unit.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if ppList pointer passed as placeholder for holding
+ * the target port group list is found to be invalid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned when the plugin for the specified oid is not found.
+ *
+ * @retval MP_STATUS_INSUFFICIENT_MEMORY
+ * Returned when memory allocation failure occurs
+ *
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetAssociatedTPGOidList(
+ MP_OID oid,
+ MP_OID_LIST **ppList)
+{
+ MP_GetAssociatedTPGOidListFn PassFunc;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if (ppList == NULL)
+ return MP_STATUS_INVALID_PARAMETER;
+
+ if ((status = validate_object(oid, MP_OBJECT_TYPE_MULTIPATH_LU,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = oid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_GetAssociatedTPGOidListFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_GetAssociatedTPGOidList");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(oid, ppList);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_FAILED;
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Gets the properties of the specified target port group.
+ *
+ * @param oid
+ * The object ID of the target port group.
+ *
+ * @param pProps
+ * A pointer to an MP_TARGET_PORT_GROUP_PROPERTIES structure
+ * allocated by the caller. On successful return, this structure
+ * will contain the properties of the port specified by oid.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pProps is NULL or specifies a memory area to
+ * which data cannot be written.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned if oid has an owner that is not currently known to
+ * the system.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetTargetPortGroupProperties(
+ MP_OID oid,
+ MP_TARGET_PORT_GROUP_PROPERTIES *pProps)
+{
+ MP_GetTargetPortGroupPropertiesFn PassFunc;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if (pProps == NULL)
+ return MP_STATUS_INVALID_PARAMETER;
+
+ if ((status = validate_object(oid, MP_OBJECT_TYPE_TARGET_PORT_GROUP,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = oid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_GetTargetPortGroupPropertiesFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_GetTargetPortGroupProperties");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(oid, pProps);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_FAILED;
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Gets a list of multipath logical units associated with the specific target
+ * port group.
+ *
+ * @param oid
+ * The object ID of the target port group.
+ *
+ * @param ppList
+ * A pointer to a pointer to an MP_OID_LIST structure.
+ * On a successful return, this will contain a pointer to
+ * an MP_OID_LIST that contains the object IDs of all the multipath
+ * logical units associated with the specified target port group.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if ppList pointer passed as placeholder for holding
+ * the multipath logical unit list is found to be invalid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned when the plugin for the specified oid is not found.
+ *
+ * @retval MP_STATUS_INSUFFICIENT_MEMORY
+ * Returned when memory allocation failure occurs
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetMPLuOidListFromTPG(
+ MP_OID oid,
+ MP_OID_LIST **ppList)
+{
+ MP_GetMPLuOidListFromTPGFn PassFunc;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if (ppList == NULL)
+ return MP_STATUS_INVALID_PARAMETER;
+
+ if ((status = validate_object(oid, MP_OBJECT_TYPE_TARGET_PORT_GROUP,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = oid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_GetMPLuOidListFromTPGFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_GetMPLuOidListFromTPG");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(oid, ppList);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_FAILED;
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Gets a list of the object IDs of all the proprietary load balance
+ * algorithms associated with this plugin.
+ *
+ * @param oid
+ * The object ID of the plugin.
+ *
+ * @param ppList
+ * A pointer to a pointer to an MP_OID_LIST structure.
+ * On a successful return, this will contain a pointer to
+ * an MP_OID_LIST that contains the object IDs of all the proprietary
+ * load balance algorithms associated with the specified plugin.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if ppList pointer passed as placeholder for holding
+ * the proprietary load balance oid list is found to be invalid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned when the plugin for the specified oid is not found.
+ *
+ * @retval MP_STATUS_INSUFFICIENT_MEMORY
+ * Returned when memory allocation failure occurs
+ *
+ * @retval MP_STATUS_UNSUPPORTED
+ * Returned when the API is not supported.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetProprietaryLoadBalanceOidList(
+ MP_OID oid,
+ MP_OID_LIST **ppList)
+{
+ MP_GetProprietaryLoadBalanceOidListPluginFn PassFunc;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if (ppList == NULL)
+ return MP_STATUS_INVALID_PARAMETER;
+
+ if ((status = validate_object(oid, MP_OBJECT_TYPE_PLUGIN,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = oid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_GetProprietaryLoadBalanceOidListPluginFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_GetProprietaryLoadBalanceOidListPlugin");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(ppList);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_FAILED;
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Gets the properties of the specified load balance properties structure.
+ *
+ * @param oid
+ * The object ID of the load balance properties structure.
+ *
+ * @param pProps
+ * A pointer to an MP_LOAD_BALANCE_PROPRIETARY_TYPE structure
+ * allocated by the caller. On successful return, this structure
+ * will contain the properties of the proprietary load balance algorithm
+ * specified by oid.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pProps is NULL or specifies a memory area to
+ * which data cannot be written.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned if oid has an owner that is not currently known to
+ * the system.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetProprietaryLoadBalanceProperties (
+ MP_OID oid,
+ MP_PROPRIETARY_LOAD_BALANCE_PROPERTIES *pProps)
+{
+ MP_GetProprietaryLoadBalancePropertiesFn PassFunc;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if (pProps == NULL)
+ return MP_STATUS_INVALID_PARAMETER;
+
+ if ((status = validate_object(oid, MP_OBJECT_TYPE_PROPRIETARY_LOAD_BALANCE,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = oid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_GetProprietaryLoadBalancePropertiesFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_GetProprietaryLoadBalanceProperties");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(oid, pProps);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_FAILED;
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Gets a list of the object IDs of the target ports in the specified target
+ * port group.
+ *
+ * @param oid
+ * The object ID of the target port group.
+ *
+ * @param ppList
+ * A pointer to a pointer to an MP_OID_LIST structure.
+ * On a successful return, this will contain a pointer to
+ * an MP_OID_LIST that contains the object IDs of all the target ports
+ * associated with the specified target port group.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if ppList pointer passed as placeholder for holding
+ * the multipath logical unit list is found to be invalid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned when the plugin for the specified oid is not found.
+ *
+ * @retval MP_STATUS_INSUFFICIENT_MEMORY
+ * Returned when memory allocation failure occurs
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetTargetPortOidList(
+ MP_OID oid,
+ MP_OID_LIST **ppList)
+{
+ MP_GetTargetPortOidListFn PassFunc;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if (ppList == NULL)
+ return MP_STATUS_INVALID_PARAMETER;
+
+ if ((status = validate_object(oid, MP_OBJECT_TYPE_TARGET_PORT_GROUP,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = oid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_GetTargetPortOidListFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_GetTargetPortOidList");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(oid, ppList);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_FAILED;
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Gets the properties of the specified target port.
+ *
+ * @param oid
+ * The object ID of the target port.
+ *
+ * @param pProps
+ * A pointer to an MP_TARGET_PORT_PROPERTIES structure
+ * allocated by the caller. On successful return, this structure
+ * will contain the properties of the port specified by oid.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pProps is NULL or specifies a memory area to
+ * which data cannot be written.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned if oid has an owner that is not currently known to
+ * the system.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetTargetPortProperties(
+ MP_OID oid,
+ MP_TARGET_PORT_PROPERTIES *pProps)
+{
+ MP_GetTargetPortPropertiesFn PassFunc;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if (pProps == NULL)
+ return MP_STATUS_INVALID_PARAMETER;
+
+ if ((status = validate_object(oid, MP_OBJECT_TYPE_TARGET_PORT,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = oid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_GetTargetPortPropertiesFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_GetTargetPortProperties");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(oid, pProps);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_FAILED;
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+
+/**
+ *******************************************************************************
+ *
+ * Assign a multipath logical unit to a target port group.
+ *
+ * @param tpgOid
+ * An MP_TARGET_PORT_GROUP oid. The target port group currently in
+ * active access state that the administrator would like the LU
+ * assigned to.
+ *
+ * @param luOid
+ * An MP_MULTIPATH_LOGICAL_UNIT oid.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned when luOid is not associated with tpgOid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned if oid has an owner that is not currently known to
+ * the system.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_AssignLogicalUnitToTPG(
+ MP_OID tpgOid,
+ MP_OID luOid)
+{
+ MP_AssignLogicalUnitToTPGFn PassFunc;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if (luOid.ownerId != tpgOid.ownerId) {
+ return (MP_STATUS_INVALID_PARAMETER);
+ }
+
+ if ((status = validate_object(tpgOid, MP_OBJECT_TYPE_TARGET_PORT_GROUP,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ if ((status = validate_object(luOid, MP_OBJECT_TYPE_MULTIPATH_LU,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = tpgOid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_AssignLogicalUnitToTPGFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_AssignLogicalUnitToTPG");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(tpgOid, luOid);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_FAILED;
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Manually override the path for a logical unit. The path exclusively used to
+ * access the logical unit until cleared.
+ *
+ * @param logicalUnitOid
+ * The object ID of the multipath logical unit.
+ *
+ * @param pathOid
+ * The object ID of the path logical unit.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if the oid of the object is not valid
+ *
+ * @retval MP_STATUS_UNSUPPORTED
+ * Returned when the implementation does not support the API
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_PATH_NONOPERATIONAL
+ * Returned when the driver cannot communicate through selected path.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_SetOverridePath(
+ MP_OID logicalUnitOid,
+ MP_OID pathOid)
+{
+ MP_SetOverridePathFn PassFunc;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if ((status = validate_object(logicalUnitOid, MP_OBJECT_TYPE_MULTIPATH_LU,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+ if ((status = validate_object(pathOid, MP_OBJECT_TYPE_PATH_LU,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = pathOid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_SetOverridePathFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_SetOverridePath");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(logicalUnitOid, pathOid);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_FAILED;
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Cancel a path override and re-enable load balancing.
+ *
+ * @param luOid
+ * An MP_MULTIPATH_LOGICAL_UNIT oid.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if MP_MULTIPATH_LOGICAL_UNIT with the luOid is not found.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned if oid has an owner that is not currently known to
+ * the system.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_CancelOverridePath(
+ MP_OID luOid)
+{
+ MP_CancelOverridePathFn PassFunc;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if ((status = validate_object(luOid, MP_OBJECT_TYPE_MULTIPATH_LU,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = luOid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_CancelOverridePathFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_CancelOverridePath");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(luOid);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_FAILED;
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Enables Auto-failback.
+ *
+ * @param oid
+ * The oid of the plugin.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if oid is NULL or specifies a memory area that is not
+ * a valid plugin oid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_EnableAutoFailback(
+ MP_OID oid)
+{
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if (((status = validate_object(oid, MP_OBJECT_TYPE_PLUGIN,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) &&
+ ((status = validate_object(oid, MP_OBJECT_TYPE_MULTIPATH_LU,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS)) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = oid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ if (oid.objectType == MP_OBJECT_TYPE_PLUGIN) {
+ MP_EnableAutoFailbackPluginFn PassFunc;
+ PassFunc = (MP_EnableAutoFailbackPluginFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_EnableAutoFailbackPlugin");
+
+ if (PassFunc != NULL) {
+ status = PassFunc();
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else if (oid.objectType == MP_OBJECT_TYPE_MULTIPATH_LU) {
+ MP_EnableAutoFailbackLuFn PassFunc;
+ PassFunc = (MP_EnableAutoFailbackLuFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_EnableAutoFailbackLu");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(oid);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_INVALID_PARAMETER;
+ }
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Enables Auto-probing.
+ *
+ * @param oid
+ * The oid of the plugin or the multipath logical unit.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if oid is NULL or specifies a memory area that is not
+ * a valid plugin oid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_EnableAutoProbing(
+ MP_OID oid)
+{
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if (((status = validate_object(oid, MP_OBJECT_TYPE_PLUGIN,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) &&
+ ((status = validate_object(oid, MP_OBJECT_TYPE_MULTIPATH_LU,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS)) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = oid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ if (oid.objectType == MP_OBJECT_TYPE_PLUGIN) {
+ MP_EnableAutoProbingPluginFn PassFunc;
+ PassFunc = (MP_EnableAutoProbingPluginFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_EnableAutoProbingPlugin");
+
+ if (PassFunc != NULL) {
+ status = PassFunc();
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else if (oid.objectType == MP_OBJECT_TYPE_MULTIPATH_LU) {
+ MP_EnableAutoProbingLuFn PassFunc;
+ PassFunc = (MP_EnableAutoProbingLuFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_EnableAutoProbingLu");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(oid);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_INVALID_PARAMETER;
+ }
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Disables Auto-failback.
+ *
+ * @param oid
+ * The oid of the plugin.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if oid is NULL or specifies a memory area that is not
+ * a valid plugin oid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_DisableAutoFailback(
+ MP_OID oid)
+{
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if (((status = validate_object(oid, MP_OBJECT_TYPE_PLUGIN,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) &&
+ ((status = validate_object(oid, MP_OBJECT_TYPE_MULTIPATH_LU,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS)) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = oid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ if (oid.objectType == MP_OBJECT_TYPE_PLUGIN) {
+ MP_DisableAutoFailbackPluginFn PassFunc;
+ PassFunc = (MP_DisableAutoFailbackPluginFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_DisableAutoFailbackPlugin");
+
+ if (PassFunc != NULL) {
+ status = PassFunc();
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else if (oid.objectType == MP_OBJECT_TYPE_MULTIPATH_LU) {
+ MP_DisableAutoFailbackLuFn PassFunc;
+ PassFunc = (MP_DisableAutoFailbackLuFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_DisableAutoFailbackLu");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(oid);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_INVALID_PARAMETER;
+ }
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Disables Auto-probing.
+ *
+ * @param oid
+ * The oid of the plugin or the multipath logical unit.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if oid is NULL or specifies a memory area that is not
+ * a valid plugin oid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_DisableAutoProbing(
+ MP_OID oid)
+{
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if (((status = validate_object(oid, MP_OBJECT_TYPE_PLUGIN,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) &&
+ ((status = validate_object(oid, MP_OBJECT_TYPE_MULTIPATH_LU,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS)) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = oid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ if (oid.objectType == MP_OBJECT_TYPE_PLUGIN) {
+ MP_DisableAutoProbingPluginFn PassFunc;
+ PassFunc = (MP_DisableAutoProbingPluginFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_DisableAutoProbingPlugin");
+
+ if (PassFunc != NULL) {
+ status = PassFunc();
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else if (oid.objectType == MP_OBJECT_TYPE_MULTIPATH_LU) {
+ MP_DisableAutoFailbackLuFn PassFunc;
+ PassFunc = (MP_DisableAutoProbingLuFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_DisableAutoProbingLu");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(oid);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_INVALID_PARAMETER;
+ }
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Enables a path. This API may cause failover in a logical unit with
+ * asymmetric access.
+ *
+ * @param oid
+ * The oid of the path.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if oid is NULL or specifies a memory area that is not
+ * a valid path oid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_EnablePath(
+ MP_OID oid)
+{
+ MP_EnablePathFn PassFunc;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if ((status = validate_object(oid, MP_OBJECT_TYPE_PATH_LU,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = oid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_EnablePathFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_EnablePath");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(oid);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_FAILED;
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Disables a path. This API may cause failover in a logical unit with
+ * asymmetric access. This API may cause a logical unit to become unavailable.
+ *
+ * @param oid
+ * The oid of the path.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if oid is NULL or specifies a memory area that is not
+ * a valid path oid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_DisablePath(
+ MP_OID oid)
+{
+ MP_DisablePathFn PassFunc;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if ((status = validate_object(oid, MP_OBJECT_TYPE_PATH_LU,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = oid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_DisablePathFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_DisablePath");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(oid);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_FAILED;
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Set the multipath logical unit s load balancing policy.
+ *
+ * @param logicalUnitoid
+ * The object ID of the multipath logical unit.
+ *
+ * @param loadBanlance
+ * The desired load balance policy for the specified logical unit.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if no MP_MULTIPATH_LOGICAL_UNIT associated with
+ * @ref ligicalUnitrOid is found or invalid MP_LOAD_BALANCE_TYPE is
+ * specified.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned when the specified loadBalance type cannot be handled
+ * by the plugin.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_SetLogicalUnitLoadBalanceType(
+ MP_OID logicalUnitOid,
+ MP_LOAD_BALANCE_TYPE loadBalance)
+{
+ MP_SetLogicalUnitLoadBalanceTypeFn PassFunc;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if ((status = validate_object(logicalUnitOid,
+ MP_OBJECT_TYPE_MULTIPATH_LU,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = logicalUnitOid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_SetLogicalUnitLoadBalanceTypeFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_SetLogicalUnitLoadBalanceType");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(logicalUnitOid, loadBalance);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_FAILED;
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Set the weight to be assigned to a particular path.
+ *
+ * @param pathOid
+ * The object ID of the path logical unit.
+ *
+ * @param weight
+ * weight that will be assigned to the path logical unit.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned when the MP Path specified by the PathOid could not be
+ * found.
+ *
+ * @retval MP_STATUS_UNSUPPORTED
+ * Returned when the implementation does not support the API
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned when the operation failed.
+ *
+ * @retval MP_STATUS_PATH_NONOPERATIONAL
+ * Returned when the driver cannot communicate through selected path.
+ *
+ * @retval MP_STATUS_INVALID_WEIGHT
+ * Returned when the weight parameter is greater than the plugin's
+ * maxWeight property.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_SetPathWeight(
+ MP_OID pathOid,
+ MP_UINT32 weight)
+{
+ MP_SetPathWeightFn PassFunc;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if ((status = validate_object(pathOid, MP_OBJECT_TYPE_PATH_LU,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = pathOid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_SetPathWeightFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_SetPathWeight");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(pathOid, weight);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_FAILED;
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Set the default load balance policy for the plugin.
+ *
+ * @param oid
+ * The object ID of the plugin
+ *
+ * @param loadBalance
+ * The desired default load balance policy for the specified plugin.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned when the the plugin specified by @ref oid could not be
+ * found.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if the oid of the object is not valid.
+ *
+ * @retval MP_STATUS_UNSUPPORTED
+ * Returned when the implementation does not support the API
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned when the specified loadBalance type cannot be handled
+ * by the plugin.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_SetPluginLoadBalanceType(
+ MP_OID oid,
+ MP_LOAD_BALANCE_TYPE loadBalance)
+{
+ MP_SetPluginLoadBalanceTypePluginFn PassFunc;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if ((status = validate_object(oid, MP_OBJECT_TYPE_PLUGIN,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = oid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_SetPluginLoadBalanceTypePluginFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_SetPluginLoadBalanceTypePlugin");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(loadBalance);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_FAILED;
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Set the failback polling rates. Setting both rates to zero disables polling.
+ *
+ * @param pluginOid
+ * The object ID of the plugin or multipath lu.
+ *
+ * @param pollingRate
+ * The value to be set in MP_PLUGIN_PROPERTIES currentPollingRate.or
+ * MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES pollingRate.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned when the the plugin specified by @ref oid could not be
+ * found.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if one of the polling values is outside the range
+ * supported by the driver.
+ *
+ * @retval MP_STATUS_UNSUPPORTED
+ * Returned when the implementation does not support the API
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_SetFailbackPollingRate(
+ MP_OID oid,
+ MP_UINT32 pollingRate)
+{
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if (((status = validate_object(oid, MP_OBJECT_TYPE_PLUGIN,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) &&
+ ((status = validate_object(oid, MP_OBJECT_TYPE_MULTIPATH_LU,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS)) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = oid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ if (oid.objectType == MP_OBJECT_TYPE_PLUGIN) {
+ MP_SetFailbackPollingRatePluginFn PassFunc;
+ PassFunc = (MP_SetFailbackPollingRatePluginFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_SetFailbackPollingRatePlugin");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(pollingRate);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else if (oid.objectType == MP_OBJECT_TYPE_MULTIPATH_LU) {
+ MP_SetFailbackPollingRateLuFn PassFunc;
+ PassFunc = (MP_SetFailbackPollingRateLuFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_SetFailbackPollingRateLu");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(oid, pollingRate);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_INVALID_PARAMETER;
+ }
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Set the probing polling rates. Setting both rates to zero disables polling.
+ *
+ * @param pluginOid
+ * The object ID of either the plugin or a multipath logical unit.
+ *
+ * @param pollingRate
+ * The value to be set in MP_PLUGIN_PROPERTIES current pollingRate or
+ * MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES pollingRate.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned when the the plugin specified by @ref oid could not be
+ * found.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if one of the polling values is outside the range
+ * supported by the driver.
+ *
+ * @retval MP_STATUS_UNSUPPORTED
+ * Returned when the implementation does not support the API
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_SetProbingPollingRate(
+ MP_OID oid,
+ MP_UINT32 pollingRate)
+{
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if (((status = validate_object(oid, MP_OBJECT_TYPE_PLUGIN,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) &&
+ ((status = validate_object(oid, MP_OBJECT_TYPE_MULTIPATH_LU,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS)) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = oid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ if (oid.objectType == MP_OBJECT_TYPE_PLUGIN) {
+ MP_SetProbingPollingRatePluginFn PassFunc;
+ PassFunc = (MP_SetProbingPollingRatePluginFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_SetProbingPollingRatePlugin");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(pollingRate);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else if (oid.objectType == MP_OBJECT_TYPE_MULTIPATH_LU) {
+ MP_SetProbingPollingRateLuFn PassFunc;
+ PassFunc = (MP_SetProbingPollingRateLuFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_SetProbingPollingRateLu");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(oid, pollingRate);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_INVALID_PARAMETER;
+ }
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Set proprietary properties in supported object instances.
+ *
+ * @param pluginOid
+ * The object ID of MP_LOAD_BALANCE_PROPRIETARY_TYPE, MP_PLUGIN_PROPERTIES
+ * or MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES.
+ *
+ * @param count
+ * The number of valid items in pPropertyList.
+ *
+ * @param pPropertyList
+ * A pointer to an array of property name/value pairs. This array must
+ * contain the same number of elements as count.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned when the the plugin specified by @ref oid could not be
+ * found.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if one of the polling values is outside the range
+ * supported by the driver.
+ *
+ * @retval MP_STATUS_UNSUPPORTED
+ * Returned when the implementation does not support the API
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_SetProprietaryProperties(
+ MP_OID oid,
+ MP_UINT32 count,
+ MP_PROPRIETARY_PROPERTY *pPropertyList)
+{
+ MP_SetProprietaryPropertiesFn PassFunc;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if (((status = validate_object(oid, MP_OBJECT_TYPE_PLUGIN,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) &&
+ ((status = validate_object(oid, MP_OBJECT_TYPE_MULTIPATH_LU,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) &&
+ ((status = validate_object(oid, MP_OBJECT_TYPE_PROPRIETARY_LOAD_BALANCE,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS)) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = oid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_SetProprietaryPropertiesFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_SetProprietaryProperties");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(oid, count, pPropertyList);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_FAILED;
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Set the access state for a list of target port groups. This allows
+ * a client to force a failover or failback to a desired set of target port
+ * groups.
+ *
+ * @param luOid
+ * The object ID of the logical unit where the command is sent.
+ *
+ * @param count
+ * The number of valid items in the pTpgStateList.
+ *
+ * @param pTpgStateList
+ * A pointer to an array of TPG/access-state values. This array must
+ * contain the same number of elements as @ref count.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned when the MP_MULTIPATH_LOGICAL_UNIT associated with @ref
+ * oid could not be found.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pTpgStateList is null or if one of the TPGs referenced
+ * in the list is not associated with the specified MP logical unit.
+ *
+ * @retval MP_STATUS_UNSUPPORTED
+ * Returned when the implementation does not support the API
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_ACCESS_STATE_INVALID
+ * Returned if the target device returns a status indicating the caller
+ * is attempting to establish an illegal combination of access states.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned if the underlying interface failed the commend for some
+ * reason other than MP_STATUS_ACCESS_STATE_INVALID
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_SetTPGAccess(
+ MP_OID luOid,
+ MP_UINT32 count,
+ MP_TPG_STATE_PAIR *pTpgStateList)
+{
+ MP_SetTPGAccessFn PassFunc;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if ((status = validate_object(luOid, MP_OBJECT_TYPE_MULTIPATH_LU,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ index = luOid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_SetTPGAccessFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_SetTPGAccess");
+
+ if (PassFunc != NULL) {
+ status = PassFunc(luOid, count, pTpgStateList);
+ } else {
+ status = MP_STATUS_UNSUPPORTED;
+ }
+ } else {
+ status = MP_STATUS_FAILED;
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Registers a client function that is to be called
+ * whenever the property of an an object changes.
+ *
+ * @param pClientFn,
+ * A pointer to an MP_OBJECT_PROPERTY_FN function defined by the
+ * client. On successful return this function will be called to
+ * inform the client of objects that have had one or more properties
+ * change.
+ *
+ * @param objectType
+ * The type of object the client wishes to deregister for
+ * property change callbacks. If null, then all objects types are
+ * deregistered.
+ *
+ * @param pCallerData
+ * A pointer that is passed to the callback routine with each event.
+ * This may be used by the caller to correlate the event to source of
+ * the registration.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pClientFn is NULL or specifies a memory area
+ * that is not executable.
+ *
+ * @retval MP_STATUS_FN_REPLACED
+ * Returned when an existing client function is replaced with the one
+ * specified in pClientFn.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_RegisterForObjectPropertyChanges(
+ MP_OBJECT_PROPERTY_FN pClientFn,
+ MP_OBJECT_TYPE objectType,
+ void *pCallerData,
+ MP_OID pluginOid)
+{
+ MP_RegisterForObjectPropertyChangesPluginFn PassFunc;
+ MP_UINT32 i;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if (pClientFn == NULL) {
+ return (MP_STATUS_INVALID_PARAMETER);
+ }
+
+ if (objectType > MP_OBJECT_TYPE_MAX) {
+ return (MP_STATUS_INVALID_OBJECT_TYPE);
+ }
+
+ if (!(is_zero_oid(pluginOid))) {
+ if ((status = validate_object(pluginOid, MP_OBJECT_TYPE_PLUGIN,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ if (is_zero_oid(pluginOid)) {
+ for (i = 0; i < number_of_plugins; i++) {
+ if (plugintable[i].hdlPlugin != NULL) {
+ PassFunc = (MP_RegisterForObjectPropertyChangesPluginFn)
+ dlsym(plugintable[i].hdlPlugin,
+ "MP_RegisterForObjectPropertyChangesPlugin");
+ }
+
+ if (PassFunc != NULL) {
+ status =
+ PassFunc(pClientFn, objectType, pCallerData);
+ /* ignore an error and continue */
+ }
+ }
+ } else {
+ index = pluginOid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_RegisterForObjectPropertyChangesPluginFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_RegisterForObjectPropertyChangesPlugin");
+ }
+
+ if (PassFunc != NULL) {
+ status = PassFunc(pClientFn, objectType, pCallerData);
+ }
+ }
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Deregisters a previously registered client function that is to be invoked
+ * whenever an object's property changes.
+ *
+ * @param pClientFn,
+ * A pointer to an MP_OBJECT_PROPERTY_FN function defined by the
+ * client that was previously registered using
+ * the MP_RegisterForObjectPropertyChanges API. On successful return
+ * this function will no longer be called to inform the client of
+ * object property changes.
+ *
+ * @param objectType
+ * The type of object the client wishes to deregister for
+ * property change callbacks. If null, then all objects types are
+ * deregistered.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pClientFn is NULL or specifies a memory area
+ * that is not executable.
+ *
+ * @retval MP_STATUS_UNKNOWN_FN
+ * Returned if pClientFn is not the same as the previously registered
+ * function.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned if pClientFn deregistration is not possible at this time.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_DeregisterForObjectPropertyChanges(
+ MP_OBJECT_PROPERTY_FN pClientFn,
+ MP_OBJECT_TYPE objectType,
+ MP_OID pluginOid)
+{
+ MP_DeregisterForObjectPropertyChangesPluginFn PassFunc;
+ MP_UINT32 i;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if (pClientFn == NULL) {
+ return (MP_STATUS_INVALID_PARAMETER);
+ }
+
+ if (objectType > MP_OBJECT_TYPE_MAX) {
+ return (MP_STATUS_INVALID_OBJECT_TYPE);
+ }
+
+ if (!(is_zero_oid(pluginOid))) {
+ if ((status = validate_object(pluginOid, MP_OBJECT_TYPE_PLUGIN,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ if (is_zero_oid(pluginOid)) {
+ for (i = 0; i < number_of_plugins; i++) {
+ if (plugintable[i].hdlPlugin != NULL) {
+ PassFunc = (MP_DeregisterForObjectPropertyChangesPluginFn)
+ dlsym(plugintable[i].hdlPlugin,
+ "MP_DeregisterForObjectPropertyChangesPlugin");
+ }
+
+ if (PassFunc != NULL) {
+ status = PassFunc(pClientFn, objectType);
+ }
+ }
+ } else {
+ index = pluginOid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_DeregisterForObjectPropertyChangesPluginFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_DeregisterForObjectPropertyChangesPlugin");
+ }
+
+ if (PassFunc != NULL) {
+ status = PassFunc(pClientFn, objectType);
+ }
+ }
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Registers a client function that is to be called
+ * whenever a high level object appears or disappears.
+ *
+ * @param pClientFn,
+ * A pointer to an MP_OBJECT_VISIBILITY_FN function defined by the
+ * client. On successful return this function will be called to
+ * inform the client of objects whose visibility has changed.
+ *
+ * @param objectType
+ * The type of object the client wishes to deregister for
+ * property change callbacks. If null, then all objects types are
+ * deregistered.
+ *
+ * @param pCallerData
+ * A pointer that is passed to the callback routine with each event.
+ * This may be used by the caller to correlate the event to source of
+ * the registration.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pClientFn is NULL or specifies a memory area
+ * that is not executable.
+ *
+ * @retval MP_STATUS_FN_REPLACED
+ * Returned when an existing client function is replaced with the one
+ * specified in pClientFn.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if objectType does not specify any valid object type.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_RegisterForObjectVisibilityChanges(
+ MP_OBJECT_VISIBILITY_FN pClientFn,
+ MP_OBJECT_TYPE objectType,
+ void *pCallerData,
+ MP_OID pluginOid)
+{
+ MP_RegisterForObjectVisibilityChangesPluginFn PassFunc;
+ MP_UINT32 i;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if (pClientFn == NULL) {
+ return (MP_STATUS_INVALID_PARAMETER);
+ }
+
+ if (objectType > MP_OBJECT_TYPE_MAX) {
+ return (MP_STATUS_INVALID_OBJECT_TYPE);
+ }
+
+ if (!(is_zero_oid(pluginOid))) {
+ if ((status = validate_object(pluginOid, MP_OBJECT_TYPE_PLUGIN,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ if (is_zero_oid(pluginOid)) {
+ for (i = 0; i < number_of_plugins; i++) {
+ if (plugintable[i].hdlPlugin != NULL) {
+ PassFunc = (MP_RegisterForObjectVisibilityChangesPluginFn)
+ dlsym(plugintable[i].hdlPlugin,
+ "MP_RegisterForObjectVisibilityChangesPlugin");
+ }
+
+ if (PassFunc != NULL) {
+ status = PassFunc(pClientFn, objectType, pCallerData);
+ /* ignore an error and continue. */
+ }
+ }
+ } else {
+ index = pluginOid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_RegisterForObjectVisibilityChangesPluginFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_RegisterForObjectVisibilityChangesPlugin");
+ }
+
+ if (PassFunc != NULL) {
+ status = PassFunc(pClientFn, objectType, pCallerData);
+ }
+ }
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+
+}
+
+/**
+ *******************************************************************************
+ *
+ * Deregisters a previously registered client function that is to be invoked
+ * whenever a high level object appears or disappears.
+ *
+ * @param pClientFn,
+ * A pointer to an MP_OBJECT_VISIBILITY_FN function defined by the
+ * client that was previously registered using
+ * the MP_RegisterForObjectVisibilityChanges API. On successful return
+ * this function will no longer be called to inform the client of
+ * object property changes.
+ *
+ * @param objectType
+ * The type of object the client wishes to deregister for visibility
+ * change callbacks. If null, then all objects types are
+ * deregistered.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pClientFn is NULL or specifies a memory area
+ * that is not executable.
+ *
+ * @retval MP_STATUS_UNKNOWN_FN
+ * Returned if pClientFn is not the same as the previously registered
+ * function.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if objectType does not specify any valid object type.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned if pClientFn deregistration is not possible at this time.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_DeregisterForObjectVisibilityChanges(
+ MP_OBJECT_VISIBILITY_FN pClientFn,
+ MP_OBJECT_TYPE objectType,
+ MP_OID pluginOid)
+{
+ MP_DeregisterForObjectVisibilityChangesPluginFn PassFunc;
+ MP_UINT32 i;
+ MP_UINT32 index;
+ MP_STATUS status;
+
+ if (pClientFn == NULL) {
+ return (MP_STATUS_INVALID_PARAMETER);
+ }
+
+ if (objectType > MP_OBJECT_TYPE_MAX) {
+ return (MP_STATUS_INVALID_OBJECT_TYPE);
+ }
+
+ if (!(is_zero_oid(pluginOid))) {
+ if ((status = validate_object(pluginOid, MP_OBJECT_TYPE_PLUGIN,
+ MP_OBJECT_TYPE_MATCH)) != MP_STATUS_SUCCESS) {
+ return (status);
+ }
+ }
+
+ (void) pthread_mutex_lock(&mp_lib_mutex);
+
+ if (is_zero_oid(pluginOid)) {
+ for (i = 0; i < number_of_plugins; i++) {
+ if (plugintable[i].hdlPlugin != NULL) {
+ PassFunc = (MP_DeregisterForObjectVisibilityChangesPluginFn)
+ dlsym(plugintable[i].hdlPlugin,
+ "MP_DeregisterForObjectVisibilityChangesPlugin");
+ if (PassFunc != NULL) {
+ status = PassFunc(pClientFn, objectType);
+ }
+ }
+ }
+ } else {
+ index = pluginOid.ownerId - 1;
+ if (plugintable[index].hdlPlugin != NULL) {
+ PassFunc = (MP_DeregisterForObjectVisibilityChangesPluginFn)
+ dlsym(plugintable[index].hdlPlugin,
+ "MP_DeregisterForObjectVisibilityChangesPlugin");
+ if (PassFunc != NULL) {
+ status = PassFunc(pClientFn, objectType);
+ }
+ }
+ }
+
+ (void) pthread_mutex_unlock(&mp_lib_mutex);
+ return (status);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Compare two Oids for equality to see whether they refer to the same object.
+ *
+ * @param oid1
+ * Oid to compare.
+ *
+ * @param oid2
+ * Oid to compare.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the two Oids do refer to the same object.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned if the Oids don't compare.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_CompareOIDs(
+ MP_OID oid1,
+ MP_OID oid2)
+{
+ if ((oid1.objectType == oid2.objectType) && (oid1.ownerId == oid2.ownerId)
+ && (oid1.objectSequenceNumber == oid2.objectSequenceNumber)) {
+ return (MP_STATUS_SUCCESS);
+ } else {
+ return (MP_STATUS_FAILED);
+ }
+}
+
+/**
+ *******************************************************************************
+ *
+ * Frees memory returned by an MP API.
+ *
+ * @param pOidList
+ * A pointer to the memory returned by an MP API. On successful
+ return, the allocated memory is freed.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when pPluginId is deregistered successfully.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pMemory is NULL or specifies a memory area to which
+ * data cannot be written.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_FreeOidList(MP_OID_LIST *pOidList)
+{
+ if (pOidList == NULL) {
+ return (MP_STATUS_INVALID_PARAMETER);
+ }
+
+ free(pOidList);
+
+ return (MP_STATUS_SUCCESS);
+}
+
+static MP_CHAR *HDR =
+"#\n"
+"# This file contains names and references to MP API plugin libraries\n"
+"#\n"
+"# Do NOT manually edit this file\n"
+"#\n"
+"# Format:\n"
+"#\n"
+"# <library ID> <library pathname>\n"
+"#\n";
+
+#define CLEANUP_N_RET(fd, ret) \
+ if (lock_register(fd, F_SETLK, F_UNLCK, 0, SEEK_SET, 0) < 0) { \
+ close(fd); \
+ return (MP_STATUS_FAILED); \
+ } \
+ close(fd); \
+ return (ret)
+
+/*
+ * This function sets an advisory lock on the file pointed to by the argument
+ * fd, which is a file descriptor. The lock is set using fcntl() which uses
+ * flock structure.
+ */
+static int
+lock_register(int fd, int cmd, int type, off_t offset, int whence, off_t len)
+{
+ struct flock lock;
+
+ lock.l_type = type;
+ lock.l_start = offset;
+ lock.l_whence = whence;
+ lock.l_len = len;
+
+ return (fcntl(fd, cmd, &lock));
+}
+
+/*
+ * This function searches for "srch_str" (of length "slen") in "buf" (of length
+ * "buflen"). If it is not found, "write_offset" has the offset in "buf" where
+ * "srch_str" would have to be added in "buf". If "srch_str" is found in "buf",
+ * "write_offset" has its offset in "buf"
+ *
+ * ARGUMENTS :
+ * buf - buffer to search in
+ * buflen - length of buffer
+ * srch_id - id to search
+ * id_len - length of srch_id
+ * write_offset - Set in function on exit
+ * - It is the offset in buf where srch_str is or should be
+ * bytes_left - Set in function on exit
+ * - It is the # of bytes left beyond write_offset in buf
+ * RETURN VALUES :
+ * Zero - "srch_id" found in "buf"... "write_offset" has offset in "buf"
+ * != 0 - "srch_str" NOT found in "buf" ... "write_offset" points to the end of
+ * "buf".
+ */
+static int
+search_line(MP_CHAR *buf, size_t buflen, MP_CHAR *srch_id, size_t id_len,
+ int *write_offset, int *bytes_left)
+{
+ int retval, sizeof_conf_hdr = strlen(HDR);
+ MP_CHAR *sol; /* Pointer to Start-Of-Line */
+ MP_CHAR *cur_pos; /* current position */
+
+ *bytes_left = buflen;
+ *write_offset = 0;
+
+ if (buf == NULL || buflen <= 0)
+ return (-1);
+
+ if (srch_id == NULL || id_len <= 0)
+ return (0);
+
+ sol = cur_pos = buf;
+
+ /*
+ * mp conf file should not be edited but takes care of
+ * any extra white space when parsing the line.
+ *
+ * The line should have id + delimiter + name + newline.
+ */
+ while (*bytes_left >= (id_len + 3)) {
+ /* skip leading blank or space. */
+ while ((*cur_pos == ' ') || (*cur_pos == '\t')) {
+ cur_pos++;
+ }
+
+ if (strncmp(cur_pos, srch_id, id_len) == 0) {
+ /* id matched. */
+ cur_pos += id_len;
+
+ while (*cur_pos != '\n') {
+ cur_pos++;
+ }
+ *write_offset = (sol - buf);
+ *bytes_left = buflen - ((cur_pos + 1) - buf);
+ return (0);
+ } else {
+ /* move to the next line */
+ while (*cur_pos != '\n') {
+ cur_pos++;
+ }
+ *bytes_left = buflen - ((cur_pos + 1) - buf);
+ }
+ sol = cur_pos = cur_pos + 1;
+ }
+
+ /* Given strings are not found. */
+ *write_offset = buflen;
+ return (-1);
+}
+
+/**
+ *******************************************************************************
+ *
+ * Registers a plugin with common library. The implementation of this routine
+ * is based on configuration file /etc/mpapi.conf that contains a list of
+ * plugin libraries.
+ *
+ * @param pPluginId
+ * A pointer to the key name shall be the reversed domain name of
+ * the vendor followed by followed by the vendor specific name for
+ * the plugin that uniquely identifies the plugin. Should be NULL
+ * terminated.
+ *
+ * @param pFileName
+ * The full path to the plugin library.
+ * Should be NULL terminated.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when pPluginId is deregistered successfully.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pPluginId is NULL or specifies a memory area that
+ * is not executable.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned if pClientFn deregistration is not possible at this time.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_RegisterPlugin(
+ MP_WCHAR *pPluginId,
+ char *pFileName)
+{
+ int mpconf, bytes_left, write_offset;
+ MP_CHAR fullline[MAX_LINE_SIZE]; /* Full line to add to mpapi.conf */
+ MP_CHAR *mpconf_buf;
+ MP_CHAR pluginid[MAX_NAME_SIZE];
+ char systemPath[MAX_NAME_SIZE], mpConfFilePath[MAX_NAME_SIZE];
+ MP_UINT32 new_file_flag = 0;
+ MP_UINT32 sizeof_conf_hdr = strlen(HDR);
+ struct stat stbuf;
+
+ if ((pPluginId == NULL) || (pFileName == NULL)) {
+ return (MP_STATUS_INVALID_PARAMETER);
+ }
+
+ if (stat(pFileName, &stbuf) != 0) {
+ return (MP_STATUS_INVALID_PARAMETER);
+ }
+
+ if (wcstombs(pluginid, pPluginId, MAX_NAME_SIZE) != wcslen(pPluginId)) {
+ return (MP_STATUS_INVALID_PARAMETER);
+ }
+
+ *fullline = '\0';
+ strncpy(fullline, pluginid, MAX_NAME_SIZE);
+ /* add tab */
+ strncat(fullline, "\t", MAX_LINE_SIZE - strlen(pluginid));
+ strncat(fullline, pFileName, MAX_LINE_SIZE - strlen(pluginid) - 1);
+ /* add a new line. */
+ strncat(fullline, "\n",
+ MAX_LINE_SIZE - strlen(pluginid) - strlen(pFileName) -1);
+
+ /* Open configuration file from known location */
+ strncpy(mpConfFilePath, "/etc/mpapi.conf", MAX_NAME_SIZE);
+
+ if ((chmod(mpConfFilePath, S_IRUSR|S_IRGRP|S_IROTH) == -1) &&
+ (errno == ENOENT)) {
+ new_file_flag = 1;
+ }
+
+ if ((mpconf = open(mpConfFilePath, O_RDWR | O_CREAT)) == -1) {
+ return (MP_STATUS_FAILED);
+ }
+
+ if (fchmod(mpconf, S_IRUSR | S_IRGRP | S_IROTH) < 0) {
+ close(mpconf);
+ return (MP_STATUS_FAILED);
+ }
+
+ if (lock_register(mpconf, F_SETLKW, F_WRLCK, 0, SEEK_SET, 0) < 0) {
+ close(mpconf);
+ return (MP_STATUS_FAILED);
+ }
+
+ if (fstat(mpconf, &stbuf) == -1) {
+ CLEANUP_N_RET(mpconf, MP_STATUS_FAILED);
+ }
+
+ if ((new_file_flag) || (stbuf.st_size == 0)) {
+ if (write(mpconf, HDR, sizeof_conf_hdr) !=
+ sizeof_conf_hdr) {
+ CLEANUP_N_RET(mpconf, MP_STATUS_FAILED);
+ }
+
+ if (pwrite(mpconf, fullline, strlen(fullline),
+ sizeof_conf_hdr) !=
+ strlen(fullline)) {
+ CLEANUP_N_RET(mpconf, MP_STATUS_FAILED);
+ }
+ CLEANUP_N_RET(mpconf, MP_STATUS_SUCCESS);
+ }
+
+ if ((mpconf_buf = (MP_CHAR *)mmap(0, stbuf.st_size,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED, mpconf, 0)) == MAP_FAILED) {
+ CLEANUP_N_RET(mpconf, MP_STATUS_FAILED);
+ }
+
+ if (search_line(mpconf_buf, stbuf.st_size,
+ pluginid, strlen(pluginid), &write_offset, &bytes_left) == 0) {
+ /* found a match. */
+ munmap((void *)mpconf_buf, stbuf.st_size);
+ CLEANUP_N_RET(mpconf, MP_STATUS_SUCCESS);
+ } else {
+ munmap((void *)mpconf_buf, stbuf.st_size);
+ /* append the fullline to the mpconf. */
+ if (pwrite(mpconf, fullline, strlen(fullline),
+ write_offset) !=
+ strlen(fullline)) {
+ CLEANUP_N_RET(mpconf, MP_STATUS_FAILED);
+ } else {
+ CLEANUP_N_RET(mpconf, MP_STATUS_SUCCESS);
+ }
+ }
+}
+
+/**
+ *******************************************************************************
+ *
+ * Deregisters a plugin from the common library. This routine is based on
+ * configuration file /etc/mpapi.conf that contains a list of plugin libraries.
+ *
+ * @param pPluginId
+ * A pointer to a Plugin ID previously registered using
+ * the MP_RegisterPlugin API..
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when pPluginId is deregistered successfully.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pPluginId is NULL or specifies a memory area that
+ * is not executable.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned if pClientFn deregistration is not possible at this time.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_DeregisterPlugin(
+ MP_WCHAR *pPluginId)
+{
+ int mpconf, tmp_mpconf, bytes_left, write_offset;
+ char systemPath[MAX_NAME_SIZE], mpConfFilePath[MAX_NAME_SIZE],
+ tmp_mpConfFilePath[MAX_NAME_SIZE + sizeof(pid_t)];
+ MP_CHAR pluginid[MAX_NAME_SIZE];
+ MP_CHAR *mpconf_buf;
+ MP_UINT32 sizeof_conf_hdr = strlen(HDR);
+ struct stat stbuf;
+
+ if (pPluginId == NULL) {
+ return (MP_STATUS_INVALID_PARAMETER);
+ }
+
+ if (wcstombs(pluginid, pPluginId, MAX_NAME_SIZE) != wcslen(pPluginId)) {
+ return (MP_STATUS_INVALID_PARAMETER);
+ }
+
+ /* Open configuration file from known location */
+ strncpy(mpConfFilePath, "/etc/mpapi.conf", MAX_NAME_SIZE);
+
+ if ((chmod(mpConfFilePath, S_IRUSR|S_IRGRP|S_IROTH) == -1) &&
+ (errno == ENOENT)) {
+ /* no file found */
+ return (MP_STATUS_UNKNOWN_FN);
+ }
+
+ if ((mpconf = open(mpConfFilePath, O_RDWR)) == -1) {
+ return (MP_STATUS_FAILED);
+ }
+
+ if (fchmod(mpconf, S_IRUSR | S_IRGRP | S_IROTH) < 0) {
+ close(mpconf);
+ return (MP_STATUS_FAILED);
+ }
+
+ if (lock_register(mpconf, F_SETLKW, F_WRLCK, 0, SEEK_SET, 0) < 0) {
+ close(mpconf);
+ return (MP_STATUS_FAILED);
+ }
+
+ if (fstat(mpconf, &stbuf) == -1) {
+ CLEANUP_N_RET(mpconf, MP_STATUS_FAILED);
+ }
+
+ if (stbuf.st_size == 0) {
+ CLEANUP_N_RET(mpconf, MP_STATUS_SUCCESS);
+ }
+
+ if ((mpconf_buf = (MP_CHAR *)mmap(0, stbuf.st_size,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED, mpconf, 0)) == MAP_FAILED) {
+ CLEANUP_N_RET(mpconf, MP_STATUS_FAILED);
+ }
+
+ if (search_line(mpconf_buf, stbuf.st_size, pluginid, strlen(pluginid),
+ &write_offset, &bytes_left) != 0) {
+ munmap((void *)mpconf_buf, stbuf.st_size);
+ CLEANUP_N_RET(mpconf, MP_STATUS_UNKNOWN_FN);
+ } else {
+ /*
+ * found a match.
+ * construct temp file name using pid.
+ */
+ (void) snprintf(tmp_mpConfFilePath, MAX_NAME_SIZE,
+ "%s%ld", "/etc/mpapi.conf", getpid());
+
+ if ((tmp_mpconf = open(tmp_mpConfFilePath,
+ O_RDWR|O_CREAT|O_TRUNC, S_IRUSR | S_IWUSR)) < 0) {
+ CLEANUP_N_RET(mpconf, MP_STATUS_FAILED);
+ }
+
+ if (write(tmp_mpconf, mpconf_buf, write_offset) != write_offset) {
+ close(tmp_mpconf);
+ CLEANUP_N_RET(mpconf, MP_STATUS_FAILED);
+ }
+
+ if (pwrite(tmp_mpconf, mpconf_buf + (stbuf.st_size - bytes_left),
+ bytes_left, write_offset) != bytes_left) {
+ close(tmp_mpconf);
+ CLEANUP_N_RET(mpconf, MP_STATUS_FAILED);
+ }
+
+ close(tmp_mpconf);
+ munmap((void *)mpconf_buf, stbuf.st_size);
+
+ /* rename temp file to mpConfFile before unlock and close. */
+ if (rename(tmp_mpConfFilePath, mpConfFilePath) != 0) {
+ CLEANUP_N_RET(mpconf, MP_STATUS_FAILED);
+ } else {
+ CLEANUP_N_RET(mpconf, MP_STATUS_SUCCESS);
+ }
+ }
+}
diff --git a/usr/src/lib/mpapi/libmpapi/common/mpapi.conf b/usr/src/lib/mpapi/libmpapi/common/mpapi.conf
new file mode 100644
index 0000000000..f7ea9c6b2d
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpapi/common/mpapi.conf
@@ -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.
+#
+# This file contains names and references to MP API plugin libraries
+#
+# Do NOT manually edit this file
+#
+# Format:
+#
+# <library ID> <library pathname>
+#
diff --git a/usr/src/lib/mpapi/libmpapi/common/mpapi.h b/usr/src/lib/mpapi/libmpapi/common/mpapi.h
new file mode 100644
index 0000000000..3c2e0f180c
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpapi/common/mpapi.h
@@ -0,0 +1,2593 @@
+/******************************************************************************
+ *
+ * Description
+ * mpapi.h - general header file for Multipath Management API Version 1.0
+ * client
+ *
+ * License:
+ * The contents of this file are subject to the SNIA Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://mp-mgmt-api.sourceforge.net
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * The Original Code is SNIA iSCSI Management API and Multipath Management API
+ * general header file
+ *
+ * The Initial Developer of the Original Code is:
+ * Benjamin F. Kuo Troika Networks, Inc. (benk@troikanetworks.com)
+ * David Dillard VERITAS Software(david.dillard@veritas.com)
+ * Jeff Ding Adaptec, Inc. (jding@corp.adaptec.com)
+ * Dave Wysochanski Network Appliance, Inc. (davidw@netapp.com)
+ * Hyon Kim Sun Microsystems(hyon.kim@sun.com)
+ *
+ * Contributor(s):
+ * Paul von Behren Sun Microsystems(paul.vonbehren@sun.com)
+ *
+ ******************************************************************************
+ *
+ * Changes:
+ * 1/15/2005 Implemented SNIA MP API specification 1.0
+ * 10/11/2005
+ * - Added the license location in the header comment.
+ * - Added an implementation note in constants and macros
+ * declarations section.
+ * - Fixed field name value in struct _MP_PROPRIETARY_PROPERTY.
+ * - Fixed typo in logicalUnitGroupID in
+ * _MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES
+ * - Fixed typo in desiredState in struct _MP_TPG_STATE_PAIR.
+ * - Fixed typo in API name MP_GetTargetPortGroupProperties.
+ * - Clarified description of MP_STATUS_INVALID_PARAMETER error
+ * in MP_GetObjectType().
+ * - Fixed typo in API name
+ * MP_GetProprietaryLoadBalanceProperties().
+ * 3/6/2006
+ * - mpapi.h header file is updated for
+ * MP_LOAD_BALANCE_TYPE change in the spec.
+ *****************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifndef MPAPI_H
+#define MPAPI_H
+
+#include <time.h>
+#include <wchar.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+/* Library version string */
+#define MP_LIBVERSION 1
+
+/**
+ *******************************************************************************
+ *
+ * Generic MP Constant Definitions
+ *
+ *******************************************************************************
+ */
+#define RL_LIBRARY_SEQNUM 0
+
+/**
+* Value which can be assigned to an MP_BOOL and or an MP_XBOOL.
+*/
+#define MP_TRUE 1
+
+/**
+* Value which can be assigned to an MP_BOOL and or an MP_XBOOL.
+*/
+#define MP_FALSE 0
+
+/**
+* Value which can be assigned to an MP_XBOOL.
+*/
+#define MP_UNKNOWN 0xFFFFFFFF
+
+#define MP_MAX_NUM_PLUGINS 64
+#define MP_OBJECT_TYPE_MATCH 1
+#define MP_OBJECT_TYPE_ANY 2
+#define MAX_NAME_SIZE 256
+#define MAX_LINE_SIZE 515
+
+
+/**
+ ******************************************************************************
+ *
+ * Base MP API Type Definitions
+ *
+ ******************************************************************************
+ */
+
+typedef unsigned char MP_UINT8; /* unsigned 8 bits */
+typedef char MP_INT8; /* signed 8 bits */
+typedef unsigned short MP_UINT16; /* unsigned 16 bits */
+typedef short MP_INT16; /* signed 16 bits */
+typedef unsigned int MP_UINT32; /* unsigned 32 bits */
+typedef int MP_INT32; /* signed 32 bits */
+typedef void* MP_PVOID; /* pointer to void */
+typedef MP_UINT32 MP_VOID32; /* opaque 32 bits */
+typedef long long MP_INT64; /* signed 64 bits */
+typedef unsigned long long MP_UINT64; /* unsigned 64 bits */
+
+/**
+ * A character.
+ */
+typedef char MP_CHAR;
+
+/**
+ * A wide character.
+ */
+typedef wchar_t MP_WCHAR;
+
+/**
+ * An unsigned character.
+ */
+typedef unsigned char MP_BYTE;
+
+/**
+ * A boolean.
+ */
+typedef MP_UINT32 MP_BOOL;
+
+/**
+ * An extended boolean: can have the values @ref MP_TRUE, @ref MP_FALSE, and
+ * @ref MP_UNKNOWN.
+ */
+typedef MP_UINT32 MP_XBOOL;
+
+/**
+ ******************************************************************************
+ *
+ * Constants and macros declarations related to MP_STATUS
+ * Implementation Notes: This library does validation for OID argument and
+ * returns the following errors.
+ *
+ * 1. MP_STATUS_INVALID_OBJECT_TYPE when input OID type is not
+ * one of legitimate types defined SNIA Multipath Management
+ * Spec.
+ * 2. MP_STATUS_INVALID_PARAMETER when input OID type is
+ * legitimate but not a proper type for API.
+ * 3. MP_STATUS_OBJECT_NOT_FOUND when the ownerId of input OID is
+ * not found or no object instance with matching
+ * sequenceNumber is found.
+ * The ownerId is validated by the common library and the
+ * sequence number is validated by the plugin library.
+ *
+ ******************************************************************************
+ */
+typedef enum {
+ MP_STATUS_SUCCESS = 0,
+ MP_STATUS_INVALID_PARAMETER = 1,
+ MP_STATUS_UNKNOWN_FN = 2,
+ MP_STATUS_FAILED = 3,
+ MP_STATUS_INSUFFICIENT_MEMORY = 4,
+ MP_STATUS_INVALID_OBJECT_TYPE = 5,
+ MP_STATUS_OBJECT_NOT_FOUND = 6,
+ MP_STATUS_UNSUPPORTED = 7,
+ MP_STATUS_FN_REPLACED = 8,
+ MP_STATUS_ACCESS_STATE_INVALID = 9,
+ MP_STATUS_INVALID_WEIGHT = 10,
+ MP_STATUS_PATH_NONOPERATIONAL = 11,
+ MP_STATUS_TRY_AGAIN = 12,
+ MP_STATUS_NOT_PERMITTED = 13
+
+} MP_STATUS;
+
+/**
+ ******************************************************************************
+ *
+ * Declaration of the MP_PATH_STATE constants
+ *
+ ******************************************************************************
+ */
+#define MP_PATH_STATE_OKAY 0
+#define MP_PATH_STATE_PATH_ERR 1
+#define MP_PATH_STATE_LU_ERR 2
+#define MP_PATH_STATE_RESERVED 3
+#define MP_PATH_STATE_REMOVED 4
+#define MP_PATH_STATE_TRANSITIONING 5
+#define MP_PATH_STATE_OPERATIONAL_CLOSED 6
+#define MP_PATH_STATE_INVALID_CLOSED 7
+#define MP_PATH_STATE_OFFLINE_CLOSED 8
+#define MP_PATH_STATE_UNKNOWN 9
+
+typedef MP_UINT32 MP_PATH_STATE;
+
+/**
+ *******************************************************************************
+ *
+ * Declaration of the MP_OBJECT_TYPE constants
+ *
+ *******************************************************************************
+ */
+#define MP_OBJECT_TYPE_UNKNOWN 0
+#define MP_OBJECT_TYPE_PLUGIN 1
+#define MP_OBJECT_TYPE_INITIATOR_PORT 2
+#define MP_OBJECT_TYPE_TARGET_PORT 3
+#define MP_OBJECT_TYPE_MULTIPATH_LU 4
+#define MP_OBJECT_TYPE_PATH_LU 5
+#define MP_OBJECT_TYPE_DEVICE_PRODUCT 6
+#define MP_OBJECT_TYPE_TARGET_PORT_GROUP 7
+#define MP_OBJECT_TYPE_PROPRIETARY_LOAD_BALANCE 8
+
+/* set to the highest constant of object type. */
+#define MP_OBJECT_TYPE_MAX 8
+
+typedef MP_UINT32 MP_OBJECT_TYPE;
+
+/**
+ *******************************************************************************
+ *
+ * Declaration of the MP_PORT_TRANSPORT_TYPE
+ *
+ *******************************************************************************
+ */
+#define MP_PORT_TRANSPORT_TYPE_UNKNOWN 0
+#define MP_PORT_TRANSPORT_TYPE_MPNODE 1
+#define MP_PORT_TRANSPORT_TYPE_FC 2
+#define MP_PORT_TRANSPORT_TYPE_SPI 3
+#define MP_PORT_TRANSPORT_TYPE_ISCSI 4
+#define MP_PORT_TRANSPORT_TYPE_IFB 5
+
+typedef MP_UINT32 MP_PORT_TRANSPORT_TYPE;
+
+/**
+ *******************************************************************************
+ *
+ * Declaration of the MP_ACCESS_STATE_TYPE constants
+ *
+ *******************************************************************************
+ */
+#define MP_ACCESS_STATE_ACTIVE_OPTIMIZED (0x0)
+#define MP_ACCESS_STATE_ACTIVE_NONOPTIMIZED (0x1)
+#define MP_ACCESS_STATE_STANDBY (0x2)
+#define MP_ACCESS_STATE_UNAVAILABLE (0x3)
+#define MP_ACCESS_STATE_TRANSITIONING (0xF)
+#define MP_ACCESS_STATE_ACTIVE (0x10)
+
+typedef MP_UINT32 MP_ACCESS_STATE_TYPE;
+
+/**
+ *******************************************************************************
+ *
+ * Declaration of the MP_LOAD_BALANCE_TYPE constants
+ *
+ *******************************************************************************
+ */
+#define MP_LOAD_BALANCE_TYPE_UNKNOWN (1<<0)
+#define MP_LOAD_BALANCE_TYPE_ROUNDROBIN (1<<1)
+#define MP_LOAD_BALANCE_TYPE_LEASTBLOCKS (1<<2)
+#define MP_LOAD_BALANCE_TYPE_LEASTIO (1<<3)
+#define MP_LOAD_BALANCE_TYPE_DEVICE_PRODUCT (1<<4)
+#define MP_LOAD_BALANCE_TYPE_LBA_REGION (1<<5)
+#define MP_LOAD_BALANCE_TYPE_FAILOVER_ONLY (1<<6)
+/**
+ * Proprietary load balance type should start from 0x10000(1<<16) or greater.
+ * It is exposed through API MP_GetProprietaryLoadBalanceProperties if exists.
+ */
+
+typedef MP_UINT32 MP_LOAD_BALANCE_TYPE;
+
+typedef struct mpPluginInfo {
+ MP_WCHAR pluginName[MAX_NAME_SIZE];
+ MP_CHAR pluginPath[MAX_NAME_SIZE];
+ void* hdlPlugin;
+ MP_UINT32 ownerId;
+} MPPLUGININFO_T;
+
+
+/**
+ *******************************************************************************
+ *
+ * Declaration of the MP_PROPRIETARY_PROPERTY
+ *
+ *******************************************************************************
+ */
+typedef struct _MP_PROPRIETARY_PROPERTY
+{
+ MP_WCHAR name[16];
+ MP_WCHAR value[48];
+
+} MP_PROPRIETARY_PROPERTY;
+
+/**
+ *******************************************************************************
+ *
+ * Declaration of the MP_PROPRIETARY_LOAD_BALANCE_PROPERTIES
+ *
+ *******************************************************************************
+ */
+typedef struct _MP_PROPRIETARY_LOAD_BALANCE_PROPERTIES
+{
+ MP_LOAD_BALANCE_TYPE typeIndex;
+ MP_WCHAR name[256];
+ MP_WCHAR vendorName[256];
+ MP_UINT32 proprietaryPropertyCount;
+ MP_PROPRIETARY_PROPERTY proprietaryProperties[8];
+
+} MP_PROPRIETARY_LOAD_BALANCE_PROPERTIES;
+
+/**
+ *******************************************************************************
+ *
+ * Declaration of the MP_UINT32 MP_LOGICAL_UNIT_NAME_TYPE constants
+ *
+ *******************************************************************************
+ */
+#define MP_LU_NAME_TYPE_UNKNOWN 0
+#define MP_LU_NAME_TYPE_VPD83_TYPE1 1
+#define MP_LU_NAME_TYPE_VPD83_TYPE2 2
+#define MP_LU_NAME_TYPE_VPD83_TYPE3 3
+#define MP_LU_NAME_TYPE_DEVICE_SPECIFIC 4
+
+typedef MP_UINT32 MP_LOGICAL_UNIT_NAME_TYPE;
+
+/**
+ *******************************************************************************
+ *
+ * Declaration of the MP_UINT32 MP_AUTOFAILBACK_SUPPORT constants
+ *
+ *******************************************************************************
+ */
+#define MP_AUTOFAILBACK_SUPPORT_NONE 0
+#define MP_AUTOFAILBACK_SUPPORT_PLUGIN 1
+#define MP_AUTOFAILBACK_SUPPORT_MPLU 2
+#define MP_AUTOFAILBACK_SUPPORT_PLUGINANDMPLU 3
+
+typedef MP_UINT32 MP_AUTOFAILBACK_SUPPORT;
+
+/**
+ *******************************************************************************
+ *
+ * Declaration of the MP_UINT32 MP_AUTOPROBING_SUPPORT constants
+ *
+ *******************************************************************************
+ */
+#define MP_AUTOPROBING_SUPPORT_NONE 0
+#define MP_AUTOPROBING_SUPPORT_PLUGIN 1
+#define MP_AUTORPOBING_SUPPORT_MPLU 2
+#define MP_AUTORPOBING_SUPPORT_PLUGINANDMPLU 3
+
+typedef MP_UINT32 MP_AUTOPROBING_SUPPORT;
+
+/**
+ *******************************************************************************
+ *
+ * Declaration of the MP_OID structure
+ *
+ * This structure should be treated as opaque by clients of the API.
+ * Appropriate APIs should be used to extract information from the structure.
+ *
+ * Also ZERO_OID is defined for APIs that may handle multiple plugin OIDs.
+ *
+ *******************************************************************************
+ */
+typedef struct _MP_OID
+{
+ /**
+ * The type of the object. When an object ID is supplied as a parameter
+ * to an API the library uses this value to insure that the supplied
+ * object ID's type is appropriate for the API.
+ */
+ MP_OBJECT_TYPE objectType;
+
+ /**
+ * A value determined by the library which it uses to uniquely identify the
+ * owner of an object. The owner of an object is either the library itself
+ * or a plugin. When an object ID is supplied as a parameter to an API the
+ * library uses this value to determine if it should handle the call itself
+ * or direct the call to one or more plugins.
+ */
+ MP_UINT32 ownerId;
+
+ /**
+ * A value determined by a plugin which a plugin uses, perhaps in
+ * combination with the object type, to uniquely identify one of its
+ * objects.
+ */
+ MP_UINT64 objectSequenceNumber;
+
+} MP_OID;
+
+#define ZERO_OID ((const MP_OID){MP_OBJECT_TYPE_UNKNOWN,0,0})
+
+/**
+ *******************************************************************************
+ *
+ * Declaration of the MP_OID_LIST structure
+ *
+ * This structure is used by a number of APIs to return lists of objects. Any
+ * instance of this structure returned by an API must be freed by a client
+ * using the MP_FreeOidList API. Although oids is declared to be an
+ * array of one
+ * @ref MP_OID structure it can in fact contain any number of
+ * @ref MP_OID structures. The oidCount indicates the number of @ref MP_OID
+ * structures in the oids array.
+ *
+ * @note The @a oids array is a variable length array, despite its declaration
+ * below it can be of any length.
+ *
+ *******************************************************************************
+ */
+typedef struct _MP_OID_LIST
+{
+ /**
+ * The number of object IDs in the @a oids array.
+ */
+ MP_UINT32 oidCount;
+
+ /**
+ * A variable length array of zero or more object IDs. There are
+ * 'oidCount' object IDs in this array.
+ */
+ MP_OID oids[1];
+
+} MP_OID_LIST;
+
+/**
+ *******************************************************************************
+ *
+ * Declaration of the MP_LIBRARY_PROPERTIES structure
+ *
+ * This structure is returned by the MP_GetLibraryProperties() API.
+ *
+ *******************************************************************************
+ */
+typedef struct _MP_LIBRARY_PROPERTIES
+{
+ /**
+ * The version of the Multipath Management API implemented by the library.
+ */
+ MP_UINT32 supportedMpVersion;
+
+ /**
+ * A null terminated ASCII string containing the name of the vendor that
+ * created the binary version of the library.
+ */
+ MP_WCHAR vendor[256];
+
+ /**
+ * A null terminated ASCII string containing the implementation version
+ * of the library from the vendor specified in the 'vendor' field.
+ */
+ MP_WCHAR implementationVersion[256];
+
+ /**
+ * A null terminated ASCII string ideally containing the path and file
+ * name of the library that is being used by the currently executing
+ * process can be found. If the path cannot be determined then it is
+ * acceptable to fill this field with only the name (and extension if
+ * applicable) of the file of the library. If this cannot be determined
+ * then this field should be an empty string.
+ */
+ MP_CHAR fileName[256];
+
+ /**
+ * The time and date that the library that is executing was built.
+ */
+ MP_WCHAR buildTime[256];
+
+} MP_LIBRARY_PROPERTIES;
+
+/**
+ *******************************************************************************
+ *
+ * Declaration of the MP_PLUGIN_PROPERTIES structure
+ *
+ * This structure is returned by the MP_GetPluginProperties() API.
+ *
+ *******************************************************************************
+ */
+typedef struct _MP_PLUGIN_PROPERTIES
+{
+ /**
+ * The version of the Multipath Management API implemented by a plugin.
+ */
+ MP_UINT32 supportedMpVersion;
+
+ /**
+ * A null terminated Unicode string containing the name of the vendor that
+ * created the binary version of the plugin.
+ */
+ MP_WCHAR vendor[256];
+
+ /**
+ * A null terminated Unicode string containing the implementation version
+ * of the plugin from the vendor specified in vendor.
+ */
+ MP_WCHAR implementationVersion[256];
+
+ /**
+ * A null terminated ASCII string ideally containing the path and file
+ * name of the plugin that is filling in this structure.
+ */
+ MP_CHAR fileName[256];
+
+ /**
+ * The time and date that the plugin that is executing was built.
+ */
+ MP_WCHAR buildTime[256];
+
+ /**
+ * A null terminated Unicode string containing the name of the multipath
+ * driver vendor associated with this plugin.
+ */
+ MP_WCHAR driverVendor[256];
+
+ /**
+ * A null terminated Unicode string ideally containing the path and file
+ * name of the plugin that is filling in this structure.
+ */
+ MP_CHAR driverName[256];
+
+ /**
+ * A null terminated Unicode string containing the version number of
+ * the multipath driver.
+ */
+ MP_WCHAR driverVersion[256];
+
+ /**
+ * A set of flags representing the load balance types
+ * (MP_LOAD_BALANCE_TYPES) supported by the plugin/driver as a plugin-wide
+ * property.
+ */
+ MP_UINT32 supportedLoadBalanceTypes;
+
+ /**
+ * boolean indicating whether the implementation supports activating target
+ * port groups.
+ */
+ MP_BOOL canSetTPGAccess;
+
+ /**
+ * A Boolean indicating whether the implementations supports overriding
+ * paths. Setting this to true indicates MP_SetOverridePath and
+ * MP_CancelOverridePath are supported.
+ */
+ MP_BOOL canOverridePaths;
+
+ /**
+ * A boolean indicating whether the implementation exposes (or leaves
+ * exposed) device files for the individual paths encapsulated by the
+ * multipath device file. This is typically true for MP drivers that sit
+ * near the top of the driver stack..
+ */
+ MP_BOOL exposesPathDeviceFiles;
+
+ /**
+ * A string representing the primary file names the driver uses for
+ * multipath logical units.
+ */
+ MP_CHAR deviceFileNamespace[256];
+
+ /**
+ * A boolean indicating whether the driver limits multipath capabilities
+ * to certain device types. If true, then the driver only provides multipath
+ * support to devices exposed through MP_DEVICE_PRODUCT_PROPERTIES
+ * instances. If false, then the driver supports any device that provides
+ * standard SCSI logical unit identifiers.
+ */
+ MP_BOOL onlySupportsSpecifiedProducts;
+
+ /**
+ * Describes the range of administer settable path weights supported by the
+ * driver. A driver with no path preference capabilities should set
+ * this property to zero. A driver with the ability to enable/disable
+ * paths should set this property to 1. Drivers with more weight settings
+ * can set the property appropriately.
+ */
+ MP_UINT32 maximumWeight;
+
+ /**
+ * The autofailback support indicates whether the implementation supports
+ * auto-failback (to reenable paths that revert to a good state) at the
+ * plugin level, the multipath logical unit level, both levels or whether
+ * auto-failback is unsupported.
+ */
+ MP_AUTOFAILBACK_SUPPORT autoFailbackSupport;
+
+ /**
+ * A Boolean indicating whether plugin-wide autofailback is currently
+ * enabled. This parameter is undefined if autoFailbackSupport is
+ * MP_AUTOFAILBACK_SUPPORT_NONE or MP_AUTOFAILBACK_SUPPORT_MPLU.
+ */
+ MP_BOOL pluginAutoFailbackEnabled;
+
+ /**
+ * The maximum plugin-wide polling rate (in seconds) for auto-failback
+ * supported by the driver. A value of zero indicates the driver/plugin
+ * does not support polling. Undefined if autoFailbackSupport is
+ * MP_AUTOFAILBACK_SUPPORT_NONE or MP_AUTOFAILBACK_SUPPORT_MPLU. If the
+ * plugin/driver supports auto-failback without polling or does not provide
+ * a way to set the polling rate, then this must be set to zero (0).
+ * This value is set by the plugin and cannot be modified by users.
+ */
+ MP_UINT32 failbackPollingRateMax;
+
+ /**
+ * The current plugin-wide auto-failback polling rate (in seconds).
+ * Undefined if autofailbackSupport is MP_AUTOFAILBACK_SUPPORT_NONE or
+ * MP_AUTOFAILBACK_SUPPORT_MPLU. Cannot be more that plooingRateMax.
+ */
+ MP_UINT32 currentFailbackPollingRate;
+
+ /**
+ * An enumerated type indicating whether the implementation supports
+ * auto-probing at the plugin level, the multipath logical unit level, both
+ * levels or whether auto-probing is unsupported.
+ */
+ MP_AUTOPROBING_SUPPORT autoProbingSupport;
+
+ /**
+ * A boolean indicating that plugin-wide auto-probing is enabled. This
+ * property is undefined if autoProbingSupport is
+ * MP_AUTOPROBING_SUPPORT_NONE or MP_AUTOPROBING_SUPPORT_MPLU.
+ */
+ MP_BOOL pluginAutoProbingEnabled;
+
+ /**
+ * The maximum plugin-wide polling rate (in seconds) for auto-probing
+ * supported by the driver. Undefined if autoProbingSupport is
+ * MP_AUTOPROBING_SUPPORT_NONE or MP_AUTOPROBING_SUPPORT_MPLU. If the
+ * plugin/driver supports auto-probing without polling or does not provide a
+ * way to set the probing polling rate, then this must be set to zero (0).
+ * This value is set by the plugin and cannot be modified by users.
+ */
+ MP_UINT32 probingPollingRateMax;
+
+ /**
+ * The current plugin-wide auto-probing polling rate (in seconds).
+ * Undefined if autoProbingSupport is MP_AUTOPROBING_SUPPORT_NONE or
+ * MP_AUTOPROBING_SUPPORT_MPLU. Cannot be more that probingPollingRateMax.
+ */
+ MP_UINT32 currentProbingPollingRate;
+
+ /**
+ * The load balance type that will be used by the driver for devices
+ * (without a corresponding MP_DEVICE_PRODUCT_PROPERTIES instance) unless
+ * overridden by the administrator. Any logical unit with vendor, product,
+ * and revision properties matching a MP_DEVICE_PRODUCT_PROPERTIES instance
+ * will default to a device-specific load balance type.
+ */
+ MP_LOAD_BALANCE_TYPE defaultloadBalanceType;
+
+ /**
+ * The count of proprietary properties (less that or equal to eight)
+ * supported.
+ */
+ MP_UINT32 proprietaryPropertyCount;
+
+ /**
+ * A list of proprietary property name/value pairs.
+ */
+ MP_PROPRIETARY_PROPERTY proprietaryProperties[8];
+
+} MP_PLUGIN_PROPERTIES;
+
+/**
+ *******************************************************************************
+ *
+ * Declaration of the MP_DEVICE_PRODUCT_PROPERTIES structure.
+ *
+ * This structure is returned by the MP_GetDeviceProductProperties() API.
+ *
+ *******************************************************************************
+ */
+typedef struct _MP_DEVICE_PRODUCT_PROPERTIES
+{
+ MP_CHAR vendor[8];
+ MP_CHAR product[16];
+ MP_CHAR revision[4];
+ MP_UINT32 supportedLoadBalanceTypes;
+
+} MP_DEVICE_PRODUCT_PROPERTIES;
+
+/**
+ *******************************************************************************
+ *
+ * Declaration of the MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES structure.
+ *
+ * This structure is returned by the MP_GetMPLogicalUnitProperties() API.
+ *
+ *******************************************************************************
+ */
+typedef struct _MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES
+{
+ MP_CHAR vendor[8];
+ MP_CHAR product[16];
+ MP_CHAR revision[4];
+ MP_CHAR name[256];
+ MP_LOGICAL_UNIT_NAME_TYPE nameType;
+ MP_CHAR deviceFileName[256];
+ MP_BOOL asymmetric;
+ MP_OID overridePath;
+ MP_LOAD_BALANCE_TYPE currentLoadBalanceType;
+ MP_UINT32 logicalUnitGroupID;
+ MP_XBOOL autoFailbackEnabled;
+ MP_UINT32 failbackPollingRateMax;
+ MP_UINT32 currentFailbackPollingRate;
+ MP_XBOOL autoProbingEnabled;
+ MP_UINT32 probingPollingRateMax;
+ MP_UINT32 currentProbingPollingRate;
+ MP_UINT32 proprietaryPropertyCount;
+ MP_PROPRIETARY_PROPERTY proprietaryProperties[8];
+
+} MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES;
+
+/**
+ *******************************************************************************
+ *
+ * Declaration of the MP_PATH_LOGICAL_UNIT_PROPERTIES structure.
+ *
+ * This structure is returned by the MP_GetPathLogicalUnitProperties() API.
+ *
+ *******************************************************************************
+ */
+typedef struct _MP_PATH_LOGICAL_UNIT_PROPERTIES
+{
+ MP_UINT32 weight;
+ MP_PATH_STATE pathState;
+ MP_BOOL disabled;
+ MP_OID initiatorPortOid;
+ MP_OID targetPortOid;
+ MP_OID logicalUnitOid;
+ MP_UINT64 logicalUnitNumber;
+ MP_CHAR deviceFileName[256];
+ MP_UINT32 busNumber;
+ MP_UINT32 portNumber;
+
+} MP_PATH_LOGICAL_UNIT_PROPERTIES;
+
+/**
+ *******************************************************************************
+ *
+ * Declaration of the MP_INITIATOR_PORT_PROPERTIES structure.
+ *
+ * This structure is returned by the MP_GetInitiatorPortProperties() API.
+ *
+ *******************************************************************************
+ */
+typedef struct _MP_INITIATOR_PORT_PROPERTIES
+{
+ MP_CHAR portID[256];
+ MP_PORT_TRANSPORT_TYPE portType;
+ MP_CHAR osDeviceFile[256];
+ MP_WCHAR osFriendlyName[256];
+
+} MP_INITIATOR_PORT_PROPERTIES;
+
+/**
+ *******************************************************************************
+ *
+ * Declaration of the MP_TARGET_PORT_PROPERTIES structure.
+ *
+ * This structure is returned by the MP_GetTargetPortProperties() API.
+ *
+ *******************************************************************************
+ */
+typedef struct _MP_TARGET_PORT_PROPERTIES
+{
+ MP_CHAR portID[256];
+ MP_UINT32 relativePortID;
+
+} MP_TARGET_PORT_PROPERTIES;
+
+/**
+ *******************************************************************************
+ *
+ * Declaration of the MP_TARGET_PORT_GROUP_PROPERTIES structure.
+ *
+ * This structure is returned by the MP_GetTargetPortGroupProperties() API.
+ *
+ *******************************************************************************
+ */
+typedef struct _MP_TARGET_PORT_GROUP_PROPERTIES
+{
+ MP_ACCESS_STATE_TYPE accessState;
+ MP_BOOL explicitFailover;
+ MP_BOOL supportsLuAssignment;
+ MP_BOOL preferredLuPath;
+ MP_UINT32 tpgID;
+
+} MP_TARGET_PORT_GROUP_PROPERTIES;
+
+/**
+ *******************************************************************************
+ *
+ * Declaration of the MP_TPG_STATE_PAIR structure.
+ *
+ * This structure is used as an argument for the MP_SetTPGAcess() API.
+ *
+ *******************************************************************************
+ */
+typedef struct _MP_TPG_STATE_PAIR
+{
+ MP_OID tpgOid;
+ MP_ACCESS_STATE_TYPE desiredState;
+
+} MP_TPG_STATE_PAIR;
+
+/**
+ *******************************************************************************
+ *
+ * Declaration of call back function type for event support
+ *
+ *******************************************************************************
+ */
+typedef void (* MP_OBJECT_PROPERTY_FN) (
+ MP_OID_LIST *pOidList, void *pCallerData
+);
+
+typedef void (* MP_OBJECT_VISIBILITY_FN) (
+ MP_BOOL becomingVisible, MP_OID_LIST *pOidList, void *pCallerData
+);
+
+void InitLibrary();
+void ExitLibrary();
+
+/**
+ ******************************************************************************
+ *
+ * The APIs for property and object related discovery.
+ *
+ * - MP_GetLibraryProperties
+ * - MP_GetPluginOidList
+ * - MP_GetPluginProperties
+ * - MP_GetAssociatedPluginOid
+ * - MP_GetObjectType
+ * - MP_GetDeviceProductOidList
+ * - MP_GetDeviceProductProperties
+ * - MP_GetInitiatorPortOidList
+ * - MP_GetInitiatorPortProperties
+ * - MP_GetMultipathLus
+ * - MP_GetMPLogicalUnitProperties
+ * - MP_GetAssociatedPathOidList
+ * - MP_GetPathLogicalUnitProperties
+ * - MP_GetAssociatedTPGOidList
+ * - MP_GetTargetPortGroupProperties
+ * - MP_GetMPLuOidListFromTPG
+ * - MP_GetProprietaryLoadBalanceOidList
+ * - MP_GetProprietaryLoadBalanceProperties
+ * - MP_GetTargetPortOidList
+ * - MP_GetTargetPortProperties
+ *
+ ******************************************************************************
+ */
+
+/**
+ *******************************************************************************
+ *
+ * Gets the properties of the MP API library that is being used.
+ *
+ * @param pProps
+ * A pointer to an MP_LIBRARY_PROPERTIES structure allocated by
+ * the caller. On successful return this structure will contain the
+ * properties of the MP API library.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned if the library properties were successfully returned.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if ppList pointer passed as placeholder for holding the
+ * library properties is found to be invalid.
+ *
+ * @retval MP_STATUS_UNSUPPORTED
+ * Returned when the implementation does not support the API.
+ *
+ ******************************************************************************
+ */
+MP_STATUS MP_GetLibraryProperties(
+ MP_LIBRARY_PROPERTIES *pProps
+);
+
+/**
+ ******************************************************************************
+ *
+ * Gets a list of the object IDs of all currently loaded plugins.
+ *
+ * @param ppList
+ * A pointer to a pointer to an MP_OID_LIST. On successful
+ * return this will contain a pointer to an @ref MP_OID_LIST
+ * which contains the object IDs of all of the plugins currently
+ * loaded by the library.
+ *
+ * @return MP_STATUS indicating if the operation was successful or
+ * if an error occurred.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type. This is
+ * most likely to happen if an uninitialized object ID is passed to
+ * the API.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if ppList is NULL or specifies a memory area to which data
+ * cannot be written. MP_STATUS_SUCCESS Returned when the operation is
+ * successful.
+ *
+ * @retval MP_STATUS_INSUFFICIENT_MEMORY
+ * Returned when memory allocation failure occurs*
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned if the plugin ID list was successfully returned.
+ *
+ ******************************************************************************
+ */
+MP_STATUS MP_GetPluginOidList(
+ MP_OID_LIST **ppList
+);
+
+/**
+ *******************************************************************************
+ *
+ * Gets the properties of the specified vendor plugin.
+ *
+ * @param oid
+ * The ID of the plugin whose properties are being retrieved.
+ *
+ * @param pProps
+ * A pointer to an @ref MP_PLUGIN_PROPERTIES structure allocated by
+ * the caller. On successful return this will contain the properties
+ * of the plugin specified by pluginOid.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if an
+ * error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned if the plugin properties were successfully returned.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned if oid has an owner that is not currently known to
+ * the system.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if 'pProps' is NULL or specifies a memory area to
+ * which data cannot be written.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetPluginProperties(
+ MP_OID oid,
+ MP_PLUGIN_PROPERTIES *pProps
+);
+
+
+/**
+ *******************************************************************************
+ *
+ * Gets the object ID for the plugin associated with the specified object ID.
+ *
+ * @param oid
+ * The object ID of an object that has been received from a previous
+ * library call.
+ *
+ * @param pPluginOid
+ * A pointer to an MP_OID structure allocated by the caller. On
+ * successful return this will contain the object ID of the plugin
+ * associated with the object specified by @a objectId.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned if the associated plugin ID was successfully returned.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned if oid does not specify a plugin that is currently known to
+ * the system.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if 'oid' specifies an object not owned by a plugin or
+ * if pPluginOid is NULL or specifies a memory area to which data
+ * cannot be written.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if 'oid' specifies an object with an invalid type.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetAssociatedPluginOid(
+ MP_OID oid,
+ MP_OID *pPluginOid
+);
+
+
+/**
+ *******************************************************************************
+ *
+ * Gets the object type of an initialized object ID.
+ *
+ * @param oid
+ * The object ID of an object that has been received from a previous
+ * library call.
+ *
+ * @param pObjectType
+ * A pointer to an MP_OBJECT_TYPE variable allocated by the caller.
+ * On successful return this will contain the object type of oid.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or
+ * if an error occurred.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned if oid has an owner that is not currently known to
+ * the system.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetObjectType(
+ MP_OID oid,
+ MP_OBJECT_TYPE *pObjectType
+);
+
+
+/**
+ *******************************************************************************
+ *
+ * Gets a list of the object IDs of all the device product properties
+ * associated with this plugin.
+ *
+ * @param oid
+ * The object ID of plugin.
+ *
+ * @param ppList
+ * A pointer to a pointer to an MP_OID_LIST structure.
+ * On a successful return, this will contain a pointer to
+ * an MP_OID_LIST that contains the object IDs of all the device
+ * product descriptors associated with the specified plugin.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if ppList pointer passed as placeholder for holding
+ * the device product list is found to be invalid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned when the plugin for the specified oid is not found.
+ *
+ * @retval MP_STATUS_INSUFFICIENT_MEMORY
+ * Returned when memory allocation failure occurs
+ *
+ * @retval MP_STATUS_UNSUPPORTED
+ * Returned when the API is not supported.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetDeviceProductOidList(
+ MP_OID oid,
+ MP_OID_LIST **ppList
+);
+
+/**
+ *******************************************************************************
+ *
+ * Gets the device product properties of the specified plugin oid.
+ *
+ * @param oid
+ * The object ID of the plugin.
+ *
+ * @param ppProps
+ * A pointer to an MP_DEVICE_PRODUCT_PROPERTIES structure
+ * allocated by the caller. On successful return it will contain
+ * a pointer to an MP_DEVICE_PRODUCT_PROPERTIES structure allocated
+ * by the library.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if ppProps pointer passed as placeholder for holding
+ * the device product properties is found to be invalid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned when the plugin for the specified oid is not found.
+ *
+ * @retval MP_STATUS_INSUFFICIENT_MEMORY
+ * Returned when memory allocation failure occurs
+ *
+ * @retval MP_STATUS_UNSUPPORTED
+ * Returned when the API is not supported.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetDeviceProductProperties(
+ MP_OID oid,
+ MP_DEVICE_PRODUCT_PROPERTIES *pProps
+);
+
+/**
+ *******************************************************************************
+ *
+ * Gets a list of the object IDs of all the initiator ports associated
+ * with this plugin.
+ *
+ * @param oid
+ * The object ID of plugin.
+ *
+ * @param ppList
+ * A pointer to a pointer to an MP_OID_LIST structure.
+ * On a successful return, this will contain a pointer to
+ * an MP_OID_LIST that contains the object IDs of all the initiator
+ * ports associated with the specified plugin.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if ppList pointer passed as placeholder for holding
+ * the initiator port list is found to be invalid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned when the plugin for the specified oid is not found.
+ *
+ * @retval MP_STATUS_INSUFFICIENT_MEMORY
+ * Returned when memory allocation failure occurs
+ *
+ * @retval MP_STATUS_UNSUPPORTED
+ * Returned when the API is not supported.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetInitiatorPortOidList(
+ MP_OID oid,
+ MP_OID_LIST **ppList
+);
+
+/**
+ *******************************************************************************
+ *
+ * Gets the properties of the specified initiator port.
+ *
+ * @param oid
+ * The object ID of the initiator port.
+ *
+ * @param pProps
+ * A pointer to an MP_INITIATOR_PORT_PROPERTIES structure
+ * allocated by the caller. On successful return, this structure
+ * will contain the properties of the port specified by oid.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pProps is NULL or specifies a memory area to
+ * which data cannot be written.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned if oid has an owner that is not currently known to
+ * the system.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetInitiatorPortProperties(
+ MP_OID oid,
+ MP_INITIATOR_PORT_PROPERTIES *pProps
+);
+
+/**
+ *******************************************************************************
+ *
+ * Gets a list of multipath logical units associated to a plugin.
+ *
+ * @param oid
+ * The object ID of plugin.
+ *
+ * @param ppList
+ * A pointer to a pointer to an MP_OID_LIST structure.
+ * On a successful return, this will contain a pointer to
+ * an MP_OID_LIST that contains the object IDs of all the multipath
+ * logical units associated with the specified plugin.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if ppList pointer passed as placeholder for holding
+ * the multipath logical unit list is found to be invalid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned when the plugin for the specified oid is not found.
+ *
+ * @retval MP_STATUS_INSUFFICIENT_MEMORY
+ * Returned when memory allocation failure occurs
+ *
+ * @retval MP_STATUS_UNSUPPORTED
+ * Returned when the API is not supported.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetMultipathLus(
+ MP_OID oid,
+ MP_OID_LIST **ppList
+);
+
+/**
+ *******************************************************************************
+ *
+ * Gets the properties of the specified logical unit.
+ *
+ * @param oid
+ * The object ID of the multipath logical unit.
+ *
+ * @param pProps
+ * A pointer to an MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES structure
+ * allocated by the caller. On successful return, this structure
+ * will contain the properties of the port specified by oid.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pProps is NULL or specifies a memory area to
+ * which data cannot be written.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned if oid has an owner that is not currently known to
+ * the system.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetMPLogicalUnitProperties(
+ MP_OID oid,
+ MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES *pProps
+);
+
+/**
+ *******************************************************************************
+ *
+ * Gets a list of the object IDs of all the path logical units associated
+ * with the specified multipath logical unit, initiator port, or target port.
+ *
+ * @param oid
+ * The object ID of multipath logical unit, initiator port, or
+ * target port.
+ *
+ * @param ppList
+ * A pointer to a pointer to an MP_OID_LIST structure.
+ * On a successful return, this will contain a pointer to
+ * an MP_OID_LIST that contains the object IDs of all the mp path
+ * logical units associated with the specified OID.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if ppList pointer passed as placeholder for holding
+ * the device product list is found to be invalid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned when the plugin for the specified oid is not found.
+ *
+ * @retval MP_STATUS_INSUFFICIENT_MEMORY
+ * Returned when memory allocation failure occurs
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned if oid has an owner that is not currently known to
+ * the system.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetAssociatedPathOidList(
+ MP_OID oid,
+ MP_OID_LIST **ppList
+);
+
+/**
+ *******************************************************************************
+ *
+ * Gets the properties of the specified path logical unit.
+ *
+ * @param oid
+ * The object ID of the path logical unit.
+ *
+ * @param pProps
+ * A pointer to an MP_PATH_LOGICAL_UNIT_PROPERTIES structure
+ * allocated by the caller. On successful return, this structure
+ * will contain the properties of the port specified by oid.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pProps is NULL or specifies a memory area to
+ * which data cannot be written.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned if oid has an owner that is not currently known to
+ * the system.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetPathLogicalUnitProperties(
+ MP_OID oid,
+ MP_PATH_LOGICAL_UNIT_PROPERTIES *pProps
+);
+
+/**
+ *******************************************************************************
+ *
+ * Gets a list of the object IDs of all the target port group associated
+ * with the specified multipath logical unit.
+ *
+ * @param oid
+ * The object ID of the multiple logical unit.
+ *
+ * @param ppList
+ * A pointer to a pointer to an MP_OID_LIST structure.
+ * On a successful return, this will contain a pointer to
+ * an MP_OID_LIST that contains the object IDs of all the target
+ * port group associated with the specified multipath logical unit.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if ppList pointer passed as placeholder for holding
+ * the target port group list is found to be invalid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned when the plugin for the specified oid is not found.
+ *
+ * @retval MP_STATUS_INSUFFICIENT_MEMORY
+ * Returned when memory allocation failure occurs
+ *
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetAssociatedTPGOidList(
+ MP_OID oid,
+ MP_OID_LIST **ppList
+);
+
+/**
+ *******************************************************************************
+ *
+ * Gets the properties of the specified target port group.
+ *
+ * @param oid
+ * The object ID of the target port group.
+ *
+ * @param pProps
+ * A pointer to an MP_TARGET_PORT_GROUP_PROPERTIES structure
+ * allocated by the caller. On successful return, this structure
+ * will contain the properties of the port specified by oid.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pProps is NULL or specifies a memory area to
+ * which data cannot be written.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned if oid has an owner that is not currently known to
+ * the system.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetTargetPortGroupProperties(
+ MP_OID oid,
+ MP_TARGET_PORT_GROUP_PROPERTIES *pProps
+);
+
+/**
+ *******************************************************************************
+ *
+ * Gets a list of multipath logical units associated with the specific target
+ * port group.
+ *
+ * @param oid
+ * The object ID of the target port group.
+ *
+ * @param ppList
+ * A pointer to a pointer to an MP_OID_LIST structure.
+ * On a successful return, this will contain a pointer to
+ * an MP_OID_LIST that contains the object IDs of all the multipath
+ * logical units associated with the specified target port group.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if ppList pointer passed as placeholder for holding
+ * the multipath logical unit list is found to be invalid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned when the plugin for the specified oid is not found.
+ *
+ * @retval MP_STATUS_INSUFFICIENT_MEMORY
+ * Returned when memory allocation failure occurs
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetMPLuOidListFromTPG(
+ MP_OID oid,
+ MP_OID_LIST **ppList
+);
+
+/**
+ *******************************************************************************
+ *
+ * Gets a list of the object IDs of all the proprietary load balance
+ * algorithms associated with this plugin.
+ *
+ * @param oid
+ * The object ID of the plugin.
+ *
+ * @param ppList
+ * A pointer to a pointer to an MP_OID_LIST structure.
+ * On a successful return, this will contain a pointer to
+ * an MP_OID_LIST that contains the object IDs of all the proprietary
+ * load balance algorithms associated with the specified plugin.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if ppList pointer passed as placeholder for holding
+ * the proprietary load balance oid list is found to be invalid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned when the plugin for the specified oid is not found.
+ *
+ * @retval MP_STATUS_INSUFFICIENT_MEMORY
+ * Returned when memory allocation failure occurs
+ *
+ * @retval MP_STATUS_UNSUPPORTED
+ * Returned when the API is not supported.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetProprietaryLoadBalanceOidList(
+ MP_OID oid,
+ MP_OID_LIST **ppList
+);
+
+/**
+ *******************************************************************************
+ *
+ * Gets the properties of the specified load balance properties structure.
+ *
+ * @param oid
+ * The object ID of the proprietary load balance structure.
+ *
+ * @param pProps
+ * A pointer to an MP_PROPRIETARY_LOAD_BALANCE_PROPERTIES structure
+ * allocated by the caller. On successful return, this structure
+ * will contain the properties of the port specified by oid.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pProps is NULL or specifies a memory area to
+ * which data cannot be written.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned if oid has an owner that is not currently known to
+ * the system.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetProprietaryLoadBalanceProperties(
+ MP_OID oid,
+ MP_PROPRIETARY_LOAD_BALANCE_PROPERTIES *pProps
+);
+
+/**
+ *******************************************************************************
+ *
+ * Gets a list of the object IDs of the target ports in the specified target
+ * port group.
+ *
+ * @param oid
+ * The object ID of the target port group.
+ *
+ * @param ppList
+ * A pointer to a pointer to an MP_OID_LIST structure.
+ * On a successful return, this will contain a pointer to
+ * an MP_OID_LIST that contains the object IDs of all the target ports
+ * associated with the specified target port group.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if ppList pointer passed as placeholder for holding
+ * the multipath logical unit list is found to be invalid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned when the plugin for the specified oid is not found.
+ *
+ * @retval MP_STATUS_INSUFFICIENT_MEMORY
+ * Returned when memory allocation failure occurs
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetTargetPortOidList(
+ MP_OID oid,
+ MP_OID_LIST **ppList
+);
+
+/**
+ *******************************************************************************
+ *
+ * Gets the properties of the specified target port.
+ *
+ * @param oid
+ * The object ID of the target port.
+ *
+ * @param pProps
+ * A pointer to an MP_TARGET_PORT_PROPERTIES structure
+ * allocated by the caller. On successful return, this structure
+ * will contain the properties of the port specified by oid.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pProps is NULL or specifies a memory area to
+ * which data cannot be written.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned if oid has an owner that is not currently known to
+ * the system.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_GetTargetPortProperties(
+ MP_OID oid,
+ MP_TARGET_PORT_PROPERTIES *pProps
+);
+
+/**
+ ******************************************************************************
+ *
+ * The APIs for path management.
+ *
+ * - MP_AssignLogicalUnitToTPG
+ * - MP_SetOverridePath
+ * - MP_CancelOverridePath
+ * - MP_EnableAutoFailback
+ * - MP_DisableAutoFailback
+ * - MP_EnableAutoProbing
+ * - MP_DisableAutoProbing
+ * - MP_EnablePath
+ * - MP_DisablePath
+ * - MP_SetLogicalUnitLoadBalanceType
+ * - MP_SetPluginLoadBalanceType
+ * - MP_SetPathWeight
+ * - MP_SetFailbackPollingRates
+ * - MP_SetProbingPollingRates
+ * - MP_SetProprietaryProperties
+ * - MP_SetTPGAccess
+ *
+ ******************************************************************************
+ */
+
+/**
+ *******************************************************************************
+ *
+ * Assign a multipath logical unit to a target port group.
+ *
+ * @param tpgOid
+ * An MP_TARGET_PORT_GROUP oid. The target port group currently in
+ * active access state that the administrator would like the LU
+ * assigned to.
+ *
+ * @param luOid
+ * An MP_MULTIPATH_LOGICAL_UNIT oid.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned when luOid is not associated with tpgOid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned if oid has an owner that is not currently known to
+ * the system.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_AssignLogicalUnitToTPG(
+ MP_OID tpgOid,
+ MP_OID luOid
+);
+
+/**
+ *******************************************************************************
+ *
+ * Manually override the path for a logical unit. The path exclusively used to
+ * access the logical unit until cleared.
+ *
+ * @param logicalUnitOid
+ * The object ID of the multipath logical unit.
+ *
+ * @param pathOid
+ * The object ID of the path logical unit.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if the oid of the object is not valid
+ *
+ * @retval MP_STATUS_UNSUPPORTED
+ * Returned when the implementation does not support the API
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_PATH_NONOPERATIONAL
+ * Returned when the driver cannot communicate through selected path.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_SetOverridePath(
+ MP_OID logicalUnitOid,
+ MP_OID pathOid
+);
+
+/**
+ *******************************************************************************
+ *
+ * Cancel a path override and re-enable load balancing.
+ *
+ * @param luOid
+ * An MP_MULTIPATH_LOGICAL_UNIT oid.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if MP_MULTIPATH_LOGICAL_UNIT with the luOid is not found.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned if oid has an owner that is not currently known to
+ * the system.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_CancelOverridePath(
+ MP_OID logicalUnitOid
+);
+
+/**
+ *******************************************************************************
+ *
+ * Enables Auto-failback.
+ *
+ * @param oid
+ * The oid of the plugin or the multipath logical unit.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if oid is NULL or specifies a memory area that is not
+ * a valid plugin oid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_EnableAutoFailback(
+ MP_OID oid
+);
+
+/**
+ *******************************************************************************
+ *
+ * Disables Auto-failback.
+ *
+ * @param oid
+ * The oid of the plugin or the multipath logical unit..
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if oid is NULL or specifies a memory area that is not
+ * a valid plugin oid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_DisableAutoFailback(
+ MP_OID oid
+);
+
+/**
+ *******************************************************************************
+ *
+ * Enables Auto-probing.
+ *
+ * @param oid
+ * The oid of the plugin or the multipath logical unit.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if oid is NULL or specifies a memory area that is not
+ * a valid plugin oid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_EnableAutoProbing(
+ MP_OID oid
+);
+
+/**
+ *******************************************************************************
+ *
+ * Disables Auto-probing.
+ *
+ * @param oid
+ * The oid of the plugin or the multipath logical unit.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if oid is NULL or specifies a memory area that is not
+ * a valid plugin oid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_DisableAutoProbing(
+ MP_OID oid
+);
+
+/**
+ *******************************************************************************
+ *
+ * Enables a path. This API may cause failover in a logical unit with
+ * asymmetric access.
+ *
+ * @param oid
+ * The oid of the path.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if oid is NULL or specifies a memory area that is not
+ * a valid path oid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_EnablePath(
+ MP_OID oid
+);
+
+/**
+ *******************************************************************************
+ *
+ * Disables a path. This API may cause failover in a logical unit with
+ * asymmetric access. This API may cause a logical unit to become unavailable.
+ *
+ * @param oid
+ * The oid of the path.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if oid is NULL or specifies a memory area that is not
+ * a valid path oid.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_UNSUPPORTED
+ * Returned when the API is not supported.
+ *
+ * @retval MP_STATUS_TRY_AGAIN
+ * Returned when path cannot be disabled at this time.
+ *
+ * @retval MP_STATUS_NOT_PERMITTED
+ * Returned when disabling thsi path would cause the login unit to
+ * become unavailable.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_DisablePath(
+ MP_OID oid
+);
+
+/**
+ *******************************************************************************
+ *
+ * Set the multipath logical unit s load balancing policy.
+ *
+ * @param logicalUnitoid
+ * The object ID of the multipath logical unit.
+ *
+ * @param loadBanlance
+ * The desired load balance policy for the specified logical unit.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if no MP_MULTIPATH_LOGICAL_UNIT associated with
+ * @ref ligicalUnitrOid is found or invalid MP_LOAD_BALANCE_TYPE is
+ * specified.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned when the specified loadBalance type cannot be handled
+ * by the plugin.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_SetLogicalUnitLoadBalanceType(
+ MP_OID logicalUnitOid,
+ MP_LOAD_BALANCE_TYPE loadBalance
+);
+
+/**
+ *******************************************************************************
+ *
+ * Set the weight to be assigned to a particular path.
+ *
+ * @param pathOid
+ * The object ID of the path logical unit.
+ *
+ * @param weight
+ * weight that will be assigned to the path logical unit.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned when the MP Path specified by the PathOid could not be
+ * found.
+ *
+ * @retval MP_STATUS_UNSUPPORTED
+ * Returned when the implementation does not support the API
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned when the operation failed.
+ *
+ * @retval MP_STATUS_INVALID_WEIGHT
+ * Returned when the weight parameter is greater than the plugin's
+ * maxWeight property.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_SetPathWeight(
+ MP_OID pathOid,
+ MP_UINT32 weight
+);
+
+/**
+ *******************************************************************************
+ *
+ * Set the default load balance policy for the plugin.
+ *
+ * @param oid
+ * The object ID of the plugin
+ *
+ * @param loadBalance
+ * The desired default load balance policy for the specified plugin.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned when the the plugin specified by @ref oid could not be
+ * found.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if the oid of the object is not valid.
+ *
+ * @retval MP_STATUS_UNSUPPORTED
+ * Returned when the implementation does not support the API
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned when the specified loadBalance type cannot be handled
+ * by the plugin.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_SetPluginLoadBalanceType(
+ MP_OID oid,
+ MP_LOAD_BALANCE_TYPE loadBalance
+);
+
+/**
+ *******************************************************************************
+ *
+ * Set the failback polling rates. Setting both rates to zero disables polling.
+ *
+ * @param pluginOid
+ * The object ID of either the plugin or a multipath logical unit.
+ *
+ * @param pollingRate
+ * The value to be set in MP_PLUGIN_PROPERTIES current pollingRate or
+ * MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES pollingRate.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned when the the plugin specified by @ref oid could not be
+ * found.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if one of the polling values is outside the range
+ * supported by the driver.
+ *
+ * @retval MP_STATUS_UNSUPPORTED
+ * Returned when the implementation does not support the API
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_SetFailbackPollingRate(
+ MP_OID oid,
+ MP_UINT32 pollingRate
+);
+
+/**
+ *******************************************************************************
+ *
+ * Set the probing polling rates. Setting both rates to zero disables polling.
+ *
+ * @param pluginOid
+ * The object ID of either the plugin or a multipath logical unit.
+ *
+ * @param pollingRate
+ * The value to be set in MP_PLUGIN_PROPERTIES current pollingRate or
+ * MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES pollingRate.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned when the the plugin specified by @ref oid could not be
+ * found.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if one of the polling values is outside the range
+ * supported by the driver.
+ *
+ * @retval MP_STATUS_UNSUPPORTED
+ * Returned when the implementation does not support the API
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_SetProbingPollingRate(
+ MP_OID oid,
+ MP_UINT32 pollingRate
+);
+
+/**
+ *******************************************************************************
+ *
+ * Set proprietary properties in supported object instances.
+ *
+ * @param pluginOid
+ * The object ID of MP_PROPRIETARY_LOAD_BALANCE_PROPERTIES,
+ * MP_PLUGIN_PROPERTIES or MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES.
+ *
+ * @param count
+ * The number of valid items in pPropertyList.
+ *
+ * @param pPropertyList
+ * A pointer to an array of property name/value pairs. This array must
+ * contain the same number of elements as count.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned when the the plugin specified by @ref oid could not be
+ * found.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if one of the polling values is outside the range
+ * supported by the driver.
+ *
+ * @retval MP_STATUS_UNSUPPORTED
+ * Returned when the implementation does not support the API
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_SetProprietaryProperties(
+ MP_OID oid,
+ MP_UINT32 count,
+ MP_PROPRIETARY_PROPERTY *pPropertyList
+);
+
+/**
+ *******************************************************************************
+ *
+ * Set the access state for a list of target port groups. This allows
+ * a client to force a failover or failback to a desired set of target port
+ * groups.
+ *
+ * @param luOid
+ * The object ID of the logical unit where the command is sent.
+ *
+ * @param count
+ * The number of valid items in the pTpgStateList.
+ *
+ * @param pTpgStateList
+ * A pointer to an array of TPG/access-state values. This array must
+ * contain the same number of elements as @ref count.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_OBJECT_NOT_FOUND
+ * Returned when the MP_MULTIPATH_LOGICAL_UNIT associated with @ref
+ * oid could not be found.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pTpgStateList is null or if one of the TPGs referenced
+ * in the list is not associated with the specified MP logical unit.
+ *
+ * @retval MP_STATUS_UNSUPPORTED
+ * Returned when the implementation does not support the API
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if oid does not specify any valid object type.
+ *
+ * @retval MP_STATUS_ACCESS_STATE_INVALID
+ * Returned if the target device returns a status indicating the caller
+ * is attempting to establish an illegal combination of access states.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned if the underlying interface failed the commend for some
+ * reason other than MP_STATUS_ACCESS_STATE_INVALID
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_SetTPGAccess(
+ MP_OID luOid,
+ MP_UINT32 count,
+ MP_TPG_STATE_PAIR *pTpgStateList
+);
+
+/**
+ ******************************************************************************
+ *
+ * The APIs that are associated with event support.
+ *
+ * - MP_RegisterForObjectPropertyChanges
+ * - MP_DeregisterForObjectPropertyChanges
+ * - MP_RegisterForObjectVisibilityChanges
+ * - MP_DeregisterForObjectVisibilityChanges
+ *
+ ******************************************************************************
+ */
+
+/**
+ *******************************************************************************
+ *
+ * Registers a client function that is to be called
+ * whenever the property of an an object changes.
+ *
+ * @param pClientFn,
+ * A pointer to an MP_OBJECT_PROPERTY_FN function defined by the
+ * client. On successful return this function will be called to
+ * inform the client of objects that have had one or more properties
+ * change.
+ *
+ * @param objectType
+ * The type of object the client wishes to deregister for
+ * property change callbacks. If null, then all objects types are
+ * deregistered.
+ *
+ * @param pCallerData
+ * A pointer that is passed to the callback routine with each event.
+ * This may be used by the caller to correlate the event to source of
+ * the registration.
+ *
+ * @param pluginOid
+ * A plugin oid that the client wishes to deregister for property change.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pClientFn is NULL or specifies a memory area
+ * that is not executable.
+ *
+ * @retval MP_STATUS_FN_REPLACED
+ * Returned when an existing client function is replaced with the one
+ * specified in pClientFn.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if objectType does not specify any valid object type.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_RegisterForObjectPropertyChanges(
+ MP_OBJECT_PROPERTY_FN pClientFn,
+ MP_OBJECT_TYPE objectType,
+ void *pCallerData,
+ MP_OID pluginOid
+);
+
+/**
+ *******************************************************************************
+ *
+ * Deregisters a previously registered client function that is to be invoked
+ * whenever an object's property changes.
+ *
+ * @param pClientFn,
+ * A pointer to an MP_OBJECT_PROPERTY_FN function defined by the
+ * client that was previously registered using
+ * the MP_RegisterForObjectPropertyChanges API. On successful return
+ * this function will no longer be called to inform the client of
+ * object property changes.
+ *
+ * @param objectType
+ * The type of object the client wishes to deregister for
+ * property change callbacks. If null, then all objects types are
+ * deregistered.
+ *
+ * @param pluginOid
+ * A plugin oid that the client wishes to deregister for property change.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pClientFn is NULL or specifies a memory area
+ * that is not executable.
+ *
+ * @retval MP_STATUS_UNKNOWN_FN
+ * Returned if pClientFn is not the same as the previously registered
+ * function.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if objectType does not specify any valid object type.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned if pClientFn deregistration is not possible at this time.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_DeregisterForObjectPropertyChanges(
+ MP_OBJECT_PROPERTY_FN pClientFn,
+ MP_OBJECT_TYPE objectType,
+ MP_OID pluginOid
+);
+
+/**
+ *******************************************************************************
+ *
+ * Registers a client function that is to be called
+ * whenever a high level object appears or disappears.
+ *
+ * @param pClientFn,
+ * A pointer to an MP_OBJECT_VISIBILITY_FN function defined by the
+ * client. On successful return this function will be called to
+ * inform the client of objects whose visibility has changed.
+ *
+ * @param objectType
+ * The type of object the client wishes to deregister for
+ * property change callbacks. If null, then all objects types are
+ * deregistered.
+ *
+ * @param pCallerData
+ * A pointer that is passed to the callback routine with each event.
+ * This may be used by the caller to correlate the event to source of
+ * the registration.
+ *
+ * @param pluginOid
+ * A plugin oid that the client wishes to deregister for property change.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pClientFn is NULL or specifies a memory area
+ * that is not executable.
+ *
+ * @retval MP_STATUS_FN_REPLACED
+ * Returned when an existing client function is replaced with the one
+ * specified in pClientFn.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if objectType does not specify any valid object type.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_RegisterForObjectVisibilityChanges(
+ MP_OBJECT_VISIBILITY_FN pClientFn,
+ MP_OBJECT_TYPE objectType,
+ void *pCallerData,
+ MP_OID pluginOid
+);
+
+/**
+ *******************************************************************************
+ *
+ * Deregisters a previously registered client function that is to be invoked
+ * whenever a high level object appears or disappears.
+ *
+ * @param pClientFn,
+ * A pointer to an MP_OBJECT_VISIBILITY_FN function defined by the
+ * client that was previously registered using
+ * the MP_RegisterForObjectVisibilityChanges API. On successful return
+ * this function will no longer be called to inform the client of
+ * object property changes.
+ *
+ * @param objectType
+ * The type of object the client wishes to deregister for visibility
+ * change callbacks. If null, then all objects types are
+ * deregistered.
+ *
+ * @param pluginOid
+ * A plugin oid that the client wishes to deregister for property change.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the operation is successful.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pClientFn is NULL or specifies a memory area
+ * that is not executable.
+ *
+ * @retval MP_STATUS_UNKNOWN_FN
+ * Returned if pClientFn is not the same as the previously registered
+ * function.
+ *
+ * @retval MP_STATUS_INVALID_OBJECT_TYPE
+ * Returned if objectType does not specify any valid object type.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned if pClientFn deregistration is not possible at this time.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_DeregisterForObjectVisibilityChanges(
+ MP_OBJECT_VISIBILITY_FN pClientFn,
+ MP_OBJECT_TYPE objectType,
+ MP_OID pluginOid
+);
+
+/**
+ ******************************************************************************
+ *
+ * The utility APIs
+ *
+ * - MP_CompareOIDs
+ * - MP_FreeOidList
+ * - MP_RegisterPlugin
+ * - MP_DeregisterPlugin
+ *
+ ******************************************************************************
+ */
+
+/**
+ *******************************************************************************
+ *
+ * Compare two Oids for equality to see whether they refer to the same object.
+ *
+ * @param oid1
+ * Oid to compare.
+ *
+ * @param oid2
+ * Oid to compare.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when the two Oids do refer to the same object.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned if the Oids don't compare.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_CompareOIDs(
+ MP_OID oid1,
+ MP_OID oid2
+);
+
+/**
+ *******************************************************************************
+ *
+ * Frees memory returned by an MP API.
+ *
+ * @param pMemory
+ * A pointer to the memory returned by an MP API. On successful
+ return, the allocated memory is freed.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when pPluginId is deregistered successfully.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pMemory is NULL or specifies a memory area to which
+ * data cannot be written.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_FreeOidList(
+ MP_OID_LIST *pOidList
+);
+
+/**
+ *******************************************************************************
+ *
+ * Registers a plugin with common library. The implementation of this routine
+ * is based on configuration file /etc/mpapi.conf that contains a list of
+ * plugin libraries.
+ *
+ * @param pPluginId
+ * A pointer to the key name shall be the reversed domain name of
+ * the vendor followed by followed by the vendor specific name for
+ * the plugin that uniquely identifies the plugin.
+ *
+ * @param pFileName
+ * The full path to the plugin library.
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when pPluginId is deregistered successfully.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pPluginId is NULL or specifies a memory area that
+ * is not executable.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned if pClientFn deregistration is not possible at this time.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_RegisterPlugin(
+ MP_WCHAR *pPluginId,
+ MP_CHAR *pFileName
+);
+
+/**
+ *******************************************************************************
+ *
+ * Deregisters a plugin from the common library.
+ *
+ * @param pPluginId
+ * A pointer to a Plugin ID previously registered using
+ * the MP_RegisterPlugin API..
+ *
+ * @return An MP_STATUS indicating if the operation was successful or if
+ * an error occurred.
+ *
+ * @retval MP_STATUS_SUCCESS
+ * Returned when pPluginId is deregistered successfully.
+ *
+ * @retval MP_STATUS_INVALID_PARAMETER
+ * Returned if pPluginId is NULL or specifies a memory area that
+ * is not executable.
+ *
+ * @retval MP_STATUS_FAILED
+ * Returned if pClientFn deregistration is not possible at this time.
+ *
+ *******************************************************************************
+ */
+MP_STATUS MP_DeregisterPlugin(
+ MP_WCHAR *pPluginId
+);
+
+#endif
+
+#ifdef __cplusplus
+};
+#endif
+
diff --git a/usr/src/lib/mpapi/libmpapi/i386/Makefile b/usr/src/lib/mpapi/libmpapi/i386/Makefile
new file mode 100644
index 0000000000..c7cca61bea
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpapi/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.
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/mpapi/libmpapi/sparc/Makefile b/usr/src/lib/mpapi/libmpapi/sparc/Makefile
new file mode 100644
index 0000000000..c7cca61bea
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpapi/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.
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/mpapi/libmpapi/sparcv9/Makefile b/usr/src/lib/mpapi/libmpapi/sparcv9/Makefile
new file mode 100644
index 0000000000..bbc20fa470
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpapi/sparcv9/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.
+#
+
+include ../Makefile.com
+include ../../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/Makefile b/usr/src/lib/mpapi/libmpscsi_vhci/Makefile
new file mode 100644
index 0000000000..f7e3396ef5
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/Makefile
@@ -0,0 +1,50 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+include ../../Makefile.lib
+
+SUBDIRS = $(MACH)
+$(BUILD64)SUBDIRS += $(MACH64)
+
+all := TARGET= all
+clean := TARGET= clean
+clobber := TARGET= clobber
+install := TARGET= install
+lint := TARGET= lint
+
+.KEEP_STATE:
+
+all clean clobber install lint: $(SUBDIRS)
+
+install_h:
+
+check:
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+include ../../Makefile.targ
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/Makefile.com b/usr/src/lib/mpapi/libmpscsi_vhci/Makefile.com
new file mode 100644
index 0000000000..4a357345fa
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/Makefile.com
@@ -0,0 +1,74 @@
+#
+# 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.
+#
+
+LIBRARY= libmpscsi_vhci.a
+VERS= .1
+OBJECTS= Initialize.o MP_AssignLogicalUnitToTPG.o \
+ MP_CancelOverridePath.o MP_DeregForObjPropChangesPlugin.o \
+ MP_DeregForObjVisChangesPlugin.o MP_DisableAutoFailbackLu.o \
+ MP_DisableAutoFailbackPlugin.o MP_DisableAutoProbingLu.o \
+ MP_DisableAutoProbingPlugin.o MP_DisablePath.o \
+ MP_EnableAutoFailbackLu.o MP_EnableAutoFailbackPlugin.o \
+ MP_EnableAutoProbingLu.o MP_EnableAutoProbingPlugin.o \
+ MP_EnablePath.o MP_GetAssociatedPathOidList.o \
+ MP_GetAssociatedTPGOidList.o \
+ MP_GetDeviceProductOidListPlugin.o \
+ MP_GetDeviceProductProperties.o \
+ MP_GetInitiatorPortOidListPlugin.o \
+ MP_GetInitiatorPortProperties.o \
+ MP_GetMPLogicalUnitProperties.o \
+ MP_GetMPLuOidListFromTPG.o MP_GetMultipathLusDevProd.o \
+ MP_GetMultipathLusPlugin.o MP_GetPathLogicalUnitProperties.o \
+ MP_GetPluginPropertiesPlugin.o \
+ MP_GetProprietaryLBOidListPlugin.o MP_GetProprietaryLBProp.o \
+ MP_GetTargetPortGroupProperties.o MP_GetTargetPortOidList.o \
+ MP_GetTargetPortProperties.o MP_RegForObjPropChangesPlugin.o \
+ MP_RegForObjVisChangesPlugin.o MP_SetFailbackPollingRateLu.o \
+ MP_SetFailbackPollingRatePlugin.o \
+ MP_SetLogicalUnitLoadBalanceType.o MP_SetOverridePath.o \
+ MP_SetPathWeight.o MP_SetPluginLBTypePlugin.o \
+ MP_SetProbingPollingRateLu.o MP_SetProbingPollingRatePlugin.o \
+ MP_SetProprietaryProperties.o MP_SetTPGAccess.o \
+ Sun_MP_SendScsiCmd.o Terminate.o debug_logging.o mp_utils.o
+
+include ../../../Makefile.lib
+include ../../../Makefile.rootfs
+
+SRCDIR = ../common
+
+LIBS = $(DYNLIB)
+LDLIBS += -lc -ldevinfo -lsysevent -lnvpair
+
+CFLAGS += $(CCVERBOSE)
+CPPFLAGS += -I$(SRCDIR) -D_POSIX_PTHREAD_SEMANTICS
+CPPFLAGS += -DBUILD_TIME='"Wed Sep 24 12:00:00 2008"'
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+lint: lintcheck
+
+include ../../../Makefile.targ
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/amd64/Makefile b/usr/src/lib/mpapi/libmpscsi_vhci/amd64/Makefile
new file mode 100644
index 0000000000..bbc20fa470
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/amd64/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.
+#
+
+include ../Makefile.com
+include ../../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/Initialize.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/Initialize.c
new file mode 100644
index 0000000000..24750cdfab
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/Initialize.c
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "mp_utils.h"
+
+
+/*
+ * Global Variables
+ */
+
+MP_UINT32 g_pluginOwnerID = 0;
+int g_scsi_vhci_fd = -1;
+
+PROPERTY_CALLBACK_NODE g_Property_Callback_List[MP_OBJECT_TYPE_MAX + 1];
+VISIBILITY_CALLBACK_NODE g_Visibility_Callback_List[MP_OBJECT_TYPE_MAX + 1];
+
+sysevent_handle_t *g_SysEventHandle = NULL;
+
+pthread_mutex_t g_visa_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t g_prop_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/*
+ * Called by the common layer to request the plugin to initialize
+ * itself.
+ */
+
+MP_STATUS
+Initialize(MP_UINT32 pluginOwnerID)
+{
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+
+ log(LOG_INFO, "Initialize()", " - enter");
+
+
+ (void) memset(&g_Property_Callback_List, 0,
+ sizeof (PROPERTY_CALLBACK_NODE) * (MP_OBJECT_TYPE_MAX + 1));
+
+ (void) memset(&g_Visibility_Callback_List, 0,
+ sizeof (VISIBILITY_CALLBACK_NODE) * (MP_OBJECT_TYPE_MAX + 1));
+
+ /* Attempt to open the driver that this plugin will make request of. */
+ g_scsi_vhci_fd = open("/devices/scsi_vhci:devctl",
+ O_NDELAY | O_RDONLY);
+
+ if (g_scsi_vhci_fd < 0) {
+ log(LOG_INFO, "Initialize()",
+ " - failed to open driver. error is : %s",
+ strerror(errno));
+ log(LOG_INFO, "Initialize()", " - error exit");
+ return (MP_STATUS_FAILED);
+ }
+
+ g_pluginOwnerID = pluginOwnerID;
+
+ /* Register to listen for visibility and property change events */
+ mpStatus = init_sysevents();
+
+ log(LOG_INFO, "Initialize()",
+ " - init_sysevents() returned %d",
+ mpStatus);
+
+
+ log(LOG_INFO, "Initialize()", " - exit");
+
+ return (mpStatus);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_AssignLogicalUnitToTPG.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_AssignLogicalUnitToTPG.c
new file mode 100644
index 0000000000..7a8863e21d
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_AssignLogicalUnitToTPG.c
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ */
+
+#include <syslog.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stropts.h>
+
+#include "mp_utils.h"
+
+
+/*
+ * Called by the common layer to request the plugin to assign
+ * a logical unit to a TPG. luOid is the logical unit to assign
+ * to the TPG, tpgOid.
+ */
+
+MP_STATUS
+MP_AssignLogicalUnitToTPG(MP_OID tpgOid, MP_OID luOid)
+{
+ mp_lu_tpg_pair_t tpgPair;
+ mp_iocdata_t mp_ioctl;
+
+ int ioctlStatus = 0;
+
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+
+
+ log(LOG_INFO, "MP_AssignLogicalUnitToTPG()", " - enter");
+
+
+ log(LOG_INFO, "MP_AssignLogicalUnitToTPG()",
+ "tpgOid.objectSequenceNumber = %llx",
+ tpgOid.objectSequenceNumber);
+
+ log(LOG_INFO, "MP_AssignLogicalUnitToTPG()",
+ "luOid.objectSequenceNumber = %llx",
+ luOid.objectSequenceNumber);
+
+
+ if (g_scsi_vhci_fd < 0) {
+ log(LOG_INFO, "MP_AssignLogicalUnitToTPG()",
+ "invalid driver file handle");
+ log(LOG_INFO, "MP_AssignLogicalUnitToTPG()",
+ " - error exit");
+ return (MP_STATUS_FAILED);
+ }
+
+ (void) memset(&tpgPair, 0, sizeof (mp_lu_tpg_pair_t));
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+
+ tpgPair.tpgId = tpgOid.objectSequenceNumber;
+ tpgPair.luId = luOid.objectSequenceNumber;
+
+ mp_ioctl.mp_cmd = MP_ASSIGN_LU_TO_TPG;
+ mp_ioctl.mp_ibuf = (caddr_t)&tpgPair;
+ mp_ioctl.mp_ilen = sizeof (mp_lu_tpg_pair_t);
+ mp_ioctl.mp_xfer = MP_XFER_WRITE;
+
+ log(LOG_INFO, "MP_AssignLogicalUnitToTPG()",
+ "mp_ioctl.mp_cmd (MP_ASSIGN_LU_TO_TPG) : %d",
+ mp_ioctl.mp_cmd);
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+
+ log(LOG_INFO, "MP_AssignLogicalUnitToTPG()",
+ " IOCTL call returned: %d", ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if (ioctlStatus != 0) {
+ log(LOG_INFO, "MP_AssignLogicalUnitToTPG()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO, "MP_AssignLogicalUnitToTPG()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO, "MP_AssignLogicalUnitToTPG()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+ if (ENOTSUP == ioctlStatus) {
+ mpStatus = MP_STATUS_UNSUPPORTED;
+ } else if (0 == mp_ioctl.mp_errno) {
+ mpStatus = MP_STATUS_FAILED;
+ } else {
+ mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno);
+ }
+
+ log(LOG_INFO, "MP_AssignLogicalUnitToTPG()",
+ " - error exit, returning %d to caller.", mpStatus);
+
+ return (mpStatus);
+ }
+
+
+ log(LOG_INFO, "MP_AssignLogicalUnitToTPG()", " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_CancelOverridePath.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_CancelOverridePath.c
new file mode 100644
index 0000000000..58efa0d3cb
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_CancelOverridePath.c
@@ -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.
+ */
+
+#include <syslog.h>
+
+#include "mp_utils.h"
+
+
+MP_STATUS
+MP_CancelOverridePath(MP_OID luOid)
+{
+ log(LOG_INFO, "MP_CancelOverridePath()", " - enter");
+
+
+ log(LOG_INFO, "MP_CancelOverridePath()",
+ " - luOid.objectSequenceNumber: %llx",
+ luOid.objectSequenceNumber);
+
+
+ log(LOG_INFO, "MP_CancelOverridePath()", " - exit");
+
+ return (MP_STATUS_UNSUPPORTED);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DeregForObjPropChangesPlugin.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DeregForObjPropChangesPlugin.c
new file mode 100644
index 0000000000..260531406a
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DeregForObjPropChangesPlugin.c
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+#include "mp_utils.h"
+
+
+/*
+ * Called by the common layer to request the plugin to no longer call
+ * a client application's callback (pClientFn) when a property change
+ * is detected for the given object type.
+ */
+
+MP_STATUS
+MP_DeregisterForObjectPropertyChangesPlugin(MP_OBJECT_PROPERTY_FN pClientFn,
+ MP_OBJECT_TYPE objectType)
+{
+ log(LOG_INFO, "MP_DeregisterForObjectPropertyChangesPlugin()",
+ " - enter");
+
+
+ if (NULL == pClientFn) {
+
+ log(LOG_INFO, "MP_DeregisterForObjectPropertyChangesPlugin()",
+ " - pClientFn is NULL");
+
+ log(LOG_INFO, "MP_DeregisterForObjectPropertyChangesPlugin()",
+ " - error exit");
+
+ return (MP_STATUS_INVALID_PARAMETER);
+ }
+
+ /* Validate the object type passes in within range */
+ if (objectType > MP_OBJECT_TYPE_MAX) {
+
+ log(LOG_INFO, "MP_DeregisterForObjectPropertyChangesPlugin()",
+ " - objectType is invalid");
+
+ log(LOG_INFO, "MP_DeregisterForObjectPropertyChangesPlugin()",
+ " - error exit");
+
+ return (MP_STATUS_INVALID_PARAMETER);
+ }
+
+ if (objectType < 1) {
+
+ log(LOG_INFO, "MP_DeregisterForObjectPropertyChangesPlugin()",
+ " - objectType is invalid");
+
+ log(LOG_INFO, "MP_DeregisterForObjectPropertyChangesPlugin()",
+ " - error exit");
+
+ return (MP_STATUS_INVALID_PARAMETER);
+ }
+
+ /* Remove registration. */
+ (void) pthread_mutex_lock(&g_prop_mutex);
+ g_Property_Callback_List[objectType].pClientFn = NULL;
+ g_Property_Callback_List[objectType].pCallerData = NULL;
+ (void) pthread_mutex_unlock(&g_prop_mutex);
+
+
+ log(LOG_INFO, "MP_DeregisterForObjectPropertyChangesPlugin()",
+ " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DeregForObjVisChangesPlugin.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DeregForObjVisChangesPlugin.c
new file mode 100644
index 0000000000..9903d22820
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DeregForObjVisChangesPlugin.c
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+#include "mp_utils.h"
+
+
+/*
+ * Called by the common layer to request the plugin to no longer call
+ * a client application's callback (pClientFn) when a visibility change
+ * is detected for the given object type.
+ */
+
+MP_STATUS
+MP_DeregisterForObjectVisibilityChangesPlugin(MP_OBJECT_VISIBILITY_FN pClientFn,
+ MP_OBJECT_TYPE objectType)
+{
+ log(LOG_INFO, "MP_DeregisterForObjectVisibilityChangesPlugin()",
+ " - enter");
+
+
+ if (NULL == pClientFn) {
+
+ log(LOG_INFO, "MP_DeregisterForObjectVisibilityChangesPlugin()",
+ " - pClientFn is NULL");
+
+ log(LOG_INFO, "MP_DeregisterForObjectVisibilityChangesPlugin()",
+ " - error exit");
+
+ return (MP_STATUS_INVALID_PARAMETER);
+ }
+
+
+ /* Validate the object type passes in within range */
+ if (objectType > MP_OBJECT_TYPE_MAX) {
+
+ log(LOG_INFO, "MP_DeregisterForObjectVisibilityChangesPlugin()",
+ " - objectType is invalid");
+
+ log(LOG_INFO, "MP_DeregisterForObjectVisibilityChangesPlugin()",
+ " - error exit");
+
+ return (MP_STATUS_INVALID_PARAMETER);
+ }
+
+ if (objectType < 1) {
+
+ log(LOG_INFO, "MP_DeregisterForObjectVisibilityChangesPlugin()",
+ " - objectType is invalid");
+
+ log(LOG_INFO, "MP_DeregisterForObjectVisibilityChangesPlugin()",
+ " - error exit");
+
+ return (MP_STATUS_INVALID_PARAMETER);
+ }
+
+ /* Remove registration. */
+ (void) pthread_mutex_lock(&g_visa_mutex);
+ g_Visibility_Callback_List[objectType].pClientFn = NULL;
+ g_Visibility_Callback_List[objectType].pCallerData = NULL;
+ (void) pthread_mutex_unlock(&g_visa_mutex);
+
+
+ log(LOG_INFO, "MP_DeregisterForObjectVisibilityChangesPlugin()",
+ " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DisableAutoFailbackLu.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DisableAutoFailbackLu.c
new file mode 100644
index 0000000000..ef71c84723
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DisableAutoFailbackLu.c
@@ -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.
+ */
+
+#include <syslog.h>
+
+#include "mp_utils.h"
+
+
+MP_STATUS
+MP_DisableAutoFailbackLu(MP_OID oid)
+{
+ log(LOG_INFO, "MP_DisableAutoFailbackLu()", " - enter");
+
+
+ log(LOG_INFO, "MP_DisableAutoFailbackLu()",
+ " - oid.objectSequenceNumber: %llx",
+ oid.objectSequenceNumber);
+
+
+ log(LOG_INFO, "MP_DisableAutoFailbackLu()", " - exit");
+
+ return (MP_STATUS_UNSUPPORTED);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DisableAutoFailbackPlugin.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DisableAutoFailbackPlugin.c
new file mode 100644
index 0000000000..50d1b3d90e
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DisableAutoFailbackPlugin.c
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+
+#include <syslog.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stropts.h>
+
+#include "mp_utils.h"
+
+
+/*
+ * Called by the common layer to request the plugin to request
+ * to disable autofailback.
+ */
+
+MP_STATUS
+MP_DisableAutoFailbackPlugin(void)
+{
+ mp_iocdata_t mp_ioctl;
+
+ int ioctlStatus = 0;
+
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+ char chBuffer[256];
+
+
+
+ log(LOG_INFO, "MP_DisableAutoFailbackPlugin()", " - enter");
+
+
+ if (g_scsi_vhci_fd < 0) {
+ log(LOG_INFO, "MP_DisableAutoFailbackPlugin()",
+ "invalid driver file handle");
+ log(LOG_INFO, "MP_DisableAutoFailbackPlugin()",
+ " - error exit");
+ return (MP_STATUS_FAILED);
+ }
+
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+ (void) memset(&chBuffer, 0, 256);
+
+ mp_ioctl.mp_cmd = MP_DISABLE_AUTO_FAILBACK;
+ mp_ioctl.mp_ibuf = (caddr_t)&chBuffer[0];
+ mp_ioctl.mp_xfer = MP_XFER_WRITE;
+
+
+ log(LOG_INFO, "MP_DisableAutoFailbackPlugin()",
+ "mp_ioctl.mp_cmd (MP_DISABLE_AUTO_FAILBACK) : %d",
+ mp_ioctl.mp_cmd);
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+
+ log(LOG_INFO, "MP_DisableAutoFailbackPlugin()",
+ " IOCTL call returned: %d", ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if (ioctlStatus != 0) {
+ log(LOG_INFO, "MP_DisableAutoFailbackPlugin()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO, "MP_DisableAutoFailbackPlugin()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO, "MP_DisableAutoFailbackPlugin()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+ if (ENOTSUP == ioctlStatus) {
+ mpStatus = MP_STATUS_UNSUPPORTED;
+ } else if (0 == mp_ioctl.mp_errno) {
+ mpStatus = MP_STATUS_FAILED;
+ } else {
+ mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno);
+ }
+
+ log(LOG_INFO, "MP_DisableAutoFailbackPlugin()",
+ " - error exit");
+
+ return (mpStatus);
+ }
+
+
+ log(LOG_INFO, "MP_DisableAutoFailbackPlugin()", " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DisableAutoProbingLu.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DisableAutoProbingLu.c
new file mode 100644
index 0000000000..7cfb2fe019
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DisableAutoProbingLu.c
@@ -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.
+ */
+
+#include <syslog.h>
+
+#include "mp_utils.h"
+
+
+MP_STATUS
+MP_DisableAutoProbingLu(MP_OID oid)
+{
+ log(LOG_INFO, "MP_DisableAutoProbingLu()", " - enter");
+
+
+ log(LOG_INFO, "MP_DisableAutoProbingLu()",
+ " - oid.objectSequenceNumber: %llx",
+ oid.objectSequenceNumber);
+
+
+ log(LOG_INFO, "MP_DisableAutoProbingLu()", " - exit");
+
+ return (MP_STATUS_UNSUPPORTED);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DisableAutoProbingPlugin.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DisableAutoProbingPlugin.c
new file mode 100644
index 0000000000..0ba0ea3bda
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DisableAutoProbingPlugin.c
@@ -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.
+ */
+
+#include <syslog.h>
+
+#include "mp_utils.h"
+
+
+MP_STATUS
+MP_DisableAutoProbingPlugin(void)
+{
+ log(LOG_INFO, "MP_DisableAutoProbingPlugin()", " - enter");
+
+
+ log(LOG_INFO, "MP_DisableAutoProbingPlugin()", " - exit");
+
+ return (MP_STATUS_UNSUPPORTED);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DisablePath.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DisablePath.c
new file mode 100644
index 0000000000..a46abda663
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_DisablePath.c
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+
+#include <syslog.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stropts.h>
+
+#include "mp_utils.h"
+
+
+/*
+ * Called by the common layer to request to disable a path
+ */
+
+MP_STATUS
+MP_DisablePath(MP_OID oid)
+{
+ mp_iocdata_t mp_ioctl;
+
+ int ioctlStatus = 0;
+
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+
+
+ log(LOG_INFO, "MP_DisablePath()", " - enter");
+
+
+ log(LOG_INFO, "MP_DisablePath()",
+ "oid.objectSequenceNumber = %llx",
+ oid.objectSequenceNumber);
+
+ if (g_scsi_vhci_fd < 0) {
+ log(LOG_INFO, "MP_DisablePath()",
+ "invalid driver file handle");
+ log(LOG_INFO, "MP_DisablePath()", " - error exit");
+ return (MP_STATUS_FAILED);
+ }
+
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+
+ mp_ioctl.mp_cmd = MP_DISABLE_PATH;
+ mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber;
+ mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber);
+ mp_ioctl.mp_xfer = MP_XFER_WRITE;
+
+ log(LOG_INFO, "MP_DisablePath()",
+ "mp_ioctl.mp_cmd (MP_DISABLE_PATH) : %d",
+ mp_ioctl.mp_cmd);
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+
+ log(LOG_INFO, "MP_DisablePath()",
+ " IOCTL call returned: %d", ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if (ioctlStatus != 0) {
+ log(LOG_INFO, "MP_DisablePath()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO, "MP_DisablePath()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO, "MP_DisablePath()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+ if (ENOTSUP == ioctlStatus) {
+ mpStatus = MP_STATUS_UNSUPPORTED;
+ } else if (0 == mp_ioctl.mp_errno) {
+ mpStatus = MP_STATUS_FAILED;
+ } else {
+ mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno);
+ }
+
+ log(LOG_INFO, "MP_DisablePath()",
+ " - error exit");
+
+ return (mpStatus);
+ }
+
+
+ log(LOG_INFO, "MP_DisablePath()", " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_EnableAutoFailbackLu.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_EnableAutoFailbackLu.c
new file mode 100644
index 0000000000..18a272cf18
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_EnableAutoFailbackLu.c
@@ -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.
+ */
+
+#include <syslog.h>
+
+#include "mp_utils.h"
+
+
+MP_STATUS
+MP_EnableAutoFailbackLu(MP_OID oid)
+{
+ log(LOG_INFO, "MP_EnableAutoFailbackLu()", " - enter");
+
+
+ log(LOG_INFO, "MP_EnableAutoFailbackLu()",
+ " - oid.objectSequenceNumber: %llx",
+ oid.objectSequenceNumber);
+
+
+ log(LOG_INFO, "MP_EnableAutoFailbackLu()", " - exit");
+
+ return (MP_STATUS_UNSUPPORTED);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_EnableAutoFailbackPlugin.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_EnableAutoFailbackPlugin.c
new file mode 100644
index 0000000000..90b33d1303
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_EnableAutoFailbackPlugin.c
@@ -0,0 +1,105 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <syslog.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stropts.h>
+
+#include "mp_utils.h"
+
+
+MP_STATUS
+MP_EnableAutoFailbackPlugin(void)
+{
+ mp_iocdata_t mp_ioctl;
+
+ int ioctlStatus = 0;
+
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+ char chBuffer[256];
+
+
+ log(LOG_INFO, "MP_EnableAutoFailbackPlugin()", " - enter");
+
+
+ if (g_scsi_vhci_fd < 0) {
+ log(LOG_INFO, "MP_EnableAutoFailbackPlugin()",
+ "invalid driver file handle");
+ log(LOG_INFO, "MP_EnableAutoFailbackPlugin()", " - error exit");
+ return (MP_STATUS_FAILED);
+ }
+
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+ (void) memset(&chBuffer, 0, 256);
+
+ mp_ioctl.mp_cmd = MP_ENABLE_AUTO_FAILBACK;
+ mp_ioctl.mp_ibuf = (caddr_t)&chBuffer[0];
+ mp_ioctl.mp_xfer = MP_XFER_WRITE;
+
+ log(LOG_INFO, "MP_EnableAutoFailbackPlugin()",
+ "mp_ioctl.mp_cmd (MP_ENABLE_AUTO_FAILBACK) : %d",
+ mp_ioctl.mp_cmd);
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+
+ log(LOG_INFO, "MP_EnableAutoFailbackPlugin()",
+ " IOCTL call returned: %d", ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if (ioctlStatus != 0) {
+ log(LOG_INFO, "MP_EnableAutoFailbackPlugin()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO, "MP_EnableAutoFailbackPlugin()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO, "MP_EnableAutoFailbackPlugin()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+ if (ENOTSUP == ioctlStatus) {
+ mpStatus = MP_STATUS_UNSUPPORTED;
+ } else if (0 == mp_ioctl.mp_errno) {
+ mpStatus = MP_STATUS_FAILED;
+ } else {
+ mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno);
+ }
+
+ log(LOG_INFO, "MP_EnableAutoFailbackPlugin()",
+ " - error exit");
+
+ return (mpStatus);
+ }
+
+
+ log(LOG_INFO, "MP_EnableAutoFailbackPlugin()", " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_EnableAutoProbingLu.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_EnableAutoProbingLu.c
new file mode 100644
index 0000000000..1c185010a8
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_EnableAutoProbingLu.c
@@ -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.
+ */
+
+#include <syslog.h>
+
+#include "mp_utils.h"
+
+
+MP_STATUS
+MP_EnableAutoProbingLu(MP_OID oid)
+{
+ log(LOG_INFO, "MP_EnableAutoProbingLu()", " - enter");
+
+
+ log(LOG_INFO, "MP_EnableAutoProbingLu()",
+ " - oid.objectSequenceNumber: %llx",
+ oid.objectSequenceNumber);
+
+
+ log(LOG_INFO, "MP_EnableAutoProbingLu()", " - exit");
+
+ return (MP_STATUS_UNSUPPORTED);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_EnableAutoProbingPlugin.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_EnableAutoProbingPlugin.c
new file mode 100644
index 0000000000..c3f74c35c1
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_EnableAutoProbingPlugin.c
@@ -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.
+ */
+
+#include <syslog.h>
+
+#include "mp_utils.h"
+
+
+MP_STATUS
+MP_EnableAutoProbingPlugin(void)
+{
+ log(LOG_INFO, "MP_EnableAutoProbingPlugin()", " - enter");
+
+
+ log(LOG_INFO, "MP_EnableAutoProbingPlugin()", " - exit");
+
+ return (MP_STATUS_UNSUPPORTED);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_EnablePath.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_EnablePath.c
new file mode 100644
index 0000000000..41e66a77ee
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_EnablePath.c
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+
+
+#include <syslog.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stropts.h>
+
+#include "mp_utils.h"
+
+
+/*
+ * Called by the common layer to request to enable a path
+ */
+
+MP_STATUS
+MP_EnablePath(MP_OID oid)
+{
+ mp_iocdata_t mp_ioctl;
+
+ int ioctlStatus = 0;
+
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+
+
+ log(LOG_INFO, "MP_EnablePath()", " - enter");
+
+
+ log(LOG_INFO, "MP_EnablePath()",
+ "oid.objectSequenceNumber = %llx",
+ oid.objectSequenceNumber);
+
+ if (g_scsi_vhci_fd < 0) {
+ log(LOG_INFO, "MP_EnablePath()",
+ "invalid driver file handle");
+ log(LOG_INFO, "MP_EnablePath()", " - error exit");
+ return (MP_STATUS_FAILED);
+ }
+
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+
+ mp_ioctl.mp_cmd = MP_ENABLE_PATH;
+ mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber;
+ mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber);
+ mp_ioctl.mp_xfer = MP_XFER_WRITE;
+
+ log(LOG_INFO, "MP_EnablePath()",
+ "mp_ioctl.mp_cmd (MP_ENABLE_PATH) : %d",
+ mp_ioctl.mp_cmd);
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+
+ log(LOG_INFO, "MP_EnablePath()",
+ " IOCTL call returned: %d", ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if (ioctlStatus != 0) {
+ log(LOG_INFO, "MP_EnablePath()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO, "MP_EnablePath()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO, "MP_EnablePath()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+ if (ENOTSUP == ioctlStatus) {
+ mpStatus = MP_STATUS_UNSUPPORTED;
+ } else if (0 == mp_ioctl.mp_errno) {
+ mpStatus = MP_STATUS_FAILED;
+ } else {
+ mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno);
+ }
+
+ log(LOG_INFO, "MP_EnablePath()",
+ " - error exit");
+
+ return (mpStatus);
+ }
+
+
+ log(LOG_INFO, "MP_EnablePath()", " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetAssociatedPathOidList.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetAssociatedPathOidList.c
new file mode 100644
index 0000000000..cfc0842afa
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetAssociatedPathOidList.c
@@ -0,0 +1,652 @@
+/*
+ * 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.
+ */
+
+#include <syslog.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stropts.h>
+
+#include "mp_utils.h"
+
+#include <libdevinfo.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+
+static MP_STATUS doDevInfoStuffForIntPort(MP_OID oid)
+{
+ di_node_t root_node = DI_NODE_NIL;
+
+ di_node_t vh_node = DI_NODE_NIL;
+ di_node_t ph_node = DI_NODE_NIL;
+ di_node_t sv_node = DI_NODE_NIL;
+
+
+ di_path_t path = DI_PATH_NIL;
+
+ struct stat buffer;
+
+ int instNum = 0;
+ int majorNum = 0;
+
+ int oidInstNum = 0;
+ int oidMajorNum = 0;
+
+ int found = 0;
+ int status = -1;
+
+
+ char *pathName = NULL;
+ char *minorName = "c";
+
+ char fullName[512];
+
+
+
+
+ log(LOG_INFO, "doDevInfoStuffForIntPort()", " - enter");
+
+
+ oidInstNum = (int)MP_GET_INST_FROM_ID(oid.objectSequenceNumber);
+ oidMajorNum = (int)MP_GET_MAJOR_FROM_ID(oid.objectSequenceNumber);
+
+
+ root_node = di_init("/", DINFOCACHE);
+ if (DI_NODE_NIL == root_node) {
+ log(LOG_INFO, "doDevInfoStuffForIntPort()",
+ " - di_init() failed");
+
+ return (MP_STATUS_FAILED);
+ }
+
+ vh_node = di_vhci_first_node(root_node);
+
+ while (DI_NODE_NIL != vh_node) {
+ if ((di_driver_name(vh_node) != NULL) &&
+ (strncmp(di_driver_name(vh_node), "scsi_vhci", 9) == 0)) {
+ ph_node = di_phci_first_node(vh_node);
+ while (DI_NODE_NIL != ph_node) {
+
+ instNum = di_instance(ph_node);
+ majorNum = di_driver_major(ph_node);
+
+ if ((majorNum == oidMajorNum) &&
+ (instNum == oidInstNum)) {
+
+ log(LOG_INFO,
+ "doDevInfoStuffForIntPort()",
+ "got a match");
+
+ found = 1;
+
+ break;
+ }
+
+ ph_node = di_phci_next_node(ph_node);
+ }
+ }
+
+ if (found) {
+
+ break;
+ }
+
+ vh_node = di_vhci_next_node(vh_node);
+ }
+
+
+ if (!found) {
+
+ di_fini(root_node);
+
+ log(LOG_INFO,
+ "doDevInfoStuffForIntPort()",
+ " - no match found, error exit");
+
+ return (MP_STATUS_OBJECT_NOT_FOUND);
+ }
+
+
+ path = di_path_next(ph_node, DI_PATH_NIL);
+
+ if (DI_PATH_NIL == path) {
+
+ log(LOG_INFO, "doDevInfoStuffForIntPort()",
+ " - path is DI_PATH_NIL");
+ }
+
+ while (DI_PATH_NIL != path) {
+
+ sv_node = di_path_client_node(path);
+ if (DI_NODE_NIL == sv_node) {
+
+ log(LOG_INFO, "doDevInfoStuffForIntPort()",
+ " - sv_node is DI_NODE_NIL");
+
+ } else {
+
+ pathName = di_devfs_path(sv_node);
+ (void) snprintf(fullName, 511, "/devices%s:%s",
+ pathName, minorName);
+
+ (void) di_devfs_path_free(pathName);
+
+ status = stat(fullName, &buffer);
+ if (status < 0) {
+
+ log(LOG_INFO,
+ "doDevInfoStuffForIntPort()",
+ " - stat() call failed: %d", status);
+
+ log(LOG_INFO,
+ "doDevInfoStuffForIntPort()",
+ " - errno: [%d].", errno);
+
+ log(LOG_INFO,
+ "doDevInfoStuffForIntPort()",
+ " - strerror(errno): [%s].",
+ strerror(errno));
+
+
+ di_fini(root_node);
+
+ log(LOG_INFO,
+ "doDevInfoStuffForIntPort()",
+ " - error exit.");
+
+ return (MP_STATUS_FAILED);
+ }
+ }
+
+ path = di_path_next(ph_node, path);
+ }
+
+
+ di_fini(root_node);
+
+ log(LOG_INFO, "doDevInfoStuffForIntPort()", " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
+
+
+static MP_STATUS doDevInfoStuffForTargetPort(MP_OID oid)
+{
+ di_node_t root_node = DI_NODE_NIL;
+ di_node_t sv_node = DI_NODE_NIL;
+ di_node_t child_node = DI_NODE_NIL;
+
+ di_path_t path = DI_PATH_NIL;
+
+ int match = 0;
+ int count = 0;
+ int ioctlStatus = 0;
+ int status = -1;
+
+ struct stat buffer;
+
+ char *pathName = NULL;
+ char *minorName = "c";
+
+ char fullName[512];
+
+ uchar_t *targetPort = NULL;
+
+ mp_iocdata_t mp_ioctl;
+
+ mp_target_port_prop_t tpInfo;
+
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+
+ log(LOG_INFO, "doDevInfoStuffForTargetPort()", " - enter");
+
+
+ log(LOG_INFO, "doDevInfoStuffForTargetPort()",
+ "oid.objectSequenceNumber = %llx",
+ oid.objectSequenceNumber);
+
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+ (void) memset(&tpInfo, 0, sizeof (mp_target_port_prop_t));
+
+ mp_ioctl.mp_cmd = MP_GET_TARGET_PORT_PROP;
+ mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber;
+ mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber);
+ mp_ioctl.mp_obuf = (caddr_t)&tpInfo;
+ mp_ioctl.mp_olen = sizeof (mp_target_port_prop_t);
+ mp_ioctl.mp_xfer = MP_XFER_READ;
+
+ log(LOG_INFO, "doDevInfoStuffForTargetPort()",
+ "mp_ioctl.mp_cmd (MP_GET_TARGET_PORT_PROP) : %d",
+ mp_ioctl.mp_cmd);
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+
+ log(LOG_INFO, "doDevInfoStuffForTargetPort()",
+ " IOCTL call returned: %d", ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if (ioctlStatus != 0) {
+ log(LOG_INFO, "doDevInfoStuffForTargetPort()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO, "doDevInfoStuffForTargetPort()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO, "doDevInfoStuffForTargetPort()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+ if (ENOTSUP == ioctlStatus) {
+ mpStatus = MP_STATUS_UNSUPPORTED;
+ } else if (0 == mp_ioctl.mp_errno) {
+ mpStatus = MP_STATUS_FAILED;
+ } else {
+ mpStatus =
+ getStatus4ErrorCode(mp_ioctl.mp_errno);
+ }
+
+ log(LOG_INFO, "doDevInfoStuffForTargetPort()",
+ " - error exit");
+
+ return (mpStatus);
+ }
+
+ root_node = di_init("/", DINFOCACHE);
+
+ if (DI_NODE_NIL == root_node) {
+ log(LOG_INFO, "doDevInfoStuffForTargetPort()",
+ " - di_init() failed");
+
+ return (MP_STATUS_FAILED);
+ }
+
+
+ sv_node = di_drv_first_node("scsi_vhci", root_node);
+ if (DI_NODE_NIL == sv_node) {
+ log(LOG_INFO, "doDevInfoStuffForTargetPort()",
+ " - di_drv_first_node() failed");
+
+ di_fini(root_node);
+
+ return (MP_STATUS_FAILED);
+ }
+
+ child_node = di_child_node(sv_node);
+
+ while (DI_NODE_NIL != child_node) {
+
+ path = di_path_next(child_node, path);
+
+ match = 0;
+
+ while (DI_PATH_NIL != path) {
+
+ count = di_path_prop_lookup_bytes(path,
+ "target-port",
+ &targetPort);
+
+ if (NULL != targetPort) {
+
+ if (0 == memcmp(targetPort,
+ tpInfo.portName,
+ count)) {
+
+ match = 1;
+
+ break;
+ }
+ }
+
+ path = di_path_next(child_node, path);
+ }
+
+ if (match) {
+
+ log(LOG_INFO, "doDevInfoStuffForTargetPort()",
+ " - got a match");
+
+ pathName = di_devfs_path(child_node);
+
+ (void) snprintf(fullName, 511, "/devices%s:%s",
+ pathName, minorName);
+
+ (void) di_devfs_path_free(pathName);
+
+ status = stat(fullName, &buffer);
+ if (status < 0) {
+
+ log(LOG_INFO,
+ "doDevInfoStuffForTargetPort()",
+ " - stat() call failed: %d", status);
+
+ log(LOG_INFO,
+ "doDevInfoStuffForTargetPort()",
+ " - errno: [%d].", errno);
+
+ log(LOG_INFO,
+ "doDevInfoStuffForTargetPort()",
+ " - strerror(errno): [%s].",
+ strerror(errno));
+
+
+ di_fini(root_node);
+
+ log(LOG_INFO,
+ "doDevInfoStuffForTargetPort()",
+ " - error exit.");
+
+ return (MP_STATUS_FAILED);
+ }
+ }
+
+ child_node = di_sibling_node(child_node);
+ }
+
+
+ di_fini(root_node);
+
+ log(LOG_INFO, "doDevInfoStuffForTargetPort()", " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
+
+
+
+MP_STATUS
+MP_GetAssociatedPathOidList(MP_OID oid, MP_OID_LIST **ppList)
+{
+ mp_iocdata_t mp_ioctl;
+
+ uint64_t *objList = NULL;
+
+ int numOBJ = 0;
+ int i = 0;
+ int ioctlStatus = 0;
+
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+ int request = MP_GET_PATH_LIST_FOR_MP_LU;
+
+
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()", " - enter");
+
+
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ " set default request to MP_GET_PATH_LIST_FOR_MP_LU");
+
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "oid.objectSequenceNumber = %llx",
+ oid.objectSequenceNumber);
+
+
+ if (g_scsi_vhci_fd < 0) {
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "invalid driver file handle");
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()", " - error exit");
+ return (MP_STATUS_FAILED);
+ }
+
+ if (MP_OBJECT_TYPE_INITIATOR_PORT == oid.objectType) {
+ request = MP_GET_PATH_LIST_FOR_INIT_PORT;
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ " set request to MP_GET_PATH_LIST_FOR_INIT_PORT");
+
+ mpStatus = doDevInfoStuffForIntPort(oid);
+ if (MP_STATUS_SUCCESS != mpStatus) {
+
+ return (mpStatus);
+ }
+ } else if (MP_OBJECT_TYPE_TARGET_PORT == oid.objectType) {
+ request = MP_GET_PATH_LIST_FOR_TARGET_PORT;
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ " set request to MP_GET_PATH_LIST_FOR_TARGET_PORT");
+
+ mpStatus = doDevInfoStuffForTargetPort(oid);
+ if (MP_STATUS_SUCCESS != mpStatus) {
+
+ return (mpStatus);
+ }
+ }
+
+ objList = (uint64_t *)calloc(1, DEFAULT_BUFFER_SIZE_PATH_LIST);
+ if (NULL == objList) {
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "no memory for objList(1)");
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ " - error exit");
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+
+ mp_ioctl.mp_cmd = request;
+ mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber;
+ mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber);
+ mp_ioctl.mp_obuf = (caddr_t)objList;
+ mp_ioctl.mp_olen = DEFAULT_BUFFER_SIZE_PATH_LIST;
+ mp_ioctl.mp_xfer = MP_XFER_READ;
+
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "mp_ioctl.mp_cmd : %d", mp_ioctl.mp_cmd);
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "mp_ioctl.mp_obuf: %x", mp_ioctl.mp_obuf);
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "mp_ioctl.mp_olen: %d", mp_ioctl.mp_olen);
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "mp_ioctl.mp_xfer: %d (MP_XFER_READ)",
+ mp_ioctl.mp_xfer);
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "ioctl call returned ioctlStatus: %d",
+ ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if ((ioctlStatus != 0) && (MP_MORE_DATA != mp_ioctl.mp_errno)) {
+
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+
+ free(objList);
+
+ if (ENOTSUP == ioctlStatus) {
+ mpStatus = MP_STATUS_UNSUPPORTED;
+ } else if (0 == mp_ioctl.mp_errno) {
+ mpStatus = MP_STATUS_FAILED;
+ } else {
+ mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno);
+ }
+
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ " - error exit");
+
+ return (mpStatus);
+ }
+
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ " - mp_ioctl.mp_alen : %d",
+ mp_ioctl.mp_alen);
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ " - sizeof (uint64_t): %d",
+ sizeof (uint64_t));
+
+ numOBJ = mp_ioctl.mp_alen / sizeof (uint64_t);
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "Length of list: %d", numOBJ);
+
+ if (numOBJ < 1) {
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "driver returned empty list.");
+
+ free(objList);
+
+ *ppList = createOidList(1);
+ if (NULL == *ppList) {
+ log(LOG_INFO,
+ "MP_GetAssociatedPathOidList()",
+ "no memory for MP_OID_LIST");
+ log(LOG_INFO,
+ "MP_GetAssociatedPathOidList()",
+ " - error exit");
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ return (MP_STATUS_SUCCESS);
+ }
+
+ if (mp_ioctl.mp_alen > DEFAULT_BUFFER_SIZE_PATH_LIST) {
+
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "buffer size too small, need : %d",
+ mp_ioctl.mp_alen);
+
+ free(objList);
+
+ objList = (uint64_t *)calloc(1, numOBJ * sizeof (uint64_t));
+ if (NULL == objList) {
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "no memory for objList(2)");
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ " - error exit");
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+
+ mp_ioctl.mp_cmd = request;
+ mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber;
+ mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber);
+ mp_ioctl.mp_obuf = (caddr_t)objList;
+ mp_ioctl.mp_olen = numOBJ * sizeof (uint64_t);
+ mp_ioctl.mp_xfer = MP_XFER_READ;
+
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "mp_ioctl.mp_cmd : %d", mp_ioctl.mp_cmd);
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "mp_ioctl.mp_obuf: %x", mp_ioctl.mp_obuf);
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "mp_ioctl.mp_olen: %d", mp_ioctl.mp_olen);
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "mp_ioctl.mp_xfer: %d (MP_XFER_READ)",
+ mp_ioctl.mp_xfer);
+
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "ioctl call returned ioctlStatus: %d",
+ ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if (ioctlStatus != 0) {
+
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+
+ free(objList);
+
+ if (ENOTSUP == ioctlStatus) {
+ mpStatus = MP_STATUS_UNSUPPORTED;
+ } else if (0 == mp_ioctl.mp_errno) {
+ mpStatus = MP_STATUS_FAILED;
+ } else {
+ mpStatus =
+ getStatus4ErrorCode(mp_ioctl.mp_errno);
+ }
+
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ " - error exit");
+
+ return (mpStatus);
+ }
+ }
+
+
+ *ppList = createOidList(numOBJ);
+ if (NULL == *ppList) {
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "no memory for *ppList");
+ free(objList);
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ " - error exit");
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ (*ppList)->oidCount = numOBJ;
+
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "(*ppList)->oidCount = %d",
+ (*ppList)->oidCount);
+
+ for (i = 0; i < numOBJ; i++) {
+ (*ppList)->oids[i].objectType = MP_OBJECT_TYPE_PATH_LU;
+ (*ppList)->oids[i].ownerId = g_pluginOwnerID;
+ (*ppList)->oids[i].objectSequenceNumber = objList[i];
+
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "(*ppList)->oids[%d].objectType = %d",
+ i, (*ppList)->oids[i].objectType);
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "(*ppList)->oids[%d].ownerId = %d",
+ i, (*ppList)->oids[i].ownerId);
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()",
+ "(*ppList)->oids[%d].objectSequenceNumber = %llx",
+ i, (*ppList)->oids[i].objectSequenceNumber);
+ }
+
+ free(objList);
+
+
+ log(LOG_INFO, "MP_GetAssociatedPathOidList()", " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetAssociatedTPGOidList.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetAssociatedTPGOidList.c
new file mode 100644
index 0000000000..9223803e10
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetAssociatedTPGOidList.c
@@ -0,0 +1,295 @@
+/*
+ * 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.
+ */
+
+#include <syslog.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stropts.h>
+
+#include "mp_utils.h"
+MP_STATUS
+MP_GetAssociatedTPGOidList(MP_OID oid, MP_OID_LIST **ppList)
+{
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+
+ log(LOG_INFO, "MP_GetAssociatedTPGOidList()", " - enter");
+
+
+ mpStatus = getAssociatedTPGOidList(oid, ppList);
+
+
+ log(LOG_INFO, "MP_GetAssociatedTPGOidList()", " - exit");
+
+ return (mpStatus);
+}
+
+
+MP_STATUS
+getAssociatedTPGOidList(MP_OID oid, MP_OID_LIST **ppList)
+{
+ mp_iocdata_t mp_ioctl;
+
+ uint64_t *objList = NULL;
+
+ int numOBJ = 0;
+ int i = 0;
+ int ioctlStatus = 0;
+
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+
+ log(LOG_INFO, "getAssociatedTPGOidList()", " - enter");
+
+
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "oid.objectSequenceNumber = %llx",
+ oid.objectSequenceNumber);
+
+ if (g_scsi_vhci_fd < 0) {
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "invalid driver file handle");
+ log(LOG_INFO, "getAssociatedTPGOidList()", " - error exit");
+ return (MP_STATUS_FAILED);
+ }
+
+ objList = (uint64_t *)calloc(1, DEFAULT_BUFFER_SIZE_TPG);
+ if (NULL == objList) {
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "no memory for objList(1)");
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ " - error exit");
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+
+ mp_ioctl.mp_cmd = MP_GET_TPG_LIST;
+ mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber;
+ mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber);
+ mp_ioctl.mp_obuf = (caddr_t)objList;
+ mp_ioctl.mp_olen = DEFAULT_BUFFER_SIZE_TPG;
+ mp_ioctl.mp_xfer = MP_XFER_READ;
+
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "mp_ioctl.mp_cmd (MP_GET_TPG_LIST) : %d",
+ mp_ioctl.mp_cmd);
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "mp_ioctl.mp_obuf: %x", mp_ioctl.mp_obuf);
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "mp_ioctl.mp_olen: %d", mp_ioctl.mp_olen);
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "mp_ioctl.mp_xfer: %d (MP_XFER_READ)",
+ mp_ioctl.mp_xfer);
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "ioctl call returned ioctlStatus: %d",
+ ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if ((ioctlStatus != 0) && (MP_MORE_DATA != mp_ioctl.mp_errno)) {
+
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+
+ free(objList);
+
+ if (ENOTSUP == ioctlStatus) {
+ mpStatus = MP_STATUS_UNSUPPORTED;
+ } else if (0 == mp_ioctl.mp_errno) {
+ mpStatus = MP_STATUS_FAILED;
+ } else {
+ mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno);
+ }
+
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ " - error exit, returning %d to caller.", mpStatus);
+
+ return (mpStatus);
+ }
+
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ " - mp_ioctl.mp_alen : %d",
+ mp_ioctl.mp_alen);
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ " - sizeof (uint64_t): %d",
+ sizeof (uint64_t));
+
+ numOBJ = mp_ioctl.mp_alen / sizeof (uint64_t);
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "Length of list: %d", numOBJ);
+
+ if (numOBJ < 1) {
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "driver returned empty list.");
+
+ free(objList);
+
+ *ppList = createOidList(1);
+ if (NULL == *ppList) {
+ log(LOG_INFO,
+ "getAssociatedTPGOidList()",
+ "no memory for MP_OID_LIST");
+ log(LOG_INFO,
+ "getAssociatedTPGOidList()",
+ " - error exit");
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ return (MP_STATUS_SUCCESS);
+ }
+
+ if (mp_ioctl.mp_alen > DEFAULT_BUFFER_SIZE_TPG) {
+
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "buffer size too small, need : %d",
+ mp_ioctl.mp_alen);
+
+ free(objList);
+
+ objList = (uint64_t *)calloc(1, numOBJ * sizeof (uint64_t));
+ if (NULL == objList) {
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "no memory for objList(2)");
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ " - error exit");
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+
+ mp_ioctl.mp_cmd = MP_GET_TPG_LIST;
+ mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber;
+ mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber);
+ mp_ioctl.mp_obuf = (caddr_t)objList;
+ mp_ioctl.mp_olen = numOBJ * sizeof (uint64_t);
+ mp_ioctl.mp_xfer = MP_XFER_READ;
+
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "mp_ioctl.mp_cmd (MP_GET_TPG_LIST) : %d",
+ mp_ioctl.mp_cmd);
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "mp_ioctl.mp_obuf: %x", mp_ioctl.mp_obuf);
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "mp_ioctl.mp_olen: %d", mp_ioctl.mp_olen);
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "mp_ioctl.mp_xfer: %d (MP_XFER_READ)",
+ mp_ioctl.mp_xfer);
+
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "ioctl call returned ioctlStatus: %d",
+ ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if (ioctlStatus != 0) {
+
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+
+ free(objList);
+
+ if (ENOTSUP == ioctlStatus) {
+ mpStatus = MP_STATUS_UNSUPPORTED;
+ } else if (0 == mp_ioctl.mp_errno) {
+ mpStatus = MP_STATUS_FAILED;
+ } else {
+ mpStatus =
+ getStatus4ErrorCode(mp_ioctl.mp_errno);
+ }
+
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ " - error exit");
+
+ return (mpStatus);
+ }
+ }
+
+
+ *ppList = createOidList(numOBJ);
+ if (NULL == *ppList) {
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "no memory for *ppList");
+ free(objList);
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ " - error exit");
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ (*ppList)->oidCount = numOBJ;
+
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "(*ppList)->oidCount = %d",
+ (*ppList)->oidCount);
+
+ for (i = 0; i < numOBJ; i++) {
+ (*ppList)->oids[i].objectType =
+ MP_OBJECT_TYPE_TARGET_PORT_GROUP;
+ (*ppList)->oids[i].ownerId = g_pluginOwnerID;
+ (*ppList)->oids[i].objectSequenceNumber = objList[i];
+
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "(*ppList)->oids[%d].objectType = %d",
+ i, (*ppList)->oids[i].objectType);
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "(*ppList)->oids[%d].ownerId = %d",
+ i, (*ppList)->oids[i].ownerId);
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ "(*ppList)->oids[%d].objectSequenceNumber = %llx",
+ i, (*ppList)->oids[i].objectSequenceNumber);
+ }
+
+ free(objList);
+
+
+ log(LOG_INFO, "getAssociatedTPGOidList()",
+ " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetDeviceProductOidListPlugin.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetDeviceProductOidListPlugin.c
new file mode 100644
index 0000000000..f01cda2535
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetDeviceProductOidListPlugin.c
@@ -0,0 +1,278 @@
+/*
+ * 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.
+ */
+
+#include <syslog.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stropts.h>
+
+#include "mp_utils.h"
+
+
+/*
+ * Called by the common layer to request a list of Device Products
+ */
+
+MP_STATUS
+MP_GetDeviceProductOidListPlugin(MP_OID_LIST **ppList)
+{
+ mp_iocdata_t mp_ioctl;
+
+ uint64_t *objList = NULL;
+
+ int numOBJ = 0;
+ int i = 0;
+ int ioctlStatus = 0;
+
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()", " - enter");
+
+ if (g_scsi_vhci_fd < 0) {
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ "invalid driver file handle");
+ return (MP_STATUS_FAILED);
+ }
+
+
+ objList = (uint64_t *)calloc(1, DEFAULT_BUFFER_SIZE_DEV_PROD);
+ if (NULL == objList) {
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ "no memory for objList(1)");
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ " - error exit");
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+
+ mp_ioctl.mp_cmd = MP_GET_DEV_PROD_LIST;
+ mp_ioctl.mp_obuf = (caddr_t)objList;
+ mp_ioctl.mp_olen = DEFAULT_BUFFER_SIZE_DEV_PROD;
+ mp_ioctl.mp_xfer = MP_XFER_READ;
+
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ "mp_ioctl.mp_cmd : %d (MP_GET_DEV_PROD_LIST)",
+ mp_ioctl.mp_cmd);
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ "mp_ioctl.mp_obuf: %x",
+ mp_ioctl.mp_obuf);
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ "mp_ioctl.mp_olen: %d",
+ mp_ioctl.mp_olen);
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ "mp_ioctl.mp_xfer: %d (MP_XFER_READ)",
+ mp_ioctl.mp_xfer);
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ "ioctl call returned ioctlStatus: %d",
+ ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if ((ioctlStatus != 0) && (MP_MORE_DATA != mp_ioctl.mp_errno)) {
+
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+
+ free(objList);
+
+ if (ENOTSUP == ioctlStatus) {
+ mpStatus = MP_STATUS_UNSUPPORTED;
+ } else if (0 == mp_ioctl.mp_errno) {
+ mpStatus = MP_STATUS_FAILED;
+ } else {
+ mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno);
+ }
+
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ " - error exit");
+
+ return (mpStatus);
+ }
+
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ " - mp_ioctl.mp_alen : %d",
+ mp_ioctl.mp_alen);
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ " - sizeof (uint64_t): %d",
+ sizeof (uint64_t));
+
+ numOBJ = mp_ioctl.mp_alen / sizeof (uint64_t);
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ "Length of list: %d", numOBJ);
+
+ if (numOBJ < 1) {
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ "driver returned empty list.");
+
+ free(objList);
+
+ *ppList = createOidList(1);
+ if (NULL == *ppList) {
+ log(LOG_INFO,
+ "MP_GetDeviceProductOidListPlugin()",
+ "no memory for MP_OID_LIST");
+ log(LOG_INFO,
+ "MP_GetDeviceProductOidListPlugin()",
+ " - error exit");
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ return (MP_STATUS_SUCCESS);
+ }
+
+
+ if (mp_ioctl.mp_alen > DEFAULT_BUFFER_SIZE_DEV_PROD) {
+
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ "buffer size too small, need : %d",
+ mp_ioctl.mp_alen);
+
+ free(objList);
+
+ objList = (uint64_t *)calloc(1, numOBJ * sizeof (uint64_t));
+ if (NULL == objList) {
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ "no memory for objList(2)");
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ " - error exit");
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+
+ mp_ioctl.mp_cmd = MP_GET_DEV_PROD_LIST;
+ mp_ioctl.mp_obuf = (caddr_t)objList;
+ mp_ioctl.mp_olen = numOBJ * sizeof (uint64_t);
+ mp_ioctl.mp_xfer = MP_XFER_READ;
+
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ "mp_ioctl.mp_cmd : %d (MP_GET_DEV_PROD_LIST)",
+ mp_ioctl.mp_cmd);
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ "mp_ioctl.mp_obuf: %x",
+ mp_ioctl.mp_obuf);
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ "mp_ioctl.mp_olen: %d",
+ mp_ioctl.mp_olen);
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ "mp_ioctl.mp_xfer: %d (MP_XFER_READ)",
+ mp_ioctl.mp_xfer);
+
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ "ioctl call returned ioctlStatus: %d",
+ ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if (ioctlStatus != 0) {
+
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+
+ free(objList);
+
+ if (ENOTSUP == ioctlStatus) {
+ mpStatus = MP_STATUS_UNSUPPORTED;
+ } else if (0 == mp_ioctl.mp_errno) {
+ mpStatus = MP_STATUS_FAILED;
+ } else {
+ mpStatus =
+ getStatus4ErrorCode(mp_ioctl.mp_errno);
+ }
+
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ " - error exit");
+
+ return (mpStatus);
+ }
+ }
+
+
+ *ppList = createOidList(numOBJ);
+ if (NULL == *ppList) {
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ "no memory for *ppList");
+ free(objList);
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ " - error exit");
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ (*ppList)->oidCount = numOBJ;
+
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ "(*ppList)->oidCount = %d",
+ (*ppList)->oidCount);
+
+ for (i = 0; i < numOBJ; i++) {
+ (*ppList)->oids[i].objectType = MP_OBJECT_TYPE_DEVICE_PRODUCT;
+ (*ppList)->oids[i].ownerId = g_pluginOwnerID;
+ (*ppList)->oids[i].objectSequenceNumber = objList[i];
+
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ "(*ppList)->oids[%d].objectType = %d",
+ i, (*ppList)->oids[i].objectType);
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ "(*ppList)->oids[%d].ownerId = %d",
+ i, (*ppList)->oids[i].ownerId);
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ "(*ppList)->oids[%d].objectSequenceNumber = %llx",
+ i, (*ppList)->oids[i].objectSequenceNumber);
+ }
+
+ free(objList);
+
+
+ log(LOG_INFO, "MP_GetDeviceProductOidListPlugin()",
+ " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetDeviceProductProperties.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetDeviceProductProperties.c
new file mode 100644
index 0000000000..838d6f2360
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetDeviceProductProperties.c
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ */
+
+#include "mp_utils.h"
+
+#include <string.h>
+#include <syslog.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stropts.h>
+
+
+/*
+ * Called by the common layer to request properties for a Device Product
+ */
+
+MP_STATUS
+MP_GetDeviceProductProperties(MP_OID oid, MP_DEVICE_PRODUCT_PROPERTIES *pProps)
+{
+ mp_iocdata_t mp_ioctl;
+ mp_dev_prod_prop_t devProdInfo;
+
+ int ioctlStatus = 0;
+
+ int vendorLength = 0;
+ int productLength = 0;
+ int revisionLength = 0;
+
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+
+ log(LOG_INFO, "MP_GetDeviceProductProperties()", " - enter");
+
+ log(LOG_INFO, "MP_GetDeviceProductProperties()",
+ "oid.objectSequenceNumber = %llx",
+ oid.objectSequenceNumber);
+
+ if (g_scsi_vhci_fd < 0) {
+ log(LOG_INFO, "MP_GetDeviceProductProperties()",
+ "invalid driver file handle");
+ log(LOG_INFO, "MP_GetDeviceProductProperties",
+ " - error exit");
+ return (MP_STATUS_FAILED);
+ }
+
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+ (void) memset(&devProdInfo, 0, sizeof (mp_dev_prod_prop_t));
+
+ mp_ioctl.mp_cmd = MP_GET_DEV_PROD_PROP;
+ mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber;
+ mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber);
+ mp_ioctl.mp_obuf = (caddr_t)&devProdInfo;
+ mp_ioctl.mp_olen = sizeof (mp_dev_prod_prop_t);
+ mp_ioctl.mp_xfer = MP_XFER_READ;
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+
+ log(LOG_INFO, "MP_GetDeviceProductProperties()",
+ " IOCTL call returned: %d", ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if (ioctlStatus != 0) {
+ log(LOG_INFO, "MP_GetDeviceProductProperties()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO, "MP_GetDeviceProductProperties()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO, "MP_GetDeviceProductProperties()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+ if (ENOTSUP == ioctlStatus) {
+ mpStatus = MP_STATUS_UNSUPPORTED;
+ } else if (0 == mp_ioctl.mp_errno) {
+ mpStatus = MP_STATUS_FAILED;
+ } else {
+ mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno);
+ }
+
+ log(LOG_INFO, "MP_GetDeviceProductProperties()",
+ " - error exit");
+
+ return (mpStatus);
+ }
+
+ (void) memset(pProps, 0, sizeof (MP_DEVICE_PRODUCT_PROPERTIES));
+
+
+ vendorLength = sizeof (pProps->vendor);
+ productLength = sizeof (pProps->product);
+ revisionLength = sizeof (pProps->revision);
+
+
+ (void) strncpy(pProps->vendor,
+ devProdInfo.prodInfo.vendor,
+ vendorLength);
+
+ (void) strncpy(pProps->product,
+ devProdInfo.prodInfo.product,
+ productLength);
+
+ (void) strncpy(pProps->revision,
+ devProdInfo.prodInfo.revision,
+ revisionLength);
+
+ pProps->supportedLoadBalanceTypes =
+ devProdInfo.supportedLoadBalanceTypes;
+
+
+ log(LOG_INFO, "MP_GetDeviceProductProperties()",
+ " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetInitiatorPortOidListPlugin.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetInitiatorPortOidListPlugin.c
new file mode 100644
index 0000000000..310de4766c
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetInitiatorPortOidListPlugin.c
@@ -0,0 +1,193 @@
+/*
+ * 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.
+ */
+
+#include <syslog.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stropts.h>
+
+#include "mp_utils.h"
+
+#include <libdevinfo.h>
+
+
+static int getOidList(di_node_t root_node, MP_OID_LIST *pOidList)
+{
+ int numNodes = 0;
+ int instNum = 0;
+ int majorNum = 0;
+
+ di_node_t vh_node = DI_NODE_NIL;
+ di_node_t ph_node = DI_NODE_NIL;
+
+ MP_UINT64 osn = 0;
+
+ int haveList = (NULL != pOidList);
+
+
+ log(LOG_INFO, "getOidList()", " - enter");
+
+ vh_node = di_vhci_first_node(root_node);
+
+ while (DI_NODE_NIL != vh_node) {
+ if ((di_driver_name(vh_node) != NULL) &&
+ (strncmp(di_driver_name(vh_node), "scsi_vhci", 9) == 0)) {
+ ph_node = di_phci_first_node(vh_node);
+ while (DI_NODE_NIL != ph_node) {
+ if (haveList) {
+
+ instNum = di_instance(ph_node);
+ majorNum = di_driver_major(ph_node);
+
+ log(LOG_INFO, "getOidList()",
+ "instNum = %d",
+ instNum);
+
+ log(LOG_INFO, "getOidList()",
+ "majorNum = %d",
+ majorNum);
+
+ if (numNodes < pOidList->oidCount) {
+
+ osn = 0;
+
+ osn =
+ MP_STORE_INST_TO_ID(instNum,
+ osn);
+
+ osn =
+ MP_STORE_MAJOR_TO_ID(majorNum,
+ osn);
+
+ pOidList->oids[numNodes]
+ .objectSequenceNumber =
+ osn;
+
+ pOidList->oids[numNodes].
+ objectType =
+ MP_OBJECT_TYPE_INITIATOR_PORT;
+
+ pOidList->oids[numNodes].
+ ownerId =
+ g_pluginOwnerID;
+ }
+ }
+
+ ++numNodes;
+ ph_node = di_phci_next_node(ph_node);
+ }
+
+ }
+ vh_node = di_vhci_next_node(vh_node);
+ }
+
+ log(LOG_INFO,
+ "getOidList()",
+ " - numNodes: %d",
+ numNodes);
+
+
+ log(LOG_INFO, "getOidList()", " - exit");
+
+ return (numNodes);
+}
+
+
+
+MP_STATUS
+MP_GetInitiatorPortOidListPlugin(MP_OID_LIST **ppList)
+{
+ di_node_t root_node = DI_NODE_NIL;
+
+ int i = 0;
+ int numNodes = 0;
+
+
+
+ log(LOG_INFO, "MP_GetInitiatorPortOidListPlugin()", " - enter");
+
+
+ root_node = di_init("/", DINFOCACHE);
+ if (DI_NODE_NIL == root_node) {
+ log(LOG_INFO, "MP_GetInitiatorPortOidListPlugin()",
+ " - di_init() failed");
+
+ return (MP_STATUS_FAILED);
+ }
+
+ numNodes = getOidList(root_node, NULL);
+
+ if (numNodes < 1) {
+
+ *ppList = createOidList(1);
+
+ if (NULL == *ppList) {
+ log(LOG_INFO, "MP_GetInitiatorPortOidListPlugin()",
+ "no memory for *ppList");
+ log(LOG_INFO, "MP_GetInitiatorPortOidListPlugin()",
+ " - error exit");
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ log(LOG_INFO, "MP_GetInitiatorPortOidListPlugin()",
+ " - returning empty list.");
+
+ return (MP_STATUS_SUCCESS);
+ }
+
+ *ppList = createOidList(numNodes);
+ if (NULL == *ppList) {
+ log(LOG_INFO, "MP_GetInitiatorPortOidListPlugin()",
+ "no memory for *ppList");
+ log(LOG_INFO, "MP_GetInitiatorPortOidListPlugin()",
+ " - error exit");
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ (*ppList)->oidCount = numNodes;
+
+ numNodes = getOidList(root_node, *ppList);
+
+ for (i = 0; i < (*ppList)->oidCount; i++) {
+
+ log(LOG_INFO, "MP_GetInitiatorPortOidListPlugin()",
+ "(*ppList)->oids[%d].objectType = %d",
+ i, (*ppList)->oids[i].objectType);
+ log(LOG_INFO, "MP_GetInitiatorPortOidListPlugin()",
+ "(*ppList)->oids[%d].ownerId = %d",
+ i, (*ppList)->oids[i].ownerId);
+ log(LOG_INFO, "MP_GetInitiatorPortOidListPlugin()",
+ "(*ppList)->oids[%d].objectSequenceNumber = %llx",
+ i, (*ppList)->oids[i].objectSequenceNumber);
+ }
+
+
+ di_fini(root_node);
+
+
+ log(LOG_INFO, "MP_GetInitiatorPortOidListPlugin()", " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetInitiatorPortProperties.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetInitiatorPortProperties.c
new file mode 100644
index 0000000000..1a81b0a643
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetInitiatorPortProperties.c
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+
+#include "mp_utils.h"
+
+#include <string.h>
+#include <syslog.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stropts.h>
+
+
+
+MP_STATUS
+MP_GetInitiatorPortProperties(MP_OID oid, MP_INITIATOR_PORT_PROPERTIES *pProps)
+{
+ mp_iocdata_t mp_ioctl;
+ mp_init_port_prop_t initPortInfo;
+
+ int ioctlStatus = 0;
+
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+
+ log(LOG_INFO, "MP_GetInitiatorPortProperties()", " - enter");
+
+
+ log(LOG_INFO, "MP_GetInitiatorPortProperties()",
+ "oid.objectSequenceNumber = %llx",
+ oid.objectSequenceNumber);
+
+ if (g_scsi_vhci_fd < 0) {
+ log(LOG_INFO, "MP_GetInitiatorPortProperties()",
+ "invalid driver file handle");
+ log(LOG_INFO, "MP_GetInitiatorPortProperties()",
+ " - error exit");
+ return (MP_STATUS_FAILED);
+ }
+
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+ (void) memset(&initPortInfo, 0, sizeof (mp_init_port_prop_t));
+
+ mp_ioctl.mp_cmd = MP_GET_INIT_PORT_PROP;
+ mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber;
+ mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber);
+ mp_ioctl.mp_obuf = (caddr_t)&initPortInfo;
+ mp_ioctl.mp_olen = sizeof (mp_init_port_prop_t);
+ mp_ioctl.mp_xfer = MP_XFER_READ;
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+
+ log(LOG_INFO, "MP_GetInitiatorPortProperties()",
+ " IOCTL call returned: %d", ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if (ioctlStatus != 0) {
+ log(LOG_INFO, "MP_GetInitiatorPortProperties()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO, "MP_GetInitiatorPortProperties()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO, "MP_GetInitiatorPortProperties()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+ if (ENOTSUP == ioctlStatus) {
+ mpStatus = MP_STATUS_UNSUPPORTED;
+ } else if (0 == mp_ioctl.mp_errno) {
+ mpStatus = MP_STATUS_FAILED;
+ } else {
+ mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno);
+ }
+
+ log(LOG_INFO, "MP_GetInitiatorPortProperties()",
+ " - error exit");
+
+ return (mpStatus);
+ }
+
+ (void) memset(pProps, 0, sizeof (MP_INITIATOR_PORT_PROPERTIES));
+
+ (void) strncpy(pProps->osDeviceFile,
+ initPortInfo.osDeviceFile,
+ sizeof (pProps->osDeviceFile));
+ (void) strncpy(pProps->portID,
+ initPortInfo.portID,
+ sizeof (pProps->portID));
+ pProps->portType =
+ initPortInfo.portType;
+
+
+ /* where does "pProps->osFriendlyName" (MP_WCHAR) come from ??? */
+
+
+ log(LOG_INFO, "MP_GetInitiatorPortProperties()", " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetMPLogicalUnitProperties.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetMPLogicalUnitProperties.c
new file mode 100644
index 0000000000..94fe7c9f72
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetMPLogicalUnitProperties.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.
+ */
+
+#include <string.h>
+#include <syslog.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stropts.h>
+
+#include <libdevinfo.h>
+
+#include "mp_utils.h"
+
+
+typedef struct walk_devlink {
+ char *path;
+ size_t len;
+ char **linkpp;
+} walk_devlink_t;
+
+
+
+static int
+get_devlink(di_devlink_t devlink, void *arg) {
+
+ walk_devlink_t *warg = (walk_devlink_t *)arg;
+
+
+ log(LOG_INFO, "get_devlink()", " - enter");
+
+
+ *(warg->linkpp) = strdup(di_devlink_path(devlink));
+
+
+ log(LOG_INFO, "get_devlink()", " - exit");
+
+ return (DI_WALK_TERMINATE);
+}
+
+
+char
+*getDeviceFileName(MP_UINT64 instanceNum)
+{
+ char *deviceFileName = NULL;
+
+ di_node_t root_node = DI_NODE_NIL;
+ di_node_t cur_node = DI_NODE_NIL;
+
+ MP_UINT64 nodeInstance = 0;
+
+ char *pathName = NULL;
+ char *minorName = "c,raw";
+ char *devLink = NULL;
+
+ char fullName[512];
+
+ walk_devlink_t warg;
+ di_devlink_handle_t dlHandle = NULL;
+
+ int diStatus = 0;
+
+
+ log(LOG_INFO, "getDeviceFileName()", " - enter");
+
+ log(LOG_INFO, "getDeviceFileName()",
+ " - instanceNum: %llx",
+ instanceNum);
+
+ root_node = di_init("/", DINFOCACHE);
+ if (DI_NODE_NIL == root_node) {
+ log(LOG_INFO, "MP_GetMultipathLusPlugin()",
+ " - $ERROR, di_init() failed");
+
+ return (NULL);
+ }
+
+
+ cur_node = di_drv_first_node("scsi_vhci", root_node);
+ if (DI_NODE_NIL == cur_node) {
+ log(LOG_INFO, "getDeviceFileName()",
+ " - $ERROR, di_drv_first_node() failed");
+
+ di_fini(root_node);
+
+ return (NULL);
+ }
+
+
+ cur_node = di_child_node(cur_node);
+
+ while (DI_NODE_NIL != cur_node) {
+
+ nodeInstance =
+ (MP_UINT64)di_instance(cur_node);
+
+ if (nodeInstance == instanceNum) {
+
+ log(LOG_INFO, "getDeviceFileName()",
+ " - found node.");
+
+ break;
+ }
+
+ cur_node = di_sibling_node(cur_node);
+ }
+
+ if (DI_NODE_NIL != cur_node) {
+
+ dlHandle = di_devlink_init(NULL, 0);
+ if (NULL == dlHandle) {
+ log(LOG_INFO, "getDeviceFileName()",
+ " - $ERROR, di_devlink_init() failed.");
+
+ di_fini(root_node);
+
+ return (NULL);
+ }
+
+ pathName = di_devfs_path(cur_node);
+
+ (void) snprintf(fullName, 511, "%s:%s", pathName, minorName);
+
+ log(LOG_INFO, "getDeviceFileName()",
+ " - fullName: {%s]", fullName);
+
+ (void) memset(&warg, 0, sizeof (walk_devlink_t));
+
+ devLink = NULL;
+ warg.linkpp = &devLink;
+
+ diStatus = di_devlink_walk(dlHandle,
+ NULL,
+ fullName,
+ DI_PRIMARY_LINK,
+ (void *)&warg,
+ get_devlink);
+
+ if (diStatus != 0) {
+
+ log(LOG_INFO, "getDeviceFileName()",
+ "diStatus: %d", diStatus);
+
+ if (diStatus < 0) {
+ diStatus = errno;
+ }
+
+ log(LOG_INFO, "getDeviceFileName()",
+ "diStatus: %d", diStatus);
+
+ log(LOG_INFO, "getDeviceFileName()",
+ "strerror(diStatus): %s", strerror(diStatus));
+ }
+
+ if (NULL != devLink) {
+
+ deviceFileName =
+ (char *)calloc(1, strlen(devLink) + 1);
+
+ (void) strncpy(deviceFileName, devLink,
+ strlen(devLink));
+
+ } else {
+
+ log(LOG_INFO, "getDeviceFileName()",
+ " - $ERROR, devLink is NULL.");
+
+ deviceFileName =
+ (char *)calloc(1, 256);
+
+ (void) strncpy(deviceFileName, pathName, 255);
+ }
+
+ di_devfs_path_free(pathName);
+
+ (void) di_devlink_fini(&dlHandle);
+
+ }
+
+
+ di_fini(root_node);
+
+
+ log(LOG_INFO, "getDeviceFileName()", " - exit");
+
+ return (deviceFileName);
+}
+
+
+
+MP_STATUS
+MP_GetMPLogicalUnitProperties(MP_OID oid,
+ MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES *pProps)
+{
+ mp_iocdata_t mp_ioctl;
+ mp_logical_unit_prop_t luInfo;
+
+ MP_OID overridePathOID;
+
+ int ioctlStatus = 0;
+
+ int vendorLength = 0;
+ int productLength = 0;
+ int revisionLength = 0;
+
+ char *deviceFileName = NULL;
+
+
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+
+ log(LOG_INFO, "MP_GetMPLogicalUnitProperties()", " - enter");
+
+
+ log(LOG_INFO, "MP_GetMPLogicalUnitProperties()",
+ "oid.objectSequenceNumber = %llx",
+ oid.objectSequenceNumber);
+
+ if (g_scsi_vhci_fd < 0) {
+ log(LOG_INFO, "MP_GetMPLogicalUnitProperties()",
+ "invalid driver file handle");
+ log(LOG_INFO, "MP_GetMPLogicalUnitProperties()",
+ " - error exit");
+ return (MP_STATUS_FAILED);
+ }
+
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+ (void) memset(&luInfo, 0, sizeof (mp_logical_unit_prop_t));
+
+ mp_ioctl.mp_cmd = MP_GET_LU_PROP;
+ mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber;
+ mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber);
+ mp_ioctl.mp_obuf = (caddr_t)&luInfo;
+ mp_ioctl.mp_olen = sizeof (mp_logical_unit_prop_t);
+ mp_ioctl.mp_xfer = MP_XFER_READ;
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+
+ log(LOG_INFO, "MP_GetMPLogicalUnitProperties()",
+ " IOCTL call returned: %d", ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if (ioctlStatus != 0) {
+ log(LOG_INFO, "MP_GetMPLogicalUnitProperties()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO, "MP_GetMPLogicalUnitProperties()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO, "MP_GetMPLogicalUnitProperties()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+ if (ENOTSUP == ioctlStatus) {
+ mpStatus = MP_STATUS_UNSUPPORTED;
+ } else if (0 == mp_ioctl.mp_errno) {
+ mpStatus = MP_STATUS_FAILED;
+ } else {
+ mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno);
+ }
+
+ log(LOG_INFO, "MP_GetMPLogicalUnitProperties()",
+ " - error exit");
+
+ return (mpStatus);
+ }
+
+ (void) memset(pProps, 0, sizeof (MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES));
+
+ pProps->asymmetric = luInfo.asymmetric;
+ pProps->autoFailbackEnabled = luInfo.autoFailbackEnabled;
+ pProps->autoProbingEnabled = luInfo.autoProbingEnabled;
+ pProps->currentFailbackPollingRate = luInfo.currentFailBackPollingRate;
+ pProps->currentLoadBalanceType = luInfo.currentLoadBalanceType;
+ pProps->currentProbingPollingRate = luInfo.currentProbingPollingRate;
+
+
+ deviceFileName = getDeviceFileName(oid.objectSequenceNumber);
+
+ if (NULL != deviceFileName) {
+
+ log(LOG_INFO, "MP_GetMPLogicalUnitProperties()",
+ "deviceFileName: %s",
+ deviceFileName);
+
+ (void) strncpy(pProps->deviceFileName,
+ deviceFileName,
+ sizeof (pProps->deviceFileName) - 1);
+
+ free(deviceFileName);
+ }
+
+ pProps->failbackPollingRateMax = luInfo.failbackPollingRateMax;
+ pProps->logicalUnitGroupID = luInfo.luGroupID;
+
+ (void) strncpy(pProps->name, luInfo.name, sizeof (pProps->name) - 1);
+
+ pProps->nameType = luInfo.nameType;
+
+ overridePathOID.objectSequenceNumber = luInfo.overridePathID;
+ overridePathOID.objectType = MP_OBJECT_TYPE_PATH_LU;
+ overridePathOID.ownerId = g_pluginOwnerID;
+ (void) memcpy(&pProps->overridePath, &overridePathOID, sizeof (MP_OID));
+
+ pProps->probingPollingRateMax = luInfo.probingPollingRateMax;
+
+
+ vendorLength = sizeof (pProps->vendor);
+ productLength = sizeof (pProps->product);
+ revisionLength = sizeof (pProps->revision);
+
+ (void) strncpy(pProps->vendor,
+ luInfo.prodInfo.vendor,
+ vendorLength);
+
+ (void) strncpy(pProps->product,
+ luInfo.prodInfo.product,
+ productLength);
+
+ (void) strncpy(pProps->revision,
+ luInfo.prodInfo.revision,
+ revisionLength);
+
+ log(LOG_INFO, "MP_GetMPLogicalUnitProperties()", " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetMPLuOidListFromTPG.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetMPLuOidListFromTPG.c
new file mode 100644
index 0000000000..bb05513cb3
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetMPLuOidListFromTPG.c
@@ -0,0 +1,508 @@
+/*
+ * 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.
+ */
+
+#include <errno.h>
+#include <unistd.h>
+#include <stropts.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <libdevinfo.h>
+#include <sys/stat.h>
+
+#include "mp_utils.h"
+
+
+/*
+ * The plugin library will call MP_CMD ioctl with
+ * MP_GET_TARGET_PORT_LIST_FOR_TPG subcommand.
+ * For each target port, the plugin will get the target port name property.
+ *
+ * A scsi_vhci device with pathinfo containing matching target port name
+ * may potentially be associated with the given TPG.
+ * The plugin library will check the TPG list for qualifying scsi_vhci
+ * devices and find a matching TPG id.
+ *
+ * An rfe was filed against MDI to
+ * refresh DINFOCACHE snapshot for pathinfo update.
+ */
+
+
+
+
+
+/*
+ * Returns MP_TRUE if the ID found in the dev info snapshot matches the ID
+ * provided by the schi_vhci driver.
+ */
+
+static int checkTPGList(MP_UINT32 tpgID, int inst_num)
+{
+ int tpg = 0;
+ int status = MP_FALSE;
+
+ MP_OID luOID;
+
+ MP_OID_LIST *ppList = NULL;
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+ MP_TARGET_PORT_GROUP_PROPERTIES tpgProps;
+
+
+
+ log(LOG_INFO, "checkTPGList()", " - enter");
+
+
+ luOID.objectSequenceNumber = (MP_UINT64)inst_num;
+ luOID.objectType = MP_OBJECT_TYPE_MULTIPATH_LU;
+ luOID.ownerId = g_pluginOwnerID;
+
+ mpStatus = getAssociatedTPGOidList(luOID, &ppList);
+ if (MP_STATUS_SUCCESS != mpStatus) {
+
+ log(LOG_INFO, "checkTPGList()",
+ " - getAssociatedTPGOidList() failed: %d",
+ mpStatus);
+
+ return (MP_FALSE);
+ }
+
+ for (tpg = 0; tpg < ppList->oidCount; tpg++) {
+
+ mpStatus =
+ getTargetPortGroupProperties(ppList->oids[tpg],
+ &tpgProps);
+
+ if (MP_STATUS_SUCCESS != mpStatus) {
+
+ log(LOG_INFO, "checkTPGList()",
+ " - getTargetPortGroupProperties()"
+ " failed: %d",
+ mpStatus);
+
+ return (MP_FALSE);
+ }
+
+ if (tpgProps.tpgID == tpgID) {
+
+ status = MP_TRUE;
+
+ log(LOG_INFO,
+ "checkTPGList()",
+ " - found a match");
+
+ break;
+ }
+ }
+
+ free(ppList);
+
+
+ log(LOG_INFO, "checkTPGList()", " - exit");
+
+ return (status);
+}
+
+
+
+/*
+ * Returns the number of matches found. If pOidList is not NULL, then
+ * populate it. A return values of -1 indicates and error, zerom menas
+ * no match is found.
+ */
+
+static int getOidList(di_node_t root_node, int tpgID,
+ MP_OID_LIST *tpList, MP_OID_LIST *pOidList)
+{
+ di_node_t sv_node = DI_NODE_NIL;
+ di_node_t child_node = DI_NODE_NIL;
+ di_path_t path = DI_PATH_NIL;
+
+ int numNodes = 0;
+ int tp = 0;
+ int ioctlStatus = 0;
+ int match = 0;
+ int status = -1;
+ int sv_child_inst = 0;
+ int hasTpgMatch = MP_FALSE;
+
+ struct stat buffer;
+
+ char *pathName = NULL;
+ char *minorName = "c";
+
+ char fullName[512];
+
+ char *portName = NULL;
+
+ mp_iocdata_t mp_ioctl;
+
+ mp_target_port_prop_t tpInfo;
+
+ MP_UINT64 tpOSN = 0;
+
+ int haveList = (NULL != pOidList);
+
+
+ log(LOG_INFO, "getOidList()", " - enter");
+
+
+ /* Look through the list of target ports for a portName that matches */
+ for (tp = 0; tp < tpList->oidCount; tp++) {
+
+ tpOSN = tpList->oids[tp].objectSequenceNumber;
+
+ log(LOG_INFO, "getOidList()",
+ "tpOSN = %llx",
+ tpOSN);
+
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+ (void) memset(&tpInfo, 0, sizeof (mp_target_port_prop_t));
+
+ mp_ioctl.mp_cmd = MP_GET_TARGET_PORT_PROP;
+ mp_ioctl.mp_ibuf = (caddr_t)&tpOSN;
+ mp_ioctl.mp_ilen = sizeof (tpOSN);
+ mp_ioctl.mp_obuf = (caddr_t)&tpInfo;
+ mp_ioctl.mp_olen = sizeof (mp_target_port_prop_t);
+ mp_ioctl.mp_xfer = MP_XFER_READ;
+
+ log(LOG_INFO, "getOidList()",
+ "mp_ioctl.mp_cmd (MP_GET_TARGET_PORT_PROP) : %d",
+ mp_ioctl.mp_cmd);
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+
+ log(LOG_INFO, "getOidList()",
+ " IOCTL call returned: %d", ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if (ioctlStatus != 0) {
+ log(LOG_INFO, "getOidList()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO, "getOidList()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO, "getOidList()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+ log(LOG_INFO, "getOidList()",
+ " - error exit");
+
+ return (-1);
+ }
+
+ sv_node = di_drv_first_node("scsi_vhci", root_node);
+ if (DI_NODE_NIL == sv_node) {
+ log(LOG_INFO, "getOidList()",
+ " - di_drv_first_node() failed");
+
+ return (-1);
+ }
+
+ child_node = di_child_node(sv_node);
+
+ while (DI_NODE_NIL != child_node) {
+
+ path = di_path_next(child_node, path);
+
+ match = 0;
+
+ while (DI_PATH_NIL != path) {
+
+
+ (void) di_path_prop_lookup_strings(path,
+ "target-port",
+ &portName);
+
+ if (NULL != portName) {
+
+ if (0 == strncmp(portName,
+ tpInfo.portName,
+ strlen(tpInfo.portName))) {
+
+ match = 1;
+
+ break;
+ }
+ }
+
+ path = di_path_next(child_node, path);
+ }
+
+ if (match) {
+
+ log(LOG_INFO, "getOidList()",
+ " - got a match");
+
+ pathName = di_devfs_path(child_node);
+
+ (void) snprintf(fullName, 511, "/devices%s:%s",
+ pathName, minorName);
+
+ di_devfs_path_free(pathName);
+
+ status = stat(fullName, &buffer);
+ if (status < 0) {
+
+ log(LOG_INFO,
+ "getOidList()",
+ " - stat() call failed: %d",
+ status);
+
+ log(LOG_INFO,
+ "getOidList()",
+ " - errno: [%d].", errno);
+
+ log(LOG_INFO,
+ "getOidList()",
+ " - strerror(errno): [%s].",
+ strerror(errno));
+
+ log(LOG_INFO,
+ "getOidList()",
+ " - error exit.");
+
+ return (-1);
+ }
+
+ sv_child_inst = di_instance(child_node);
+
+ /*
+ * OK, found an portName that matches, let's
+ * to see if the IDs match.
+ */
+ hasTpgMatch =
+ checkTPGList(tpgID,
+ sv_child_inst);
+
+ if (MP_TRUE != hasTpgMatch) {
+
+ child_node =
+ di_sibling_node(child_node);
+
+ continue;
+ }
+
+ if (haveList &&
+ (numNodes < pOidList->oidCount)) {
+
+ pOidList->oids[numNodes].
+ objectSequenceNumber =
+ sv_child_inst;
+
+ pOidList->oids[numNodes].objectType =
+ MP_OBJECT_TYPE_MULTIPATH_LU;
+
+ pOidList->oids[numNodes].ownerId =
+ g_pluginOwnerID;
+ }
+
+ ++numNodes;
+ }
+
+ child_node = di_sibling_node(child_node);
+ }
+ }
+
+ log(LOG_INFO,
+ "getOidList()",
+ " - numNodes: %d",
+ numNodes);
+
+
+ log(LOG_INFO, "getOidList()", " - exit");
+
+ return (numNodes);
+}
+
+
+
+/*
+ * Called by the common layer to request a list of multipath logical units
+ * associated with a given target port group.
+ */
+
+MP_STATUS
+MP_GetMPLuOidListFromTPG(MP_OID oid, MP_OID_LIST **ppList)
+{
+
+ di_node_t root_node = DI_NODE_NIL;
+
+ int i = 0;
+ int numNodes = 0;
+
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+ MP_UINT32 sourceTpgID = 0;
+
+ MP_OID_LIST *pOidList = NULL;
+ MP_OID_LIST *tpList = NULL;
+
+ MP_TARGET_PORT_GROUP_PROPERTIES sourceTpgProps;
+
+
+
+ log(LOG_INFO, "MP_GetMPLuOidListFromTPG()", " - enter");
+
+
+
+ log(LOG_INFO, "MP_GetMPLuOidListFromTPG()",
+ "oid.objectSequenceNumber = %llx",
+ oid.objectSequenceNumber);
+
+ mpStatus = getTargetPortGroupProperties(oid, &sourceTpgProps);
+ if (MP_STATUS_SUCCESS != mpStatus) {
+
+ log(LOG_INFO, "MP_GetMPLuOidListFromTPG()",
+ " - getTargetPortGroupProperties() failed: %d",
+ mpStatus);
+
+ return (mpStatus);
+ }
+
+ /* The TPG ID we will use as a serch key */
+ sourceTpgID = sourceTpgProps.tpgID;
+
+ log(LOG_INFO, "MP_GetMPLuOidListFromTPG()",
+ "sourceTpgID = %d",
+ sourceTpgID);
+
+ /* Get a list of target ports for the TPG */
+ mpStatus = getTargetPortOidList(oid, &tpList);
+ if (MP_STATUS_SUCCESS != mpStatus) {
+
+ log(LOG_INFO, "getOidList()",
+ " - getTargetPortOidList() failed: %d",
+ mpStatus);
+
+ return (mpStatus);
+ }
+
+ /* Take a snapshot */
+ root_node = di_init("/", DINFOCACHE);
+ if (DI_NODE_NIL == root_node) {
+ log(LOG_INFO, "MP_GetMPLuOidListFromTPG()",
+ " - di_init() failed");
+
+ free(tpList);
+
+ return (MP_STATUS_FAILED);
+ }
+
+ /* search for the number of multipath logical units that match */
+ numNodes = getOidList(root_node, sourceTpgID, tpList, NULL);
+
+ if (numNodes < 0) {
+
+ log(LOG_INFO,
+ "MP_GetMPLuOidListFromTPG()",
+ " - unable to get OID list.");
+
+ log(LOG_INFO, "MP_GetMPLuOidListFromTPG()",
+ " - error exit");
+
+ free(tpList);
+
+ di_fini(root_node);
+
+ return (MP_STATUS_FAILED);
+ }
+
+ if (0 == numNodes) {
+
+ pOidList = createOidList(1);
+ if (NULL == pOidList) {
+
+ log(LOG_INFO,
+ "MP_GetMPLuOidListFromTPG()",
+ " - unable to create OID list.");
+
+ free(tpList);
+
+ di_fini(root_node);
+
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ pOidList->oids[0].objectType =
+ MP_OBJECT_TYPE_MULTIPATH_LU;
+
+ pOidList->oids[0].ownerId =
+ g_pluginOwnerID;
+
+ *ppList = pOidList;
+
+ log(LOG_INFO, "MP_GetMPLuOidListFromTPG()",
+ " - returning empty list.");
+
+ free(tpList);
+
+ return (MP_STATUS_SUCCESS);
+ }
+
+ *ppList = createOidList(numNodes);
+ if (NULL == *ppList) {
+ log(LOG_INFO, "MP_GetMPLuOidListFromTPG()",
+ "no memory for *ppList");
+ log(LOG_INFO, "MP_GetMPLuOidListFromTPG()",
+ " - error exit");
+
+ free(tpList);
+
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ /* now populate the list */
+
+ (*ppList)->oidCount = numNodes;
+
+ numNodes = getOidList(root_node, sourceTpgID, tpList, *ppList);
+
+ for (i = 0; i < (*ppList)->oidCount; i++) {
+
+ log(LOG_INFO, "MP_GetMPLuOidListFromTPG()",
+ "(*ppList)->oids[%d].objectType = %d",
+ i, (*ppList)->oids[i].objectType);
+ log(LOG_INFO, "MP_GetMPLuOidListFromTPG()",
+ "(*ppList)->oids[%d].ownerId = %d",
+ i, (*ppList)->oids[i].ownerId);
+ log(LOG_INFO, "MP_GetMPLuOidListFromTPG()",
+ "(*ppList)->oids[%d].objectSequenceNumber = %llx",
+ i, (*ppList)->oids[i].objectSequenceNumber);
+ }
+
+ free(tpList);
+
+ di_fini(root_node);
+
+
+ log(LOG_INFO, "MP_GetMPLuOidListFromTPG()", " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetMultipathLusDevProd.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetMultipathLusDevProd.c
new file mode 100644
index 0000000000..a7da4c2e07
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetMultipathLusDevProd.c
@@ -0,0 +1,320 @@
+/*
+ * 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.
+ */
+
+#include <string.h>
+#include <syslog.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stropts.h>
+#include <libdevinfo.h>
+
+#include "mp_utils.h"
+
+
+static int getOidList(di_node_t root_node,
+ MP_OID_LIST *pOidList,
+ char *pProductID,
+ char *pVendorID)
+{
+ int numNodes = 0;
+ int pidSize = 0;
+ int vidSize = 0;
+
+ int haveList = (NULL != pOidList);
+
+ char *pid = NULL;
+ char *vid = NULL;
+
+ di_node_t sv_node = DI_NODE_NIL;
+ di_node_t sv_child_node = DI_NODE_NIL;
+
+ MP_UINT64 nodeInstance = 0;
+
+
+ log(LOG_INFO, "getOidList()", " - enter");
+
+
+ sv_node = di_drv_first_node("scsi_vhci", root_node);
+ if (DI_NODE_NIL == sv_node) {
+ log(LOG_INFO, "getOidList()",
+ " - di_drv_first_node() failed");
+
+ return (-1);
+ }
+
+
+ sv_child_node = di_child_node(sv_node);
+
+ while (DI_NODE_NIL != sv_child_node) {
+
+ (void) di_prop_lookup_strings(DDI_DEV_T_ANY,
+ sv_child_node,
+ "inquiry-product-id",
+ &pid);
+
+ pidSize = strlen(pid);
+
+ (void) di_prop_lookup_strings(DDI_DEV_T_ANY,
+ sv_child_node,
+ "inquiry-vendor-id",
+ &vid);
+
+ vidSize = strlen(vid);
+
+ if ((0 == strncmp(pProductID, pid, pidSize)) &&
+ (0 == strncmp(pVendorID, vid, vidSize))) {
+
+ if (haveList) {
+
+ nodeInstance =
+ (MP_UINT64)
+ di_instance(sv_child_node);
+
+ if (numNodes < pOidList->oidCount) {
+
+ pOidList->oids[numNodes].
+ objectType =
+ MP_OBJECT_TYPE_MULTIPATH_LU;
+
+ pOidList->oids[numNodes].
+ ownerId =
+ g_pluginOwnerID;
+
+ pOidList->oids[numNodes].
+ objectSequenceNumber =
+ nodeInstance;
+ }
+ }
+
+ ++numNodes;
+ }
+
+ sv_child_node = di_sibling_node(sv_child_node);
+ }
+
+
+ log(LOG_INFO,
+ "getOidList()",
+ " - numNodes: %d",
+ numNodes);
+
+
+ log(LOG_INFO, "getOidList()", " - exit");
+
+ return (numNodes);
+}
+
+
+MP_STATUS
+MP_GetMultipathLusDevProd(MP_OID oid, MP_OID_LIST **ppList)
+{
+ di_node_t root_node = DI_NODE_NIL;
+
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+ int numNodes = 0;
+ int ioctlStatus = 0;
+ int i = 0;
+
+ mp_iocdata_t mp_ioctl;
+ mp_dev_prod_prop_t devProdInfo;
+
+ char inqProductID[256];
+ char inqVendorID[256];
+
+
+
+ log(LOG_INFO, "MP_GetMultipathLusDevProd()", " - enter");
+
+
+
+ log(LOG_INFO, "MP_GetMultipathLusDevProd()",
+ "oid.objectSequenceNumber = %llx",
+ oid.objectSequenceNumber);
+
+ if (g_scsi_vhci_fd < 0) {
+ log(LOG_INFO, "MP_GetMultipathLusDevProd()",
+ "invalid driver file handle");
+ log(LOG_INFO, "MP_GetMultipathLusDevProd",
+ " - error exit");
+ return (MP_STATUS_FAILED);
+ }
+
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+ (void) memset(&devProdInfo, 0, sizeof (mp_dev_prod_prop_t));
+
+ mp_ioctl.mp_cmd = MP_GET_DEV_PROD_PROP;
+ mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber;
+ mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber);
+ mp_ioctl.mp_obuf = (caddr_t)&devProdInfo;
+ mp_ioctl.mp_olen = sizeof (mp_dev_prod_prop_t);
+ mp_ioctl.mp_xfer = MP_XFER_READ;
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+
+ log(LOG_INFO, "MP_GetMultipathLusDevProd()",
+ " IOCTL call returned: %d", ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if (ioctlStatus != 0) {
+ log(LOG_INFO, "MP_GetMultipathLusDevProd()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO, "MP_GetMultipathLusDevProd()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO, "MP_GetMultipathLusDevProd()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+ if (ENOTSUP == ioctlStatus) {
+ mpStatus = MP_STATUS_UNSUPPORTED;
+ } else if (0 == mp_ioctl.mp_errno) {
+ mpStatus = MP_STATUS_FAILED;
+ } else {
+ mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno);
+ }
+
+ log(LOG_INFO, "MP_GetMultipathLusDevProd()",
+ " - error exit");
+
+ return (mpStatus);
+ }
+
+ (void) strncpy(inqProductID,
+ devProdInfo.prodInfo.product,
+ sizeof (devProdInfo.prodInfo.product));
+
+ (void) strncpy(inqVendorID,
+ devProdInfo.prodInfo.vendor,
+ sizeof (devProdInfo.prodInfo.vendor));
+
+ log(LOG_INFO, "MP_GetMultipathLusDevProd()",
+ " - inqProductID: [%s]", inqProductID);
+ log(LOG_INFO, "MP_GetMultipathLusDevProd()",
+ " - inqVendorID: [%s]", inqVendorID);
+
+
+ root_node = di_init("/", DINFOCACHE);
+ if (DI_NODE_NIL == root_node) {
+ log(LOG_INFO, "MP_GetMultipathLusDevProd()",
+ " - di_init() failed");
+
+ log(LOG_INFO, "MP_GetMultipathLusDevProd()",
+ " - error exit");
+
+ return (MP_STATUS_FAILED);
+ }
+
+ numNodes = getOidList(root_node,
+ NULL,
+ inqProductID,
+ inqVendorID);
+
+ if (numNodes < 0) {
+
+ log(LOG_INFO,
+ "MP_GetMultipathLusDevProd()",
+ " - unable to get OID list.");
+
+ log(LOG_INFO, "MP_GetMultipathLusDevProd()",
+ " - error exit");
+
+ di_fini(root_node);
+
+ return (MP_STATUS_FAILED);
+ }
+
+
+ if (0 == numNodes) {
+
+ *ppList = createOidList(1);
+ if (NULL == *ppList) {
+
+ log(LOG_INFO,
+ "MP_GetMultipathLusDevProd()",
+ " - unable to create OID list.");
+
+ log(LOG_INFO, "MP_GetMultipathLusDevProd()",
+ " - error exit");
+
+ di_fini(root_node);
+
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ (*ppList)->oids[0].objectType =
+ MP_OBJECT_TYPE_MULTIPATH_LU;
+
+ (*ppList)->oids[0].ownerId =
+ g_pluginOwnerID;
+
+ log(LOG_INFO, "MP_GetMultipathLusDevProd()",
+ " - returning empty list.");
+
+ return (MP_STATUS_SUCCESS);
+ }
+
+ *ppList = createOidList(numNodes);
+ if (NULL == *ppList) {
+ log(LOG_INFO, "MP_GetMultipathLusDevProd()",
+ "no memory for *ppList");
+ log(LOG_INFO, "MP_GetMultipathLusDevProd()",
+ " - error exit");
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ (*ppList)->oidCount = numNodes;
+
+ numNodes = getOidList(root_node,
+ *ppList,
+ inqProductID,
+ inqVendorID);
+
+
+ for (i = 0; i < (*ppList)->oidCount; i++) {
+
+ log(LOG_INFO, "MP_GetMultipathLusDevProd()",
+ "(*ppList)->oids[%d].objectType = %d",
+ i, (*ppList)->oids[i].objectType);
+ log(LOG_INFO, "MP_GetMultipathLusDevProd()",
+ "(*ppList)->oids[%d].ownerId = %d",
+ i, (*ppList)->oids[i].ownerId);
+ log(LOG_INFO, "MP_GetMultipathLusDevProd()",
+ "(*ppList)->oids[%d].objectSequenceNumber = %llx",
+ i, (*ppList)->oids[i].objectSequenceNumber);
+ }
+
+
+ di_fini(root_node);
+
+ log(LOG_INFO, "MP_GetMultipathLusDevProd()", " - exit");
+
+ return (MP_STATUS_SUCCESS);
+
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetMultipathLusPlugin.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetMultipathLusPlugin.c
new file mode 100644
index 0000000000..91670ad4f0
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetMultipathLusPlugin.c
@@ -0,0 +1,198 @@
+/*
+ * 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.
+ */
+
+#include <syslog.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stropts.h>
+
+#include "mp_utils.h"
+
+#include <libdevinfo.h>
+
+static int getOidList(di_node_t root_node, MP_OID_LIST *pOidList)
+{
+ int numNodes = 0;
+
+ MP_UINT64 instNum = 0;
+
+ di_node_t sv_node = DI_NODE_NIL;
+ di_node_t sv_child_node = DI_NODE_NIL;
+
+ int haveList = (NULL != pOidList);
+
+
+ log(LOG_INFO, "getOidList()", " - enter");
+
+
+ sv_node = di_drv_first_node("scsi_vhci", root_node);
+ if (DI_NODE_NIL == sv_node) {
+ log(LOG_INFO, "getOidList()",
+ " - di_drv_first_node() failed");
+
+ return (-1);
+ }
+
+ sv_child_node = di_child_node(sv_node);
+
+ while (DI_NODE_NIL != sv_child_node) {
+
+ if (haveList && (numNodes < pOidList->oidCount)) {
+
+ instNum =
+ (MP_UINT64)di_instance(sv_child_node);
+
+ log(LOG_INFO, "getOidList()",
+ " - instance number is: %llx",
+ instNum);
+
+ pOidList->oids[numNodes].objectType =
+ MP_OBJECT_TYPE_MULTIPATH_LU;
+
+ pOidList->oids[numNodes].ownerId =
+ g_pluginOwnerID;
+
+ pOidList->oids[numNodes].objectSequenceNumber =
+ instNum;
+ }
+
+ ++numNodes;
+
+ sv_child_node = di_sibling_node(sv_child_node);
+ }
+
+ log(LOG_INFO,
+ "getOidList()",
+ " - numNodes: %d",
+ numNodes);
+
+
+
+ log(LOG_INFO, "getOidList()", " - exit");
+
+ return (numNodes);
+}
+
+
+MP_STATUS
+MP_GetMultipathLusPlugin(MP_OID_LIST **ppList)
+{
+ di_node_t root_node = DI_NODE_NIL;
+ MP_OID_LIST *pOidList = NULL;
+
+ int numNodes = 0;
+ int i = 0;
+
+ log(LOG_INFO, "MP_GetMultipathLusPlugin()", " - enter");
+
+
+ root_node = di_init("/", DINFOCACHE);
+ if (DI_NODE_NIL == root_node) {
+ log(LOG_INFO, "MP_GetMultipathLusPlugin()",
+ " - di_init() failed");
+
+ return (MP_STATUS_FAILED);
+ }
+
+ numNodes = getOidList(root_node, NULL);
+
+ if (numNodes < 0) {
+
+ log(LOG_INFO,
+ "MP_GetMultipathLusPlugin()",
+ " - unable to get OID list.");
+
+ log(LOG_INFO, "MP_GetMultipathLusPlugin()",
+ " - error exit");
+
+ di_fini(root_node);
+
+ return (MP_STATUS_FAILED);
+ }
+
+ if (0 == numNodes) {
+
+ pOidList = createOidList(1);
+ if (NULL == pOidList) {
+
+ log(LOG_INFO,
+ "MP_GetMultipathLusPlugin()",
+ " - unable to create OID list.");
+
+ di_fini(root_node);
+
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ pOidList->oids[0].objectType =
+ MP_OBJECT_TYPE_MULTIPATH_LU;
+
+ pOidList->oids[0].ownerId =
+ g_pluginOwnerID;
+
+ *ppList = pOidList;
+
+ log(LOG_INFO, "MP_GetMultipathLusPlugin()",
+ " - returning empty list.");
+
+ di_fini(root_node);
+
+ return (MP_STATUS_SUCCESS);
+ }
+
+ *ppList = createOidList(numNodes);
+ if (NULL == *ppList) {
+ log(LOG_INFO, "MP_GetMultipathLusPlugin()",
+ "no memory for *ppList");
+ log(LOG_INFO, "MP_GetMultipathLusPlugin()",
+ " - error exit");
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ (*ppList)->oidCount = numNodes;
+
+ numNodes = getOidList(root_node, *ppList);
+
+ for (i = 0; i < (*ppList)->oidCount; i++) {
+
+ log(LOG_INFO, "MP_GetMultipathLusPlugin()",
+ "(*ppList)->oids[%d].objectType = %d",
+ i, (*ppList)->oids[i].objectType);
+ log(LOG_INFO, "MP_GetMultipathLusPlugin()",
+ "(*ppList)->oids[%d].ownerId = %d",
+ i, (*ppList)->oids[i].ownerId);
+ log(LOG_INFO, "MP_GetMultipathLusPlugin()",
+ "(*ppList)->oids[%d].objectSequenceNumber = %llx",
+ i, (*ppList)->oids[i].objectSequenceNumber);
+ }
+
+
+ di_fini(root_node);
+
+ log(LOG_INFO, "MP_GetMultipathLusPlugin()", " - exit");
+
+ return (MP_STATUS_SUCCESS);
+
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetPathLogicalUnitProperties.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetPathLogicalUnitProperties.c
new file mode 100644
index 0000000000..40f3caa2e6
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetPathLogicalUnitProperties.c
@@ -0,0 +1,174 @@
+/*
+ * 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.
+ */
+
+#include <string.h>
+#include <syslog.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stropts.h>
+
+#include "mp_utils.h"
+
+
+MP_STATUS
+MP_GetPathLogicalUnitProperties(MP_OID oid,
+ MP_PATH_LOGICAL_UNIT_PROPERTIES *pProps)
+{
+ mp_iocdata_t mp_ioctl;
+ mp_path_prop_t pathInfo;
+
+ int ioctlStatus = 0;
+
+ MP_OID initPortOID;
+ MP_OID targetPortOID;
+ MP_OID luOID;
+
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+
+
+ log(LOG_INFO, "MP_GetPathLogicalUnitProperties()", " - enter");
+
+
+ log(LOG_INFO, "MP_GetPathLogicalUnitProperties()",
+ "oid.objectSequenceNumber = %llx",
+ oid.objectSequenceNumber);
+
+
+ if (g_scsi_vhci_fd < 0) {
+ log(LOG_INFO, "MP_GetPathLogicalUnitProperties()",
+ "invalid driver file handle");
+ log(LOG_INFO, "MP_GetPathLogicalUnitProperties()",
+ " - error exit");
+ return (MP_STATUS_FAILED);
+ }
+
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+ (void) memset(&pathInfo, 0, sizeof (mp_path_prop_t));
+
+ mp_ioctl.mp_cmd = MP_GET_PATH_PROP;
+ mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber;
+ mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber);
+ mp_ioctl.mp_obuf = (caddr_t)&pathInfo;
+ mp_ioctl.mp_olen = sizeof (mp_path_prop_t);
+ mp_ioctl.mp_xfer = MP_XFER_READ;
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+
+ log(LOG_INFO, "MP_GetPathLogicalUnitProperties()",
+ " IOCTL call returned: %d", ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if (ioctlStatus != 0) {
+ log(LOG_INFO, "MP_GetPathLogicalUnitProperties()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO, "MP_GetPathLogicalUnitProperties()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO, "MP_GetPathLogicalUnitProperties()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+ if (ENOTSUP == ioctlStatus) {
+ mpStatus = MP_STATUS_UNSUPPORTED;
+ } else if (0 == mp_ioctl.mp_errno) {
+ mpStatus = MP_STATUS_FAILED;
+ } else {
+ mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno);
+ }
+
+ log(LOG_INFO, "MP_GetPathLogicalUnitProperties()",
+ " - error exit");
+
+ return (mpStatus);
+ }
+
+ (void) memset(pProps, 0, sizeof (MP_PATH_LOGICAL_UNIT_PROPERTIES));
+
+ pProps->disabled = pathInfo.disabled;
+
+ initPortOID.objectSequenceNumber = pathInfo.initPort.id;
+ initPortOID.objectType = MP_OBJECT_TYPE_INITIATOR_PORT;
+ initPortOID.ownerId = g_pluginOwnerID;
+
+ (void) memcpy(&pProps->initiatorPortOid, &initPortOID, sizeof (MP_OID));
+
+ targetPortOID.objectSequenceNumber = pathInfo.targetPort.id;
+ targetPortOID.objectType = MP_OBJECT_TYPE_TARGET_PORT;
+ targetPortOID.ownerId = g_pluginOwnerID;
+
+ (void) memcpy(&pProps->targetPortOid, &targetPortOID, sizeof (MP_OID));
+
+ luOID.objectSequenceNumber = pathInfo.logicalUnit.id;
+ luOID.objectType = MP_OBJECT_TYPE_MULTIPATH_LU;
+ luOID.ownerId = g_pluginOwnerID;
+
+ (void) memcpy(&pProps->logicalUnitOid, &luOID, sizeof (MP_OID));
+
+ pProps->logicalUnitNumber = pathInfo.logicalUnit.id;
+
+ switch (pathInfo.pathState) {
+
+ case MP_DRVR_PATH_STATE_ACTIVE:
+ case MP_DRVR_PATH_STATE_PASSIVE:
+ pProps->pathState = MP_PATH_STATE_OKAY;
+ break;
+
+ case MP_DRVR_PATH_STATE_PATH_ERR:
+ pProps->pathState = MP_PATH_STATE_PATH_ERR;
+ break;
+
+ case MP_DRVR_PATH_STATE_LU_ERR:
+ pProps->pathState = MP_PATH_STATE_LU_ERR;
+ break;
+
+ case MP_DRVR_PATH_STATE_RESERVED:
+ pProps->pathState = MP_PATH_STATE_RESERVED;
+ break;
+
+ case MP_DRVR_PATH_STATE_REMOVED:
+ pProps->pathState = MP_PATH_STATE_REMOVED;
+ break;
+
+ case MP_DRVR_PATH_STATE_TRANSITIONING:
+ pProps->pathState = MP_PATH_STATE_TRANSITIONING;
+ break;
+
+ default:
+ pProps->pathState = MP_PATH_STATE_UNKNOWN;
+
+ }
+
+ pProps->weight = pathInfo.weight;
+
+
+ log(LOG_INFO, "MP_GetPathLogicalUnitProperties()", " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetPluginPropertiesPlugin.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetPluginPropertiesPlugin.c
new file mode 100644
index 0000000000..28addebcbe
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetPluginPropertiesPlugin.c
@@ -0,0 +1,147 @@
+/*
+ * 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.
+ */
+
+#include "mp_utils.h"
+
+#include <string.h>
+#include <syslog.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stropts.h>
+
+
+
+MP_STATUS
+MP_GetPluginPropertiesPlugin(MP_PLUGIN_PROPERTIES *pProps)
+{
+ mp_iocdata_t mp_ioctl;
+ mp_driver_prop_t driverInfo;
+
+ int ioctlStatus = 0;
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+ log(LOG_INFO, "MP_GetPluginPropertiesPlugin()", " - enter");
+
+ if (g_scsi_vhci_fd < 0) {
+ log(LOG_INFO, "MP_GetPluginPropertiesPlugin()",
+ "invalid driver file handle");
+ return (MP_STATUS_FAILED);
+ }
+
+ (void) memset(pProps, 0, sizeof (MP_PLUGIN_PROPERTIES));
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+ (void) memset(&driverInfo, 0, sizeof (mp_driver_prop_t));
+
+ mp_ioctl.mp_cmd = MP_GET_DRIVER_PROP;
+ mp_ioctl.mp_obuf = (caddr_t)&driverInfo;
+ mp_ioctl.mp_olen = sizeof (mp_driver_prop_t);
+ mp_ioctl.mp_xfer = MP_XFER_READ;
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+
+ log(LOG_INFO, "MP_GetPluginPropertiesPlugin()",
+ " IOCTL call returned: %d", ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if (ioctlStatus != 0) {
+ log(LOG_INFO, "MP_GetPluginPropertiesPlugin()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO, "MP_GetPluginPropertiesPlugin()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO, "MP_GetPluginPropertiesPlugin()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+ if (ENOTSUP == ioctlStatus) {
+ mpStatus = MP_STATUS_UNSUPPORTED;
+ } else if (0 == mp_ioctl.mp_errno) {
+ mpStatus = MP_STATUS_FAILED;
+ } else {
+ mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno);
+ }
+
+ log(LOG_INFO, "MP_GetPluginPropertiesPlugin()",
+ " - error exit");
+
+ return (mpStatus);
+ }
+
+ (void) wcsncpy(pProps->vendor, L"Sun Microsystems", 255);
+
+ pProps->autoFailbackSupport = driverInfo.autoFailbackSupport;
+ pProps->autoProbingSupport = driverInfo.autoProbingSupport;
+
+#ifdef BUILD_TIME
+ (void) mbstowcs(pProps->buildTime, BUILD_TIME, 256);
+#endif
+
+ pProps->canOverridePaths = driverInfo.canOverridePaths;
+ pProps->canSetTPGAccess = driverInfo.canSetTPGAccess;
+ pProps->currentFailbackPollingRate =
+ driverInfo.currentFailbackPollingRate;
+ pProps->currentProbingPollingRate =
+ driverInfo.currentProbingPollingRate;
+ pProps->defaultloadBalanceType =
+ driverInfo.defaultLoadBalanceType;
+
+ (void) strncpy(pProps->deviceFileNamespace,
+ driverInfo.deviceFileNamespace, 255);
+
+ (void) strncpy(pProps->driverName, "scsi_vhci", 255);
+
+ (void) wcsncpy(pProps->driverVendor, L"Sun Microsystems", 255);
+
+ (void) mbstowcs(pProps->driverVersion, driverInfo.driverVersion, 256);
+
+ pProps->exposesPathDeviceFiles = driverInfo.exposesPathDeviceFiles;
+ pProps->failbackPollingRateMax = driverInfo.failbackPollingRateMax;
+
+ (void) strncpy(pProps->fileName, "libmpscsi_vhci.so", 255);
+
+ (void) wcsncpy(pProps->implementationVersion, L"1.0.0.0", 255);
+
+ pProps->maximumWeight = driverInfo.maximumWeight;
+ pProps->onlySupportsSpecifiedProducts =
+ driverInfo.onlySupportsSpecifiedProducts;
+
+ pProps->pluginAutoFailbackEnabled = driverInfo.autoFailbackEnabled;
+ pProps->pluginAutoProbingEnabled = driverInfo.autoProbingEnabled;
+
+ pProps->probingPollingRateMax = driverInfo.probingPollingRateMax;
+
+ pProps->supportedLoadBalanceTypes =
+ driverInfo.supportedLoadBalanceTypes;
+ pProps->supportedMpVersion = MP_LIBVERSION;
+
+
+ log(LOG_INFO, "MP_GetPluginPropertiesPlugin()", " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetProprietaryLBOidListPlugin.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetProprietaryLBOidListPlugin.c
new file mode 100644
index 0000000000..c06be96768
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetProprietaryLBOidListPlugin.c
@@ -0,0 +1,287 @@
+/*
+ * 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.
+ */
+
+#include <syslog.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stropts.h>
+
+#include "mp_utils.h"
+
+
+MP_STATUS
+MP_GetProprietaryLoadBalanceOidListPlugin(MP_OID_LIST **ppList)
+{
+ mp_iocdata_t mp_ioctl;
+
+ uint64_t *objList = NULL;
+
+ int numOBJ = 0;
+ int i = 0;
+ int ioctlStatus = 0;
+
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ " - enter");
+
+
+ if (g_scsi_vhci_fd < 0) {
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ "invalid driver file handle");
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ " - error exit");
+ return (MP_STATUS_FAILED);
+ }
+
+ objList = (uint64_t *)calloc(1, DEFAULT_BUFFER_SIZE_LOADBALANCE);
+ if (NULL == objList) {
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ "no memory for objList(1)");
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ " - error exit");
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+
+ mp_ioctl.mp_cmd = MP_GET_PROPRIETARY_LOADBALANCE_LIST;
+ mp_ioctl.mp_obuf = (caddr_t)objList;
+ mp_ioctl.mp_olen = DEFAULT_BUFFER_SIZE_LOADBALANCE;
+ mp_ioctl.mp_xfer = MP_XFER_READ;
+
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ "mp_ioctl.mp_cmd : %d", mp_ioctl.mp_cmd);
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ "mp_ioctl.mp_obuf: %x", mp_ioctl.mp_obuf);
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ "mp_ioctl.mp_olen: %d", mp_ioctl.mp_olen);
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ "mp_ioctl.mp_xfer: %d (MP_XFER_READ)",
+ mp_ioctl.mp_xfer);
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+ log(LOG_INFO, "MP_GetInitiatorPortOidListPlugin()",
+ "ioctl call returned ioctlStatus: %d",
+ ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if ((ioctlStatus != 0) && (MP_MORE_DATA != mp_ioctl.mp_errno)) {
+
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+
+ free(objList);
+
+ if (ENOTSUP == ioctlStatus) {
+ mpStatus = MP_STATUS_UNSUPPORTED;
+ } else if (0 == mp_ioctl.mp_errno) {
+ mpStatus = MP_STATUS_FAILED;
+ } else {
+ mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno);
+ }
+
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ " - error exit");
+
+ return (mpStatus);
+ }
+
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ " - mp_ioctl.mp_alen : %d",
+ mp_ioctl.mp_alen);
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ " - sizeof (uint64_t): %d",
+ sizeof (uint64_t));
+
+ numOBJ = mp_ioctl.mp_alen / sizeof (uint64_t);
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ "Length of list: %d", numOBJ);
+
+ if (numOBJ < 1) {
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ "driver returned empty list.");
+
+ free(objList);
+
+ *ppList = createOidList(1);
+ if (NULL == *ppList) {
+ log(LOG_INFO,
+ "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ "no memory for MP_OID_LIST");
+ log(LOG_INFO,
+ "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ " - error exit");
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ return (MP_STATUS_SUCCESS);
+ }
+
+ if (mp_ioctl.mp_alen > DEFAULT_BUFFER_SIZE_LOADBALANCE) {
+
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ "buffer size too small, need : %d",
+ mp_ioctl.mp_alen);
+
+ free(objList);
+
+ objList = (uint64_t *)calloc(1, numOBJ * sizeof (uint64_t));
+ if (NULL == objList) {
+ log(LOG_INFO,
+ "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ "no memory for objList(2)");
+ log(LOG_INFO,
+ "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ " - error exit");
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+
+ mp_ioctl.mp_cmd = MP_GET_PROPRIETARY_LOADBALANCE_LIST;
+ mp_ioctl.mp_obuf = (caddr_t)objList;
+ mp_ioctl.mp_olen = numOBJ * sizeof (uint64_t);
+ mp_ioctl.mp_xfer = MP_XFER_READ;
+
+ log(LOG_INFO,
+ "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ "mp_ioctl.mp_cmd : %d", mp_ioctl.mp_cmd);
+ log(LOG_INFO,
+ "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ "mp_ioctl.mp_obuf: %x", mp_ioctl.mp_obuf);
+ log(LOG_INFO,
+ "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ "mp_ioctl.mp_olen: %d", mp_ioctl.mp_olen);
+ log(LOG_INFO,
+ "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ "mp_ioctl.mp_xfer: %d (MP_XFER_READ)",
+ mp_ioctl.mp_xfer);
+
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ "ioctl call returned ioctlStatus: %d",
+ ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if (ioctlStatus != 0) {
+
+ log(LOG_INFO,
+ "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO,
+ "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO,
+ "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+
+ free(objList);
+
+ if (ENOTSUP == ioctlStatus) {
+ mpStatus = MP_STATUS_UNSUPPORTED;
+ } else if (0 == mp_ioctl.mp_errno) {
+ mpStatus = MP_STATUS_FAILED;
+ } else {
+ mpStatus =
+ getStatus4ErrorCode(mp_ioctl.mp_errno);
+ }
+
+ log(LOG_INFO,
+ "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ " - error exit");
+
+ return (mpStatus);
+ }
+ }
+
+
+ *ppList = createOidList(numOBJ);
+ if (NULL == *ppList) {
+ log(LOG_INFO,
+ "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ "no memory for *ppList");
+ free(objList);
+ log(LOG_INFO,
+ "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ " - error exit");
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ (*ppList)->oidCount = numOBJ;
+
+ log(LOG_INFO,
+ "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ "(*ppList)->oidCount = %d",
+ (*ppList)->oidCount);
+
+ for (i = 0; i < numOBJ; i++) {
+
+ (*ppList)->oids[i].objectType =
+ MP_OBJECT_TYPE_PROPRIETARY_LOAD_BALANCE;
+ (*ppList)->oids[i].ownerId =
+ g_pluginOwnerID;
+ (*ppList)->oids[i].objectSequenceNumber =
+ objList[i];
+
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ "(*ppList)->oids[%d].objectType = %d",
+ i, (*ppList)->oids[i].objectType);
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ "(*ppList)->oids[%d].ownerId = %d",
+ i, (*ppList)->oids[i].ownerId);
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ "(*ppList)->oids[%d].objectSequenceNumber = %llx",
+ i, (*ppList)->oids[i].objectSequenceNumber);
+ }
+
+ free(objList);
+
+
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceOidListPlugin()",
+ " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetProprietaryLBProp.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetProprietaryLBProp.c
new file mode 100644
index 0000000000..cf61b19d2a
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetProprietaryLBProp.c
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+
+#include <syslog.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stropts.h>
+
+
+#include "mp_utils.h"
+
+
+MP_STATUS
+MP_GetProprietaryLoadBalanceProperties(MP_OID oid,
+ MP_PROPRIETARY_LOAD_BALANCE_PROPERTIES *pProps)
+{
+ mp_iocdata_t mp_ioctl;
+ mp_proprietary_loadbalance_prop_t lbProps;
+
+ int ioctlStatus = 0;
+
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceProperties()", " - enter");
+
+
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceProperties()",
+ "oid.objectSequenceNumber = %llx",
+ oid.objectSequenceNumber);
+
+ if (g_scsi_vhci_fd < 0) {
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceProperties()",
+ "invalid driver file handle");
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceProperties",
+ " - error exit");
+ return (MP_STATUS_FAILED);
+ }
+
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+ (void) memset(&lbProps, 0, sizeof (mp_proprietary_loadbalance_prop_t));
+
+ mp_ioctl.mp_cmd = MP_GET_PROPRIETARY_LOADBALANCE_PROP;
+ mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber;
+ mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber);
+ mp_ioctl.mp_obuf = (caddr_t)&lbProps;
+ mp_ioctl.mp_olen = sizeof (mp_proprietary_loadbalance_prop_t);
+ mp_ioctl.mp_xfer = MP_XFER_READ;
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceProperties()",
+ " IOCTL call returned: %d", ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if (ioctlStatus != 0) {
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceProperties()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceProperties()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceProperties()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+ if (ENOTSUP == ioctlStatus) {
+ mpStatus = MP_STATUS_UNSUPPORTED;
+ } else if (0 == mp_ioctl.mp_errno) {
+ mpStatus = MP_STATUS_FAILED;
+ } else {
+ mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno);
+ }
+
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceProperties()",
+ " - error exit");
+
+ return (mpStatus);
+ }
+
+ (void) memset(pProps, 0,
+ sizeof (MP_PROPRIETARY_LOAD_BALANCE_PROPERTIES));
+
+ (void) mbstowcs(pProps->name, lbProps.name, 256);
+
+ /*
+ *
+ * Get:
+ *
+ * pProps->proprietaryPropertyCount &
+ * pProps->proprietaryProperties
+ *
+ * when they are available
+ *
+ */
+
+ pProps->typeIndex = lbProps.typeIndex;
+ (void) mbstowcs(pProps->vendorName, lbProps.vendorName, 256);
+
+
+ log(LOG_INFO, "MP_GetProprietaryLoadBalanceProperties()", " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetTargetPortGroupProperties.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetTargetPortGroupProperties.c
new file mode 100644
index 0000000000..0e2b510c1f
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetTargetPortGroupProperties.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.
+ */
+
+#include <string.h>
+#include <syslog.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stropts.h>
+
+
+#include "mp_utils.h"
+
+
+
+MP_STATUS
+MP_GetTargetPortGroupProperties(MP_OID oid,
+ MP_TARGET_PORT_GROUP_PROPERTIES *pProps)
+{
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+
+ log(LOG_INFO, "MP_GetTargetPortGroupProperties()", " - enter");
+
+
+ mpStatus = getTargetPortGroupProperties(oid, pProps);
+
+
+ log(LOG_INFO, "MP_GetTargetPortGroupProperties()", " - exit");
+
+ return (mpStatus);
+}
+
+
+MP_STATUS
+getTargetPortGroupProperties(MP_OID oid,
+ MP_TARGET_PORT_GROUP_PROPERTIES *pProps)
+{
+ mp_iocdata_t mp_ioctl;
+ mp_tpg_prop_t tpgProps;
+
+ int ioctlStatus = 0;
+
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+
+ log(LOG_INFO, "getTargetPortGroupProperties()", " - enter");
+
+ if (g_scsi_vhci_fd < 0) {
+ log(LOG_INFO, "getTargetPortGroupProperties()",
+ "invalid driver file handle");
+ log(LOG_INFO, "getTargetPortGroupProperties",
+ " - error exit");
+ return (MP_STATUS_FAILED);
+ }
+
+ log(LOG_INFO, "getTargetPortGroupProperties()",
+ "oid.objectSequenceNumber = %llx",
+ oid.objectSequenceNumber);
+
+ (void) memset(pProps, 0, sizeof (MP_TARGET_PORT_GROUP_PROPERTIES));
+ (void) memset(&tpgProps, 0, sizeof (mp_tpg_prop_t));
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+
+ mp_ioctl.mp_cmd = MP_GET_TPG_PROP;
+ mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber;
+ mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber);
+ mp_ioctl.mp_obuf = (caddr_t)&tpgProps;
+ mp_ioctl.mp_olen = sizeof (mp_tpg_prop_t);
+ mp_ioctl.mp_xfer = MP_XFER_READ;
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+
+ log(LOG_INFO, "getTargetPortGroupProperties()",
+ " IOCTL call returned: %d", ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if (ioctlStatus != 0) {
+ log(LOG_INFO, "getTargetPortGroupProperties()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO, "getTargetPortGroupProperties()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO, "getTargetPortGroupProperties()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+ if (ENOTSUP == ioctlStatus) {
+ mpStatus = MP_STATUS_UNSUPPORTED;
+ } else if (0 == mp_ioctl.mp_errno) {
+ mpStatus = MP_STATUS_FAILED;
+ } else {
+ mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno);
+ }
+
+ log(LOG_INFO, "getTargetPortGroupProperties()",
+ " - error exit");
+
+ return (mpStatus);
+ }
+
+ pProps->accessState = tpgProps.accessState;
+ pProps->explicitFailover = tpgProps.explicitFailover;
+ pProps->preferredLuPath = tpgProps.preferredLuPath;
+ pProps->supportsLuAssignment = tpgProps.supportsLuAssignment;
+ pProps->tpgID = tpgProps.tpgId;
+
+
+ log(LOG_INFO, "getTargetPortGroupProperties()", " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetTargetPortOidList.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetTargetPortOidList.c
new file mode 100644
index 0000000000..9b823bea18
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetTargetPortOidList.c
@@ -0,0 +1,297 @@
+/*
+ * 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.
+ */
+
+#include <string.h>
+#include <syslog.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stropts.h>
+
+
+#include "mp_utils.h"
+
+
+MP_STATUS
+MP_GetTargetPortOidList(MP_OID oid, MP_OID_LIST **ppList)
+{
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+
+ log(LOG_INFO, "MP_GetTargetPortOidList()", " - enter");
+
+
+ mpStatus = getTargetPortOidList(oid, ppList);
+
+
+ log(LOG_INFO, "MP_GetTargetPortOidList()", " - exit");
+
+ return (mpStatus);
+}
+
+
+
+MP_STATUS
+getTargetPortOidList(MP_OID oid, MP_OID_LIST **ppList)
+{
+ mp_iocdata_t mp_ioctl;
+
+ uint64_t *objList = NULL;
+
+ int numOBJ = 0;
+ int i = 0;
+ int ioctlStatus = 0;
+
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+
+ log(LOG_INFO, "getTargetPortOidList()", " - enter");
+
+
+ log(LOG_INFO, "getTargetPortOidList()",
+ "oid.objectSequenceNumber = %llx",
+ oid.objectSequenceNumber);
+
+ if (g_scsi_vhci_fd < 0) {
+ log(LOG_INFO, "getTargetPortOidList()",
+ "invalid driver file handle");
+ log(LOG_INFO, "getTargetPortOidList()", " - error exit");
+ return (MP_STATUS_FAILED);
+ }
+
+ objList = (uint64_t *)calloc(1, DEFAULT_BUFFER_SIZE_TPG);
+ if (NULL == objList) {
+ log(LOG_INFO, "getTargetPortOidList()",
+ "no memory for objList(1)");
+ log(LOG_INFO, "getTargetPortOidList()",
+ " - error exit");
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+
+ mp_ioctl.mp_cmd = MP_GET_TARGET_PORT_LIST_FOR_TPG;
+ mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber;
+ mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber);
+ mp_ioctl.mp_obuf = (caddr_t)objList;
+ mp_ioctl.mp_olen = DEFAULT_BUFFER_SIZE_TPG;
+ mp_ioctl.mp_xfer = MP_XFER_READ;
+
+ log(LOG_INFO, "getTargetPortOidList()",
+ "mp_ioctl.mp_cmd (MP_GET_TARGET_PORT_LIST_FOR_TPG): %d",
+ mp_ioctl.mp_cmd);
+ log(LOG_INFO, "getTargetPortOidList()",
+ "mp_ioctl.mp_obuf: %x", mp_ioctl.mp_obuf);
+ log(LOG_INFO, "getTargetPortOidList()",
+ "mp_ioctl.mp_olen: %d", mp_ioctl.mp_olen);
+ log(LOG_INFO, "getTargetPortOidList()",
+ "mp_ioctl.mp_xfer: %d (MP_XFER_READ)",
+ mp_ioctl.mp_xfer);
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+ log(LOG_INFO, "getTargetPortOidList()",
+ "ioctl call returned ioctlStatus: %d",
+ ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if ((ioctlStatus != 0) && (MP_MORE_DATA != mp_ioctl.mp_errno)) {
+
+ log(LOG_INFO, "getTargetPortOidList()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO, "getTargetPortOidList()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO, "getTargetPortOidList()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+
+ free(objList);
+
+ if (ENOTSUP == ioctlStatus) {
+ mpStatus = MP_STATUS_UNSUPPORTED;
+ } else if (0 == mp_ioctl.mp_errno) {
+ mpStatus = MP_STATUS_FAILED;
+ } else {
+ mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno);
+ }
+
+ log(LOG_INFO, "getTargetPortOidList()",
+ " - error exit");
+
+ return (mpStatus);
+ }
+
+ log(LOG_INFO, "getTargetPortOidList()",
+ " - mp_ioctl.mp_alen : %d",
+ mp_ioctl.mp_alen);
+ log(LOG_INFO, "getTargetPortOidList()",
+ " - sizeof (uint64_t): %d",
+ sizeof (uint64_t));
+
+ numOBJ = mp_ioctl.mp_alen / sizeof (uint64_t);
+ log(LOG_INFO, "getTargetPortOidList()",
+ "Length of list: %d", numOBJ);
+
+ if (numOBJ < 1) {
+ log(LOG_INFO, "getTargetPortOidList()",
+ "driver returned empty list.");
+
+ free(objList);
+
+ *ppList = createOidList(1);
+ if (NULL == *ppList) {
+ log(LOG_INFO,
+ "getTargetPortOidList()",
+ "no memory for MP_OID_LIST");
+ log(LOG_INFO,
+ "getTargetPortOidList()",
+ " - error exit");
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ return (MP_STATUS_SUCCESS);
+ }
+
+ if (mp_ioctl.mp_alen > DEFAULT_BUFFER_SIZE_TPG) {
+
+ log(LOG_INFO, "getTargetPortOidList()",
+ "buffer size too small, need : %d",
+ mp_ioctl.mp_alen);
+
+ free(objList);
+
+ objList = (uint64_t *)calloc(1, numOBJ * sizeof (uint64_t));
+ if (NULL == objList) {
+ log(LOG_INFO, "getTargetPortOidList()",
+ "no memory for objList(2)");
+ log(LOG_INFO, "getTargetPortOidList()",
+ " - error exit");
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+
+ mp_ioctl.mp_cmd = MP_GET_TARGET_PORT_LIST_FOR_TPG;
+ mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber;
+ mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber);
+ mp_ioctl.mp_obuf = (caddr_t)objList;
+ mp_ioctl.mp_olen = numOBJ * sizeof (uint64_t);
+ mp_ioctl.mp_xfer = MP_XFER_READ;
+
+ log(LOG_INFO, "getTargetPortOidList()",
+ "mp_ioctl.mp_cmd (MP_GET_TARGET_PORT_LIST_FOR_TPG): %d",
+ mp_ioctl.mp_cmd);
+ log(LOG_INFO, "getTargetPortOidList()",
+ "mp_ioctl.mp_obuf: %x", mp_ioctl.mp_obuf);
+ log(LOG_INFO, "getTargetPortOidList()",
+ "mp_ioctl.mp_olen: %d", mp_ioctl.mp_olen);
+ log(LOG_INFO, "getTargetPortOidList()",
+ "mp_ioctl.mp_xfer: %d (MP_XFER_READ)",
+ mp_ioctl.mp_xfer);
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+ log(LOG_INFO, "getTargetPortOidList()",
+ "ioctl call returned ioctlStatus: %d",
+ ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if (ioctlStatus != 0) {
+
+ log(LOG_INFO, "getTargetPortOidList()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO, "getTargetPortOidList()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO, "getTargetPortOidList()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+
+ free(objList);
+
+ if (ENOTSUP == ioctlStatus) {
+ mpStatus = MP_STATUS_UNSUPPORTED;
+ } else if (0 == mp_ioctl.mp_errno) {
+ mpStatus = MP_STATUS_FAILED;
+ } else {
+ mpStatus =
+ getStatus4ErrorCode(mp_ioctl.mp_errno);
+ }
+
+ log(LOG_INFO, "getTargetPortOidList()",
+ " - error exit");
+
+ return (mpStatus);
+ }
+ }
+
+
+ *ppList = createOidList(numOBJ);
+ if (NULL == *ppList) {
+ log(LOG_INFO, "getTargetPortOidList()",
+ "no memory for *ppList");
+ free(objList);
+ log(LOG_INFO, "getTargetPortOidList()",
+ " - error exit");
+ return (MP_STATUS_INSUFFICIENT_MEMORY);
+ }
+
+ (*ppList)->oidCount = numOBJ;
+
+ log(LOG_INFO, "getTargetPortOidList()",
+ "(*ppList)->oidCount = %d",
+ (*ppList)->oidCount);
+
+ for (i = 0; i < numOBJ; i++) {
+ (*ppList)->oids[i].objectType = MP_OBJECT_TYPE_TARGET_PORT;
+ (*ppList)->oids[i].ownerId = g_pluginOwnerID;
+ (*ppList)->oids[i].objectSequenceNumber = objList[i];
+
+ log(LOG_INFO, "getTargetPortOidList()",
+ "(*ppList)->oids[%d].objectType = %d",
+ i, (*ppList)->oids[i].objectType);
+ log(LOG_INFO, "getTargetPortOidList()",
+ "(*ppList)->oids[%d].ownerId = %d",
+ i, (*ppList)->oids[i].ownerId);
+ log(LOG_INFO, "getTargetPortOidList()",
+ "(*ppList)->oids[%d].objectSequenceNumber = %llx",
+ i, (*ppList)->oids[i].objectSequenceNumber);
+ }
+
+ free(objList);
+
+
+ log(LOG_INFO, "getTargetPortOidList()", " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetTargetPortProperties.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetTargetPortProperties.c
new file mode 100644
index 0000000000..64422605ff
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_GetTargetPortProperties.c
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+#include <string.h>
+#include <syslog.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stropts.h>
+
+#include "mp_utils.h"
+
+
+
+MP_STATUS
+MP_GetTargetPortProperties(MP_OID oid,
+ MP_TARGET_PORT_PROPERTIES *pProps)
+{
+ mp_iocdata_t mp_ioctl;
+ mp_target_port_prop_t tpInfo;
+
+ int ioctlStatus = 0;
+
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+
+
+ log(LOG_INFO, "MP_GetTargetPortProperties()", " - enter");
+
+
+ log(LOG_INFO, "MP_GetTargetPortProperties()",
+ "oid.objectSequenceNumber = %llx",
+ oid.objectSequenceNumber);
+
+ if (g_scsi_vhci_fd < 0) {
+ log(LOG_INFO, "MP_GetTargetPortProperties()",
+ "invalid driver file handle");
+ log(LOG_INFO, "MP_GetTargetPortProperties()", " - error exit");
+ return (MP_STATUS_FAILED);
+ }
+
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+ (void) memset(&tpInfo, 0, sizeof (mp_target_port_prop_t));
+
+ mp_ioctl.mp_cmd = MP_GET_TARGET_PORT_PROP;
+ mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber;
+ mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber);
+ mp_ioctl.mp_obuf = (caddr_t)&tpInfo;
+ mp_ioctl.mp_olen = sizeof (mp_target_port_prop_t);
+ mp_ioctl.mp_xfer = MP_XFER_READ;
+
+ log(LOG_INFO, "MP_GetTargetPortProperties()",
+ "mp_ioctl.mp_cmd (MP_GET_TARGET_PORT_PROP) : %d",
+ mp_ioctl.mp_cmd);
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+
+ log(LOG_INFO, "MP_GetTargetPortProperties()",
+ " IOCTL call returned: %d", ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if (ioctlStatus != 0) {
+ log(LOG_INFO, "MP_GetTargetPortProperties()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO, "MP_GetTargetPortProperties()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO, "MP_GetTargetPortProperties()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+ if (ENOTSUP == ioctlStatus) {
+ mpStatus = MP_STATUS_UNSUPPORTED;
+ } else if (0 == mp_ioctl.mp_errno) {
+ mpStatus = MP_STATUS_FAILED;
+ } else {
+ mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno);
+ }
+
+ log(LOG_INFO, "MP_GetTargetPortProperties()",
+ " - error exit");
+
+ return (mpStatus);
+ }
+
+ (void) memset(pProps, 0, sizeof (MP_TARGET_PORT_PROPERTIES));
+
+ (void) strncpy(pProps->portID, tpInfo.portName,
+ sizeof (pProps->portID));
+ pProps->relativePortID = tpInfo.relativePortID;
+
+
+ log(LOG_INFO, "MP_GetTargetPortProperties()", " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_RegForObjPropChangesPlugin.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_RegForObjPropChangesPlugin.c
new file mode 100644
index 0000000000..2fa2e58e44
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_RegForObjPropChangesPlugin.c
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+
+#include "mp_utils.h"
+
+
+/*
+ * Called by the common layer to request the plugin to call
+ * a client application's callback (pClientFn) when a property change
+ * is detected for the given object type.
+ */
+
+MP_STATUS
+MP_RegisterForObjectPropertyChangesPlugin(MP_OBJECT_PROPERTY_FN pClientFn,
+ MP_OBJECT_TYPE objectType,
+ void *pCallerData)
+{
+ MP_BOOL hasFunc = MP_FALSE;
+
+
+ log(LOG_INFO, "MP_RegisterForObjectPropertyChangesPlugin()",
+ " - enter");
+
+
+ /* Validate the object type passes in within range */
+ if (objectType > MP_OBJECT_TYPE_MAX) {
+
+ log(LOG_INFO, "MP_RegisterForObjectPropertyChangesPlugin()",
+ " - objectType is invalid");
+
+ log(LOG_INFO, "MP_RegisterForObjectPropertyChangesPlugin()",
+ " - error exit");
+
+ return (MP_STATUS_INVALID_PARAMETER);
+ }
+
+ if (objectType < 1) {
+
+ log(LOG_INFO, "MP_RegisterForObjectPropertyChangesPlugin()",
+ " - objectType is invalid");
+
+ log(LOG_INFO, "MP_RegisterForObjectPropertyChangesPlugin()",
+ " - error exit");
+
+ return (MP_STATUS_INVALID_PARAMETER);
+ }
+
+ /* Check to see if we are going to be replacing */
+ (void) pthread_mutex_lock(&g_prop_mutex);
+ if (g_Property_Callback_List[objectType].pClientFn != NULL) {
+
+ hasFunc = MP_TRUE;
+ }
+
+ /* Add the registration. */
+ g_Property_Callback_List[objectType].pClientFn = pClientFn;
+ g_Property_Callback_List[objectType].pCallerData = pCallerData;
+ (void) pthread_mutex_unlock(&g_prop_mutex);
+
+ if (hasFunc) {
+
+ log(LOG_INFO, "MP_RegisterForObjectPropertyChangesPlugin()",
+ " - returning MP_STATUS_FN_REPLACED");
+
+ return (MP_STATUS_FN_REPLACED);
+ }
+
+
+ log(LOG_INFO, "MP_RegisterForObjectPropertyChangesPlugin()",
+ " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_RegForObjVisChangesPlugin.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_RegForObjVisChangesPlugin.c
new file mode 100644
index 0000000000..59585d3311
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_RegForObjVisChangesPlugin.c
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+#include "mp_utils.h"
+
+
+/*
+ * Called by the common layer to request the plugin to call
+ * a client application's callback (pClientFn) when a visibility change
+ * is detected for the given object type.
+ */
+
+MP_STATUS
+MP_RegisterForObjectVisibilityChangesPlugin(MP_OBJECT_VISIBILITY_FN pClientFn,
+ MP_OBJECT_TYPE objectType,
+ void *pCallerData)
+{
+ MP_BOOL hasFunc = MP_FALSE;
+
+
+ log(LOG_INFO, "MP_RegisterForObjectVisibilityChangesPlugin()",
+ " - enter");
+
+
+ /* Validate the object type passes in within range */
+ if (objectType > MP_OBJECT_TYPE_MAX) {
+
+ log(LOG_INFO, "MP_RegisterForObjectVisibilityChangesPlugin()",
+ " - objectType is invalid");
+
+ log(LOG_INFO, "MP_RegisterForObjectVisibilityChangesPlugin()",
+ " - error exit");
+
+ return (MP_STATUS_INVALID_PARAMETER);
+ }
+
+ if (objectType < 1) {
+
+ log(LOG_INFO, "MP_RegisterForObjectVisibilityChangesPlugin()",
+ " - objectType is invalid");
+
+ log(LOG_INFO, "MP_RegisterForObjectVisibilityChangesPlugin()",
+ " - error exit");
+
+ return (MP_STATUS_INVALID_PARAMETER);
+ }
+
+ /* Check to see if we are going to be replacing */
+ (void) pthread_mutex_lock(&g_visa_mutex);
+ if (g_Visibility_Callback_List[objectType].pClientFn != NULL) {
+
+ hasFunc = MP_TRUE;
+ }
+
+ g_Visibility_Callback_List[objectType].pClientFn = pClientFn;
+ g_Visibility_Callback_List[objectType].pCallerData = pCallerData;
+ (void) pthread_mutex_unlock(&g_visa_mutex);
+
+ if (hasFunc) {
+
+ log(LOG_INFO, "MP_RegisterForObjectVisibilityChangesPlugin()",
+ " - returning MP_STATUS_FN_REPLACED");
+
+ return (MP_STATUS_FN_REPLACED);
+ }
+
+
+ log(LOG_INFO, "MP_RegisterForObjectVisibilityChangesPlugin()",
+ " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetFailbackPollingRateLu.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetFailbackPollingRateLu.c
new file mode 100644
index 0000000000..22c1f21a94
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetFailbackPollingRateLu.c
@@ -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.
+ */
+
+#include <syslog.h>
+
+#include "mp_utils.h"
+
+
+MP_STATUS
+MP_SetFailbackPollingRateLu(MP_OID oid, MP_UINT32 pollingRate)
+{
+ log(LOG_INFO, "MP_SetFailbackPollingRateLu()", " - enter");
+
+
+ log(LOG_INFO, "MP_SetFailbackPollingRateLu()",
+ " - oid.objectSequenceNumber: %llx",
+ oid.objectSequenceNumber);
+
+ log(LOG_INFO, "MP_SetFailbackPollingRateLu()",
+ " - pollingRate: %d",
+ pollingRate);
+
+
+ log(LOG_INFO, "MP_SetFailbackPollingRateLu()", " - exit");
+
+ return (MP_STATUS_UNSUPPORTED);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetFailbackPollingRatePlugin.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetFailbackPollingRatePlugin.c
new file mode 100644
index 0000000000..e27a28fb83
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetFailbackPollingRatePlugin.c
@@ -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.
+ */
+
+#include <syslog.h>
+
+#include "mp_utils.h"
+
+
+MP_STATUS
+MP_SetFailbackPollingRatePlugin(MP_UINT32 pollingRate)
+{
+ log(LOG_INFO, "MP_SetFailbackPollingRatePlugin()", " - enter");
+
+
+ log(LOG_INFO, "MP_SetFailbackPollingRatePlugin()",
+ " - pollingRate: %d",
+ pollingRate);
+
+
+ log(LOG_INFO, "MP_SetFailbackPollingRatePlugin()", " - exit");
+
+ return (MP_STATUS_UNSUPPORTED);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetLogicalUnitLoadBalanceType.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetLogicalUnitLoadBalanceType.c
new file mode 100644
index 0000000000..13006dcaee
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetLogicalUnitLoadBalanceType.c
@@ -0,0 +1,50 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <syslog.h>
+
+#include "mp_utils.h"
+
+
+MP_STATUS
+MP_SetLogicalUnitLoadBalanceType(MP_OID logicalUnitOid,
+ MP_LOAD_BALANCE_TYPE loadBalance)
+{
+ log(LOG_INFO, "MP_SetLogicalUnitLoadBalanceType()", " - enter");
+
+
+ log(LOG_INFO, "MP_SetLogicalUnitLoadBalanceType()",
+ " - logicalUnitOid.objectSequenceNumber: %llx",
+ logicalUnitOid.objectSequenceNumber);
+
+ log(LOG_INFO, "MP_SetLogicalUnitLoadBalanceType()",
+ " - loadBalance: %d",
+ loadBalance);
+
+
+ log(LOG_INFO, "MP_SetLogicalUnitLoadBalanceType()", " - exit");
+
+ return (MP_STATUS_UNSUPPORTED);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetOverridePath.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetOverridePath.c
new file mode 100644
index 0000000000..0ca5387efc
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetOverridePath.c
@@ -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.
+ */
+
+#include <syslog.h>
+
+#include "mp_utils.h"
+
+
+MP_STATUS
+MP_SetOverridePath(MP_OID logicalUnitOid, MP_OID pathOid)
+{
+ log(LOG_INFO, "MP_SetOverridePath()", " - enter");
+
+
+ log(LOG_INFO, "MP_SetOverridePath()",
+ " - logicalUnitOid.objectSequenceNumber: %llx",
+ logicalUnitOid.objectSequenceNumber);
+
+ log(LOG_INFO, "MP_SetOverridePath()",
+ " - pathOid.objectSequenceNumber: %llx",
+ pathOid.objectSequenceNumber);
+
+
+ log(LOG_INFO, "MP_SetOverridePath()", " - exit");
+
+ return (MP_STATUS_UNSUPPORTED);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetPathWeight.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetPathWeight.c
new file mode 100644
index 0000000000..2d22a8085b
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetPathWeight.c
@@ -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.
+ */
+
+#include <syslog.h>
+
+#include "mp_utils.h"
+
+
+MP_STATUS
+MP_SetPathWeight(MP_OID pathOid, MP_UINT32 weight)
+{
+ log(LOG_INFO, "MP_SetPathWeight()", " - enter");
+
+
+ log(LOG_INFO, "MP_SetPathWeight()",
+ " - pathOid.objectSequenceNumber: %llx",
+ pathOid.objectSequenceNumber);
+
+ log(LOG_INFO, "MP_SetPathWeight()",
+ " - weight: %d",
+ weight);
+
+
+ log(LOG_INFO, "MP_SetPathWeight()", " - exit");
+
+ return (MP_STATUS_UNSUPPORTED);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetPluginLBTypePlugin.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetPluginLBTypePlugin.c
new file mode 100644
index 0000000000..846d94113a
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetPluginLBTypePlugin.c
@@ -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.
+ */
+
+#include <syslog.h>
+
+#include "mp_utils.h"
+
+
+MP_STATUS
+MP_SetPluginLoadBalanceTypePlugin(MP_LOAD_BALANCE_TYPE loadBalance)
+{
+ log(LOG_INFO, "MP_SetPluginLoadBalanceTypePlugin()", " - enter");
+
+
+ log(LOG_INFO, "MP_SetPluginLoadBalanceTypePlugin()",
+ " - loadBalance: %d",
+ loadBalance);
+
+
+ log(LOG_INFO, "MP_SetPluginLoadBalanceTypePlugin()", " - exit");
+
+ return (MP_STATUS_UNSUPPORTED);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetProbingPollingRateLu.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetProbingPollingRateLu.c
new file mode 100644
index 0000000000..5688005b5f
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetProbingPollingRateLu.c
@@ -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.
+ */
+
+#include <syslog.h>
+
+#include "mp_utils.h"
+
+
+MP_STATUS
+MP_SetProbingPollingRateLu(MP_OID oid, MP_UINT32 pollingRate)
+{
+ log(LOG_INFO, "MP_SetProbingPollingRateLu()", " - enter");
+
+
+ log(LOG_INFO, "MP_SetProbingPollingRateLu()",
+ " - oid.objectSequenceNumber: %llx",
+ oid.objectSequenceNumber);
+
+ log(LOG_INFO, "MP_SetProbingPollingRateLu()",
+ " - pollingRate: %d",
+ pollingRate);
+
+
+ log(LOG_INFO, "MP_SetProbingPollingRateLu()", " - exit");
+
+ return (MP_STATUS_UNSUPPORTED);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetProbingPollingRatePlugin.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetProbingPollingRatePlugin.c
new file mode 100644
index 0000000000..a2fba5c93d
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetProbingPollingRatePlugin.c
@@ -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.
+ */
+
+#include <syslog.h>
+
+#include "mp_utils.h"
+
+
+MP_STATUS
+MP_SetProbingPollingRatePlugin(MP_UINT32 pollingRate)
+{
+ log(LOG_INFO, "MP_SetProbingPollingRatePlugin()", " - enter");
+
+
+ log(LOG_INFO, "MP_SetProbingPollingRatePlugin()",
+ " - pollingRate: %d",
+ pollingRate);
+
+
+ log(LOG_INFO, "MP_SetProbingPollingRatePlugin()", " - exit");
+
+ return (MP_STATUS_UNSUPPORTED);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetProprietaryProperties.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetProprietaryProperties.c
new file mode 100644
index 0000000000..9ff74ad24c
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetProprietaryProperties.c
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#include <syslog.h>
+
+#include "mp_utils.h"
+
+
+MP_STATUS
+MP_SetProprietaryProperties(MP_OID oid, MP_UINT32 count,
+ MP_PROPRIETARY_PROPERTY *pPropertyList)
+{
+ log(LOG_INFO, "MP_SetProprietaryProperties()", " - enter");
+
+
+ log(LOG_INFO, "MP_SetProprietaryProperties()",
+ " - oid.objectSequenceNumber: %llx",
+ oid.objectSequenceNumber);
+
+ log(LOG_INFO, "MP_SetProprietaryProperties()",
+ " - count: %d",
+ count);
+
+ log(LOG_INFO, "MP_SetProprietaryProperties()",
+ " - pPropertyList: %llx",
+ pPropertyList);
+
+
+ log(LOG_INFO, "MP_SetProprietaryProperties()", " - exit");
+
+ return (MP_STATUS_UNSUPPORTED);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetTPGAccess.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetTPGAccess.c
new file mode 100644
index 0000000000..1a8cdf9164
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/MP_SetTPGAccess.c
@@ -0,0 +1,207 @@
+/*
+ * 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.
+ */
+
+#include <string.h>
+#include <syslog.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stropts.h>
+
+
+#include "mp_utils.h"
+
+
+/*
+ * Called by the common layer to request the plugin to set the
+ * access state for a list of target port groups.
+ */
+
+MP_STATUS
+MP_SetTPGAccess(MP_OID oid, MP_UINT32 count,
+ MP_TPG_STATE_PAIR *pTpgStateList)
+{
+
+ MP_TPG_STATE_PAIR *head = pTpgStateList;
+
+ mp_iocdata_t mp_ioctl;
+ mp_set_tpg_state_req_t setTpgStateRequest;
+
+ int r = 0;
+
+ int ioctlStatus = 0;
+
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+
+
+ log(LOG_INFO, "MP_SetTPGAccess()", " - enter");
+
+
+ if (NULL == pTpgStateList) {
+
+ log(LOG_INFO, "MP_SetTPGAccess()",
+ "pTpgStateList is NULL");
+
+ return (MP_STATUS_INVALID_PARAMETER);
+ }
+
+
+ if (g_scsi_vhci_fd < 0) {
+ log(LOG_INFO, "MP_SetTPGAccess()",
+ "invalid driver file handle");
+ log(LOG_INFO, "MP_SetTPGAccess()", " - error exit");
+ return (MP_STATUS_FAILED);
+ }
+
+
+ log(LOG_INFO, "MP_SetTPGAccess()",
+ "oid.ownerId = %d",
+ oid.ownerId);
+
+ log(LOG_INFO, "MP_SetTPGAccess()",
+ "oid.objectType = %d",
+ oid.objectType);
+
+ log(LOG_INFO, "MP_SetTPGAccess()",
+ "oid.objectSequenceNumber = %llx",
+ oid.objectSequenceNumber);
+
+
+ log(LOG_INFO, "MP_SetTPGAccess()",
+ "count = %d",
+ count);
+
+
+ for (r = 0; r < count; r++) {
+
+ if (head->tpgOid.ownerId != g_pluginOwnerID) {
+
+ log(LOG_INFO, "MP_SetTPGAccess()",
+ "pTpgStateList->tpgOid.ownerId is not for"
+ " this plugin");
+
+ log(LOG_INFO, "MP_SetTPGAccess()",
+ "error exit");
+
+ return (MP_STATUS_INVALID_PARAMETER);
+ }
+
+ if (head->tpgOid.objectType !=
+ MP_OBJECT_TYPE_TARGET_PORT_GROUP) {
+
+ log(LOG_INFO, "MP_SetTPGAccess()",
+ "pTpgStateList->tpgOid.objectType is not"
+ " MP_OBJECT_TYPE_TARGET_PORT_GROUP");
+
+ log(LOG_INFO, "MP_SetTPGAccess()",
+ "error exit");
+
+ return (MP_STATUS_INVALID_PARAMETER);
+ }
+
+
+ head++;
+ }
+
+
+ head = pTpgStateList;
+
+ for (r = 0; r < count; r++) {
+
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+ (void) memset(&setTpgStateRequest, 0,
+ sizeof (mp_set_tpg_state_req_t));
+
+ setTpgStateRequest.desiredState
+ = head->desiredState;
+ setTpgStateRequest.luTpgPair.luId
+ = oid.objectSequenceNumber;
+ setTpgStateRequest.luTpgPair.tpgId
+ = head->tpgOid.objectSequenceNumber;
+
+ mp_ioctl.mp_cmd = MP_SET_TPG_ACCESS_STATE;
+ mp_ioctl.mp_ibuf = (caddr_t)&setTpgStateRequest;
+ mp_ioctl.mp_ilen = sizeof (mp_set_tpg_state_req_t);
+ mp_ioctl.mp_xfer = MP_XFER_WRITE;
+
+ log(LOG_INFO, "MP_SetTPGAccess()",
+ "mp_ioctl.mp_cmd (MP_SET_TPG_ACCESS_STATE) : %d",
+ mp_ioctl.mp_cmd);
+
+ log(LOG_INFO, "MP_SetTPGAccess()",
+ "setTpgStateRequest.luTpgPair.luId = %llx",
+ setTpgStateRequest.luTpgPair.luId);
+
+ log(LOG_INFO, "MP_SetTPGAccess()",
+ "setTpgStateRequest.luTpgPair.tpgId = %llx",
+ setTpgStateRequest.luTpgPair.tpgId);
+
+ log(LOG_INFO, "MP_SetTPGAccess()",
+ "setTpgStateRequest.desiredState = %d",
+ setTpgStateRequest.desiredState);
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+
+ log(LOG_INFO, "MP_SetTPGAccess()",
+ " IOCTL call returned: %d", ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if (ioctlStatus != 0) {
+ log(LOG_INFO, "MP_SetTPGAccess()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO, "MP_SetTPGAccess()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO, "MP_SetTPGAccess()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+ if (ENOTSUP == ioctlStatus) {
+ mpStatus = MP_STATUS_UNSUPPORTED;
+ } else if (0 == mp_ioctl.mp_errno) {
+ mpStatus = MP_STATUS_FAILED;
+ } else {
+ mpStatus =
+ getStatus4ErrorCode(mp_ioctl.mp_errno);
+ }
+
+ log(LOG_INFO, "MP_SetTPGAccess()",
+ " - error exit");
+
+ return (mpStatus);
+ }
+
+ head++;
+ }
+
+
+ log(LOG_INFO, "MP_SetTPGAccess()", " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/Sun_MP_SendScsiCmd.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/Sun_MP_SendScsiCmd.c
new file mode 100644
index 0000000000..b78705784e
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/Sun_MP_SendScsiCmd.c
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+
+#include <syslog.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stropts.h>
+#include <sys/scsi/impl/uscsi.h>
+
+#include "mp_utils.h"
+
+
+/*
+ * Called by the common layer to request to steer a path
+ */
+
+MP_STATUS
+Sun_MP_SendScsiCmd(MP_OID pathOid, struct uscsi_cmd *cmd)
+{
+ mp_iocdata_t mp_ioctl;
+
+ int ioctlStatus = 0;
+
+ MP_STATUS mpStatus = MP_STATUS_SUCCESS;
+
+ log(LOG_INFO, "Sun_MP_SendScsiCmd()", " - enter");
+
+ log(LOG_INFO, "Sun_MP_SendScsiCmd()",
+ "pathOid.objectSequenceNumber = %llx",
+ pathOid.objectSequenceNumber);
+
+ if (g_scsi_vhci_fd < 0) {
+ log(LOG_INFO, "Sun_MP_SendScsiCmd()",
+ "invalid driver file handle");
+ log(LOG_INFO, "Sun_MP_SendScsiCmd()", " - error exit");
+ return (MP_STATUS_FAILED);
+ }
+
+ (void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
+
+ mp_ioctl.mp_cmd = MP_SEND_SCSI_CMD;
+ mp_ioctl.mp_ibuf = (caddr_t)&pathOid.objectSequenceNumber;
+ mp_ioctl.mp_ilen = sizeof (pathOid.objectSequenceNumber);
+ mp_ioctl.mp_xfer =
+ ((cmd->uscsi_flags & USCSI_READ) ? MP_XFER_READ : MP_XFER_WRITE);
+ mp_ioctl.mp_obuf = (char *)cmd;
+ mp_ioctl.mp_olen = sizeof (*cmd);
+
+ log(LOG_INFO, "Sun_MP_SendScsiCmd()",
+ "mp_ioctl.mp_cmd (MP_SEND_SCSI_CMD) : %d",
+ mp_ioctl.mp_cmd);
+
+ ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
+
+ log(LOG_INFO, "Sun_MP_SendScsiCmd()",
+ " IOCTL call returned: %d", ioctlStatus);
+
+ if (ioctlStatus < 0) {
+ ioctlStatus = errno;
+ }
+
+ if (ioctlStatus != 0) {
+ log(LOG_INFO, "Sun_MP_SendScsiCmd()",
+ "IOCTL call failed. IOCTL error is: %d",
+ ioctlStatus);
+ log(LOG_INFO, "Sun_MP_SendScsiCmd()",
+ "IOCTL call failed. IOCTL error is: %s",
+ strerror(ioctlStatus));
+ log(LOG_INFO, "Sun_MP_SendScsiCmd()",
+ "IOCTL call failed. mp_ioctl.mp_errno: %x",
+ mp_ioctl.mp_errno);
+
+ if (ENOTSUP == ioctlStatus) {
+ mpStatus = MP_STATUS_UNSUPPORTED;
+ } else if (EPERM == ioctlStatus) {
+ mpStatus = MP_STATUS_NOT_PERMITTED;
+ } else if (0 == mp_ioctl.mp_errno) {
+ mpStatus = MP_STATUS_FAILED;
+ } else {
+ mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno);
+ }
+
+ log(LOG_INFO, "Sun_MP_SendScsiCmd()",
+ " - error exit");
+
+ return (mpStatus);
+ }
+
+
+ log(LOG_INFO, "Sun_MP_SendScsiCmd()", " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/Terminate.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/Terminate.c
new file mode 100644
index 0000000000..fc1e72713a
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/Terminate.c
@@ -0,0 +1,53 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <syslog.h>
+#include <unistd.h>
+
+#include "mp_utils.h"
+
+
+MP_STATUS
+Terminate(void)
+{
+ log(LOG_INFO, "Terminate()", " - enter");
+
+
+ if (g_scsi_vhci_fd > -1) {
+ (void) close(g_scsi_vhci_fd);
+ }
+
+ if (NULL != g_SysEventHandle) {
+
+ sysevent_unbind_handle(g_SysEventHandle);
+ }
+
+ (void) pthread_mutex_destroy(&g_visa_mutex);
+ (void) pthread_mutex_destroy(&g_prop_mutex);
+
+ log(LOG_INFO, "Terminate()", " - exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/debug_logging.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/debug_logging.c
new file mode 100644
index 0000000000..7f0703ac30
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/debug_logging.c
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+#include <stdio.h>
+#include <sys/varargs.h>
+#include <syslog.h>
+#include <time.h>
+#include <string.h>
+#include <errno.h>
+
+#define MAX_LOG_LEN 2048
+
+
+void
+log(int priority, const char *routine, char *msg, ...)
+{
+ char header[MAX_LOG_LEN+1];
+ char message[MAX_LOG_LEN+1];
+ int oldErrno = 0;
+ va_list ap;
+
+
+ oldErrno = errno;
+
+ (void) memset(&header, 0, MAX_LOG_LEN+1);
+ (void) memset(&message, 0, MAX_LOG_LEN+1);
+
+ (void) va_start(ap, msg);
+
+ (void) snprintf(header, MAX_LOG_LEN, "%s: %s: %s",
+ "MP-API (SUN) Plugin",
+ routine,
+ msg);
+
+ /* LINTED E_SEC_PRINTF_VAR_FMT */
+ (void) vsnprintf(message, MAX_LOG_LEN, header, ap);
+ /* LINTED E_SEC_PRINTF_VAR_FMT */
+ (void) syslog(LOG_USER|LOG_DEBUG, message);
+
+ (void) va_end(ap);
+
+ errno = oldErrno;
+
+ oldErrno = priority;
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/mapfile-vers b/usr/src/lib/mpapi/libmpscsi_vhci/common/mapfile-vers
new file mode 100644
index 0000000000..07d617465c
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/mapfile-vers
@@ -0,0 +1,87 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+SUNW_1.1 {
+ global:
+ Initialize;
+ Terminate;
+ MP_GetPluginPropertiesPlugin;
+ MP_GetDeviceProductOidListPlugin;
+ MP_GetDeviceProductProperties;
+ MP_GetInitiatorPortOidListPlugin;
+ MP_GetInitiatorPortProperties;
+ MP_GetMultipathLusPlugin;
+ MP_GetMultipathLusDevProd;
+ MP_GetMPLogicalUnitProperties;
+ MP_GetAssociatedPathOidList;
+ MP_GetPathLogicalUnitProperties;
+ MP_GetAssociatedTPGOidList;
+ MP_GetTargetPortGroupProperties;
+ MP_GetMPLuOidListFromTPG;
+ MP_GetProprietaryLoadBalanceOidListPlugin;
+ MP_GetProprietaryLoadBalanceProperties;
+ MP_GetTargetPortOidList;
+ MP_GetTargetPortProperties;
+ MP_GetTargetPortGroupProperties;
+ MP_AssignLogicalUnitToTPG;
+ MP_SetOverridePath;
+ MP_CancelOverridePath;
+ MP_EnableAutoFailbackPlugin;
+ MP_EnableAutoFailbackLu;
+ MP_DisableAutoFailbackPlugin;
+ MP_DisableAutoFailbackLu;
+ MP_EnableAutoProbingPlugin;
+ MP_EnableAutoProbingLu;
+ MP_DisableAutoProbingPlugin;
+ MP_DisableAutoProbingLu;
+ MP_EnablePath;
+ MP_DisablePath;
+ MP_SetLogicalUnitLoadBalanceType;
+ MP_SetPluginLoadBalanceTypePlugin;
+ MP_SetPathWeight;
+ MP_SetFailbackPollingRatePlugin;
+ MP_SetFailbackPollingRateLu;
+ MP_SetProbingPollingRatePlugin;
+ MP_SetProbingPollingRateLu;
+ MP_SetProprietaryProperties;
+ MP_SetTPGAccess;
+ MP_RegisterForObjectPropertyChangesPlugin;
+ MP_DeregisterForObjectPropertyChangesPlugin;
+ MP_RegisterForObjectVisibilityChangesPlugin;
+ MP_DeregisterForObjectVisibilityChangesPlugin;
+ Sun_MP_SendScsiCmd;
+ local:
+ *;
+};
+
+SUNWprivate_1.1 {
+ global:
+ init_sysevents;
+ log;
+ getStatus4ErrorCode;
+ createOidList;
+ local:
+ *;
+};
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/mp_utils.c b/usr/src/lib/mpapi/libmpscsi_vhci/common/mp_utils.c
new file mode 100644
index 0000000000..37ba6b2d2f
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/mp_utils.c
@@ -0,0 +1,675 @@
+/*
+ * 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.
+ */
+
+#include "mp_utils.h"
+#include <sys/sunddi.h>
+
+#ifndef OIDLIST
+#define OIDLIST "oid"
+#endif
+
+
+/* Remove these 5 when this source can compile with sunddi.h */
+#ifndef EC_DDI
+#define EC_DDI "EC_ddi"
+#endif
+
+#ifndef ESC_DDI_INITIATOR_REGISTER
+#define ESC_DDI_INITIATOR_REGISTER "ESC_ddi_initiator_register"
+#endif
+
+#ifndef ESC_DDI_INITIATOR_UNREGISTER
+#define ESC_DDI_INITIATOR_UNREGISTER "ESC_ddi_initiator_unregister"
+#endif
+
+#ifndef DDI_DRIVER_MAJOR
+#define DDI_DRIVER_MAJOR "ddi.major"
+#endif
+
+#ifndef DDI_INSTANCE
+#define DDI_INSTANCE "ddi.instance"
+#endif
+
+
+#define VISA_CHANGE 1
+#define PROP_CHANGE 2
+
+
+
+MP_STATUS
+getStatus4ErrorCode(int driverError)
+{
+ MP_STATUS mpStatus = MP_STATUS_FAILED;
+
+ log(LOG_INFO, "getStatus4ErrorCode()", "- enter");
+
+ switch (driverError) {
+
+ case MP_DRVR_INVALID_ID:
+ log(LOG_INFO, "getStatus4ErrorCode()",
+ " received mp_errno=MP_DRVR_INVALID_ID"
+ " from driver call.");
+ log(LOG_INFO, "getStatus4ErrorCode()",
+ " returning MP_STATUS_OBJECT_NOT_FOUND"
+ " to caller.");
+ mpStatus = MP_STATUS_OBJECT_NOT_FOUND;
+ break;
+
+
+ case MP_DRVR_ID_OBSOLETE:
+ log(LOG_INFO, "getStatus4ErrorCode()",
+ " received mp_errno=MP_DRVR_ID_OBSOLETE"
+ " from driver call.");
+ log(LOG_INFO, "getStatus4ErrorCode()",
+ " returning MP_STATUS_OBJECT_NOT_FOUND"
+ " to caller.");
+ mpStatus = MP_STATUS_OBJECT_NOT_FOUND;
+ break;
+
+
+ case MP_DRVR_ACCESS_SYMMETRIC:
+ log(LOG_INFO, "getStatus4ErrorCode()",
+ " received mp_errno=MP_DRVR_ACCESS_SYMMETRIC"
+ " from driver call.");
+ log(LOG_INFO, "getStatus4ErrorCode()",
+ " returning MP_STATUS_INVALID_PARAMETER"
+ " to caller.");
+ mpStatus = MP_STATUS_INVALID_PARAMETER;
+ break;
+
+
+ case MP_DRVR_PATH_UNAVAILABLE:
+ log(LOG_INFO, "getStatus4ErrorCode()",
+ " received mp_errno=MP_DRVR_PATH_UNAVAILABLE"
+ " from driver call.");
+ log(LOG_INFO, "getStatus4ErrorCode()",
+ " returning MP_STATUS_PATH_NONOPERATIONAL"
+ " to caller.");
+ mpStatus = MP_STATUS_PATH_NONOPERATIONAL;
+ break;
+
+
+ case MP_DRVR_IDS_NOT_ASSOCIATED:
+ log(LOG_INFO, "getStatus4ErrorCode()",
+ " received mp_errno=MP_DRVR_IDS_NOT_ASSOCIATED"
+ " from driver call.");
+ log(LOG_INFO, "getStatus4ErrorCode()",
+ " returning MP_STATUS_INVALID_PARAMETER"
+ " to caller.");
+ mpStatus = MP_STATUS_INVALID_PARAMETER;
+ break;
+
+
+ case MP_DRVR_ILLEGAL_ACCESS_STATE_REQUEST:
+ log(LOG_INFO, "getStatus4ErrorCode()",
+ " received mp_errno="
+ "MP_DRVR_ILLEGAL_ACCESS_STATE_REQUEST"
+ " from driver call.");
+ log(LOG_INFO, "getStatus4ErrorCode()",
+ " returning MP_STATUS_INVALID_PARAMETER"
+ " to caller.");
+ mpStatus = MP_STATUS_ACCESS_STATE_INVALID;
+ break;
+
+
+ default:
+ log(LOG_INFO, "getStatus4ErrorCode()",
+ " - received (unsupported) mp_errno=%d from"
+ " driver call.", driverError);
+ log(LOG_INFO, "getStatus4ErrorCode()",
+ " - returning MP_STATUS_FAILED to caller.");
+ mpStatus = MP_STATUS_FAILED;
+ }
+
+ log(LOG_INFO, "getStatus4ErrorCode()", "- exit");
+
+ return (mpStatus);
+}
+
+
+
+MP_OID_LIST
+*createOidList(int size) {
+
+ MP_OID_LIST *pOidList = NULL;
+
+
+ log(LOG_INFO, "createOidList()", "- enter");
+
+
+ if (size < 1) {
+
+ log(LOG_INFO, "createOidList()",
+ "requested size is less than 1");
+ log(LOG_INFO, "createOidList()",
+ " - error exit");
+ return (NULL);
+
+ } else {
+
+ pOidList = (MP_OID_LIST*)calloc(1,
+ sizeof (MP_OID_LIST) +
+ ((size - 1) *
+ sizeof (MP_OID)));
+
+ if (NULL == pOidList) {
+ log(LOG_INFO, "createOidList()",
+ "no memory for pOidList");
+ log(LOG_INFO, "createOidList()",
+ " - error exit");
+ return (NULL);
+ }
+
+ log(LOG_INFO,
+ "createOidList()",
+ "- exit(%d)",
+ size);
+
+ return (pOidList);
+ }
+}
+
+/* Calls the client callback function, if one is registered */
+static void
+notifyClient(sysevent_t *ev)
+{
+ nvlist_t *attr_list = NULL;
+
+ uint64_t *val = NULL;
+ int32_t *instance = NULL;
+ int32_t *major = NULL;
+
+ int valAllocated = 0;
+
+ uint_t nelem = 0;
+
+ int i = 0;
+ int eventType = 0;
+ int index = -1;
+
+ void *pCallerData = NULL;
+
+ char subClassName[256];
+
+ MP_BOOL becomingVisible = MP_FALSE;
+
+ MP_OID_LIST *oidList = NULL;
+
+
+ log(LOG_INFO, "notifyClient()", "- enter");
+
+
+ (void) strncpy(subClassName, sysevent_get_subclass_name(ev), 256);
+
+ if (strstr(subClassName, "change")) {
+
+ eventType = PROP_CHANGE;
+
+ log(LOG_INFO, "notifyClient()", "- got a change event");
+ log(LOG_INFO, "notifyClient()", ": [%s]",
+ subClassName);
+
+ if (strncmp(subClassName, ESC_SUN_MP_LU_CHANGE, 255) == 0) {
+
+ index = MP_OBJECT_TYPE_MULTIPATH_LU;
+
+ } else if (strncmp(subClassName, ESC_SUN_MP_PATH_CHANGE, 255)
+ == 0) {
+
+ index = MP_OBJECT_TYPE_PATH_LU;
+
+ } else if (strncmp(subClassName, ESC_SUN_MP_INIT_PORT_CHANGE,
+ 255) == 0) {
+
+ index = MP_OBJECT_TYPE_INITIATOR_PORT;
+
+ } else if (strncmp(subClassName, ESC_SUN_MP_TPG_CHANGE, 255)
+ == 0) {
+
+ index = MP_OBJECT_TYPE_TARGET_PORT_GROUP;
+
+ } else if (strncmp(subClassName, ESC_SUN_MP_TARGET_PORT_CHANGE,
+ 255) == 0) {
+
+ index = MP_OBJECT_TYPE_TARGET_PORT;
+
+ } else if (strncmp(subClassName, ESC_SUN_MP_DEV_PROD_CHANGE,
+ 255) == 0) {
+
+ index = MP_OBJECT_TYPE_DEVICE_PRODUCT;
+ }
+
+ } else if ((strstr(subClassName, "add")) ||
+ (strstr(subClassName, "initiator_register"))) {
+
+ eventType = VISA_CHANGE;
+ becomingVisible = MP_TRUE;
+
+ log(LOG_INFO, "notifyClient()", "- got a visibility"
+ " add event");
+ log(LOG_INFO, "notifyClient()", ": [%s]",
+ subClassName);
+
+ if (strncmp(subClassName, ESC_DEVFS_DEVI_ADD, 255) == 0) {
+
+ index = MP_OBJECT_TYPE_MULTIPATH_LU;
+
+ } else if (strncmp(subClassName, ESC_SUN_MP_PATH_ADD, 255)
+ == 0) {
+
+ index = MP_OBJECT_TYPE_PATH_LU;
+
+ } else if (strncmp(subClassName, ESC_DDI_INITIATOR_REGISTER,
+ 244) == 0) {
+
+ index = MP_OBJECT_TYPE_INITIATOR_PORT;
+
+ } else if (strncmp(subClassName, ESC_SUN_MP_TPG_ADD,
+ 255) == 0) {
+
+ index = MP_OBJECT_TYPE_TARGET_PORT_GROUP;
+
+ } else if (strncmp(subClassName, ESC_SUN_MP_TARGET_PORT_ADD,
+ 255) == 0) {
+
+ index = MP_OBJECT_TYPE_TARGET_PORT;
+
+ } else if (strncmp(subClassName, ESC_SUN_MP_DEV_PROD_ADD, 255)
+ == 0) {
+
+ index = MP_OBJECT_TYPE_DEVICE_PRODUCT;
+ }
+
+
+ } else if ((strstr(subClassName, "remove")) ||
+ (strstr(subClassName, "initiator_unregister"))) {
+
+ eventType = VISA_CHANGE;
+ becomingVisible = MP_FALSE;
+
+ log(LOG_INFO, "notifyClient()", "- got a visibility"
+ " remove event");
+ log(LOG_INFO, "notifyClient()", ": [%s]",
+ subClassName);
+
+ if (strncmp(subClassName, ESC_DEVFS_DEVI_REMOVE, 255) == 0) {
+
+ index = MP_OBJECT_TYPE_MULTIPATH_LU;
+
+ } else if (strncmp(subClassName, ESC_SUN_MP_PATH_REMOVE, 255)
+ == 0) {
+
+ index = MP_OBJECT_TYPE_PATH_LU;
+
+ } else if (strncmp(subClassName, ESC_DDI_INITIATOR_UNREGISTER,
+ 255) == 0) {
+
+ index = MP_OBJECT_TYPE_INITIATOR_PORT;
+
+ } else if (strncmp(subClassName, ESC_SUN_MP_TPG_REMOVE, 255)
+ == 0) {
+
+ index = MP_OBJECT_TYPE_TARGET_PORT_GROUP;
+
+ } else if (strncmp(subClassName, ESC_SUN_MP_TARGET_PORT_REMOVE,
+ 255) == 0) {
+
+ index = MP_OBJECT_TYPE_TARGET_PORT;
+
+ } else if (strncmp(subClassName, ESC_SUN_MP_DEV_PROD_REMOVE,
+ 255) == 0) {
+
+ index = MP_OBJECT_TYPE_DEVICE_PRODUCT;
+ }
+
+
+ } else {
+ log(LOG_INFO, "notifyClient()", "- got an unsupported event");
+ return;
+ }
+
+ if (index < 0) {
+
+ log(LOG_INFO, "notifyClient()", "- index is less than zero");
+ return;
+ }
+
+ if (eventType == VISA_CHANGE) {
+
+ (void) pthread_mutex_lock(&g_visa_mutex);
+
+ if (NULL == g_Visibility_Callback_List[index].pClientFn) {
+
+ log(LOG_INFO, "notifyClient()",
+ "- no visibility change callback to notify");
+
+ (void) pthread_mutex_unlock(&g_visa_mutex);
+
+ return;
+ }
+
+ (void) pthread_mutex_unlock(&g_visa_mutex);
+ }
+
+ if (eventType == PROP_CHANGE) {
+
+ (void) pthread_mutex_lock(&g_prop_mutex);
+
+ if (NULL == g_Property_Callback_List[index].pClientFn) {
+
+ log(LOG_INFO, "notifyClient()",
+ "- no property change callback to notify");
+
+ (void) pthread_mutex_unlock(&g_prop_mutex);
+
+ return;
+ }
+
+ (void) pthread_mutex_unlock(&g_prop_mutex);
+ }
+
+ (void) sysevent_get_attr_list(ev, &attr_list);
+ if (NULL != attr_list) {
+
+ if ((VISA_CHANGE == eventType) &&
+ (MP_OBJECT_TYPE_MULTIPATH_LU == index)) {
+
+ (void) nvlist_lookup_int32_array(attr_list,
+ DEVFS_INSTANCE, &instance, &nelem);
+
+ log(LOG_INFO, "notifyClient()",
+ "- event has [%d] elements",
+ nelem);
+
+ if (NULL != instance) {
+
+ val = (uint64_t *)malloc(sizeof (uint64_t));
+
+ valAllocated = 1;
+
+ *val = *instance;
+ nelem = 1;
+
+ } else {
+
+ nelem = 0;
+ }
+
+ } else if ((VISA_CHANGE == eventType) &&
+ (MP_OBJECT_TYPE_INITIATOR_PORT == index)) {
+
+ (void) nvlist_lookup_int32_array(attr_list,
+ DDI_INSTANCE, &instance, &nelem);
+
+ log(LOG_INFO, "notifyClient()",
+ "- event (PHCI_INSTANCE) has [%d] elements",
+ nelem);
+
+ (void) nvlist_lookup_int32_array(attr_list,
+ DDI_DRIVER_MAJOR, &major, &nelem);
+
+ log(LOG_INFO, "notifyClient()",
+ "- event (PHCI_DRIVER_MAJOR) has [%d] elements",
+ nelem);
+
+ if ((NULL != instance) & (NULL != major)) {
+
+ val = (uint64_t *)malloc(sizeof (uint64_t));
+
+ valAllocated = 1;
+
+ *val = MP_STORE_INST_TO_ID(*instance, *val);
+ *val = MP_STORE_MAJOR_TO_ID(*major, *val);
+
+ nelem = 1;
+
+ } else {
+
+ nelem = 0;
+ }
+
+ } else {
+
+ (void) nvlist_lookup_uint64_array(attr_list, OIDLIST,
+ &val, &nelem);
+
+ log(LOG_INFO, "notifyClient()",
+ "- event has [%d] elements",
+ nelem);
+ }
+
+ if (nelem > 0) {
+
+ for (i = 0; i < nelem; i++) {
+
+ log(LOG_INFO, "notifyClient()",
+ "- event [%d] = %llx",
+ i, val[i]);
+ }
+
+ oidList = createOidList(nelem);
+ if (NULL == oidList) {
+
+ log(LOG_INFO, "notifyClient()",
+ "- unable to create MP_OID_LIST");
+
+ log(LOG_INFO, "notifyClient()",
+ "- error exit");
+
+ nvlist_free(attr_list);
+
+ return;
+ }
+
+ oidList->oidCount = nelem;
+
+ for (i = 0; i < nelem; i++) {
+
+ oidList->oids[i].objectType = index;
+ oidList->oids[i].ownerId = g_pluginOwnerID;
+ oidList->oids[i].objectSequenceNumber = val[i];
+ }
+
+ if (valAllocated) {
+
+ free(val);
+ }
+
+ for (i = 0; i < oidList->oidCount; i++) {
+
+ log(LOG_INFO, "notifyClient()",
+ "oidList->oids[%d].objectType"
+ " = %d",
+ i, oidList->oids[i].objectType);
+ log(LOG_INFO, "notifyClient()",
+ "oidList->oids[%d].ownerId"
+ " = %d",
+ i, oidList->oids[i].ownerId);
+ log(LOG_INFO, "notifyClient()",
+ "oidList->oids[%d].objectSequenceNumber"
+ " = %llx",
+ i,
+ oidList->oids[i].objectSequenceNumber);
+ }
+
+ if (eventType == PROP_CHANGE) {
+
+ (void) pthread_mutex_lock(&g_prop_mutex);
+
+ pCallerData = g_Property_Callback_List[index].
+ pCallerData;
+
+ (g_Property_Callback_List[index].pClientFn)
+ (oidList, pCallerData);
+
+ (void) pthread_mutex_unlock(&g_prop_mutex);
+
+ } else if (eventType == VISA_CHANGE) {
+
+ (void) pthread_mutex_lock(&g_visa_mutex);
+
+ pCallerData = g_Visibility_Callback_List[index].
+ pCallerData;
+
+ (g_Visibility_Callback_List[index].pClientFn)
+ (becomingVisible, oidList, pCallerData);
+
+ (void) pthread_mutex_unlock(&g_visa_mutex);
+
+ }
+ }
+
+ nvlist_free(attr_list);
+ }
+
+
+ log(LOG_INFO, "notifyClient()", "- exit");
+}
+
+/* Event handler called by system */
+static void
+sysevent_handler(sysevent_t *ev)
+{
+ log(LOG_INFO, "sysevent_handler()", "- enter");
+
+ /* Is the event one of ours? */
+ if ((strncmp(EC_SUN_MP, sysevent_get_class_name(ev), 9) != 0) &&
+ (strncmp(EC_DEVFS, sysevent_get_class_name(ev), 8) != 0) &&
+ (strncmp(EC_DDI, sysevent_get_class_name(ev), 6) != 0)) {
+
+ return;
+ }
+
+ /* Notify client if it cares */
+ notifyClient(ev);
+
+
+ log(LOG_INFO, "sysevent_handler()", "- exit");
+}
+
+/* Registers the plugin to the sysevent framework */
+MP_STATUS init_sysevents() {
+
+ const char *subclass_list[] = {
+
+ ESC_SUN_MP_LU_CHANGE,
+
+ ESC_SUN_MP_PATH_CHANGE,
+ ESC_SUN_MP_PATH_ADD,
+ ESC_SUN_MP_PATH_REMOVE,
+
+ ESC_SUN_MP_INIT_PORT_CHANGE,
+
+ ESC_SUN_MP_TPG_CHANGE,
+ ESC_SUN_MP_TPG_ADD,
+ ESC_SUN_MP_TPG_REMOVE,
+
+ ESC_SUN_MP_TARGET_PORT_CHANGE,
+ ESC_SUN_MP_TARGET_PORT_ADD,
+ ESC_SUN_MP_TARGET_PORT_REMOVE,
+
+ ESC_SUN_MP_DEV_PROD_CHANGE,
+ ESC_SUN_MP_DEV_PROD_ADD,
+ ESC_SUN_MP_DEV_PROD_REMOVE
+
+ };
+
+ const char *lu_subclass_list[] = {
+
+ ESC_DEVFS_DEVI_ADD,
+ ESC_DEVFS_DEVI_REMOVE
+
+ };
+
+ const char *init_port_subclass_list[] = {
+
+ ESC_DDI_INITIATOR_REGISTER,
+ ESC_DDI_INITIATOR_UNREGISTER
+ };
+
+
+
+ log(LOG_INFO, "init_sysevents()", "- enter");
+
+
+ g_SysEventHandle = sysevent_bind_handle(sysevent_handler);
+ if (g_SysEventHandle == NULL) {
+
+ log(LOG_INFO, "init_sysevents()",
+ "- sysevent_bind_handle() failed");
+
+ log(LOG_INFO, "init_sysevents()", "- error exit");
+
+ return (MP_STATUS_FAILED);
+ }
+
+ if (sysevent_subscribe_event(g_SysEventHandle, EC_SUN_MP,
+ subclass_list, 14) != 0) {
+
+
+ log(LOG_INFO, "init_sysevents()",
+ "- sysevent_subscribe_event() failed for subclass_list");
+
+ log(LOG_INFO, "init_sysevents()", "- error exit");
+
+ sysevent_unbind_handle(g_SysEventHandle);
+
+ return (MP_STATUS_FAILED);
+ }
+
+ if (sysevent_subscribe_event(g_SysEventHandle, EC_DEVFS,
+ lu_subclass_list, 2) != 0) {
+
+
+ log(LOG_INFO, "init_sysevents()",
+ "- sysevent_subscribe_event() failed for lu_subclass_list");
+
+ log(LOG_INFO, "init_sysevents()", "- error exit");
+
+ sysevent_unbind_handle(g_SysEventHandle);
+
+ return (MP_STATUS_FAILED);
+ }
+
+ if (sysevent_subscribe_event(g_SysEventHandle, EC_DDI,
+ init_port_subclass_list, 2) != 0) {
+
+
+ log(LOG_INFO, "init_sysevents()",
+ "- sysevent_subscribe_event() failed "
+ "for init_port_subclass_list");
+
+ log(LOG_INFO, "init_sysevents()", "- error exit");
+
+ sysevent_unbind_handle(g_SysEventHandle);
+
+ return (MP_STATUS_FAILED);
+ }
+
+
+ log(LOG_INFO, "init_sysevents()", "- exit");
+
+ return (MP_STATUS_SUCCESS);
+}
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/common/mp_utils.h b/usr/src/lib/mpapi/libmpscsi_vhci/common/mp_utils.h
new file mode 100644
index 0000000000..411043098c
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/common/mp_utils.h
@@ -0,0 +1,117 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#ifndef _MP_UTILS_H
+#define _MP_UTILS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <mpapi.h>
+#include <sys/scsi/adapters/mpapi_impl.h>
+
+#include <sys/types.h>
+#include <libsysevent.h>
+#include <syslog.h>
+#include <pthread.h>
+
+/* Default bytes */
+#define DEFAULT_BUFFER_SIZE_LU_LIST 4096
+#define DEFAULT_BUFFER_SIZE_INIT_PORT_LIST 1024
+#define DEFAULT_BUFFER_SIZE_PATH_LIST 1024
+#define DEFAULT_BUFFER_SIZE_DEV_PROD 1024
+#define DEFAULT_BUFFER_SIZE_TPG 1024
+#define DEFAULT_BUFFER_SIZE_LOADBALANCE 1024
+
+
+/* Node to hold pointer to client callback */
+typedef struct _property_node
+{
+ MP_OBJECT_PROPERTY_FN pClientFn;
+ void *pCallerData;
+
+} PROPERTY_CALLBACK_NODE;
+
+
+/* Node to hold pointer to client callback */
+typedef struct _visibility_node
+{
+ MP_OBJECT_VISIBILITY_FN pClientFn;
+ void *pCallerData;
+
+} VISIBILITY_CALLBACK_NODE;
+
+
+/* Global array to hold client callbacks */
+extern
+PROPERTY_CALLBACK_NODE g_Property_Callback_List[MP_OBJECT_TYPE_MAX + 1];
+
+/* Global array to hold client callbacks */
+extern
+VISIBILITY_CALLBACK_NODE g_Visibility_Callback_List[MP_OBJECT_TYPE_MAX + 1];
+
+
+/* Global variable to hold this pligin's ID */
+extern MP_UINT32 g_pluginOwnerID;
+
+/* Global variable to hold scsi_vhci file descriptor */
+extern int g_scsi_vhci_fd;
+
+/* Global variable to hold sysevent handle */
+extern sysevent_handle_t *g_SysEventHandle;
+
+/* Mutexes to make array modify/read thread safe */
+extern pthread_mutex_t g_visa_mutex;
+extern pthread_mutex_t g_prop_mutex;
+
+
+
+/* Used to add debug (log) info */
+void log(int priority, const char *routine, char *msg, ...);
+
+/* Returns an MP_STATUS code for an mp_iocdata_t.mp_errno code */
+MP_STATUS getStatus4ErrorCode(int driverError);
+
+/* Returns an MP_OID_LIST that will hold "size" MP_OID elements */
+MP_OID_LIST *createOidList(int size);
+
+/* Initializes the sysevent framework */
+MP_STATUS init_sysevents();
+
+/* Implementation function for MP_GetAssociatedTPGOidList() */
+MP_STATUS getAssociatedTPGOidList(MP_OID oid, MP_OID_LIST **ppList);
+
+/* Implementation function for MP_GetTargetPortGroupProperties() */
+MP_STATUS getTargetPortGroupProperties(MP_OID oid,
+ MP_TARGET_PORT_GROUP_PROPERTIES *pProps);
+
+/* Implementation function for MP_GetTargetPortOidList() */
+MP_STATUS getTargetPortOidList(MP_OID oid, MP_OID_LIST **ppList);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MP_UTILS_H */
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/i386/Makefile b/usr/src/lib/mpapi/libmpscsi_vhci/i386/Makefile
new file mode 100644
index 0000000000..4acb0bde30
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/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.
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS)
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/sparc/Makefile b/usr/src/lib/mpapi/libmpscsi_vhci/sparc/Makefile
new file mode 100644
index 0000000000..4acb0bde30
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/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.
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS)
diff --git a/usr/src/lib/mpapi/libmpscsi_vhci/sparcv9/Makefile b/usr/src/lib/mpapi/libmpscsi_vhci/sparcv9/Makefile
new file mode 100644
index 0000000000..bbc20fa470
--- /dev/null
+++ b/usr/src/lib/mpapi/libmpscsi_vhci/sparcv9/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.
+#
+
+include ../Makefile.com
+include ../../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)