diff options
Diffstat (limited to 'usr/src/lib')
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) |