summaryrefslogtreecommitdiff
path: root/usr/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib')
-rw-r--r--usr/src/lib/Makefile3
-rw-r--r--usr/src/lib/libsecdb/exec_attr.txt1
-rw-r--r--usr/src/lib/smhba/Makefile59
-rw-r--r--usr/src/lib/smhba/Makefile.com64
-rw-r--r--usr/src/lib/smhba/THIRDPARTYLICENSE404
-rw-r--r--usr/src/lib/smhba/THIRDPARTYLICENSE.descrip1
-rw-r--r--usr/src/lib/smhba/amd64/Makefile30
-rw-r--r--usr/src/lib/smhba/common/SMHBAAPILIB.c4988
-rw-r--r--usr/src/lib/smhba/common/llib-lSMHBAAPI30
-rw-r--r--usr/src/lib/smhba/common/mapfile-vers136
-rw-r--r--usr/src/lib/smhba/common/smhba.conf36
-rw-r--r--usr/src/lib/smhba/common/smhbaapi.h672
-rw-r--r--usr/src/lib/smhba/common/vendorsmhbaapi.h207
-rw-r--r--usr/src/lib/smhba/i386/Makefile29
-rw-r--r--usr/src/lib/smhba/sparc/Makefile29
-rw-r--r--usr/src/lib/smhba/sparcv9/Makefile30
-rw-r--r--usr/src/lib/sun_sas/Makefile54
-rw-r--r--usr/src/lib/sun_sas/Makefile.com99
-rw-r--r--usr/src/lib/sun_sas/amd64/Makefile34
-rw-r--r--usr/src/lib/sun_sas/common/SMHBA_RegisterLibrary.c100
-rw-r--r--usr/src/lib/sun_sas/common/Sun_sasCloseAdapter.c99
-rw-r--r--usr/src/lib/sun_sas/common/Sun_sasFreeLibrary.c131
-rw-r--r--usr/src/lib/sun_sas/common/Sun_sasGetAdapterAttributes.c62
-rw-r--r--usr/src/lib/sun_sas/common/Sun_sasGetAdapterName.c67
-rw-r--r--usr/src/lib/sun_sas/common/Sun_sasGetAdapterPortAttributes.c111
-rw-r--r--usr/src/lib/sun_sas/common/Sun_sasGetDiscoveredPortAttributes.c143
-rw-r--r--usr/src/lib/sun_sas/common/Sun_sasGetLUNStatistics.c38
-rw-r--r--usr/src/lib/sun_sas/common/Sun_sasGetNumberOfAdapters.c46
-rw-r--r--usr/src/lib/sun_sas/common/Sun_sasGetNumberOfPorts.c79
-rw-r--r--usr/src/lib/sun_sas/common/Sun_sasGetPersistentBinding.c36
-rw-r--r--usr/src/lib/sun_sas/common/Sun_sasGetPhyStatistics.c258
-rw-r--r--usr/src/lib/sun_sas/common/Sun_sasGetPortAttributesByWWN.c189
-rw-r--r--usr/src/lib/sun_sas/common/Sun_sasGetPortType.c98
-rw-r--r--usr/src/lib/sun_sas/common/Sun_sasGetProtocolStatistics.c39
-rw-r--r--usr/src/lib/sun_sas/common/Sun_sasGetSASPhyAttributes.c99
-rw-r--r--usr/src/lib/sun_sas/common/Sun_sasGetTargetMapping.c179
-rw-r--r--usr/src/lib/sun_sas/common/Sun_sasGetVendorLibraryAttributes.c50
-rw-r--r--usr/src/lib/sun_sas/common/Sun_sasGetVersion.c34
-rw-r--r--usr/src/lib/sun_sas/common/Sun_sasLoadLibrary.c102
-rw-r--r--usr/src/lib/sun_sas/common/Sun_sasOpenAdapter.c59
-rw-r--r--usr/src/lib/sun_sas/common/Sun_sasRefreshAdapterConfiguration.c155
-rw-r--r--usr/src/lib/sun_sas/common/Sun_sasRefreshInformation.c159
-rw-r--r--usr/src/lib/sun_sas/common/Sun_sasScsiInquiry.c273
-rw-r--r--usr/src/lib/sun_sas/common/Sun_sasScsiReadCapacity.c261
-rw-r--r--usr/src/lib/sun_sas/common/Sun_sasScsiReportLUNs.c233
-rw-r--r--usr/src/lib/sun_sas/common/Sun_sasSendSMPPassThru.c250
-rw-r--r--usr/src/lib/sun_sas/common/Sun_sasSetPersistentBinding.c36
-rw-r--r--usr/src/lib/sun_sas/common/devlink_disco.c251
-rw-r--r--usr/src/lib/sun_sas/common/devtree_device_disco.c1075
-rw-r--r--usr/src/lib/sun_sas/common/devtree_hba_disco.c634
-rw-r--r--usr/src/lib/sun_sas/common/devtree_phy_disco.c202
-rw-r--r--usr/src/lib/sun_sas/common/event.c268
-rw-r--r--usr/src/lib/sun_sas/common/log.c68
-rw-r--r--usr/src/lib/sun_sas/common/mapfile-vers77
-rw-r--r--usr/src/lib/sun_sas/common/sun_sas.c431
-rw-r--r--usr/src/lib/sun_sas/common/sun_sas.h294
-rw-r--r--usr/src/lib/sun_sas/common/verify.c79
-rw-r--r--usr/src/lib/sun_sas/i386/Makefile29
-rw-r--r--usr/src/lib/sun_sas/sparc/Makefile33
-rw-r--r--usr/src/lib/sun_sas/sparcv9/Makefile34
60 files changed, 13767 insertions, 0 deletions
diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile
index 7f523ccaa8..557b39a8fe 100644
--- a/usr/src/lib/Makefile
+++ b/usr/src/lib/Makefile
@@ -147,7 +147,9 @@ SUBDIRS += \
nametoaddr \
ncad_addr \
hbaapi \
+ smhba \
sun_fc \
+ sun_sas \
gss_mechs/mech_krb5 .WAIT \
libkrb5 .WAIT \
krb5 .WAIT \
@@ -486,6 +488,7 @@ HDRSUBDIRS= \
smbsrv \
scsi \
hbaapi \
+ smhba \
libima \
libsun_ima \
mpapi \
diff --git a/usr/src/lib/libsecdb/exec_attr.txt b/usr/src/lib/libsecdb/exec_attr.txt
index 272ab0191d..d0cd0b360b 100644
--- a/usr/src/lib/libsecdb/exec_attr.txt
+++ b/usr/src/lib/libsecdb/exec_attr.txt
@@ -101,6 +101,7 @@ File System Management:solaris:cmd:::/usr/sbin/quotaoff:uid=0;gid=sys
File System Management:solaris:cmd:::/usr/sbin/quotaon:uid=0;gid=sys
File System Management:solaris:cmd:::/usr/sbin/raidctl:privs=sys_config,sys_devices;euid=0
File System Management:suser:cmd:::/usr/sbin/ramdiskadm:euid=0
+File System Management:solaris:cmd:::/usr/sbin/sasinfo:privs=sys_devices
File System Management:solaris:cmd:::/usr/sbin/sbdadm:privs=sys_devices
File System Management:suser:cmd:::/usr/sbin/share:uid=0;gid=root
File System Management:suser:cmd:::/usr/sbin/sharemgr:uid=0;gid=root
diff --git a/usr/src/lib/smhba/Makefile b/usr/src/lib/smhba/Makefile
new file mode 100644
index 0000000000..d17215194c
--- /dev/null
+++ b/usr/src/lib/smhba/Makefile
@@ -0,0 +1,59 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 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
+
+# definitions for install_h target
+HDRS= smhbaapi.h
+HDRDIR= common
+
+.KEEP_STATE:
+
+all clean clobber install lint: $(SUBDIRS)
+
+# install rule for install_h target
+
+install_h: $(ROOTHDRS)
+
+# These headers and source should be excluded from check target
+check: $(CHECKHDRS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+include ../Makefile.targ
diff --git a/usr/src/lib/smhba/Makefile.com b/usr/src/lib/smhba/Makefile.com
new file mode 100644
index 0000000000..e13057c82b
--- /dev/null
+++ b/usr/src/lib/smhba/Makefile.com
@@ -0,0 +1,64 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+
+LIBRARY = libSMHBAAPI.a
+VERS = .1
+OBJECTS = SMHBAAPILIB.o
+CONFIGFILE= smhba.conf
+ROOTETC= $(ROOT)/etc
+
+include ../../Makefile.lib
+
+HETCFILES= $(CONFIGFILE:%=$(ROOTETC)/%)
+HETCFILES:= FILEMODE= 644
+HETCFILES:= OWNER= root
+HETCFILES:= GROUP= sys
+
+LIBS = $(DYNLIB) $(LINTLIB)
+SRCDIR= ../common
+
+INCS += -I$(SRCDIR)
+INCS += -I$(SRC)/lib/hbaapi/common
+CFLAGS += -DSOLARIS
+CFLAGS += -DVERSION='"Version 1"'
+CFLAGS += -DUSESYSLOG
+CPPFLAGS += $(INCS)
+CPPFLAGS += -DPOSIX_THREADS
+
+LDLIBS += -lc
+
+$(LINTLIB) := SRCS= $(SRCDIR)/$(LINTSRC)
+
+$(ROOTETC)/%: ../common/%
+ $(INS.file)
+
+.KEEP_STATE:
+
+all: $(LIBS) $(HETCFILES)
+
+lint: lintcheck
+
+include ../../Makefile.targ
diff --git a/usr/src/lib/smhba/THIRDPARTYLICENSE b/usr/src/lib/smhba/THIRDPARTYLICENSE
new file mode 100644
index 0000000000..464ee756eb
--- /dev/null
+++ b/usr/src/lib/smhba/THIRDPARTYLICENSE
@@ -0,0 +1,404 @@
+--------------------------------------------------------------------
+
+*STORAGE NETWORKING INDUSTRY ASSOCIATION
+PUBLIC LICENSE
+Version 1.1 *
+________________________
+
+*1. Definitions.*
+
+ * 1.1 "Commercial Use" means distribution or otherwise making the
+ Covered Code available to a third party.
+ * 1.2 "Contributor" means each entity that creates or contributes to
+ the creation of Modifications.
+ * 1.3 "Contributor Version" means the combination of the Original
+ Code, prior Modifications used by a Contributor, and the
+ Modifications made by that particular Contributor.
+ * 1.4 "Covered Code" means the Original Code or Modifications or the
+ combination of the Original Code and Modifications, in each case
+ including portions thereof.
+ * 1.5 "Electronic Distribution Mechanism" means a mechanism
+ generally accepted in the software development community for the
+ electronic transfer of data.
+ * 1.6 "Executable" means Covered Code in any form other than Source
+ Code.
+ * 1.7 "Initial Developer" means the individual or entity identified
+ as the Initial Developer in the Source Code notice required by
+ Exhibit A.
+ * 1.8 "Larger Work" means a work which combines Covered Code or
+ portions thereof with code not governed by the terms of this License.
+ * 1.9 "License" means this document.
+ * 1.10 "Licensable" means having the right to grant, to the maximum
+ extent possible, whether at the time of the initial grant or
+ subsequently acquired, any and all of the rights conveyed herein.
+ * 1.11 "Modifications" means any addition to or deletion from the
+ substance or structure of either the Original Code or any previous
+ Modifications. When Covered Code is released as a series of files,
+ a Modification is:
+ o A. Any addition to or deletion from the contents of a file
+ containing Original Code or previous Modifications.
+ o B. Any new file that contains any part of the Original Code
+ or previous Modifications.
+
+ 1.12 "Original Code" means Source Code of computer software code
+ which is described in the Source Code notice required by Exhibit A
+ as Original Code, and which, at the time of its release under this
+ License is not already Covered Code governed by this License.
+
+ * 1.13 "Patent Claims" means any patent claim(s), now owned or
+ hereafter acquired, including without limitation, method, process,
+ and apparatus claims, in any patent Licensable by grantor.
+ * 1.14 "Source Code" means the preferred form of the Covered Code
+ for making modifications to it, including all modules it contains,
+ plus any associated interface definition files, scripts used to
+ control compilation and installation of an Executable, or source
+ code differential comparisons against either the Original Code or
+ another well known, available Covered Code of the Contributor's
+ choice. The Source Code can be in a compressed or archival form,
+ provided the appropriate decompression or de-archiving software is
+ widely available for no charge.
+ * 1.15 "You" (or "Your") means an individual or a legal entity
+ exercising rights under, and complying with all of the terms of,
+ this License or a future version of this License issued under
+ Section 6.1. For legal entities, "You" includes any entity which
+ controls, is controlled by, or is under common control with You.
+ For purposes of this definition, "control" means (a) the power,
+ direct or indirect, to cause the direction or management of such
+ entity, whether by contract or otherwise, or (b) ownership of more
+ than fifty percent (50%) of the outstanding shares or beneficial
+ ownership of such entity
+
+*2. Source Code License.*
+
+ * 2.1 The Initial Developer Grant. The Initial Developer hereby
+ grants You a world-wide, royalty-free, non-exclusive license,
+ subject to third party intellectual property claims:
+ o (a) under intellectual property rights (other than patent or
+ trademark) Licensable by Initial Developer to use,
+ reproduce, modify, display, perform, sublicense and
+ distribute the Original Code (or portions thereof) with or
+ without Modifications, and/or as part of a Larger Work; and
+ o (b) under Patents Claims infringed by the making, using or
+ selling of Original Code, to make, have made, use, practice,
+ sell, and offer for sale, and/or otherwise dispose of the
+ Original Code (or portions thereof).
+ o (c) the licenses granted in this Section 2.1(a) and (b) are
+ effective on the date Initial Developer first distributes
+ Original Code under the terms of this License.
+ o (d) Notwithstanding Section 2.1(b) above, no patent license
+ is granted: 1) for code that You delete from the Original
+ Code; 2) separate from the Original Code; or 3) for
+ infringements caused by: i) the modification of the Original
+ Code or ii) the combination of the Original Code with other
+ software or devices.
+
+ * 2.2 Contributor Grant. Subject to third party intellectual
+ property claims, each Contributor hereby grants You a world-wide,
+ royalty-free, non-exclusive license
+ o (a) under intellectual property rights (other than patent or
+ trademark) Licensable by Contributor, to use, reproduce,
+ modify, display, perform, sublicense and distribute the
+ Modifications created by such Contributor (or portions
+ thereof) either on an unmodified basis, with other
+ Modifications, as Covered Code and/or as part of a Larger
+ Work; and
+ o (b) under Patent Claims infringed by the making, using, or
+ selling of Modifications made by that Contributor either
+ alone and/or in combination with its Contributor Version (or
+ portions of such combination), to make, use, sell, offer for
+ sale, have made, and/or otherwise dispose of: 1)
+ Modifications made by that Contributor (or portions
+ thereof); and 2) the combination of Modifications made by
+ that Contributor with its Contributor Version (or portions
+ of such combination).
+ o (c) the licenses granted in Sections 2.2(a) and 2.2(b) are
+ effective on the date Contributor first makes Commercial Use
+ of the Covered Code.
+ o (d) Notwithstanding Section 2.2(b) above, no patent license
+ is granted: 1) for any code that Contributor has deleted
+ from the Contributor Version; 2) separate from the
+ Contributor Version; 3) for infringements caused by: i)
+ third party modifications of Contributor Version or ii) the
+ combination of Modifications made by that Contributor with
+ other software (except as part of the Contributor Version)
+ or other devices; or 4) under Patent Claims infringed by
+ Covered Code in the absence of Modifications made by that
+ Contributor.
+
+*3. Distribution Obligations.*
+
+ * 3.1 Application of License. The Modifications which You create or
+ to which You contribute are governed by the terms of this License,
+ including without limitation Section 2.2. The Source Code version
+ of Covered Code may be distributed only under the terms of this
+ License or a future version of this License released under Section
+ 6.1, and You must include a copy of this License with every copy
+ of the Source Code You distribute. You may not offer or impose any
+ terms on any Source Code version that alters or restricts the
+ applicable version of this License or the recipients' rights
+ hereunder. However, You may include an additional document
+ offering the additional rights described in Section 3.5.
+ * 3.2 Availability of Source Code. Any Modification which You create
+ or to which You contribute must be made available in Source Code
+ form under the terms of this License either on the same media as
+ an Executable version or via an accepted Electronic Distribution
+ Mechanism to anyone to whom you made an Executable version
+ available; and if made available via Electronic Distribution
+ Mechanism, must remain available for at least twelve (12) months
+ after the date it initially became available, or at least six (6)
+ months after a subsequent version of that particular Modification
+ has been made available to such recipients. You are responsible
+ for ensuring that the Source Code version remains available even
+ if the Electronic Distribution Mechanism is maintained by a third
+ party.
+ * 3.3 Description of Modifications. You must cause all Covered Code
+ to which You contribute to contain a file documenting the changes
+ You made to create that Covered Code and the date of any change.
+ You must include a prominent statement that the Modification is
+ derived, directly or indirectly, from Original Code provided by
+ the Initial Developer and including the name of the Initial
+ Developer in (a) the Source Code, and (b) in any notice in an
+ Executable version or related documentation in which You describe
+ the origin or ownership of the Covered Code.
+ * 3.4 Intellectual Property Matters.
+ o (a) Third Party Claims. If Contributor has actual knowledge
+ that a license under a third party's intellectual property
+ rights is required to exercise the rights granted by such
+ Contributor under Sections 2.1 or 2.2, Contributor must
+ include a text file with the Source Code distribution titled
+ "LEGAL" which describes the claim and the party making the
+ claim in sufficient detail that a recipient will know whom
+ to contact. If Contributor obtains such knowledge after the
+ Modification is made available as described in Section 3.2,
+ Contributor shall promptly modify the LEGAL file in all
+ copies Contributor makes available thereafter.
+ o (b) Contributor API's. If Contributor's Modifications
+ include an application programming interface and Contributor
+ has actual knowledge of patent licenses which are reasonably
+ necessary to implement that API, Contributor must also
+ include this information in the LEGAL file.
+ o (c) Representations. Contributor represents that, except as
+ disclosed pursuant to Section 3.4(a) above, Contributor
+ believes that Contributor's Modifications are Contributor's
+ original creation(s) and/or Contributor has sufficient
+ rights to grant the rights conveyed by this License.
+ * 3.5 Required Notices. You must duplicate the notice in *Exhibit A*
+ in each file of the Source Code. If it is not possible to put such
+ notice in a particular Source Code file due to its structure, then
+ You must include such notice in a location (such as a relevant
+ directory) where a user would be most likely to look for such a
+ notice. If You created one or more Modification(s) You may add
+ your name as a Contributor to the notice described in *Exhibit A.
+ *You must also duplicate this License in any documentation for the
+ Source Code where You describe recipients' rights or ownership
+ rights relating to Covered Code. You may choose to offer, and to
+ charge a fee for, warranty, support, indemnity or liability
+ obligations to one or more recipients of Covered Code. However,
+ You may do so only on Your own behalf, and not on behalf of the
+ Initial Developer or any Contributor. You must make it absolutely
+ clear that any such warranty, support, indemnity or liability
+ obligation is offered by You alone, and You hereby agree to
+ indemnify the Initial Developer and every Contributor for any
+ liability (excluding any liability arising from intellectual
+ property claims relating to the Covered Code) incurred by the
+ Initial Developer or such Contributor as a result of warranty,
+ support, indemnity or liability terms You offer.
+ * 3.6 Distribution of Executable Versions. You may distribute
+ Covered Code in Executable form only if the requirements of
+ Section* 3.1-3.5 *have been met for that Covered Code, and if You
+ include a notice stating that the Source Code version of the
+ Covered Code is available under the terms of this License,
+ including a description of how and where You have fulfilled the
+ obligation of Section *3.2.* The notice must be conspicuously
+ included in any notice in an Executable version, related
+ documentation or collateral in which You describe recipients'
+ rights relating to the Covered Code. You may distribute the
+ Executable version of Covered Code or ownership rights under a
+ license of Your choice, which may contain terms different from
+ this License, provided that You are in compliance with the terms
+ of this License and that the license for the Executable version
+ does not attempt to limit or alter the recipient's rights in the
+ Source Code version from the rights set forth in this License. If
+ You distribute the Executable version under a different license
+ You must make it absolutely clear that any terms which differ from
+ this License are offered by You alone, not by the Initial
+ Developer or any Contributor. You hereby agree to indemnify the
+ Initial Developer and every Contributor for any liability
+ (excluding any liability arising from intellectual property claims
+ relating to the Covered Code) incurred by the Initial Developer or
+ such Contributor as a result of any such terms You offer.
+ * 3.7 Larger Works. You may create a Larger Work by combining
+ Covered Code with other code not governed by the terms of this
+ License and distribute the Larger Work as a single product. In
+ such a case, You must make sure the requirements of this License
+ are fulfilled for the Covered Code.
+
+*4. Inability to Comply Due to Statute or Regulation.* If it is
+impossible for You to comply with any of the terms of this License with
+respect to some or all of the Covered Code due to statute, judicial
+order, or regulation then You must: (a) comply with the terms of this
+License to the maximum extent possible; and (b) describe the limitations
+and the code they affect. Such description must be included in the LEGAL
+file described in Section 3.4 and must be included with all
+distributions of the Source Code. Except to the extent prohibited by
+statute or regulation, such description must be sufficiently detailed
+for a recipient of ordinary skill to be able to understand it.
+
+*5. Application of this License.* This License applies to code to which
+the Initial Developer has attached the notice in Exhibit A and to
+related Covered Code.
+
+*6. Versions of the License.*
+
+ * 6.1 New Versions. The Storage Networking Industry Association (the
+ "SNIA") may publish revised and/or new versions of the License
+ from time to time. Each version will be given a distinguishing
+ version number.
+ * 6.2 Effect of New Versions. Once Covered Code has been published
+ under a particular version of the License, You may always continue
+ to use it under the terms of that version. You may also choose to
+ use such Covered Code under the terms of any subsequent version of
+ the License published by the SNIA. No one other than the SNIA has
+ the right to modify the terms applicable to Covered Code created
+ under this License.
+ * 6.3 Derivative Works. If You create or use a modified version of
+ this License (which you may only do in order to apply it to code
+ which is not already Covered Code governed by this License), You
+ must (a) rename Your license so that the phrases "Storage
+ Networking Industry Association," "SNIA," or any confusingly
+ similar phrase do not appear in your license (except to note that
+ your license differs from this License) and (b) otherwise make it
+ clear that Your version of the license contains terms which differ
+ from the SNIA Public License. (Filling in the name of the Initial
+ Developer, Original Code or Contributor in the notice described in
+ Exhibit A shall not of themselves be deemed to be modifications of
+ this License.)
+
+*7. DISCLAIMER OF WARRANTY. COVERED CODE IS PROVIDED UNDER THIS LICENSE
+ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR
+IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE
+IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR
+NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY
+RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME
+THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS
+DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO
+USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS
+DISCLAIMER.*
+
+*8. TERMINATION.*
+
+ * *8.1 *This License and the rights granted hereunder will terminate
+ automatically if You fail to comply with terms herein and fail to
+ cure such breach within a reasonable time after becoming aware of
+ the breach. All sublicenses to the Covered Code which are properly
+ granted shall survive any termination of this License. Provisions
+ which, by their nature, must remain in effect beyond the
+ termination of this License shall survive.
+ * *8.2* If You initiate litigation by asserting a patent
+ infringement claim (excluding declaratory judgment actions)
+ against Initial Developer or a Contributor (the Initial Developer
+ or Contributor against whom You file such action is referred to as
+ "Participant") alleging that:
+ o *(a)* such Participant's Contributor Version directly or
+ indirectly infringes any patent, then any and all rights
+ granted by such Participant to You under Sections 2.1 and/or
+ 2.2 of this License shall, upon 60 days notice from
+ Participant terminate prospectively, unless if within 60
+ days after receipt of notice You either: (i) agree in
+ writing to pay Participant a mutually agreeable reasonable
+ royalty for Your past and future use of Modifications made
+ by such Participant, or (ii) withdraw Your litigation claim
+ with respect to the Contributor Version against such
+ Participant. If within 60 days of notice, a reasonable
+ royalty and payment arrangement are not mutually agreed upon
+ in writing by the parties or the litigation claim is not
+ withdrawn, the rights granted by Participant to You under
+ Sections 2.1 and/or 2.2 automatically terminate at the
+ expiration of the 60 day notice period specified above.
+ * *8.3* If You assert a patent infringement claim against
+ Participant alleging that such Participant's Contributor Version
+ directly or indirectly infringes any patent where such claim is
+ resolved (such as by license or settlement) prior to the
+ initiation of patent infringement litigation, then the reasonable
+ value of the licenses granted by such Participant under Sections
+ 2.1 or 2.2 shall be taken into account in determining the amount
+ or value of any payment or license.
+
+
+
+ * *8.4* In the event of termination under Sections 8.1 or 8.2 above,
+ all end user license agreements (excluding distributors and
+ resellers) which have been validly granted by You or any
+ distributor hereunder prior to termination shall survive termination.
+
+*9. LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL
+THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE,
+SHALL YOU, THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY
+DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE
+LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR
+CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION,
+DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR
+MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF
+SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES.
+THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR
+PERSONAL INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT
+APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT
+ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL
+DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.*
+
+*10. U.S. GOVERNMENT END USERS.* The Covered Code is a "commercial
+item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995),
+consisting of "commercial computer software" and "commercial computer
+software documentation," as such terms are used in 48 C.F.R. 12.212
+(Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1
+through 227.7202-4 (June 1995), all U.S. Government End Users acquire
+Covered Code with only those rights set forth herein.
+
+*11. MISCELLANEOUS *This License represents the complete agreement
+concerning subject matter hereof. If any provision of this License is
+held to be unenforceable, such provision shall be reformed only to the
+extent necessary to make it enforceable. This License shall be governed
+by California law provisions (except to the extent applicable law, if
+any, provides otherwise), excluding its conflict-of-law provisions. The
+application of the United Nations Convention on Contracts for the
+International Sale of Goods is expressly excluded. Any law or regulation
+which provides that the language of a contract shall be construed
+against the drafter shall not apply to this License.
+
+*12. RESPONSIBILITY FOR CLAIMS.* As between Initial Developer and the
+Contributors, each party is responsible for claims and damages arising,
+directly or indirectly, out of its utilization of rights under this
+License and You agree to work with Initial Developer and Contributors to
+distribute such responsibility on an equitable basis. Nothing herein is
+intended or shall be deemed to constitute any admission of liability.
+
+*13. MULTIPLE-LICENSED CODE.* Initial Developer may designate portions
+of the Covered Code as "Multiple-Licensed". "Multiple-Licensed" means
+that the Initial Developer permits you to utilize portions of the
+Covered Code under Your choice of this License or the alternative
+licenses, if any, specified by the Initial Developer in the file
+described in Exhibit A.
+
+*14. ACCEPTANCE.* This License is accepted by You if You retain, use, or
+distribute the Covered Code for any purpose.
+
+*EXHIBIT A —The SNIA Public 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/SourceLicense-v1.1.html
+
+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 _ ._
+
+The Initial Developer of the Original Code is _ [COMPLETE THIS] _.
+
+Contributor(s): ______________________________________.
+
diff --git a/usr/src/lib/smhba/THIRDPARTYLICENSE.descrip b/usr/src/lib/smhba/THIRDPARTYLICENSE.descrip
new file mode 100644
index 0000000000..ab95413837
--- /dev/null
+++ b/usr/src/lib/smhba/THIRDPARTYLICENSE.descrip
@@ -0,0 +1 @@
+SM-HBA SOFTWARE
diff --git a/usr/src/lib/smhba/amd64/Makefile b/usr/src/lib/smhba/amd64/Makefile
new file mode 100644
index 0000000000..dfeeb9953a
--- /dev/null
+++ b/usr/src/lib/smhba/amd64/Makefile
@@ -0,0 +1,30 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT)
diff --git a/usr/src/lib/smhba/common/SMHBAAPILIB.c b/usr/src/lib/smhba/common/SMHBAAPILIB.c
new file mode 100644
index 0000000000..ae2fd4b0d8
--- /dev/null
+++ b/usr/src/lib/smhba/common/SMHBAAPILIB.c
@@ -0,0 +1,4988 @@
+/*
+ * ************************************************************************
+ * Description
+ * HBAAPILIB.c - Implements a sample common (wrapper) HBA API library
+ *
+ * License:
+ * The contents of this file are subject to the SNIA Public License
+ * Version 1.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * /http://www.snia.org/English/Resources/Code/OpenSource.html
+ *
+ * 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 HBA API Wrapper Library
+ *
+ * The Initial Developer of the Original Code is:
+ * Benjamin F. Kuo, Troika Networks, Inc. (benk@troikanetworks.com)
+ *
+ * Contributor(s):
+ * Tuan Lam, QLogic Corp. (t_lam@qlc.com)
+ * Dan Willie, Emulex Corp. (Dan.Willie@emulex.com)
+ * Dixon Hutchinson, Legato Systems, Inc. (dhutchin@legato.com)
+ * David Dillard, VERITAS Software Corp. (david.dillard@veritas.com)
+ *
+ * ************************************************************************
+ *
+ * Adding on SM-HBA support
+ *
+ * The implementation includes Three different categories functions to support
+ * both HBAAPI and SM-HBA through the same library.
+ *
+ * SM-HBA unique interface:
+ * 1. CHECKLIBRARYANDVERSION(SMHBA) : match SMHBA VSL
+ * Or checking specifically if version is SMHBA beforehand.
+ * 2. resolved to ftable.smhbafunctiontable.{interface}
+ * HBAAPIV2 unique functions
+ * 1. CHECKLIBRARYANDVERSION(HBAAPIV2) : validate and match HBAAPI V2 VSL.
+ * Or checking specifically if version is HBAAPIV2 beforehand.
+ * 2. resolved to ftable.functiontable.{interface}
+ * Common interface between SM-HBA and HBAAPIV2.
+ * 1. CHECKLIBRARY() : to validate the VSL.
+ * 2. FUNCCOMMON macro to map the appropriate entry point table
+ * (union ftable).
+ * 3. If the interface is not supported by HBAAPI(Version 1)
+ * the funtiion ptr will be set to NULL.
+ * Common interface between HBAAPI and HBAAPIV2.
+ * 1. Check if version is not SMHBA).
+ * 2. ftable.functiontalbe.(interface)
+ *
+ * ************************************************************************
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#include <string.h>
+/*
+ * Next define forces entry points in the dll to be exported
+ * See hbaapi.h to see what it does.
+ */
+#define HBAAPI_EXPORTS
+#else
+#include <dlfcn.h>
+#include <strings.h>
+#endif
+#include <stdio.h>
+#include <time.h>
+#include "smhbaapi.h"
+#include "vendorsmhbaapi.h"
+#include <stdlib.h>
+#ifdef USESYSLOG
+#include <syslog.h>
+#endif
+#ifdef SOLARIS
+#include <link.h>
+#include <limits.h>
+static int *handle;
+static Link_map *map, *mp;
+#endif
+
+/*
+ * LIBRARY_NUM is a shortcut to figure out which library we need to call.
+ * The top 16 bits of handle are the library index
+ */
+#define LIBRARY_NUM(handle) ((handle)>>16)
+
+/*
+ * VENDOR_HANDLE turns a global library handle into a vendor specific handle,
+ * with all upper 16 bits set to 0
+ */
+#define VENDOR_HANDLE(handle) ((handle)&0xFFFF)
+
+#define HBA_HANDLE_FROM_LOCAL(library, vendor) \
+ (((library)<<16) | ((vendor)&0x0000FFFF))
+
+int _hbaapi_debuglevel = 0;
+#define DEBUG(L, STR, A1, A2, A3)
+
+#if defined(USESYSLOG) && defined(USELOGFILE)
+FILE *_hbaapi_debug_fd = NULL;
+int _hbaapi_sysloginit = 0;
+#undef DEBUG
+#ifdef WIN32
+#define DEBUG(L, STR, A1, A2, A3)\
+ if ((L) <= _hbaapi_debuglevel) {\
+ if (_hbaapi_sysloginit == 0) {\
+ openlog("HBAAPI", LOG_PID|LOG_ODELAY, LOG_USER);\
+ _hbaapi_sysloginit = 1;\
+ }\
+ syslog(LOG_INFO, (STR), (A1), (A2), (A3));\
+ if (_hbaapi_debug_fd == NULL) {\
+ char _logFile[MAX_PATH]; \
+ GetTempPath(MAX_PATH, _logFile); \
+ strcat(_logFile, "HBAAPI.log"); \
+ _hbaapi_debug_fd = fopen(_logFile, "a");\
+ }\
+ if (_hbaapi_debug_fd != NULL) {\
+ fprintf(_hbaapi_debug_fd, #STR "\n", (A1), (A2), (A3));\
+ }\
+ }
+#else /* WIN32 */
+#define DEBUG(L, STR, A1, A2, A3)\
+ if ((L) <= _hbaapi_debuglevel) {\
+ if (_hbaapi_sysloginit == 0) {\
+ openlog("HBAAPI", LOG_PID|LOG_ODELAY, LOG_USER);\
+ _hbaapi_sysloginit = 1;\
+ }\
+ syslog(LOG_INFO, (STR), (A1), (A2), (A3));\
+ if (_hbaapi_debug_fd == NULL) {\
+ _hbaapi_debug_fd = fopen("/tmp/HBAAPI.log", "a");\
+ }\
+ if (_hbaapi_debug_fd != NULL) {\
+ fprintf(_hbaapi_debug_fd, #STR "\n", (A1), (A2), (A3));\
+ }\
+ }
+#endif /* WIN32 */
+
+#else /* Not both USESYSLOG and USELOGFILE */
+#if defined(USESYSLOG)
+int _hbaapi_sysloginit = 0;
+#undef DEBUG
+#define DEBUG(L, STR, A1, A2, A3) \
+ if ((L) <= _hbaapi_debuglevel) {\
+ if (_hbaapi_sysloginit == 0) {\
+ openlog("HBAAPI", LOG_PID|LOG_ODELAY, LOG_USER);\
+ _hbaapi_sysloginit = 1;\
+ }\
+ syslog(LOG_DEBUG, (STR), (A1), (A2), (A3));\
+ }
+#endif /* USESYSLOG */
+#if defined(USELOGFILE)
+FILE *_hbaapi_debug_fd = NULL;
+#undef DEBUG
+#ifdef WIN32
+#define DEBUG(L, STR, A1, A2, A3) \
+ if ((L) <= _hbaapi_debuglevel) {\
+ if (_hbaapi_debug_fd == NULL) {\
+ char _logFile[MAX_PATH]; \
+ GetTempPath(MAX_PATH, _logFile); \
+ strcat(_logFile, "HBAAPI.log"); \
+ _hbaapi_debug_fd = fopen(_logFile, "a");\
+ }\
+ }
+#else /* WIN32 */
+#define DEBUG(L, STR, A1, A2, A3) \
+ if ((L) <= _hbaapi_debuglevel) {\
+ if (_hbaapi_debug_fd == NULL) {\
+ _hbaapi_debug_fd = fopen("/tmp/HBAAPI.log", "a");\
+ }\
+ if (_hbaapi_debug_fd != NULL) { \
+ fprintf(_hbaapi_debug_fd, #STR "\n", (A1), (A2), (A3));\
+ }\
+ }
+#endif /* WIN32 */
+#endif /* USELOGFILE */
+#endif /* Not both USELOGFILE and USESYSLOG */
+
+#ifdef POSIX_THREADS
+#include <pthread.h>
+/*
+ * When multiple mutex's are grabed, they must be always be grabbed in
+ * the same order, or deadlock can result. There are three levels
+ * of mutex's involved in this API. If LL_mutex is grabbed, always grap
+ * it first. If AL_mutex is grabbed, it may not be grabbed before
+ * LL_mutex. If grabbed in a multi grab sequence, the mutex's protecting
+ * the callback lists must always be grabbed last and release before calling
+ * a vendor specific library function that might invoke a callback function
+ * on the same thread.
+ */
+#define GRAB_MUTEX(M) grab_mutex(M)
+#define RELEASE_MUTEX(M) release_mutex(M)
+#define RELEASE_MUTEX_RETURN(M, RET) release_mutex(M); return (RET)
+#elif defined(WIN32)
+#define GRAB_MUTEX(m) EnterCriticalSection(m)
+#define RELEASE_MUTEX(m) LeaveCriticalSection(m)
+#define RELEASE_MUTEX_RETURN(m, RET) LeaveCriticalSection(m); return (RET)
+#else
+#define GRAB_MUTEX(M)
+#define RELEASE_MUTEX(M)
+#define RELEASE_MUTEX_RETURN(M, RET) return (RET)
+#endif
+
+/*
+ * Vendor library information
+ */
+typedef enum {
+ HBA_LIBRARY_UNKNOWN,
+ HBA_LIBRARY_LOADED,
+ HBA_LIBRARY_NOT_LOADED
+} HBA_LIBRARY_STATUS;
+
+typedef enum {
+ UNKNOWN = 1,
+ SMHBA,
+ HBAAPIV2,
+ HBAAPI
+} LIBRARY_VERSION;
+
+typedef struct hba_library_info {
+ struct hba_library_info
+ *next;
+#ifdef WIN32
+ HINSTANCE hLibrary; /* Handle to a loaded DLL */
+#else
+ char *LibraryName;
+ void* hLibrary; /* Handle to a loaded DLL */
+#endif
+ char *LibraryPath;
+ LIBRARY_VERSION version; /* resolve union */
+ HBA_UINT32 numOfAdapters;
+ union {
+ SMHBA_ENTRYPOINTS smhbafunctionTable; /* smhba function pointers */
+ HBA_ENTRYPOINTSV2 functionTable; /* hba api function pointers */
+ } ftable;
+ HBA_LIBRARY_STATUS status; /* info on this library */
+ HBA_UINT32 index;
+} HBA_LIBRARY_INFO, *PHBA_LIBRARY_INFO;
+
+#define ARE_WE_INITED() \
+ if (_hbaapi_librarylist == NULL) { \
+ return (HBA_STATUS_ERROR_NOT_LOADED); \
+ }
+HBA_LIBRARY_INFO *_hbaapi_librarylist = NULL;
+HBA_UINT32 _hbaapi_total_library_count = 0;
+#ifdef POSIX_THREADS
+pthread_mutex_t _hbaapi_LL_mutex = PTHREAD_MUTEX_INITIALIZER;
+#elif defined(WIN32)
+CRITICAL_SECTION _hbaapi_LL_mutex;
+#endif
+
+/*
+ * Macro to use the right function table between smhba and hbaapi.
+ */
+#define FUNCTABLE(lib_infop) \
+ ((lib_infop->version == SMHBA) ? \
+ lib_infop->ftable.smhbafunctionTable : \
+ lib_infop->ftable.functionTable);
+
+/*
+ * Macro to use the right function ptr between smhba and hbaapi function table.
+ * Should be used for an interface common to SM-HBA and HBAAPIV2.
+ */
+#define FUNCCOMMON(lib_infop, func) \
+ ((lib_infop->version == SMHBA) ? \
+ lib_infop->ftable.smhbafunctionTable.func : \
+ lib_infop->ftable.functionTable.func)
+
+/*
+ * Macro to use the hbaapi function ptr.
+ * Should be used for an interface applicable only HBAAPIV2.
+ */
+#define FUNCHBAAPIV2(lib_infop, func) \
+ lib_infop->ftable.functionTable.func
+
+/*
+ * Macro to use the hbaapi function ptr.
+ * Should be used for an interface applicable only HBAAPIV2.
+ */
+#define FUNCSMHBA(lib_infop, func) \
+ lib_infop->ftable.smhbafunctionTable.func
+
+/*
+ * Individual adapter (hba) information
+ */
+typedef struct hba_adapter_info {
+ struct hba_adapter_info
+ *next;
+ HBA_STATUS GNstatus; /* status from GetAdapterNameFunc */
+ char *name;
+ HBA_WWN nodeWWN;
+ HBA_LIBRARY_INFO *library;
+ HBA_UINT32 index;
+} HBA_ADAPTER_INFO;
+
+HBA_ADAPTER_INFO *_hbaapi_adapterlist = NULL;
+HBA_UINT32 _hbaapi_total_adapter_count = 0;
+#ifdef POSIX_THREADS
+pthread_mutex_t _hbaapi_AL_mutex = PTHREAD_MUTEX_INITIALIZER;
+#elif defined(WIN32)
+CRITICAL_SECTION _hbaapi_AL_mutex;
+#endif
+
+/*
+ * Call back registration
+ */
+typedef struct hba_vendorcallback_elem {
+ struct hba_vendorcallback_elem
+ *next;
+ HBA_CALLBACKHANDLE vendorcbhandle;
+ HBA_LIBRARY_INFO *lib_info;
+} HBA_VENDORCALLBACK_ELEM;
+
+/*
+ * Each instance of HBA_ADAPTERCALLBACK_ELEM represents a call to one of
+ * "register" functions that apply to a particular adapter.
+ * HBA_ALLADAPTERSCALLBACK_ELEM is used just for HBA_RegisterForAdapterAddEvents
+ */
+typedef struct hba_adaptercallback_elem {
+ struct hba_adaptercallback_elem
+ *next;
+ HBA_LIBRARY_INFO *lib_info;
+ void *userdata;
+ HBA_CALLBACKHANDLE vendorcbhandle;
+ void (*callback)();
+} HBA_ADAPTERCALLBACK_ELEM;
+
+typedef struct hba_alladapterscallback_elem {
+ struct hba_alladapterscallback_elem
+ *next;
+ void *userdata;
+ HBA_VENDORCALLBACK_ELEM *vendorhandlelist;
+ void (*callback)();
+} HBA_ALLADAPTERSCALLBACK_ELEM;
+
+HBA_ALLADAPTERSCALLBACK_ELEM *_hbaapi_adapteraddevents_callback_list = NULL;
+HBA_ADAPTERCALLBACK_ELEM *_hbaapi_adapterevents_callback_list = NULL;
+HBA_ADAPTERCALLBACK_ELEM *_hbaapi_adapterportevents_callback_list = NULL;
+HBA_ADAPTERCALLBACK_ELEM *_hbaapi_adapterportstatevents_callback_list = NULL;
+HBA_ADAPTERCALLBACK_ELEM *_hbaapi_targetevents_callback_list = NULL;
+HBA_ADAPTERCALLBACK_ELEM *_hbaapi_linkevents_callback_list = NULL;
+
+HBA_ALLADAPTERSCALLBACK_ELEM *_smhba_adapteraddevents_callback_list = NULL;
+HBA_ADAPTERCALLBACK_ELEM *_smhba_adapterevents_callback_list = NULL;
+HBA_ADAPTERCALLBACK_ELEM *_smhba_adapterportevents_callback_list = NULL;
+HBA_ADAPTERCALLBACK_ELEM *_smhba_adapterportstatevents_callback_list = NULL;
+HBA_ADAPTERCALLBACK_ELEM *_smhba_adapterphystatevents_callback_list = NULL;
+HBA_ADAPTERCALLBACK_ELEM *_smhba_targetevents_callback_list = NULL;
+
+#ifdef POSIX_THREADS
+/* mutex's to protect each list */
+pthread_mutex_t _hbaapi_AAE_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t _hbaapi_AE_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t _hbaapi_APE_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t _hbaapi_APSE_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t _hbaapi_TE_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t _hbaapi_LE_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t _smhba_AAE_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t _smhba_AE_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t _smhba_APE_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t _smhba_APSE_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t _smhba_APHYSE_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t _smhba_TE_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t _smhba_LE_mutex = PTHREAD_MUTEX_INITIALIZER;
+#elif defined(WIN32)
+CRITICAL_SECTION _hbaapi_AAE_mutex;
+CRITICAL_SECTION _hbaapi_AE_mutex;
+CRITICAL_SECTION _hbaapi_APE_mutex;
+CRITICAL_SECTION _hbaapi_APSE_mutex;
+CRITICAL_SECTION _hbaapi_TE_mutex;
+CRITICAL_SECTION _smhba_AAE_mutex;
+CRITICAL_SECTION _smhba_AE_mutex;
+CRITICAL_SECTION _smhba_APE_mutex;
+CRITICAL_SECTION _smhba_APSE_mutex;
+CRITICAL_SECTION _smhba_APHYSE_mutex;
+CRITICAL_SECTION _smhba_TE_mutex;
+CRITICAL_SECTION _hbaapi_LE_mutex;
+#endif
+
+HBA_ADAPTERCALLBACK_ELEM **cb_lists_array[] = {
+ &_hbaapi_adapterevents_callback_list,
+ &_hbaapi_adapterportevents_callback_list,
+ &_hbaapi_adapterportstatevents_callback_list,
+ &_hbaapi_targetevents_callback_list,
+ &_hbaapi_linkevents_callback_list,
+ &_smhba_adapterevents_callback_list,
+ &_smhba_adapterportevents_callback_list,
+ &_smhba_adapterportstatevents_callback_list,
+ &_smhba_adapterphystatevents_callback_list,
+ &_smhba_targetevents_callback_list,
+ NULL};
+
+/*
+ * Common library internal. Mutex handling
+ */
+#ifdef POSIX_THREADS
+static void
+grab_mutex(pthread_mutex_t *mp) {
+/* LINTED E_FUNC_SET_NOT_USED */
+ int ret;
+ if ((ret = pthread_mutex_lock(mp)) != 0) {
+ perror("pthread_mutex_lock - HBAAPI:");
+ DEBUG(1, "pthread_mutex_lock returned %d", ret, 0, 0);
+ }
+}
+
+static void
+release_mutex(pthread_mutex_t *mp) {
+/* LINTED E_FUNC_SET_NOT_USED */
+ int ret;
+ if ((ret = pthread_mutex_unlock(mp)) != 0) {
+ perror("pthread_mutex_unlock - HBAAPI:");
+ DEBUG(1, "pthread_mutex_unlock returned %d", ret, 0, 0);
+ }
+}
+#endif
+
+/*
+ * Common library internal. Check library and return vendorhandle
+ */
+static HBA_STATUS
+HBA_CheckLibrary(HBA_HANDLE handle,
+ HBA_LIBRARY_INFO **lib_infopp,
+ HBA_HANDLE *vendorhandle) {
+
+ HBA_UINT32 libraryIndex;
+ HBA_LIBRARY_INFO *lib_infop;
+
+ if (_hbaapi_librarylist == NULL) {
+ return (HBA_STATUS_ERROR);
+ }
+ libraryIndex = LIBRARY_NUM(handle);
+
+ GRAB_MUTEX(&_hbaapi_LL_mutex);
+ for (lib_infop = _hbaapi_librarylist;
+ lib_infop != NULL;
+ lib_infop = lib_infop->next) {
+ if (lib_infop->index == libraryIndex) {
+ if (lib_infop->status != HBA_LIBRARY_LOADED) {
+ return (HBA_STATUS_ERROR);
+ }
+ *lib_infopp = lib_infop;
+ *vendorhandle = VENDOR_HANDLE(handle);
+ /* caller will release the mutex */
+ return (HBA_STATUS_OK);
+ }
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INVALID_HANDLE);
+}
+#define CHECKLIBRARY() \
+ status = HBA_CheckLibrary(handle, &lib_infop, &vendorHandle);\
+ if (status != HBA_STATUS_OK) { \
+ return (status); \
+ }
+
+#define CHECKLIBRARYANDVERSION(ver) \
+ status = HBA_CheckLibrary(handle, &lib_infop, &vendorHandle); \
+ if (status != HBA_STATUS_OK) { \
+ return (status); \
+ } else { \
+ if (ver != lib_infop->version) { \
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, \
+ HBA_STATUS_ERROR_INCOMPATIBLE); \
+ } \
+ }
+
+/*
+ * freevendorhandlelist is called with _hbaapi_LL_mutex already held
+ */
+static void
+freevendorhandlelist(HBA_VENDORCALLBACK_ELEM *vhlist) {
+ HBA_VENDORCALLBACK_ELEM *vhlp;
+ HBA_VENDORCALLBACK_ELEM *vnext;
+ HBARemoveCallbackFunc registeredfunc;
+
+ for (vhlp = vhlist; vhlp != NULL; vhlp = vnext) {
+ vnext = vhlp->next;
+ registeredfunc =
+ FUNCCOMMON(vhlp->lib_info, RemoveCallbackHandler);
+ if (registeredfunc == NULL) {
+ continue;
+ }
+ (registeredfunc)(vhlp->vendorcbhandle);
+ free(vhlp);
+ }
+}
+
+static
+HBA_STATUS
+local_remove_callback(HBA_CALLBACKHANDLE cbhandle) {
+ HBA_ADAPTERCALLBACK_ELEM ***listp;
+ HBA_ADAPTERCALLBACK_ELEM **lastp;
+ HBA_ALLADAPTERSCALLBACK_ELEM **lap;
+ HBA_ALLADAPTERSCALLBACK_ELEM *allcbp;
+ HBA_ADAPTERCALLBACK_ELEM *cbp;
+ HBARemoveCallbackFunc registeredfunc;
+ HBA_VENDORCALLBACK_ELEM *vhlp;
+ HBA_VENDORCALLBACK_ELEM *vnext;
+ int found;
+ HBA_STATUS status = HBA_STATUS_ERROR_INVALID_HANDLE;
+
+
+ /* search through the simple lists first */
+ GRAB_MUTEX(&_hbaapi_AAE_mutex);
+ GRAB_MUTEX(&_hbaapi_AE_mutex);
+ GRAB_MUTEX(&_hbaapi_APE_mutex);
+ GRAB_MUTEX(&_hbaapi_APSE_mutex);
+ GRAB_MUTEX(&_hbaapi_TE_mutex);
+ GRAB_MUTEX(&_hbaapi_LE_mutex);
+ GRAB_MUTEX(&_smhba_AAE_mutex);
+ GRAB_MUTEX(&_smhba_AE_mutex);
+ GRAB_MUTEX(&_smhba_APE_mutex);
+ GRAB_MUTEX(&_smhba_APSE_mutex);
+ GRAB_MUTEX(&_smhba_TE_mutex);
+ for (listp = cb_lists_array, found = 0;
+ (found == 0 && *listp != NULL); listp++) {
+ lastp = *listp;
+ for (cbp = **listp; cbp != NULL; cbp = cbp->next) {
+ if (cbhandle != (HBA_CALLBACKHANDLE)cbp) {
+ lastp = &(cbp->next);
+ continue;
+ }
+ found = 1;
+ registeredfunc =
+ FUNCCOMMON(cbp->lib_info, RemoveCallbackHandler);
+ if (registeredfunc == NULL) {
+ break;
+ }
+ (registeredfunc)(cbp->vendorcbhandle);
+ *lastp = cbp->next;
+ free(cbp);
+ break;
+ }
+ }
+ RELEASE_MUTEX(&_hbaapi_LE_mutex);
+ RELEASE_MUTEX(&_hbaapi_TE_mutex);
+ RELEASE_MUTEX(&_hbaapi_APSE_mutex);
+ RELEASE_MUTEX(&_hbaapi_APE_mutex);
+ RELEASE_MUTEX(&_hbaapi_AE_mutex);
+ RELEASE_MUTEX(&_hbaapi_AAE_mutex);
+ RELEASE_MUTEX(&_smhba_AAE_mutex);
+ RELEASE_MUTEX(&_smhba_AE_mutex);
+ RELEASE_MUTEX(&_smhba_APE_mutex);
+ RELEASE_MUTEX(&_smhba_APSE_mutex);
+ RELEASE_MUTEX(&_smhba_TE_mutex);
+
+ if (found != 0) {
+ if (registeredfunc == NULL) {
+ return (HBA_STATUS_ERROR_NOT_SUPPORTED);
+ }
+ return (HBA_STATUS_OK);
+ }
+
+ GRAB_MUTEX(&_hbaapi_AAE_mutex);
+ /*
+ * if it wasnt in the simple lists,
+ * look in the list for adapteraddevents
+ */
+ lap = &_hbaapi_adapteraddevents_callback_list;
+ for (allcbp = _hbaapi_adapteraddevents_callback_list;
+ allcbp != NULL;
+ allcbp = allcbp->next) {
+ if (cbhandle != (HBA_CALLBACKHANDLE)allcbp) {
+ lap = &allcbp->next;
+ continue;
+ }
+ for (vhlp = allcbp->vendorhandlelist; vhlp != NULL; vhlp = vnext) {
+ vnext = vhlp->next;
+ /* should be HBAAPIV2 VSL to get to here */
+ registeredfunc =
+ vhlp->lib_info->ftable.functionTable.RemoveCallbackHandler;
+ if (registeredfunc == NULL) {
+ continue;
+ }
+ (registeredfunc)(vhlp->vendorcbhandle);
+ free(vhlp);
+ }
+ *lap = allcbp->next;
+ free(allcbp);
+ status = HBA_STATUS_OK;
+ break;
+ }
+ RELEASE_MUTEX(&_hbaapi_AAE_mutex);
+
+ /* now search smhba adapteradd events. */
+ GRAB_MUTEX(&_smhba_AAE_mutex);
+ lap = &_smhba_adapteraddevents_callback_list;
+ for (allcbp = _smhba_adapteraddevents_callback_list;
+ allcbp != NULL;
+ allcbp = allcbp->next) {
+ if (cbhandle != (HBA_CALLBACKHANDLE)allcbp) {
+ lap = &allcbp->next;
+ continue;
+ }
+ for (vhlp = allcbp->vendorhandlelist; vhlp != NULL; vhlp = vnext) {
+ vnext = vhlp->next;
+ /* should be SMHBA VSL to get to here */
+ registeredfunc =
+ vhlp->lib_info->
+ ftable.smhbafunctionTable.RemoveCallbackHandler;
+ if (registeredfunc == NULL) {
+ continue;
+ }
+ (registeredfunc)(vhlp->vendorcbhandle);
+ free(vhlp);
+ }
+ *lap = allcbp->next;
+ free(allcbp);
+ status = HBA_STATUS_OK;
+ break;
+ }
+ RELEASE_MUTEX(&_smhba_AAE_mutex);
+
+ return (status);
+}
+
+/* LINTED E_STATIC_UE_STATIC_UNUSED */
+static char wwn_str1[17];
+/* LINTED E_STATIC_UE_STATIC_UNUSED */
+static char wwn_str2[17];
+/* LINTED E_STATIC_UE_STATIC_UNUSED */
+static char wwn_str3[17];
+#define WWN2STR1(wwn) WWN2str(wwn_str1, (wwn))
+#define WWN2STR2(wwn) WWN2str(wwn_str2, (wwn))
+#define WWN2STR3(wwn) WWN2str(wwn_str3, (wwn))
+static char *
+/* LINTED E_STATIC_UE_STATIC_UNUSED */
+WWN2str(char *buf, HBA_WWN *wwn) {
+ int j;
+ unsigned char *pc = (unsigned char *)&(wwn->wwn[0]);
+ buf[0] = '\0';
+ for (j = 0; j < 16; j += 2) {
+ (void) sprintf(&buf[j], "%02X", (int)*pc++);
+ }
+ return (buf);
+}
+
+#ifdef WIN32
+BOOL APIENTRY
+DllMain(HANDLE hModule,
+ DWORD ul_reason_for_call,
+ LPVOID lpReserved)
+{
+ switch (ul_reason_for_call) {
+ case DLL_PROCESS_ATTACH:
+ break;
+ case DLL_PROCESS_DETACH:
+ break;
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ break;
+ }
+ return (TRUE);
+}
+#endif
+
+/*
+ * Read in the config file and load all the specified vendor specific
+ * libraries and perform the function registration exercise
+ */
+HBA_STATUS
+HBA_LoadLibrary()
+{
+ HBARegisterLibraryFunc RegisterFunc;
+ HBARegisterLibraryV2Func RegisterV2Func;
+ SMHBARegisterLibraryFunc RegisterSMHBAFunc;
+ HBALoadLibraryFunc LoadLibraryFunc;
+ HBAGetVersionFunc GetVersionFunc;
+#ifdef POSIX_THREADS
+ int ret;
+#endif
+ HBA_STATUS status;
+ HBA_UINT32 libversion;
+
+ /* Open configuration file from known location */
+#ifdef WIN32
+ LONG lStatus;
+ HKEY hkSniaHba, hkVendorLib;
+ FILETIME ftLastWriteTime;
+ TCHAR cSubKeyName[256];
+ DWORD i, dwSize, dwType;
+ BYTE byFileName[MAX_PATH];
+ HBA_LIBRARY_INFO *lib_infop;
+
+ if (_hbaapi_librarylist != NULL) {
+ /* this is an app programming error */
+ return (HBA_STATUS_ERROR);
+ }
+
+ lStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\SNIA\\HBA",
+ 0, KEY_READ, &hkSniaHba);
+ if (lStatus != ERROR_SUCCESS) {
+ /* ???Opportunity to send error msg, configuration error */
+ return (HBA_STATUS_ERROR);
+ }
+ /*
+ * Enumerate all the subkeys. These have the form:
+ * HKLM\Software\SNIA\HBA\<Vendor id> - note that we don't care
+ * what the vendor id is
+ */
+ for (i = 0; ; i++) {
+ dwSize = 255; /* how big the buffer is */
+ lStatus = RegEnumKeyEx(hkSniaHba, i,
+ (char *)&cSubKeyName, &dwSize, NULL,
+ NULL, NULL, &ftLastWriteTime);
+ if (lStatus == ERROR_NO_MORE_ITEMS) {
+ break; /* we're done */
+ } else if (lStatus == ERROR_MORE_DATA) { /* buffer not big enough */
+ /* do whatever */
+ ;
+ }
+ /* Now open the subkey that pertains to this vendor's library */
+ lStatus = RegOpenKeyEx(hkSniaHba, cSubKeyName, 0, KEY_READ,
+ &hkVendorLib);
+ if (lStatus != ERROR_SUCCESS) {
+ RegCloseKey(hkSniaHba);
+ /* ???Opportunity to send error msg, installation error */
+ return (HBA_STATUS_ERROR);
+ /*
+ * you may want to return something
+ * else or keep trying
+ */
+ }
+ /*
+ * The name of the library is contained in a REG_SZ Value
+ * keyed to "LibraryFile"
+ */
+ dwSize = MAX_PATH;
+ lStatus = RegQueryValueEx(hkVendorLib, "LibraryFile", NULL, &dwType,
+ byFileName, &dwSize);
+ if (lStatus != ERROR_SUCCESS) {
+ RegCloseKey(hkVendorLib);
+ /* ???Opportunity to send error msg, installation error */
+ continue;
+ }
+ lib_infop = (HBA_LIBRARY_INFO *)calloc(1, sizeof (HBA_LIBRARY_INFO));
+ if (lib_infop == NULL) {
+ /* what is the right thing to do in MS land??? */
+ RegCloseKey(hkVendorLib);
+ /* ???Opportunity to send error msg, installation error */
+ return (HBA_STATUS_ERROR);
+ }
+ lib_infop->status = HBA_LIBRARY_NOT_LOADED;
+ lib_infop->next = _hbaapi_librarylist;
+ lib_infop->index = _hbaapi_total_library_count;
+ _hbaapi_total_library_count++;
+ _hbaapi_librarylist = lib_infop;
+
+ /* Now I can try to load the library */
+ lib_infop->hLibrary = LoadLibrary(byFileName);
+ if (lib_infop->hLibrary == NULL) {
+ /* printf("unable to load library %s\n", librarypath); */
+ /* ???Opportunity to send error msg, installation error */
+ goto dud_library;
+ }
+ lib_infop->LibraryPath = strdup(byFileName);
+ DEBUG(1, "HBAAPI loading: %s\n", byFileName, 0, 0);
+
+ RegisterSMHBAFunc = (SMHBARegisterLibraryFunc)
+ GetProcAddress(lib_infop->hLibrary, "SMHBA_RegisterLibrary");
+ if (RegisterSMHBAFunc != NULL) {
+ status = ((RegisterSMHBAFunc)(SMHBA_ENTRYPOINTS *)
+ (&lib_infop->ftable.smhbafunctionTable));
+ if (status != HBA_STATUS_OK) {
+ /* library not loaded */
+ /* ???Opportunity to send error msg, library error? */
+ goto dud_library;
+ } else {
+ lib_infop->version = SMHBA;
+ }
+ } else {
+ /* Call the registration function to get the list of pointers */
+ RegisterV2Func = (HBARegisterLibraryV2Func)GetProcAddress(
+ lib_infop->hLibrary, "HBA_RegisterLibraryV2");
+ if (RegisterV2Func != NULL) {
+ /*
+ * Load the function pointers directly into
+ * the table of functions
+ */
+ status = ((RegisterV2Func)
+ (HBA_ENTRYPOINTSV2 *)(&lib_infop->ftable.functionTable));
+ if (status != HBA_STATUS_OK) {
+ /* library not loaded */
+ /* ???Opportunity to send error msg, library error? */
+ goto dud_library;
+ } else {
+ lib_infop->version = HBAAPIV2;
+ }
+ } else {
+ /* Maybe the vendor library is only Rev1 */
+ RegisterFunc = (HBARegisterLibraryFunc)
+ GetProcAddress(lib_infop->hLibrary, "HBA_RegisterLibrary");
+ if (RegisterFunc == NULL) {
+ /* ???Opportunity to send error msg, library error? */
+ goto dud_library;
+ }
+ /*
+ * Load the function points directly into
+ * the Rev 2 table of functions
+ */
+ status = ((RegisterFunc)(
+ (HBA_ENTRYPOINTS *)(&lib_infop->ftable.functionTable)));
+ if (status != HBA_STATUS_OK) {
+ /* library not loaded */
+ /* ???Opportunity to send error msg, library error? */
+ goto dud_library;
+ } else {
+ lib_infop->version = HBAAPI;
+ }
+ }
+ }
+
+ /* successfully loaded library */
+ /*
+ * SM-HBA and HBAAPI has a seperate handler for GetVersion but
+ * they have the same function signature so use the same variable here.
+ */
+ GetVersionFunc = FUNCCOMMON(lib_infop, GetVersionHandler);
+ if (GetVersionFunc != NULL) {
+ if (lib_infop->version == SMHBA) {
+ /* Check the version of this library before loading */
+ libversion = ((GetVersionFunc)());
+#ifdef NOTDEF /* save for a later time... when it matters */
+ if (libversion < SMHBA_LIBVERSION) {
+ goto dud_library;
+ }
+#endif
+ } else {
+ /* Check the version of this library before loading */
+ /* Actually... This wrapper is compatible with version 1 */
+ libversion = ((GetVersionFunc)());
+#ifdef NOTDEF /* save for a later time... when it matters */
+ if (libversion < HBA_LIBVERSION) {
+ goto dud_library;
+ }
+#endif
+ }
+ } else {
+ /* ???Opportunity to send error msg, library error? */
+ goto dud_library;
+ }
+
+ LoadLibraryFunc = FUNCCOMMON(lib_infop, LoadLibraryHandler);
+ if (LoadLibraryFunc == NULL) {
+ /* Hmmm, dont we need to flag this in a realy big way??? */
+ /* How about messages to the system event logger ??? */
+ /* ???Opportunity to send error msg, library error? */
+ goto dud_library;
+ }
+ /* Initialize this library */
+ status = ((LoadLibraryFunc)());
+ if (status != HBA_STATUS_OK) {
+ /* ???Opportunity to send error msg, library error? */
+ continue;
+ }
+ /* successfully loaded library */
+ lib_infop->status = HBA_LIBRARY_LOADED;
+
+ dud_library: /* its also just the end of the loop */
+ RegCloseKey(hkVendorLib);
+ }
+ RegCloseKey(hkSniaHba);
+
+#else /* Unix as opposed to Win32 */
+ FILE *hbaconf;
+ char fullline[512]; /* line read from HBA.conf */
+ char *libraryname; /* Read in from file HBA.conf */
+ char *librarypath; /* Read in from file HBA.conf */
+ char hbaConfFilePath[256];
+ char *charPtr;
+ HBA_LIBRARY_INFO *lib_infop;
+
+ GRAB_MUTEX(&_hbaapi_LL_mutex);
+ if (_hbaapi_librarylist != NULL) {
+ (void) fprintf(stderr,
+ "HBA_LoadLibrary: previously unfreed "
+ "libraries exist, call HBA_FreeLibrary().\n");
+ RELEASE_MUTEX(&_hbaapi_LL_mutex);
+ return (HBA_STATUS_ERROR);
+ }
+
+ (void) strcpy(hbaConfFilePath, "/etc/smhba.conf");
+
+ if ((hbaconf = fopen(hbaConfFilePath, "r")) == NULL) {
+ (void) printf("Cannot open %s\n", hbaConfFilePath);
+ RELEASE_MUTEX(&_hbaapi_LL_mutex);
+ return (HBA_STATUS_ERROR);
+ }
+
+ /* Read in each line and load library */
+ while ((hbaconf != NULL) &&
+ (fgets(fullline, sizeof (fullline), hbaconf))) {
+ /* Skip the comments... */
+ if ((fullline[0] == '#') || (fullline[0] == '\n')) {
+ continue;
+ }
+
+ /* grab first 'thing' in line (if its there) */
+ if ((libraryname = strtok(fullline, " \t\n")) != NULL) {
+ if (strlen(libraryname) >= 64) {
+ (void) fprintf(stderr,
+ "Library name(%s) in %s is > 64 characters\n",
+ libraryname, hbaConfFilePath);
+ }
+ }
+ /* grab second 'thing' in line (if its there) */
+ if ((librarypath = strtok(NULL, " \t\n")) != NULL) {
+ if (strlen(librarypath) >= 256) {
+ (void) fprintf(stderr,
+ "Library path(%s) in %s is > 256 characters\n",
+ librarypath, hbaConfFilePath);
+ }
+ }
+
+ /* there should be no more 'things' in the line */
+ if ((charPtr = strtok(NULL, " \n\t")) != NULL) {
+ (void) fprintf(stderr, "Extraneous characters (\"%s\") in %s\n",
+ charPtr, hbaConfFilePath);
+ }
+
+ /* Continue to the next line if library name or path is invalid */
+ if (libraryname == NULL ||
+ strlen(libraryname) == 0 ||
+ librarypath == NULL ||
+ (strlen(librarypath) == 0)) {
+ continue;
+ }
+
+ /*
+ * Special case....
+ * Look for loglevel
+ */
+ if (strcmp(libraryname, "debuglevel") == 0) {
+ _hbaapi_debuglevel = strtol(librarypath, NULL, 10);
+ /* error handling does the right thing automagically */
+ continue;
+ }
+
+ lib_infop = (HBA_LIBRARY_INFO *)calloc(1, sizeof (HBA_LIBRARY_INFO));
+ if (lib_infop == NULL) {
+ (void) fprintf(stderr, "HBA_LoadLibrary: out of memeory\n");
+ RELEASE_MUTEX(&_hbaapi_LL_mutex);
+ return (HBA_STATUS_ERROR);
+ }
+ lib_infop->status = HBA_LIBRARY_NOT_LOADED;
+ lib_infop->LibraryName = strdup(libraryname);
+ lib_infop->LibraryPath = strdup(librarypath);
+ lib_infop->numOfAdapters = 0;
+ lib_infop->version = UNKNOWN;
+ lib_infop->index = _hbaapi_total_library_count;
+ _hbaapi_total_library_count++;
+ lib_infop->next = _hbaapi_librarylist;
+ _hbaapi_librarylist = lib_infop;
+
+ /* Load the DLL now */
+ if ((lib_infop->hLibrary = dlopen(librarypath, RTLD_LAZY)) == NULL) {
+ /* printf("unable to load library %s\n", librarypath); */
+ continue;
+ }
+ /* Call the registration function to get the list of pointers */
+ RegisterSMHBAFunc = (SMHBARegisterLibraryFunc)
+ dlsym(lib_infop->hLibrary, "SMHBA_RegisterLibrary");
+ if (RegisterSMHBAFunc != NULL) {
+ /*
+ * Load the function points directly into
+ * the table of functions
+ */
+ status = ((RegisterSMHBAFunc)
+ (&lib_infop->ftable.smhbafunctionTable));
+ if (status != HBA_STATUS_OK) {
+ /* library not loaded */
+ continue;
+ } else {
+ lib_infop->version = SMHBA;
+ }
+ } else {
+ RegisterV2Func = (HBARegisterLibraryV2Func)
+ dlsym(lib_infop->hLibrary, "HBA_RegisterLibraryV2");
+ if (RegisterV2Func != NULL) {
+ /*
+ * Load the function points directly into
+ * the table of functions
+ */
+ status = ((RegisterV2Func)((HBA_ENTRYPOINTSV2 *)
+ (&lib_infop->ftable.functionTable)));
+ if (status != HBA_STATUS_OK) {
+ /* library not loaded */
+ continue;
+ } else {
+ lib_infop->version = HBAAPIV2;
+ }
+ } else {
+ /* Maybe the vendor library is only Rev1 */
+ RegisterFunc = (HBARegisterLibraryFunc)
+ dlsym(lib_infop->hLibrary, "HBA_RegisterLibrary");
+ if (RegisterFunc == NULL) {
+ /* This function is required */
+ (void) fprintf(stderr,
+ "HBA_LoadLibrary: vendor specific RegisterLibrary "
+ "function not found. lib: %s\n", librarypath);
+ DEBUG(1, "HBA_LoadLibrary: vendor specific "
+ "RegisterLibrary function not found. lib: %s\n",
+ librarypath, 0, 0);
+ continue;
+ }
+ /*
+ * Load the function points directly into
+ * the table of functions
+ */
+ status = ((RegisterFunc)
+ ((HBA_ENTRYPOINTS *)(&lib_infop->ftable.functionTable)));
+ if (status != HBA_STATUS_OK) {
+ /* library not loaded */
+ (void) fprintf(stderr,
+ "HBA_LoadLibrary: vendor specific RegisterLibrary "
+ "function encountered an error. lib: %s\n",
+ librarypath);
+ DEBUG(1,
+ "HBA_LoadLibrary: vendor specific RegisterLibrary "
+ "function encountered an error. lib: %s\n",
+ librarypath, 0, 0);
+ continue;
+ } else {
+ lib_infop->version = HBAAPI;
+ }
+ }
+ }
+
+ /* successfully loaded library */
+ /*
+ * SM-HBA and HBAAPI has a seperate handler for GetVersion but
+ * they have the same function signature so use the same variable here.
+ */
+ if ((GetVersionFunc = FUNCCOMMON(lib_infop, GetVersionHandler))
+ == NULL) {
+ continue;
+ }
+ if (lib_infop->version == SMHBA) {
+ libversion = ((GetVersionFunc)());
+ if (libversion < SMHBA_LIBVERSION) {
+ (void) printf("Library version mismatch."
+ "Got %d expected %d.\n",
+ libversion, SMHBA_LIBVERSION);
+ continue;
+ }
+ } else {
+ libversion = ((GetVersionFunc)());
+ /* Check the version of this library before loading */
+ /* Actually... This wrapper is compatible with version 1 */
+ if (libversion < HBA_LIBVERSION) {
+ (void) printf("Library version mismatch."
+ "Got %d expected %d.\n",
+ libversion, HBA_LIBVERSION);
+ continue;
+ }
+ }
+
+ DEBUG(1, "%s libversion = %d", librarypath, libversion, 0);
+ LoadLibraryFunc = FUNCCOMMON(lib_infop, LoadLibraryHandler);
+ if (LoadLibraryFunc == NULL) {
+ /* this function is required */
+ (void) fprintf(stderr,
+ "HBA_LoadLibrary: vendor specific LoadLibrary "
+ "function not found. lib: %s\n", librarypath);
+ DEBUG(1, "HBA_LoadLibrary: vendor specific LoadLibrary "
+ "function not found. lib: %s\n", librarypath, 0, 0);
+ continue;
+ }
+ /* Initialize this library */
+ if ((status = ((LoadLibraryFunc)())) != HBA_STATUS_OK) {
+ /* maybe this should be a printf so that we CANNOT miss it */
+ (void) fprintf(stderr,
+ "HBA_LoadLibrary: Encounterd and error loading: %s",
+ librarypath);
+ DEBUG(1, "Encounterd and error loading: %s", librarypath, 0, 0);
+ DEBUG(1, " HBA_STATUS: %d", status, 0, 0);
+ continue;
+ }
+ /* successfully loaded library */
+ lib_infop->status = HBA_LIBRARY_LOADED;
+ }
+#endif /* WIN32 or UNIX */
+#ifdef POSIX_THREADS
+ /*
+ * The _hbaapi_LL_mutex is already grabbed to proctect the caller of
+ * HBA_FreeLibrary() during loading.
+ * The mutexes are already initialized
+ * with PTHREAD_MUTEX_INITIALIZER. Do we need to init again?
+ * Keeping the code from HBAAPI source...
+ */
+ ret = pthread_mutex_init(&_hbaapi_AL_mutex, NULL);
+ if (ret == 0) {
+ ret = pthread_mutex_init(&_hbaapi_AAE_mutex, NULL);
+ }
+ if (ret == 0) {
+ ret = pthread_mutex_init(&_hbaapi_AE_mutex, NULL);
+ }
+ if (ret == 0) {
+ ret = pthread_mutex_init(&_hbaapi_APE_mutex, NULL);
+ }
+ if (ret == 0) {
+ ret = pthread_mutex_init(&_hbaapi_APSE_mutex, NULL);
+ }
+ if (ret == 0) {
+ ret = pthread_mutex_init(&_hbaapi_TE_mutex, NULL);
+ }
+ if (ret == 0) {
+ ret = pthread_mutex_init(&_smhba_AAE_mutex, NULL);
+ }
+ if (ret == 0) {
+ ret = pthread_mutex_init(&_smhba_AE_mutex, NULL);
+ }
+ if (ret == 0) {
+ ret = pthread_mutex_init(&_smhba_APE_mutex, NULL);
+ }
+ if (ret == 0) {
+ ret = pthread_mutex_init(&_smhba_APSE_mutex, NULL);
+ }
+ if (ret == 0) {
+ ret = pthread_mutex_init(&_smhba_TE_mutex, NULL);
+ }
+ if (ret == 0) {
+ ret = pthread_mutex_init(&_hbaapi_LE_mutex, NULL);
+ }
+ if (ret != 0) {
+ perror("pthread_mutex_init - HBA_LoadLibrary");
+ RELEASE_MUTEX(&_hbaapi_LL_mutex);
+ return (HBA_STATUS_ERROR);
+ }
+ RELEASE_MUTEX(&_hbaapi_LL_mutex);
+#elif defined(WIN32)
+ InitializeCriticalSection(&_hbaapi_LL_mutex);
+ InitializeCriticalSection(&_hbaapi_AL_mutex);
+ InitializeCriticalSection(&_hbaapi_AAE_mutex);
+ InitializeCriticalSection(&_hbaapi_AE_mutex);
+ InitializeCriticalSection(&_hbaapi_APE_mutex);
+ InitializeCriticalSection(&_hbaapi_APSE_mutex);
+ InitializeCriticalSection(&_hbaapi_TE_mutex);
+ InitializeCriticalSection(&_hbaapi_LE_mutex);
+ InitializeCriticalSection(&_smhba_AAE_mutex);
+ InitializeCriticalSection(&_smhba_AE_mutex);
+ InitializeCriticalSection(&_smhba_APE_mutex);
+ InitializeCriticalSection(&_smhba_APSE_mutex);
+ InitializeCriticalSection(&_smhba_TE_mutex);
+#endif
+
+ return (HBA_STATUS_OK);
+}
+
+HBA_STATUS
+HBA_FreeLibrary() {
+ HBAFreeLibraryFunc FreeLibraryFunc;
+/* LINTED E_FUNC_SET_NOT_USED */
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_LIBRARY_INFO *lib_next;
+ HBA_ADAPTERCALLBACK_ELEM
+ ***listp;
+ HBA_ADAPTER_INFO *adapt_infop;
+ HBA_ADAPTER_INFO *adapt_next;
+
+ GRAB_MUTEX(&_hbaapi_LL_mutex);
+ if (_hbaapi_librarylist == NULL) {
+ RELEASE_MUTEX(&_hbaapi_LL_mutex);
+ return (HBA_STATUS_ERROR_NOT_LOADED);
+ }
+
+ GRAB_MUTEX(&_hbaapi_AL_mutex);
+
+ DEBUG(1, "HBA_FreeLibrary()", 0, 0, 0);
+ for (lib_infop = _hbaapi_librarylist; lib_infop != NULL;
+ lib_infop = lib_next) {
+ lib_next = lib_infop->next;
+ if (lib_infop->status == HBA_LIBRARY_LOADED) {
+ FreeLibraryFunc = FUNCCOMMON(lib_infop, FreeLibraryHandler);
+ if (FreeLibraryFunc != NULL) {
+ /* Free this library */
+ status = ((FreeLibraryFunc)());
+ DEBUG(1, "HBA_FreeLibrary() Failed %d", status, 0, 0);
+ }
+#ifdef WIN32
+ FreeLibrary(lib_infop->hLibrary); /* Unload DLL from memory */
+#else
+ (void) dlclose(lib_infop->hLibrary); /* Unload DLL from memory */
+#endif
+ }
+#ifndef WIN32
+ free(lib_infop->LibraryName);
+#endif
+ free(lib_infop->LibraryPath);
+ free(lib_infop);
+
+ }
+ _hbaapi_librarylist = NULL;
+ /*
+ * OK, now all functions are disabled except for LoadLibrary,
+ * Hope no other thread calls it before we have returned
+ */
+ _hbaapi_total_library_count = 0;
+
+ for (adapt_infop = _hbaapi_adapterlist;
+ adapt_infop != NULL;
+ adapt_infop = adapt_next) {
+ adapt_next = adapt_infop->next;
+ free(adapt_infop->name);
+ free(adapt_infop);
+ }
+ _hbaapi_adapterlist = NULL;
+ _hbaapi_total_adapter_count = 0;
+
+ /*
+ * Free up the callbacks, this is not the most efficient, but it works
+ */
+ while ((volatile HBA_ADAPTERCALLBACK_ELEM *)
+ _hbaapi_adapteraddevents_callback_list
+ != NULL) {
+ (void) local_remove_callback((HBA_CALLBACKHANDLE)
+ _hbaapi_adapteraddevents_callback_list);
+ }
+ while ((volatile HBA_ADAPTERCALLBACK_ELEM *)
+ _smhba_adapteraddevents_callback_list
+ != NULL) {
+ (void) local_remove_callback((HBA_CALLBACKHANDLE)
+ _smhba_adapteraddevents_callback_list);
+ }
+ for (listp = cb_lists_array; *listp != NULL; listp++) {
+ while ((volatile HBA_ADAPTERCALLBACK_ELEM ***)**listp != NULL) {
+ (void) local_remove_callback((HBA_CALLBACKHANDLE)**listp);
+ }
+ }
+
+ RELEASE_MUTEX(&_hbaapi_AL_mutex);
+ RELEASE_MUTEX(&_hbaapi_LL_mutex);
+
+#ifdef USESYSLOG
+ closelog();
+#endif
+#ifdef USELOGFILE
+ if (_hbaapi_debug_fd != NULL) {
+ fclose(_hbaapi_debug_fd);
+ }
+ _hbaapi_debug_fd = NULL;
+#endif
+#ifdef POSIX_THREADS
+ /* this will unlock them as well, but who cares */
+ (void) pthread_mutex_destroy(&_hbaapi_LE_mutex);
+ (void) pthread_mutex_destroy(&_hbaapi_TE_mutex);
+ (void) pthread_mutex_destroy(&_hbaapi_APSE_mutex);
+ (void) pthread_mutex_destroy(&_hbaapi_APE_mutex);
+ (void) pthread_mutex_destroy(&_hbaapi_AE_mutex);
+ (void) pthread_mutex_destroy(&_hbaapi_AAE_mutex);
+ (void) pthread_mutex_destroy(&_smhba_TE_mutex);
+ (void) pthread_mutex_destroy(&_smhba_APSE_mutex);
+ (void) pthread_mutex_destroy(&_smhba_APE_mutex);
+ (void) pthread_mutex_destroy(&_smhba_AE_mutex);
+ (void) pthread_mutex_destroy(&_smhba_AAE_mutex);
+ (void) pthread_mutex_destroy(&_hbaapi_AL_mutex);
+ (void) pthread_mutex_destroy(&_hbaapi_LL_mutex);
+#elif defined(WIN32)
+ DeleteCriticalSection(&_hbaapi_LL_mutex);
+ DeleteCriticalSection(&_hbaapi_AL_mutex);
+ DeleteCriticalSection(&_hbaapi_AAE_mutex);
+ DeleteCriticalSection(&_hbaapi_AE_mutex);
+ DeleteCriticalSection(&_hbaapi_APE_mutex);
+ DeleteCriticalSection(&_hbaapi_APSE_mutex);
+ DeleteCriticalSection(&_hbaapi_TE_mutex);
+ DeleteCriticalSection(&_hbaapi_LE_mutex);
+ DeleteCriticalSection(&_smhba_TE_mutex);
+ DeleteCriticalSection(&_smhba_APSE_mutex);
+ DeleteCriticalSection(&_smhba_APE_mutex);
+ DeleteCriticalSection(&_smhba_AE_mutex);
+ DeleteCriticalSection(&_smhba_AAE_mutex);
+#endif
+
+ return (HBA_STATUS_OK);
+}
+
+/*
+ * The API used to use fixed size tables as its primary data structure.
+ * Indexing from 1 to N identified each adapters. Now the adapters are
+ * on a linked list. There is a unique "index" foreach each adapter.
+ * Adapters always keep their index, even if they are removed from the
+ * hardware. The only time the indexing is reset is on HBA_FreeLibrary
+ */
+HBA_UINT32
+HBA_GetNumberOfAdapters()
+{
+ int j = 0;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBAGetNumberOfAdaptersFunc GetNumberOfAdaptersFunc;
+ HBAGetAdapterNameFunc GetAdapterNameFunc;
+ HBA_BOOLEAN found_name;
+ HBA_ADAPTER_INFO *adapt_infop;
+ HBA_STATUS status;
+
+ char adaptername[256];
+ int num_adapters; /* local */
+
+ if (_hbaapi_librarylist == NULL) {
+ return (0);
+ }
+ GRAB_MUTEX(&_hbaapi_LL_mutex); /* pay attention to order */
+ GRAB_MUTEX(&_hbaapi_AL_mutex);
+
+ for (lib_infop = _hbaapi_librarylist;
+ lib_infop != NULL;
+ lib_infop = lib_infop->next) {
+
+ if (lib_infop->status != HBA_LIBRARY_LOADED) {
+ continue;
+ }
+
+ GetNumberOfAdaptersFunc =
+ FUNCCOMMON(lib_infop, GetNumberOfAdaptersHandler);
+ if (GetNumberOfAdaptersFunc == NULL) {
+ continue;
+ }
+ num_adapters = ((GetNumberOfAdaptersFunc)());
+#ifndef WIN32
+ DEBUG(1, "HBAAPI: num_adapters for %s = %d\n",
+ lib_infop->LibraryName, num_adapters, 0);
+#else
+ DEBUG(1, "HBAAPI: num_adapters for %s = %d\n",
+ lib_infop->LibraryPath, num_adapters, 0);
+#endif
+
+ /* Also get the names of all the adapters here and cache */
+ GetAdapterNameFunc = FUNCCOMMON(lib_infop, GetAdapterNameHandler);
+ if (GetAdapterNameFunc == NULL) {
+ continue;
+ }
+
+ for (j = 0; j < num_adapters; j++) {
+ found_name = 0;
+ status = (GetAdapterNameFunc)(j, (char *)&adaptername);
+ if (status == HBA_STATUS_OK) {
+ for (adapt_infop = _hbaapi_adapterlist;
+ adapt_infop != NULL;
+ adapt_infop = adapt_infop->next) {
+ /*
+ * check for duplicates, really,
+ * this may just be a second
+ * call to this function
+ * ??? how do we know when a name becomes stale?
+ */
+ if (strcmp(adaptername, adapt_infop->name) == 0) {
+ /* already got this one */
+ found_name++;
+ break;
+ }
+ }
+ if (found_name != 0) {
+ continue;
+ }
+ }
+
+ adapt_infop = (HBA_ADAPTER_INFO *)
+ calloc(1, sizeof (HBA_ADAPTER_INFO));
+ if (adapt_infop == NULL) {
+#ifndef WIN32
+ (void) fprintf(stderr,
+ "HBA_GetNumberOfAdapters: calloc failed"
+ " on sizeof:%lu\n",
+ (unsigned long)(sizeof (HBA_ADAPTER_INFO)));
+#endif
+ RELEASE_MUTEX(&_hbaapi_AL_mutex);
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex,
+ _hbaapi_total_adapter_count);
+ }
+ if ((adapt_infop->GNstatus = status) == HBA_STATUS_OK) {
+ adapt_infop->name = strdup(adaptername);
+ } else {
+ char dummyname[512];
+ (void) sprintf(dummyname, "NULLADAPTER-%255s-%03d",
+ lib_infop->LibraryPath, _hbaapi_total_adapter_count);
+ dummyname[511] = '\0';
+ adapt_infop->name = strdup(dummyname);
+ }
+ lib_infop->numOfAdapters++;
+ adapt_infop->library = lib_infop;
+ adapt_infop->next = _hbaapi_adapterlist;
+ adapt_infop->index = _hbaapi_total_adapter_count;
+ _hbaapi_adapterlist = adapt_infop;
+ _hbaapi_total_adapter_count++;
+ }
+ }
+ RELEASE_MUTEX(&_hbaapi_AL_mutex);
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, _hbaapi_total_adapter_count);
+}
+
+HBA_STATUS
+HBA_GetAdapterName(
+ HBA_UINT32 adapterindex,
+ char *adaptername)
+{
+ HBA_ADAPTER_INFO *adapt_infop;
+ HBA_STATUS ret = HBA_STATUS_ERROR_ILLEGAL_INDEX;
+
+ if (adaptername == NULL) {
+ DEBUG(1, "HBA_GetAdapterName: NULL pointer adatpername",
+ 0, 0, 0);
+ return (HBA_STATUS_ERROR_ARG);
+ }
+
+ /*
+ * The adapter index is from old code, but we have
+ * to support it. Go down the list looking for
+ * the adapter
+ */
+ ARE_WE_INITED();
+ GRAB_MUTEX(&_hbaapi_AL_mutex);
+ *adaptername = '\0';
+ for (adapt_infop = _hbaapi_adapterlist;
+ adapt_infop != NULL;
+ adapt_infop = adapt_infop->next) {
+
+ if (adapt_infop->index == adapterindex) {
+ if (adapt_infop->name != NULL &&
+ adapt_infop->GNstatus == HBA_STATUS_OK) {
+ (void) strcpy(adaptername, adapt_infop->name);
+ } else {
+ *adaptername = '\0';
+ }
+ ret = adapt_infop->GNstatus;
+ break;
+ }
+ }
+ DEBUG(2, "GetAdapterName for index:%d ->%s",
+ adapterindex, adaptername, 0);
+ RELEASE_MUTEX_RETURN(&_hbaapi_AL_mutex, ret);
+}
+
+HBA_HANDLE
+HBA_OpenAdapter(char *adaptername)
+{
+ HBA_HANDLE handle;
+ HBAOpenAdapterFunc OpenAdapterFunc;
+ HBA_ADAPTER_INFO *adapt_infop;
+ HBA_LIBRARY_INFO *lib_infop;
+
+ DEBUG(2, "OpenAdapter: %s", adaptername, 0, 0);
+
+ handle = HBA_HANDLE_INVALID;
+ if (_hbaapi_librarylist == NULL) {
+ return (handle);
+ }
+ if (adaptername == NULL) {
+ DEBUG(1, "HBA_OpenAdapter: NULL pointer adatpername",
+ 0, 0, 0);
+ return (handle);
+ }
+ GRAB_MUTEX(&_hbaapi_AL_mutex);
+ for (adapt_infop = _hbaapi_adapterlist;
+ adapt_infop != NULL;
+ adapt_infop = adapt_infop->next) {
+ if (strcmp(adaptername, adapt_infop->name) != 0) {
+ continue;
+ }
+ lib_infop = adapt_infop->library;
+ OpenAdapterFunc = FUNCCOMMON(lib_infop, OpenAdapterHandler);
+
+ if (OpenAdapterFunc != NULL) {
+ /* retrieve the vendor handle */
+ handle = (OpenAdapterFunc)(adaptername);
+ if (handle != 0) {
+ /* or this with the library index to get the common handle */
+ handle = HBA_HANDLE_FROM_LOCAL(lib_infop->index, handle);
+ }
+ }
+ break;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_AL_mutex, handle);
+}
+
+/*
+ * Finding an adapter with matching WWN.
+ */
+HBA_STATUS
+HBA_OpenAdapterByWWN(HBA_HANDLE *phandle, HBA_WWN nodeWWN) {
+ HBA_HANDLE handle;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBAGetNumberOfAdaptersFunc
+ GetNumberOfAdaptersFunc;
+ HBAOpenAdapterByWWNFunc
+ OpenAdapterFunc;
+ HBA_STATUS status;
+
+ DEBUG(2, "OpenAdapterByWWN: %s", WWN2STR1(&nodeWWN), 0, 0);
+ ARE_WE_INITED();
+
+ *phandle = HBA_HANDLE_INVALID;
+
+ GRAB_MUTEX(&_hbaapi_LL_mutex);
+ for (lib_infop = _hbaapi_librarylist;
+ lib_infop != NULL;
+ lib_infop = lib_infop->next) {
+
+ status = HBA_STATUS_ERROR_ILLEGAL_WWN;
+
+ if (lib_infop->status != HBA_LIBRARY_LOADED) {
+ continue;
+ }
+
+ /* only for HBAAPIV2 */
+ if (lib_infop->version != HBAAPIV2) {
+ continue;
+ }
+
+ GetNumberOfAdaptersFunc =
+ FUNCCOMMON(lib_infop, GetNumberOfAdaptersHandler);
+ if (GetNumberOfAdaptersFunc == NULL) {
+ continue;
+ }
+
+ /* look for new hardware */
+ (void) ((GetNumberOfAdaptersFunc)());
+
+ OpenAdapterFunc =
+ lib_infop->ftable.functionTable.OpenAdapterByWWNHandler;
+ if (OpenAdapterFunc == NULL) {
+ continue;
+ }
+ /*
+ * We do not know if the WWN is known by this vendor,
+ * just try it
+ */
+ if ((status = (OpenAdapterFunc)(&handle, nodeWWN)) != HBA_STATUS_OK) {
+ continue;
+ }
+ /* OK, make a vendor non-specific handle */
+ *phandle = HBA_HANDLE_FROM_LOCAL(lib_infop->index, handle);
+ status = HBA_STATUS_OK;
+ break;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+void
+HBA_RefreshAdapterConfiguration() {
+ DEBUG(2, "HBA_RefreshAdapterConfiguration", 0, 0, 0);
+ (void) HBA_GetNumberOfAdapters();
+}
+
+HBA_UINT32
+HBA_GetVersion() {
+ DEBUG(2, "HBA_GetVersion", 0, 0, 0);
+ return (HBA_LIBVERSION);
+}
+
+/*
+ * This function is VERY OS dependent. Wing it as best you can.
+ */
+HBA_UINT32
+HBA_GetWrapperLibraryAttributes(
+ HBA_LIBRARYATTRIBUTES *attributes)
+{
+
+ DEBUG(2, "HBA_GetWrapperLibraryAttributes", 0, 0, 0);
+
+ if (attributes == NULL) {
+ DEBUG(1, "HBA_GetWrapperLibraryAttributes:"
+ "NULL pointer attributes",
+ 0, 0, 0);
+ return (HBA_STATUS_ERROR_ARG);
+ }
+
+ (void) memset(attributes, 0, sizeof (HBA_LIBRARYATTRIBUTES));
+
+#if defined(SOLARIS)
+ if ((handle = dlopen("libHBAAPI.so", RTLD_NOW)) != NULL) {
+ if (dlinfo(handle, RTLD_DI_LINKMAP, &map) >= 0) {
+ for (mp = map; mp != NULL; mp = mp->l_next) {
+ if (strlen(map->l_name) < 256) {
+ (void) strcpy(attributes->LibPath, map->l_name);
+ }
+ }
+ }
+ }
+#elif defined(WIN32)
+ HMODULE module;
+
+ /* No need to do anything with the module handle */
+ /* It wasn't alloocated so it doesn't need to be freed */
+ module = GetModuleHandle("HBAAPI");
+ if (module != NULL) {
+ if (GetModuleFileName(module, attributes->LibPath,
+ sizeof (attributes->LibPath)) == 0) {
+ attributes->LibPath[0] = '\0';
+ }
+ }
+#endif
+#if defined(VENDOR)
+ (void) strcpy(attributes->VName, VENDOR);
+#else
+ attributes->VName[0] = '\0';
+#endif
+#if defined(VERSION)
+ (void) strcpy(attributes->VVersion, VERSION);
+#else
+ attributes->VVersion[0] = '\0';
+#endif
+#if defined(BUILD_DATE)
+#if defined(WIN32)
+ int matchCount;
+ matchCount = sscanf(BUILD_DATE, "%u/%u/%u %u:%u:%u",
+ &attributes->build_date.tm_year,
+ &attributes->build_date.tm_mon,
+ &attributes->build_date.tm_mday,
+ &attributes->build_date.tm_hour,
+ &attributes->build_date.tm_min,
+ &attributes->build_date.tm_sec);
+
+ if (matchCount != 6) {
+ memset(&attributes->build_date, 0, sizeof (struct tm));
+ } else {
+ attributes->build_date.tm_year -= 1900;
+ attributes->build_date.tm_isdst = -1;
+ }
+#else
+ if (strptime(BUILD_DATE,
+ "%Y/%m/%d %T %Z", &(attributes->build_date)) == NULL) {
+ (void) memset(&attributes->build_date, 0, sizeof (struct tm));
+ }
+#endif
+#else
+ (void) memset(&attributes->build_date, 0, sizeof (struct tm));
+#endif
+ return (2);
+}
+
+/*
+ * Callback registation and handling
+ */
+HBA_STATUS
+HBA_RemoveCallback(HBA_CALLBACKHANDLE cbhandle) {
+ HBA_STATUS status;
+
+ DEBUG(2, "HBA_RemoveCallback", 0, 0, 0);
+ ARE_WE_INITED();
+
+ GRAB_MUTEX(&_hbaapi_LL_mutex);
+ status = local_remove_callback(cbhandle);
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+/* Adapter Add Events ************************************************* */
+static void
+/* LINTED E_FUNC_ARG_UNUSED */
+adapteraddevents_callback(void *data, HBA_WWN PortWWN, HBA_UINT32 eventType) {
+ HBA_ALLADAPTERSCALLBACK_ELEM *cbp;
+
+ DEBUG(3, "AddAdapterEvent, port: %s", WWN2STR1(&PortWWN), 0, 0);
+
+ GRAB_MUTEX(&_hbaapi_AAE_mutex);
+ for (cbp = _hbaapi_adapteraddevents_callback_list;
+ cbp != NULL;
+ cbp = cbp->next) {
+ (*cbp->callback)(data, PortWWN, HBA_EVENT_ADAPTER_ADD);
+ }
+ RELEASE_MUTEX(&_hbaapi_AAE_mutex);
+
+}
+
+HBA_STATUS
+HBA_RegisterForAdapterAddEvents(
+ void (*callback)(
+ void *data,
+ HBA_WWN PortWWN,
+ HBA_UINT32 eventType),
+ void *userData,
+ HBA_CALLBACKHANDLE *callbackHandle) {
+
+ HBA_ALLADAPTERSCALLBACK_ELEM *cbp;
+ HBA_VENDORCALLBACK_ELEM *vcbp;
+ HBA_VENDORCALLBACK_ELEM *vendorhandlelist;
+ HBARegisterForAdapterAddEventsFunc registeredfunc;
+ HBA_STATUS status = HBA_STATUS_OK;
+ HBA_STATUS failure = HBA_STATUS_OK;
+ HBA_LIBRARY_INFO *lib_infop;
+ int registered_cnt = 0;
+ int vendor_cnt = 0;
+ int not_supported_cnt = 0;
+ int status_OK_bar_cnt = 0;
+ int status_OK_cnt = 0;
+
+ DEBUG(2, "HBA_RegisterForAdapterAddEvents", 0, 0, 0);
+ ARE_WE_INITED();
+
+ cbp = (HBA_ALLADAPTERSCALLBACK_ELEM *)
+ calloc(1, sizeof (HBA_ALLADAPTERSCALLBACK_ELEM));
+ *callbackHandle = (HBA_CALLBACKHANDLE) cbp;
+ if (cbp == NULL) {
+#ifndef WIN32
+ (void) fprintf(stderr,
+ "HBA_RegisterForAdapterAddEvents: calloc failed "
+ "for %lu bytes\n",
+ (unsigned long)(sizeof (HBA_ALLADAPTERSCALLBACK_ELEM)));
+#endif
+ return (HBA_STATUS_ERROR);
+ }
+
+ GRAB_MUTEX(&_hbaapi_LL_mutex);
+ GRAB_MUTEX(&_hbaapi_AAE_mutex);
+ cbp->callback = callback;
+ cbp->next = _hbaapi_adapteraddevents_callback_list;
+ _hbaapi_adapteraddevents_callback_list = cbp;
+ /*
+ * Need to release the mutex now incase the vendor function invokes the
+ * callback. We will grap the mutex later to attach the vendor handle
+ * list to the callback structure
+ */
+ RELEASE_MUTEX(&_hbaapi_AAE_mutex);
+
+ /*
+ * now create a list of vendors (vendor libraryies, NOT ADAPTERS)
+ * that have successfully registerred
+ */
+ vendorhandlelist = NULL;
+ for (lib_infop = _hbaapi_librarylist;
+ lib_infop != NULL;
+ lib_infop = lib_infop->next) {
+
+ /* only for HBAAPI V2 */
+ if ((lib_infop->version != HBAAPIV2)) {
+ continue;
+ } else {
+ vendor_cnt++;
+ }
+
+ registeredfunc =
+ lib_infop->ftable.functionTable.RegisterForAdapterAddEventsHandler;
+ if (registeredfunc == NULL) {
+ continue;
+ }
+
+ vcbp = (HBA_VENDORCALLBACK_ELEM *)
+ calloc(1, sizeof (HBA_VENDORCALLBACK_ELEM));
+ if (vcbp == NULL) {
+#ifndef WIN32
+ (void) fprintf(stderr,
+ "HBA_RegisterForAdapterAddEvents: "
+ "calloc failed for %lu bytes\n",
+ (unsigned long)(sizeof (HBA_VENDORCALLBACK_ELEM)));
+#endif
+ freevendorhandlelist(vendorhandlelist);
+ status = HBA_STATUS_ERROR;
+ break;
+ }
+
+ registered_cnt++;
+ status = (registeredfunc)(adapteraddevents_callback,
+ userData, &vcbp->vendorcbhandle);
+ if (status == HBA_STATUS_ERROR_NOT_SUPPORTED) {
+ not_supported_cnt++;
+ free(vcbp);
+ continue;
+ } else if (status != HBA_STATUS_OK) {
+ status_OK_bar_cnt++;
+ DEBUG(1,
+ "HBA_RegisterForAdapterAddEvents: Library->%s, Error->%d",
+ lib_infop->LibraryPath, status, 0);
+#ifndef WIN32
+ (void) fprintf(stderr,
+ "HBA_RegisterForAdapterAddEvents: Library->%s, Error->%d",
+ lib_infop->LibraryPath, status);
+#endif
+ failure = status;
+ free(vcbp);
+ continue;
+ } else {
+ status_OK_cnt++;
+ }
+ vcbp->lib_info = lib_infop;
+ vcbp->next = vendorhandlelist;
+ vendorhandlelist = vcbp;
+ }
+ if (vendor_cnt == 0) {
+ /* no HBAAPIV2 is deteced. should be okay? */
+ status = HBA_STATUS_ERROR;
+ } else if (registered_cnt == 0) {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ freevendorhandlelist(vendorhandlelist);
+ (void) local_remove_callback((HBA_CALLBACKHANDLE) cbp);
+ } else if (status_OK_cnt == 0 && not_supported_cnt != 0) {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ } else if (status_OK_cnt == 0) {
+ /*
+ * At least one vendor library registered this function, but no
+ * vendor call succeeded
+ */
+ (void) local_remove_callback((HBA_CALLBACKHANDLE) cbp);
+ status = failure;
+ } else {
+ /* we have had atleast some success, now finish up */
+ GRAB_MUTEX(&_hbaapi_AAE_mutex);
+ /*
+ * this seems silly, but what if another thread called
+ * the callback remove
+ */
+ for (cbp = _hbaapi_adapteraddevents_callback_list;
+ cbp != NULL; cbp = cbp->next) {
+ if ((HBA_CALLBACKHANDLE)cbp == *callbackHandle) {
+ /* yup, its still there, hooray */
+ cbp->vendorhandlelist = vendorhandlelist;
+ vendorhandlelist = NULL;
+ break;
+ }
+ }
+ RELEASE_MUTEX(&_hbaapi_AAE_mutex);
+ if (vendorhandlelist != NULL) {
+ /*
+ * bummer, somebody removed the callback before we finished
+ * registration, probably will never happen
+ */
+ freevendorhandlelist(vendorhandlelist);
+ DEBUG(1,
+ "HBA_RegisterForAdapterAddEvents: HBA_RemoveCallback was "
+ "called for a handle before registration was finished.",
+ 0, 0, 0);
+ status = HBA_STATUS_ERROR;
+ } else {
+ status = HBA_STATUS_OK;
+ }
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+/* Adapter Events (other than add) ************************************** */
+static void
+adapterevents_callback(void *data,
+ HBA_WWN PortWWN,
+ HBA_UINT32 eventType) {
+ HBA_ADAPTERCALLBACK_ELEM *acbp;
+
+ DEBUG(3, "AdapterEvent, port:%s, eventType:%d", WWN2STR1(&PortWWN),
+ eventType, 0);
+
+ GRAB_MUTEX(&_hbaapi_AE_mutex);
+ for (acbp = _hbaapi_adapterevents_callback_list;
+ acbp != NULL;
+ acbp = acbp->next) {
+ if (data == (void *)acbp) {
+ (*acbp->callback)(acbp->userdata, PortWWN, eventType);
+ break;
+ }
+ }
+ RELEASE_MUTEX(&_hbaapi_AE_mutex);
+}
+HBA_STATUS
+HBA_RegisterForAdapterEvents(
+ void (*callback) (
+ void *data,
+ HBA_WWN PortWWN,
+ HBA_UINT32 eventType),
+ void *userData,
+ HBA_HANDLE handle,
+ HBA_CALLBACKHANDLE *callbackHandle) {
+
+ HBA_ADAPTERCALLBACK_ELEM *acbp;
+ HBARegisterForAdapterEventsFunc registeredfunc;
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+
+ DEBUG(2, "HBA_RegisterForAdapterEvents", 0, 0, 0);
+
+ CHECKLIBRARYANDVERSION(HBAAPIV2);
+
+ /* we now have the _hbaapi_LL_mutex */
+
+ registeredfunc =
+ lib_infop->ftable.functionTable.RegisterForAdapterEventsHandler;
+ if (registeredfunc == NULL) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
+ }
+
+ /*
+ * that allocated memory is used both as the handle for the
+ * caller, and as userdata to the vendor call so that on
+ * callback the specific registration may be recalled
+ */
+ acbp = (HBA_ADAPTERCALLBACK_ELEM *)
+ calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
+ if (acbp == NULL) {
+#ifndef WIN32
+ (void) fprintf(stderr,
+ "HBA_RegisterForAdapterEvents: calloc failed for %lu bytes\n",
+ (unsigned long)(sizeof (HBA_ADAPTERCALLBACK_ELEM)));
+#endif
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
+ }
+ *callbackHandle = (HBA_CALLBACKHANDLE) acbp;
+ acbp->callback = callback;
+ acbp->userdata = userData;
+ acbp->lib_info = lib_infop;
+
+ status = (registeredfunc)(adapterevents_callback,
+ (void *)acbp,
+ vendorHandle,
+ &acbp->vendorcbhandle);
+ if (status != HBA_STATUS_OK) {
+ free(acbp);
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+ }
+
+ GRAB_MUTEX(&_hbaapi_AE_mutex);
+ acbp->next = _hbaapi_adapterevents_callback_list;
+ _hbaapi_adapterevents_callback_list = acbp;
+ RELEASE_MUTEX(&_hbaapi_AE_mutex);
+
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
+}
+
+/* Adapter Port Events ************************************************** */
+static void
+adapterportevents_callback(void *data,
+ HBA_WWN PortWWN,
+ HBA_UINT32 eventType,
+ HBA_UINT32 fabricPortID) {
+ HBA_ADAPTERCALLBACK_ELEM *acbp;
+
+ DEBUG(3, "AdapterPortEvent, port:%s, eventType:%d fabricPortID:0X%06x",
+ WWN2STR1(&PortWWN), eventType, fabricPortID);
+
+ GRAB_MUTEX(&_hbaapi_APE_mutex);
+
+ for (acbp = _hbaapi_adapterportevents_callback_list;
+ acbp != NULL;
+ acbp = acbp->next) {
+ if (data == (void *)acbp) {
+ (*acbp->callback)(acbp->userdata, PortWWN, eventType, fabricPortID);
+ break;
+ }
+ }
+ RELEASE_MUTEX(&_hbaapi_APE_mutex);
+}
+
+HBA_STATUS
+HBA_RegisterForAdapterPortEvents(
+ void (*callback) (
+ void *data,
+ HBA_WWN PortWWN,
+ HBA_UINT32 eventType,
+ HBA_UINT32 fabricPortID),
+ void *userData,
+ HBA_HANDLE handle,
+ HBA_WWN PortWWN,
+ HBA_CALLBACKHANDLE *callbackHandle) {
+
+ HBA_ADAPTERCALLBACK_ELEM *acbp;
+ HBARegisterForAdapterPortEventsFunc registeredfunc;
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+
+ DEBUG(2, "HBA_RegisterForAdapterPortEvents for port: %s",
+ WWN2STR1(&PortWWN), 0, 0);
+
+ CHECKLIBRARYANDVERSION(HBAAPIV2);
+ /* we now have the _hbaapi_LL_mutex */
+
+ registeredfunc =
+ lib_infop->ftable.functionTable.RegisterForAdapterPortEventsHandler;
+ if (registeredfunc == NULL) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
+ }
+
+ /*
+ * that allocated memory is used both as the handle for the
+ * caller, and as userdata to the vendor call so that on
+ * callback the specific registration may be recalled
+ */
+ acbp = (HBA_ADAPTERCALLBACK_ELEM *)
+ calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
+ if (acbp == NULL) {
+#ifndef WIN32
+ (void) fprintf(stderr,
+ "HBA_RegisterForAdapterPortEvents: "
+ "calloc failed for %lu bytes\n",
+ (unsigned long)(sizeof (HBA_ADAPTERCALLBACK_ELEM)));
+#endif
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
+
+ }
+ *callbackHandle = (HBA_CALLBACKHANDLE) acbp;
+ acbp->callback = callback;
+ acbp->userdata = userData;
+ acbp->lib_info = lib_infop;
+
+ status = (registeredfunc)(adapterportevents_callback,
+ (void *)acbp,
+ vendorHandle,
+ PortWWN,
+ &acbp->vendorcbhandle);
+ if (status != HBA_STATUS_OK) {
+ free(acbp);
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+ }
+
+ GRAB_MUTEX(&_hbaapi_APE_mutex);
+ acbp->next = _hbaapi_adapterportevents_callback_list;
+ _hbaapi_adapterportevents_callback_list = acbp;
+ RELEASE_MUTEX(&_hbaapi_APE_mutex);
+
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
+}
+
+/* Adapter State Events ************************************************ */
+static void
+adapterportstatevents_callback(void *data,
+ HBA_WWN PortWWN,
+ HBA_UINT32 eventType) {
+ HBA_ADAPTERCALLBACK_ELEM *acbp;
+
+ DEBUG(3, "AdapterPortStatEvent, port:%s, eventType:%d",
+ WWN2STR1(&PortWWN),
+ eventType, 0);
+
+ GRAB_MUTEX(&_hbaapi_APSE_mutex);
+ for (acbp = _hbaapi_adapterportstatevents_callback_list;
+ acbp != NULL;
+ acbp = acbp->next) {
+ if (data == (void *)acbp) {
+ (*acbp->callback)(acbp->userdata, PortWWN, eventType);
+ return;
+ }
+ }
+ RELEASE_MUTEX(&_hbaapi_APSE_mutex);
+}
+HBA_STATUS
+HBA_RegisterForAdapterPortStatEvents(
+ void (*callback) (
+ void *data,
+ HBA_WWN PortWWN,
+ HBA_UINT32 eventType),
+ void *userData,
+ HBA_HANDLE handle,
+ HBA_WWN PortWWN,
+ HBA_PORTSTATISTICS stats,
+ HBA_UINT32 statType,
+ HBA_CALLBACKHANDLE *callbackHandle) {
+
+ HBA_ADAPTERCALLBACK_ELEM *acbp;
+ HBARegisterForAdapterPortStatEventsFunc
+ registeredfunc;
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+
+ DEBUG(2, "HBA_RegisterForAdapterPortStatEvents for port: %s",
+ WWN2STR1(&PortWWN), 0, 0);
+
+ CHECKLIBRARYANDVERSION(HBAAPIV2);
+ /* we now have the _hbaapi_LL_mutex */
+
+ registeredfunc =
+ lib_infop->ftable.functionTable.RegisterForAdapterPortStatEventsHandler;
+ if (registeredfunc == NULL) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
+ }
+
+ /*
+ * that allocated memory is used both as the handle for the
+ * caller, and as userdata to the vendor call so that on
+ * callback the specific registration may be recalled
+ */
+ acbp = (HBA_ADAPTERCALLBACK_ELEM *)
+ calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
+ if (acbp == NULL) {
+#ifndef WIN32
+ (void) fprintf(stderr,
+ "HBA_RegisterForAdapterPortStatEvents: "
+ "calloc failed for %lu bytes\n",
+ (unsigned long)(sizeof (HBA_ADAPTERCALLBACK_ELEM)));
+#endif
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
+ }
+ *callbackHandle = (HBA_CALLBACKHANDLE) acbp;
+ acbp->callback = callback;
+ acbp->userdata = userData;
+ acbp->lib_info = lib_infop;
+
+ status = (registeredfunc)(adapterportstatevents_callback,
+ (void *)acbp,
+ vendorHandle,
+ PortWWN,
+ stats,
+ statType,
+ &acbp->vendorcbhandle);
+ if (status != HBA_STATUS_OK) {
+ free(acbp);
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+ }
+
+ GRAB_MUTEX(&_hbaapi_APSE_mutex);
+ acbp->next = _hbaapi_adapterportstatevents_callback_list;
+ _hbaapi_adapterportstatevents_callback_list = acbp;
+ RELEASE_MUTEX(&_hbaapi_APSE_mutex);
+
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
+}
+
+/* Target Events ******************************************************* */
+static void
+targetevents_callback(void *data,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN discoveredPortWWN,
+ HBA_UINT32 eventType) {
+
+ HBA_ADAPTERCALLBACK_ELEM *acbp;
+
+ DEBUG(3, "TargetEvent, hbaPort:%s, discoveredPort:%s eventType:%d",
+ WWN2STR1(&hbaPortWWN), WWN2STR2(&discoveredPortWWN), eventType);
+
+ GRAB_MUTEX(&_hbaapi_TE_mutex);
+ for (acbp = _hbaapi_targetevents_callback_list;
+ acbp != NULL;
+ acbp = acbp->next) {
+ if (data == (void *)acbp) {
+ (*acbp->callback)(acbp->userdata, hbaPortWWN,
+ discoveredPortWWN, eventType);
+ break;
+ }
+ }
+ RELEASE_MUTEX(&_hbaapi_TE_mutex);
+}
+
+HBA_STATUS
+HBA_RegisterForTargetEvents(
+ void (*callback) (
+ void *data,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN discoveredPortWWN,
+ HBA_UINT32 eventType),
+ void *userData,
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN discoveredPortWWN,
+ HBA_CALLBACKHANDLE *callbackHandle,
+ HBA_UINT32 allTargets) {
+
+ HBA_ADAPTERCALLBACK_ELEM
+ *acbp;
+ HBARegisterForTargetEventsFunc
+ registeredfunc;
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+
+ DEBUG(2, "HBA_RegisterForTargetEvents, hbaPort: %s, discoveredPort: %s",
+ WWN2STR1(&hbaPortWWN), WWN2STR2(&discoveredPortWWN), 0);
+
+ CHECKLIBRARYANDVERSION(HBAAPIV2);
+ /* we now have the _hbaapi_LL_mutex */
+
+ registeredfunc =
+ lib_infop->ftable.functionTable.RegisterForTargetEventsHandler;
+ if (registeredfunc == NULL) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
+ }
+
+ /*
+ * that allocated memory is used both as the handle for the
+ * caller, and as userdata to the vendor call so that on
+ * callback the specific registration may be recalled
+ */
+ acbp = (HBA_ADAPTERCALLBACK_ELEM *)
+ calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
+ if (acbp == NULL) {
+#ifndef WIN32
+ (void) fprintf(stderr,
+ "HBA_RegisterForTargetEvents: calloc failed for %lu bytes\n",
+ (unsigned long)(sizeof (HBA_ADAPTERCALLBACK_ELEM)));
+#endif
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
+ }
+ *callbackHandle = (HBA_CALLBACKHANDLE) acbp;
+ acbp->callback = callback;
+ acbp->userdata = userData;
+ acbp->lib_info = lib_infop;
+
+ status = (registeredfunc)(targetevents_callback,
+ (void *)acbp,
+ vendorHandle,
+ hbaPortWWN,
+ discoveredPortWWN,
+ &acbp->vendorcbhandle,
+ allTargets);
+ if (status != HBA_STATUS_OK) {
+ free(acbp);
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+ }
+
+ GRAB_MUTEX(&_hbaapi_TE_mutex);
+ acbp->next = _hbaapi_targetevents_callback_list;
+ _hbaapi_targetevents_callback_list = acbp;
+ RELEASE_MUTEX(&_hbaapi_TE_mutex);
+
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
+}
+
+/* Link Events ********************************************************* */
+static void
+linkevents_callback(void *data,
+ HBA_WWN adapterWWN,
+ HBA_UINT32 eventType,
+ void *pRLIRBuffer,
+ HBA_UINT32 RLIRBufferSize) {
+ HBA_ADAPTERCALLBACK_ELEM *acbp;
+
+ DEBUG(3, "LinkEvent, hbaWWN:%s, eventType:%d",
+ WWN2STR1(&adapterWWN), eventType, 0);
+
+ GRAB_MUTEX(&_hbaapi_LE_mutex);
+ for (acbp = _hbaapi_linkevents_callback_list;
+ acbp != NULL;
+ acbp = acbp->next) {
+ if (data == (void *)acbp) {
+ (*acbp->callback)(acbp->userdata, adapterWWN,
+ eventType, pRLIRBuffer, RLIRBufferSize);
+ break;
+ }
+ }
+ RELEASE_MUTEX(&_hbaapi_LE_mutex);
+}
+HBA_STATUS
+HBA_RegisterForLinkEvents(
+ void (*callback) (
+ void *data,
+ HBA_WWN adapterWWN,
+ HBA_UINT32 eventType,
+ void *pRLIRBuffer,
+ HBA_UINT32 RLIRBufferSize),
+ void *userData,
+ void *pRLIRBuffer,
+ HBA_UINT32 RLIRBufferSize,
+ HBA_HANDLE handle,
+ HBA_CALLBACKHANDLE *callbackHandle) {
+
+ HBA_ADAPTERCALLBACK_ELEM *acbp;
+ HBARegisterForLinkEventsFunc
+ registeredfunc;
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+
+ DEBUG(2, "HBA_RegisterForLinkEvents", 0, 0, 0);
+
+ CHECKLIBRARY();
+ /* we now have the _hbaapi_LL_mutex */
+
+ registeredfunc = FUNCCOMMON(lib_infop, RegisterForLinkEventsHandler);
+
+ if (registeredfunc == NULL) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
+ }
+
+ /*
+ * that allocated memory is used both as the handle for the
+ * caller, and as userdata to the vendor call so that on
+ * callback the specific registration may be recalled
+ */
+ acbp = (HBA_ADAPTERCALLBACK_ELEM *)
+ calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
+ if (acbp == NULL) {
+#ifndef WIN32
+ (void) fprintf(stderr,
+ "HBA_RegisterForLinkEvents: calloc failed for %lu bytes\n",
+ (unsigned long)(sizeof (HBA_ADAPTERCALLBACK_ELEM)));
+#endif
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
+ }
+ *callbackHandle = (HBA_CALLBACKHANDLE) acbp;
+ acbp->callback = callback;
+ acbp->userdata = userData;
+ acbp->lib_info = lib_infop;
+
+ status = (registeredfunc)(linkevents_callback,
+ (void *)acbp,
+ pRLIRBuffer,
+ RLIRBufferSize,
+ vendorHandle,
+ &acbp->vendorcbhandle);
+ if (status != HBA_STATUS_OK) {
+ free(acbp);
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+ }
+
+ GRAB_MUTEX(&_hbaapi_LE_mutex);
+ acbp->next = _hbaapi_linkevents_callback_list;
+ _hbaapi_linkevents_callback_list = acbp;
+ RELEASE_MUTEX(&_hbaapi_LE_mutex);
+
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
+}
+
+/*
+ * All of the functions below are almost passthru functions to the
+ * vendor specific function
+ */
+
+void
+HBA_CloseAdapter(HBA_HANDLE handle) {
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBACloseAdapterFunc CloseAdapterFunc;
+
+ DEBUG(2, "HBA_CloseAdapter", 0, 0, 0);
+
+ status = HBA_CheckLibrary(handle, &lib_infop, &vendorHandle);
+ if (status == HBA_STATUS_OK) {
+ CloseAdapterFunc = FUNCCOMMON(lib_infop, CloseAdapterHandler);
+ if (CloseAdapterFunc != NULL) {
+ ((CloseAdapterFunc)(vendorHandle));
+ }
+ RELEASE_MUTEX(&_hbaapi_LL_mutex);
+ }
+}
+
+HBA_STATUS
+HBA_GetAdapterAttributes(
+ HBA_HANDLE handle,
+ HBA_ADAPTERATTRIBUTES
+ *hbaattributes)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBAGetAdapterAttributesFunc GetAdapterAttributesFunc;
+
+ DEBUG(2, "HBA_GetAdapterAttributes", 0, 0, 0);
+
+ CHECKLIBRARY();
+
+ if (lib_infop->version == SMHBA) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
+ }
+
+ GetAdapterAttributesFunc =
+ lib_infop->ftable.functionTable.GetAdapterAttributesHandler;
+ if (GetAdapterAttributesFunc != NULL) {
+ status = ((GetAdapterAttributesFunc)(vendorHandle, hbaattributes));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_GetAdapterPortAttributes(
+ HBA_HANDLE handle,
+ HBA_UINT32 portindex,
+ HBA_PORTATTRIBUTES *portattributes)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBAGetAdapterPortAttributesFunc
+ GetAdapterPortAttributesFunc;
+
+ DEBUG(2, "HBA_GetAdapterPortAttributes", 0, 0, 0);
+
+ CHECKLIBRARY();
+ if (lib_infop->version == SMHBA) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
+ }
+
+ GetAdapterPortAttributesFunc =
+ lib_infop->ftable.functionTable.GetAdapterPortAttributesHandler;
+ if (GetAdapterPortAttributesFunc != NULL) {
+ status = ((GetAdapterPortAttributesFunc)
+ (vendorHandle, portindex, portattributes));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_GetPortStatistics(
+ HBA_HANDLE handle,
+ HBA_UINT32 portindex,
+ HBA_PORTSTATISTICS *portstatistics)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBAGetPortStatisticsFunc
+ GetPortStatisticsFunc;
+
+ DEBUG(2, "HBA_GetPortStatistics", 0, 0, 0);
+
+ CHECKLIBRARY();
+ if (lib_infop->version == SMHBA) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
+ }
+
+ GetPortStatisticsFunc =
+ lib_infop->ftable.functionTable.GetPortStatisticsHandler;
+ if (GetPortStatisticsFunc != NULL) {
+ status = ((GetPortStatisticsFunc)
+ (vendorHandle, portindex, portstatistics));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_GetDiscoveredPortAttributes(
+ HBA_HANDLE handle,
+ HBA_UINT32 portindex,
+ HBA_UINT32 discoveredportindex,
+ HBA_PORTATTRIBUTES *portattributes)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBAGetDiscoveredPortAttributesFunc
+ GetDiscoveredPortAttributesFunc;
+
+ DEBUG(2, "HBA_GetDiscoveredPortAttributes", 0, 0, 0);
+
+ CHECKLIBRARY();
+ if (lib_infop->version == SMHBA) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
+ }
+
+ GetDiscoveredPortAttributesFunc =
+ lib_infop->ftable.functionTable.GetDiscoveredPortAttributesHandler;
+ if (GetDiscoveredPortAttributesFunc != NULL) {
+ status = ((GetDiscoveredPortAttributesFunc)
+ (vendorHandle, portindex, discoveredportindex,
+ portattributes));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_GetPortAttributesByWWN(
+ HBA_HANDLE handle,
+ HBA_WWN PortWWN,
+ HBA_PORTATTRIBUTES *portattributes)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBAGetPortAttributesByWWNFunc
+ GetPortAttributesByWWNFunc;
+
+ DEBUG(2, "HBA_GetPortAttributesByWWN: %s", WWN2STR1(&PortWWN), 0, 0);
+
+ CHECKLIBRARY();
+ if (lib_infop->version == SMHBA) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
+ }
+
+ GetPortAttributesByWWNFunc =
+ lib_infop->ftable.functionTable.GetPortAttributesByWWNHandler;
+ if (GetPortAttributesByWWNFunc != NULL) {
+ status = ((GetPortAttributesByWWNFunc)
+ (vendorHandle, PortWWN, portattributes));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_SendCTPassThru(
+ HBA_HANDLE handle,
+ void *pReqBuffer,
+ HBA_UINT32 ReqBufferSize,
+ void *pRspBuffer,
+ HBA_UINT32 RspBufferSize)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBASendCTPassThruFunc
+ SendCTPassThruFunc;
+
+ DEBUG(2, "HBA_SendCTPassThru", 0, 0, 0);
+
+ CHECKLIBRARY();
+ if (lib_infop->version == SMHBA) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
+ }
+
+ SendCTPassThruFunc =
+ lib_infop->ftable.functionTable.SendCTPassThruHandler;
+ if (SendCTPassThruFunc != NULL) {
+ status = (SendCTPassThruFunc)
+ (vendorHandle,
+ pReqBuffer, ReqBufferSize,
+ pRspBuffer, RspBufferSize);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_SendCTPassThruV2(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ void *pReqBuffer,
+ HBA_UINT32 ReqBufferSize,
+ void *pRspBuffer,
+ HBA_UINT32 *pRspBufferSize)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBASendCTPassThruV2Func
+ registeredfunc;
+
+ DEBUG(2, "HBA_SendCTPassThruV2m hbaPortWWN: %s",
+ WWN2STR1(&hbaPortWWN), 0, 0);
+
+ CHECKLIBRARYANDVERSION(HBAAPIV2);
+ registeredfunc = FUNCCOMMON(lib_infop, SendCTPassThruV2Handler);
+ if (registeredfunc != NULL) {
+ status = (registeredfunc)
+ (vendorHandle, hbaPortWWN,
+ pReqBuffer, ReqBufferSize,
+ pRspBuffer, pRspBufferSize);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_GetEventBuffer(
+ HBA_HANDLE handle,
+ PHBA_EVENTINFO EventBuffer,
+ HBA_UINT32 *EventBufferCount)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBAGetEventBufferFunc
+ GetEventBufferFunc;
+
+ DEBUG(2, "HBA_GetEventBuffer", 0, 0, 0);
+
+ CHECKLIBRARY();
+ if (lib_infop->version == SMHBA) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
+ }
+
+ GetEventBufferFunc =
+ lib_infop->ftable.functionTable.GetEventBufferHandler;
+ if (GetEventBufferFunc != NULL) {
+ status = (GetEventBufferFunc)
+ (vendorHandle, EventBuffer, EventBufferCount);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_SetRNIDMgmtInfo(HBA_HANDLE handle, HBA_MGMTINFO Info) {
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBASetRNIDMgmtInfoFunc
+ SetRNIDMgmtInfoFunc;
+
+ DEBUG(2, "HBA_SetRNIDMgmtInfo", 0, 0, 0);
+
+ CHECKLIBRARY();
+ SetRNIDMgmtInfoFunc = FUNCCOMMON(lib_infop, SetRNIDMgmtInfoHandler);
+ if (SetRNIDMgmtInfoFunc != NULL) {
+ status = (SetRNIDMgmtInfoFunc)(vendorHandle, Info);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_GetRNIDMgmtInfo(HBA_HANDLE handle, HBA_MGMTINFO *pInfo) {
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBAGetRNIDMgmtInfoFunc
+ GetRNIDMgmtInfoFunc;
+
+ DEBUG(2, "HBA_GetRNIDMgmtInfo", 0, 0, 0);
+
+ CHECKLIBRARY();
+ GetRNIDMgmtInfoFunc = FUNCCOMMON(lib_infop, GetRNIDMgmtInfoHandler);
+ if (GetRNIDMgmtInfoFunc != NULL) {
+ status = (GetRNIDMgmtInfoFunc)(vendorHandle, pInfo);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_SendRNID(
+ HBA_HANDLE handle,
+ HBA_WWN wwn,
+ HBA_WWNTYPE wwntype,
+ void *pRspBuffer,
+ HBA_UINT32 *pRspBufferSize)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBASendRNIDFunc SendRNIDFunc;
+
+ DEBUG(2, "HBA_SendRNID for wwn: %s", WWN2STR1(&wwn), 0, 0);
+
+ CHECKLIBRARY();
+ if (lib_infop->version == SMHBA) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
+ }
+
+ SendRNIDFunc = lib_infop->ftable.functionTable.SendRNIDHandler;
+ if (SendRNIDFunc != NULL) {
+ status = ((SendRNIDFunc)(vendorHandle, wwn, wwntype,
+ pRspBuffer, pRspBufferSize));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_SendRNIDV2(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN destWWN,
+ HBA_UINT32 destFCID,
+ HBA_UINT32 NodeIdDataFormat,
+ void *pRspBuffer,
+ HBA_UINT32 *pRspBufferSize)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBASendRNIDV2Func registeredfunc;
+
+ DEBUG(2, "HBA_SendRNIDV2, hbaPortWWN: %s", WWN2STR1(&hbaPortWWN), 0, 0);
+
+ CHECKLIBRARY();
+ registeredfunc = FUNCCOMMON(lib_infop, SendRNIDV2Handler);
+ if (registeredfunc != NULL) {
+ status = (registeredfunc)
+ (vendorHandle, hbaPortWWN, destWWN, destFCID, NodeIdDataFormat,
+ pRspBuffer, pRspBufferSize);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+void
+HBA_RefreshInformation(HBA_HANDLE handle) {
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBARefreshInformationFunc
+ RefreshInformationFunc;
+
+ DEBUG(2, "HBA_RefreshInformation", 0, 0, 0);
+
+ status = HBA_CheckLibrary(handle, &lib_infop, &vendorHandle);
+ if (status == HBA_STATUS_OK) {
+ RefreshInformationFunc =
+ FUNCCOMMON(lib_infop, RefreshInformationHandler);
+ if (RefreshInformationFunc != NULL) {
+ ((RefreshInformationFunc)(vendorHandle));
+ }
+ RELEASE_MUTEX(&_hbaapi_LL_mutex);
+ }
+}
+
+void
+HBA_ResetStatistics(HBA_HANDLE handle, HBA_UINT32 portindex) {
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBAResetStatisticsFunc
+ ResetStatisticsFunc;
+
+ DEBUG(2, "HBA_ResetStatistics", 0, 0, 0);
+
+ status = HBA_CheckLibrary(handle, &lib_infop, &vendorHandle);
+ if (status == HBA_STATUS_OK) {
+ if (lib_infop->version == SMHBA) {
+ RELEASE_MUTEX(&_hbaapi_LL_mutex);
+ }
+
+ ResetStatisticsFunc =
+ lib_infop->ftable.functionTable.ResetStatisticsHandler;
+ if (ResetStatisticsFunc != NULL) {
+ ((ResetStatisticsFunc)(vendorHandle, portindex));
+ }
+ RELEASE_MUTEX(&_hbaapi_LL_mutex);
+ }
+}
+
+HBA_STATUS
+HBA_GetFcpTargetMapping(HBA_HANDLE handle, PHBA_FCPTARGETMAPPING mapping) {
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBAGetFcpTargetMappingFunc GetFcpTargetMappingFunc;
+
+ DEBUG(2, "HBA_GetFcpTargetMapping", 0, 0, 0);
+
+ CHECKLIBRARY();
+ if (lib_infop->version == SMHBA) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
+ }
+
+ GetFcpTargetMappingFunc =
+ lib_infop->ftable.functionTable.GetFcpTargetMappingHandler;
+ if (GetFcpTargetMappingFunc != NULL) {
+ status = ((GetFcpTargetMappingFunc)(vendorHandle, mapping));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_GetFcpTargetMappingV2(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_FCPTARGETMAPPINGV2 *pmapping)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBAGetFcpTargetMappingV2Func
+ registeredfunc;
+
+ DEBUG(2, "HBA_GetFcpTargetMapping", 0, 0, 0);
+
+ CHECKLIBRARYANDVERSION(HBAAPIV2);
+
+ registeredfunc =
+ lib_infop->ftable.functionTable.GetFcpTargetMappingV2Handler;
+ if (registeredfunc != NULL) {
+ status = ((registeredfunc)(vendorHandle, hbaPortWWN, pmapping));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_GetFcpPersistentBinding(HBA_HANDLE handle, PHBA_FCPBINDING binding) {
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBAGetFcpPersistentBindingFunc
+ GetFcpPersistentBindingFunc;
+
+ DEBUG(2, "HBA_GetFcpPersistentBinding", 0, 0, 0);
+
+ CHECKLIBRARY();
+ if (lib_infop->version == SMHBA) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
+ }
+
+ GetFcpPersistentBindingFunc =
+ lib_infop->ftable.functionTable.GetFcpPersistentBindingHandler;
+ if (GetFcpPersistentBindingFunc != NULL) {
+ status = ((GetFcpPersistentBindingFunc)(vendorHandle, binding));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_ScsiInquiryV2(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN discoveredPortWWN,
+ HBA_UINT64 fcLUN,
+ HBA_UINT8 CDB_Byte1,
+ HBA_UINT8 CDB_Byte2,
+ void *pRspBuffer,
+ HBA_UINT32 *pRspBufferSize,
+ HBA_UINT8 *pScsiStatus,
+ void *pSenseBuffer,
+ HBA_UINT32 *pSenseBufferSize)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBAScsiInquiryV2Func ScsiInquiryV2Func;
+
+ DEBUG(2, "HBA_ScsiInquiryV2 to discoveredPortWWN: %s",
+ WWN2STR1(&discoveredPortWWN), 0, 0);
+
+ CHECKLIBRARYANDVERSION(HBAAPIV2);
+
+ ScsiInquiryV2Func =
+ lib_infop->ftable.functionTable.ScsiInquiryV2Handler;
+ if (ScsiInquiryV2Func != NULL) {
+ status = ((ScsiInquiryV2Func)(
+ vendorHandle, hbaPortWWN, discoveredPortWWN, fcLUN, CDB_Byte1,
+ CDB_Byte2, pRspBuffer, pRspBufferSize, pScsiStatus,
+ pSenseBuffer, pSenseBufferSize));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_SendScsiInquiry(
+ HBA_HANDLE handle,
+ HBA_WWN PortWWN,
+ HBA_UINT64 fcLUN,
+ HBA_UINT8 EVPD,
+ HBA_UINT32 PageCode,
+ void *pRspBuffer,
+ HBA_UINT32 RspBufferSize,
+ void *pSenseBuffer,
+ HBA_UINT32 SenseBufferSize)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBASendScsiInquiryFunc SendScsiInquiryFunc;
+
+ DEBUG(2, "HBA_SendScsiInquiry to PortWWN: %s",
+ WWN2STR1(&PortWWN), 0, 0);
+
+ CHECKLIBRARY();
+ if (lib_infop->version == SMHBA) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
+ }
+
+ SendScsiInquiryFunc =
+ lib_infop->ftable.functionTable.ScsiInquiryHandler;
+ if (SendScsiInquiryFunc != NULL) {
+ status = ((SendScsiInquiryFunc)(
+ vendorHandle, PortWWN, fcLUN, EVPD, PageCode, pRspBuffer,
+ RspBufferSize, pSenseBuffer, SenseBufferSize));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_ScsiReportLUNsV2(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN discoveredPortWWN,
+ void *pRespBuffer,
+ HBA_UINT32 *pRespBufferSize,
+ HBA_UINT8 *pScsiStatus,
+ void *pSenseBuffer,
+ HBA_UINT32 *pSenseBufferSize)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBAScsiReportLUNsV2Func ScsiReportLUNsV2Func;
+
+ DEBUG(2, "HBA_ScsiReportLUNsV2 to discoveredPortWWN: %s",
+ WWN2STR1(&discoveredPortWWN), 0, 0);
+
+ CHECKLIBRARYANDVERSION(HBAAPIV2);
+
+ ScsiReportLUNsV2Func =
+ lib_infop->ftable.functionTable.ScsiReportLUNsV2Handler;
+ if (ScsiReportLUNsV2Func != NULL) {
+ status = ((ScsiReportLUNsV2Func)(
+ vendorHandle, hbaPortWWN, discoveredPortWWN,
+ pRespBuffer, pRespBufferSize,
+ pScsiStatus,
+ pSenseBuffer, pSenseBufferSize));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_SendReportLUNs(
+ HBA_HANDLE handle,
+ HBA_WWN portWWN,
+ void *pRspBuffer,
+ HBA_UINT32 RspBufferSize,
+ void *pSenseBuffer,
+ HBA_UINT32 SenseBufferSize)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBASendReportLUNsFunc SendReportLUNsFunc;
+
+ DEBUG(2, "HBA_SendReportLUNs to PortWWN: %s", WWN2STR1(&portWWN), 0, 0);
+
+ CHECKLIBRARY();
+ if (lib_infop->version == SMHBA) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
+ }
+
+ SendReportLUNsFunc = lib_infop->ftable.functionTable.ReportLUNsHandler;
+ if (SendReportLUNsFunc != NULL) {
+ status = ((SendReportLUNsFunc)(
+ vendorHandle, portWWN, pRspBuffer,
+ RspBufferSize, pSenseBuffer, SenseBufferSize));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_ScsiReadCapacityV2(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN discoveredPortWWN,
+ HBA_UINT64 fcLUN,
+ void *pRspBuffer,
+ HBA_UINT32 *pRspBufferSize,
+ HBA_UINT8 *pScsiStatus,
+ void *pSenseBuffer,
+ HBA_UINT32 *SenseBufferSize)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBAScsiReadCapacityV2Func ScsiReadCapacityV2Func;
+
+ DEBUG(2, "HBA_ScsiReadCapacityV2 to discoveredPortWWN: %s",
+ WWN2STR1(&discoveredPortWWN), 0, 0);
+
+ CHECKLIBRARYANDVERSION(HBAAPIV2);
+
+ ScsiReadCapacityV2Func =
+ lib_infop->ftable.functionTable.ScsiReadCapacityV2Handler;
+ if (ScsiReadCapacityV2Func != NULL) {
+ status = ((ScsiReadCapacityV2Func)(
+ vendorHandle, hbaPortWWN, discoveredPortWWN, fcLUN,
+ pRspBuffer, pRspBufferSize,
+ pScsiStatus,
+ pSenseBuffer, SenseBufferSize));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_SendReadCapacity(
+ HBA_HANDLE handle,
+ HBA_WWN portWWN,
+ HBA_UINT64 fcLUN,
+ void *pRspBuffer,
+ HBA_UINT32 RspBufferSize,
+ void *pSenseBuffer,
+ HBA_UINT32 SenseBufferSize)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBASendReadCapacityFunc SendReadCapacityFunc;
+
+ DEBUG(2, "HBA_SendReadCapacity to portWWN: %s",
+ WWN2STR1(&portWWN), 0, 0);
+
+ CHECKLIBRARY();
+ if (lib_infop->version == SMHBA) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_INCOMPATIBLE);
+ }
+
+ SendReadCapacityFunc =
+ lib_infop->ftable.functionTable.ReadCapacityHandler;
+ if (SendReadCapacityFunc != NULL) {
+ status = ((SendReadCapacityFunc)
+ (vendorHandle, portWWN, fcLUN, pRspBuffer,
+ RspBufferSize, pSenseBuffer, SenseBufferSize));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_SendRPL(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN agent_wwn,
+ HBA_UINT32 agent_domain,
+ HBA_UINT32 portindex,
+ void *pRspBuffer,
+ HBA_UINT32 *pRspBufferSize)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBASendRPLFunc registeredfunc;
+
+ DEBUG(2, "HBA_SendRPL to agent_wwn: %s:%d",
+ WWN2STR1(&agent_wwn), agent_domain, 0);
+
+ CHECKLIBRARY();
+ registeredfunc = FUNCCOMMON(lib_infop, SendRPLHandler);
+ if (registeredfunc != NULL) {
+ status = (registeredfunc)(
+ vendorHandle, hbaPortWWN, agent_wwn, agent_domain, portindex,
+ pRspBuffer, pRspBufferSize);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_SendRPS(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN agent_wwn,
+ HBA_UINT32 agent_domain,
+ HBA_WWN object_wwn,
+ HBA_UINT32 object_port_number,
+ void *pRspBuffer,
+ HBA_UINT32 *pRspBufferSize)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBASendRPSFunc registeredfunc;
+
+ DEBUG(2, "HBA_SendRPS to agent_wwn: %s:%d",
+ WWN2STR1(&agent_wwn), agent_domain, 0);
+
+ CHECKLIBRARY();
+ registeredfunc = FUNCCOMMON(lib_infop, SendRPSHandler);
+ if (registeredfunc != NULL) {
+ status = (registeredfunc)(
+ vendorHandle, hbaPortWWN, agent_wwn, agent_domain,
+ object_wwn, object_port_number,
+ pRspBuffer, pRspBufferSize);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_SendSRL(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN wwn,
+ HBA_UINT32 domain,
+ void *pRspBuffer,
+ HBA_UINT32 *pRspBufferSize)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBASendSRLFunc registeredfunc;
+
+ DEBUG(2, "HBA_SendSRL to wwn:%s domain:%d", WWN2STR1(&wwn), domain, 0);
+
+ CHECKLIBRARY();
+ registeredfunc = FUNCCOMMON(lib_infop, SendSRLHandler);
+ if (registeredfunc != NULL) {
+ status = (registeredfunc)(
+ vendorHandle, hbaPortWWN, wwn, domain,
+ pRspBuffer, pRspBufferSize);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+HBA_STATUS
+HBA_SendRLS(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN destWWN,
+ void *pRspBuffer,
+ HBA_UINT32 *pRspBufferSize)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBASendRLSFunc registeredfunc;
+
+ DEBUG(2, "HBA_SendRLS dest_wwn: %s",
+ WWN2STR1(&destWWN), 0, 0);
+
+ CHECKLIBRARY();
+ registeredfunc = FUNCCOMMON(lib_infop, SendRLSHandler);
+ if (registeredfunc != NULL) {
+ status = (registeredfunc)(
+ vendorHandle, hbaPortWWN, destWWN,
+ pRspBuffer, pRspBufferSize);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_SendLIRR(
+ HBA_HANDLE handle,
+ HBA_WWN sourceWWN,
+ HBA_WWN destWWN,
+ HBA_UINT8 function,
+ HBA_UINT8 type,
+ void *pRspBuffer,
+ HBA_UINT32 *pRspBufferSize)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBASendLIRRFunc registeredfunc;
+
+ DEBUG(2, "HBA_SendLIRR destWWN:%s", WWN2STR1(&destWWN), 0, 0);
+
+ CHECKLIBRARY();
+ registeredfunc = FUNCCOMMON(lib_infop, SendLIRRHandler);
+ if (registeredfunc != NULL) {
+ status = (registeredfunc)(
+ vendorHandle, sourceWWN, destWWN, function, type,
+ pRspBuffer, pRspBufferSize);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_GetBindingCapability(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_BIND_CAPABILITY *pcapability)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBAGetBindingCapabilityFunc
+ registeredfunc;
+
+ DEBUG(2, "HBA_GetBindingCapability", 0, 0, 0);
+
+ CHECKLIBRARYANDVERSION(HBAAPIV2);
+
+ registeredfunc =
+ lib_infop->ftable.functionTable.GetBindingCapabilityHandler;
+ if (registeredfunc != NULL) {
+ status = (registeredfunc)(vendorHandle, hbaPortWWN, pcapability);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_GetBindingSupport(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_BIND_CAPABILITY *pcapability)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBAGetBindingSupportFunc
+ registeredfunc;
+
+ DEBUG(2, "HBA_GetBindingSupport", 0, 0, 0);
+
+ CHECKLIBRARYANDVERSION(HBAAPIV2);
+
+ registeredfunc =
+ lib_infop->ftable.functionTable.GetBindingSupportHandler;
+ if (registeredfunc != NULL) {
+ status = (registeredfunc)(vendorHandle, hbaPortWWN, pcapability);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_SetBindingSupport(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_BIND_CAPABILITY capability)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBASetBindingSupportFunc
+ registeredfunc;
+
+ DEBUG(2, "HBA_SetBindingSupport", 0, 0, 0);
+
+ CHECKLIBRARYANDVERSION(HBAAPIV2);
+
+ registeredfunc =
+ lib_infop->ftable.functionTable.SetBindingSupportHandler;
+ if (registeredfunc != NULL) {
+ status = (registeredfunc)(vendorHandle, hbaPortWWN, capability);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_SetPersistentBindingV2(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ const HBA_FCPBINDING2 *pbinding)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBASetPersistentBindingV2Func
+ registeredfunc;
+
+ DEBUG(2, "HBA_SetPersistentBindingV2 port: %s",
+ WWN2STR1(&hbaPortWWN), 0, 0);
+
+ CHECKLIBRARYANDVERSION(HBAAPIV2);
+
+ registeredfunc =
+ lib_infop->ftable.functionTable.SetPersistentBindingV2Handler;
+ if (registeredfunc != NULL) {
+ status = (registeredfunc)(vendorHandle, hbaPortWWN, pbinding);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_GetPersistentBindingV2(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_FCPBINDING2 *pbinding)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBAGetPersistentBindingV2Func
+ registeredfunc;
+
+ DEBUG(2, "HBA_GetPersistentBindingV2 port: %s",
+ WWN2STR1(&hbaPortWWN), 0, 0);
+
+ CHECKLIBRARYANDVERSION(HBAAPIV2);
+
+ registeredfunc =
+ lib_infop->ftable.functionTable.GetPersistentBindingV2Handler;
+ if (registeredfunc != NULL) {
+ status = (registeredfunc)(vendorHandle, hbaPortWWN, pbinding);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_RemovePersistentBinding(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ const HBA_FCPBINDING2
+ *pbinding)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBARemovePersistentBindingFunc
+ registeredfunc;
+
+ DEBUG(2, "HBA_RemovePersistentBinding", 0, 0, 0);
+
+ CHECKLIBRARYANDVERSION(HBAAPIV2);
+
+ registeredfunc =
+ lib_infop->ftable.functionTable.RemovePersistentBindingHandler;
+ if (registeredfunc != NULL) {
+ status = (registeredfunc)(vendorHandle, hbaPortWWN, pbinding);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_RemoveAllPersistentBindings(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBARemoveAllPersistentBindingsFunc
+ registeredfunc;
+
+ DEBUG(2, "HBA_RemoveAllPersistentBindings", 0, 0, 0);
+
+ CHECKLIBRARYANDVERSION(HBAAPIV2);
+
+ registeredfunc =
+ lib_infop->ftable.functionTable.RemoveAllPersistentBindingsHandler;
+ if (registeredfunc != NULL) {
+ status = (registeredfunc)(vendorHandle, hbaPortWWN);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_GetFC4Statistics(
+ HBA_HANDLE handle,
+ HBA_WWN portWWN,
+ HBA_UINT8 FC4type,
+ HBA_FC4STATISTICS *pstatistics)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBAGetFC4StatisticsFunc
+ registeredfunc;
+
+ DEBUG(2, "HBA_GetFC4Statistics port: %s", WWN2STR1(&portWWN), 0, 0);
+
+ CHECKLIBRARYANDVERSION(HBAAPIV2);
+
+ registeredfunc =
+ lib_infop->ftable.functionTable.GetFC4StatisticsHandler;
+ if (registeredfunc != NULL) {
+ status = (registeredfunc)
+ (vendorHandle, portWWN, FC4type, pstatistics);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+HBA_GetFCPStatistics(
+ HBA_HANDLE handle,
+ const HBA_SCSIID *lunit,
+ HBA_FC4STATISTICS *pstatistics)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ HBAGetFCPStatisticsFunc
+ registeredfunc;
+
+ DEBUG(2, "HBA_GetFCPStatistics", 0, 0, 0);
+
+ CHECKLIBRARYANDVERSION(HBAAPIV2);
+
+ registeredfunc =
+ lib_infop->ftable.functionTable.GetFCPStatisticsHandler;
+ if (registeredfunc != NULL) {
+ status = (registeredfunc)(vendorHandle, lunit, pstatistics);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_UINT32
+HBA_GetVendorLibraryAttributes(
+ HBA_UINT32 adapter_index,
+ HBA_LIBRARYATTRIBUTES *attributes)
+{
+ HBA_ADAPTER_INFO *adapt_infop;
+ HBAGetVendorLibraryAttributesFunc
+ registeredfunc;
+ HBA_UINT32 ret = 0;
+
+ DEBUG(2, "HBA_GetVendorLibraryAttributes adapterindex:%d",
+ adapter_index, 0, 0);
+ if (_hbaapi_librarylist == NULL) {
+ DEBUG(1, "HBAAPI not loaded yet.", 0, 0, 0);
+ return (0);
+ }
+
+ if (attributes == NULL) {
+ DEBUG(1,
+ "HBA_GetVendorLibraryAttributes: NULL pointer attributes",
+ 0, 0, 0);
+ return (HBA_STATUS_ERROR_ARG);
+ }
+
+ (void) memset(attributes, 0, sizeof (HBA_LIBRARYATTRIBUTES));
+
+ GRAB_MUTEX(&_hbaapi_LL_mutex);
+ GRAB_MUTEX(&_hbaapi_AL_mutex);
+ for (adapt_infop = _hbaapi_adapterlist;
+ adapt_infop != NULL;
+ adapt_infop = adapt_infop->next) {
+
+ if (adapt_infop->index == adapter_index) {
+
+ if (adapt_infop->library->version == SMHBA) {
+ RELEASE_MUTEX(&_hbaapi_AL_mutex);
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex,
+ HBA_STATUS_ERROR_INCOMPATIBLE);
+ }
+
+ registeredfunc = adapt_infop->library->
+ ftable.functionTable.GetVendorLibraryAttributesHandler;
+ if (registeredfunc != NULL) {
+ ret = (registeredfunc)(attributes);
+ } else {
+ /* Version 1 libary? */
+ HBAGetVersionFunc GetVersionFunc;
+ GetVersionFunc = adapt_infop->library->
+ ftable.functionTable.GetVersionHandler;
+ if (GetVersionFunc != NULL) {
+ ret = ((GetVersionFunc)());
+ }
+#ifdef NOTDEF
+ else {
+ /* This should not happen, dont think its going to */
+ }
+#endif
+ }
+ if (attributes->LibPath[0] == '\0') {
+ if (strlen(adapt_infop->library->LibraryPath) < 256) {
+ (void) strcpy(attributes->LibPath,
+ adapt_infop->library->LibraryPath);
+ }
+ }
+ break;
+ }
+ }
+ RELEASE_MUTEX(&_hbaapi_AL_mutex);
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, ret);
+}
+
+
+/*
+ * This function returns SM-HBA version that the warpper library implemented.
+ */
+HBA_UINT32
+SMHBA_GetVersion() {
+ DEBUG(2, "SMHBA_GetVersion", 0, 0, 0);
+ return (SMHBA_LIBVERSION);
+}
+
+/*
+ * This function returns the attributes for the warpper library.
+ */
+HBA_UINT32
+SMHBA_GetWrapperLibraryAttributes(
+ SMHBA_LIBRARYATTRIBUTES *attributes)
+{
+
+ struct timeval tv;
+ struct tm tp;
+
+ DEBUG(2, "SMHBA_GetWrapperLibraryAttributes", 0, 0, 0);
+
+ if (attributes == NULL) {
+ DEBUG(1, "SMHBA_GetWrapperLibraryAttributes: "
+ "NULL pointer attributes",
+ 0, 0, 0);
+ return (HBA_STATUS_ERROR_ARG);
+ }
+
+ (void) memset(attributes, 0, sizeof (SMHBA_LIBRARYATTRIBUTES));
+
+#if defined(SOLARIS)
+ if ((handle = dlopen("libSMHBAAPI.so", RTLD_NOW)) != NULL) {
+ if (dlinfo(handle, RTLD_DI_LINKMAP, &map) >= 0) {
+ for (mp = map; mp != NULL; mp = mp->l_next) {
+ if (strlen(map->l_name) < 256) {
+ (void) strcpy(attributes->LibPath, map->l_name);
+ }
+ }
+ }
+ }
+
+#endif
+
+#if defined(VENDOR)
+ (void) strcpy(attributes->VName, VENDOR);
+#else
+ attributes->VName[0] = '\0';
+#endif
+#if defined(VERSION)
+ (void) strcpy(attributes->VVersion, VERSION);
+#else
+ attributes->VVersion[0] = '\0';
+#endif
+
+ if (gettimeofday(&tv, (void *)0) == 0) {
+ if (localtime_r(&tv.tv_sec, &tp) != NULL) {
+ attributes->build_date.tm_mday = tp.tm_mday;
+ attributes->build_date.tm_mon = tp.tm_mon;
+ attributes->build_date.tm_year = tp.tm_year;
+ } else {
+ (void) memset(&attributes->build_date, 0,
+ sizeof (attributes->build_date));
+ }
+ (void) memset(&attributes->build_date, 0,
+ sizeof (attributes->build_date));
+ }
+
+ return (1);
+}
+
+/*
+ * This function returns the attributes for the warpper library.
+ */
+HBA_UINT32
+SMHBA_GetVendorLibraryAttributes(
+ HBA_UINT32 adapter_index,
+ SMHBA_LIBRARYATTRIBUTES *attributes)
+{
+ HBA_ADAPTER_INFO *adapt_infop;
+ SMHBAGetVendorLibraryAttributesFunc
+ registeredfunc;
+ HBA_UINT32 ret = 0;
+
+ DEBUG(2, "SMHBA_GetVendorLibraryAttributes adapterindex:%d",
+ adapter_index, 0, 0);
+ if (_hbaapi_librarylist == NULL) {
+ DEBUG(1, "SMHBAAPI not loaded yet.", 0, 0, 0);
+ return (0);
+ }
+
+ if (attributes == NULL) {
+ DEBUG(1, "SMHBA_GetVendorLibraryAttributes: "
+ "NULL pointer attributes",
+ 0, 0, 0);
+ return (HBA_STATUS_ERROR_ARG);
+ }
+
+ (void) memset(attributes, 0, sizeof (SMHBA_LIBRARYATTRIBUTES));
+
+ GRAB_MUTEX(&_hbaapi_LL_mutex);
+ GRAB_MUTEX(&_hbaapi_AL_mutex);
+ for (adapt_infop = _hbaapi_adapterlist;
+ adapt_infop != NULL;
+ adapt_infop = adapt_infop->next) {
+
+ if (adapt_infop->index == adapter_index) {
+
+ if (adapt_infop->library->version != SMHBA) {
+ RELEASE_MUTEX(&_hbaapi_AL_mutex);
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex,
+ HBA_STATUS_ERROR_INCOMPATIBLE);
+ }
+
+ registeredfunc = adapt_infop->library->
+ ftable.smhbafunctionTable.GetVendorLibraryAttributesHandler;
+ if (registeredfunc != NULL) {
+ ret = (registeredfunc)(attributes);
+#ifdef NOTDEF
+ } else {
+ /* This should not happen since the VSL is already loaded. */
+#endif
+ }
+ if (attributes->LibPath[0] == '\0') {
+ if (strlen(adapt_infop->library->LibraryPath) < 256) {
+ (void) strcpy(attributes->LibPath,
+ adapt_infop->library->LibraryPath);
+ }
+ }
+ break;
+ }
+ }
+ RELEASE_MUTEX(&_hbaapi_AL_mutex);
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, ret);
+}
+
+HBA_STATUS
+SMHBA_GetAdapterAttributes(
+ HBA_HANDLE handle,
+ SMHBA_ADAPTERATTRIBUTES *hbaattributes)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ SMHBAGetAdapterAttributesFunc GetAdapterAttributesFunc;
+
+ DEBUG(2, "SMHBA_GetAdapterAttributes", 0, 0, 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+
+ GetAdapterAttributesFunc =
+ lib_infop->ftable.smhbafunctionTable.GetAdapterAttributesHandler;
+ if (GetAdapterAttributesFunc != NULL) {
+ status = ((GetAdapterAttributesFunc)(vendorHandle, hbaattributes));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+SMHBA_GetNumberOfPorts(
+ HBA_HANDLE handle,
+ HBA_UINT32 *numberofports)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ SMHBAGetNumberOfPortsFunc GetNumberOfPortsFunc;
+
+ DEBUG(2, "SMHBA_GetAdapterAttributes", 0, 0, 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+
+ GetNumberOfPortsFunc =
+ lib_infop->ftable.smhbafunctionTable.GetNumberOfPortsHandler;
+ if (GetNumberOfPortsFunc != NULL) {
+ status = ((GetNumberOfPortsFunc)(vendorHandle, numberofports));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+SMHBA_GetPortType(
+ HBA_HANDLE handle,
+ HBA_UINT32 portindex,
+ HBA_PORTTYPE *porttype)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ SMHBAGetPortTypeFunc GetPortTypeFunc;
+
+ DEBUG(2, "SMHBA_GetAdapterAttributes", 0, 0, 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+
+ GetPortTypeFunc =
+ lib_infop->ftable.smhbafunctionTable.GetPortTypeHandler;
+ if (GetPortTypeFunc != NULL) {
+ status = ((GetPortTypeFunc)(vendorHandle, portindex, porttype));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+SMHBA_GetAdapterPortAttributes(
+ HBA_HANDLE handle,
+ HBA_UINT32 portindex,
+ SMHBA_PORTATTRIBUTES *portattributes)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ SMHBAGetAdapterPortAttributesFunc
+ GetAdapterPortAttributesFunc;
+
+ DEBUG(2, "SMHBA_GetAdapterPortAttributes", 0, 0, 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+
+ GetAdapterPortAttributesFunc =
+ lib_infop->ftable.smhbafunctionTable.\
+ GetAdapterPortAttributesHandler;
+ if (GetAdapterPortAttributesFunc != NULL) {
+ status = ((GetAdapterPortAttributesFunc)
+ (vendorHandle, portindex, portattributes));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+SMHBA_GetDiscoveredPortAttributes(
+ HBA_HANDLE handle,
+ HBA_UINT32 portindex,
+ HBA_UINT32 discoveredportindex,
+ SMHBA_PORTATTRIBUTES *portattributes)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ SMHBAGetDiscoveredPortAttributesFunc
+ GetDiscoveredPortAttributesFunc;
+
+ DEBUG(2, "SMHBA_GetDiscoveredPortAttributes", 0, 0, 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+
+ GetDiscoveredPortAttributesFunc =
+ lib_infop->ftable.smhbafunctionTable.\
+ GetDiscoveredPortAttributesHandler;
+ if (GetDiscoveredPortAttributesFunc != NULL) {
+ status = ((GetDiscoveredPortAttributesFunc)
+ (vendorHandle, portindex, discoveredportindex,
+ portattributes));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+SMHBA_GetPortAttributesByWWN(
+ HBA_HANDLE handle,
+ HBA_WWN portWWN,
+ HBA_WWN domainPortWWN,
+ SMHBA_PORTATTRIBUTES *portattributes)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ SMHBAGetPortAttributesByWWNFunc
+ GetPortAttributesByWWNFunc;
+
+ DEBUG(2, "SMHBA_GetPortAttributesByWWN: %s", WWN2STR1(&portWWN), 0, 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+
+ GetPortAttributesByWWNFunc =
+ lib_infop->ftable.smhbafunctionTable.GetPortAttributesByWWNHandler;
+ if (GetPortAttributesByWWNFunc != NULL) {
+ status = ((GetPortAttributesByWWNFunc)
+ (vendorHandle, portWWN, domainPortWWN, portattributes));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+SMHBA_GetFCPhyAttributes(
+ HBA_HANDLE handle,
+ HBA_UINT32 portindex,
+ HBA_UINT32 phyindex,
+ SMHBA_FC_PHY *phytype)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ SMHBAGetFCPhyAttributesFunc GetFCPhyAttributesFunc;
+
+ DEBUG(2, "SMHBA_GetFCPhyAttributesByWWN", 0, 0, 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+
+ GetFCPhyAttributesFunc =
+ lib_infop->ftable.smhbafunctionTable.GetFCPhyAttributesHandler;
+ if (GetFCPhyAttributesFunc != NULL) {
+ status = ((GetFCPhyAttributesFunc)
+ (vendorHandle, portindex, phyindex, phytype));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+SMHBA_GetSASPhyAttributes(
+ HBA_HANDLE handle,
+ HBA_UINT32 portindex,
+ HBA_UINT32 phyindex,
+ SMHBA_SAS_PHY *phytype)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ SMHBAGetSASPhyAttributesFunc GetSASPhyAttributesFunc;
+
+ DEBUG(2, "SMHBA_GetFCPhyAttributesByWWN", 0, 0, 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+
+ GetSASPhyAttributesFunc =
+ lib_infop->ftable.smhbafunctionTable.GetSASPhyAttributesHandler;
+ if (GetSASPhyAttributesFunc != NULL) {
+ status = ((GetSASPhyAttributesFunc)
+ (vendorHandle, portindex, phyindex, phytype));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+SMHBA_GetProtocolStatistics(
+ HBA_HANDLE handle,
+ HBA_UINT32 portindex,
+ HBA_UINT32 protocoltype,
+ SMHBA_PROTOCOLSTATISTICS *pProtocolStatistics)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ SMHBAGetProtocolStatisticsFunc
+ GetProtocolStatisticsFunc;
+
+ DEBUG(2, "SMHBA_GetProtocolStatistics port index: %d protocol type: %d",
+ portindex, protocoltype, 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+
+ GetProtocolStatisticsFunc =
+ lib_infop->ftable.smhbafunctionTable.GetProtocolStatisticsHandler;
+ if (GetProtocolStatisticsFunc != NULL) {
+ status = (GetProtocolStatisticsFunc)
+ (vendorHandle, portindex, protocoltype, pProtocolStatistics);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+SMHBA_GetPhyStatistics(
+ HBA_HANDLE handle,
+ HBA_UINT32 portindex,
+ HBA_UINT32 phyindex,
+ SMHBA_PHYSTATISTICS *pPhyStatistics)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ SMHBAGetPhyStatisticsFunc
+ GetPhyStatisticsFunc;
+
+ DEBUG(2, "SMHBA_GetPhyStatistics port index: %d phy idex: %d",
+ portindex, phyindex, 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+
+ GetPhyStatisticsFunc =
+ lib_infop->ftable.smhbafunctionTable.GetPhyStatisticsHandler;
+ if (GetPhyStatisticsFunc != NULL) {
+ status = (GetPhyStatisticsFunc)
+ (vendorHandle, portindex, phyindex, pPhyStatistics);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+SMHBA_GetBindingCapability(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN domainPortWWN,
+ SMHBA_BIND_CAPABILITY *pFlags)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ SMHBAGetBindingCapabilityFunc GetBindingCapabilityFunc;
+
+ DEBUG(2, "HBA_GetBindingCapability", 0, 0, 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+
+ GetBindingCapabilityFunc =
+ lib_infop->ftable.smhbafunctionTable.GetBindingCapabilityHandler;
+ if (GetBindingCapabilityFunc != NULL) {
+ status = (GetBindingCapabilityFunc)(vendorHandle, hbaPortWWN,
+ domainPortWWN, pFlags);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+SMHBA_GetBindingSupport(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN domainPortWWN,
+ SMHBA_BIND_CAPABILITY *pFlags)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ SMHBAGetBindingSupportFunc
+ GetBindingSupporFunc;
+
+ DEBUG(2, "SMHBA_GetBindingSupport port: %s",
+ WWN2STR1(&hbaPortWWN), 0, 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+
+ GetBindingSupporFunc =
+ lib_infop->ftable.smhbafunctionTable.GetBindingSupportHandler;
+ if (GetBindingSupporFunc != NULL) {
+ status = (GetBindingSupporFunc)(vendorHandle,
+ hbaPortWWN, domainPortWWN, pFlags);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+SMHBA_SetBindingSupport(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN domainPortWWN,
+ SMHBA_BIND_CAPABILITY flags)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ SMHBASetBindingSupportFunc
+ SetBindingSupporFunc;
+
+ DEBUG(2, "SMHBA_GetBindingSupport port: %s",
+ WWN2STR1(&hbaPortWWN), 0, 0);
+
+ CHECKLIBRARYANDVERSION(HBAAPIV2);
+
+ SetBindingSupporFunc =
+ lib_infop->ftable.smhbafunctionTable.SetBindingSupportHandler;
+ if (SetBindingSupporFunc != NULL) {
+ status = (SetBindingSupporFunc)
+ (vendorHandle, hbaPortWWN, domainPortWWN, flags);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+SMHBA_GetTargetMapping(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN domainPortWWN,
+ SMHBA_TARGETMAPPING *pMapping)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ SMHBAGetTargetMappingFunc GetTargetMappingFunc;
+
+ DEBUG(2, "SMHBA_GetTargetMapping port WWN: %s",
+ WWN2STR1(&hbaPortWWN), 0, 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+
+ GetTargetMappingFunc =
+ lib_infop->ftable.smhbafunctionTable.GetTargetMappingHandler;
+ if (GetTargetMappingFunc != NULL) {
+ status = ((GetTargetMappingFunc)(vendorHandle,
+ hbaPortWWN, domainPortWWN, pMapping));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+SMHBA_GetPersistentBinding(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN domainPortWWN,
+ SMHBA_BINDING *binding)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ SMHBAGetPersistentBindingFunc
+ GetPersistentBindingFunc;
+
+ DEBUG(2, "SMHBA_GetPersistentBinding port WWN: %s",
+ WWN2STR1(&hbaPortWWN), 0, 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+
+ GetPersistentBindingFunc =
+ lib_infop->ftable.smhbafunctionTable.GetPersistentBindingHandler;
+ if (GetPersistentBindingFunc != NULL) {
+ status = ((GetPersistentBindingFunc)(vendorHandle,
+ hbaPortWWN, domainPortWWN, binding));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+SMHBA_SetPersistentBinding(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN domainPortWWN,
+ const SMHBA_BINDING *binding)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ SMHBASetPersistentBindingFunc
+ SetPersistentBindingFunc;
+
+ DEBUG(2, "SMHBA_SetPersistentBinding port WWN: %s",
+ WWN2STR1(&hbaPortWWN), 0, 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+
+ SetPersistentBindingFunc =
+ lib_infop->ftable.smhbafunctionTable.SetPersistentBindingHandler;
+ if (SetPersistentBindingFunc != NULL) {
+ status = ((SetPersistentBindingFunc)(vendorHandle,
+ hbaPortWWN, domainPortWWN, binding));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+SMHBA_RemovePersistentBinding(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN domainPortWWN,
+ const SMHBA_BINDING *binding)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ SMHBARemovePersistentBindingFunc
+ RemovePersistentBindingFunc;
+
+ DEBUG(2, "SMHBA_RemovePersistentBinding port WWN: %s",
+ WWN2STR1(&hbaPortWWN), 0, 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+
+ RemovePersistentBindingFunc =
+ lib_infop->ftable.smhbafunctionTable.RemovePersistentBindingHandler;
+ if (RemovePersistentBindingFunc != NULL) {
+ status = ((RemovePersistentBindingFunc)(vendorHandle,
+ hbaPortWWN, domainPortWWN, binding));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+SMHBA_RemoveAllPersistentBindings(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN domainPortWWN)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ SMHBARemoveAllPersistentBindingsFunc
+ RemoveAllPersistentBindingsFunc;
+
+ DEBUG(2, "SMHBA_RemoveAllPersistentBinding port WWN: %s",
+ WWN2STR1(&hbaPortWWN), 0, 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+
+ RemoveAllPersistentBindingsFunc =
+ lib_infop->ftable.smhbafunctionTable.\
+ RemoveAllPersistentBindingsHandler;
+ if (RemoveAllPersistentBindingsFunc != NULL) {
+ status = ((RemoveAllPersistentBindingsFunc)(vendorHandle,
+ hbaPortWWN, domainPortWWN));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+SMHBA_GetLUNStatistics(
+ HBA_HANDLE handle,
+ const HBA_SCSIID *lunit,
+ SMHBA_PROTOCOLSTATISTICS *statistics)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ SMHBAGetLUNStatisticsFunc GetLUNStatisticsFunc;
+
+ DEBUG(2, "SMHBA_GetLUNStatistics", 0, 0, 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+
+ GetLUNStatisticsFunc =
+ lib_infop->ftable.smhbafunctionTable.GetLUNStatisticsHandler;
+ if (GetLUNStatisticsFunc != NULL) {
+ status = ((GetLUNStatisticsFunc)(vendorHandle, lunit, statistics));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+SMHBA_ScsiInquiry(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN discoveredPortWWN,
+ HBA_WWN domainPortWWN,
+ SMHBA_SCSILUN smhbaLUN,
+ HBA_UINT8 CDB_Byte1,
+ HBA_UINT8 CDB_Byte2,
+ void *pRspBuffer,
+ HBA_UINT32 *pRspBufferSize,
+ HBA_UINT8 *pScsiStatus,
+ void *pSenseBuffer,
+ HBA_UINT32 *pSenseBufferSize)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ SMHBAScsiInquiryFunc ScsiInquiryFunc;
+
+ DEBUG(2, "SMHBA_ScsiInquiry to hba port: %s discoveredPortWWN: %s",
+ WWN2STR1(&hbaPortWWN), WWN2STR1(&discoveredPortWWN), 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+
+ ScsiInquiryFunc =
+ lib_infop->ftable.smhbafunctionTable.ScsiInquiryHandler;
+ if (ScsiInquiryFunc != NULL) {
+ status = ((ScsiInquiryFunc)(
+ vendorHandle, hbaPortWWN, discoveredPortWWN, domainPortWWN,
+ smhbaLUN, CDB_Byte1, CDB_Byte2, pRspBuffer, pRspBufferSize,
+ pScsiStatus, pSenseBuffer, pSenseBufferSize));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+SMHBA_ScsiReportLUNs(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN discoveredPortWWN,
+ HBA_WWN domainPortWWN,
+ void *pRspBuffer,
+ HBA_UINT32 *pRspBufferSize,
+ HBA_UINT8 *pScsiStatus,
+ void *pSenseBuffer,
+ HBA_UINT32 *pSenseBufferSize)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ SMHBAScsiReportLUNsFunc ScsiReportLUNsFunc;
+
+ DEBUG(2, "SMHBA_ScsiReportLuns to hba port: %s discoveredPortWWN: %s",
+ WWN2STR1(&hbaPortWWN), WWN2STR1(&discoveredPortWWN), 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+
+ ScsiReportLUNsFunc =
+ lib_infop->ftable.smhbafunctionTable.ScsiReportLUNsHandler;
+ if (ScsiReportLUNsFunc != NULL) {
+ status = ((ScsiReportLUNsFunc)(
+ vendorHandle, hbaPortWWN, discoveredPortWWN, domainPortWWN,
+ pRspBuffer, pRspBufferSize, pScsiStatus, pSenseBuffer,
+ pSenseBufferSize));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+SMHBA_ScsiReadCapacity(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN discoveredPortWWN,
+ HBA_WWN domainPortWWN,
+ SMHBA_SCSILUN smhbaLUN,
+ void *pRspBuffer,
+ HBA_UINT32 *pRspBufferSize,
+ HBA_UINT8 *pScsiStatus,
+ void *pSenseBuffer,
+ HBA_UINT32 *pSenseBufferSize)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ SMHBAScsiReadCapacityFunc ScsiReadCapacityFunc;
+
+ DEBUG(2, "SMHBA_ScsiReadCapacity to hba port: %s discoveredPortWWN: %s",
+ WWN2STR1(&hbaPortWWN), WWN2STR1(&discoveredPortWWN), 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+
+ ScsiReadCapacityFunc =
+ lib_infop->ftable.smhbafunctionTable.ScsiReadCapacityHandler;
+ if (ScsiReadCapacityFunc != NULL) {
+ status = ((ScsiReadCapacityFunc)(
+ vendorHandle, hbaPortWWN, discoveredPortWWN, domainPortWWN,
+ smhbaLUN, pRspBuffer, pRspBufferSize, pScsiStatus, pSenseBuffer,
+ pSenseBufferSize));
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+SMHBA_SendTEST(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN destWWN,
+ HBA_UINT32 destFCID,
+ void *pRspBuffer,
+ HBA_UINT32 pRspBufferSize)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ SMHBASendTESTFunc SendTESTFunc;
+
+ DEBUG(2, "SMHBA_SendTEST, hbaPortWWN: %s destWWN",
+ WWN2STR1(&hbaPortWWN),
+ WWN2STR1(&destWWN), 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+
+ SendTESTFunc = lib_infop->ftable.smhbafunctionTable.SendTESTHandler;
+ if (SendTESTFunc != NULL) {
+ status = (SendTESTFunc)
+ (vendorHandle, hbaPortWWN, destWWN, destFCID,
+ pRspBuffer, pRspBufferSize);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+SMHBA_SendECHO(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN destWWN,
+ HBA_UINT32 destFCID,
+ void *pReqBuffer,
+ HBA_UINT32 ReqBufferSize,
+ void *pRspBuffer,
+ HBA_UINT32 *pRspBufferSize)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ SMHBASendECHOFunc SendECHOFunc;
+
+ DEBUG(2, "SMHBA_SendECHO, hbaPortWWN: %s destWWN",
+ WWN2STR1(&hbaPortWWN), WWN2STR1(&destWWN), 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+
+ SendECHOFunc = lib_infop->ftable.smhbafunctionTable.SendECHOHandler;
+ if (SendECHOFunc != NULL) {
+ status = (SendECHOFunc)
+ (vendorHandle, hbaPortWWN, destWWN, destFCID,
+ pReqBuffer, ReqBufferSize, pRspBuffer, pRspBufferSize);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+HBA_STATUS
+SMHBA_SendSMPPassThru(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN destWWN,
+ HBA_WWN domainPortWWN,
+ void *pReqBuffer,
+ HBA_UINT32 ReqBufferSize,
+ void *pRspBuffer,
+ HBA_UINT32 *pRspBufferSize)
+{
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+ SMHBASendSMPPassThruFunc SendSMPPassThruFunc;
+
+ DEBUG(2, "SMHBA_SendSMPPassThru, hbaPortWWN: %s destWWN: %s",
+ WWN2STR1(&hbaPortWWN), WWN2STR1(&destWWN), 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+
+ SendSMPPassThruFunc = lib_infop->ftable.\
+ smhbafunctionTable.SendSMPPassThruHandler;
+
+ if (SendSMPPassThruFunc != NULL) {
+ status = (SendSMPPassThruFunc)
+ (vendorHandle, hbaPortWWN, destWWN, domainPortWWN,
+ pReqBuffer, ReqBufferSize, pRspBuffer, pRspBufferSize);
+ } else {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+/*
+ * Following the similar logic of HBAAPI addaspterevents_callback.
+ *
+ * Unlike other events Adapter Add Event is not limited to a specific
+ * adpater(i.e. no adatper handle is passed for registration) so
+ * the event should be passed to all registrants. The routine below
+ * is passed to the VSLs as a callback and when Adapter Add event is detected
+ * by VSL it will call smhba_adapteraddevents_callback() which in turn check
+ * if the passed userdata ptr matches with the one stored in the callback list
+ * and calls the stored callback.
+ *
+ * For the situation that multiple clients are registered for Adapter Add event
+ * each registration is passed to VSLs so VSL may call
+ * smhba_adapteraddevents_callback() multiple times or it may call only once
+ * since the callback function is same. For this implemneation, the userdata
+ * is stored in HBA_ALLADAPTERSCALLBACK_ELEM so it is expected that VSL call
+ * smhba_adapteraddevents_callback() only once and
+ * smhba_adapteraddevents_callback() will call the client callback with proper
+ * userdata.
+ */
+static void
+smhba_adapteraddevents_callback(
+/* LINTED E_FUNC_ARG_UNUSED */
+ void *data,
+ HBA_WWN PortWWN,
+/* LINTED E_FUNC_ARG_UNUSED */
+ HBA_UINT32 eventType)
+{
+ HBA_ALLADAPTERSCALLBACK_ELEM *cbp;
+
+ DEBUG(3, "AddAdapterEvent, port:%s", WWN2STR1(&PortWWN), 0, 0);
+
+ GRAB_MUTEX(&_smhba_AAE_mutex);
+ for (cbp = _smhba_adapteraddevents_callback_list;
+ cbp != NULL;
+ cbp = cbp->next) {
+ (*cbp->callback)(cbp->userdata, PortWWN, HBA_EVENT_ADAPTER_ADD);
+ }
+ RELEASE_MUTEX(&_smhba_AAE_mutex);
+
+}
+
+HBA_STATUS
+SMHBA_RegisterForAdapterAddEvents(
+ void (*pCallback) (
+ void *data,
+ HBA_WWN PortWWN,
+ HBA_UINT32 eventType),
+ void *pUserData,
+ HBA_CALLBACKHANDLE *pCallbackHandle) {
+
+ HBA_ALLADAPTERSCALLBACK_ELEM *cbp;
+ HBA_VENDORCALLBACK_ELEM *vcbp;
+ HBA_VENDORCALLBACK_ELEM *vendorhandlelist;
+ SMHBARegisterForAdapterAddEventsFunc registeredfunc;
+ HBA_STATUS status = HBA_STATUS_OK;
+ HBA_STATUS failure = HBA_STATUS_OK;
+ HBA_LIBRARY_INFO *lib_infop;
+ int registered_cnt = 0;
+ int vendor_cnt = 0;
+ int not_supported_cnt = 0;
+ int status_OK_bar_cnt = 0;
+ int status_OK_cnt = 0;
+
+ DEBUG(2, "SMHBA_RegisterForAdapterAddEvents", 0, 0, 0);
+ ARE_WE_INITED();
+
+ cbp = (HBA_ALLADAPTERSCALLBACK_ELEM *)
+ calloc(1, sizeof (HBA_ALLADAPTERSCALLBACK_ELEM));
+ *pCallbackHandle = (HBA_CALLBACKHANDLE) cbp;
+ if (cbp == NULL) {
+ return (HBA_STATUS_ERROR);
+ }
+
+ GRAB_MUTEX(&_hbaapi_LL_mutex);
+ GRAB_MUTEX(&_smhba_AAE_mutex);
+ cbp->callback = pCallback;
+ cbp->userdata = pUserData;
+ cbp->next = _smhba_adapteraddevents_callback_list;
+ _smhba_adapteraddevents_callback_list = cbp;
+
+ /*
+ * Need to release the mutex now incase the vendor function invokes the
+ * callback. We will grap the mutex later to attach the vendor handle
+ * list to the callback structure
+ */
+ RELEASE_MUTEX(&_smhba_AAE_mutex);
+
+
+ /*
+ * now create a list of vendors (vendor libraryies, NOT ADAPTERS)
+ * that have successfully registerred
+ */
+ vendorhandlelist = NULL;
+ for (lib_infop = _hbaapi_librarylist;
+ lib_infop != NULL;
+ lib_infop = lib_infop->next) {
+
+ /* only for HBAAPI V2 */
+ if (lib_infop->version != SMHBA) {
+ continue;
+ } else {
+ vendor_cnt++;
+ }
+
+ registeredfunc =
+ lib_infop->ftable.smhbafunctionTable.\
+ RegisterForAdapterAddEventsHandler;
+ if (registeredfunc == NULL) {
+ continue;
+ }
+
+ vcbp = (HBA_VENDORCALLBACK_ELEM *)
+ calloc(1, sizeof (HBA_VENDORCALLBACK_ELEM));
+ if (vcbp == NULL) {
+ freevendorhandlelist(vendorhandlelist);
+ status = HBA_STATUS_ERROR;
+ break;
+ }
+
+ registered_cnt++;
+ status = (registeredfunc)(smhba_adapteraddevents_callback,
+ pUserData, &vcbp->vendorcbhandle);
+ if (status == HBA_STATUS_ERROR_NOT_SUPPORTED) {
+ not_supported_cnt++;
+ free(vcbp);
+ continue;
+ } else if (status != HBA_STATUS_OK) {
+ status_OK_bar_cnt++;
+ DEBUG(1,
+ "SMHBA_RegisterForAdapterAddEvents: Library->%s, Error->%d",
+ lib_infop->LibraryPath, status, 0);
+ failure = status;
+ free(vcbp);
+ continue;
+ } else {
+ status_OK_cnt++;
+ }
+ vcbp->lib_info = lib_infop;
+ vcbp->next = vendorhandlelist;
+ vendorhandlelist = vcbp;
+ }
+
+ if (vendor_cnt == 0) {
+ /* no SMHBA VSL found. Should be okay?? */
+ status = HBA_STATUS_ERROR;
+ } else if (registered_cnt == 0) {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ freevendorhandlelist(vendorhandlelist);
+ (void) local_remove_callback((HBA_CALLBACKHANDLE) cbp);
+ } else if (status_OK_cnt == 0 && not_supported_cnt != 0) {
+ status = HBA_STATUS_ERROR_NOT_SUPPORTED;
+ } else if (status_OK_cnt == 0) {
+ /*
+ * At least one vendor library registered this function, but no
+ * vendor call succeeded
+ */
+ (void) local_remove_callback((HBA_CALLBACKHANDLE) cbp);
+ status = failure;
+ } else {
+ /* we have had atleast some success, now finish up */
+ GRAB_MUTEX(&_smhba_AAE_mutex);
+ /*
+ * this seems silly, but what if another thread called
+ * the callback remove
+ */
+ for (cbp = _smhba_adapteraddevents_callback_list;
+ cbp != NULL; cbp = cbp->next) {
+ if ((HBA_CALLBACKHANDLE)cbp == *pCallbackHandle) {
+ /* yup, its still there, hooray */
+ cbp->vendorhandlelist = vendorhandlelist;
+ vendorhandlelist = NULL;
+ break;
+ }
+ }
+ RELEASE_MUTEX(&_smhba_AAE_mutex);
+ if (vendorhandlelist != NULL) {
+ /*
+ * bummer, somebody removed the callback before we finished
+ * registration, probably will never happen
+ */
+ freevendorhandlelist(vendorhandlelist);
+ DEBUG(1,
+ "HBA_RegisterForAdapterAddEvents: HBA_RemoveCallback was "
+ "called for a handle before registration was finished.",
+ 0, 0, 0);
+ status = HBA_STATUS_ERROR;
+ } else {
+ status = HBA_STATUS_OK;
+ }
+ }
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+}
+
+/* SMHBA Adapter Events (other than add) ******************************** */
+static void
+smhba_adapterevents_callback(void *data,
+ HBA_WWN PortWWN,
+ HBA_UINT32 eventType)
+{
+ HBA_ADAPTERCALLBACK_ELEM *acbp;
+
+ DEBUG(3, "AdapterEvent, port:%s, eventType:%d", WWN2STR1(&PortWWN),
+ eventType, 0);
+
+ GRAB_MUTEX(&_hbaapi_AE_mutex);
+ for (acbp = _smhba_adapterevents_callback_list;
+ acbp != NULL;
+ acbp = acbp->next) {
+ if (data == (void *)acbp) {
+ (*acbp->callback)(acbp->userdata, PortWWN, eventType);
+ break;
+ }
+ }
+ RELEASE_MUTEX(&_hbaapi_AE_mutex);
+}
+
+HBA_STATUS
+SMHBA_RegisterForAdapterEvents(
+ void (*pCallback) (
+ void *data,
+ HBA_WWN PortWWN,
+ HBA_UINT32 eventType),
+ void *pUserData,
+ HBA_HANDLE handle,
+ HBA_CALLBACKHANDLE *pCallbackHandle) {
+
+ HBA_ADAPTERCALLBACK_ELEM *acbp;
+ SMHBARegisterForAdapterEventsFunc registeredfunc;
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+
+ DEBUG(2, "SMHBA_RegisterForAdapterEvents", 0, 0, 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+
+ /* we now have the _hbaapi_LL_mutex */
+
+ registeredfunc = lib_infop->ftable.smhbafunctionTable.\
+ RegisterForAdapterEventsHandler;
+ if (registeredfunc == NULL) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
+ }
+
+ /*
+ * that allocated memory is used both as the handle for the
+ * caller, and as userdata to the vendor call so that on
+ * callback the specific registration may be recalled
+ */
+ acbp = (HBA_ADAPTERCALLBACK_ELEM *)
+ calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
+ if (acbp == NULL) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
+ }
+ *pCallbackHandle = (HBA_CALLBACKHANDLE) acbp;
+ acbp->callback = pCallback;
+ acbp->userdata = pUserData;
+ acbp->lib_info = lib_infop;
+
+ status = (registeredfunc)(smhba_adapterevents_callback,
+ (void *)acbp,
+ vendorHandle,
+ &acbp->vendorcbhandle);
+ if (status != HBA_STATUS_OK) {
+ free(acbp);
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+ }
+
+ GRAB_MUTEX(&_smhba_AE_mutex);
+ acbp->next = _smhba_adapterevents_callback_list;
+ _hbaapi_adapterevents_callback_list = acbp;
+
+ RELEASE_MUTEX(&_smhba_AE_mutex);
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
+}
+
+/* Adapter Port Events *********************************************** */
+static void
+smhba_adapterportevents_callback(void *data,
+ HBA_WWN PortWWN,
+ HBA_UINT32 eventType,
+ HBA_UINT32 fabricPortID)
+{
+ HBA_ADAPTERCALLBACK_ELEM *acbp;
+
+ DEBUG(3,
+ "SMHBA_AdapterPortEvent, port:%s, eventType:%d fabricPortID:0X%06x",
+ WWN2STR1(&PortWWN), eventType, fabricPortID);
+
+ GRAB_MUTEX(&_smhba_APE_mutex);
+
+ for (acbp = _smhba_adapterportevents_callback_list;
+ acbp != NULL;
+ acbp = acbp->next) {
+ if (data == (void *)acbp) {
+ (*acbp->callback)(acbp->userdata, PortWWN,
+ eventType, fabricPortID);
+ break;
+ }
+ }
+ RELEASE_MUTEX(&_smhba_APE_mutex);
+}
+
+HBA_STATUS
+SMHBA_RegisterForAdapterPortEvents(
+ void (*pCallback) (
+ void *pData,
+ HBA_WWN PortWWN,
+ HBA_UINT32 eventType,
+ HBA_UINT32 fabricPortID),
+ void *pUserData,
+ HBA_HANDLE handle,
+ HBA_WWN portWWN,
+ HBA_UINT32 specificEventType,
+ HBA_CALLBACKHANDLE *pCallbackHandle) {
+
+ HBA_ADAPTERCALLBACK_ELEM *acbp;
+ SMHBARegisterForAdapterPortEventsFunc registeredfunc;
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+
+ DEBUG(2, "SMHBA_RegisterForAdapterPortEvents for port: %s",
+ WWN2STR1(&portWWN), 0, 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+ /* we now have the _hbaapi_LL_mutex */
+
+ registeredfunc =
+ lib_infop->ftable.smhbafunctionTable.\
+ RegisterForAdapterPortEventsHandler;
+ if (registeredfunc == NULL) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
+ }
+
+ /*
+ * that allocated memory is used both as the handle for the
+ * caller, and as userdata to the vendor call so that on
+ * callback the specific registration may be recalled
+ */
+ acbp = (HBA_ADAPTERCALLBACK_ELEM *)
+ calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
+ if (acbp == NULL) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
+ }
+ *pCallbackHandle = (HBA_CALLBACKHANDLE) acbp;
+ acbp->callback = pCallback;
+ acbp->userdata = pUserData;
+ acbp->lib_info = lib_infop;
+
+ status = (registeredfunc)(smhba_adapterportevents_callback,
+ (void *)acbp,
+ vendorHandle,
+ portWWN,
+ specificEventType,
+ &acbp->vendorcbhandle);
+ if (status != HBA_STATUS_OK) {
+ free(acbp);
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+ }
+
+ GRAB_MUTEX(&_smhba_APE_mutex);
+ acbp->next = _smhba_adapterportevents_callback_list;
+ _smhba_adapterportevents_callback_list = acbp;
+
+ RELEASE_MUTEX(&_smhba_APE_mutex);
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
+}
+
+/* SMHBA Adapter Port Stat Events ******************************** */
+static void
+smhba_adapterportstatevents_callback(void *data,
+ HBA_WWN portWWN,
+ HBA_UINT32 protocolType,
+ HBA_UINT32 eventType)
+{
+ HBA_ADAPTERCALLBACK_ELEM *acbp;
+
+ DEBUG(3,
+ "SMBA_AdapterPortStateEvent, port:%s, eventType:%d",
+ WWN2STR1(&portWWN), eventType, 0);
+
+ GRAB_MUTEX(&_smhba_APSE_mutex);
+ for (acbp = _smhba_adapterportstatevents_callback_list;
+ acbp != NULL;
+ acbp = acbp->next) {
+ if (data == (void *)acbp) {
+ (*acbp->callback)(acbp->userdata, portWWN,
+ protocolType, eventType);
+ return;
+ }
+ }
+ RELEASE_MUTEX(&_smhba_APSE_mutex);
+}
+
+HBA_STATUS
+SMHBA_RegisterForAdapterPortStatEvents(
+ void (*pCallback) (
+ void *pData,
+ HBA_WWN portWWN,
+ HBA_UINT32 protocolType,
+ HBA_UINT32 eventType),
+ void *pUserData,
+ HBA_HANDLE handle,
+ HBA_WWN portWWN,
+ HBA_UINT32 protocolType,
+ SMHBA_PROTOCOLSTATISTICS stats,
+ HBA_UINT32 statType,
+ HBA_CALLBACKHANDLE *pCallbackHandle) {
+
+ HBA_ADAPTERCALLBACK_ELEM *acbp;
+ SMHBARegisterForAdapterPortStatEventsFunc
+ registeredfunc;
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+
+ DEBUG(2, "SMHBA_RegisterForAdapterPortStatEvents for port: %s",
+ WWN2STR1(&portWWN), 0, 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+ /* we now have the _hbaapi_LL_mutex */
+
+ registeredfunc =
+ lib_infop->ftable.smhbafunctionTable.\
+ RegisterForAdapterPortStatEventsHandler;
+ if (registeredfunc == NULL) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
+ }
+
+ /*
+ * that allocated memory is used both as the handle for the
+ * caller, and as userdata to the vendor call so that on
+ * callback the specific registration may be recalled
+ */
+ acbp = (HBA_ADAPTERCALLBACK_ELEM *)
+ calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
+ if (acbp == NULL) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
+ }
+ *pCallbackHandle = (HBA_CALLBACKHANDLE) acbp;
+ acbp->callback = pCallback;
+ acbp->userdata = pUserData;
+ acbp->lib_info = lib_infop;
+
+ status = (registeredfunc)(smhba_adapterportstatevents_callback,
+ (void *)acbp,
+ vendorHandle,
+ portWWN,
+ protocolType,
+ stats,
+ statType,
+ &acbp->vendorcbhandle);
+ if (status != HBA_STATUS_OK) {
+ free(acbp);
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+ }
+
+ GRAB_MUTEX(&_smhba_APSE_mutex);
+ acbp->next = _smhba_adapterportstatevents_callback_list;
+ _smhba_adapterportstatevents_callback_list = acbp;
+
+ RELEASE_MUTEX(&_smhba_APSE_mutex);
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
+}
+
+/* SMHBA Adapter Port Phy Stat Events ************************************ */
+static void
+smhba_adapterphystatevents_callback(void *data,
+ HBA_WWN portWWN,
+ HBA_UINT32 phyIndex,
+ HBA_UINT32 eventType)
+{
+ HBA_ADAPTERCALLBACK_ELEM *acbp;
+
+ DEBUG(3,
+ "SMBA_AdapterPortStateEvent, port:%s, eventType:%d",
+ WWN2STR1(&portWWN), eventType, 0);
+
+ GRAB_MUTEX(&_smhba_APHYSE_mutex);
+ for (acbp = _smhba_adapterphystatevents_callback_list;
+ acbp != NULL;
+ acbp = acbp->next) {
+ if (data == (void *)acbp) {
+ (*acbp->callback)(acbp->userdata, portWWN, phyIndex, eventType);
+ return;
+ }
+ }
+ RELEASE_MUTEX(&_smhba_APHYSE_mutex);
+}
+
+HBA_STATUS
+SMHBA_RegisterForAdapterPhyStatEvents(
+ void (*pCallback) (
+ void *pData,
+ HBA_WWN portWWN,
+ HBA_UINT32 phyIndex,
+ HBA_UINT32 eventType),
+ void *pUserData,
+ HBA_HANDLE handle,
+ HBA_WWN portWWN,
+ HBA_UINT32 phyIndex,
+ SMHBA_PHYSTATISTICS stats,
+ HBA_UINT32 statType,
+ HBA_CALLBACKHANDLE *pCallbackHandle) {
+
+ HBA_ADAPTERCALLBACK_ELEM *acbp;
+ SMHBARegisterForAdapterPhyStatEventsFunc
+ registeredfunc;
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+
+ DEBUG(2, "SMHBA_RegisterForAdapterPhyStatEvents for port: %s",
+ WWN2STR1(&portWWN), 0, 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+ /* we now have the _hbaapi_LL_mutex */
+
+ registeredfunc =
+ lib_infop->ftable.smhbafunctionTable.\
+ RegisterForAdapterPhyStatEventsHandler;
+ if (registeredfunc == NULL) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
+ }
+
+ /*
+ * that allocated memory is used both as the handle for the
+ * caller, and as userdata to the vendor call so that on
+ * callback the specific registration may be recalled
+ */
+ acbp = (HBA_ADAPTERCALLBACK_ELEM *)
+ calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
+ if (acbp == NULL) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
+ }
+ *pCallbackHandle = (HBA_CALLBACKHANDLE) acbp;
+ acbp->callback = pCallback;
+ acbp->userdata = pUserData;
+ acbp->lib_info = lib_infop;
+
+ status = (registeredfunc)(smhba_adapterphystatevents_callback,
+ (void *)acbp,
+ vendorHandle,
+ portWWN,
+ phyIndex,
+ stats,
+ statType,
+ &acbp->vendorcbhandle);
+ if (status != HBA_STATUS_OK) {
+ free(acbp);
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+ }
+
+ GRAB_MUTEX(&_smhba_APHYSE_mutex);
+ acbp->next = _smhba_adapterphystatevents_callback_list;
+ _smhba_adapterphystatevents_callback_list = acbp;
+
+ RELEASE_MUTEX(&_smhba_APHYSE_mutex);
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
+}
+
+/* SMHBA Target Events ********************************************* */
+static void
+smhba_targetevents_callback(void *data,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN discoveredPortWWN,
+ HBA_WWN domainPortWWN,
+ HBA_UINT32 eventType)
+{
+ HBA_ADAPTERCALLBACK_ELEM *acbp;
+
+ DEBUG(3, "TargetEvent, hbaPort:%s, discoveredPort:%s eventType:%d",
+ WWN2STR1(&hbaPortWWN), WWN2STR2(&discoveredPortWWN), eventType);
+
+ GRAB_MUTEX(&_smhba_TE_mutex);
+ for (acbp = _smhba_targetevents_callback_list;
+ acbp != NULL;
+ acbp = acbp->next) {
+ if (data == (void *)acbp) {
+ (*acbp->callback)(acbp->userdata, hbaPortWWN,
+ discoveredPortWWN, domainPortWWN, eventType);
+ break;
+ }
+ }
+ RELEASE_MUTEX(&_smhba_TE_mutex);
+}
+
+HBA_STATUS
+SMHBA_RegisterForTargetEvents(
+ void (*pCallback) (
+ void *pData,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN discoveredPortWWN,
+ HBA_WWN domainPortWWN,
+ HBA_UINT32 eventType),
+ void *pUserData,
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN discoveredPortWWN,
+ HBA_WWN domainPortWWN,
+ HBA_CALLBACKHANDLE *pCallbackHandle,
+ HBA_UINT32 allTargets) {
+
+ HBA_ADAPTERCALLBACK_ELEM *acbp;
+ SMHBARegisterForTargetEventsFunc
+ registeredfunc;
+ HBA_STATUS status;
+ HBA_LIBRARY_INFO *lib_infop;
+ HBA_HANDLE vendorHandle;
+
+ DEBUG(2, "SMHBA_RegisterForTargetEvents, hbaPort:"
+ "%s, discoveredPort: %s",
+ WWN2STR1(&hbaPortWWN), WWN2STR2(&discoveredPortWWN), 0);
+
+ CHECKLIBRARYANDVERSION(SMHBA);
+ /* we now have the _hbaapi_LL_mutex */
+
+ registeredfunc = lib_infop->ftable.smhbafunctionTable.\
+ RegisterForTargetEventsHandler;
+
+ if (registeredfunc == NULL) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR_NOT_SUPPORTED);
+ }
+
+ /*
+ * that allocated memory is used both as the handle for the
+ * caller, and as userdata to the vendor call so that on
+ * callback the specific registration may be recalled
+ */
+ acbp = (HBA_ADAPTERCALLBACK_ELEM *)
+ calloc(1, sizeof (HBA_ADAPTERCALLBACK_ELEM));
+ if (acbp == NULL) {
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_ERROR);
+ }
+ *pCallbackHandle = (HBA_CALLBACKHANDLE) acbp;
+ acbp->callback = pCallback;
+ acbp->userdata = pUserData;
+ acbp->lib_info = lib_infop;
+
+ status = (registeredfunc)(smhba_targetevents_callback,
+ (void *)acbp,
+ vendorHandle,
+ hbaPortWWN,
+ discoveredPortWWN,
+ domainPortWWN,
+ &acbp->vendorcbhandle,
+ allTargets);
+ if (status != HBA_STATUS_OK) {
+ free(acbp);
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, status);
+ }
+
+ GRAB_MUTEX(&_smhba_TE_mutex);
+ acbp->next = _smhba_targetevents_callback_list;
+ _smhba_targetevents_callback_list = acbp;
+
+ RELEASE_MUTEX(&_smhba_TE_mutex);
+ RELEASE_MUTEX_RETURN(&_hbaapi_LL_mutex, HBA_STATUS_OK);
+}
diff --git a/usr/src/lib/smhba/common/llib-lSMHBAAPI b/usr/src/lib/smhba/common/llib-lSMHBAAPI
new file mode 100644
index 0000000000..18e4b625cb
--- /dev/null
+++ b/usr/src/lib/smhba/common/llib-lSMHBAAPI
@@ -0,0 +1,30 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*LINTLIBRARY*/
+/*PROTOLIB1*/
+
+#include <smhbaapi.h>
diff --git a/usr/src/lib/smhba/common/mapfile-vers b/usr/src/lib/smhba/common/mapfile-vers
new file mode 100644
index 0000000000..c1c823a847
--- /dev/null
+++ b/usr/src/lib/smhba/common/mapfile-vers
@@ -0,0 +1,136 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# MAPFILE HEADER START
+#
+# WARNING: STOP NOW. DO NOT MODIFY THIS FILE.
+# Object versioning must comply with the rules detailed in
+#
+# usr/src/lib/README.mapfiles
+#
+# You should not be making modifications here until you've read the most current
+# copy of that file. If you need help, contact a gatekeeper for guidance.
+#
+# MAPFILE HEADER END
+#
+
+
+SUNW_1.1 {
+ global:
+ HBA_GetVersion;
+ HBA_GetWrapperLibraryAttributes;
+ HBA_LoadLibrary;
+ HBA_FreeLibrary;
+ HBA_GetNumberOfAdapters;
+ HBA_GetAdapterName;
+ HBA_OpenAdapter;
+ HBA_CloseAdapter;
+ HBA_GetAdapterAttributes;
+ HBA_GetAdapterPortAttributes;
+ HBA_GetPortStatistics;
+ HBA_GetDiscoveredPortAttributes;
+ HBA_GetPortAttributesByWWN;
+ HBA_SendCTPassThru;
+ HBA_RefreshInformation;
+ HBA_ResetStatistics;
+ HBA_GetFcpTargetMapping;
+ HBA_GetFcpPersistentBinding;
+ HBA_GetEventBuffer;
+ HBA_SetRNIDMgmtInfo;
+ HBA_GetRNIDMgmtInfo;
+ HBA_SendRNID;
+ HBA_SendScsiInquiry;
+ HBA_SendReportLUNs;
+ HBA_SendReadCapacity;
+ HBA_GetVendorLibraryAttributes;
+ HBA_OpenAdapterByWWN;
+ HBA_SendCTPassThruV2;
+ HBA_RefreshAdapterConfiguration;
+ HBA_GetFcpTargetMappingV2;
+ HBA_RemoveCallback;
+ HBA_RegisterForAdapterAddEvents;
+ HBA_RegisterForAdapterEvents;
+ HBA_RegisterForAdapterPortEvents;
+ HBA_RegisterForAdapterPortStatEvents;
+ HBA_RegisterForTargetEvents;
+ HBA_RegisterForLinkEvents;
+ HBA_SendRNIDV2;
+ HBA_SendRLS;
+ HBA_SendRPL;
+ HBA_SendRPS;
+ HBA_SendSRL;
+ HBA_SendLIRR;
+ HBA_ScsiInquiryV2;
+ HBA_ScsiReportLUNsV2;
+ HBA_ScsiReadCapacityV2;
+ HBA_GetBindingCapability;
+ HBA_SetBindingSupport;
+ HBA_GetBindingSupport;
+ HBA_SetPersistentBindingV2;
+ HBA_GetPersistentBindingV2;
+ HBA_RemovePersistentBinding;
+ HBA_RemoveAllPersistentBindings;
+ HBA_GetFC4Statistics;
+ HBA_GetFCPStatistics;
+ SMHBA_GetVersion;
+ SMHBA_GetWrapperLibraryAttributes;
+ SMHBA_GetVendorLibraryAttributes;
+ SMHBA_GetAdapterAttributes;
+ SMHBA_GetNumberOfPorts;
+ SMHBA_GetPortType;
+ SMHBA_GetAdapterPortAttributes;
+ SMHBA_GetDiscoveredPortAttributes;
+ SMHBA_GetPortAttributesByWWN;
+ SMHBA_GetFCPhyAttributes;
+ SMHBA_GetSASPhyAttributes;
+ SMHBA_GetProtocolStatistics;
+ SMHBA_GetPhyStatistics;
+ SMHBA_GetBindingCapability;
+ SMHBA_GetBindingSupport;
+ SMHBA_SetBindingSupport;
+ SMHBA_GetTargetMapping;
+ SMHBA_GetPersistentBinding;
+ SMHBA_SetPersistentBinding;
+ SMHBA_RemovePersistentBinding;
+ SMHBA_RemoveAllPersistentBindings;
+ SMHBA_GetLUNStatistics;
+ SMHBA_ScsiInquiry;
+ SMHBA_ScsiReportLUNs;
+ SMHBA_ScsiReadCapacity;
+ SMHBA_SendTEST;
+ SMHBA_SendECHO;
+ SMHBA_SendSMPPassThru;
+ SMHBA_RegisterForAdapterAddEvents;
+ SMHBA_RegisterForAdapterEvents;
+ SMHBA_RegisterForAdapterPortEvents;
+ SMHBA_RegisterForAdapterPortStatEvents;
+ SMHBA_RegisterForAdapterPortStatEvents;
+ SMHBA_RegisterForTargetEvents;
+
+ local:
+ *;
+};
+
diff --git a/usr/src/lib/smhba/common/smhba.conf b/usr/src/lib/smhba/common/smhba.conf
new file mode 100644
index 0000000000..c93436e087
--- /dev/null
+++ b/usr/src/lib/smhba/common/smhba.conf
@@ -0,0 +1,36 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#
+# This file contains names and references to SM-HBA libraries
+#
+# Format:
+#
+# <library name> <library pathname>
+#
+# The library name should be prepended with the domain of
+# the manufacturer or driver author.
+com.sun.sashba /usr/lib/libsun_sas.so.1
+com.sun.sashba64 /usr/lib/64/libsun_sas.so.1
+
diff --git a/usr/src/lib/smhba/common/smhbaapi.h b/usr/src/lib/smhba/common/smhbaapi.h
new file mode 100644
index 0000000000..958b34f342
--- /dev/null
+++ b/usr/src/lib/smhba/common/smhbaapi.h
@@ -0,0 +1,672 @@
+/*
+ * ****************************************************************************
+ *
+ * Description
+ * smhbaapi.h - general header file for client
+ * and library developers
+ *
+ * License:
+ * The contents of this file are subject to the SNIA Public License
+ * Version 1.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * /http://www.snia.org/English/Resources/Code/OpenSource.html
+ *
+ * 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 for SM-HBA API general header file
+ *
+ * The Initial Developer of the Original Code is:
+ * Benjamin F. Kuo, Troika Networks, Inc. (benk@troikanetworks.com)
+ *
+ * Contributor(s):
+ * Tuan Lam, QLogic Corp. (t_lam@qlc.com)
+ * Dan Willie, Emulex Corp. (Dan.Willie@emulex.com)
+ * Dixon Hutchinson, Legato Systems, Inc. (dhutchin@legato.com)
+ * David Dillard, VERITAS Software Corp. (david.dillard@veritas.com)
+ *
+ * ****************************************************************************
+ *
+ * Adding on SM-HBA related definitions.
+ *
+ * - Includes the original HBA API header.
+ * - SMHBA_* interfaces and structures are defined.
+ *
+ * ****************************************************************************
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SMHBAAPI_H_
+#define _SMHBAAPI_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <hbaapi.h>
+
+/* Library version string */
+#define SMHBA_LIBVERSION 1
+
+/*
+ * A SCSI function was requested at a time when issuing the requested command
+ * would cause a SCSI overlapped command condition (see SAM-3)
+ */
+#define HBA_STATUS_ERROR_TARGET_BUSY 30
+/* SM-HBA 6.2 Status Return Values */
+/* A call was made to HBA_FreeLibrary when no library was loaded */
+#define HBA_STATUS_ERROR_NOT_LOADED 31
+/* A call was made to HBA_LoadLibrary when a library was already loaded */
+#define HBA_STATUS_ERROR_ALREADY_LOADED 32
+/*
+ * The Address Identifier specified in a call to HBA_SendRNIDV2
+ * violates access control rules * for that call.
+ */
+#define HBA_STATUS_ERROR_ILLEGAL_FCID 33
+#define HBA_STATUS_ERROR_NOT_ASCSIDEVICE 34
+#define HBA_STATUS_ERROR_INVALID_PROTOCOL_TYPE 35
+#define HBA_STATUS_ERROR_BAD_EVENT_TYPE 36
+
+
+/* SM-HBA 6.4.1.1 Port Type */
+#define HBA_PORTTYPE_SASDEVICE 30 /* SAS (SSP or STP) */
+#define HBA_PORTTYPE_SATADEVICE 31 /* SATA Device, i.e. Direct Attach SATA */
+#define HBA_PORTTYPE_SASEXPANDER 32 /* SAS Expander */
+
+/* SM-HBA 6.4.1.2 Port State */
+#define HBA_PORTSTATE_DEGRADED 9 /* Degraded, but Operational mode */
+
+/* SM-HBA 6.11.1.3 Port Speed */
+#define HBA_PORTSPEED_4GBIT 8 /* 4 GBit / sec */
+
+/* SM-HBA 6.1 Basic Attributes Types */
+typedef struct SMHBA_scsilun {HBA_UINT8 lun[8]; }
+ SMHBA_SCSILUN, *PSMHBA_SCSILUN;
+ /* A byte array representation of a SCSI */
+ /* LUN (see SAM-4). The first byte of the */
+ /* LUN shall be in the first byte of the */
+ /* array, and successive bytes of the SCSI */
+ /* LUN shall be in successive bytes of the */
+ /* array. */
+typedef unsigned long HBA_SCSILUN;
+ /* A 64 bit unsigned integer representation */
+ /* of a SCSI LUN (see SAM-4); */
+ /* may use OS-specific typedef. */
+ /* Byte zero of a SCSI LUN shall be stored */
+ /* in the lowest memory address */
+ /* of the unsigned 64-bit integer value, */
+ /* and successive bytes of the SCSI LUN */
+ /* shall be stored in successively higher memory */
+ /* addresses of the unsigned 64-bit intege value. */
+ /* Note that computers often do not store */
+ /* a byte array in memory in the same order */
+ /* as they store an integer. */
+ /* This standard requires storage as a byte array */
+
+
+/* SM-HBA 6.3.1 Generic Adapter Attribute */
+typedef struct SMHBA_AdapterAttributes {
+ char Manufacturer[64];
+ char SerialNumber[64];
+ char Model[256];
+ char ModelDescription[256];
+ char HardwareVersion[256];
+ char DriverVersion[256];
+ char OptionROMVersion[256];
+ char FirmwareVersion[256];
+ HBA_UINT32 VendorSpecificID;
+ char DriverName[256];
+ char HBASymbolicName[256];
+ char RedundantOptionROMVersion[256];
+ char RedundantFirmwareVersion[256];
+} SMHBA_ADAPTERATTRIBUTES, *PSMHBA_ADAPTERATTRIBUTES;
+
+/* SM-HBA 6.4.6 SMHBA FC Port Attributes */
+typedef struct SMHBA_FC_Port {
+ HBA_WWN NodeWWN;
+ HBA_WWN PortWWN;
+ HBA_UINT32 FcId;
+ HBA_COS PortSupportedClassofService;
+ HBA_FC4TYPES PortSupportedFc4Types;
+ HBA_FC4TYPES PortActiveFc4Types;
+ HBA_WWN FabricName;
+ char PortSymbolicName[256];
+ HBA_UINT32 NumberofDiscoveredPorts;
+ HBA_UINT8 NumberofPhys;
+}SMHBA_FC_PORT, *PSMHBA_FC_PORT;
+
+/* SM-HBA 6.4.7.1 HBA_SASPortProtocol */
+typedef HBA_UINT32 HBA_SASPORTPROTOCOL;
+#define HBA_SASPORTPROTOCOL_SSP 1 /* Serial SCSI Protocol Port */
+#define HBA_SASPORTPROTOCOL_STP 2 /* Serial ATA Tunneling Protocol Port */
+#define HBA_SASPORTPROTOCOL_SMP 4 /* Serial Management Protocol Port */
+/* SATA Device, Direct Attached or anywhere in the domain. */
+#define HBA_SASPORTPROTOCOL_SATA 8
+
+/* SM-HBA 6.4.8 SMHBA SAS Port Attributes */
+typedef struct SMHBA_SAS_Port {
+ HBA_SASPORTPROTOCOL PortProtocol;
+ HBA_WWN LocalSASAddress;
+ HBA_WWN AttachedSASAddress;
+ HBA_UINT32 NumberofDiscoveredPorts;
+ HBA_UINT32 NumberofPhys;
+} SMHBA_SAS_PORT, *PSMHBA_SAS_PORT;
+
+/* SM-HBA 6.4.2 Generic Port Attributes */
+typedef union SMHBA_Port {
+ SMHBA_FC_PORT *FCPort;
+ SMHBA_SAS_PORT *SASPort;
+} SMHBA_PORT, *PSMHBA_PORT;
+
+typedef struct SMHBA_PortAttributes {
+ HBA_PORTTYPE PortType;
+ HBA_PORTSTATE PortState;
+ char OSDeviceName[256];
+ SMHBA_PORT PortSpecificAttribute;
+} SMHBA_PORTATTRIBUTES, *PSMHBA_PORTATTRIBUTES;
+
+/* SM-HBA 6.5.1.1 FC Phy Speed */
+typedef HBA_UINT32 HBA_FCPHYSPEED;
+/* Unknown transceiver incapable of reporting */
+#define HBA_FCSPEED_UNKNOWN 0
+/*
+ * The following are redundantly defined in SM-HBA 6.11.1.3 Port Speed.
+ * #define HBA_PORTSPEED_1GBIT 1 1 GBit/sec
+ * #define HBA_PORTSPEED_2GBIT 2 2 GBit/sec
+ * #define HBA_PORTSPEED_10GBIT 4 10 GBit/sec
+ * #define HBA_PORTSPEED_4GBIT 8 4 GBit/sec
+ */
+#define HBA_FCPHYSPEED_8GBIT 16 /* 8 GBit/sec */
+#define HBA_FCPHYSPEED_16GBIT 32 /* 16 GBit/sec */
+/*
+ * The following conflicts with HBA API
+ * #define HBA_PORTSPEED_NOT_NEGOTIATED (1<<15) Speed not established
+ */
+
+/* SM-HBA 6.6.1.2 SM-HBA FC Phy Type */
+typedef HBA_UINT8 HBA_FCPHYTYPE;
+#define HBA_FCPHYTYPE_UNKNOWN 1 /* Unknown Phy type */
+#define HBA_FCPHYTYPE_OPTICAL 2 /* Optical Phy */
+#define HBA_FCPHYTYPE_COPPER 4 /* Copper Phy */
+
+/* SM-HBA 6.5.2 SM-HBA FC Phy Attributes */
+typedef struct SMHBA_FC_Phy {
+ HBA_FCPHYSPEED PhySupportedSpeed; /* PhySupportedSpeed */
+ HBA_FCPHYSPEED PhySpeed; /* PhySpeed */
+ HBA_FCPHYTYPE PhyType;
+ HBA_UINT32 MaxFrameSize; /* MaxFrameSize */
+} SMHBA_FC_PHY, *PSMHBA_FC_PHY;
+
+/* SM-HBA 6.5.4 SAS PHY Attribute Data Declaration */
+typedef HBA_UINT32 HBA_SASPHYSPEED;
+
+#define HBA_SASSTATE_UNKNOWN 0x00 /* Phy is enabled. Speed is unknown */
+#define HBA_SASSTATE_DISABLED 0x01 /* Phy is disabled. */
+/* Phy is enabled. But failed speed negotiation. */
+#define HBA_SASSTATE_FAILED 0x02
+/*
+ * Phy is enabled. Detected a SATA device and entered the SATA Spinup hold
+ * state.
+ */
+#define HBA_SASSTATE_SATASPINUP 0x03
+/* The phy is attached to a Port Selector (see SATA-2.6). */
+#define HBA_SASSTATE_SATAPORTSEL 0x04
+#define HBA_SASSPEED_1_5GBIT 0x08 /* 1.5 GBit/sec */
+#define HBA_SASSPEED_3GBIT 0x09 /* 3 GBit/sec */
+#define HBA_SASSPEED_6GBIT 0x0a /* 6 GBit/sec */
+
+/* SM-HBA 6.5.5 SAS Phy Attribute */
+typedef struct SMHBA_SAS_Phy {
+ HBA_UINT8 PhyIdentifier;
+ HBA_SASPHYSPEED NegotiatedLinkRate;
+ HBA_SASPHYSPEED ProgrammedMinLinkRate;
+ HBA_SASPHYSPEED HardwareMinLinkRate;
+ HBA_SASPHYSPEED ProgrammedMaxLinkRate;
+ HBA_SASPHYSPEED HardwareMaxLinkRate;
+ HBA_WWN domainPortWWN;
+} SMHBA_SAS_PHY, *PSMHBA_SAS_PHY;
+
+/* SM-HBA 6.6.1.1 Protocol Statistics Data Declarations */
+/* Statistical counters for FC-4, SSP, STP, SMP protocols */
+typedef struct SMHBA_ProtocolStatistics {
+ HBA_INT64 SecondsSinceLastReset;
+ HBA_INT64 InputRequests;
+ HBA_INT64 OutputRequests;
+ HBA_INT64 ControlRequests;
+ HBA_INT64 InputMegabytes;
+ HBA_INT64 OutputMegabytes;
+} SMHBA_PROTOCOLSTATISTICS, *PSMHBA_PROTOCOLSTATISTICS;
+
+/* SM-HBA 6.6.2.1 Port Statistics Data Declarations */
+typedef struct SMHBA_PortStatistics {
+ HBA_INT64 SecondsSinceLastReset;
+ HBA_INT64 TxFrames;
+ HBA_INT64 TxWords;
+ HBA_INT64 RxFrames;
+ HBA_INT64 RxWords;
+}SMHBA_PORTSTATISTICS, *PSMHBA_PORTSTATISTICS;
+
+/* SM-HBA 6.6.2.2 SAS Phy Statistics Data Declaration */
+typedef struct SMHBA_SASPhyStatistics {
+ HBA_INT64 SecondsSinceLastReset;
+ HBA_INT64 TxFrames;
+ HBA_INT64 TxWords;
+ HBA_INT64 RxFrames;
+ HBA_INT64 RxWords;
+ HBA_INT64 InvalidDwordCount;
+ HBA_INT64 RunningDisparityErrorCount;
+ HBA_INT64 LossofDwordSyncCount;
+ HBA_INT64 PhyResetProblemCount;
+} SMHBA_SASPHYSTATISTICS, *PSMHBA_SASPHYSTATISTICS;
+
+/* SM-HBA 6.6.2.4 FC Phy Statistics Data Declaration */
+/* Statistical counters for FC-0, FC-1, and FC-2 */
+typedef struct SMHBA_FCPhyStatistics {
+ HBA_INT64 SecondsSinceLastReset;
+ HBA_INT64 TxFrames;
+ HBA_INT64 TxWords;
+ HBA_INT64 RxFrames;
+ HBA_INT64 RxWords;
+ HBA_INT64 LIPCount;
+ HBA_INT64 NOSCount;
+ HBA_INT64 ErrorFrames;
+ HBA_INT64 DumpedFrames;
+ HBA_INT64 LinkFailureCount;
+ HBA_INT64 LossOfSyncCount;
+ HBA_INT64 LossOfSignalCount;
+ HBA_INT64 PrimitiveSeqProtocolErrCount;
+ HBA_INT64 InvalidTxWordCount;
+ HBA_INT64 InvalidCRCCount;
+}SMHBA_FCPHYSTATISTICS, *PSMHBA_FCPHYSTATISTICS;
+
+/* SM-HBA 6.6.2.1 Phy Statistics Data Declaration */
+typedef union SMHBA_PhyStatistics {
+ SMHBA_SASPHYSTATISTICS *SASPhyStatistics;
+ SMHBA_FCPHYSTATISTICS *FCPhyStatistics;
+} SMHBA_PHYSTATISTICS, *PSMHBA_PHYSTATISTICS;
+
+/* SM-HBA 6.7.1.1 SMHBA_BIND_CAPABILITY */
+typedef HBA_UINT32 SMHBA_BIND_CAPABILITY;
+#define SMHBA_CAN_BIND_TO_WWPN 0x0001
+#define SMHBA_CAN_BIND_TO_LUID 0x0002
+#define SMHBA_CAN_BIND_ANY_LUNS 0x0400
+#define SMHBA_CAN_BIND_AUTOMAP 0x0800
+
+/* SM-HBA 6.7.1.2 SMHBA_BIND_TYPE */
+typedef HBA_UINT32 SMHBA_BIND_TYPE;
+#define SMHBA_BIND_TO_WWPN 0x0001
+#define SMHBA_BIND_TO_LUID 0x0002
+
+/* SM-HBA 6.7.1.3 SMHBA_ScsiId */
+typedef struct SMHBA_ScsiId {
+ char OSDeviceName[256];
+ HBA_UINT32 ScsiBusNumber;
+ HBA_UINT32 ScsiTargetNumber;
+ HBA_UINT32 ScsiOSLun;
+} SMHBA_SCSIID, *PSMHBA_SCSIID;
+
+/* SM-HBA 6.7.1.4 SMHBA_LUID */
+typedef struct SMHBA_LUID {
+ char buffer[256];
+} SMHBA_LUID, *PSMHBA_LUID;
+
+/* SM-HBA 6.7.1.5 SMHBA_PORTLUN */
+typedef struct SMHBA_PORTLUN {
+ HBA_WWN PortWWN;
+ HBA_WWN domainPortWWN;
+ SMHBA_SCSILUN TargetLun;
+} SMHBA_PORTLUN, *PSMHBA_PORTLUN;
+
+/* SM-HBA 6.7.1.6 Composite types */
+typedef struct SMHBA_ScsiEntry {
+ SMHBA_SCSIID ScsiId;
+ SMHBA_PORTLUN PortLun;
+ SMHBA_LUID LUID;
+} SMHBA_SCSIENTRY, *PSMHBA_SCSIENTRY;
+
+typedef struct SMHBA_TargetMapping {
+ HBA_UINT32 NumberOfEntries;
+ SMHBA_SCSIENTRY entry[1]; /* Variable length array */
+} SMHBA_TARGETMAPPING, *PSMHBA_TARGETMAPPING;
+
+typedef struct SMHBA_BindingEntry {
+ SMHBA_BIND_TYPE type;
+ SMHBA_SCSIID ScsiId;
+ SMHBA_PORTLUN PortLun;
+ SMHBA_LUID LUID;
+ HBA_STATUS Status;
+} SMHBA_BINDINGENTRY, *PSMHBA_BINDINGENTRY;
+
+typedef struct SMHBA_Binding {
+ HBA_UINT32 NumberOfEntries;
+ SMHBA_BINDINGENTRY entry[1]; /* Variable length array */
+} SMHBA_BINDING, *PSMHBA_BINDING;
+
+/* SM-HBA 6.9.5 Library Attribute Data Declarations */
+typedef struct SMHBA_LibraryAttributes {
+ char LibPath[256];
+ char VName[256];
+ char VVersion[256];
+ struct {
+ int tm_mday; /* day of the month - [1 - 31] */
+ int tm_mon; /* months since January - [0 - 11] */
+ int tm_year; /* years since 1900 */
+ } build_date;
+} SMHBA_LIBRARYATTRIBUTES, *PSMHBA_LIBRARYATTRIBUTES;
+
+/* SM-HBA 6.8.1 Asynchronous Event Data Declarations */
+#define HBA_EVENT_PORT_BROADCAST_CHANGE 0x205
+#define HBA_EVENT_PORT_BROADCAST_SES 0x208
+#define HBA_EVENT_PORT_BROADCAST_D24_0 0x206
+#define HBA_EVENT_PORT_BROADCAST_D27_4 0x207
+#define HBA_EVENT_PORT_BROADCAST_D01_4 0x209
+#define HBA_EVENT_PORT_BROADCAST_D04_7 0x20A
+#define HBA_EVENT_PORT_BROADCAST_D16_7 0x20B
+#define HBA_EVENT_PORT_BROADCAST_D29_7 0x20C
+#define HBA_EVENT_PORT_ALL 0x2FF
+
+/* SM-HBA specific entry points. */
+
+HBA_UINT32 SMHBA_GetVersion();
+
+HBA_UINT32 SMHBA_GetWrapperLibraryAttributes(
+ SMHBA_LIBRARYATTRIBUTES *attributes
+);
+
+HBA_UINT32 SMHBA_GetVendorLibraryAttributes(
+ HBA_UINT32 adapter_index,
+ SMHBA_LIBRARYATTRIBUTES *attributes
+);
+
+HBA_STATUS SMHBA_GetAdapterAttributes(
+ HBA_HANDLE handle,
+ SMHBA_ADAPTERATTRIBUTES *pAdapterAttributes
+);
+
+HBA_STATUS SMHBA_GetNumberOfPorts(
+ HBA_HANDLE handle,
+ HBA_UINT32 *numberofports
+);
+
+HBA_STATUS SMHBA_GetPortType(
+ HBA_HANDLE handle,
+ HBA_UINT32 portindex,
+ HBA_PORTTYPE *porttype
+);
+
+HBA_STATUS SMHBA_GetAdapterPortAttributes(
+ HBA_HANDLE handle,
+ HBA_UINT32 portindex,
+ SMHBA_PORTATTRIBUTES *portattributes
+);
+
+HBA_STATUS SMHBA_GetDiscoveredPortAttributes(
+ HBA_HANDLE handle,
+ HBA_UINT32 portindex,
+ HBA_UINT32 discoveredportindex,
+ SMHBA_PORTATTRIBUTES *porattributes
+);
+
+HBA_STATUS SMHBA_GetPortAttributesByWWN(
+ HBA_HANDLE handle,
+ HBA_WWN portWWN,
+ HBA_WWN domainPortWWN,
+ SMHBA_PORTATTRIBUTES *portattributes
+);
+
+HBA_STATUS SMHBA_GetPortAttributesByWWN(
+ HBA_HANDLE handle,
+ HBA_WWN portWWN,
+ HBA_WWN domainPortWWN,
+ SMHBA_PORTATTRIBUTES *portattributes
+);
+
+HBA_STATUS SMHBA_GetFCPhyAttributes(
+ HBA_HANDLE handle,
+ HBA_UINT32 portindex,
+ HBA_UINT32 phyindex,
+ SMHBA_FC_PHY *phytype
+);
+
+HBA_STATUS SMHBA_GetSASPhyAttributes(
+ HBA_HANDLE handle,
+ HBA_UINT32 portindex,
+ HBA_UINT32 phyindex,
+ SMHBA_SAS_PHY *phytype
+);
+
+HBA_STATUS SMHBA_GetProtocolStatistics(
+ HBA_HANDLE handle,
+ HBA_UINT32 portindex,
+ HBA_UINT32 protocoltype,
+ SMHBA_PROTOCOLSTATISTICS *pProtocolStatistics
+);
+
+HBA_STATUS SMHBA_GetPhyStatistics(
+ HBA_HANDLE handle,
+ HBA_UINT32 portindex,
+ HBA_UINT32 phyindex,
+ SMHBA_PHYSTATISTICS *pPhyStatistics
+);
+
+HBA_STATUS SMHBA_SendTEST(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN destWWN,
+ HBA_UINT32 destFCID,
+ void *pReqBuffer,
+ HBA_UINT32 ReqBufferSize
+);
+
+HBA_STATUS SMHBA_SendECHO(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN destWWN,
+ HBA_UINT32 destFCID,
+ void *pReqBuffer,
+ HBA_UINT32 ReqBufferSize,
+ void *pRspBuffer,
+ HBA_UINT32 *pRspBufferSize
+);
+
+HBA_UINT32 SMHBA_SendSMPPassThru(
+ HBA_HANDLE handle,
+ HBA_WWN hbaportWWN,
+ HBA_WWN destportWWN,
+ HBA_WWN domainPortWWN,
+ void *pReqBuffer,
+ HBA_UINT32 ReqBufferSize,
+ void *pRspBuffer,
+ HBA_UINT32 *pRspBufferSize
+);
+
+HBA_STATUS SMHBA_GetBindingCapability(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN domainPortWWN,
+ SMHBA_BIND_CAPABILITY *pFlags
+);
+
+HBA_STATUS SMHBA_GetBindingSupport(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN domainPortWWN,
+ SMHBA_BIND_CAPABILITY *pFlags
+);
+
+HBA_STATUS SMHBA_SetBindingSupport(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN domainPortWWN,
+ SMHBA_BIND_CAPABILITY flags
+);
+
+HBA_STATUS SMHBA_GetTargetMapping(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN domainPortWWN,
+ SMHBA_TARGETMAPPING *pMapping
+);
+
+HBA_STATUS SMHBA_GetPersistentBinding(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN domainPortWWN,
+ SMHBA_BINDING *binding
+);
+
+HBA_STATUS SMHBA_SetPersistentBinding(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN domainPortWWN,
+ const SMHBA_BINDING *binding
+);
+
+HBA_STATUS SMHBA_RemovePersistentBinding(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN domainPortWWN,
+ const SMHBA_BINDING *binding
+);
+
+HBA_STATUS SMHBA_RemoveAllPersistentBindings(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN domainPortWWN
+);
+
+HBA_STATUS SMHBA_GetLUNStatistics(
+ HBA_HANDLE handle,
+ const HBA_SCSIID *lunit,
+ SMHBA_PROTOCOLSTATISTICS *statistics
+);
+
+HBA_STATUS SMHBA_ScsiInquiry(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN discoveredPortWWN,
+ HBA_WWN domainPortWWN,
+ SMHBA_SCSILUN smhbaLUN,
+ HBA_UINT8 CDB_Byte1,
+ HBA_UINT8 CDB_Byte2,
+ void *pRspBuffer,
+ HBA_UINT32 *pRspBufferSize,
+ HBA_UINT8 *pScsiStatus,
+ void *pSenseBuffer,
+ HBA_UINT32 *pSenseBufferSize
+);
+
+HBA_STATUS SMHBA_ScsiReportLUNs(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN discoveredPortWWN,
+ HBA_WWN domainPortWWN,
+ void *pRspBuffer,
+ HBA_UINT32 *pRspBufferSize,
+ HBA_UINT8 *pScsiStatus,
+ void *pSenseBuffer,
+ HBA_UINT32 *pSenseBufferSize
+);
+
+HBA_STATUS SMHBA_ScsiReadCapacity(
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN discoveredPortWWN,
+ HBA_WWN domainPortWWN,
+ SMHBA_SCSILUN smhbaLUN,
+ void *pRspBuffer,
+ HBA_UINT32 *pRspBufferSize,
+ HBA_UINT8 *pScsiStatus,
+ void *pSenseBuffer,
+ HBA_UINT32 *pSenseBufferSize
+);
+
+HBA_STATUS SMHBA_RegisterForAdapterAddEvents(
+ void (*pCallback) (
+ void *pData,
+ HBA_WWN portWWN,
+ HBA_UINT32 eventType),
+ void *pUserData,
+ HBA_CALLBACKHANDLE *pCallbackHandle
+);
+
+HBA_STATUS SMHBA_RegisterForAdapterEvents(
+ void (*pCallback) (
+ void *pData,
+ HBA_WWN portWWN,
+ HBA_UINT32 eventType),
+ void *pUserData,
+ HBA_HANDLE handle,
+ HBA_CALLBACKHANDLE *pCallbackHandle
+);
+
+HBA_STATUS SMHBA_RegisterForAdapterPortEvents(
+ void (*pCallback) (
+ void *pData,
+ HBA_WWN portWWN,
+ HBA_UINT32 eventType,
+ HBA_UINT32 fabricPortID),
+ void *pUserData,
+ HBA_HANDLE handle,
+ HBA_WWN portWWN,
+ HBA_UINT32 specificEventType,
+ HBA_CALLBACKHANDLE *pCallbackHandle
+);
+
+HBA_STATUS SMHBA_RegisterForAdapterPortStatEvents(
+ void (*pCallback) (
+ void *pData,
+ HBA_WWN portWWN,
+ HBA_UINT32 protocolType,
+ HBA_UINT32 eventType),
+ void *pUserData,
+ HBA_HANDLE handle,
+ HBA_WWN portWWN,
+ HBA_UINT32 protocolType,
+ SMHBA_PROTOCOLSTATISTICS stats,
+ HBA_UINT32 statType,
+ HBA_CALLBACKHANDLE *pCallbackHandle
+);
+
+HBA_STATUS SMHBA_RegisterForAdapterPhyStatEvents(
+ void (*pCallback) (
+ void *pData,
+ HBA_WWN portWWN,
+ HBA_UINT32 phyIndex,
+ HBA_UINT32 eventType),
+ void *pUserData,
+ HBA_HANDLE handle,
+ HBA_WWN portWWN,
+ HBA_UINT32 phyIndex,
+ SMHBA_PHYSTATISTICS stats,
+ HBA_UINT32 statType,
+ HBA_CALLBACKHANDLE *pCallbackHandle
+);
+
+HBA_STATUS SMHBA_RegisterForTargetEvents(
+ void (*pCallback) (
+ void *pData,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN discoveredPortWWN,
+ HBA_WWN domainPortWWN,
+ HBA_UINT32 eventType),
+ void *pUserData,
+ HBA_HANDLE handle,
+ HBA_WWN hbaPortWWN,
+ HBA_WWN discoveredPortWWN,
+ HBA_WWN domainPortWWN,
+ HBA_CALLBACKHANDLE *pCallbackHandle,
+ HBA_UINT32 allTargets
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SMHBAAPI_H_ */
diff --git a/usr/src/lib/smhba/common/vendorsmhbaapi.h b/usr/src/lib/smhba/common/vendorsmhbaapi.h
new file mode 100644
index 0000000000..42982bc909
--- /dev/null
+++ b/usr/src/lib/smhba/common/vendorsmhbaapi.h
@@ -0,0 +1,207 @@
+/*
+ * ****************************************************************************
+ *
+ * Description
+ * vendorhbaapi.h - incombination with hbaapi.h, defines interface to
+ * vendor specific API
+ *
+ * License:
+ * The contents of this file are subject to the SNIA Public License
+ * Version 1.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * /http://www.snia.org/English/Resources/Code/OpenSource.html
+ *
+ * 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 HBA API general header file
+ *
+ * The Initial Developer of the Original Code is:
+ * Benjamin F. Kuo, Troika Networks, Inc. (benk@troikanetworks.com)
+ *
+ * Contributor(s):
+ * Tuan Lam, QLogic Corp. (t_lam@qlc.com)
+ * Dan Willie, Emulex Corp. (Dan.Willie@emulex.com)
+ * Dixon Hutchinson, Legato Systems, Inc. (dhutchin@legato.com)
+ * David Dillard, VERITAS Software Corp. (david.dillard@veritas.com)
+ *
+ * ****************************************************************************
+ *
+ * Changes:
+ * 12/12/2001 Original revision, code split out of hbaapi.h
+ * (for other changes... see the CVS logs)
+ * ****************************************************************************
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _VENDORSMHBAAPI_H_
+#define _VENDORSMHBAAPI_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <vendorhbaapi.h>
+
+/* SM-HBA-2 6.9.2 Function Prototypes */
+typedef HBA_UINT32 (* SMHBAGetVersionFunc)();
+typedef HBA_UINT32 (* SMHBAGetWrapperLibraryAttributesFunc)
+ (HBA_UINT32, SMHBA_LIBRARYATTRIBUTES *);
+typedef HBA_UINT32 (* SMHBAGetVendorLibraryAttributesFunc)
+ (SMHBA_LIBRARYATTRIBUTES *);
+typedef HBA_STATUS (* SMHBAGetAdapterAttributesFunc)
+ (HBA_HANDLE, SMHBA_ADAPTERATTRIBUTES *);
+typedef HBA_STATUS (* SMHBAGetNumberOfPortsFunc)
+ (HBA_HANDLE, HBA_UINT32 *);
+typedef HBA_STATUS (* SMHBAGetPortTypeFunc)
+ (HBA_HANDLE, HBA_UINT32, HBA_PORTTYPE *);
+typedef HBA_STATUS (* SMHBAGetAdapterPortAttributesFunc)
+ (HBA_HANDLE, HBA_UINT32, SMHBA_PORTATTRIBUTES *);
+typedef HBA_STATUS (* SMHBAGetDiscoveredPortAttributesFunc)
+ (HBA_HANDLE, HBA_UINT32, HBA_UINT32, SMHBA_PORTATTRIBUTES *);
+typedef HBA_STATUS (* SMHBAGetPortAttributesByWWNFunc)
+ (HBA_HANDLE, HBA_WWN, HBA_WWN, SMHBA_PORTATTRIBUTES *);
+typedef HBA_STATUS (* SMHBAGetFCPhyAttributesFunc)
+ (HBA_HANDLE, HBA_UINT32, HBA_UINT32, SMHBA_FC_PHY *);
+typedef HBA_STATUS (* SMHBAGetSASPhyAttributesFunc)
+ (HBA_HANDLE, HBA_UINT32, HBA_UINT32, SMHBA_SAS_PHY *);
+typedef HBA_STATUS (* SMHBAGetProtocolStatisticsFunc)
+ (HBA_HANDLE, HBA_UINT32, HBA_UINT32, SMHBA_PROTOCOLSTATISTICS *);
+typedef HBA_STATUS (* SMHBAGetPhyStatisticsFunc)
+ (HBA_HANDLE, HBA_UINT32, HBA_UINT32, SMHBA_PHYSTATISTICS *);
+typedef HBA_STATUS (* SMHBASendTESTFunc)
+ (HBA_HANDLE, HBA_WWN, HBA_WWN, HBA_UINT32, void *, HBA_UINT32);
+typedef HBA_STATUS (* SMHBASendECHOFunc)
+ (HBA_HANDLE, HBA_WWN, HBA_WWN, HBA_UINT32, void *, HBA_UINT32,
+ void *, HBA_UINT32 *);
+typedef HBA_STATUS (* SMHBASendSMPPassThruFunc)
+ (HBA_HANDLE, HBA_WWN, HBA_WWN, HBA_WWN, void *, HBA_UINT32, void *,
+ HBA_UINT32 *);
+typedef HBA_STATUS (* SMHBAGetBindingCapabilityFunc)
+ (HBA_HANDLE, HBA_WWN, HBA_WWN, SMHBA_BIND_CAPABILITY *);
+typedef HBA_STATUS (* SMHBAGetBindingSupportFunc)
+ (HBA_HANDLE, HBA_WWN, HBA_WWN, SMHBA_BIND_CAPABILITY *);
+typedef HBA_STATUS (* SMHBASetBindingSupportFunc)
+ (HBA_HANDLE, HBA_WWN, HBA_WWN, SMHBA_BIND_CAPABILITY);
+typedef HBA_STATUS (* SMHBAGetTargetMappingFunc)
+ (HBA_HANDLE, HBA_WWN, HBA_WWN, SMHBA_TARGETMAPPING *);
+typedef HBA_STATUS (* SMHBAGetPersistentBindingFunc)
+ (HBA_HANDLE, HBA_WWN, HBA_WWN, SMHBA_BINDING *);
+typedef HBA_STATUS (* SMHBASetPersistentBindingFunc)
+ (HBA_HANDLE, HBA_WWN, HBA_WWN, const SMHBA_BINDING *);
+typedef HBA_STATUS (* SMHBARemovePersistentBindingFunc)
+ (HBA_HANDLE, HBA_WWN, HBA_WWN, const SMHBA_BINDING *);
+typedef HBA_STATUS (* SMHBARemoveAllPersistentBindingsFunc)
+ (HBA_HANDLE, HBA_WWN, HBA_WWN);
+typedef HBA_STATUS (* SMHBAGetLUNStatisticsFunc)
+ (HBA_HANDLE, const HBA_SCSIID *, SMHBA_PROTOCOLSTATISTICS *);
+typedef HBA_STATUS (* SMHBARegisterForAdapterAddEventsFunc)
+ (void (*)(void *, HBA_WWN, HBA_UINT32), void *, HBA_CALLBACKHANDLE *);
+typedef HBA_STATUS (* SMHBARegisterForAdapterEventsFunc)
+ (void (*)(void *, HBA_WWN, HBA_UINT32),
+ void *, HBA_HANDLE, HBA_CALLBACKHANDLE *);
+typedef HBA_STATUS (* SMHBARegisterForAdapterPortEventsFunc)
+ (void (*)(void *, HBA_WWN, HBA_UINT32, HBA_UINT32),
+ void *, HBA_HANDLE, HBA_WWN, HBA_UINT32, HBA_CALLBACKHANDLE *);
+typedef HBA_STATUS (* SMHBARegisterForAdapterPortStatEventsFunc)
+ (void (*)(void *, HBA_WWN, HBA_UINT32, HBA_UINT32),
+ void *, HBA_HANDLE, HBA_WWN, HBA_UINT32, SMHBA_PROTOCOLSTATISTICS,
+ HBA_UINT32, HBA_CALLBACKHANDLE *);
+typedef HBA_STATUS (* SMHBARegisterForAdapterPhyStatEventsFunc)
+ (void (*)(void *, HBA_WWN, HBA_UINT32, HBA_UINT32),
+ void *, HBA_HANDLE, HBA_WWN, HBA_UINT32, SMHBA_PHYSTATISTICS,
+ HBA_UINT32, HBA_CALLBACKHANDLE *);
+typedef HBA_STATUS (* SMHBARegisterForTargetEventsFunc)
+ (void (*)(void *, HBA_WWN, HBA_WWN, HBA_WWN, HBA_UINT32),
+ void *, HBA_HANDLE, HBA_WWN, HBA_WWN, HBA_WWN,
+ HBA_CALLBACKHANDLE *, HBA_UINT32);
+typedef HBA_STATUS (* SMHBAScsiInquiryFunc)
+ (HBA_HANDLE, HBA_WWN, HBA_WWN, HBA_WWN, SMHBA_SCSILUN, HBA_UINT8,
+ HBA_UINT8, void *, HBA_UINT32 *, HBA_UINT8 *, void *, HBA_UINT32 *);
+typedef HBA_STATUS (* SMHBAScsiReportLUNsFunc)
+ (HBA_HANDLE, HBA_WWN, HBA_WWN, HBA_WWN, void *, HBA_UINT32 *,
+ HBA_UINT8 *, void *, HBA_UINT32 *);
+typedef HBA_STATUS (* SMHBAScsiReadCapacityFunc)
+ (HBA_HANDLE, HBA_WWN, HBA_WWN, HBA_WWN, SMHBA_SCSILUN, void *,
+ HBA_UINT32 *, HBA_UINT8 *, void *, HBA_UINT32 *);
+
+/* SM-HBA-2 6.9.3 Entry Point Data Declarations */
+typedef struct SMHBA_EntryPoints {
+ SMHBAGetVersionFunc GetVersionHandler;
+ HBALoadLibraryFunc LoadLibraryHandler;
+ HBAFreeLibraryFunc FreeLibraryHandler;
+ HBAGetNumberOfAdaptersFunc GetNumberOfAdaptersHandler;
+ HBARefreshInformationFunc RefreshInformationHandler;
+ SMHBAGetVendorLibraryAttributesFunc
+ GetVendorLibraryAttributesHandler;
+ HBAGetAdapterNameFunc GetAdapterNameHandler;
+ HBAOpenAdapterFunc OpenAdapterHandler;
+ HBACloseAdapterFunc CloseAdapterHandler;
+ SMHBAGetAdapterAttributesFunc GetAdapterAttributesHandler;
+ SMHBAGetNumberOfPortsFunc GetNumberOfPortsHandler;
+ SMHBAGetPortTypeFunc GetPortTypeHandler;
+ SMHBAGetAdapterPortAttributesFunc
+ GetAdapterPortAttributesHandler;
+ SMHBAGetDiscoveredPortAttributesFunc
+ GetDiscoveredPortAttributesHandler;
+ SMHBAGetPortAttributesByWWNFunc GetPortAttributesByWWNHandler;
+ SMHBAGetFCPhyAttributesFunc GetFCPhyAttributesHandler;
+ SMHBAGetSASPhyAttributesFunc GetSASPhyAttributesHandler;
+ SMHBAGetProtocolStatisticsFunc GetProtocolStatisticsHandler;
+ SMHBAGetPhyStatisticsFunc GetPhyStatisticsHandler;
+ HBASendCTPassThruV2Func SendCTPassThruV2Handler;
+ HBASetRNIDMgmtInfoFunc SetRNIDMgmtInfoHandler;
+ HBAGetRNIDMgmtInfoFunc GetRNIDMgmtInfoHandler;
+ HBASendRNIDV2Func SendRNIDV2Handler;
+ HBASendRPLFunc SendRPLHandler;
+ HBASendRPSFunc SendRPSHandler;
+ HBASendSRLFunc SendSRLHandler;
+ HBASendLIRRFunc SendLIRRHandler;
+ HBASendRLSFunc SendRLSHandler;
+ SMHBASendTESTFunc SendTESTHandler;
+ SMHBASendECHOFunc SendECHOHandler;
+ SMHBASendSMPPassThruFunc SendSMPPassThruHandler;
+ SMHBAGetBindingCapabilityFunc GetBindingCapabilityHandler;
+ SMHBAGetBindingSupportFunc GetBindingSupportHandler;
+ SMHBASetBindingSupportFunc SetBindingSupportHandler;
+ SMHBAGetTargetMappingFunc GetTargetMappingHandler;
+ SMHBAGetPersistentBindingFunc GetPersistentBindingHandler;
+ SMHBASetPersistentBindingFunc SetPersistentBindingHandler;
+ SMHBARemovePersistentBindingFunc RemovePersistentBindingHandler;
+ SMHBARemoveAllPersistentBindingsFunc
+ RemoveAllPersistentBindingsHandler;
+ SMHBAGetLUNStatisticsFunc GetLUNStatisticsHandler;
+ SMHBAScsiInquiryFunc ScsiInquiryHandler;
+ SMHBAScsiReportLUNsFunc ScsiReportLUNsHandler;
+ SMHBAScsiReadCapacityFunc ScsiReadCapacityHandler;
+ SMHBARegisterForAdapterAddEventsFunc
+ RegisterForAdapterAddEventsHandler;
+ SMHBARegisterForAdapterEventsFunc RegisterForAdapterEventsHandler;
+ SMHBARegisterForAdapterPortEventsFunc
+ RegisterForAdapterPortEventsHandler;
+ SMHBARegisterForAdapterPortStatEventsFunc
+ RegisterForAdapterPortStatEventsHandler;
+ SMHBARegisterForAdapterPhyStatEventsFunc
+ RegisterForAdapterPhyStatEventsHandler;
+ SMHBARegisterForTargetEventsFunc RegisterForTargetEventsHandler;
+ HBARegisterForLinkEventsFunc RegisterForLinkEventsHandler;
+ HBARemoveCallbackFunc RemoveCallbackHandler;
+} SMHBA_ENTRYPOINTS, *PSMHBA_ENTRYPOINTS;
+
+typedef HBA_UINT32 (* SMHBARegisterLibraryFunc)(SMHBA_ENTRYPOINTS *);
+
+HBA_STATUS SMHBA_RegisterLibrary(
+ SMHBA_ENTRYPOINTS *functionTable
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VENDORSMHBAAPI_H_ */
diff --git a/usr/src/lib/smhba/i386/Makefile b/usr/src/lib/smhba/i386/Makefile
new file mode 100644
index 0000000000..075f16dfdc
--- /dev/null
+++ b/usr/src/lib/smhba/i386/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 2009 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/smhba/sparc/Makefile b/usr/src/lib/smhba/sparc/Makefile
new file mode 100644
index 0000000000..075f16dfdc
--- /dev/null
+++ b/usr/src/lib/smhba/sparc/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 2009 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/smhba/sparcv9/Makefile b/usr/src/lib/smhba/sparcv9/Makefile
new file mode 100644
index 0000000000..dfeeb9953a
--- /dev/null
+++ b/usr/src/lib/smhba/sparcv9/Makefile
@@ -0,0 +1,30 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT)
diff --git a/usr/src/lib/sun_sas/Makefile b/usr/src/lib/sun_sas/Makefile
new file mode 100644
index 0000000000..073fe728d5
--- /dev/null
+++ b/usr/src/lib/sun_sas/Makefile
@@ -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 2009 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
+install_h := TARGET= install_h
+lint := TARGET= lint
+
+HDRDIR= common
+
+
+.KEEP_STATE:
+
+all clean clobber install lint: $(SUBDIRS)
+
+install_h: $(ROOTHDRS)
+
+check: $(CHECKHDRS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+include ../Makefile.targ
diff --git a/usr/src/lib/sun_sas/Makefile.com b/usr/src/lib/sun_sas/Makefile.com
new file mode 100644
index 0000000000..d3ddf2f450
--- /dev/null
+++ b/usr/src/lib/sun_sas/Makefile.com
@@ -0,0 +1,99 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#
+
+LIBRARY = libsun_sas.a
+VERS = .1
+
+OBJECTS = devtree_hba_disco.o \
+ devtree_device_disco.o \
+ devtree_phy_disco.o \
+ devlink_disco.o \
+ event.o \
+ verify.o \
+ SMHBA_RegisterLibrary.o \
+ Sun_sasLoadLibrary.o \
+ Sun_sasGetNumberOfAdapters.o \
+ Sun_sasGetTargetMapping.o \
+ Sun_sasGetAdapterName.o \
+ Sun_sasGetAdapterAttributes.o \
+ Sun_sasGetAdapterPortAttributes.o \
+ Sun_sasGetDiscoveredPortAttributes.o \
+ Sun_sasGetPortAttributesByWWN.o \
+ Sun_sasGetSASPhyAttributes.o \
+ Sun_sasGetPortType.o \
+ Sun_sasGetNumberOfPorts.o \
+ Sun_sasGetVersion.o \
+ Sun_sasGetPhyStatistics.o \
+ Sun_sasGetVendorLibraryAttributes.o \
+ Sun_sasFreeLibrary.o \
+ Sun_sasOpenAdapter.o \
+ Sun_sasCloseAdapter.o \
+ Sun_sasRefreshInformation.o \
+ Sun_sasRefreshAdapterConfiguration.o \
+ Sun_sasGetLUNStatistics.o \
+ Sun_sasGetProtocolStatistics.o \
+ Sun_sasGetPersistentBinding.o \
+ Sun_sasSetPersistentBinding.o \
+ Sun_sasSendSMPPassThru.o \
+ Sun_sasScsiInquiry.o \
+ Sun_sasScsiReportLUNs.o \
+ Sun_sasScsiReadCapacity.o \
+ sun_sas.o \
+ log.o
+
+include ../../Makefile.lib
+
+LIBS = $(DYNLIB)
+SRCDIR= ../common
+
+INCS += -I$(SRCDIR)
+INCS += -I$(SRC)/lib/smhba/common
+INCS += -I$(SRC)/lib/hbaapi/common
+INCS += -I$(SRC)/lib/libdevid
+
+CFLAGS += -mt
+CFLAGS += -v
+CFLAGS64 += -mt
+CFLAGS64 += -v
+CPPFLAGS += $(INCS) -D_POSIX_PTHREAD_SEMANTICS
+CPPFLAGS += -DBUILD_TIME='"Wed Feb 4 12:00:00 2009"'
+
+LDLIBS += -ldevinfo
+LDLIBS += -lsysevent
+LDLIBS += -lnvpair
+LDLIBS += -lc
+LDLIBS += -lkstat
+LDLIBS += -ldevid
+
+$(LINTLIB) := SRCS= $(SRCDIR)/$(LINTSRC)
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+lint: lintcheck
+
+include ../../Makefile.targ
diff --git a/usr/src/lib/sun_sas/amd64/Makefile b/usr/src/lib/sun_sas/amd64/Makefile
new file mode 100644
index 0000000000..5180f1b702
--- /dev/null
+++ b/usr/src/lib/sun_sas/amd64/Makefile
@@ -0,0 +1,34 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)
diff --git a/usr/src/lib/sun_sas/common/SMHBA_RegisterLibrary.c b/usr/src/lib/sun_sas/common/SMHBA_RegisterLibrary.c
new file mode 100644
index 0000000000..eb71a418f7
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/SMHBA_RegisterLibrary.c
@@ -0,0 +1,100 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sun_sas.h>
+
+HBA_STATUS
+SMHBA_RegisterLibrary(PSMHBA_ENTRYPOINTS entrypoints)
+{
+ entrypoints->GetVersionHandler = Sun_sasGetVersion;
+ entrypoints->LoadLibraryHandler = Sun_sasLoadLibrary;
+ entrypoints->FreeLibraryHandler = Sun_sasFreeLibrary;
+ entrypoints->GetNumberOfAdaptersHandler = Sun_sasGetNumberOfAdapters;
+ entrypoints->RefreshInformationHandler = Sun_sasRefreshInformation;
+ entrypoints->GetVendorLibraryAttributesHandler =
+ Sun_sasGetVendorLibraryAttributes;
+ entrypoints->GetAdapterNameHandler = Sun_sasGetAdapterName;
+ entrypoints->OpenAdapterHandler = Sun_sasOpenAdapter;
+ entrypoints->CloseAdapterHandler = Sun_sasCloseAdapter;
+ entrypoints->GetAdapterAttributesHandler = Sun_sasGetAdapterAttributes;
+ entrypoints->GetNumberOfPortsHandler = Sun_sasGetNumberOfPorts;
+ entrypoints->GetPortTypeHandler = Sun_sasGetPortType;
+ entrypoints->GetAdapterPortAttributesHandler =
+ Sun_sasGetAdapterPortAttributes;
+ entrypoints->GetDiscoveredPortAttributesHandler =
+ Sun_sasGetDiscoveredPortAttributes;
+ entrypoints->GetPortAttributesByWWNHandler =
+ Sun_sasGetPortAttributesByWWN;
+ entrypoints->GetFCPhyAttributesHandler = NULL;
+ entrypoints->GetSASPhyAttributesHandler = Sun_sasGetSASPhyAttributes;
+ entrypoints->GetProtocolStatisticsHandler =
+ Sun_sasGetProtocolStatistics;
+ entrypoints->GetPhyStatisticsHandler = Sun_sasGetPhyStatistics;
+ entrypoints->SendCTPassThruV2Handler = NULL;
+ entrypoints->SetRNIDMgmtInfoHandler = NULL;
+ entrypoints->GetRNIDMgmtInfoHandler = NULL;
+ entrypoints->SendRNIDV2Handler = NULL;
+ entrypoints->SendRPLHandler = NULL;
+ entrypoints->SendRPSHandler = NULL;
+ entrypoints->SendSRLHandler = NULL;
+ entrypoints->SendLIRRHandler = NULL;
+ entrypoints->SendRLSHandler = NULL;
+ entrypoints->SendTESTHandler = NULL;
+ entrypoints->SendECHOHandler = NULL;
+ entrypoints->SendSMPPassThruHandler = Sun_sasSendSMPPassThru;
+ entrypoints->GetBindingCapabilityHandler = NULL;
+ /* Sun_sasGetBindingCapability; */
+ entrypoints->GetBindingSupportHandler = NULL;
+ entrypoints->SetBindingSupportHandler = NULL;
+ /* Sun_sasSetBindingSupport; */
+ entrypoints->GetTargetMappingHandler = Sun_sasGetTargetMapping;
+ entrypoints->SetPersistentBindingHandler = Sun_sasSetPersistentBinding;
+ entrypoints->GetPersistentBindingHandler = Sun_sasGetPersistentBinding;
+ entrypoints->RemovePersistentBindingHandler = NULL;
+ /* Sun_sasRemovePersistentBinding; */
+ entrypoints->RemoveAllPersistentBindingsHandler = NULL;
+ /* Sun_sasRemoveAllPersistentBindings; */
+ entrypoints->GetLUNStatisticsHandler = Sun_sasGetLUNStatistics;
+ entrypoints->ScsiInquiryHandler = Sun_sasScsiInquiry;
+ entrypoints->ScsiReportLUNsHandler = Sun_sasScsiReportLUNs;
+ entrypoints->ScsiReadCapacityHandler = Sun_sasScsiReadCapacity;
+ entrypoints->RegisterForAdapterAddEventsHandler = NULL;
+ /* Sun_sasRegisterForAdapterAddEvents; */
+ entrypoints->RegisterForAdapterEventsHandler = NULL;
+ /* Sun_sasRegisterForAdapterEvents; */
+ entrypoints->RegisterForAdapterPortEventsHandler = NULL;
+ /* Sun_sasRegisterForAdapterPortEvents; */
+ entrypoints->RegisterForAdapterPortStatEventsHandler = NULL;
+ /* Sun_sasRegisterForAdapterPortStatEvents; */
+ entrypoints->RegisterForAdapterPhyStatEventsHandler = NULL;
+ /* Sun_sasRegisterForAdapterPhyStatEvents; */
+ entrypoints->RegisterForTargetEventsHandler = NULL;
+ /* Sun_sasRegisterForTargetEvents; */
+ entrypoints->RegisterForLinkEventsHandler = NULL;
+ /* Sun_sasRegisterForLinkEvents; */
+ entrypoints->RemoveCallbackHandler = NULL; /* Sun_sasRemoveCallback; */
+ return (HBA_STATUS_OK);
+}
diff --git a/usr/src/lib/sun_sas/common/Sun_sasCloseAdapter.c b/usr/src/lib/sun_sas/common/Sun_sasCloseAdapter.c
new file mode 100644
index 0000000000..d6dc259be6
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/Sun_sasCloseAdapter.c
@@ -0,0 +1,99 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sun_sas.h>
+
+/*
+ * Closes an adapter
+ *
+ * the handle is removed from the open_handles list
+ */
+void
+Sun_sasCloseAdapter(HBA_HANDLE handle)
+{
+ const char ROUTINE[] = "Sun_sasCloseAdapter";
+ struct open_handle *open_handle_ptr, *open_handle_prev_ptr;
+ int found = 0;
+
+ if (global_hba_head == NULL) {
+ log(LOG_DEBUG, ROUTINE,
+ "Attempted to close an invalid handle %08lx. "
+ "There are no hba handles loaded in the VSL.",
+ handle);
+ return;
+ }
+
+ /* Removing handle from open_handles; */
+ lock(&open_handles_lock);
+ if (global_hba_head->open_handles == NULL) {
+ /* check to see if there are any open global_hba_head */
+ log(LOG_DEBUG, ROUTINE,
+ "Attempted to close an invalid handle %08lx. "
+ "There are no open handles in the VSL.",
+ handle);
+ } else if (global_hba_head->open_handles->next == NULL) {
+ /* there is only one handle open */
+ if (global_hba_head->open_handles->handle == handle) {
+ free(global_hba_head->open_handles);
+ global_hba_head->open_handles = NULL;
+ } else {
+ log(LOG_DEBUG, ROUTINE,
+ "Attempted to close an invalid handle %08lx. "
+ "Unable to find handle to close.", handle);
+ }
+ } else { /* there is more than one handle open */
+ open_handle_ptr = global_hba_head->open_handles;
+ if (open_handle_ptr->handle == handle) {
+ global_hba_head->open_handles = open_handle_ptr->next;
+ free(open_handle_ptr);
+ } else {
+ for (open_handle_ptr = open_handle_ptr->next,
+ open_handle_prev_ptr =
+ global_hba_head->open_handles;
+ open_handle_ptr != NULL;
+ open_handle_ptr = open_handle_ptr->next) {
+ if (open_handle_ptr->handle == handle) {
+ open_handle_prev_ptr->next =
+ open_handle_ptr->next;
+ free(open_handle_ptr);
+ found = 1;
+ break;
+ } else {
+ open_handle_prev_ptr =
+ open_handle_prev_ptr->next;
+ }
+ }
+ if (found == 0) {
+ log(LOG_DEBUG, ROUTINE,
+ "Attempted to close an invalid handle "
+ "%08lx. Unable to find handle to close.",
+ handle);
+ }
+ }
+ }
+
+ unlock(&open_handles_lock);
+}
diff --git a/usr/src/lib/sun_sas/common/Sun_sasFreeLibrary.c b/usr/src/lib/sun_sas/common/Sun_sasFreeLibrary.c
new file mode 100644
index 0000000000..caffe52de1
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/Sun_sasFreeLibrary.c
@@ -0,0 +1,131 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+
+#include <sun_sas.h>
+
+/*
+ * Frees the HBA Library. Must be called after all HBA library functions
+ * to free all resources
+ */
+HBA_STATUS Sun_sasFreeLibrary() {
+ HBA_STATUS status;
+
+ lock(&all_hbas_lock);
+
+ status = FreeHBA(global_hba_head);
+
+ /* re-initialize all global variables */
+ global_hba_head = NULL;
+ hba_count = 0;
+ open_handle_index = 1;
+ unlock(&all_hbas_lock);
+ (void) mutex_destroy(&all_hbas_lock);
+
+ /* free sysevent handle. */
+ if (gSysEventHandle != NULL)
+ sysevent_unbind_handle(gSysEventHandle);
+
+ /* Reset our load count so we can be reloaded now */
+ loadCount = 0;
+
+ return (status);
+}
+
+/*
+ * Internal routine to free up hba_ptr's (and all sub-structures)
+ */
+HBA_STATUS FreeHBA(struct sun_sas_hba *hba) {
+ struct sun_sas_hba *hba_ptr = NULL;
+ struct sun_sas_hba *last_hba_ptr = NULL;
+ struct sun_sas_port *hba_port = NULL;
+ struct sun_sas_port *last_hba_port = NULL;
+ struct sun_sas_port *tgt_port = NULL;
+ struct sun_sas_port *last_tgt_port = NULL;
+ struct ScsiEntryList *scsi_info = NULL;
+ struct ScsiEntryList *last_scsi_info = NULL;
+ struct phy_info *phy_ptr = NULL;
+ struct phy_info *last_phy = NULL;
+ struct open_handle *open_handle = NULL;
+ struct open_handle *last_open_handle = NULL;
+
+ last_hba_ptr = NULL;
+ /* walk through global_hba_head list freeing each handle */
+ for (hba_ptr = hba;
+ hba_ptr != NULL;
+ hba_ptr = hba_ptr->next) {
+ /* Free the nested structures (port and attached port) */
+ hba_port = hba_ptr->first_port;
+ while (hba_port != NULL) {
+ /* Free discovered port structure list. */
+ tgt_port = hba_port->first_attached_port;
+ while (tgt_port != NULL) {
+ /* Free target mapping data list first. */
+ scsi_info = tgt_port->scsiInfo;
+ while (scsi_info != NULL) {
+ last_scsi_info = scsi_info;
+ scsi_info = scsi_info->next;
+ free(last_scsi_info);
+ }
+ last_tgt_port = tgt_port;
+ tgt_port = tgt_port->next;
+ free(last_tgt_port->port_attributes.\
+ PortSpecificAttribute.SASPort);
+ free(last_tgt_port);
+ }
+
+ phy_ptr = hba_port->first_phy;
+ while (phy_ptr != NULL) {
+ last_phy = phy_ptr;
+ phy_ptr = phy_ptr->next;
+ free(last_phy);
+ }
+
+ last_hba_port = hba_port;
+ hba_port = hba_port->next;
+ free(last_hba_port->port_attributes.\
+ PortSpecificAttribute.SASPort);
+ free(last_hba_port);
+ }
+
+ open_handle = hba_ptr->open_handles;
+ while (open_handle != NULL) {
+ last_open_handle = open_handle;
+ open_handle = open_handle->next;
+ free(last_open_handle);
+ }
+ /* Free up the top level HBA structure from the last spin */
+ if (last_hba_ptr != NULL) {
+ free(last_hba_ptr);
+ }
+ last_hba_ptr = hba_ptr;
+ }
+ if (last_hba_ptr != NULL) {
+ free(last_hba_ptr);
+ }
+
+ return (HBA_STATUS_OK);
+}
diff --git a/usr/src/lib/sun_sas/common/Sun_sasGetAdapterAttributes.c b/usr/src/lib/sun_sas/common/Sun_sasGetAdapterAttributes.c
new file mode 100644
index 0000000000..d5e5e55ec1
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/Sun_sasGetAdapterAttributes.c
@@ -0,0 +1,62 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sun_sas.h>
+/*
+ * Retrieves the attribues for an adapter
+ */
+HBA_STATUS
+Sun_sasGetAdapterAttributes(HBA_HANDLE handle,
+ PSMHBA_ADAPTERATTRIBUTES attributes) {
+ const char ROUTINE[] = "Sun_sasGetAdapterAttributes";
+ struct sun_sas_hba *hba_ptr;
+ int index = 0;
+
+ if (attributes == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL attributes pointer");
+ return (HBA_STATUS_ERROR_ARG);
+ }
+
+ lock(&all_hbas_lock);
+ index = RetrieveIndex(handle);
+ lock(&open_handles_lock);
+ hba_ptr = RetrieveHandle(index);
+ if (hba_ptr == NULL) {
+ log(LOG_DEBUG, ROUTINE,
+ "Invalid handle %08lx", handle);
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_INVALID_HANDLE);
+ }
+
+ (void) memcpy(attributes, &hba_ptr->adapter_attributes,
+ sizeof (SMHBA_ADAPTERATTRIBUTES));
+
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+
+ return (HBA_STATUS_OK);
+}
diff --git a/usr/src/lib/sun_sas/common/Sun_sasGetAdapterName.c b/usr/src/lib/sun_sas/common/Sun_sasGetAdapterName.c
new file mode 100644
index 0000000000..bf945aedb9
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/Sun_sasGetAdapterName.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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include "sun_sas.h"
+
+/*
+ * Returns the text string which describes this adapter and which is used to
+ * open the adapter with the library.
+ *
+ * Arguments:
+ * index the index to which adapter to retrive the name
+ * name buffer to which the adapter name will be placed
+ */
+HBA_STATUS Sun_sasGetAdapterName(HBA_UINT32 index, char *name) {
+ const char ROUTINE[] = "Sun_sasGetAdapterName";
+ struct sun_sas_hba *hba_ptr;
+
+ if (name == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL adapter name");
+ return (HBA_STATUS_ERROR_ARG);
+ }
+ lock(&all_hbas_lock);
+ for (hba_ptr = global_hba_head; hba_ptr != NULL;
+ hba_ptr = hba_ptr->next) {
+ if (hba_ptr->index == index) {
+ if (hba_ptr->handle_name == NULL) {
+ hba_ptr = NULL;
+ break;
+ }
+ /* Flaw in the spec! How do we know the size of name? */
+ (void) strlcpy(name, hba_ptr->handle_name,
+ strlen(hba_ptr->handle_name)+1);
+ break;
+ }
+ }
+ unlock(&all_hbas_lock);
+ if (hba_ptr == NULL) {
+ log(LOG_DEBUG, ROUTINE,
+ "Unable to find adapter index %d.", index);
+ return (HBA_STATUS_ERROR_ILLEGAL_INDEX);
+ }
+
+ return (HBA_STATUS_OK);
+}
diff --git a/usr/src/lib/sun_sas/common/Sun_sasGetAdapterPortAttributes.c b/usr/src/lib/sun_sas/common/Sun_sasGetAdapterPortAttributes.c
new file mode 100644
index 0000000000..cd60698a72
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/Sun_sasGetAdapterPortAttributes.c
@@ -0,0 +1,111 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sun_sas.h>
+
+/*
+ * Retrieves the attributes for a specified port of an adapter
+ */
+HBA_STATUS
+Sun_sasGetAdapterPortAttributes(HBA_HANDLE handle,
+ HBA_UINT32 port, PSMHBA_PORTATTRIBUTES attributes) {
+ const char ROUTINE[] = "Sun_sasGetAdapterPortAttributes";
+ HBA_STATUS status;
+ struct sun_sas_hba *hba_ptr;
+ struct sun_sas_port *hba_port_ptr;
+ int index;
+
+ /* Validate the arguments */
+ if ((attributes == NULL) ||
+ (attributes->PortSpecificAttribute.SASPort == NULL)) {
+ log(LOG_DEBUG, ROUTINE, "NULL attributes");
+ return (HBA_STATUS_ERROR_ARG);
+ }
+
+ lock(&all_hbas_lock);
+ index = RetrieveIndex(handle);
+ lock(&open_handles_lock);
+ hba_ptr = RetrieveHandle(index);
+ if (hba_ptr == NULL) {
+ log(LOG_DEBUG, ROUTINE, "Invalid handle %08lx", handle);
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_INVALID_HANDLE);
+ }
+
+ /* Check for stale data */
+ status = verifyAdapter(hba_ptr);
+ if (status != HBA_STATUS_OK) {
+ log(LOG_DEBUG, ROUTINE, "Verify Adapter failed");
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (status);
+ }
+
+ if (hba_ptr->first_port == NULL) {
+ /* This is probably an internal failure of the library */
+ if (hba_ptr->device_path) {
+ log(LOG_DEBUG, ROUTINE,
+ "Internal failure: Adapter %s contains no port data",
+ hba_ptr->device_path);
+ } else {
+ log(LOG_DEBUG, ROUTINE,
+ "Internal failure: Adapter at index %d contains no port "
+ "data", hba_ptr->index);
+ }
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR);
+ }
+ for (hba_port_ptr = hba_ptr->first_port;
+ hba_port_ptr != NULL; hba_port_ptr = hba_port_ptr->next) {
+ if (hba_port_ptr->index == port) {
+ break;
+ }
+ }
+ if (hba_port_ptr == NULL || hba_port_ptr->index != port) {
+ log(LOG_DEBUG, ROUTINE,
+ "Invalid port index %d for handle %08lx.",
+ port, handle);
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_ILLEGAL_INDEX);
+ }
+
+ attributes->PortType = hba_port_ptr->port_attributes.PortType;
+ attributes->PortState = hba_port_ptr->port_attributes.PortState;
+ (void) strlcpy(attributes->OSDeviceName,
+ hba_port_ptr->port_attributes.OSDeviceName,
+ sizeof (attributes->OSDeviceName));
+ (void) memcpy(attributes->PortSpecificAttribute.SASPort,
+ hba_port_ptr->port_attributes.PortSpecificAttribute.SASPort,
+ sizeof (struct SMHBA_SAS_Port));
+
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+
+ return (HBA_STATUS_OK);
+}
diff --git a/usr/src/lib/sun_sas/common/Sun_sasGetDiscoveredPortAttributes.c b/usr/src/lib/sun_sas/common/Sun_sasGetDiscoveredPortAttributes.c
new file mode 100644
index 0000000000..10de1cbcff
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/Sun_sasGetDiscoveredPortAttributes.c
@@ -0,0 +1,143 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sun_sas.h>
+
+/*
+ * Retrieves the attributes for a specified port discovered in the network
+ */
+HBA_STATUS
+Sun_sasGetDiscoveredPortAttributes(HBA_HANDLE handle,
+ HBA_UINT32 port, HBA_UINT32 discoveredport,
+ SMHBA_PORTATTRIBUTES *attributes) {
+ const char ROUTINE[] =
+ "Sun_sasGetDiscoveredPortAttributes";
+ HBA_STATUS status;
+ HBA_STATUS ret = HBA_STATUS_OK;
+ struct sun_sas_hba *hba_ptr;
+ struct sun_sas_port *hba_port_ptr, *hba_disco_port;
+ int index;
+
+ if (attributes == NULL) {
+ log(LOG_DEBUG, ROUTINE,
+ "NULL attributes argument. Handle %08lx, port %d, "
+ "discovered port %d", handle, port, discoveredport);
+ return (HBA_STATUS_ERROR_ARG);
+ }
+
+ lock(&all_hbas_lock);
+ index = RetrieveIndex(handle);
+ lock(&open_handles_lock);
+ hba_ptr = RetrieveHandle(index);
+ if (hba_ptr == NULL) {
+ log(LOG_DEBUG, ROUTINE,
+ "Invalid handle %08lx.", handle);
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_INVALID_HANDLE);
+ }
+
+ /* Check for stale data */
+ status = verifyAdapter(hba_ptr);
+ if (status != HBA_STATUS_OK) {
+ log(LOG_DEBUG, ROUTINE, "Verify Adapter failed");
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (status);
+ }
+
+
+ if (hba_ptr->first_port == NULL) {
+ /* This is probably an internal failure of the library */
+ if (hba_ptr->device_path) {
+ log(LOG_DEBUG, ROUTINE,
+ "Internal failure: Adapter %s contains no port data",
+ hba_ptr->device_path);
+ } else {
+ log(LOG_DEBUG, ROUTINE,
+ "Internal failure: Adapter at index %d contains no port "
+ "data", hba_ptr->index);
+ }
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR);
+ }
+
+ for (hba_port_ptr = hba_ptr->first_port;
+ hba_port_ptr != NULL; hba_port_ptr = hba_port_ptr->next) {
+ if (hba_port_ptr->index == port) {
+ break;
+ }
+ }
+
+ if (hba_port_ptr == NULL) {
+ log(LOG_DEBUG, ROUTINE,
+ "Invalid port index %d for handle %08lx",
+ port, handle);
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_ILLEGAL_INDEX);
+ }
+
+ /* check to make sure there are devices attached to this port */
+ if (hba_port_ptr->first_attached_port != NULL) {
+ for (hba_disco_port = hba_port_ptr->first_attached_port;
+ hba_disco_port != NULL;
+ hba_disco_port = hba_disco_port->next) {
+ if (hba_disco_port->index == discoveredport) {
+ break;
+ }
+ }
+ if (hba_disco_port == NULL) {
+ log(LOG_DEBUG, ROUTINE,
+ "Invalid discovered port index %d for hba port "
+ "index %d on handle %08lx.",
+ discoveredport, port, handle);
+ ret = HBA_STATUS_ERROR_ILLEGAL_INDEX;
+ } else {
+ attributes->PortType =
+ hba_disco_port->port_attributes.PortType;
+ attributes->PortState =
+ hba_disco_port->port_attributes.PortState;
+ (void) strlcpy(attributes->OSDeviceName,
+ hba_disco_port->port_attributes.OSDeviceName,
+ sizeof (attributes->OSDeviceName));
+ (void) memcpy(attributes->PortSpecificAttribute.SASPort,
+ hba_disco_port->port_attributes.PortSpecificAttribute.
+ SASPort, sizeof (struct SMHBA_SAS_Port));
+ }
+ } else {
+ /* No ports, so we can't possibly return anything */
+ log(LOG_DEBUG, ROUTINE,
+ "No discovered port on HBA port index %d for handle %08lx",
+ port, handle);
+ ret = HBA_STATUS_ERROR;
+ }
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+
+ return (ret);
+}
diff --git a/usr/src/lib/sun_sas/common/Sun_sasGetLUNStatistics.c b/usr/src/lib/sun_sas/common/Sun_sasGetLUNStatistics.c
new file mode 100644
index 0000000000..7c6cda031a
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/Sun_sasGetLUNStatistics.c
@@ -0,0 +1,38 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include "sun_sas.h"
+
+/*
+ * Not Supported
+ */
+/*ARGSUSED*/
+HBA_STATUS Sun_sasGetLUNStatistics(
+ HBA_HANDLE handle,
+ const HBA_SCSIID *lunit,
+ SMHBA_PROTOCOLSTATISTICS *pstatistics) {
+ return (HBA_STATUS_ERROR_NOT_SUPPORTED);
+}
diff --git a/usr/src/lib/sun_sas/common/Sun_sasGetNumberOfAdapters.c b/usr/src/lib/sun_sas/common/Sun_sasGetNumberOfAdapters.c
new file mode 100644
index 0000000000..71bf0fc315
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/Sun_sasGetNumberOfAdapters.c
@@ -0,0 +1,46 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sun_sas.h>
+
+/*
+ * Returns the number of HBAs supported by the library. This returns the
+ * current number of HBAs, even if this changes
+ *
+ */
+HBA_UINT32 Sun_sasGetNumberOfAdapters() {
+ int count;
+ struct sun_sas_hba *hba_ptr;
+
+ lock(&all_hbas_lock);
+ /* goes through hba list counting all the hbas found */
+ for (count = 0, hba_ptr = global_hba_head;
+ hba_ptr != NULL; hba_ptr = hba_ptr->next, count++) {}
+
+ unlock(&all_hbas_lock);
+
+ return (count);
+}
diff --git a/usr/src/lib/sun_sas/common/Sun_sasGetNumberOfPorts.c b/usr/src/lib/sun_sas/common/Sun_sasGetNumberOfPorts.c
new file mode 100644
index 0000000000..ff35c7c21a
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/Sun_sasGetNumberOfPorts.c
@@ -0,0 +1,79 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sun_sas.h>
+
+/*
+ * Returns the number of HBAs supported by the library. This returns the
+ * current number of HBAs, even if this changes
+ *
+ */
+HBA_UINT32 Sun_sasGetNumberOfPorts(
+ HBA_HANDLE handle, HBA_UINT32 *numberofports)
+{
+ const char ROUTINE[] = "Sun_sasGetNumberOfPorts";
+ int count, index;
+ struct sun_sas_hba *hba_ptr;
+ struct sun_sas_port *hba_port_ptr;
+
+ if (numberofports == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL numberofPorts pointer");
+ return (HBA_STATUS_ERROR_ARG);
+ }
+
+ lock(&all_hbas_lock);
+ index = RetrieveIndex(handle);
+ lock(&open_handles_lock);
+ hba_ptr = RetrieveHandle(index);
+ if (hba_ptr == NULL) {
+ log(LOG_DEBUG, ROUTINE, "Invalid handle %08lx.", handle);
+ /* on error, need to set NumberOfEntries to 0 */
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_INVALID_HANDLE);
+ }
+ /* goes through hba list counting all the hbas found */
+ if (hba_ptr->first_port == NULL) {
+ log(LOG_DEBUG, ROUTINE, "No HBA Port found on handle %08lx.",
+ handle);
+ /* on error, need to set NumberOfPorts to 0 */
+ *numberofports = 0;
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_OK);
+ }
+
+ for (count = 0, hba_port_ptr = hba_ptr->first_port;
+ hba_port_ptr != NULL; hba_port_ptr = hba_port_ptr->next, count++) {}
+
+ *numberofports = count;
+
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+
+ return (HBA_STATUS_OK);
+
+}
diff --git a/usr/src/lib/sun_sas/common/Sun_sasGetPersistentBinding.c b/usr/src/lib/sun_sas/common/Sun_sasGetPersistentBinding.c
new file mode 100644
index 0000000000..7fedb970e2
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/Sun_sasGetPersistentBinding.c
@@ -0,0 +1,36 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include "sun_sas.h"
+
+/*
+ * Not Supported
+ */
+/*ARGSUSED*/
+HBA_STATUS Sun_sasGetPersistentBinding(HBA_HANDLE hande, HBA_WWN hbPortWWN,
+ HBA_WWN domainPortWWN, SMHBA_BINDING *binding) {
+ return (HBA_STATUS_ERROR_NOT_SUPPORTED);
+}
diff --git a/usr/src/lib/sun_sas/common/Sun_sasGetPhyStatistics.c b/usr/src/lib/sun_sas/common/Sun_sasGetPhyStatistics.c
new file mode 100644
index 0000000000..10f73604cf
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/Sun_sasGetPhyStatistics.c
@@ -0,0 +1,258 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <kstat.h>
+#include <sun_sas.h>
+
+/*
+ * Retrieves the statistics for a specified port.phy on an adapter
+ */
+HBA_STATUS Sun_sasGetPhyStatistics(HBA_HANDLE handle,
+ HBA_UINT32 port, HBA_UINT32 phy, SMHBA_PHYSTATISTICS *pStatistics) {
+ const char ROUTINE[] = "Sun_sasGetPhyStatistics";
+ HBA_STATUS status = HBA_STATUS_OK;
+ struct sun_sas_hba *hba_ptr;
+ struct sun_sas_port *hba_port_ptr;
+ struct phy_info *phy_ptr;
+ PSMHBA_SASPHYSTATISTICS psas;
+ kstat_ctl_t *kc;
+ kstat_t *ksp;
+ kstat_named_t *kname;
+ char *charptr, path[MAXPATHLEN + 1];
+ char *driver_name, kstat_name[256];
+ di_node_t node;
+ int instance = 0;
+ int i;
+ uint64_t iport_wwn;
+
+ /* Validate the arguments */
+ if (pStatistics == NULL) {
+ log(LOG_DEBUG, ROUTINE,
+ "NULL Phy Statistics buffer of phyIndex: %08lx", phy);
+ return (HBA_STATUS_ERROR_ARG);
+ }
+ psas = pStatistics->SASPhyStatistics;
+ if (psas == NULL) {
+ log(LOG_DEBUG, ROUTINE,
+ "NULL SAS Phy Statistics buffer of phyIndex: %08lx", phy);
+ return (HBA_STATUS_ERROR_ARG);
+ }
+
+ lock(&all_hbas_lock);
+
+ if ((hba_ptr = Retrieve_Sun_sasHandle(handle)) == NULL) {
+ log(LOG_DEBUG, ROUTINE,
+ "Invalid HBA handler %08lx of phyIndex: %08lx",
+ handle, phy);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_INVALID_HANDLE);
+ }
+
+ /* Check for stale data */
+ status = verifyAdapter(hba_ptr);
+ if (status != HBA_STATUS_OK) {
+ log(LOG_DEBUG, ROUTINE,
+ "Verify Adapter failed for phyIndex: %08lx", phy);
+ unlock(&all_hbas_lock);
+ return (status);
+ }
+
+ for (hba_port_ptr = hba_ptr->first_port;
+ hba_port_ptr != NULL;
+ hba_port_ptr = hba_port_ptr->next) {
+ if (hba_port_ptr->index == port) {
+ break;
+ }
+ }
+
+ if (hba_port_ptr == NULL) {
+ log(LOG_DEBUG, ROUTINE,
+ "Invalid port index of phyIndex: %08lx", phy);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_ILLEGAL_INDEX);
+ }
+
+ if (phy >= hba_port_ptr->port_attributes.PortSpecificAttribute.
+ SASPort->NumberofPhys) {
+ log(LOG_DEBUG, ROUTINE, "Invalid phy index %08lx", phy);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_ILLEGAL_INDEX);
+ }
+
+ /* We need to find out the phy identifier. */
+ for (phy_ptr = hba_port_ptr->first_phy;
+ phy_ptr != NULL;
+ phy_ptr = phy_ptr->next) {
+ if (phy == phy_ptr->index)
+ break;
+ }
+
+ if (phy_ptr == NULL) {
+ log(LOG_DEBUG, ROUTINE, "Invalid phy index %08lx", phy);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_ILLEGAL_INDEX);
+ }
+
+ /*
+ * for statistics that are not supported, its bits should all be
+ * set to -1
+ */
+ (void) memset(pStatistics->SASPhyStatistics, 0xff,
+ sizeof (SMHBA_SASPHYSTATISTICS));
+
+
+ /* First, we need the deivce path to locate the devinfo node. */
+ (void *) strlcpy(path, hba_port_ptr->device_path,
+ sizeof (path));
+ charptr = strrchr(path, ':');
+ if (charptr) {
+ *charptr = '\0';
+ }
+
+ errno = 0;
+
+ (void *) memset(kstat_name, 0, sizeof (kstat_name));
+ node = di_init(path, DINFOCPYONE);
+ if (node == DI_NODE_NIL) {
+ di_fini(node);
+ log(LOG_DEBUG, ROUTINE,
+ "Unable to take devinfo snapshot on HBA \"%s\" "
+ "for phyIndex: %08lx due to %s",
+ path, phy, strerror(errno));
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR);
+ }
+
+ /*
+ * Then we could fetch the instance number and driver name of this
+ * device.
+ */
+ instance = di_instance(node);
+ if (instance == -1) {
+ di_fini(node);
+ log(LOG_DEBUG, ROUTINE,
+ "An instance number has not been assigned to the "
+ "device \"%s\" when get phyIndex: %08lx", path, phy);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR);
+ }
+
+ driver_name = di_driver_name(node);
+ if (driver_name == NULL) {
+ di_fini(node);
+ log(LOG_DEBUG, ROUTINE,
+ "No driver bound to this device \"%s\" "
+ "when get phyIndex: %08lx",
+ path, phy);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR);
+ }
+
+ di_fini(node);
+
+ iport_wwn = wwnConversion(hba_port_ptr->port_attributes.\
+ PortSpecificAttribute.SASPort->LocalSASAddress.wwn);
+
+ /*
+ * Construct the kstat name here.
+ */
+ (void) snprintf(kstat_name, sizeof (kstat_name), "%s.%016llx.%u.%u",
+ driver_name, iport_wwn, instance, phy_ptr->phy.PhyIdentifier);
+
+ /* retrieve all the statistics from kstat. */
+ kc = kstat_open();
+ if (kc == NULL) {
+ log(LOG_DEBUG, ROUTINE,
+ "kstat_open failed due to \"%s\" of phyIndex: %08lx",
+ strerror(errno), phy);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR);
+ }
+ ksp = kstat_lookup(kc, NULL, -1, kstat_name);
+ if (ksp == NULL) {
+ log(LOG_DEBUG, ROUTINE,
+ "No matching kstat name found for \"%s\" "
+ "of phyIndex: %08lx",
+ kstat_name, phy);
+ unlock(&all_hbas_lock);
+ (void) kstat_close(kc);
+ return (HBA_STATUS_ERROR);
+ }
+ /* Found the phy we're looking for. */
+ if (kstat_read(kc, ksp, NULL) == -1) {
+ log(LOG_DEBUG, ROUTINE,
+ "error reading kstat data due to \"%s\" "
+ "of phyIndex: %08lx",
+ strerror(errno), phy);
+ unlock(&all_hbas_lock);
+ (void) kstat_close(kc);
+ return (HBA_STATUS_ERROR);
+ }
+
+ kname = (kstat_named_t *)ksp->ks_data;
+ for (i = 0; i < ksp->ks_ndata; i++, kname++) {
+ if (strcmp(kname->name,
+ "SecondsSinceLastReset") == 0) {
+ psas->SecondsSinceLastReset = kname->value.ull;
+ continue;
+ }
+ if (strcmp(kname->name, "TxFrames") == 0) {
+ psas->TxFrames = kname->value.ull;
+ continue;
+ }
+ if (strcmp(kname->name, "RxFrames") == 0) {
+ psas->RxFrames = kname->value.ull;
+ continue;
+ }
+ if (strcmp(kname->name, "TxWords") == 0) {
+ psas->TxWords = kname->value.ull;
+ continue;
+ }
+ if (strcmp(kname->name, "RxWords") == 0) {
+ psas->RxWords = kname->value.ull;
+ continue;
+ }
+ if (strcmp(kname->name, "InvalidDwordCount") == 0) {
+ psas->InvalidDwordCount = kname->value.ull;
+ continue;
+ }
+ if (strcmp(kname->name, "RunningDisparityErrorCount") == 0) {
+ psas->RunningDisparityErrorCount = kname->value.ull;
+ continue;
+ }
+ if (strcmp(kname->name, "LossofDwordSyncCount") == 0) {
+ psas->LossofDwordSyncCount = kname->value.ull;
+ continue;
+ }
+ if (strcmp(kname->name, "PhyResetProblemCount") == 0) {
+ psas->PhyResetProblemCount = kname->value.ull;
+ }
+ }
+ unlock(&all_hbas_lock);
+ (void) kstat_close(kc);
+
+ return (HBA_STATUS_OK);
+}
diff --git a/usr/src/lib/sun_sas/common/Sun_sasGetPortAttributesByWWN.c b/usr/src/lib/sun_sas/common/Sun_sasGetPortAttributesByWWN.c
new file mode 100644
index 0000000000..5c4723791a
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/Sun_sasGetPortAttributesByWWN.c
@@ -0,0 +1,189 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sun_sas.h>
+
+/*
+ * Retrieves the attributes for a specific discovered port by WWN
+ */
+HBA_STATUS
+Sun_sasGetPortAttributesByWWN(HBA_HANDLE handle, HBA_WWN portWWN,
+ HBA_WWN domainPortWWN, PSMHBA_PORTATTRIBUTES attributes)
+{
+ const char ROUTINE[] = "Sun_sasGetPortAttributesByWWN";
+ HBA_STATUS status;
+ struct sun_sas_hba *hba_ptr;
+ struct sun_sas_port *hba_port_ptr, *hba_disco_port;
+ int index, chkDomainPort = 0, domainFound = 0;
+
+ /* Validate the arguments */
+ if (attributes == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL port attributes");
+ return (HBA_STATUS_ERROR_ARG);
+ }
+
+ if (wwnConversion(domainPortWWN.wwn) != 0) {
+ chkDomainPort = 1;
+ }
+
+ lock(&all_hbas_lock);
+ index = RetrieveIndex(handle);
+ lock(&open_handles_lock);
+ hba_ptr = RetrieveHandle(index);
+ if (hba_ptr == NULL) {
+ log(LOG_DEBUG, ROUTINE, "Invalid handle %08lx.", handle);
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_INVALID_HANDLE);
+ }
+
+ /* Check for stale data */
+ status = verifyAdapter(hba_ptr);
+ if (status != HBA_STATUS_OK) {
+ log(LOG_DEBUG, ROUTINE, "Verify adapter failed");
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (status);
+ }
+
+ if (hba_ptr->first_port == NULL) {
+ /* This is probably an internal failure of the library */
+ if (hba_ptr->device_path) {
+ log(LOG_DEBUG, ROUTINE,
+ "Internal failure: Adapter %s contains "
+ "no port data", hba_ptr->device_path);
+ } else {
+ log(LOG_DEBUG, ROUTINE,
+ "Internal failure: Adapter at index %d contains "
+ "no port data", hba_ptr->index);
+ }
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR);
+ }
+
+ /* Loop over all Adapter ports */
+ for (hba_port_ptr = hba_ptr->first_port;
+ hba_port_ptr != NULL;
+ hba_port_ptr = hba_port_ptr->next) {
+ if (chkDomainPort) {
+ if (validateDomainAddress(hba_port_ptr,
+ domainPortWWN) != HBA_STATUS_OK) {
+ continue;
+ } else
+ domainFound = 1;
+ }
+
+ if (wwnConversion(hba_port_ptr->port_attributes.
+ PortSpecificAttribute.SASPort->LocalSASAddress.wwn) ==
+ wwnConversion(portWWN.wwn)) {
+ /*
+ * We should indicate an error if we enter here
+ * without domainPortWWN set.
+ */
+ if (chkDomainPort == 0) {
+ log(LOG_DEBUG, ROUTINE,
+ "Domain Port WWN should be set when "
+ "querying HBA port %016llx for "
+ "handle %08lx",
+ wwnConversion(portWWN.wwn), handle);
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_ARG);
+ }
+ attributes->PortType =
+ hba_port_ptr->port_attributes.PortType;
+ attributes->PortState =
+ hba_port_ptr->port_attributes.PortState;
+ (void) strlcpy(attributes->OSDeviceName,
+ hba_port_ptr->port_attributes.OSDeviceName,
+ sizeof (attributes->OSDeviceName));
+ (void) memcpy(attributes->PortSpecificAttribute.SASPort,
+ hba_port_ptr->port_attributes.PortSpecificAttribute.
+ SASPort, sizeof (struct SMHBA_SAS_Port));
+
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_OK);
+ }
+
+ /* check to make sure there are devices attached to this port */
+ if (hba_port_ptr->first_attached_port != NULL) {
+
+ /* Loop over all discovered ports */
+ for (hba_disco_port = hba_port_ptr->first_attached_port;
+ hba_disco_port != NULL;
+ hba_disco_port = hba_disco_port->next) {
+ if (wwnConversion(hba_disco_port->
+ port_attributes.PortSpecificAttribute.
+ SASPort->LocalSASAddress.wwn) ==
+ wwnConversion(portWWN.wwn)) {
+ attributes->PortType =
+ hba_disco_port->port_attributes.
+ PortType;
+ attributes->PortState =
+ hba_disco_port->port_attributes.
+ PortState;
+ (void) strlcpy(attributes->OSDeviceName,
+ hba_disco_port->port_attributes.
+ OSDeviceName,
+ sizeof (attributes->OSDeviceName));
+ (void) memcpy(attributes->
+ PortSpecificAttribute.SASPort,
+ hba_disco_port->port_attributes.
+ PortSpecificAttribute.SASPort,
+ sizeof (struct SMHBA_SAS_Port));
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_OK);
+ }
+ }
+ }
+ if (chkDomainPort) {
+ log(LOG_DEBUG, ROUTINE,
+ "Invalid Port WWN %016llx for handle %08lx",
+ wwnConversion(portWWN.wwn), handle);
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_ILLEGAL_WWN);
+ }
+ }
+ if (chkDomainPort && domainFound == 0) {
+ log(LOG_DEBUG, ROUTINE, "No Matching domain port"
+ " (%16llx) for port (%16llx) for handle %08lx",
+ wwnConversion(domainPortWWN.wwn),
+ wwnConversion(portWWN.wwn),
+ handle);
+ } else {
+ /* We enter here only when chkDomainPort == 0 */
+ log(LOG_DEBUG, ROUTINE,
+ "Invalid Port WWN %016llx for handle %08lx",
+ wwnConversion(portWWN.wwn), handle);
+ }
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_ILLEGAL_WWN);
+}
diff --git a/usr/src/lib/sun_sas/common/Sun_sasGetPortType.c b/usr/src/lib/sun_sas/common/Sun_sasGetPortType.c
new file mode 100644
index 0000000000..3c422e4777
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/Sun_sasGetPortType.c
@@ -0,0 +1,98 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sun_sas.h>
+
+/*
+ * Returns the number of HBAs supported by the library. This returns the
+ * current number of HBAs, even if this changes
+ *
+ */
+HBA_UINT32 Sun_sasGetPortType(HBA_HANDLE handle, HBA_UINT32 port,
+ HBA_PORTTYPE *porttype)
+{
+ const char ROUTINE[] = "Sun_sasGetPortType";
+ int index;
+ struct sun_sas_hba *hba_ptr;
+ struct sun_sas_port *hba_port_ptr;
+
+ /* Validate the arguments */
+ if (porttype == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL attributes.");
+ return (HBA_STATUS_ERROR_ARG);
+ }
+
+ lock(&all_hbas_lock);
+ index = RetrieveIndex(handle);
+ lock(&open_handles_lock);
+ hba_ptr = RetrieveHandle(index);
+ if (hba_ptr == NULL) {
+ log(LOG_DEBUG, ROUTINE, "Invalid handle %08lx.", handle);
+ /* on error, need to set NumberOfEntries to 0 */
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_INVALID_HANDLE);
+ }
+
+ if (hba_ptr->first_port == NULL) {
+ /* This is probably an internal failure of the library */
+ if (hba_ptr->device_path) {
+ log(LOG_DEBUG, ROUTINE,
+ "Internal failure: Adapter %s contains no port "
+ "data.", hba_ptr->device_path);
+ } else {
+ log(LOG_DEBUG, ROUTINE,
+ "Internal failure: Adapter at index %d contains "
+ "no port data", hba_ptr->index);
+ }
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR);
+ }
+
+ for (hba_port_ptr = hba_ptr->first_port;
+ hba_port_ptr != NULL; hba_port_ptr = hba_port_ptr->next) {
+ if (hba_port_ptr->index == port) {
+ break;
+ }
+ }
+
+ if (hba_port_ptr == NULL || hba_port_ptr->index != port) {
+ log(LOG_DEBUG, ROUTINE,
+ "Invalid port index %d for handle %08lx.",
+ port, handle);
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_ILLEGAL_INDEX);
+ }
+
+ *porttype = HBA_PORTTYPE_SASDEVICE;
+
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+
+ return (HBA_STATUS_OK);
+}
diff --git a/usr/src/lib/sun_sas/common/Sun_sasGetProtocolStatistics.c b/usr/src/lib/sun_sas/common/Sun_sasGetProtocolStatistics.c
new file mode 100644
index 0000000000..e53df6b6a5
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/Sun_sasGetProtocolStatistics.c
@@ -0,0 +1,39 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include "sun_sas.h"
+
+/*
+ * Not Supported
+ */
+/*ARGSUSED*/
+HBA_STATUS Sun_sasGetProtocolStatistics(
+ HBA_HANDLE handle,
+ HBA_UINT32 portindex,
+ HBA_UINT32 protocoltype,
+ SMHBA_PROTOCOLSTATISTICS *pstatistics) {
+ return (HBA_STATUS_ERROR_NOT_SUPPORTED);
+}
diff --git a/usr/src/lib/sun_sas/common/Sun_sasGetSASPhyAttributes.c b/usr/src/lib/sun_sas/common/Sun_sasGetSASPhyAttributes.c
new file mode 100644
index 0000000000..b4aceb9f50
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/Sun_sasGetSASPhyAttributes.c
@@ -0,0 +1,99 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sun_sas.h>
+
+/*
+ * Retrieves the statistics for a specified port on an adapter
+ */
+HBA_STATUS Sun_sasGetSASPhyAttributes(HBA_HANDLE handle,
+ HBA_UINT32 port, HBA_UINT32 phy, SMHBA_SAS_PHY *pAttributes)
+{
+ const char ROUTINE[] = "Sun_sasGetSASPhyAttributes";
+ HBA_STATUS status = HBA_STATUS_OK;
+ struct sun_sas_hba *hba_ptr;
+ struct sun_sas_port *hba_port_ptr;
+ struct phy_info *phy_ptr;
+
+ /* Validate the arguments */
+ if (pAttributes == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL response buffer");
+ return (HBA_STATUS_ERROR_ARG);
+ }
+ lock(&all_hbas_lock);
+
+ if ((hba_ptr = Retrieve_Sun_sasHandle(handle)) == NULL) {
+ log(LOG_DEBUG, ROUTINE, "Invalid handle %08lx", handle);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_INVALID_HANDLE);
+ }
+
+ /* Check for stale data */
+ status = verifyAdapter(hba_ptr);
+ if (status != HBA_STATUS_OK) {
+ log(LOG_DEBUG, ROUTINE, "Verify adapter failed");
+ unlock(&all_hbas_lock);
+ return (status);
+ }
+
+ for (hba_port_ptr = hba_ptr->first_port;
+ hba_port_ptr != NULL;
+ hba_port_ptr = hba_port_ptr->next) {
+ if (hba_port_ptr->index == port) {
+ break;
+ }
+ }
+
+ if (hba_port_ptr == NULL) {
+ log(LOG_DEBUG, ROUTINE, "Invalid port index");
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_ILLEGAL_INDEX);
+ }
+
+ /* match phy index. */
+ if (phy >= hba_port_ptr->port_attributes.PortSpecificAttribute.
+ SASPort->NumberofPhys) {
+ log(LOG_DEBUG, ROUTINE, "Invalid phy index %d", phy);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_ILLEGAL_INDEX);
+ } else {
+ for (phy_ptr = hba_port_ptr->first_phy; phy_ptr != NULL;
+ phy_ptr = phy_ptr->next) {
+ if (phy == phy_ptr->index) {
+ (void) memset(pAttributes, 0,
+ sizeof (SMHBA_SAS_PHY));
+ (void) memcpy(pAttributes, &phy_ptr->phy,
+ sizeof (SMHBA_SAS_PHY));
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_OK);
+ }
+ }
+ }
+
+ unlock(&all_hbas_lock);
+ log(LOG_DEBUG, ROUTINE, "Illegal phy index %d", phy);
+ return (HBA_STATUS_ERROR_ILLEGAL_INDEX);
+}
diff --git a/usr/src/lib/sun_sas/common/Sun_sasGetTargetMapping.c b/usr/src/lib/sun_sas/common/Sun_sasGetTargetMapping.c
new file mode 100644
index 0000000000..7d83e386bf
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/Sun_sasGetTargetMapping.c
@@ -0,0 +1,179 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sun_sas.h>
+
+/*
+ * Retrieves the mapping between targets and OS SCSI information
+ */
+HBA_STATUS
+Sun_sasGetTargetMapping(HBA_HANDLE handle, HBA_WWN hbaPortWWN,
+ HBA_WWN domainPortWWN, SMHBA_TARGETMAPPING *mapping)
+{
+ const char ROUTINE[] = "Sun_sasGetTargetMapping";
+ int i, index;
+ int hbaPortFound = 0;
+ int domainPortFound = 0;
+ uint_t total_entries = 0;
+ struct sun_sas_hba *hba_ptr;
+ struct sun_sas_port *hba_port_ptr, *hba_disco_port;
+ struct ScsiEntryList *mapping_ptr;
+
+ if (mapping == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL mapping buffer");
+ return (HBA_STATUS_ERROR_ARG);
+ }
+
+ lock(&all_hbas_lock);
+ index = RetrieveIndex(handle);
+ lock(&open_handles_lock);
+ hba_ptr = RetrieveHandle(index);
+ if (hba_ptr == NULL) {
+ log(LOG_DEBUG, ROUTINE, "Invalid handle %08lx.", handle);
+ /* on error, need to set NumberOfEntries to 0 */
+ mapping->NumberOfEntries = 0;
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_INVALID_HANDLE);
+ }
+
+ /*
+ * We should indicate an error if no domainPortWWN passed in.
+ */
+ if (wwnConversion(domainPortWWN.wwn) == 0) {
+ log(LOG_DEBUG, ROUTINE, "domainPortWWN must be provided");
+ mapping->NumberOfEntries = 0;
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_ARG);
+ }
+ /*
+ * walk through the list of ports for this hba and count up the number
+ * of discovered ports on each hba port
+ */
+ i = 0;
+ for (hba_port_ptr = hba_ptr->first_port; hba_port_ptr != NULL;
+ hba_port_ptr = hba_port_ptr->next) {
+ if (hbaPortFound == 0) {
+ if (wwnConversion(hba_port_ptr->port_attributes.
+ PortSpecificAttribute.SASPort->LocalSASAddress.wwn)
+ != wwnConversion(hbaPortWWN.wwn)) {
+ /*
+ * Since all the ports under the same HBA have
+ * the same LocalSASAddress, we should break
+ * the loop once we find it dosn't match.
+ */
+ break;
+ } else {
+ hbaPortFound = 1;
+ }
+ }
+
+ /*
+ * Check whether the domainPortWWN matches.
+ */
+ if ((validateDomainAddress(hba_port_ptr, domainPortWWN))
+ != HBA_STATUS_OK) {
+ continue;
+ }
+ domainPortFound = 1;
+
+ for (hba_disco_port = hba_port_ptr->first_attached_port;
+ hba_disco_port != NULL;
+ hba_disco_port = hba_disco_port->next) {
+ for (mapping_ptr = hba_disco_port->scsiInfo;
+ mapping_ptr != NULL;
+ mapping_ptr = mapping_ptr->next) {
+ /*
+ * Add the information as much as mapping
+ * can hold.
+ */
+ if (wwnConversion(domainPortWWN.wwn) !=
+ wwnConversion(mapping_ptr->entry.
+ PortLun.domainPortWWN.wwn)) {
+ continue;
+ }
+
+ if (total_entries < mapping->NumberOfEntries) {
+ (void) memcpy(&mapping->entry[i].ScsiId,
+ &mapping_ptr->entry.ScsiId,
+ sizeof (SMHBA_SCSIID));
+ (void) memcpy(&mapping->entry[i].
+ PortLun, &mapping_ptr->entry.
+ PortLun, sizeof (SMHBA_PORTLUN));
+ (void) memcpy(&mapping->entry[i].LUID,
+ &mapping_ptr->entry.LUID,
+ sizeof (SMHBA_LUID));
+ i++;
+ }
+ total_entries++;
+ }
+ }
+ }
+
+ /*
+ * check to make sure user has passed in an acceptable PortWWN for
+ * the given handle
+ */
+ if (hbaPortFound == 0) {
+ log(LOG_DEBUG, ROUTINE, "Unable to locate requested "
+ "HBA Port WWN %016llx on handle %08lx",
+ wwnConversion(hbaPortWWN.wwn), handle);
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_ILLEGAL_WWN);
+ }
+
+ if (domainPortFound == 0) {
+ log(LOG_DEBUG, ROUTINE, "No matching domain "
+ "port %016llx for port %016llx on handle "
+ "%08lx", wwnConversion(domainPortWWN.wwn),
+ wwnConversion(hbaPortWWN.wwn), handle);
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_ILLEGAL_WWN);
+ }
+
+ if (total_entries > mapping->NumberOfEntries) {
+ log(LOG_DEBUG, ROUTINE,
+ "total entries: %d: mapping->NumberofEntries: %d.",
+ total_entries, mapping->NumberOfEntries);
+ mapping->NumberOfEntries = total_entries;
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_MORE_DATA);
+ }
+
+ mapping->NumberOfEntries = total_entries;
+
+ /* convert devpath to dev link */
+ convertDevpathToDevlink(mapping);
+
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+
+ return (HBA_STATUS_OK);
+}
diff --git a/usr/src/lib/sun_sas/common/Sun_sasGetVendorLibraryAttributes.c b/usr/src/lib/sun_sas/common/Sun_sasGetVendorLibraryAttributes.c
new file mode 100644
index 0000000000..0257e3525b
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/Sun_sasGetVendorLibraryAttributes.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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sun_sas.h>
+
+#define SUN_SMHBA_VENDOR_LIB VSL_NAME
+#define SUN_SMHBA_VENDOR_LIB_PATH "/usr/lib/libsun_sas.so"
+#define SUN_SMHBA_VENDOR_LIB_VERSION VSL_STRING_VERSION
+
+HBA_UINT32
+Sun_sasGetVendorLibraryAttributes(SMHBA_LIBRARYATTRIBUTES *attrs) {
+ const char ROUTINE[] = "Sun_sasGetVendorLibraryAttributes";
+
+ /* Validate the arguments */
+ if (attrs == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL attrs structure");
+ return (SMHBA_LIBRARY_VERSION1);
+ }
+ (void) strlcpy(attrs->LibPath, SUN_SMHBA_VENDOR_LIB_PATH,
+ sizeof (attrs->LibPath));
+ (void) strlcpy(attrs->VName, SUN_SMHBA_VENDOR_LIB,
+ sizeof (attrs->VName));
+ (void) strlcpy(attrs->VVersion, SUN_SMHBA_VENDOR_LIB_VERSION,
+ sizeof (attrs->VVersion));
+
+ return (SMHBA_LIBRARY_VERSION1);
+}
diff --git a/usr/src/lib/sun_sas/common/Sun_sasGetVersion.c b/usr/src/lib/sun_sas/common/Sun_sasGetVersion.c
new file mode 100644
index 0000000000..0e7ac6c824
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/Sun_sasGetVersion.c
@@ -0,0 +1,34 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include "sun_sas.h"
+
+/*
+ * Returns the version which the common HBA API library is compatible with.
+ */
+HBA_UINT32 Sun_sasGetVersion() {
+ return (SMHBA_LIBRARY_VERSION1);
+}
diff --git a/usr/src/lib/sun_sas/common/Sun_sasLoadLibrary.c b/usr/src/lib/sun_sas/common/Sun_sasLoadLibrary.c
new file mode 100644
index 0000000000..b5df2a4cc8
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/Sun_sasLoadLibrary.c
@@ -0,0 +1,102 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+
+#include <sun_sas.h>
+
+/*
+ * Loads the HBA Library. Must be called before calling any HBA library
+ * functions
+ *
+ * Return values:
+ * HBA_STATUS_OK library properly loaded
+ * HBA_STATUS_ERROR library loaded incorrectly
+ */
+int loadCount = 0;
+HBA_STATUS Sun_sasLoadLibrary() {
+ const char ROUTINE[] = "Sun_sasLoadLibrary";
+ di_node_t root;
+ boolean_t atLeastOneHBA = B_FALSE;
+ boolean_t atLeastOneFailure = B_FALSE;
+ hrtime_t start = 0;
+ hrtime_t end = 0;
+ double duration = 0;
+
+ /* Make sure that library has not been already loaded */
+ if (loadCount++ > 0) {
+ log(LOG_DEBUG, ROUTINE, "Library already loaded %d time."
+ " Ignoring.", loadCount);
+ return (HBA_STATUS_ERROR);
+ }
+ hba_count = 0;
+ open_handle_index = 1;
+ /* Initialize the read-write lock */
+ if (mutex_init(&all_hbas_lock, USYNC_THREAD, NULL)) {
+ log(LOG_DEBUG, ROUTINE,
+ "Unable to initialize lock in LoadLibrary for reason \"%s\"",
+ strerror(errno));
+ return (HBA_STATUS_ERROR);
+ }
+ /* grab write lock */
+ lock(&all_hbas_lock);
+
+ start = gethrtime();
+ if ((root = di_init("/", DINFOCACHE)) == DI_NODE_NIL) {
+ log(LOG_DEBUG, ROUTINE,
+ "Unable to load device tree for reason \"%s\"",
+ strerror(errno));
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR);
+ }
+ end = gethrtime();
+ duration = end - start;
+ duration /= HR_SECOND;
+ log(LOG_DEBUG, ROUTINE, "Loading device tree init took "
+ "%.6f seconds", duration);
+
+ /* At load time, we only gather libdevinfo information */
+ if (devtree_get_all_hbas(root) == HBA_STATUS_OK) {
+ atLeastOneHBA = B_TRUE;
+ } else {
+ atLeastOneFailure = B_TRUE;
+ }
+
+ di_fini(root);
+
+ unlock(&all_hbas_lock);
+
+ /* Now determine what status code to return */
+ if (atLeastOneHBA) {
+ /* We've got at least one HBA and possibly some failures */
+ return (HBA_STATUS_OK);
+ } else if (atLeastOneFailure) {
+ /* We have no HBAs but have failures */
+ return (HBA_STATUS_ERROR);
+ } else {
+ /* We have no HBAs and no failures */
+ return (HBA_STATUS_OK);
+ }
+}
diff --git a/usr/src/lib/sun_sas/common/Sun_sasOpenAdapter.c b/usr/src/lib/sun_sas/common/Sun_sasOpenAdapter.c
new file mode 100644
index 0000000000..4556b4f86e
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/Sun_sasOpenAdapter.c
@@ -0,0 +1,59 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sun_sas.h>
+
+/*
+ * Opens a named adapter.
+ * By opening an adapter, an upper level application is ensuring that all access
+ * to an HBA_HANDLE between and open and a close is to the same adapter.
+ *
+ * Sun_sasOpenAdapter just creates a new handle and returns the handle.
+ * It does not do a driver open
+ */
+HBA_HANDLE Sun_sasOpenAdapter(char *name) {
+ const char ROUTINE[] = "Sun_sasOpenAdapter";
+ struct sun_sas_hba *hba_ptr;
+
+ if (name == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL adapter name.");
+ return (HANDLE_ERROR);
+ }
+ lock(&all_hbas_lock);
+ for (hba_ptr = global_hba_head; hba_ptr != NULL;
+ hba_ptr = hba_ptr->next) {
+ if (strcmp(hba_ptr->handle_name, name) == 0) {
+ break;
+ }
+ }
+ unlock(&all_hbas_lock);
+ if (hba_ptr == NULL) {
+ log(LOG_DEBUG, ROUTINE, "Invalid adapter name \"%s\"", name);
+ return (HANDLE_ERROR);
+ }
+
+ return (CreateHandle(hba_ptr->index));
+}
diff --git a/usr/src/lib/sun_sas/common/Sun_sasRefreshAdapterConfiguration.c b/usr/src/lib/sun_sas/common/Sun_sasRefreshAdapterConfiguration.c
new file mode 100644
index 0000000000..591342ad39
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/Sun_sasRefreshAdapterConfiguration.c
@@ -0,0 +1,155 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sun_sas.h>
+
+/*
+ * Discover an HBA node with matching path.
+ * The di_node_t argument should be the root of the device tree.
+ * This routine assumes the locks have been taken
+ */
+static int
+find_matching_hba(di_node_t node, void *arg)
+{
+ int *propData, rval;
+ walkarg_t *wa = (walkarg_t *)arg;
+ char *devpath, fulldevpath[MAXPATHLEN];
+
+ /* Skip stub(instance -1) nodes */
+ if (IS_STUB_NODE(node)) {
+ return (DI_WALK_CONTINUE);
+ }
+
+ rval = di_prop_lookup_ints(DDI_DEV_T_ANY, node,
+ "sm-hba-supported", &propData);
+ if (rval < 0) {
+ return (DI_WALK_CONTINUE);
+ } else {
+ if ((devpath = di_devfs_path(node)) == NULL) {
+ /* still continue to see if there is matching one. */
+ return (DI_WALK_CONTINUE);
+ }
+ (void) snprintf(fulldevpath, MAXPATHLEN, "%s%s", DEVICES_DIR,
+ devpath);
+
+ if ((strstr(fulldevpath, wa->devpath)) != NULL) {
+ *wa->flag = B_TRUE;
+ /* Found a node. No need to walk any more. */
+ di_devfs_path_free(devpath);
+ return (DI_WALK_TERMINATE);
+ }
+ di_devfs_path_free(devpath);
+ }
+
+ return (DI_WALK_CONTINUE);
+}
+
+/*
+ * Refreshes information about an HBA
+ *
+ * Note: This routine holds the locks in write mode
+ * during most of the processing, and as such, will cause
+ * all other threads to block on entry into the library
+ * until the refresh is complete. An optimization would be
+ * to put fine-grain locking in for the open_handle structures.
+ */
+void
+Sun_sasRefreshAdapterConfiguration()
+{
+ const char ROUTINE[] =
+ "Sun_sasRefreshAdapterConfiguration";
+ struct sun_sas_hba *hba_ptr;
+ di_node_t root;
+ hrtime_t start;
+ hrtime_t end;
+ double duration;
+ walkarg_t wa;
+
+ /*
+ * We're going to be tweaking a lot of global lists, so write
+ * lock them.
+ */
+ lock(&all_hbas_lock);
+ lock(&open_handles_lock);
+
+ start = gethrtime();
+ /* Grab device tree */
+ if ((root = di_init("/", DINFOCACHE)) == DI_NODE_NIL) {
+ log(LOG_DEBUG, ROUTINE,
+ "Unable to load device tree for reason \"%s\"",
+ strerror(errno));
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return;
+ }
+
+ end = gethrtime();
+ duration = end - start;
+ duration /= HR_SECOND;
+ log(LOG_DEBUG, ROUTINE, "Device tree init took "
+ "%.6f seconds", duration);
+
+ for (hba_ptr = global_hba_head; hba_ptr != NULL;
+ hba_ptr = hba_ptr->next) {
+ wa.devpath = hba_ptr->device_path;
+ wa.flag = (boolean_t *)calloc(1, sizeof (boolean_t));
+ *wa.flag = B_FALSE;
+
+ if (di_walk_node(root, DI_WALK_SIBFIRST, &wa,
+ find_matching_hba) != 0) {
+ log(LOG_DEBUG, ROUTINE, "di_walk_node failed.");
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ S_FREE(wa.flag);
+ di_fini(root);
+ return;
+ }
+
+ if (*wa.flag == B_FALSE) {
+ /*
+ * Keep the HBA as it is including open handles
+ * per the SM-HBA standards. Just mark it as invalid.
+ */
+ log(LOG_DEBUG, ROUTINE, "No matching HBA found. %s",
+ hba_ptr->device_path);
+ hba_ptr->invalid = B_TRUE;
+ }
+ S_FREE(wa.flag);
+ }
+
+ /*
+ * Now we marked missing HBA(s). Redisoover hbas to refresh
+ * or add any new adapter to the hba list.
+ * Simply call devtree_get_all_hbas().
+ */
+ if (devtree_get_all_hbas(root) != HBA_STATUS_OK) {
+ log(LOG_DEBUG, ROUTINE, "devtree_get_all_hbas failed.");
+ }
+ di_fini(root);
+
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+}
diff --git a/usr/src/lib/sun_sas/common/Sun_sasRefreshInformation.c b/usr/src/lib/sun_sas/common/Sun_sasRefreshInformation.c
new file mode 100644
index 0000000000..fc26c9aa08
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/Sun_sasRefreshInformation.c
@@ -0,0 +1,159 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include "sun_sas.h"
+
+/*
+ * Discover an HBA node with mtaching path.
+ * The di_node_t argument should be the root of the device tree.
+ * This routine assumes the locks have been taken
+ */
+static int
+match_smhba_sas_hba(di_node_t node, void *arg)
+{
+ int *propData, rval;
+ walkarg_t *wa = (walkarg_t *)arg;
+ char *devpath, fulldevpath[MAXPATHLEN];
+
+ /* Skip stub(instance -1) nodes */
+ if (IS_STUB_NODE(node)) {
+ return (DI_WALK_CONTINUE);
+ }
+
+ rval = di_prop_lookup_ints(DDI_DEV_T_ANY, node,
+ "sm-hba-supported", &propData);
+ if (rval < 0) {
+ return (DI_WALK_CONTINUE);
+ } else {
+ if ((devpath = di_devfs_path(node)) == NULL) {
+ /* still continue to see if there is matching one. */
+ return (DI_WALK_CONTINUE);
+ }
+ (void) snprintf(fulldevpath, MAXPATHLEN, "%s%s", DEVICES_DIR,
+ devpath);
+
+ if ((strstr(fulldevpath, wa->devpath)) != NULL) {
+ /* add the hba to the hba list */
+ if (devtree_get_one_hba(node) ==
+ HBA_STATUS_OK) {
+ /* succeed to refresh the adapater. */
+ *wa->flag = B_TRUE;
+ }
+ /* Found a node. No need to walk any more. */
+ di_devfs_path_free(devpath);
+ return (DI_WALK_TERMINATE);
+ }
+ di_devfs_path_free(devpath);
+ }
+
+ return (DI_WALK_CONTINUE);
+}
+
+/*
+ * Refreshes information about an HBA
+ *
+ * Note: This routine holds the locks in write mode
+ * during most of the processing, and as such, will cause
+ * all other threads to block on entry into the library
+ * until the refresh is complete. An optimization would be
+ * to put fine-grain locking in for the open_handle structures.
+ */
+void
+Sun_sasRefreshInformation(HBA_HANDLE handle)
+{
+ const char ROUTINE[] = "Sun_sasRefreshInformation";
+ struct sun_sas_hba *hba_ptr;
+ struct open_handle *oHandle;
+ di_node_t root;
+ hrtime_t start;
+ hrtime_t end;
+ double duration;
+ walkarg_t wa;
+
+ /* take a lock for hbas and handles during rerfresh. */
+ lock(&all_hbas_lock);
+ lock(&open_handles_lock);
+
+ oHandle = RetrieveOpenHandle(handle);
+ if (oHandle == NULL) {
+ log(LOG_DEBUG, ROUTINE, "Invalid handle %08lx", handle);
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return;
+ }
+
+ /* now we know the associated hba exists in the global list. */
+ start = gethrtime();
+ /* Grab device tree */
+ if ((root = di_init("/", DINFOCACHE)) == DI_NODE_NIL) {
+ log(LOG_DEBUG, ROUTINE,
+ "Unable to load device tree for reason \"%s\"",
+ strerror(errno));
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return;
+ }
+
+ end = gethrtime();
+ duration = end - start;
+ duration /= HR_SECOND;
+ log(LOG_DEBUG, ROUTINE, "Device tree init took "
+ "%.6f seconds", duration);
+
+ hba_ptr = RetrieveHandle(oHandle->adapterIndex);
+ wa.devpath = hba_ptr->device_path;
+ wa.flag = (boolean_t *)calloc(1, sizeof (boolean_t));
+ *wa.flag = B_FALSE;
+
+ /* found the matching hba node and refresh hba ports and targets. */
+ if (di_walk_node(root, DI_WALK_SIBFIRST, &wa,
+ match_smhba_sas_hba) != 0) {
+ log(LOG_DEBUG, ROUTINE, "di_walk_node failed.");
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ S_FREE(wa.flag);
+ di_fini(root);
+ return;
+ }
+
+ if (*wa.flag != B_TRUE) {
+ /* no matching HBA. */
+ log(LOG_DEBUG, ROUTINE, "No matching HBA found.");
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ S_FREE(wa.flag);
+ di_fini(root);
+ return;
+ }
+
+ S_FREE(wa.flag);
+
+ di_fini(root);
+
+ /* All done, release the locks */
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+}
diff --git a/usr/src/lib/sun_sas/common/Sun_sasScsiInquiry.c b/usr/src/lib/sun_sas/common/Sun_sasScsiInquiry.c
new file mode 100644
index 0000000000..144a85d89d
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/Sun_sasScsiInquiry.c
@@ -0,0 +1,273 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sun_sas.h>
+
+/*
+ * Combine uscsi command ans send it out via ioctl
+ */
+static HBA_STATUS
+SendScsiInquiry(const char *devpath, HBA_UINT8 cdb1, HBA_UINT8 cdb2,
+ void *responseBuffer, HBA_UINT32 *responseSize, HBA_UINT8 *scsiStatus,
+ void *senseBuffer, HBA_UINT32 *senseSize)
+{
+ HBA_UINT32 status;
+ struct uscsi_cmd ucmd_buf;
+ union scsi_cdb cdb;
+
+ bzero(&cdb, sizeof (cdb));
+ bzero(&ucmd_buf, sizeof (ucmd_buf));
+ bzero(senseBuffer, *senseSize);
+ bzero(responseBuffer, *responseSize);
+
+ cdb.scc_cmd = SCMD_INQUIRY;
+ cdb.g0_addr1 = cdb2;
+ cdb.g0_addr2 = cdb1;
+ cdb.g0_count0 = *responseSize;
+
+ ucmd_buf.uscsi_cdb = (char *)&cdb;
+ ucmd_buf.uscsi_cdblen = CDB_GROUP0;
+ ucmd_buf.uscsi_bufaddr = (caddr_t)responseBuffer;
+ ucmd_buf.uscsi_buflen = *responseSize;
+ ucmd_buf.uscsi_rqbuf = (caddr_t)senseBuffer;
+ ucmd_buf.uscsi_rqlen = *senseSize;
+ ucmd_buf.uscsi_flags = USCSI_READ | USCSI_SILENT | USCSI_RQENABLE;
+
+ status = send_uscsi_cmd(devpath, &ucmd_buf);
+ *scsiStatus = ucmd_buf.uscsi_status;
+ return (status);
+}
+
+
+/*
+ * Send a SCSI inquiry to a remote WWN
+ */
+HBA_STATUS
+Sun_sasScsiInquiry(HBA_HANDLE handle, HBA_WWN portWWN, HBA_WWN targetPortWWN,
+ HBA_WWN domainPortWWN, SMHBA_SCSILUN smhbaLUN, HBA_UINT8 cdb1,
+ HBA_UINT8 cdb2, void *responseBuffer, HBA_UINT32 *responseSize,
+ HBA_UINT8 *scsiStatus, void *senseBuffer, HBA_UINT32 *senseSize)
+{
+ const char ROUTINE[] = "Sun_sasScsiInquiry";
+ HBA_STATUS status;
+ int index = 0;
+ int domainPortFound = 0;
+ int hbaPortFound = 0;
+ int chkDomainPort = 0;
+ struct sun_sas_hba *hba_ptr = NULL;
+ struct sun_sas_port *hba_port_ptr, *hba_disco_port;
+ struct ScsiEntryList *mapping_ptr;
+ hrtime_t start, end;
+ double duration;
+ HBA_SCSILUN hba_lun;
+
+ start = gethrtime();
+ /* Validate the arguments */
+ if (responseBuffer == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL response buffer");
+ return (HBA_STATUS_ERROR_ARG);
+ }
+ if (senseBuffer == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL sense buffer");
+ return (HBA_STATUS_ERROR_ARG);
+ }
+ if (responseSize == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL response size");
+ return (HBA_STATUS_ERROR_ARG);
+ }
+ if (senseSize == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL sense size");
+ return (HBA_STATUS_ERROR_ARG);
+ }
+ if (scsiStatus == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL scsi status");
+ return (HBA_STATUS_ERROR_ARG);
+ }
+
+ lock(&all_hbas_lock);
+ index = RetrieveIndex(handle);
+ lock(&open_handles_lock);
+ if ((hba_ptr = RetrieveHandle(index)) == NULL) {
+ log(LOG_DEBUG, ROUTINE, "Invalid handle %08lx", handle);
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_INVALID_HANDLE);
+ }
+
+ /* Check for stale data */
+ status = verifyAdapter(hba_ptr);
+ if (status != HBA_STATUS_OK) {
+ log(LOG_DEBUG, ROUTINE, "Verify adapter failed");
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (status);
+ }
+
+ /*
+ * We are not checking to see if our data is stale.
+ * By verifying this information here, we will take a big performance
+ * hit. This check will be done later only if the Inquiry ioctl fails
+ */
+ if (hba_ptr->device_path == NULL) {
+ log(LOG_DEBUG, ROUTINE,
+ "HBA handle had NULL device path. \
+ Unable to send SCSI cmd");
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR);
+ }
+
+ if (wwnConversion(domainPortWWN.wwn))
+ chkDomainPort = 1;
+
+ /* Determine which port to use */
+ for (hba_port_ptr = hba_ptr->first_port;
+ hba_port_ptr != NULL;
+ hba_port_ptr = hba_port_ptr->next) {
+
+ if (hbaPortFound == 0) {
+ if (wwnConversion(hba_port_ptr->port_attributes.
+ PortSpecificAttribute.SASPort->LocalSASAddress.wwn)
+ != wwnConversion(portWWN.wwn)) {
+ /*
+ * Since all the ports under the same HBA have
+ * the same LocalSASAddress, we should break
+ * the loop once we find it dosn't match.
+ */
+ break;
+ } else {
+ hbaPortFound = 1;
+ }
+ }
+
+ if (chkDomainPort) {
+ if (hba_port_ptr->first_phy != NULL &&
+ wwnConversion(hba_port_ptr->first_phy->
+ phy.domainPortWWN.wwn) ==
+ wwnConversion(domainPortWWN.wwn)) {
+ domainPortFound = 1;
+ }
+ if (!(domainPortFound)) {
+ continue;
+ }
+ }
+
+ for (hba_disco_port = hba_port_ptr->first_attached_port;
+ hba_disco_port != NULL;
+ hba_disco_port = hba_disco_port->next) {
+
+ /*
+ * If discoveredPort is not given targetPort, just skip
+ */
+ if (wwnConversion(hba_disco_port->port_attributes.\
+ PortSpecificAttribute.SASPort->LocalSASAddress.wwn)
+ != wwnConversion(targetPortWWN.wwn)) {
+ /* Does not match */
+ continue;
+ }
+
+ /*
+ * If discoveredPort is not a SAS/SATA port, it is not a
+ * target port
+ */
+ if ((hba_disco_port->port_attributes.PortType !=
+ HBA_PORTTYPE_SATADEVICE) &&
+ (hba_disco_port->port_attributes.PortType !=
+ HBA_PORTTYPE_SASDEVICE)) {
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ log(LOG_DEBUG, ROUTINE, "Target Port WWN "
+ "%016llx on handle %08lx is not a Target",
+ wwnConversion(targetPortWWN.wwn), handle);
+ return (HBA_STATUS_ERROR_NOT_A_TARGET);
+ }
+
+ /*
+ * Iterating and matching is needed.
+ */
+ for (mapping_ptr = hba_disco_port->scsiInfo;
+ mapping_ptr != NULL;
+ mapping_ptr = mapping_ptr->next) {
+
+ if (memcmp(
+ &mapping_ptr->entry.PortLun.TargetLun,
+ &smhbaLUN, sizeof (HBA_SCSILUN))
+ != 0) {
+ continue;
+ }
+
+ status = SendScsiInquiry(
+ mapping_ptr->entry.ScsiId.OSDeviceName,
+ cdb1, cdb2,
+ responseBuffer, responseSize,
+ scsiStatus, senseBuffer,
+ senseSize);
+
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ end = gethrtime();
+ duration = end - start;
+ duration /= HR_SECOND;
+ log(LOG_DEBUG, ROUTINE, "Took total\
+ of %.4f seconds", duration);
+ return (status);
+ }
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ (void *) memcpy(&hba_lun, &smhbaLUN,
+ sizeof (HBA_SCSILUN));
+ log(LOG_DEBUG, ROUTINE, "Unable to locate lun"
+ " %08lx for target %016llx on handle %08lx",
+ hba_lun, wwnConversion(targetPortWWN.wwn), handle);
+ return (HBA_STATUS_ERROR_INVALID_LUN);
+ }
+ if (chkDomainPort) {
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ log(LOG_DEBUG, ROUTINE, "Unable to locate requested "
+ "Port WWN %016llx on handle %08lx",
+ wwnConversion(targetPortWWN.wwn), handle);
+ return (HBA_STATUS_ERROR_ILLEGAL_WWN);
+ }
+ }
+
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ if (hbaPortFound == 0) {
+ log(LOG_DEBUG, ROUTINE,
+ "Unable to locate requested Port WWN %016llx on "
+ "handle %08lx", wwnConversion(portWWN.wwn), handle);
+ } else if (chkDomainPort && !domainPortFound) {
+ log(LOG_DEBUG, ROUTINE, "Unable to locate requested"
+ " domainPortWWN %016llx on handle %08lx",
+ wwnConversion(domainPortWWN.wwn), handle);
+ } else {
+ log(LOG_DEBUG, ROUTINE, "Unable to locate requested "
+ "Port WWN %016llx on handle %08lx",
+ wwnConversion(targetPortWWN.wwn), handle);
+ }
+ return (HBA_STATUS_ERROR_ILLEGAL_WWN);
+}
diff --git a/usr/src/lib/sun_sas/common/Sun_sasScsiReadCapacity.c b/usr/src/lib/sun_sas/common/Sun_sasScsiReadCapacity.c
new file mode 100644
index 0000000000..7295fe0aaa
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/Sun_sasScsiReadCapacity.c
@@ -0,0 +1,261 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sun_sas.h>
+
+/*
+ * Pass request buffer into uscsi command and sent it out via ioctl
+ */
+static HBA_STATUS
+SendScsiReadCapacity(const char *devpath, void *responseBuffer,
+ HBA_UINT32 *responseSize, HBA_UINT8 *scsiStatus,
+ void *senseBuffer, HBA_UINT32 *senseSize)
+{
+ HBA_UINT32 status;
+ struct uscsi_cmd ucmd_buf;
+ union scsi_cdb cdb;
+
+ bzero(&cdb, sizeof (cdb));
+ bzero(&ucmd_buf, sizeof (ucmd_buf));
+ bzero(senseBuffer, *senseSize);
+ bzero(responseBuffer, *responseSize);
+
+ cdb.scc_cmd = SCMD_READ_CAPACITY;
+
+ ucmd_buf.uscsi_cdb = (char *)&cdb;
+ ucmd_buf.uscsi_cdblen = CDB_GROUP1;
+ ucmd_buf.uscsi_bufaddr = (caddr_t)responseBuffer;
+ ucmd_buf.uscsi_buflen = *responseSize;
+ ucmd_buf.uscsi_rqbuf = (caddr_t)senseBuffer;
+ ucmd_buf.uscsi_rqlen = *senseSize;
+ ucmd_buf.uscsi_flags = USCSI_READ | USCSI_SILENT | USCSI_RQENABLE;
+ ucmd_buf.uscsi_timeout = 60;
+
+ status = send_uscsi_cmd(devpath, &ucmd_buf);
+ *scsiStatus = ucmd_buf.uscsi_status;
+ return (status);
+}
+
+/*
+ * Send a read capacity to a remote WWN
+ */
+HBA_STATUS
+Sun_sasScsiReadCapacity(HBA_HANDLE handle, HBA_WWN portWWN,
+ HBA_WWN targetPortWWN, HBA_WWN domainPortWWN, SMHBA_SCSILUN smhbaLUN,
+ void *responseBuffer, HBA_UINT32 *responseSize,
+ HBA_UINT8 *scsiStatus, void *senseBuffer, HBA_UINT32 *senseSize)
+{
+ const char ROUTINE[] = "Sun_sasScsiReadCapacity";
+ HBA_STATUS status;
+ int index = 0, domainPortFound = 0;
+ int hbaPortFound = 0;
+ int chkDomainPort = 0;
+ struct sun_sas_hba *hba_ptr = NULL;
+ struct sun_sas_port *hba_port_ptr, *hba_disco_port;
+ struct ScsiEntryList *mapping_ptr;
+ hrtime_t start, end;
+ double duration;
+ HBA_SCSILUN hba_lun;
+
+ start = gethrtime();
+ /* Validate the arguments */
+ if (responseBuffer == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL response buffer");
+ return (HBA_STATUS_ERROR_ARG);
+ }
+ if (senseBuffer == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL sense buffer");
+ return (HBA_STATUS_ERROR_ARG);
+ }
+ if (responseSize == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL response size");
+ return (HBA_STATUS_ERROR_ARG);
+ }
+ if (senseSize == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL sense size");
+ return (HBA_STATUS_ERROR_ARG);
+ }
+ if (scsiStatus == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL scsi status");
+ return (HBA_STATUS_ERROR_ARG);
+ }
+
+ lock(&all_hbas_lock);
+ index = RetrieveIndex(handle);
+ lock(&open_handles_lock);
+ if ((hba_ptr = RetrieveHandle(index)) == NULL) {
+ log(LOG_DEBUG, ROUTINE, "Invalid handle %08lx", handle);
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_INVALID_HANDLE);
+ }
+
+ /* Check for stale data */
+ status = verifyAdapter(hba_ptr);
+ if (status != HBA_STATUS_OK) {
+ log(LOG_DEBUG, ROUTINE, "Verify adapter failed");
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (status);
+ }
+
+ if (wwnConversion(domainPortWWN.wwn))
+ chkDomainPort = 1;
+
+ /*
+ * We are not checking to see if our data is stale.
+ * By verifying this information here, we will take a big performance
+ * hit. This check will be done later only if the FCSM ioctl fails
+ */
+
+ /* Determine which port to use */
+ for (hba_port_ptr = hba_ptr->first_port;
+ hba_port_ptr != NULL;
+ hba_port_ptr = hba_port_ptr->next) {
+
+ if (hbaPortFound == 0) {
+ if (wwnConversion(hba_port_ptr->port_attributes.
+ PortSpecificAttribute.SASPort->LocalSASAddress.wwn)
+ != wwnConversion(portWWN.wwn)) {
+ /*
+ * Since all the ports under the same HBA have
+ * the same LocalSASAddress, we should break
+ * the loop once we find it dosn't match.
+ */
+ break;
+ } else {
+ hbaPortFound = 1;
+ }
+ }
+
+ if (chkDomainPort != 0) {
+ if (hba_port_ptr->first_phy != NULL &&
+ wwnConversion(hba_port_ptr->first_phy->
+ phy.domainPortWWN.wwn) ==
+ wwnConversion(domainPortWWN.wwn)) {
+ domainPortFound = 1;
+ }
+ if (!(domainPortFound)) {
+ continue;
+ }
+ }
+
+ for (hba_disco_port = hba_port_ptr->first_attached_port;
+ hba_disco_port != NULL;
+ hba_disco_port = hba_disco_port->next) {
+
+ /*
+ * If discoveredPort is not given targetPort, just skip
+ */
+ if (wwnConversion(hba_disco_port->port_attributes.\
+ PortSpecificAttribute.SASPort->LocalSASAddress.wwn)
+ != wwnConversion(targetPortWWN.wwn)) {
+ /* Does not match */
+ continue;
+ }
+
+ /*
+ * If discoveredPort is not a SAS/SATA port, it is not a
+ * target port
+ */
+ if ((hba_disco_port->port_attributes.PortType !=
+ HBA_PORTTYPE_SATADEVICE) &&
+ (hba_disco_port->port_attributes.PortType !=
+ HBA_PORTTYPE_SASDEVICE)) {
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ log(LOG_DEBUG, ROUTINE, "Target Port WWN "
+ "%016llx on handle %08lx is not a Target",
+ wwnConversion(targetPortWWN.wwn), handle);
+ return (HBA_STATUS_ERROR_NOT_A_TARGET);
+ }
+
+ /*
+ * Iterating and matching is needed.
+ */
+ for (mapping_ptr = hba_disco_port->scsiInfo;
+ mapping_ptr != NULL;
+ mapping_ptr = mapping_ptr->next) {
+
+ if (memcmp(
+ &mapping_ptr->entry.PortLun.TargetLun,
+ &smhbaLUN, sizeof (HBA_SCSILUN))
+ != 0) {
+ continue;
+ }
+
+ status = SendScsiReadCapacity(
+ mapping_ptr->entry.ScsiId.\
+ OSDeviceName,
+ responseBuffer, responseSize,
+ scsiStatus, senseBuffer, senseSize);
+
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ end = gethrtime();
+ duration = end - start;
+ duration /= HR_SECOND;
+ log(LOG_DEBUG, ROUTINE, "Took total\
+ of %.4f seconds", duration);
+ return (status);
+ }
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ (void *) memcpy(&hba_lun, &smhbaLUN,
+ sizeof (HBA_SCSILUN));
+ log(LOG_DEBUG, ROUTINE, "Unable to locate lun"
+ " %08lx for target %016llx on handle %08lx",
+ hba_lun, wwnConversion(targetPortWWN.wwn), handle);
+ return (HBA_STATUS_ERROR_INVALID_LUN);
+ }
+
+ if (chkDomainPort) {
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ log(LOG_DEBUG, ROUTINE, "Unable to locate requested "
+ "Port WWN %016llx on handle %08lx",
+ wwnConversion(targetPortWWN.wwn), handle);
+ return (HBA_STATUS_ERROR_ILLEGAL_WWN);
+ }
+ }
+
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ if (hbaPortFound == 0) {
+ log(LOG_DEBUG, ROUTINE,
+ "Unable to locate requested Port WWN %016llx on "
+ "handle %08lx", wwnConversion(portWWN.wwn), handle);
+ } else if (chkDomainPort && !domainPortFound) {
+ log(LOG_DEBUG, ROUTINE, "Unable to locate requested"
+ " domainPortWWN %016llx on handle %08lx",
+ wwnConversion(domainPortWWN.wwn), handle);
+ } else {
+ log(LOG_DEBUG, ROUTINE, "Unable to locate requested "
+ "Port WWN %016llx on handle %08lx",
+ wwnConversion(targetPortWWN.wwn), handle);
+ }
+ return (HBA_STATUS_ERROR_ILLEGAL_WWN);
+}
diff --git a/usr/src/lib/sun_sas/common/Sun_sasScsiReportLUNs.c b/usr/src/lib/sun_sas/common/Sun_sasScsiReportLUNs.c
new file mode 100644
index 0000000000..62b428d4d4
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/Sun_sasScsiReportLUNs.c
@@ -0,0 +1,233 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sun_sas.h>
+
+/*
+ * Pass scsi request buffer into uscsi command and sent it out via ioctl
+ */
+static HBA_STATUS
+SendScsiReportLUNs(const char *devpath, void *responseBuffer,
+ HBA_UINT32 *responseSize, HBA_UINT8 *scsiStatus,
+ void *senseBuffer, HBA_UINT32 *senseSize)
+{
+ HBA_UINT32 status;
+ struct uscsi_cmd ucmd_buf;
+ union scsi_cdb cdb;
+
+ bzero(&cdb, sizeof (cdb));
+ bzero(&ucmd_buf, sizeof (ucmd_buf));
+ bzero(senseBuffer, *senseSize);
+
+ cdb.scc_cmd = SCMD_REPORT_LUNS;
+ FORMG5COUNT(&cdb, *responseSize);
+
+ ucmd_buf.uscsi_cdb = (char *)&cdb;
+ ucmd_buf.uscsi_cdblen = CDB_GROUP5;
+ ucmd_buf.uscsi_bufaddr = (caddr_t)responseBuffer;
+ ucmd_buf.uscsi_buflen = *responseSize;
+ ucmd_buf.uscsi_rqbuf = (caddr_t)senseBuffer;
+ ucmd_buf.uscsi_rqlen = *senseSize;
+ ucmd_buf.uscsi_flags = USCSI_READ | USCSI_SILENT | USCSI_RQENABLE;
+ ucmd_buf.uscsi_timeout = 60;
+
+ status = send_uscsi_cmd(devpath, &ucmd_buf);
+ *scsiStatus = ucmd_buf.uscsi_status;
+ return (status);
+
+}
+
+/*
+ * Send a SCSI report luns command to a remote WWN
+ */
+HBA_STATUS
+Sun_sasScsiReportLUNs(HBA_HANDLE handle, HBA_WWN portWWN, HBA_WWN targetPortWWN,
+ HBA_WWN domainPortWWN, void *responseBuffer, HBA_UINT32 *responseSize,
+ HBA_UINT8 *scsiStatus, void *senseBuffer, HBA_UINT32 *senseSize)
+{
+ const char ROUTINE[] = "Sun_sasScsiReportLUNs";
+ HBA_STATUS status;
+ int index = 0, domainPortFound = 0;
+ int chkDomainPort = 0;
+ int hbaPortFound = 0;
+ struct sun_sas_hba *hba_ptr = NULL;
+ struct sun_sas_port *hba_port_ptr, *hba_disco_port;
+ struct ScsiEntryList *mapping_ptr;
+ hrtime_t start, end;
+ double duration;
+
+ start = gethrtime();
+
+ /* Validate the arguments */
+ if (responseBuffer == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL response buffer");
+ return (HBA_STATUS_ERROR_ARG);
+ }
+ if (senseBuffer == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL sense buffer");
+ return (HBA_STATUS_ERROR_ARG);
+ }
+ if (responseSize == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL response size");
+ return (HBA_STATUS_ERROR_ARG);
+ }
+ if (senseSize == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL sense size");
+ return (HBA_STATUS_ERROR_ARG);
+ }
+ if (scsiStatus == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL scsi status");
+ return (HBA_STATUS_ERROR_ARG);
+ }
+
+ lock(&all_hbas_lock);
+ index = RetrieveIndex(handle);
+ lock(&open_handles_lock);
+ if ((hba_ptr = RetrieveHandle(index)) == NULL) {
+ log(LOG_DEBUG, ROUTINE, "Invalid handle %08lx", handle);
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_INVALID_HANDLE);
+ }
+
+ /* Check for stale data */
+ status = verifyAdapter(hba_ptr);
+ if (status != HBA_STATUS_OK) {
+ log(LOG_DEBUG, ROUTINE, "Verify adapter failed");
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (status);
+ }
+
+ if (wwnConversion(domainPortWWN.wwn))
+ chkDomainPort = 1;
+ /* Determine which port to use */
+ for (hba_port_ptr = hba_ptr->first_port;
+ hba_port_ptr != NULL;
+ hba_port_ptr = hba_port_ptr->next) {
+
+ if (hbaPortFound == 0) {
+ if (wwnConversion(hba_port_ptr->port_attributes.
+ PortSpecificAttribute.SASPort->LocalSASAddress.wwn)
+ != wwnConversion(portWWN.wwn)) {
+ /*
+ * Since all the ports under the same HBA have
+ * the same LocalSASAddress, we should break
+ * the loop once we find it dosn't match.
+ */
+ break;
+ } else {
+ hbaPortFound = 1;
+ }
+ }
+
+ if (chkDomainPort != 0) {
+ if (hba_port_ptr->first_phy != NULL &&
+ wwnConversion(hba_port_ptr->first_phy->
+ phy.domainPortWWN.wwn) ==
+ wwnConversion(domainPortWWN.wwn)) {
+ domainPortFound = 1;
+ }
+ if (!(domainPortFound)) {
+ continue;
+ }
+ }
+
+ for (hba_disco_port = hba_port_ptr->first_attached_port;
+ hba_disco_port != NULL;
+ hba_disco_port = hba_disco_port->next) {
+
+ /*
+ * If discoveredPort is not given targetPort, skip
+ */
+ if (wwnConversion(hba_disco_port->port_attributes.\
+ PortSpecificAttribute.SASPort->LocalSASAddress.wwn)
+ != wwnConversion(targetPortWWN.wwn)) {
+ /* Does not match */
+ continue;
+ }
+
+ /*
+ * If discoveredPort is not a SAS/SATA port, it is not a
+ * target port
+ */
+ if ((hba_disco_port->port_attributes.PortType !=
+ HBA_PORTTYPE_SATADEVICE) &&
+ (hba_disco_port->port_attributes.PortType !=
+ HBA_PORTTYPE_SASDEVICE)) {
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ log(LOG_DEBUG, ROUTINE, "Target Port WWN "
+ "%016llx on handle %08lx is not a Target",
+ wwnConversion(targetPortWWN.wwn), handle);
+ return (HBA_STATUS_ERROR_NOT_A_TARGET);
+ }
+
+ if ((mapping_ptr = hba_disco_port->scsiInfo) != NULL) {
+
+ status = SendScsiReportLUNs(
+ mapping_ptr->entry.ScsiId.OSDeviceName,
+ responseBuffer, responseSize,
+ scsiStatus, senseBuffer, senseSize);
+
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ end = gethrtime();
+ duration = end - start;
+ duration /= HR_SECOND;
+ log(LOG_DEBUG, ROUTINE, "Took total\
+ of %.4f seconds", duration);
+ return (status);
+ }
+ }
+
+ if (chkDomainPort) {
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ log(LOG_DEBUG, ROUTINE, "Unable to located requested "
+ "Port %016llx on handle %08lx",
+ wwnConversion(targetPortWWN.wwn), handle);
+ return (HBA_STATUS_ERROR_ILLEGAL_WWN);
+ }
+ }
+
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ if (hbaPortFound == 0) {
+ log(LOG_DEBUG, ROUTINE,
+ "Unable to locate requested Port WWN %016llx on "
+ "handle %08lx", wwnConversion(portWWN.wwn), handle);
+ } else if (chkDomainPort && !domainPortFound) {
+ log(LOG_DEBUG, ROUTINE, "Unable to locate requested"
+ " domainPortWWN %016llx on handle %08lx",
+ wwnConversion(domainPortWWN.wwn), handle);
+ } else {
+ log(LOG_DEBUG, ROUTINE, "Unable to locate requested "
+ "Port WWN %016llx on handle %08lx",
+ wwnConversion(targetPortWWN.wwn), handle);
+ }
+ return (HBA_STATUS_ERROR_ILLEGAL_WWN);
+}
diff --git a/usr/src/lib/sun_sas/common/Sun_sasSendSMPPassThru.c b/usr/src/lib/sun_sas/common/Sun_sasSendSMPPassThru.c
new file mode 100644
index 0000000000..914f47de06
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/Sun_sasSendSMPPassThru.c
@@ -0,0 +1,250 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sun_sas.h>
+#include <sys/scsi/impl/usmp.h>
+
+/*
+ * Pass usmp_cmd into ioctl
+ */
+static HBA_STATUS
+SendSMPPassThru(const char *devpath, void *reqframe, HBA_UINT32 *reqsize,
+ void *rspframe, HBA_UINT32 *rspsize) {
+ const char ROUTINE[] = "SendSMPPassThru";
+ int fd;
+ usmp_cmd_t ucmd_buf;
+ HBA_STATUS ret;
+
+ bzero(&ucmd_buf, sizeof (ucmd_buf));
+
+ ucmd_buf.usmp_req = (caddr_t)reqframe;
+ ucmd_buf.usmp_rsp = (caddr_t)rspframe;
+ ucmd_buf.usmp_reqsize = (size_t)(*reqsize);
+ ucmd_buf.usmp_rspsize = (size_t)(*rspsize);
+ ucmd_buf.usmp_timeout = SMP_DEFAULT_TIMEOUT;
+
+ /*
+ * open smp device
+ */
+
+ if ((fd = open(devpath, O_RDONLY | O_NONBLOCK)) == -1) {
+ log(LOG_DEBUG, ROUTINE,
+ "open devpath %s failed due to %s",
+ devpath, strerror(errno));
+ return (HBA_STATUS_ERROR);
+ }
+
+ /*
+ * send usmp command
+ */
+ if (ioctl(fd, USMPFUNC, &ucmd_buf) == -1) {
+ if ((errno == ETIME) || (errno == ETIMEDOUT) ||
+ (errno == EAGAIN)) {
+ ret = HBA_STATUS_ERROR_TRY_AGAIN;
+ } else if (errno == EBUSY) {
+ ret = HBA_STATUS_ERROR_BUSY;
+ } else {
+ ret = HBA_STATUS_ERROR;
+ }
+ log(LOG_DEBUG, ROUTINE, "ioctl:USMPFUNC failed due to %s",
+ strerror(errno));
+ (void) close(fd);
+ return (ret);
+ }
+
+ (void) close(fd);
+ return (HBA_STATUS_OK);
+}
+
+/*
+ * Send a USMP command to a remote SMP node
+ */
+HBA_STATUS
+Sun_sasSendSMPPassThru(HBA_HANDLE handle, HBA_WWN hbaPortWWN,
+ HBA_WWN destPortWWN, HBA_WWN domainPortWWN, void *pReqBuffer,
+ HBA_UINT32 ReqBufferSize, void *pRspBuffer, HBA_UINT32 *pRspBufferSize)
+{
+ const char ROUTINE[] = "Sun_sasSendSMPPassThru";
+ HBA_STATUS status;
+ struct sun_sas_hba *hba_ptr;
+ int domainPortFound = 0;
+ int chkDomainPort = 0;
+ int hbaPortFound = 0;
+ struct sun_sas_port *hba_port_ptr, *hba_disco_port;
+ hrtime_t start, end;
+ double duration;
+
+ start = gethrtime();
+ /* Validate the arguments */
+ if (pRspBuffer == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL response buffer");
+ return (HBA_STATUS_ERROR_ARG);
+ }
+ if (pReqBuffer == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL sense buffer");
+ return (HBA_STATUS_ERROR_ARG);
+ }
+ if (pRspBufferSize == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL response size");
+ return (HBA_STATUS_ERROR_ARG);
+ }
+
+ lock(&all_hbas_lock);
+ if ((hba_ptr = Retrieve_Sun_sasHandle(handle)) == NULL) {
+ log(LOG_DEBUG, ROUTINE, "Invalid handle %08lx", handle);
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_INVALID_HANDLE);
+ }
+
+ /* Check for stale data */
+ status = verifyAdapter(hba_ptr);
+ if (status != HBA_STATUS_OK) {
+ log(LOG_DEBUG, ROUTINE, "Verify adapter failed");
+ unlock(&all_hbas_lock);
+ return (status);
+ }
+
+ /*
+ * We are not checking to see if our data is stale.
+ * By verifying this information here, we will take a big performance
+ * hit. This check will be done later only if the Inquiry ioctl fails
+ */
+
+ if (hba_ptr->device_path == NULL) {
+ log(LOG_DEBUG, ROUTINE,
+ "HBA handle had NULL device path.\
+ Unable to send SCSI cmd");
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR);
+ }
+
+ if (wwnConversion(domainPortWWN.wwn))
+ chkDomainPort = 1;
+
+ /* Determine which port to use */
+ for (hba_port_ptr = hba_ptr->first_port;
+ hba_port_ptr != NULL;
+ hba_port_ptr = hba_port_ptr->next) {
+
+ if (hbaPortFound == 0) {
+ if (wwnConversion(hba_port_ptr->port_attributes.
+ PortSpecificAttribute.SASPort->LocalSASAddress.wwn)
+ != wwnConversion(hbaPortWWN.wwn)) {
+ /*
+ * Since all the ports under the same HBA have
+ * the same LocalSASAddress, we should break
+ * the loop once we find it dosn't match.
+ */
+ break;
+ } else {
+ hbaPortFound = 1;
+ }
+ }
+
+ if (chkDomainPort != 0) {
+ if (hba_port_ptr->first_phy != NULL &&
+ wwnConversion(hba_port_ptr->first_phy->
+ phy.domainPortWWN.wwn) ==
+ wwnConversion(domainPortWWN.wwn)) {
+ domainPortFound = 1;
+ }
+ if (!(domainPortFound)) {
+ continue;
+ }
+ }
+
+ for (hba_disco_port = hba_port_ptr->first_attached_port;
+ hba_disco_port != NULL;
+ hba_disco_port = hba_disco_port->next) {
+
+ /*
+ * If discoveredPort is not given targetPort, just skip
+ */
+ if (wwnConversion(hba_disco_port->port_attributes.\
+ PortSpecificAttribute.SASPort->LocalSASAddress.wwn)
+ != wwnConversion(destPortWWN.wwn)) {
+ /* Does not match */
+ continue;
+ }
+
+ /*
+ * If matching targetPort does not support SMP protocal
+ * return error.
+ * comment it out for testing only
+ */
+ if ((hba_disco_port->port_attributes.\
+ PortSpecificAttribute.SASPort->PortProtocol &
+ HBA_SASPORTPROTOCOL_SMP) == 0) {
+ log(LOG_DEBUG, ROUTINE, "Input WWN %01611x\
+ does not support SMP protocol",
+ wwnConversion(hbaPortWWN.wwn));
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR_INVALID_PROTOCOL_TYPE);
+ }
+
+ /*
+ * SMP target port doesn't have any scsi info.
+ * - like /dev/rdsk/cxtxdxsx
+ * So we use OSDeviceName from port attributes.
+ * - like /dev/smp/expd[0-9]
+ */
+ status = SendSMPPassThru(
+ hba_disco_port->port_attributes.OSDeviceName,
+ pReqBuffer, &ReqBufferSize,
+ pRspBuffer, pRspBufferSize);
+
+ unlock(&all_hbas_lock);
+ end = gethrtime();
+ duration = end - start;
+ duration /= HR_SECOND;
+ log(LOG_DEBUG, ROUTINE, "Took total\
+ of %.4f seconds", duration);
+ return (status);
+ }
+ if (chkDomainPort) {
+ unlock(&all_hbas_lock);
+ log(LOG_DEBUG, ROUTINE, "Unable to locate"
+ "requested SMP target port %16llx",
+ wwnConversion(destPortWWN.wwn));
+ return (HBA_STATUS_ERROR_ILLEGAL_WWN);
+ }
+ }
+ unlock(&all_hbas_lock);
+ if (hbaPortFound == 0) {
+ log(LOG_DEBUG, ROUTINE,
+ "Unable to locate requested Port WWN %016llx on "
+ "handle %08lx", wwnConversion(hbaPortWWN.wwn), handle);
+ } else if (chkDomainPort && !domainPortFound) {
+ log(LOG_DEBUG, ROUTINE, "Unable to locate requested"
+ " domainPortWWN %016llx on handle %08lx",
+ wwnConversion(domainPortWWN.wwn), handle);
+ } else {
+ log(LOG_DEBUG, ROUTINE, "Unable to locate"
+ "requested SMP target port %16llx",
+ wwnConversion(destPortWWN.wwn));
+ }
+ return (HBA_STATUS_ERROR_ILLEGAL_WWN);
+}
diff --git a/usr/src/lib/sun_sas/common/Sun_sasSetPersistentBinding.c b/usr/src/lib/sun_sas/common/Sun_sasSetPersistentBinding.c
new file mode 100644
index 0000000000..c879b12ecc
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/Sun_sasSetPersistentBinding.c
@@ -0,0 +1,36 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include "sun_sas.h"
+
+/*
+ * Not Supported
+ */
+/*ARGSUSED*/
+HBA_STATUS Sun_sasSetPersistentBinding(HBA_HANDLE handel, HBA_WWN hbaPortWWN,
+ HBA_WWN domainPortWWN, const SMHBA_BINDING *binding) {
+ return (HBA_STATUS_ERROR_NOT_SUPPORTED);
+}
diff --git a/usr/src/lib/sun_sas/common/devlink_disco.c b/usr/src/lib/sun_sas/common/devlink_disco.c
new file mode 100644
index 0000000000..9b616e2293
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/devlink_disco.c
@@ -0,0 +1,251 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sun_sas.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <libdevinfo.h>
+
+/*
+ * structure for di_devlink_walk
+ */
+typedef struct walk_devlink {
+ char *path;
+ size_t len;
+ char **linkpp;
+} walk_devlink_t;
+
+/*
+ * callback funtion for di_devlink_walk
+ * Find matching /dev link for the given path argument.
+ * devlink element and callback function argument.
+ * The input path is expected to not have "/devices".
+ */
+static int
+get_devlink(di_devlink_t devlink, void *arg)
+{
+ const char ROUTINE[] = "get_devlink";
+ walk_devlink_t *warg = (walk_devlink_t *)arg;
+
+ /*
+ * When path is specified, it doesn't have minor
+ * name. Therefore, the ../.. prefixes needs to be stripped.
+ */
+ if (warg->path) {
+ char *content = (char *)di_devlink_content(devlink);
+ char *start = strstr(content, "/devices");
+
+ if (start == NULL ||
+ strncmp(start, warg->path, warg->len) != 0 ||
+ /* make it sure the device path has minor name */
+ start[warg->len] != ':') {
+ return (DI_WALK_CONTINUE);
+ }
+ }
+
+ *(warg->linkpp) = strdup(di_devlink_path(devlink));
+ log(LOG_DEBUG, ROUTINE, "Walk terminate");
+ return (DI_WALK_TERMINATE);
+}
+
+/*
+ * Convert /devices paths to /dev sym-link paths.
+ * The mapping buffer OSDeviceName paths will be
+ * converted to short names.
+ * mappings The target mappings data to convert to short names
+ *
+ * If no link is found, the long path is left as is.
+ * Note: The NumberOfEntries field MUST not be greater than the size
+ * of the array passed in.
+ */
+void
+convertDevpathToDevlink(PSMHBA_TARGETMAPPING mappings)
+{
+ const char ROUTINE[] = "convertDevpathToLink";
+ di_devlink_handle_t hdl;
+ walk_devlink_t warg;
+ int j;
+ char *minor_path, *devlinkp;
+
+ if ((hdl = di_devlink_init(NULL, 0)) == NULL) {
+ log(LOG_DEBUG, ROUTINE, "di_devlink failed: errno:%d",
+ strerror(errno));
+ return;
+ }
+
+ for (j = 0; j < mappings->NumberOfEntries; j++) {
+ if (strchr(mappings->entry[j].ScsiId.OSDeviceName, ':')) {
+ /* search link for minor node */
+ minor_path = mappings->entry[j].ScsiId.OSDeviceName;
+ if (strstr(minor_path, "/devices") != NULL) {
+ minor_path = mappings->entry[j].ScsiId.
+ OSDeviceName + strlen("/devices");
+ }
+ warg.path = NULL;
+ } else {
+ minor_path = NULL;
+ if (strstr(mappings->entry[j].ScsiId.OSDeviceName,
+ "/devices") != NULL) {
+ warg.len = strlen(mappings->entry[j].ScsiId.
+ OSDeviceName) - strlen("/devices");
+ warg.path = mappings->entry[j].
+ ScsiId.OSDeviceName + strlen("/devices");
+ } else {
+ warg.len = strlen(mappings->entry[j].ScsiId.
+ OSDeviceName);
+ warg.path = mappings->entry[j].ScsiId.
+ OSDeviceName;
+ }
+ }
+
+ devlinkp = NULL;
+ warg.linkpp = &devlinkp;
+ (void) di_devlink_walk(hdl, NULL, minor_path, DI_PRIMARY_LINK,
+ (void *)&warg, get_devlink);
+
+ if (devlinkp != NULL) {
+ (void) snprintf(mappings->entry[j].ScsiId.OSDeviceName,
+ sizeof (mappings->entry[j].ScsiId.OSDeviceName),
+ "%s", devlinkp);
+ free(devlinkp);
+ }
+
+ }
+
+ (void) di_devlink_fini(&hdl);
+}
+
+/*
+ * Finds controller path for a give device path.
+ *
+ * Return value: /dev link for dir and minor name.
+ */
+static HBA_STATUS
+lookupLink(char *path, char *link, const char *dir, const char *mname)
+{
+ const char ROUTINE[] = "lookupLink";
+ DIR *dp;
+ char buf[MAXPATHLEN];
+ char node[MAXPATHLEN];
+ char *charptr;
+ struct dirent *newdirp, *dirp;
+ ssize_t count;
+ int dirplen;
+ char *subpath;
+ char tmpPath[MAXPATHLEN];
+
+ if ((dp = opendir(dir)) == NULL) {
+ log(LOG_DEBUG, ROUTINE,
+ "Unable to open %s to find controller number.", dir);
+ return (HBA_STATUS_ERROR);
+ }
+
+ if (link == NULL) {
+ log(LOG_DEBUG, ROUTINE,
+ "Invalid argument for storing the link.");
+ return (HBA_STATUS_ERROR);
+ }
+
+ /*
+ * dirplen is large enough to fit the largest path-
+ * struct dirent includes one byte (the terminator)
+ * so we don't add 1 to the calculation here.
+ */
+ dirplen = pathconf(dir, _PC_NAME_MAX);
+ dirplen = ((dirplen <= 0) ? MAXNAMELEN : dirplen) +
+ sizeof (struct dirent);
+ dirp = (struct dirent *)malloc(dirplen);
+ if (dirp == NULL) {
+ OUT_OF_MEMORY(ROUTINE);
+ return (HBA_STATUS_ERROR);
+ }
+
+ while ((readdir_r(dp, dirp, &newdirp)) == 0 && newdirp != NULL) {
+ if (strcmp(dirp->d_name, ".") == 0 ||
+ strcmp(dirp->d_name, "..") == 0) {
+ continue;
+ }
+ /*
+ * set to another pointer since dirp->d_name length is 1
+ * that will store only the first char 'c' from the name.
+ */
+ charptr = dirp->d_name;
+ (void) snprintf(node, strlen(charptr) + strlen(dir) + 2,
+ "%s/%s", dir, charptr);
+ if (count = readlink(node, buf, sizeof (buf))) {
+ subpath = NULL;
+ subpath = strstr(buf, path);
+ buf[count] = '\0';
+ if (subpath != NULL) {
+ (void) strlcpy(tmpPath, path, MAXPATHLEN);
+ (void) strlcat(tmpPath, mname, MAXPATHLEN);
+ /*
+ * if device path has substring of path
+ * and exactally matching with :scsi suffix
+ */
+ if (strcmp(subpath, tmpPath) == 0) {
+ (void) strlcpy(link, node, MAXPATHLEN);
+ (void) closedir(dp);
+ S_FREE(dirp);
+ return (HBA_STATUS_OK);
+ }
+ }
+ }
+ }
+
+ (void) closedir(dp);
+ S_FREE(dirp);
+ return (HBA_STATUS_ERROR);
+}
+
+/*
+ * Finds controller path for a give device path.
+ *
+ * Return vale:i smp devlink.
+ */
+HBA_STATUS
+lookupControllerLink(char *path, char *link)
+{
+ const char dir[] = "/dev/cfg";
+ const char mname[] = ":scsi";
+ return (lookupLink(path, link, dir, mname));
+}
+
+/*
+ * Finds smp devlink for a give smp path.
+ *
+ * Return vale: smp devlink.
+ */
+HBA_STATUS
+lookupSMPLink(char *path, char *link)
+{
+ const char dir[] = "/dev/smp";
+ const char mname[] = ":smp";
+ return (lookupLink(path, link, dir, mname));
+}
diff --git a/usr/src/lib/sun_sas/common/devtree_device_disco.c b/usr/src/lib/sun_sas/common/devtree_device_disco.c
new file mode 100644
index 0000000000..cb788e6605
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/devtree_device_disco.c
@@ -0,0 +1,1075 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sun_sas.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <inttypes.h>
+#include <ctype.h>
+#include <sys/scsi/scsi_address.h>
+#include <libdevid.h>
+
+/*
+ * Get the preferred minor node for the given path.
+ * ":n" for tapes, ":c,raw" for disks,
+ * and ":0" for enclosures.
+ */
+static void
+get_minor(char *devpath, char *minor)
+{
+ const char ROUTINE[] = "get_minor";
+ char fullpath[MAXPATHLEN];
+ int fd;
+
+ if ((strstr(devpath, "/st@")) || (strstr(devpath, "/tape@"))) {
+ (void) strcpy(minor, ":n");
+ } else if (strstr(devpath, "/smp@")) {
+ (void) strcpy(minor, ":smp");
+ } else if ((strstr(devpath, "/ssd@")) || (strstr(devpath, "/sd@")) ||
+ (strstr(devpath, "/disk@"))) {
+ (void) strcpy(minor, ":c,raw");
+ } else if ((strstr(devpath, "/ses@")) || (strstr(devpath,
+ "/enclosure@"))) {
+ (void) snprintf(fullpath, MAXPATHLEN, "%s%s%s", DEVICES_DIR,
+ devpath, ":0");
+ /* reset errno to 0 */
+ errno = 0;
+ if ((fd = open(fullpath, O_RDONLY)) == -1) {
+ /*
+ * :0 minor doesn't exist. assume bound to sgen driver
+ * and :ses minor exist.
+ */
+ if (errno == ENOENT) {
+ (void) strcpy(minor, ":ses");
+ }
+ } else {
+ (void) strcpy(minor, ":0");
+ (void) close(fd);
+ }
+ } else {
+ log(LOG_DEBUG, ROUTINE, "Unrecognized target (%s)",
+ devpath);
+ minor[0] = '\0';
+ }
+
+}
+
+/*
+ * Get the LUID through libdevid.
+ *
+ * devpath: /devices path for the devices.
+ * luidi: devid string.
+ */
+static void
+get_luid(char *devpath, char *luid)
+{
+ const char ROUTINE[] = "get_luid";
+ int fd;
+ ddi_devid_t devid = NULL;
+ char *devidstr;
+
+ /* reset errno. */
+ errno = 0;
+ if ((fd = open(devpath, O_RDONLY|O_NDELAY)) >= 0) {
+ if (devid_get(fd, &devid) == 0) {
+ if ((devidstr = devid_to_guid(devid)) != NULL) {
+ (void) strlcpy(luid, devidstr, 256);
+ devid_free_guid(devidstr);
+ } else {
+ log(LOG_DEBUG, ROUTINE,
+ "failed to get devid guid on (%s) : %s",
+ devpath, strerror(errno));
+ }
+ devid_free(devid);
+ } else {
+ log(LOG_DEBUG, ROUTINE,
+ "failed to get devid on (%s)", devpath);
+ }
+ (void) close(fd);
+ } else {
+ log(LOG_DEBUG, ROUTINE, "open failed on (%s) error: %s",
+ devpath, strerror(errno));
+ }
+}
+
+/*
+ * Free the attached port allocation.
+ */
+static void
+free_attached_port(struct sun_sas_port *port_ptr)
+{
+ struct sun_sas_port *tgt_port, *last_tgt_port;
+ struct ScsiEntryList *scsi_info = NULL, *last_scsi_info = NULL;
+
+ tgt_port = port_ptr->first_attached_port;
+ while (tgt_port != NULL) {
+ /* Free target mapping data list first. */
+ scsi_info = tgt_port->scsiInfo;
+ while (scsi_info != NULL) {
+ last_scsi_info = scsi_info;
+ scsi_info = scsi_info->next;
+ free(last_scsi_info);
+ }
+ last_tgt_port = tgt_port;
+ tgt_port = tgt_port->next;
+ free(last_tgt_port->port_attributes.\
+ PortSpecificAttribute.SASPort);
+ free(last_tgt_port);
+ }
+
+ port_ptr->first_attached_port = NULL;
+ port_ptr->port_attributes.PortSpecificAttribute.\
+ SASPort->NumberofDiscoveredPorts = 0;
+}
+
+/*
+ * Fill domainPortWWN.
+ * should be called after completing discovered port discovery.
+ */
+void
+fillDomainPortWWN(struct sun_sas_port *port_ptr)
+{
+ const char ROUTINE[] = "fillDomainPortWWN";
+ struct sun_sas_port *disco_port_ptr;
+ struct phy_info *phy_ptr;
+ uint64_t domainPort = 0;
+ struct ScsiEntryList *mapping_ptr;
+
+ for (disco_port_ptr = port_ptr->first_attached_port;
+ disco_port_ptr != NULL; disco_port_ptr = disco_port_ptr->next) {
+ if (disco_port_ptr->port_attributes.PortType ==
+ HBA_PORTTYPE_SASEXPANDER &&
+ wwnConversion(disco_port_ptr->port_attributes.
+ PortSpecificAttribute.SASPort->
+ AttachedSASAddress.wwn) ==
+ wwnConversion(port_ptr->port_attributes.
+ PortSpecificAttribute.SASPort->
+ LocalSASAddress.wwn)) {
+ (void) memcpy(&domainPort,
+ disco_port_ptr->port_attributes.
+ PortSpecificAttribute.
+ SASPort->LocalSASAddress.wwn, 8);
+ break;
+ }
+ }
+
+ if (domainPort == 0) {
+ if (port_ptr->first_attached_port) {
+ /*
+ * there is no expander device attached on an HBA port
+ * domainPortWWN should not stay to 0 since multiple
+ * hba ports can have the same LocalSASAddres within
+ * the same HBA.
+ * Set the SAS address of direct attached target.
+ */
+ if (wwnConversion(port_ptr->port_attributes.
+ PortSpecificAttribute.SASPort->
+ LocalSASAddress.wwn) ==
+ wwnConversion(port_ptr->first_attached_port->
+ port_attributes.PortSpecificAttribute.
+ SASPort->AttachedSASAddress.wwn)) {
+ (void) memcpy(&domainPort,
+ port_ptr->first_attached_port->
+ port_attributes.PortSpecificAttribute.
+ SASPort->LocalSASAddress.wwn, 8);
+ } else {
+ /*
+ * SAS address is not upstream connected.
+ * domainPortWWN stays as 0.
+ */
+ log(LOG_DEBUG, ROUTINE,
+ "DomainPortWWN is not set. "
+ "Device(s) are visible on the HBA port "
+ "but there is no expander or directly "
+ "attached port with matching upsteam "
+ "attached SAS address for "
+ "HBA port (Local SAS Address: %016llx).",
+ wwnConversion(port_ptr->port_attributes.
+ PortSpecificAttribute.
+ SASPort->LocalSASAddress.wwn));
+ return;
+ }
+ } else {
+ /*
+ * There existss an iport without properly configured
+ * child smp ndoes or child node or pathinfo.
+ * domainPortWWN stays as 0.
+ */
+ log(LOG_DEBUG, ROUTINE,
+ "DomainPortWWN is not set. No properly "
+ "configured smp or directly attached port "
+ "found on HBA port(Local SAS Address: %016llx).",
+ wwnConversion(port_ptr->port_attributes.
+ PortSpecificAttribute.
+ SASPort->LocalSASAddress.wwn));
+ return;
+ }
+ }
+
+ /* fill up phy info */
+ for (phy_ptr = port_ptr->first_phy; phy_ptr != NULL;
+ phy_ptr = phy_ptr->next) {
+ (void) memcpy(phy_ptr->phy.domainPortWWN.wwn, &domainPort, 8);
+ }
+
+ /* fill up target mapping */
+ for (disco_port_ptr = port_ptr->first_attached_port;
+ disco_port_ptr != NULL; disco_port_ptr = disco_port_ptr->next) {
+ for (mapping_ptr = disco_port_ptr->scsiInfo;
+ mapping_ptr != NULL;
+ mapping_ptr = mapping_ptr->next) {
+ (void) memcpy(mapping_ptr->entry.PortLun.
+ domainPortWWN.wwn, &domainPort, 8);
+ }
+ }
+}
+
+/*
+ * Finds attached device(target) from devinfo node.
+ */
+static HBA_STATUS
+get_attached_devices_info(di_node_t node, struct sun_sas_port *port_ptr)
+{
+ const char ROUTINE[] = "get_attached_devices_info";
+ char *propStringData = NULL;
+ int *propIntData = NULL;
+ int64_t *propInt64Data = NULL;
+ uchar_t *propByteData = NULL;
+ scsi_lun_t samLun;
+ char *unit_address;
+ char *charptr;
+ char *devpath, link[MAXNAMELEN];
+ char fullpath[MAXPATHLEN+1];
+ char minorname[MAXNAMELEN+1];
+ struct ScsiEntryList *mapping_ptr;
+ HBA_WWN SASAddress, AttachedSASAddress;
+ struct sun_sas_port *disco_port_ptr;
+ uint_t state = 0;
+ int portfound, rval, size, count, i;
+ int port_state = HBA_PORTSTATE_ONLINE;
+ uint64_t tmpAddr;
+
+ if (port_ptr == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL port_ptr argument");
+ return (HBA_STATUS_ERROR);
+ }
+
+ if ((devpath = di_devfs_path(node)) == NULL) {
+ log(LOG_DEBUG, ROUTINE,
+ "Device in device tree has no path. Skipping.");
+ return (HBA_STATUS_ERROR);
+ }
+
+ if ((di_instance(node) == -1) || di_retired(node)) {
+ log(LOG_DEBUG, ROUTINE,
+ "dev node (%s) returned instance of -1 or is retired. "
+ " Skipping.", devpath);
+ di_devfs_path_free(devpath);
+ return (HBA_STATUS_OK);
+ }
+ state = di_state(node);
+ /* when node is not attached and online, set the state to offline. */
+ if (((state & DI_DRIVER_DETACHED) == DI_DRIVER_DETACHED) ||
+ ((state & DI_DEVICE_OFFLINE) == DI_DEVICE_OFFLINE)) {
+ log(LOG_DEBUG, ROUTINE,
+ "dev node (%s) is either OFFLINE or DETACHED",
+ devpath);
+ port_state = HBA_PORTSTATE_OFFLINE;
+ }
+
+ /* add the "/devices" in the begining at the end */
+ (void) snprintf(fullpath, sizeof (fullpath), "%s%s",
+ DEVICES_DIR, devpath);
+
+ (void) memset(&SASAddress, 0, sizeof (SASAddress));
+ if ((unit_address = di_bus_addr(node)) != NULL) {
+ if ((charptr = strchr(unit_address, ',')) != NULL) {
+ *charptr = '\0';
+ }
+ for (charptr = unit_address; *charptr != '\0'; charptr++) {
+ if (isxdigit(*charptr)) {
+ break;
+ }
+ }
+ if (*charptr != '\0') {
+ tmpAddr = htonll(strtoll(charptr, NULL, 16));
+ (void) memcpy(&SASAddress.wwn[0], &tmpAddr, 8);
+ } else {
+ log(LOG_DEBUG, ROUTINE,
+ "No proper target port info on unit address of %s",
+ fullpath);
+ di_devfs_path_free(devpath);
+ return (HBA_STATUS_ERROR);
+ }
+ } else {
+ log(LOG_DEBUG, ROUTINE,
+ "Fail to get unit address of %s.",
+ fullpath);
+ di_devfs_path_free(devpath);
+ return (HBA_STATUS_ERROR);
+ }
+
+ (void) memset(&AttachedSASAddress, 0, sizeof (AttachedSASAddress));
+ if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "attached-port",
+ &propStringData) != -1) {
+ for (charptr = propStringData; *charptr != '\0'; charptr++) {
+ if (isxdigit(*charptr)) {
+ break;
+ }
+ }
+ if (*charptr != '\0') {
+ tmpAddr = htonll(strtoll(charptr, NULL, 16));
+ (void) memcpy(AttachedSASAddress.wwn, &tmpAddr, 8);
+ /* check the attached address of hba port. */
+ if (memcmp(port_ptr->port_attributes.
+ PortSpecificAttribute.SASPort->LocalSASAddress.wwn,
+ &tmpAddr, 8) == 0) {
+ /*
+ * When attached-port is set from iport
+ * attached-port prop, we do the cross check
+ * with device's own SAS address.
+ *
+ * If not set, we store device's own SAS
+ * address to iport attached SAS address.
+ */
+ if (wwnConversion(port_ptr->port_attributes.
+ PortSpecificAttribute.SASPort->
+ AttachedSASAddress.wwn)) {
+ /* verify the Attaached SAS Addr. */
+ if (memcmp(port_ptr->port_attributes.
+ PortSpecificAttribute.SASPort->
+ AttachedSASAddress.wwn,
+ SASAddress.wwn, 8) != 0) {
+ /* indentation move begin. */
+ log(LOG_DEBUG, ROUTINE,
+ "iport attached-port(%016llx) do not"
+ " match with level 1 Local"
+ " SAS address(%016llx).",
+ wwnConversion(port_ptr->port_attributes.
+ PortSpecificAttribute.
+ SASPort->AttachedSASAddress.wwn),
+ wwnConversion(SASAddress.wwn));
+ di_devfs_path_free(devpath);
+ free_attached_port(port_ptr);
+ return (HBA_STATUS_ERROR);
+ /* indentation move ends. */
+ }
+ } else {
+ (void) memcpy(port_ptr->port_attributes.
+ PortSpecificAttribute.
+ SASPort->AttachedSASAddress.wwn,
+ &SASAddress.wwn[0], 8);
+ }
+ }
+ } else {
+ log(LOG_DEBUG, ROUTINE,
+ "No proper attached SAS address value on device %s",
+ fullpath);
+ di_devfs_path_free(devpath);
+ free_attached_port(port_ptr);
+ return (HBA_STATUS_ERROR);
+ }
+ } else {
+ log(LOG_DEBUG, ROUTINE,
+ "Property AttachedSASAddress not found for device \"%s\"",
+ fullpath);
+ di_devfs_path_free(devpath);
+ free_attached_port(port_ptr);
+ return (HBA_STATUS_ERROR);
+ }
+
+ /*
+ * walk the disco list to make sure that there isn't a matching
+ * port and node wwn or a matching device path
+ */
+ portfound = 0;
+ for (disco_port_ptr = port_ptr->first_attached_port;
+ disco_port_ptr != NULL;
+ disco_port_ptr = disco_port_ptr->next) {
+ if ((disco_port_ptr->port_attributes.PortState !=
+ HBA_PORTSTATE_ERROR) && (memcmp(disco_port_ptr->
+ port_attributes.PortSpecificAttribute.
+ SASPort->LocalSASAddress.wwn, SASAddress.wwn, 8) == 0)) {
+ /*
+ * found matching disco_port
+ * look for matching device path
+ */
+ portfound = 1;
+ for (mapping_ptr = disco_port_ptr->scsiInfo;
+ mapping_ptr != NULL;
+ mapping_ptr = mapping_ptr->next) {
+ if (strstr(mapping_ptr-> entry.ScsiId.
+ OSDeviceName, devpath) != 0) {
+ log(LOG_DEBUG, ROUTINE,
+ "Found an already discovered "
+ "device %s.", fullpath);
+ di_devfs_path_free(devpath);
+ return (HBA_STATUS_OK);
+ }
+ }
+ if (portfound == 1) {
+ break;
+ }
+ }
+ }
+
+ if (portfound == 0) {
+ /*
+ * there are no matching SAS address.
+ * this must be a new device
+ */
+ if ((disco_port_ptr = (struct sun_sas_port *)calloc(1,
+ sizeof (struct sun_sas_port))) == NULL) {
+ OUT_OF_MEMORY(ROUTINE);
+ di_devfs_path_free(devpath);
+ free_attached_port(port_ptr);
+ return (HBA_STATUS_ERROR);
+ }
+
+ if ((disco_port_ptr->port_attributes.PortSpecificAttribute.\
+ SASPort = (struct SMHBA_SAS_Port *)calloc(1,
+ sizeof (struct SMHBA_SAS_Port))) == NULL) {
+ OUT_OF_MEMORY("add_hba_port_info");
+ di_devfs_path_free(devpath);
+ free_attached_port(port_ptr);
+ return (HBA_STATUS_ERROR);
+ }
+
+ (void) memcpy(disco_port_ptr->port_attributes.
+ PortSpecificAttribute.SASPort->LocalSASAddress.wwn,
+ SASAddress.wwn, 8);
+ (void) memcpy(disco_port_ptr->port_attributes.
+ PortSpecificAttribute.SASPort->AttachedSASAddress.wwn,
+ AttachedSASAddress.wwn, 8);
+
+ /* Default to unknown until we figure out otherwise */
+ rval = di_prop_lookup_strings(DDI_DEV_T_ANY, node,
+ "variant", &propStringData);
+ if (rval < 0) {
+ /* check if it is SMP target */
+ charptr = di_driver_name(node);
+ if (charptr != NULL && (strncmp(charptr, "smp",
+ strlen(charptr)) == 0)) {
+ disco_port_ptr->port_attributes.PortType =
+ HBA_PORTTYPE_SASEXPANDER;
+ disco_port_ptr->port_attributes.
+ PortSpecificAttribute.
+ SASPort->PortProtocol =
+ HBA_SASPORTPROTOCOL_SMP;
+ if (lookupSMPLink(devpath, (char *)link) ==
+ HBA_STATUS_OK) {
+ /* indentation changed here. */
+ (void) strlcpy(disco_port_ptr->port_attributes.
+ OSDeviceName, link,
+ sizeof (disco_port_ptr->port_attributes.OSDeviceName));
+ /* indentation change ends here. */
+ } else {
+ /* indentation changed here. */
+ get_minor(devpath, minorname);
+ (void) snprintf(fullpath, sizeof (fullpath), "%s%s%s",
+ DEVICES_DIR, devpath, minorname);
+ (void) strlcpy(disco_port_ptr->port_attributes.
+ OSDeviceName, fullpath,
+ sizeof (disco_port_ptr->port_attributes.OSDeviceName));
+ /* indentation change ends here. */
+ }
+ } else {
+ disco_port_ptr->port_attributes.PortType =
+ HBA_PORTTYPE_SASDEVICE;
+ disco_port_ptr->port_attributes.\
+ PortSpecificAttribute.\
+ SASPort->PortProtocol =
+ HBA_SASPORTPROTOCOL_SSP;
+ }
+ } else {
+ if ((strcmp(propStringData, "sata") == 0) ||
+ (strcmp(propStringData, "atapi") == 0)) {
+ disco_port_ptr->port_attributes.PortType =
+ HBA_PORTTYPE_SATADEVICE;
+ disco_port_ptr->port_attributes.\
+ PortSpecificAttribute.SASPort->PortProtocol
+ = HBA_SASPORTPROTOCOL_SATA;
+ } else {
+ log(LOG_DEBUG, ROUTINE,
+ "Unexpected variant prop value %s found on",
+ " device %s", propStringData, fullpath);
+ /*
+ * Port type will be 0
+ * which is not valid type.
+ */
+ }
+ }
+
+ /* SMP device was handled already */
+ if (disco_port_ptr->port_attributes.OSDeviceName[0] == '\0') {
+ /* indentation change due to ctysle check on sizeof. */
+ size = sizeof (disco_port_ptr->port_attributes.OSDeviceName);
+ (void) strlcpy(disco_port_ptr->port_attributes.
+ OSDeviceName, fullpath, size);
+ }
+
+ /* add new discovered port into the list */
+
+ if (port_ptr->first_attached_port == NULL) {
+ port_ptr->first_attached_port = disco_port_ptr;
+ disco_port_ptr->index = 0;
+ port_ptr->port_attributes.PortSpecificAttribute.\
+ SASPort->NumberofDiscoveredPorts = 1;
+ } else {
+ disco_port_ptr->next = port_ptr->first_attached_port;
+ port_ptr->first_attached_port = disco_port_ptr;
+ disco_port_ptr->index = port_ptr->port_attributes.\
+ PortSpecificAttribute.\
+ SASPort->NumberofDiscoveredPorts;
+ port_ptr->port_attributes.PortSpecificAttribute.\
+ SASPort->NumberofDiscoveredPorts++;
+ }
+ disco_port_ptr->port_attributes.PortState = port_state;
+ }
+
+ if (disco_port_ptr->port_attributes.PortType ==
+ HBA_PORTTYPE_SASEXPANDER) {
+ /* No mapping data for expander device. return ok here. */
+ di_devfs_path_free(devpath);
+ return (HBA_STATUS_OK);
+ }
+
+ if ((mapping_ptr = (struct ScsiEntryList *)calloc
+ (1, sizeof (struct ScsiEntryList))) == NULL) {
+ OUT_OF_MEMORY(ROUTINE);
+ di_devfs_path_free(devpath);
+ free_attached_port(port_ptr);
+ return (HBA_STATUS_ERROR);
+ }
+
+ if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "lun",
+ &propIntData) != -1) {
+ mapping_ptr->entry.ScsiId.ScsiOSLun = *propIntData;
+ } else {
+ if ((charptr = strchr(unit_address, ',')) != NULL) {
+ charptr++;
+ mapping_ptr->entry.ScsiId.ScsiOSLun =
+ strtoull(charptr, NULL, 10);
+ } else {
+ log(LOG_DEBUG, ROUTINE,
+ "Failed to get LUN from the unit address of device "
+ " %s.", fullpath);
+ di_devfs_path_free(devpath);
+ free_attached_port(port_ptr);
+ return (HBA_STATUS_ERROR);
+ }
+ }
+
+ /* get TargetLun(SAM-LUN). */
+ if (di_prop_lookup_int64(DDI_DEV_T_ANY, node, "lun64",
+ &propInt64Data) != -1) {
+ samLun = scsi_lun64_to_lun(*propInt64Data);
+ (void) memcpy(&mapping_ptr->entry.PortLun.TargetLun,
+ &samLun, 8);
+ } else {
+ log(LOG_DEBUG, "get_attached_devices_info",
+ "No lun64 prop found on device %s.", fullpath);
+ di_devfs_path_free(devpath);
+ free_attached_port(port_ptr);
+ return (HBA_STATUS_ERROR);
+ }
+
+ if (di_prop_lookup_ints(DDI_DEV_T_ANY, node,
+ "target", &propIntData) != -1) {
+ mapping_ptr->entry.ScsiId.ScsiTargetNumber = *propIntData;
+ } else {
+ mapping_ptr->entry.ScsiId.ScsiTargetNumber = di_instance(node);
+ }
+
+ /* get ScsiBusNumber */
+ mapping_ptr->entry.ScsiId.ScsiBusNumber = port_ptr->cntlNumber;
+
+ (void) memcpy(mapping_ptr->entry.PortLun.PortWWN.wwn,
+ SASAddress.wwn, 8);
+
+ /* Store the devices path for now. We'll convert to /dev later */
+ get_minor(devpath, minorname);
+ (void) snprintf(mapping_ptr->entry.ScsiId.OSDeviceName,
+ sizeof (mapping_ptr->entry.ScsiId.OSDeviceName),
+ "%s%s%s", DEVICES_DIR, devpath, minorname);
+
+ count = di_prop_lookup_bytes(DDI_DEV_T_ANY, node, "inquiry-page-83",
+ (uchar_t **)&propByteData);
+ if (count < 0) {
+ get_luid(mapping_ptr->entry.ScsiId.OSDeviceName,
+ mapping_ptr->entry.LUID.buffer);
+ } else {
+ for (i = 0, charptr = mapping_ptr->entry.LUID.buffer; i < count;
+ i++, charptr += 2) {
+ (void) sprintf(charptr, "%02x", propByteData[i]);
+ }
+ *charptr = '\0';
+ }
+
+ if (disco_port_ptr->scsiInfo == NULL) {
+ disco_port_ptr->scsiInfo = mapping_ptr;
+ } else {
+ mapping_ptr->next = disco_port_ptr->scsiInfo;
+ disco_port_ptr->scsiInfo = mapping_ptr;
+ }
+
+ di_devfs_path_free(devpath);
+
+ return (HBA_STATUS_OK);
+}
+
+/*
+ * Finds attached device(target) from pathinfo node.
+ */
+static HBA_STATUS
+get_attached_paths_info(di_path_t path, struct sun_sas_port *port_ptr)
+{
+ char ROUTINE[] = "get_attached_paths_info";
+ char *propStringData = NULL;
+ int *propIntData = NULL;
+ int64_t *propInt64Data = NULL;
+ scsi_lun_t samLun;
+ char *unit_address;
+ char *charptr;
+ char *clientdevpath = NULL;
+ char *pathdevpath = NULL;
+ char fullpath[MAXPATHLEN+1];
+ char minorname[MAXNAMELEN+1];
+ struct ScsiEntryList *mapping_ptr;
+ HBA_WWN SASAddress, AttachedSASAddress;
+ struct sun_sas_port *disco_port_ptr;
+ di_path_state_t state = 0;
+ di_node_t clientnode;
+ int portfound, size;
+ int port_state = HBA_PORTSTATE_ONLINE;
+ uint64_t tmpAddr;
+
+ if (port_ptr == NULL) {
+ log(LOG_DEBUG, ROUTINE, "NULL port_ptr argument");
+ return (HBA_STATUS_ERROR);
+ }
+
+ /* if not null, free before return. */
+ pathdevpath = di_path_devfs_path(path);
+
+ state = di_path_state(path);
+ /* when node is not attached and online, set the state to offline. */
+ if ((state == DI_PATH_STATE_OFFLINE) ||
+ (state == DI_PATH_STATE_FAULT)) {
+ log(LOG_DEBUG, ROUTINE,
+ "path node (%s) is either OFFLINE or FAULT state",
+ pathdevpath ? pathdevpath : "(missing device path)");
+ port_state = HBA_PORTSTATE_OFFLINE;
+ }
+
+ if (clientnode = di_path_client_node(path)) {
+ if (di_retired(clientnode)) {
+ log(LOG_DEBUG, ROUTINE,
+ "client node of path (%s) is retired. Skipping.",
+ pathdevpath ? pathdevpath :
+ "(missing device path)");
+ if (pathdevpath) di_devfs_path_free(pathdevpath);
+ return (HBA_STATUS_OK);
+ }
+ if ((clientdevpath = di_devfs_path(clientnode)) == NULL) {
+ log(LOG_DEBUG, ROUTINE,
+ "Client device of path (%s) has no path. Skipping.",
+ pathdevpath ? pathdevpath :
+ "(missing device path)");
+ if (pathdevpath) di_devfs_path_free(pathdevpath);
+ return (HBA_STATUS_ERROR);
+ }
+ } else {
+ log(LOG_DEBUG, ROUTINE,
+ "Failed to get client device from a path (%s).",
+ pathdevpath ? pathdevpath :
+ "(missing device path)");
+ if (pathdevpath) di_devfs_path_free(pathdevpath);
+ return (HBA_STATUS_ERROR);
+ }
+
+ /* add the "/devices" in the begining and the :devctl at the end */
+ (void) snprintf(fullpath, sizeof (fullpath), "%s%s", DEVICES_DIR,
+ clientdevpath);
+
+ (void) memset(&SASAddress, 0, sizeof (SASAddress));
+ if ((unit_address = di_path_bus_addr(path)) != NULL) {
+ if ((charptr = strchr(unit_address, ',')) != NULL) {
+ *charptr = '\0';
+ }
+ for (charptr = unit_address; *charptr != '\0'; charptr++) {
+ if (isxdigit(*charptr)) {
+ break;
+ }
+ }
+ if (charptr != '\0') {
+ tmpAddr = htonll(strtoll(charptr, NULL, 16));
+ (void) memcpy(&SASAddress.wwn[0], &tmpAddr, 8);
+ } else {
+ log(LOG_DEBUG, ROUTINE,
+ "No proper target port info on unit address of "
+ "path (%s).", pathdevpath ? pathdevpath :
+ "(missing device path)");
+ if (pathdevpath) di_devfs_path_free(pathdevpath);
+ di_devfs_path_free(clientdevpath);
+ return (HBA_STATUS_ERROR);
+ }
+ } else {
+ log(LOG_DEBUG, ROUTINE, "Fail to get unit address of path(%s).",
+ "path (%s).", pathdevpath ? pathdevpath :
+ "(missing device path)");
+ if (pathdevpath) di_devfs_path_free(pathdevpath);
+ di_devfs_path_free(clientdevpath);
+ return (HBA_STATUS_ERROR);
+ }
+
+ (void) memset(&AttachedSASAddress, 0, sizeof (AttachedSASAddress));
+ if (di_path_prop_lookup_strings(path, "attached-port",
+ &propStringData) != -1) {
+ for (charptr = propStringData; *charptr != '\0'; charptr++) {
+ if (isxdigit(*charptr)) {
+ break;
+ }
+ }
+ if (*charptr != '\0') {
+ tmpAddr = htonll(strtoll(charptr, NULL, 16));
+ (void) memcpy(AttachedSASAddress.wwn, &tmpAddr, 8);
+ /* check the attached address of hba port. */
+ if (memcmp(port_ptr->port_attributes.
+ PortSpecificAttribute.SASPort->
+ LocalSASAddress.wwn, &tmpAddr, 8) == 0) {
+ if (wwnConversion(port_ptr->port_attributes.
+ PortSpecificAttribute.SASPort->
+ AttachedSASAddress.wwn)) {
+ /* verify the attaached SAS Addr. */
+ if (memcmp(port_ptr->port_attributes.
+ PortSpecificAttribute.SASPort->
+ AttachedSASAddress.wwn,
+ SASAddress.wwn, 8) != 0) {
+ /* indentation move begin. */
+ log(LOG_DEBUG, ROUTINE,
+ "iport attached-port(%016llx) do not"
+ " match with level 1 Local"
+ " SAS address(%016llx).",
+ wwnConversion(port_ptr->port_attributes.
+ PortSpecificAttribute.
+ SASPort->AttachedSASAddress.wwn),
+ wwnConversion(SASAddress.wwn));
+ if (pathdevpath)
+ di_devfs_path_free(pathdevpath);
+ di_devfs_path_free(clientdevpath);
+ free_attached_port(port_ptr);
+ return (HBA_STATUS_ERROR);
+ /* indentation move ends. */
+ }
+ } else {
+ /* store the Attaached SAS Addr. */
+ (void) memcpy(port_ptr->port_attributes.
+ PortSpecificAttribute.
+ SASPort->AttachedSASAddress.wwn,
+ &SASAddress.wwn[0], 8);
+ }
+ }
+ } else {
+ log(LOG_DEBUG, ROUTINE,
+ "No proper attached SAS address value of path (%s)",
+ pathdevpath ? pathdevpath :
+ "(missing device path)");
+ if (pathdevpath) di_devfs_path_free(pathdevpath);
+ di_devfs_path_free(clientdevpath);
+ free_attached_port(port_ptr);
+ return (HBA_STATUS_ERROR);
+ }
+ } else {
+ log(LOG_DEBUG, ROUTINE,
+ "Property attached-port not found for path (%s)",
+ pathdevpath ? pathdevpath :
+ "(missing device path)");
+ if (pathdevpath) di_devfs_path_free(pathdevpath);
+ di_devfs_path_free(clientdevpath);
+ free_attached_port(port_ptr);
+ return (HBA_STATUS_ERROR);
+ }
+
+ /*
+ * walk the disco list to make sure that there isn't a matching
+ * port and node wwn or a matching device path
+ */
+ portfound = 0;
+ for (disco_port_ptr = port_ptr->first_attached_port;
+ disco_port_ptr != NULL;
+ disco_port_ptr = disco_port_ptr->next) {
+ if ((disco_port_ptr->port_attributes.PortState !=
+ HBA_PORTSTATE_ERROR) &&
+ (memcmp(disco_port_ptr->port_attributes.
+ PortSpecificAttribute.SASPort->LocalSASAddress.wwn,
+ SASAddress.wwn, 8) == 0)) {
+ /*
+ * found matching disco_port
+ * look for matching device path
+ */
+ portfound = 1;
+ for (mapping_ptr = disco_port_ptr->scsiInfo;
+ mapping_ptr != NULL;
+ mapping_ptr = mapping_ptr->next) {
+ if (strstr(mapping_ptr-> entry.ScsiId.
+ OSDeviceName, clientdevpath) != 0) {
+ log(LOG_DEBUG, ROUTINE,
+ "Found an already discovered "
+ "device %s.", clientdevpath);
+ if (pathdevpath)
+ di_devfs_path_free(pathdevpath);
+ di_devfs_path_free(clientdevpath);
+ return (HBA_STATUS_OK);
+ }
+ }
+ if (portfound == 1) {
+ break;
+ }
+ }
+ }
+
+ if (portfound == 0) {
+ /*
+ * there are no matching SAS address.
+ * this must be a new device
+ */
+ if ((disco_port_ptr = (struct sun_sas_port *)calloc(1,
+ sizeof (struct sun_sas_port))) == NULL) {
+ OUT_OF_MEMORY(ROUTINE);
+ if (pathdevpath) di_devfs_path_free(pathdevpath);
+ di_devfs_path_free(clientdevpath);
+ free_attached_port(port_ptr);
+ return (HBA_STATUS_ERROR);
+ }
+
+ if ((disco_port_ptr->port_attributes.PortSpecificAttribute.\
+ SASPort = (struct SMHBA_SAS_Port *)calloc(1,
+ sizeof (struct SMHBA_SAS_Port))) == NULL) {
+ OUT_OF_MEMORY("add_hba_port_info");
+ if (pathdevpath) di_devfs_path_free(pathdevpath);
+ di_devfs_path_free(clientdevpath);
+ free_attached_port(port_ptr);
+ return (HBA_STATUS_ERROR);
+ }
+
+ (void) memcpy(disco_port_ptr->port_attributes.
+ PortSpecificAttribute.
+ SASPort->LocalSASAddress.wwn, SASAddress.wwn, 8);
+ (void) memcpy(disco_port_ptr->port_attributes.
+ PortSpecificAttribute.
+ SASPort->AttachedSASAddress.wwn, AttachedSASAddress.wwn, 8);
+
+ /* Default to unknown until we figure out otherwise */
+ if (di_path_prop_lookup_strings(path, "variant",
+ &propStringData) != -1) {
+ if ((strcmp(propStringData, "sata") == 0) ||
+ (strcmp(propStringData, "atapi") == 0)) {
+ disco_port_ptr->port_attributes.PortType =
+ HBA_PORTTYPE_SATADEVICE;
+ disco_port_ptr->port_attributes.\
+ PortSpecificAttribute.SASPort->PortProtocol
+ = HBA_SASPORTPROTOCOL_SATA;
+ } else {
+ log(LOG_DEBUG, ROUTINE,
+ "Unexpected variant prop value %s found on",
+ " path (%s)", propStringData,
+ pathdevpath ? pathdevpath :
+ "(missing device path)");
+ /*
+ * Port type will be 0
+ * which is not valid type.
+ */
+ }
+ } else {
+ disco_port_ptr->port_attributes.PortType =
+ HBA_PORTTYPE_SASDEVICE;
+ disco_port_ptr->port_attributes.PortSpecificAttribute.\
+ SASPort->PortProtocol = HBA_SASPORTPROTOCOL_SSP;
+ }
+
+ if (disco_port_ptr->port_attributes.OSDeviceName[0] == '\0') {
+ /* indentation change due to ctysle check on sizeof. */
+ size = sizeof (disco_port_ptr->port_attributes.OSDeviceName);
+ if (pathdevpath != NULL) {
+ (void) strlcpy(disco_port_ptr->port_attributes.
+ OSDeviceName, pathdevpath, size);
+ }
+ }
+
+ /* add new discovered port into the list */
+ if (port_ptr->first_attached_port == NULL) {
+ port_ptr->first_attached_port = disco_port_ptr;
+ disco_port_ptr->index = 0;
+ port_ptr->port_attributes.PortSpecificAttribute.\
+ SASPort->NumberofDiscoveredPorts = 1;
+ } else {
+ disco_port_ptr->next = port_ptr->first_attached_port;
+ port_ptr->first_attached_port = disco_port_ptr;
+ disco_port_ptr->index = port_ptr->port_attributes.\
+ PortSpecificAttribute.\
+ SASPort->NumberofDiscoveredPorts;
+ port_ptr->port_attributes.PortSpecificAttribute.\
+ SASPort->NumberofDiscoveredPorts++;
+ }
+ disco_port_ptr->port_attributes.PortState = port_state;
+ }
+
+ if ((mapping_ptr = (struct ScsiEntryList *)calloc
+ (1, sizeof (struct ScsiEntryList))) == NULL) {
+ OUT_OF_MEMORY(ROUTINE);
+ if (pathdevpath) di_devfs_path_free(pathdevpath);
+ di_devfs_path_free(clientdevpath);
+ free_attached_port(port_ptr);
+ return (HBA_STATUS_ERROR);
+ }
+
+ if (di_path_prop_lookup_ints(path, "lun", &propIntData) != -1) {
+ mapping_ptr->entry.ScsiId.ScsiOSLun = *propIntData;
+ } else {
+ if ((charptr = strchr(unit_address, ',')) != NULL) {
+ charptr++;
+ mapping_ptr->entry.ScsiId.ScsiOSLun =
+ strtoull(charptr, NULL, 10);
+ } else {
+ log(LOG_DEBUG, ROUTINE,
+ "Failed to get LUN from unit address of path(%s).",
+ pathdevpath ? pathdevpath :
+ "(missing device path)");
+ if (pathdevpath) di_devfs_path_free(pathdevpath);
+ di_devfs_path_free(clientdevpath);
+ free_attached_port(port_ptr);
+ return (HBA_STATUS_ERROR);
+ }
+ }
+
+ /* Get TargetLun(SAM LUN). */
+ if (di_path_prop_lookup_int64s(path, "lun64", &propInt64Data) != -1) {
+ samLun = scsi_lun64_to_lun(*propInt64Data);
+ (void) memcpy(&mapping_ptr->entry.PortLun.TargetLun,
+ &samLun, 8);
+ } else {
+ log(LOG_DEBUG, ROUTINE, "No lun64 prop found on path (%s)",
+ pathdevpath ? pathdevpath :
+ "(missing device path)");
+ if (pathdevpath) di_devfs_path_free(pathdevpath);
+ di_devfs_path_free(clientdevpath);
+ free_attached_port(port_ptr);
+ return (HBA_STATUS_ERROR);
+ }
+
+ if (di_path_prop_lookup_ints(path, "target", &propIntData) != -1) {
+ mapping_ptr->entry.ScsiId.ScsiTargetNumber = *propIntData;
+ } else {
+ mapping_ptr->entry.ScsiId.ScsiTargetNumber =
+ di_path_instance(path);
+ }
+
+ /* get ScsiBusNumber */
+ mapping_ptr->entry.ScsiId.ScsiBusNumber = port_ptr->cntlNumber;
+
+ (void) memcpy(mapping_ptr->entry.PortLun.PortWWN.wwn,
+ SASAddress.wwn, 8);
+
+ /* Store the devices path for now. We'll convert to /dev later */
+ get_minor(clientdevpath, minorname);
+ (void) snprintf(mapping_ptr->entry.ScsiId.OSDeviceName,
+ sizeof (mapping_ptr->entry.ScsiId.OSDeviceName),
+ "%s%s%s", DEVICES_DIR, clientdevpath, minorname);
+
+ /* get luid. */
+ if (di_prop_lookup_strings(DDI_DEV_T_ANY, clientnode,
+ "client-guid", &propStringData) != -1) {
+ (void) strlcpy(mapping_ptr->entry.LUID.buffer, propStringData,
+ sizeof (mapping_ptr->entry.LUID.buffer));
+ } else {
+ log(LOG_DEBUG, ROUTINE, "No client-guid prop found on path(%s)",
+ pathdevpath ? pathdevpath :
+ "(missing device path)");
+ if (pathdevpath) di_devfs_path_free(pathdevpath);
+ di_devfs_path_free(clientdevpath);
+ free_attached_port(port_ptr);
+ return (HBA_STATUS_ERROR);
+ }
+
+ if (disco_port_ptr->scsiInfo == NULL) {
+ disco_port_ptr->scsiInfo = mapping_ptr;
+ } else {
+ mapping_ptr->next = disco_port_ptr->scsiInfo;
+ disco_port_ptr->scsiInfo = mapping_ptr;
+ }
+
+ if (pathdevpath) di_devfs_path_free(pathdevpath);
+ di_devfs_path_free(clientdevpath);
+
+ return (HBA_STATUS_OK);
+}
+
+/*
+ * walks the devinfo tree retrieving all hba information
+ */
+extern HBA_STATUS
+devtree_attached_devices(di_node_t node, struct sun_sas_port *port_ptr)
+{
+ const char ROUTINE[] = "devtree_attached_devices";
+ di_node_t nodechild = DI_NODE_NIL;
+ di_path_t path = DI_PATH_NIL;
+
+ /* child should be device */
+ if ((nodechild = di_child_node(node)) == DI_NODE_NIL) {
+ log(LOG_DEBUG, ROUTINE,
+ "No devinfo child on the HBA port node.");
+ }
+
+ if ((path = di_path_phci_next_path(node, path)) ==
+ DI_PATH_NIL) {
+ log(LOG_DEBUG, ROUTINE,
+ "No pathinfo node on the HBA port node.");
+ }
+
+ if ((nodechild == DI_NODE_NIL) && (path == DI_PATH_NIL)) {
+ return (HBA_STATUS_OK);
+ }
+
+ while (nodechild != DI_NODE_NIL) {
+ if (get_attached_devices_info(nodechild, port_ptr)
+ != HBA_STATUS_OK) {
+ break;
+ }
+ nodechild = di_sibling_node(nodechild);
+ }
+
+
+ while (path != DI_PATH_NIL) {
+ if (get_attached_paths_info(path, port_ptr)
+ != HBA_STATUS_OK) {
+ break;
+ }
+ path = di_path_phci_next_path(node, path);
+ }
+
+ return (HBA_STATUS_OK);
+}
diff --git a/usr/src/lib/sun_sas/common/devtree_hba_disco.c b/usr/src/lib/sun_sas/common/devtree_hba_disco.c
new file mode 100644
index 0000000000..bd3ff0898c
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/devtree_hba_disco.c
@@ -0,0 +1,634 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+
+#include <sun_sas.h>
+#include <sys/modctl.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <inttypes.h>
+#include <ctype.h>
+
+/* free hba port info for the given hba */
+static void
+free_hba_port(struct sun_sas_hba *hba_ptr)
+{
+ struct sun_sas_port *hba_port = NULL;
+ struct sun_sas_port *last_hba_port = NULL;
+ struct sun_sas_port *tgt_port = NULL;
+ struct sun_sas_port *last_tgt_port = NULL;
+ struct ScsiEntryList *scsi_info = NULL;
+ struct ScsiEntryList *last_scsi_info = NULL;
+ struct phy_info *phy_ptr = NULL;
+ struct phy_info *last_phy = NULL;
+
+ /* Free the nested structures (port and attached port) */
+ hba_port = hba_ptr->first_port;
+ while (hba_port != NULL) {
+ /* Free discovered port structure list. */
+ tgt_port = hba_port->first_attached_port;
+ while (tgt_port != NULL) {
+ /* Free target mapping data list first. */
+ scsi_info = tgt_port->scsiInfo;
+ while (scsi_info != NULL) {
+ last_scsi_info = scsi_info;
+ scsi_info = scsi_info->next;
+ free(last_scsi_info);
+ }
+ last_tgt_port = tgt_port;
+ tgt_port = tgt_port->next;
+ free(last_tgt_port->port_attributes.\
+ PortSpecificAttribute.SASPort);
+ free(last_tgt_port);
+ }
+ hba_port->first_attached_port = NULL;
+
+ phy_ptr = hba_port->first_phy;
+ while (phy_ptr != NULL) {
+ last_phy = phy_ptr;
+ phy_ptr = phy_ptr->next;
+ free(last_phy);
+ }
+ hba_port->first_phy = NULL;
+
+ last_hba_port = hba_port;
+ hba_port = hba_port->next;
+ free(last_hba_port->port_attributes.\
+ PortSpecificAttribute.SASPort);
+ free(last_hba_port);
+ }
+
+ hba_ptr->first_port = NULL;
+}
+
+/*
+ * Internal routine for adding an HBA port
+ */
+static HBA_STATUS
+add_hba_port_info(di_node_t portNode, struct sun_sas_hba *hba_ptr, int protocol)
+{
+ const char ROUTINE[] = "add_hba_port_info";
+ struct sun_sas_port *port_ptr;
+ char *portDevpath;
+ int *propIntData;
+ char *propStringData;
+ uint64_t tmpAddr;
+ char *charptr, cntlLink[MAXPATHLEN] = {'\0'};
+ int rval;
+ uint_t state = HBA_PORTSTATE_UNKNOWN;
+
+ if (hba_ptr == NULL) {
+ log(LOG_DEBUG, ROUTINE,
+ "Sun_sas handle ptr set to NULL.");
+ return (HBA_STATUS_ERROR_ARG);
+ }
+
+ if ((port_ptr = (struct sun_sas_port *)calloc(1,
+ sizeof (struct sun_sas_port))) == NULL) {
+ OUT_OF_MEMORY(ROUTINE);
+ return (HBA_STATUS_ERROR);
+ }
+
+ if ((port_ptr->port_attributes.PortSpecificAttribute.SASPort =
+ (struct SMHBA_SAS_Port *)calloc(1, sizeof (struct SMHBA_SAS_Port)))
+ == NULL) {
+ OUT_OF_MEMORY(ROUTINE);
+ return (HBA_STATUS_ERROR);
+ }
+
+ if ((portDevpath = di_devfs_path(portNode)) == NULL) {
+ log(LOG_DEBUG, ROUTINE,
+ "Unable to get device path from HBA Port Node.");
+ S_FREE(port_ptr->port_attributes.PortSpecificAttribute.SASPort);
+ S_FREE(port_ptr);
+ return (HBA_STATUS_ERROR);
+ }
+
+ state = di_state(portNode);
+ if (((state & DI_DRIVER_DETACHED) == DI_DRIVER_DETACHED) ||
+ ((state & DI_DEVICE_OFFLINE) == DI_DEVICE_OFFLINE)) {
+ log(LOG_DEBUG, ROUTINE,
+ "HBA port node %s is either OFFLINE or DETACHED",
+ portDevpath);
+ port_ptr->port_attributes.PortState = HBA_PORTSTATE_OFFLINE;
+ } else {
+ port_ptr->port_attributes.PortState = HBA_PORTSTATE_ONLINE;
+ }
+
+ port_ptr->port_attributes.PortType = HBA_PORTTYPE_SASDEVICE;
+
+ (void) strlcpy(port_ptr->device_path, portDevpath, MAXPATHLEN + 1);
+
+ if (lookupControllerLink(portDevpath, (char *)cntlLink) ==
+ HBA_STATUS_OK) {
+ (void) strlcpy(port_ptr->port_attributes.OSDeviceName, cntlLink,
+ sizeof (port_ptr->port_attributes.OSDeviceName));
+ if ((charptr = strrchr(cntlLink, '/')) != NULL) {
+ charptr++;
+ }
+ if (charptr[0] == 'c') {
+ port_ptr->cntlNumber = atoi(++charptr);
+ } else {
+ port_ptr->cntlNumber = -1;
+ }
+ } else {
+ (void) snprintf(port_ptr->port_attributes.OSDeviceName,
+ sizeof (port_ptr->port_attributes.OSDeviceName),
+ "%s%s%s", DEVICES_DIR, portDevpath, SCSI_SUFFIX);
+ }
+
+ di_devfs_path_free(portDevpath);
+
+ port_ptr->port_attributes.PortSpecificAttribute.
+ SASPort->PortProtocol = protocol;
+
+ rval = di_prop_lookup_strings(DDI_DEV_T_ANY, portNode,
+ "initiator-port", &propStringData);
+ if (rval < 0) {
+ log(LOG_DEBUG, ROUTINE,
+ "Unable to get initiator-port from HBA port node %s.",
+ port_ptr->port_attributes.OSDeviceName);
+ S_FREE(port_ptr->port_attributes.PortSpecificAttribute.SASPort);
+ S_FREE(port_ptr);
+ return (HBA_STATUS_ERROR);
+ } else {
+ for (charptr = propStringData; *charptr != '\0'; charptr++) {
+ if (isxdigit(*charptr)) {
+ break;
+ }
+ }
+ if (*charptr != '\0') {
+ tmpAddr = htonll(strtoll(charptr, NULL, 16));
+ (void) memcpy(port_ptr->port_attributes.
+ PortSpecificAttribute.SASPort->LocalSASAddress.wwn,
+ &tmpAddr, 8);
+ } else {
+ log(LOG_DEBUG, ROUTINE,
+ "No proper intiator-port prop value on HBA port %s",
+ port_ptr->port_attributes.OSDeviceName);
+ }
+ }
+
+ rval = di_prop_lookup_strings(DDI_DEV_T_ANY, portNode,
+ "attached-port", &propStringData);
+ if (rval < 0) {
+ log(LOG_DEBUG, ROUTINE,
+ "Unable to get attached-port from HBA port node %s.",
+ port_ptr->port_attributes.OSDeviceName);
+ S_FREE(port_ptr->port_attributes.PortSpecificAttribute.SASPort);
+ S_FREE(port_ptr);
+ return (HBA_STATUS_ERROR);
+ } else {
+ for (charptr = propStringData; *charptr != '\0'; charptr++) {
+ if (isxdigit(*charptr)) {
+ break;
+ }
+ }
+ if (*charptr != '\0') {
+ tmpAddr = htonll(strtoll(charptr, NULL, 16));
+ (void) memcpy(port_ptr->port_attributes.
+ PortSpecificAttribute.SASPort->
+ AttachedSASAddress.wwn, &tmpAddr, 8);
+ } else {
+ /* continue even if the attached port is NULL. */
+ log(LOG_DEBUG, ROUTINE,
+ "No proper attached-port prop value: "
+ "HBA port Local SAS Address(%016llx)",
+ wwnConversion(port_ptr->port_attributes.
+ PortSpecificAttribute.
+ SASPort->LocalSASAddress.wwn));
+ }
+ }
+
+ rval = di_prop_lookup_ints(DDI_DEV_T_ANY, portNode,
+ "num-phys", &propIntData);
+ if (rval < 0) {
+ log(LOG_DEBUG, ROUTINE,
+ "Unable to get NumberofPhys from HBA port %s.",
+ port_ptr->port_attributes.OSDeviceName);
+ S_FREE(port_ptr->port_attributes.PortSpecificAttribute.SASPort);
+ S_FREE(port_ptr);
+ return (HBA_STATUS_ERROR);
+ } else {
+ port_ptr->port_attributes.PortSpecificAttribute.\
+ SASPort->NumberofPhys = *propIntData;
+ }
+
+ if (port_ptr->port_attributes.PortSpecificAttribute.\
+ SASPort->NumberofPhys > 0) {
+ if (get_phy_info(portNode, port_ptr) != HBA_STATUS_OK) {
+ log(LOG_DEBUG, ROUTINE,
+ "Failed to get phy info on HBA port %s.",
+ port_ptr->port_attributes.OSDeviceName);
+ S_FREE(port_ptr->port_attributes.
+ PortSpecificAttribute.SASPort);
+ S_FREE(port_ptr);
+ }
+ }
+
+ /* devtree_attached_devices(portSubtreenode, port_ptr); */
+ if (devtree_attached_devices(portNode, port_ptr) != HBA_STATUS_OK) {
+ log(LOG_DEBUG, ROUTINE,
+ "Failed to get attached device info HBA port %s.",
+ port_ptr->port_attributes.OSDeviceName);
+ S_FREE(port_ptr->port_attributes.PortSpecificAttribute.SASPort);
+ S_FREE(port_ptr);
+ }
+
+ fillDomainPortWWN(port_ptr);
+
+ /* add new port onto hba handle list */
+ if (hba_ptr->first_port == NULL) {
+ port_ptr->index = 0;
+ hba_ptr->first_port = port_ptr;
+ } else {
+ port_ptr->index = hba_ptr->first_port->index + 1;
+ port_ptr->next = hba_ptr->first_port;
+ hba_ptr->first_port = port_ptr;
+ }
+
+ return (HBA_STATUS_OK);
+}
+
+HBA_STATUS
+refresh_hba(di_node_t hbaNode, struct sun_sas_hba *hba_ptr)
+{
+ const char ROUTINE[] = "refresh_hba";
+ di_node_t portNode;
+ int protocol = 0;
+ int *propIntData;
+
+ /*
+ * clean up existing hba port, discovered target, phy info.
+ * leave open handles intact.
+ */
+ free_hba_port(hba_ptr);
+
+ if ((portNode = di_child_node(hbaNode)) == NULL) {
+ log(LOG_DEBUG, ROUTINE,
+ "HBA node doesn't have iport child.");
+ return (HBA_STATUS_ERROR);
+ }
+
+ if ((di_prop_lookup_ints(DDI_DEV_T_ANY, hbaNode,
+ "supported-protocol", &propIntData)) == -1) {
+ log(LOG_DEBUG, ROUTINE,
+ "Unable to get supported-protocol from HBA node.");
+ } else {
+ protocol = *propIntData;
+ }
+
+ while (portNode != DI_NODE_NIL) {
+ if (add_hba_port_info(portNode, hba_ptr, protocol)
+ == HBA_STATUS_ERROR) {
+ S_FREE(hba_ptr->first_port);
+ S_FREE(hba_ptr);
+ return (HBA_STATUS_ERROR);
+ }
+ portNode = di_sibling_node(portNode);
+ }
+
+ return (HBA_STATUS_OK);
+}
+
+/*
+ * Discover information for one HBA in the device tree.
+ * The di_node_t argument should be a node with smhba-supported prop set
+ * to true.
+ * Without iport support, the devinfo node will represent one port hba.
+ * This routine assumes the locks have been taken.
+ */
+HBA_STATUS
+devtree_get_one_hba(di_node_t hbaNode)
+{
+ const char ROUTINE[] = "devtree_get_one_hba";
+ char *propdata = NULL;
+ int *propIntData = NULL;
+ struct sun_sas_hba *new_hba, *hba_ptr;
+ char *hbaDevpath, *hba_driver;
+ int protocol = 0;
+ di_node_t portNode;
+ int hba_instance = -1;
+
+ hba_instance = di_instance(hbaNode);
+ if (hba_instance == -1) {
+ log(LOG_DEBUG, ROUTINE,
+ "portNode has instance of -1");
+ return (DI_WALK_CONTINUE);
+ }
+
+ if ((hbaDevpath = di_devfs_path(hbaNode)) == NULL) {
+ log(LOG_DEBUG, ROUTINE, "Unable to get "
+ "device path from hbaNode");
+ return (HBA_STATUS_ERROR);
+ }
+
+ /* check to see if this is a repeat HBA */
+ if (global_hba_head) {
+ for (hba_ptr = global_hba_head;
+ hba_ptr != NULL;
+ hba_ptr = hba_ptr->next) {
+ if ((strncmp(hba_ptr->device_path, hbaDevpath,
+ strlen(hbaDevpath))) == 0) {
+ if (refresh_hba(hbaNode, hba_ptr) !=
+ HBA_STATUS_OK) {
+ log(LOG_DEBUG, ROUTINE, "Refresh failed"
+ " on hbaNode %s", hbaDevpath);
+ }
+ di_devfs_path_free(hbaDevpath);
+ return (HBA_STATUS_OK);
+ }
+ }
+ }
+
+ /* this is a new hba */
+ if ((new_hba = (struct sun_sas_hba *)calloc(1,
+ sizeof (struct sun_sas_hba))) == NULL) {
+ OUT_OF_MEMORY(ROUTINE);
+ di_devfs_path_free(hbaDevpath);
+ return (HBA_STATUS_ERROR);
+ }
+
+ (void) strlcpy(new_hba->device_path, hbaDevpath,
+ sizeof (new_hba->device_path));
+ di_devfs_path_free(hbaDevpath);
+
+ (void) snprintf(new_hba->adapter_attributes.HBASymbolicName,
+ sizeof (new_hba->adapter_attributes.HBASymbolicName),
+ "%s%s", DEVICES_DIR, new_hba->device_path);
+
+ /* Manufacturer */
+ if ((di_prop_lookup_strings(DDI_DEV_T_ANY, hbaNode,
+ "Manufacturer", (char **)&propdata)) == -1) {
+ (void) strlcpy(new_hba->adapter_attributes.Manufacturer,
+ SUN_MICROSYSTEMS,
+ sizeof (new_hba->adapter_attributes.Manufacturer));
+ } else {
+ (void) strlcpy(new_hba->adapter_attributes.Manufacturer,
+ propdata,
+ sizeof (new_hba->adapter_attributes.Manufacturer));
+ }
+
+ /* SerialNumber */
+ if ((di_prop_lookup_strings(DDI_DEV_T_ANY, hbaNode,
+ "SerialNumber", (char **)&propdata)) == -1) {
+ new_hba->adapter_attributes.SerialNumber[0] = '\0';
+ } else {
+ (void) strlcpy(new_hba->adapter_attributes.SerialNumber,
+ propdata,
+ sizeof (new_hba->adapter_attributes.SerialNumber));
+ }
+
+ /* Model */
+ if ((di_prop_lookup_strings(DDI_DEV_T_ANY, hbaNode,
+ "ModelName", (char **)&propdata)) == -1) {
+ new_hba->adapter_attributes.Model[0] = '\0';
+ } else {
+ (void) strlcpy(new_hba->adapter_attributes.Model,
+ propdata,
+ sizeof (new_hba->adapter_attributes.Model));
+ }
+
+ /* FirmwareVersion */
+ if ((di_prop_lookup_strings(DDI_DEV_T_ANY, hbaNode,
+ "firmware-version", (char **)&propdata)) == -1) {
+ log(LOG_DEBUG, ROUTINE,
+ "Property \"%s\" not found for device \"%s\"",
+ "firmware-version", new_hba->device_path);
+ } else {
+ (void) strlcpy(new_hba->adapter_attributes.FirmwareVersion,
+ propdata,
+ sizeof (new_hba->adapter_attributes.FirmwareVersion));
+ }
+
+ /* HardwareVersion */
+ if ((di_prop_lookup_strings(DDI_DEV_T_ANY, hbaNode,
+ "hardware-version", (char **)&propdata)) == -1) {
+ log(LOG_DEBUG, ROUTINE,
+ "Property \"%s\" not found for device \"%s\"",
+ "hardware-version", new_hba->device_path);
+ } else {
+ (void) strlcpy(new_hba->adapter_attributes.HardwareVersion,
+ propdata,
+ sizeof (new_hba->adapter_attributes.HardwareVersion));
+ }
+
+ /* DriverVersion */
+ if ((di_prop_lookup_strings(DDI_DEV_T_ANY, hbaNode,
+ "driver-version", (char **)&propdata)) == -1) {
+ log(LOG_DEBUG, ROUTINE,
+ "Property \"%s\" not found for device \"%s\"",
+ "driver-version", new_hba->device_path);
+ } else {
+ (void) strlcpy(new_hba->adapter_attributes.DriverVersion,
+ propdata,
+ sizeof (new_hba->adapter_attributes.DriverVersion));
+ }
+
+ if ((di_prop_lookup_ints(DDI_DEV_T_ANY, hbaNode,
+ "supported-protocol", &propIntData)) == -1) {
+ log(LOG_DEBUG, ROUTINE,
+ "Unable to get supported-protocol from HBA node.");
+ } else {
+ protocol = *propIntData;
+ }
+
+ /* We don't use these */
+ new_hba->adapter_attributes.OptionROMVersion[0] = '\0';
+ new_hba->adapter_attributes.RedundantOptionROMVersion[0] = '\0';
+ new_hba->adapter_attributes.RedundantFirmwareVersion[0] = '\0';
+ new_hba->adapter_attributes.VendorSpecificID = 0;
+
+ if ((hba_driver = di_driver_name(hbaNode)) != NULL) {
+ (void) strlcpy(new_hba->adapter_attributes.DriverName,
+ hba_driver,
+ sizeof (new_hba->adapter_attributes.DriverName));
+ } else {
+ log(LOG_DEBUG, ROUTINE,
+ "HBA driver name not found for device \"%s\"",
+ new_hba->device_path);
+ }
+
+ /*
+ * Name the adapter: like SUNW-pmcs-1
+ * Using di_instance number as the suffix for the name for persistent
+ * among rebooting.
+ */
+ (void) snprintf(new_hba->handle_name, HANDLE_NAME_LENGTH, "%s-%s-%d",
+ "SUNW", new_hba->adapter_attributes.DriverName, hba_instance);
+
+ if ((portNode = di_child_node(hbaNode)) == NULL) {
+ log(LOG_DEBUG, ROUTINE,
+ "HBA driver doesn't have iport child. \"%s\"",
+ new_hba->device_path);
+ /* continue on with an hba without any port. */
+ new_hba->index = hba_count++;
+
+ /*
+ * add newly created handle into global_hba_head list
+ */
+ if (global_hba_head != NULL) {
+ /*
+ * Make sure to move the open_handles list to back to
+ * the head if it's there (for refresh scenario)
+ */
+ if (global_hba_head->open_handles) {
+ new_hba->open_handles =
+ global_hba_head->open_handles;
+ global_hba_head->open_handles = NULL;
+ }
+ /* Now bump the new one to the head of the list */
+ new_hba->next = global_hba_head;
+ global_hba_head = new_hba;
+ } else {
+ global_hba_head = new_hba;
+ }
+ return (HBA_STATUS_OK);
+ }
+
+ while (portNode != DI_NODE_NIL) {
+ if (add_hba_port_info(portNode, new_hba, protocol)
+ == HBA_STATUS_ERROR) {
+ S_FREE(new_hba->first_port);
+ S_FREE(new_hba);
+ return (HBA_STATUS_ERROR);
+ }
+ portNode = di_sibling_node(portNode);
+ }
+
+ new_hba->index = hba_count++;
+
+ /*
+ * add newly created handle into global_hba_head list
+ */
+ if (global_hba_head != NULL) {
+ /*
+ * Make sure to move the open_handles list to back to the
+ * head if it's there (for refresh scenario)
+ */
+ if (global_hba_head->open_handles) {
+ new_hba->open_handles = global_hba_head->open_handles;
+ global_hba_head->open_handles = NULL;
+ }
+ /* Now bump the new one to the head of the list */
+ new_hba->next = global_hba_head;
+ global_hba_head = new_hba;
+ } else {
+ global_hba_head = new_hba;
+ }
+
+ return (HBA_STATUS_OK);
+}
+
+/*
+ * Discover information for all HBAs found on the system.
+ * The di_node_t argument should be the root of the device tree.
+ * This routine assumes the locks have been taken
+ */
+static int
+lookup_smhba_sas_hba(di_node_t node, void *arg)
+{
+ const char ROUTINE[] = "lookup_smhba_sas_hba";
+ int *propData, rval;
+ walkarg_t *wa = (walkarg_t *)arg;
+
+ /* Skip stub(instance -1) nodes */
+ if (IS_STUB_NODE(node)) {
+ log(LOG_DEBUG, ROUTINE, "Walk continue");
+ return (DI_WALK_CONTINUE);
+ }
+
+ rval = di_prop_lookup_ints(DDI_DEV_T_ANY, node,
+ "sm-hba-supported", &propData);
+ if (rval >= 0) {
+ if (*propData) {
+ /* add the hba to the hba list */
+ if (devtree_get_one_hba(node) != HBA_STATUS_OK) {
+ *(wa->flag) = B_TRUE;
+ }
+ /* Found a node. No need to walk the child. */
+ log(LOG_DEBUG, ROUTINE, "Walk prunechild");
+ return (DI_WALK_PRUNECHILD);
+ }
+ }
+
+ return (DI_WALK_CONTINUE);
+}
+
+/*
+ * Discover information for all HBAs found on the system.
+ * The di_node_t argument should be the root of the device tree.
+ * This routine assumes the locks have been taken
+ */
+HBA_STATUS
+devtree_get_all_hbas(di_node_t root)
+{
+ const char ROUTINE[] = "devtree_get_all_hbas";
+ int rv, ret = HBA_STATUS_ERROR;
+ walkarg_t wa;
+
+ wa.devpath = NULL;
+ if ((wa.flag = (boolean_t *)calloc(1,
+ sizeof (boolean_t))) == NULL) {
+ OUT_OF_MEMORY(ROUTINE);
+ return (HBA_STATUS_ERROR);
+ }
+ *wa.flag = B_FALSE;
+ rv = di_walk_node(root, DI_WALK_SIBFIRST, &wa, lookup_smhba_sas_hba);
+
+ if (rv == 0) {
+ /*
+ * Now determine what status code to return, taking
+ * partial failure scenarios into consideration.
+ *
+ * If we have at least one working HBA, then we return an
+ * OK status. If we have no good HBAs, but at least one
+ * failed HBA, we return an ERROR status. If we have
+ * no HBAs and no failures, we return OK.
+ */
+ if (global_hba_head) {
+ /*
+ * We've got at least one HBA and possibly some
+ * failures.
+ */
+ ret = HBA_STATUS_OK;
+ } else if (*(wa.flag)) {
+ /* We have no HBAs but have failures */
+ ret = HBA_STATUS_ERROR;
+ } else {
+ /* We have no HBAs and no failures */
+ ret = HBA_STATUS_OK;
+ }
+ }
+
+
+ S_FREE(wa.flag);
+
+ if (ret == HBA_STATUS_OK)
+ (void) registerSysevent();
+
+ return (ret);
+}
diff --git a/usr/src/lib/sun_sas/common/devtree_phy_disco.c b/usr/src/lib/sun_sas/common/devtree_phy_disco.c
new file mode 100644
index 0000000000..53351912f7
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/devtree_phy_disco.c
@@ -0,0 +1,202 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sun_sas.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <libdevinfo.h>
+#include <netinet/in.h>
+#include <inttypes.h>
+
+/*
+ * structure for di_devlink_walk
+ */
+typedef struct walk_devlink {
+ char *path;
+ size_t len;
+ char **linkpp;
+} walk_devlink_t;
+
+/*
+ * Free the phy allocation.
+ */
+static void
+free_phy_info(struct sun_sas_port *port_ptr)
+{
+ struct phy_info *phy_ptr, *last_phy;
+
+ phy_ptr = port_ptr->first_phy;
+ while (phy_ptr != NULL) {
+ last_phy = phy_ptr;
+ phy_ptr = phy_ptr->next;
+ free(last_phy);
+ }
+
+ port_ptr->first_phy = NULL;
+
+}
+
+/*
+ * callback funtion for di_devlink_walk
+ * Find matching /dev link for the given path argument.
+ * devlink element and callback function argument.
+ * The input path is expected to not have "/devices".
+ */
+extern HBA_STATUS
+get_phy_info(di_node_t node, struct sun_sas_port *port_ptr)
+{
+ const char ROUTINE[] = "get_phy_info";
+ char *portDevpath = NULL;
+ uchar_t *propByteData = NULL;
+ struct phy_info *phy_ptr;
+ uint_t nvcount;
+ int rval, count, i;
+ nvlist_t *nvl, **phyInfoVal;
+ uint8_t phyId;
+ int8_t negoRate, prgmMinRate, prgmMaxRate, hwMinRate, hwMaxRate;
+
+ /*
+ * When path is specified, it doesn't have minor
+ * name. Therefore, the ../.. prefixes needs to be stripped.
+ */
+ if ((portDevpath = di_devfs_path(node)) == NULL) {
+ log(LOG_DEBUG, ROUTINE,
+ "Unable to get device path from portNode.");
+ }
+
+ count = di_prop_lookup_bytes(DDI_DEV_T_ANY, node, "phy-info",
+ (uchar_t **)&propByteData);
+ if (count < 0) {
+ if (portDevpath) {
+ log(LOG_DEBUG, ROUTINE,
+ "Property phy-info not found on port %s%s",
+ DEVICES_DIR, portDevpath);
+ di_devfs_path_free(portDevpath);
+ } else {
+ log(LOG_DEBUG, ROUTINE, "Property phy-info not found.");
+ }
+ return (HBA_STATUS_ERROR);
+ } else {
+ rval = nvlist_unpack((char *)propByteData, count, &nvl, 0);
+ if (rval != 0) {
+ if (portDevpath) {
+ log(LOG_DEBUG, ROUTINE,
+ "nvlist_unpack failed on port %s%s",
+ DEVICES_DIR, portDevpath);
+ di_devfs_path_free(portDevpath);
+ } else {
+ log(LOG_DEBUG, ROUTINE,
+ "nvlist_unpack failed.");
+ }
+ return (HBA_STATUS_ERROR);
+ } else {
+ rval = nvlist_lookup_nvlist_array(nvl, "phy-info-nvl",
+ &phyInfoVal, &nvcount);
+ if (rval != 0) {
+ if (portDevpath) {
+ log(LOG_DEBUG, ROUTINE,
+ "nvlist array phy-info-nvl not\
+ found on port %s%s", DEVICES_DIR,
+ portDevpath);
+ di_devfs_path_free(portDevpath);
+ } else {
+ log(LOG_DEBUG, ROUTINE,
+ "nvlist array phy-info-nvl not\
+ found");
+ }
+ nvlist_free(nvl);
+ return (HBA_STATUS_ERROR);
+ } else {
+ /* indentation moved */
+ for (i = 0; i < nvcount; i++) {
+ if (nvlist_lookup_uint8(phyInfoVal[i],
+ "PhyIdentifier", &phyId) != 0) {
+ /* Indicate a failure : no better way to set */
+ phyId = 0xff;
+ }
+ if (nvlist_lookup_int8(phyInfoVal[i],
+ "NegotiatedLinkRate", &negoRate) != 0) {
+ negoRate = HBA_SASSTATE_UNKNOWN;
+ }
+ if (nvlist_lookup_int8(phyInfoVal[i],
+ "ProgrammedMinLinkRate", &prgmMinRate) != 0) {
+ prgmMinRate = HBA_SASSTATE_UNKNOWN;
+ }
+ if (nvlist_lookup_int8(phyInfoVal[i],
+ "ProgrammedMaxLinkRate", &prgmMaxRate) != 0) {
+ prgmMaxRate = HBA_SASSTATE_UNKNOWN;
+ }
+ if (nvlist_lookup_int8(phyInfoVal[i],
+ "HardwareMinLinkRate", &hwMinRate) != 0) {
+ hwMinRate = HBA_SASSTATE_UNKNOWN;
+ }
+ if (nvlist_lookup_int8(phyInfoVal[i],
+ "HardwareMaxLinkRate", &hwMaxRate) != 0) {
+ hwMaxRate = HBA_SASSTATE_UNKNOWN;
+ }
+
+ if ((phy_ptr = (struct phy_info *)calloc(1,
+ sizeof (struct phy_info))) == NULL) {
+ OUT_OF_MEMORY(ROUTINE);
+ if (portDevpath)
+ di_devfs_path_free(portDevpath);
+ free_phy_info(port_ptr);
+ nvlist_free(nvl);
+ return (HBA_STATUS_ERROR);
+ }
+ phy_ptr->phy.PhyIdentifier = phyId;
+ phy_ptr->phy.NegotiatedLinkRate = negoRate;
+ phy_ptr->phy.ProgrammedMinLinkRate = prgmMinRate;
+ phy_ptr->phy.ProgrammedMaxLinkRate = prgmMaxRate;
+ phy_ptr->phy.HardwareMinLinkRate = hwMinRate;
+ phy_ptr->phy.HardwareMaxLinkRate = hwMaxRate;
+ /*
+ * we will fill domain port later.
+ */
+ (void) memset(phy_ptr->phy.domainPortWWN.wwn, 0, 8);
+ phy_ptr->index = i;
+ if (port_ptr->first_phy == NULL) {
+ port_ptr->first_phy = phy_ptr;
+ } else {
+ phy_ptr->next = port_ptr->first_phy;
+ port_ptr->first_phy = phy_ptr;
+ }
+
+ }
+ nvlist_free(nvl);
+ /* end of indentation move */
+ }
+ }
+ }
+
+ if (portDevpath) {
+ di_devfs_path_free(portDevpath);
+ }
+
+ return (HBA_STATUS_OK);
+}
diff --git a/usr/src/lib/sun_sas/common/event.c b/usr/src/lib/sun_sas/common/event.c
new file mode 100644
index 0000000000..a4030d5d1b
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/event.c
@@ -0,0 +1,268 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sun_sas.h>
+#include <libsysevent.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <inttypes.h>
+#include <ctype.h>
+
+
+/* Remove these 5 when the header containing the event names aver available. */
+/*
+ * Event definitions
+ */
+/* Event Class */
+#define EC_HBA "EC_hba"
+#define EC_DR "EC_dr"
+/* Event Sub-Class */
+#define ESC_SAS_HBA_PORT_BROADCAST "ESC_sas_hba_port_broadcast"
+#define ESC_SAS_PHY_EVENT "ESC_sas_phy_event"
+#define ESC_DR_TARGET_STATE_CHANGE "ESC_dr_target_state_change"
+
+/* Broadcast Event Types */
+#define SAS_PORT_BROADCAST_CHANGE "port_broadcast_change"
+#define SAS_PORT_BROADCAST_SES "port_broadcast_ses"
+#define SAS_PORT_BROADCAST_D24_0 "port_broadcast_d24_0"
+#define SAS_PORT_BROADCAST_D27_4 "port_broadcast_d27_4"
+#define SAS_PORT_BROADCAST_D01_4 "port_broadcast_d01_4"
+#define SAS_PORT_BROADCAST_D04_7 "port_broadcast_d04_7"
+#define SAS_PORT_BROADCAST_D16_7 "port_broadcast_d16_7"
+#define SAS_PORT_BROADCAST_D29_7 "port_broadcast_d29_7"
+
+/* Phy Event Types */
+#define SAS_PHY_ONLINE "port_online"
+#define SAS_PHY_OFFLINE "port_offline"
+#define SAS_PHY_REMOVE "port_remove"
+
+/* Event payload */
+#define SAS_DRV_INST "driver_instance"
+#define SAS_PORT_ADDR "port_address"
+#define SAS_DEVFS_PATH "devfs_path"
+#define SAS_EVENT_TYPE "event_type"
+
+#define HBA_PORT_MATCH 1
+#define TARGET_PORT_MATCH 2
+#define PHY_MATCH 3
+
+#define REMOVED 1
+#define ONLINE 2
+#define OFFLINE 3
+
+sysevent_handle_t *gSysEventHandle = NULL;
+
+/* Calls the client callback function, if one is registered */
+static HBA_STATUS
+updateMatchingPhy(HBA_WWN portAddr, uint8_t phyId, int update, uint8_t linkRate)
+{
+ const char ROUTINE[] = "updateMatchingPhy";
+ struct sun_sas_hba *hba_ptr;
+ struct sun_sas_port *hba_port_ptr;
+ struct phy_info *phy_ptr;
+
+ log(LOG_DEBUG, ROUTINE, "- phy matching");
+ /* grab write lock */
+ lock(&all_hbas_lock);
+ /* loop through HBAs */
+ for (hba_ptr = global_hba_head; hba_ptr != NULL;
+ hba_ptr = hba_ptr->next) {
+ /* loop through HBA ports */
+ for (hba_port_ptr = hba_ptr->first_port;
+ hba_port_ptr != NULL;
+ hba_port_ptr = hba_port_ptr->next) {
+ if (wwnConversion(hba_port_ptr->
+ port_attributes.PortSpecificAttribute.
+ SASPort->LocalSASAddress.wwn) ==
+ wwnConversion(portAddr.wwn)) {
+ /* loop through phys */
+ for (phy_ptr = hba_port_ptr->first_phy;
+ phy_ptr != NULL; phy_ptr =
+ phy_ptr->next) {
+ if (phy_ptr->phy.PhyIdentifier ==
+ phyId) {
+ if (update == REMOVED) {
+ phy_ptr->invalid =
+ B_TRUE;
+ } else if (update == OFFLINE) {
+ phy_ptr->phy.
+ NegotiatedLinkRate
+ = 0;
+ } else { /* online */
+ phy_ptr->phy.
+ NegotiatedLinkRate
+ = linkRate;
+ }
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_OK);
+ }
+ } /* for phys */
+ } /* wwn mismatch. continue */
+ } /* for HBA ports */
+ } /* for HBAs */
+
+ unlock(&all_hbas_lock);
+ return (HBA_STATUS_ERROR);
+}
+
+/* Event handler called by system */
+static void
+syseventHandler(sysevent_t *ev)
+{
+
+ const char ROUTINE[] = "syseventHandler";
+ nvlist_t *attrList = NULL;
+ char *eventStr, *portAddrStr, *charptr;
+ int update;
+ uint64_t addr;
+ uint8_t phyId, linkRate;
+ HBA_WWN portAddr;
+
+ /* Is the event one of ours? */
+ if (strncmp(EC_HBA, sysevent_get_class_name(ev), strlen(EC_HBA)) == 0) {
+ /* handle phy events */
+ if (strncmp(ESC_SAS_PHY_EVENT, sysevent_get_subclass_name(ev),
+ strlen(ESC_SAS_PHY_EVENT)) == 0) {
+ if (sysevent_get_attr_list(ev, &attrList) != 0) {
+ log(LOG_DEBUG, ROUTINE,
+ "Failed to get event attributes on %s/%s",
+ EC_HBA, ESC_SAS_PHY_EVENT);
+ return;
+ } else {
+ if (nvlist_lookup_string(attrList,
+ "event_type", &eventStr) != 0) {
+ log(LOG_DEBUG, ROUTINE,
+ "Event type not found");
+ return;
+ } else {
+ if (strncmp(eventStr, "phy_online",
+ sizeof (eventStr)) == 0) {
+ update = ONLINE;
+ if (nvlist_lookup_uint8(
+ attrList, "link_rate",
+ &linkRate) != 0) {
+ log(LOG_DEBUG, ROUTINE,
+ "Link Rate not \
+ found");
+ return;
+ }
+ } else if (strncmp(eventStr,
+ "phy_offline",
+ sizeof (eventStr)) == 0) {
+ update = OFFLINE;
+ } else if (strncmp(eventStr,
+ "phy_remove",
+ sizeof (eventStr)) == 0) {
+ update = REMOVED;
+ } else {
+ log(LOG_DEBUG, ROUTINE,
+ "Invalid event type");
+ return;
+ }
+ }
+ if (nvlist_lookup_string(attrList,
+ "port_address", &portAddrStr) != 0) {
+ log(LOG_DEBUG, ROUTINE,
+ "Port SAS address not found");
+ return;
+ } else {
+ for (charptr = portAddrStr;
+ charptr != NULL; charptr++) {
+ if (isxdigit(*charptr)) {
+ break;
+ }
+ }
+ addr = htonll(strtoll(charptr,
+ NULL, 16));
+ (void) memcpy(portAddr.wwn, &addr, 8);
+ }
+ if (nvlist_lookup_uint8(attrList,
+ "PhyIdentifier", &phyId) != 0) {
+ log(LOG_DEBUG, ROUTINE,
+ "Port SAS address not found");
+ return;
+ }
+ }
+ if (updateMatchingPhy(portAddr, phyId, update,
+ linkRate) != HBA_STATUS_OK) {
+ log(LOG_DEBUG, ROUTINE,
+ "updating phy for the events failed.");
+ }
+ }
+ } else if (strncmp(EC_DR, sysevent_get_class_name(ev), 2) == 0) {
+ /* handle DR events */
+ log(LOG_DEBUG, ROUTINE,
+ "handle EC_dr events.");
+ } else {
+ log(LOG_DEBUG, ROUTINE,
+ "Found Unregistered event. - exit");
+ return;
+ }
+
+ log(LOG_DEBUG, ROUTINE, "- exit");
+}
+
+/* Registers events to the sysevent framework */
+HBA_STATUS
+registerSysevent() {
+
+ const char ROUTINE[] = "registerSysevent";
+ const char *hba_subclass_list[] = {
+ ESC_SAS_PHY_EVENT
+ };
+ const char *dr_subclass_list[] = {
+ ESC_DR_TARGET_STATE_CHANGE
+ };
+
+ gSysEventHandle = sysevent_bind_handle(syseventHandler);
+ if (gSysEventHandle == NULL) {
+ log(LOG_DEBUG, ROUTINE,
+ "- sysevent_bind_handle() failed");
+ log(LOG_DEBUG, ROUTINE, "- error exit");
+ return (HBA_STATUS_ERROR);
+ }
+
+ if (sysevent_subscribe_event(gSysEventHandle, EC_HBA,
+ hba_subclass_list, 1) != 0) {
+ log(LOG_DEBUG, ROUTINE,
+ "- sysevent_subscribe_event() failed for EC_HBA subclass");
+ log(LOG_DEBUG, ROUTINE, "- error exit");
+ sysevent_unbind_handle(gSysEventHandle);
+ return (HBA_STATUS_ERROR);
+ }
+
+ if (sysevent_subscribe_event(gSysEventHandle, EC_DR,
+ dr_subclass_list, 1) != 0) {
+ log(LOG_DEBUG, ROUTINE,
+ "- sysevent_subscribe_event() failed for DR subclass");
+ log(LOG_DEBUG, ROUTINE, "- error exit");
+ sysevent_unbind_handle(gSysEventHandle);
+ return (HBA_STATUS_ERROR);
+ }
+
+ log(LOG_DEBUG, ROUTINE, "- exit");
+
+ return (HBA_STATUS_ERROR);
+}
diff --git a/usr/src/lib/sun_sas/common/log.c b/usr/src/lib/sun_sas/common/log.c
new file mode 100644
index 0000000000..d556ecc8d7
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/log.c
@@ -0,0 +1,68 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/varargs.h>
+#include <errno.h>
+#include <string.h>
+
+#include <sun_sas.h>
+
+#define MAX_LOG_LEN 2048
+
+void
+log(
+ int level,
+ 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);
+
+ va_start(ap, msg);
+ (void) snprintf(header, MAX_LOG_LEN, "%s: %s: %s",
+ "SM-HBA Sun SAS VSL", routine, msg);
+
+ /* LINTED E_SEC_PRINTF_VAR_FMT */
+ (void) vsnprintf(message, MAX_LOG_LEN, header, ap);
+
+ /* LINTED E_SEC_PRINTF_VAR_FMT */
+ syslog(level, message);
+
+ va_end(ap);
+
+ errno = oldErrno;
+}
diff --git a/usr/src/lib/sun_sas/common/mapfile-vers b/usr/src/lib/sun_sas/common/mapfile-vers
new file mode 100644
index 0000000000..d0085ce9e1
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/mapfile-vers
@@ -0,0 +1,77 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# MAPFILE HEADER START
+#
+# WARNING: STOP NOW. DO NOT MODIFY THIS FILE.
+# Object versioning must comply with the rules detailed in
+#
+# usr/src/lib/README.mapfiles
+#
+# You should not be making modifications here until you've read the most current
+# copy of that file. If you need help, contact a gatekeeper for guidance.
+#
+# MAPFILE HEADER END
+#
+
+
+SUNWprivate {
+ global:
+ SMHBA_RegisterLibrary;
+ Sun_sasGetNumberOfAdapters;
+ Sun_sasLoadLibrary;
+ Sun_sasFreeLibrary;
+ Sun_sasRefreshInformation;
+ Sun_sasRefreshAdapterConfiguration;
+ Sun_sasCloseAdapter;
+ Sun_sasFreeLibrary;
+ Sun_sasGetAdapterAttributes;
+ Sun_sasGetAdapterName;
+ Sun_sasGetAdapterPortAttributes;
+ Sun_sasGetDiscoveredPortAttributes;
+ Sun_sasGetLUNStatistics;
+ Sun_sasGetNumberOfAdapters;
+ Sun_sasGetNumberOfPorts;
+ Sun_sasSetPersistentBinding;
+ Sun_sasGetPersistentBinding;
+ Sun_sasGetPhyStatistics;
+ Sun_sasGetPortAttributesByWWN;
+ Sun_sasGetPortType;
+ Sun_sasGetProtocolStatistics;
+ Sun_sasGetSASPhyAttributes;
+ Sun_sasGetTargetMapping;
+ Sun_sasGetVendorLibraryAttributes;
+ Sun_sasGetVersion;
+ Sun_sasScsiReadCapacity;
+ Sun_sasScsiReportLUNs;
+ Sun_sasScsiInquiry;
+ Sun_sasLoadLibrary;
+ Sun_sasSendSMPPassThru;
+ Sun_sasOpenAdapter;
+ FreeHBA;
+ local:
+ *;
+};
diff --git a/usr/src/lib/sun_sas/common/sun_sas.c b/usr/src/lib/sun_sas/common/sun_sas.c
new file mode 100644
index 0000000000..152a25a723
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/sun_sas.c
@@ -0,0 +1,431 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+
+#include <sys/byteorder.h>
+#include <sun_sas.h>
+
+/*
+ * creates a handle each time Sun_sas_OpenAdapter() is called.
+ *
+ * a open_handle_struct was created to keep track of which handles are currently
+ * open. This prevents a user from using an old handle that corresponds to
+ * an hba that has already been closed.
+ */
+HBA_HANDLE
+CreateHandle(int adapterIndex)
+{
+ const char ROUTINE[] = "CreateHandle";
+ struct open_handle *new_open_handle;
+ HBA_UINT32 new_handle_index;
+ HBA_UINT8 max_handle_wrap = 0;
+
+ if (global_hba_head == NULL) {
+ log(LOG_DEBUG, ROUTINE,
+ "an error as occurred. global_hba_head is "
+ "NULL. Library may not be loaded yet.");
+ return (HANDLE_ERROR);
+ }
+
+ while (RetrieveIndex(open_handle_index) != -1) {
+ open_handle_index = open_handle_index + 1;
+ if (open_handle_index == 0) {
+ /*
+ * If open_handle_index wraps back to zero again,
+ * that means all handles are currently in use.
+ * Spec only allows for 16 bits of handles
+ */
+ if (max_handle_wrap == 1) {
+ log(LOG_DEBUG, ROUTINE,
+ "Max number of handles reached.");
+ return (HANDLE_ERROR);
+ }
+ open_handle_index = 1;
+ max_handle_wrap = 1;
+ }
+ }
+
+ new_handle_index = open_handle_index;
+ if ((new_open_handle = (struct open_handle *)calloc(1,
+ sizeof (struct open_handle))) == NULL) {
+ OUT_OF_MEMORY(ROUTINE);
+ return (HANDLE_ERROR);
+ }
+ (void) memset(new_open_handle, 0, sizeof (struct open_handle));
+ new_open_handle->adapterIndex = adapterIndex;
+ new_open_handle->handle = new_handle_index;
+
+ lock(&open_handles_lock);
+
+ /* add new open handle struct to the open_handles list */
+ if (global_hba_head->open_handles == NULL) {
+ global_hba_head->open_handles = new_open_handle;
+ } else {
+ new_open_handle->next = global_hba_head->open_handles;
+ global_hba_head->open_handles = new_open_handle;
+ }
+
+ unlock(&open_handles_lock);
+ open_handle_index = open_handle_index + 1;
+ if (open_handle_index == 0) {
+ open_handle_index = 1;
+ }
+
+ return (new_handle_index);
+}
+
+/*
+ * given a handle, returns the adapterIndex number.
+ *
+ * This functions checkes to see if the given handle corresponds to an open
+ * HBA. If it does, the adapterIndex is returned.
+ */
+int
+RetrieveIndex(HBA_HANDLE handle)
+{
+
+ struct open_handle *open_handle_ptr;
+
+ lock(&open_handles_lock);
+
+ open_handle_ptr = RetrieveOpenHandle(handle);
+
+ unlock(&open_handles_lock);
+ if (open_handle_ptr == NULL) {
+ return (-1);
+ }
+
+ return (open_handle_ptr->adapterIndex);
+}
+/*
+ * Given a handle, returns the open_handle structure
+ * The routine assumes that the open_handles_lock has already
+ * been taken.
+ */
+struct open_handle *
+RetrieveOpenHandle(HBA_HANDLE handle)
+{
+
+ const char ROUTINE[] = "RetrieveOpenHandle";
+ struct open_handle *open_handle_ptr = NULL;
+
+ if (global_hba_head == NULL) {
+ log(LOG_DEBUG, ROUTINE, "No adpater is found.");
+ return (NULL);
+ }
+
+ for (open_handle_ptr = global_hba_head->open_handles;
+ open_handle_ptr != NULL;
+ open_handle_ptr = open_handle_ptr->next) {
+ if (open_handle_ptr->handle == handle) {
+ break;
+ }
+ }
+
+ return (open_handle_ptr);
+}
+
+/*
+ * Given an adapterIndex, this functions returns a pointer to the handle
+ * structure. This handle structure holds the hba's information
+ * Caller must take all_hbas_lock first.
+ */
+struct sun_sas_hba *
+RetrieveHandle(int index)
+{
+ struct sun_sas_hba *hba_ptr = NULL;
+
+ for (hba_ptr = global_hba_head; hba_ptr != NULL;
+ hba_ptr = hba_ptr->next) {
+ if (hba_ptr->index == index)
+ break;
+ }
+
+ return (hba_ptr);
+}
+
+/*
+ * Given an adapterIndex, this functions returns a pointer to the handle
+ * structure and extracts it from the global list.
+ *
+ * all_hbas_lock must be taken already.
+ */
+struct sun_sas_hba *
+ExtractHandle(int index)
+{
+ struct sun_sas_hba *last = NULL;
+ struct sun_sas_hba *hba_ptr = NULL;
+
+ for (hba_ptr = global_hba_head;
+ hba_ptr != NULL;
+ last = hba_ptr, hba_ptr = hba_ptr->next) {
+ if (hba_ptr->index == index) {
+ if (last) {
+ last->next = hba_ptr->next;
+ } else {
+ /* Hmm, must be the head of the list. */
+ global_hba_head = hba_ptr->next;
+ }
+ hba_ptr->next = NULL; /* Zap it to be safe */
+ break;
+ }
+ }
+
+ return (hba_ptr);
+}
+
+
+/*
+ * Given an handle, this functions returns a pointer to the handle structure
+ * for that hba
+ *
+ * Caller must take all_hbas_lock first.
+ */
+struct sun_sas_hba *
+Retrieve_Sun_sasHandle(HBA_HANDLE handle)
+{
+ const char ROUTINE[] = "Retrieve_Sun_sasHandle";
+ struct sun_sas_hba *handle_struct = NULL;
+ int index;
+
+ /* Retrieve fp device path from handle */
+ index = RetrieveIndex(handle);
+ if (index == -1) {
+ log(LOG_DEBUG, ROUTINE,
+ "handle could not be found.");
+ return (handle_struct);
+ }
+ lock(&open_handles_lock);
+ handle_struct = RetrieveHandle(index);
+ if (handle_struct == NULL) {
+ log(LOG_DEBUG, ROUTINE,
+ "could not find index in the handle list.");
+ unlock(&open_handles_lock);
+ return (handle_struct);
+ }
+ unlock(&open_handles_lock);
+
+ return (handle_struct);
+}
+
+/*
+ * Take a mutex lock. The routine will try, and if it fails,
+ * it will loop for a while and retry. If it fails many times,
+ * it will start writing to the log file.
+ */
+void
+lock(mutex_t *mp)
+{
+ int status;
+ int loop = 0;
+ const char ROUTINE[] = "lock";
+
+ do {
+ loop++;
+ status = mutex_trylock(mp);
+ switch (status) {
+ case 0:
+ break;
+ case EFAULT:
+ log(LOG_DEBUG, ROUTINE,
+ "Lock failed: fault 0x%x", mp);
+ break;
+ case EINVAL:
+ log(LOG_DEBUG, ROUTINE,
+ "Lock failed: invalid 0x%x", mp);
+ break;
+ case EBUSY:
+ if (loop > DEADLOCK_WARNING) {
+ log(LOG_DEBUG, ROUTINE,
+ "Lock busy, possible deadlock:0x%x",
+ mp);
+ }
+ break;
+ case EOWNERDEAD:
+ log(LOG_DEBUG, ROUTINE,
+ "Lock failed: owner dead 0x%x",
+ mp);
+ break;
+ case ELOCKUNMAPPED:
+ log(LOG_DEBUG, ROUTINE,
+ "Lock failed: unmapped 0x%x",
+ mp);
+ break;
+ case ENOTRECOVERABLE:
+ log(LOG_DEBUG, ROUTINE,
+ "Lock failed: not recoverable 0x%x", mp);
+ default:
+ if (loop > DEADLOCK_WARNING) {
+ log(LOG_DEBUG, ROUTINE,
+ "Lock failed: %s 0x%x",
+ strerror(status), mp);
+ break;
+ }
+ }
+
+ if (status) {
+ (void) sleep(LOCK_SLEEP);
+ }
+
+ } while (status);
+}
+
+/*
+ * Unlock a mutex lock.
+ */
+void
+unlock(mutex_t *mp)
+{
+ (void) mutex_unlock(mp);
+}
+
+
+/*
+ * Get the Port WWN of the first adapter port. This routine
+ * is used by the old V1 interfaces so that they can call
+ * the new V2 interfaces and exhibit the same behavior.
+ * In the event of error the WWN will be zero.
+ *
+ * This function will transition to PAA state but it will not
+ * verfiy whether data is stale or not
+ */
+HBA_WWN
+getFirstAdapterPortWWN(HBA_HANDLE handle)
+{
+ const char ROUTINE[] = "getFirstAdapterPortWWN";
+ HBA_WWN pwwn = {0, 0, 0, 0, 0, 0, 0, 0};
+ struct sun_sas_hba *hba_ptr = NULL;
+ int index = 0;
+ HBA_STATUS status;
+
+ lock(&all_hbas_lock);
+ index = RetrieveIndex(handle);
+ lock(&open_handles_lock);
+ hba_ptr = RetrieveHandle(index);
+ if (hba_ptr == NULL) {
+ log(LOG_DEBUG, ROUTINE, "Invalid handle %08lx", handle);
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (pwwn); /* zero WWN */
+ }
+
+ /* Check for stale data */
+ status = verifyAdapter(hba_ptr);
+ if (status != HBA_STATUS_OK) {
+ log(LOG_DEBUG, ROUTINE, "Verify adapter failed");
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (pwwn);
+ }
+
+ if (hba_ptr->first_port == NULL) {
+ /* This is probably an internal failure of the library */
+ if (hba_ptr->device_path) {
+ log(LOG_DEBUG, ROUTINE,
+ "Internal failure: Adapter %s contains no "
+ "port data", hba_ptr->device_path);
+ } else {
+ log(LOG_DEBUG, ROUTINE,
+ "Internal failure: Adapter at index %d contains "
+ " no support data", hba_ptr->index);
+ }
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+ return (pwwn); /* zero WWN */
+ }
+ /* Set the WWN now and return it */
+ pwwn = hba_ptr->first_port->port_attributes.PortSpecificAttribute.\
+ SASPort->LocalSASAddress;
+ unlock(&open_handles_lock);
+ unlock(&all_hbas_lock);
+
+ return (pwwn);
+}
+
+u_longlong_t
+wwnConversion(uchar_t *wwn)
+{
+ u_longlong_t tmp;
+ (void) memcpy(&tmp, wwn, sizeof (u_longlong_t));
+ tmp = ntohll(tmp);
+ return (tmp);
+}
+
+/*
+ * Using ioctl to send uscsi command out
+ */
+HBA_STATUS
+send_uscsi_cmd(const char *devpath, struct uscsi_cmd *ucmd)
+{
+ const char ROUTINE[] = "send_uscsi_cmd";
+ int fd;
+ HBA_STATUS ret;
+
+ /* set default timeout to 200 */
+ ucmd->uscsi_timeout = 200;
+
+ /* reset errno. */
+ errno = 0;
+ if ((fd = open(devpath, O_RDONLY | O_NDELAY)) == -1) {
+ log(LOG_DEBUG, ROUTINE,
+ "open devpath %s failed: %s", devpath, strerror(errno));
+ return (HBA_STATUS_ERROR);
+ }
+
+ if (ioctl(fd, USCSICMD, ucmd) == -1) {
+ if (errno == EBUSY) {
+ ret = HBA_STATUS_ERROR_BUSY;
+ } else if (errno == EAGAIN) {
+ ret = HBA_STATUS_ERROR_TRY_AGAIN;
+ } else {
+ ret = HBA_STATUS_ERROR;
+ }
+ log(LOG_DEBUG, ROUTINE,
+ "ioctl send uscsi to devpath: %s failed: %s",
+ devpath, strerror(errno));
+ (void) close(fd);
+ return (ret);
+ }
+
+ (void) close(fd);
+
+ return (HBA_STATUS_OK);
+}
+
+/*
+ * Check whether the given Domain Address is valid.
+ */
+HBA_STATUS
+validateDomainAddress(struct sun_sas_port *hba_port_ptr, HBA_WWN DomainAddr)
+{
+ if (hba_port_ptr->first_phy != NULL &&
+ wwnConversion(hba_port_ptr->first_phy->
+ phy.domainPortWWN.wwn) ==
+ wwnConversion(DomainAddr.wwn)) {
+ return (HBA_STATUS_OK);
+ }
+ return (HBA_STATUS_ERROR);
+}
diff --git a/usr/src/lib/sun_sas/common/sun_sas.h b/usr/src/lib/sun_sas/common/sun_sas.h
new file mode 100644
index 0000000000..d6872e5628
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/sun_sas.h
@@ -0,0 +1,294 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+
+#ifndef _SUN_SAS_H
+#define _SUN_SAS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <smhbaapi.h>
+#include <vendorsmhbaapi.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <string.h>
+#include <limits.h>
+#include <syslog.h>
+#include <thread.h>
+#include <synch.h>
+#include <unistd.h>
+#include <stropts.h>
+#include <libdevinfo.h>
+#include <sys/time.h>
+#include <sys/scsi/generic/commands.h>
+#include <sys/scsi/impl/commands.h>
+#include <sys/scsi/impl/sense.h>
+#include <sys/scsi/generic/inquiry.h>
+#include <sys/scsi/impl/uscsi.h>
+#include <sys/varargs.h>
+#include <sys/varargs.h>
+#include <libsysevent.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define VSL_NUMERIC_VERSION 1
+#define VSL_STRING_VERSION "Version 1"
+#define VSL_NAME "Sun T11 SM-HBA Vendor Library for SAS HBAs"
+#define SMHBA_LIBRARY_VERSION1 VSL_NUMERIC_VERSION
+
+/* The /dev links we expose */
+#define DEV_DISK_DIR "/dev/rdsk"
+#define DEV_TAPE_DIR "/dev/rmt"
+#define DEV_ES_DIR "/dev/es"
+#define DEV_CFG_DIR "/dev/cfg"
+#define DEVICES_DIR "/devices"
+#define DEVCTL_SUFFIX ":devctl"
+#define SCSI_SUFFIX ":scsi"
+
+/* To be consistent, when out of memory call this macro routine */
+#define OUT_OF_MEMORY(routine) \
+ log(LOG_DEBUG, routine, "Out of memory.")
+
+#define S_FREE(x) (((x) != NULL) ? (free(x), (x) = NULL) : (void *)0)
+
+#define IS_STUB_NODE(s) (di_instance(s) == -1 && \
+ di_nodeid(s) == (DI_PROM_NODEID))
+
+/* manf+model+10(char length of UINTMAX)+6(for 2 -'s, NULL & extra 3bytes */
+#define HANDLE_NAME_LENGTH (64 + 256 + 10 + 6)
+#define HANDLE_ERROR 0 /* This is an error condition */
+
+/* Some timing values */
+#define LOCK_SLEEP 1
+#define BUSY_SLEEP 10000 /* 1/100 second */
+#define BUSY_RETRY_TIMER 5000000000 /* Retry for 5 seconds */
+#define STATE_RETRY_TIMER 10000000000 /* Retry for 10 seconds */
+#define HR_SECOND 1000000000
+/* How many times to silently retry, before starting to print warnings */
+#define DEADLOCK_WARNING 10
+
+#define MAX_LUN 4096
+#define REP_LUNS_RSP_SIZE sizeof (rep_luns_rsp_t)+ \
+ (sizeof (lun_list_element_t)*(MAX_LUN - 1))
+
+/* misc */
+#define SUN_MICROSYSTEMS "Sun Microsystems, Inc."
+
+mutex_t all_hbas_lock;
+mutex_t open_handles_lock;
+mutex_t log_file_lock;
+HBA_UINT32 hba_count;
+HBA_UINT16 open_handle_index;
+
+
+/* Internal structures that aren't exposed to clients */
+struct open_handle {
+ int adapterIndex;
+ HBA_UINT32 handle;
+ struct open_handle *next;
+};
+
+struct sun_sas_hba {
+ HBA_UINT32 index; /* Can be sparse */
+ struct open_handle *open_handles;
+ int fd; /* when open, the FD */
+ /* The libdevinfo HBA path (lacking /devices) */
+ char device_path[MAXPATHLEN];
+ char handle_name[HANDLE_NAME_LENGTH];
+ SMHBA_ADAPTERATTRIBUTES adapter_attributes;
+
+ /* State tracking */
+ boolean_t invalid;
+ struct sun_sas_hba *next;
+ struct sun_sas_port *first_port;
+};
+
+struct sun_sas_hba *global_hba_head;
+
+struct ScsiEntryList {
+ SMHBA_SCSIENTRY entry;
+ struct ScsiEntryList *next;
+};
+
+struct phy_info {
+ HBA_UINT32 index;
+ boolean_t invalid;
+ SMHBA_SAS_PHY phy;
+ struct phy_info *next;
+};
+
+struct sun_sas_port {
+ HBA_UINT32 index;
+ boolean_t invalid;
+
+ /* The libdevinfo HBA path (lacking /devices) */
+ char device_path[MAXPATHLEN];
+ SMHBA_PORTATTRIBUTES port_attributes;
+ struct ScsiEntryList *scsiInfo;
+ int cntlNumber;
+
+ /* The following are used to track the device map */
+ int num_devices;
+ struct sun_sas_port *first_attached_port; /* Only for HBA port */
+ struct phy_info *first_phy; /* Only for HBA port */
+ struct sun_sas_port *next;
+};
+
+typedef struct walkarg {
+ char *devpath;
+ boolean_t *flag;
+} walkarg_t;
+
+extern int loadCount;
+
+extern sysevent_handle_t *gSysEventHandle;
+
+/* External routines */
+extern HBA_STATUS SMHBA_RegisterLibrary(PSMHBA_ENTRYPOINTS);
+extern HBA_UINT32 Sun_sasGetVendorLibraryAttributes(SMHBA_LIBRARYATTRIBUTES *);
+extern HBA_STATUS Sun_sasGetAdapterAttributes(HBA_HANDLE,
+ SMHBA_ADAPTERATTRIBUTES *);
+extern HBA_UINT32 Sun_sasGetNumberOfAdapters();
+extern HBA_STATUS Sun_sasGetAdapterName(HBA_UINT32, char *);
+extern HBA_STATUS Sun_sasGetPortType(HBA_HANDLE, HBA_UINT32, HBA_PORTTYPE *);
+extern HBA_STATUS Sun_sasGetAdapterPortAttributes(HBA_HANDLE, HBA_UINT32,
+ SMHBA_PORTATTRIBUTES *);
+extern HBA_STATUS Sun_sasGetPortAttributesByWWN(HBA_HANDLE, HBA_WWN, HBA_WWN,
+ SMHBA_PORTATTRIBUTES *);
+extern HBA_STATUS Sun_sasGetFCPhyAttributes(HBA_HANDLE, HBA_UINT32, HBA_UINT32,
+ SMHBA_FC_PHY *);
+extern HBA_STATUS Sun_sasGetSASPhyAttributes(HBA_HANDLE, HBA_UINT32,
+ HBA_UINT32, SMHBA_SAS_PHY *);
+extern HBA_STATUS Sun_sasGetProtocolStatistics(HBA_HANDLE, HBA_UINT32,
+ HBA_UINT32, SMHBA_PROTOCOLSTATISTICS *);
+extern HBA_STATUS Sun_sasGetPhyStatistics(HBA_HANDLE, HBA_UINT32,
+ HBA_UINT32, SMHBA_PHYSTATISTICS *);
+extern HBA_STATUS Sun_sasSendSMPPassThru(HBA_HANDLE, HBA_WWN, HBA_WWN, HBA_WWN,
+ void *, HBA_UINT32, void *, HBA_UINT32 *);
+extern HBA_STATUS Sun_sasGetBindingCapability(HBA_HANDLE, HBA_WWN, HBA_WWN,
+ SMHBA_BIND_CAPABILITY *);
+extern HBA_STATUS Sun_sasGetBindingSupport(HBA_HANDLE, HBA_WWN, HBA_WWN,
+ SMHBA_BIND_CAPABILITY *);
+extern HBA_STATUS Sun_sasSetBindingSupport(HBA_HANDLE, HBA_WWN, HBA_WWN,
+ SMHBA_BIND_CAPABILITY);
+extern HBA_STATUS Sun_sasGetTargetMapping(HBA_HANDLE, HBA_WWN, HBA_WWN,
+ SMHBA_TARGETMAPPING *);
+extern HBA_STATUS Sun_sasGetPersistentBinding(HBA_HANDLE, HBA_WWN, HBA_WWN,
+ SMHBA_BINDING *);
+extern HBA_STATUS Sun_sasSetPersistentBinding(HBA_HANDLE, HBA_WWN, HBA_WWN,
+ const SMHBA_BINDING *);
+extern HBA_STATUS Sun_sasRemovePersistentBinding(HBA_HANDLE, HBA_WWN, HBA_WWN,
+ const SMHBA_BINDING *);
+extern HBA_STATUS Sun_sasRemoveAllPersistentBindings(HBA_HANDLE, HBA_WWN,
+ HBA_WWN);
+extern HBA_STATUS Sun_sasGetLUNStatistics(HBA_HANDLE, const HBA_SCSIID *,
+ SMHBA_PROTOCOLSTATISTICS *);
+extern HBA_STATUS Sun_sasRegisterForAdapterAddEvents(void (*)(void *, HBA_WWN,
+ HBA_UINT32), void *, HBA_CALLBACKHANDLE *);
+extern HBA_STATUS Sun_sasRegisterForAdapterEvents(void (*)(void *, HBA_WWN,
+ HBA_UINT32), void *, HBA_HANDLE, HBA_CALLBACKHANDLE *);
+extern HBA_STATUS Sun_sasRegisterForAdapterPortEvents(void (*)(void *, HBA_WWN,
+ HBA_UINT32, HBA_UINT32), void *, HBA_HANDLE, HBA_WWN, HBA_UINT32,
+ HBA_CALLBACKHANDLE *);
+extern HBA_STATUS Sun_sasRegisterForAdapterPortStatEvents(void (*)(void *,
+ HBA_WWN, HBA_UINT32, HBA_UINT32), void *, HBA_HANDLE, HBA_WWN, HBA_UINT32,
+ SMHBA_PROTOCOLSTATISTICS, HBA_UINT32, HBA_CALLBACKHANDLE *);
+extern HBA_STATUS Sun_sasRegisterForAdapterPhyStatEvents(void (*)(void *,
+ HBA_WWN, HBA_UINT32, HBA_UINT32), void *, HBA_HANDLE, HBA_WWN, HBA_UINT32,
+ SMHBA_PHYSTATISTICS, HBA_UINT32, HBA_CALLBACKHANDLE *);
+extern HBA_STATUS Sun_sasRegisterForTargetEvents(void (*)(void *, HBA_WWN,
+ HBA_WWN, HBA_WWN, HBA_UINT32), void *, HBA_HANDLE, HBA_WWN, HBA_WWN,
+ HBA_WWN, HBA_CALLBACKHANDLE *, HBA_UINT32);
+extern HBA_STATUS Sun_sasRegisterForLinkEvents(void (*)(void *, HBA_WWN,
+ HBA_UINT32, void *, HBA_UINT32), void *, void *, HBA_UINT32, HBA_HANDLE,
+ HBA_CALLBACKHANDLE *);
+extern HBA_STATUS Sun_sasScsiInquiry(HBA_HANDLE, HBA_WWN, HBA_WWN, HBA_WWN,
+ SMHBA_SCSILUN, HBA_UINT8, HBA_UINT8, void *, HBA_UINT32 *, HBA_UINT8 *,
+ void *, HBA_UINT32 *);
+extern HBA_STATUS Sun_sasScsiReportLUNs(HBA_HANDLE, HBA_WWN, HBA_WWN,
+ HBA_WWN, void *, HBA_UINT32 *, HBA_UINT8 *, void *, HBA_UINT32 *);
+extern HBA_STATUS Sun_sasScsiReadCapacity(HBA_HANDLE, HBA_WWN, HBA_WWN, HBA_WWN,
+ SMHBA_SCSILUN, void *, HBA_UINT32 *, HBA_UINT8 *, void *, HBA_UINT32 *);
+extern HBA_UINT32 Sun_sasGetVersion();
+extern HBA_STATUS Sun_sasLoadLibrary();
+extern HBA_STATUS Sun_sasFreeLibrary();
+extern HBA_UINT32 Sun_sasGetNumberOfAdapters();
+extern HBA_UINT32 Sun_sasGetNumberOfPorts(HBA_HANDLE, HBA_UINT32 *);
+extern HBA_STATUS Sun_sasGetAdapterName(HBA_UINT32, char *);
+extern HBA_HANDLE Sun_sasOpenAdapter(char *);
+extern void Sun_sasCloseAdapter(HBA_HANDLE);
+extern HBA_STATUS Sun_sasGetDiscoveredPortAttributes(HBA_HANDLE, HBA_UINT32,
+ HBA_UINT32, SMHBA_PORTATTRIBUTES *);
+extern HBA_STATUS Sun_sasGetPortAttributesByWWN(HBA_HANDLE, HBA_WWN, HBA_WWN,
+ SMHBA_PORTATTRIBUTES *);
+extern void Sun_sasRefreshInformation(HBA_HANDLE);
+extern void Sun_sasRefreshAdapterConfiguration(void);
+extern HBA_STATUS Sun_sasRemoveCallback(HBA_CALLBACKHANDLE);
+
+
+/* Internal routines */
+extern void log(int, const char *, char *, ...);
+extern u_longlong_t wwnConversion(uchar_t *wwn);
+extern HBA_STATUS devtree_attached_devices(di_node_t, struct sun_sas_port *);
+extern HBA_HANDLE CreateHandle(int);
+extern int RetrieveIndex(HBA_HANDLE);
+extern struct open_handle *RetrieveOpenHandle(HBA_HANDLE);
+extern struct sun_sas_hba *RetrieveHandle(int);
+extern struct sun_sas_hba *ExtractHandle(int);
+extern struct sun_sas_hba *Retrieve_Sun_sasHandle(HBA_HANDLE);
+extern void lock(mutex_t *mp);
+extern void unlock(mutex_t *mp);
+extern void reportSense(struct scsi_extended_sense *, const char *);
+extern HBA_STATUS verifyAdapter(struct sun_sas_hba *hba_ptr);
+extern HBA_STATUS devtree_get_all_hbas(di_node_t root);
+extern HBA_STATUS devtree_get_one_hba(di_node_t node);
+extern HBA_STATUS FreeHBA(struct sun_sas_hba *hba);
+extern HBA_WWN getFirstAdapterPortWWN(HBA_HANDLE handle);
+extern HBA_STATUS getPortStateCounter(char *fpPath, HBA_UINT32 *stateCount);
+extern HBA_STATUS lookupControllerLink(char *path, char *link);
+extern HBA_STATUS lookupSMPLink(char *path, char *link);
+extern void convertDevpathToDevlink(PSMHBA_TARGETMAPPING mappings);
+extern void fillDomainPortWWN(struct sun_sas_port *);
+extern HBA_STATUS get_phy_info(di_node_t, struct sun_sas_port *);
+extern HBA_STATUS send_uscsi_cmd(const char *devpath, struct uscsi_cmd *ucmd);
+extern HBA_STATUS registerSysevent();
+extern HBA_STATUS validateDomainAddress(struct sun_sas_port *, HBA_WWN);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SUN_SAS_H */
diff --git a/usr/src/lib/sun_sas/common/verify.c b/usr/src/lib/sun_sas/common/verify.c
new file mode 100644
index 0000000000..c87aee5672
--- /dev/null
+++ b/usr/src/lib/sun_sas/common/verify.c
@@ -0,0 +1,79 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sun_sas.h>
+#include <signal.h>
+
+/*
+ * Verify that a given adapter is present on the system.
+ * No checks will be performed on the targets, and it is assumed
+ * that an adapter can't change the number of ports it has.
+ */
+HBA_STATUS
+verifyAdapter(struct sun_sas_hba *hba_ptr) {
+ const char ROUTINE[] = "verifyAdapter";
+ char *charptr, path[MAXPATHLEN+1];
+ di_node_t node;
+ uint_t state;
+
+ /*
+ * valid test for a removed HBA.
+ */
+ if (hba_ptr == NULL) {
+ log(LOG_DEBUG, ROUTINE, "Null hba_ptr argument");
+ return (HBA_STATUS_ERROR);
+ }
+ (void) strlcpy(path, hba_ptr->device_path, sizeof (path));
+
+ charptr = strrchr(path, ':');
+ if (charptr) {
+ *charptr = '\0';
+ }
+
+ errno = 0;
+
+ node = di_init(path, DINFOCPYALL);
+ if (node == DI_NODE_NIL) {
+ log(LOG_DEBUG, ROUTINE,
+ "Unable to take devinfo snapshot on HBA \"%s\" due to %s",
+ path, strerror(errno));
+ return (HBA_STATUS_ERROR);
+ } else {
+ state = di_state(node);
+ if (((state & DI_DRIVER_DETACHED) == DI_DRIVER_DETACHED) ||
+ ((state & DI_BUS_DOWN) == DI_BUS_DOWN) ||
+ ((state & DI_BUS_QUIESCED) == DI_BUS_QUIESCED)) {
+ di_fini(node);
+ log(LOG_DEBUG, ROUTINE,
+ "devinfo node is not online state: %d", state);
+ return (HBA_STATUS_ERROR);
+ }
+ }
+
+ di_fini(node);
+
+ return (HBA_STATUS_OK);
+}
diff --git a/usr/src/lib/sun_sas/i386/Makefile b/usr/src/lib/sun_sas/i386/Makefile
new file mode 100644
index 0000000000..47878e05bc
--- /dev/null
+++ b/usr/src/lib/sun_sas/i386/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 2009 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/sun_sas/sparc/Makefile b/usr/src/lib/sun_sas/sparc/Makefile
new file mode 100644
index 0000000000..7cdca9a2c6
--- /dev/null
+++ b/usr/src/lib/sun_sas/sparc/Makefile
@@ -0,0 +1,33 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#
+
+include ../Makefile.com
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+install: all $(ROOTLIBS) $(ROOTLINKS)
diff --git a/usr/src/lib/sun_sas/sparcv9/Makefile b/usr/src/lib/sun_sas/sparcv9/Makefile
new file mode 100644
index 0000000000..5180f1b702
--- /dev/null
+++ b/usr/src/lib/sun_sas/sparcv9/Makefile
@@ -0,0 +1,34 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)