xref: /onnv-gate/usr/src/lib/sun_fc/common/TgtFCHBAPort.cc (revision 10088:accb636cf069)
17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM  * CDDL HEADER START
37836SJohn.Forte@Sun.COM  *
47836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM  *
87836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM  * and limitations under the License.
127836SJohn.Forte@Sun.COM  *
137836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM  *
197836SJohn.Forte@Sun.COM  * CDDL HEADER END
207836SJohn.Forte@Sun.COM  */
217836SJohn.Forte@Sun.COM /*
22*10088SAllan.Ou@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237836SJohn.Forte@Sun.COM  * Use is subject to license terms.
247836SJohn.Forte@Sun.COM  */
257836SJohn.Forte@Sun.COM 
267836SJohn.Forte@Sun.COM 
277836SJohn.Forte@Sun.COM 
287836SJohn.Forte@Sun.COM #include <TgtFCHBAPort.h>
297836SJohn.Forte@Sun.COM #include <Exceptions.h>
307836SJohn.Forte@Sun.COM #include <Trace.h>
317836SJohn.Forte@Sun.COM #include <sun_fc.h>
327836SJohn.Forte@Sun.COM #include <iostream>
337836SJohn.Forte@Sun.COM #include <iomanip>
347836SJohn.Forte@Sun.COM #include <sys/types.h>
357836SJohn.Forte@Sun.COM #include <sys/mkdev.h>
367836SJohn.Forte@Sun.COM #include <sys/stat.h>
377836SJohn.Forte@Sun.COM #include <fcntl.h>
387836SJohn.Forte@Sun.COM #include <unistd.h>
397836SJohn.Forte@Sun.COM #include <stropts.h>
407836SJohn.Forte@Sun.COM #include <dirent.h>
417836SJohn.Forte@Sun.COM #include <sys/fibre-channel/fc.h>
427836SJohn.Forte@Sun.COM #include <sys/fctio.h>
437836SJohn.Forte@Sun.COM #include <sys/fibre-channel/impl/fc_error.h>
447836SJohn.Forte@Sun.COM #include <sys/fibre-channel/fc_appif.h>
457836SJohn.Forte@Sun.COM #include <sys/scsi/generic/commands.h>
467836SJohn.Forte@Sun.COM #include <sys/scsi/impl/commands.h>
477836SJohn.Forte@Sun.COM #include <sys/scsi/impl/sense.h>
487836SJohn.Forte@Sun.COM #include <sys/scsi/generic/inquiry.h>
497836SJohn.Forte@Sun.COM #include <sys/scsi/generic/status.h>
507836SJohn.Forte@Sun.COM #include <errno.h>
517836SJohn.Forte@Sun.COM 
527836SJohn.Forte@Sun.COM 
537836SJohn.Forte@Sun.COM using namespace std;
547836SJohn.Forte@Sun.COM 
557836SJohn.Forte@Sun.COM const int TgtFCHBAPort::MAX_FCTIO_MSG_LEN = 256;
567836SJohn.Forte@Sun.COM const string TgtFCHBAPort::FCT_DRIVER_PATH = "/devices/pseudo/fct@0:admin";
577836SJohn.Forte@Sun.COM 
587836SJohn.Forte@Sun.COM /*
597836SJohn.Forte@Sun.COM  * Interpret the error code in the fctio_t structure
607836SJohn.Forte@Sun.COM  *
617836SJohn.Forte@Sun.COM  * message must be at least MAX_FCTIO_MSG_LEN in length.
627836SJohn.Forte@Sun.COM  */
637836SJohn.Forte@Sun.COM void
transportError(uint32_t fctio_errno,char * message)647836SJohn.Forte@Sun.COM TgtFCHBAPort::transportError(uint32_t fctio_errno, char *message) {
657836SJohn.Forte@Sun.COM 	Trace log("transportError");
667836SJohn.Forte@Sun.COM 	string fcioErrorString;
677836SJohn.Forte@Sun.COM 	if (message == NULL) {
687836SJohn.Forte@Sun.COM 	    log.internalError("NULL routine argument");
697836SJohn.Forte@Sun.COM 	    return;
707836SJohn.Forte@Sun.COM 	}
717836SJohn.Forte@Sun.COM 	switch (fctio_errno) {
727836SJohn.Forte@Sun.COM 	case (uint32_t)FC_FAILURE:
737836SJohn.Forte@Sun.COM 	    fcioErrorString = "general failure";
747836SJohn.Forte@Sun.COM 	    break;
757836SJohn.Forte@Sun.COM 	case (uint32_t)FC_FAILURE_SILENT:
767836SJohn.Forte@Sun.COM 	    fcioErrorString = "general failure but fail silently";
777836SJohn.Forte@Sun.COM 	    break;
787836SJohn.Forte@Sun.COM 	case FC_SUCCESS:
797836SJohn.Forte@Sun.COM 	    fcioErrorString = "successful completion";
807836SJohn.Forte@Sun.COM 	    break;
817836SJohn.Forte@Sun.COM 	case FC_CAP_ERROR:
827836SJohn.Forte@Sun.COM 	    fcioErrorString = "FCA capability error";
837836SJohn.Forte@Sun.COM 	    break;
847836SJohn.Forte@Sun.COM 	case FC_CAP_FOUND:
857836SJohn.Forte@Sun.COM 	    fcioErrorString = "FCA capability unsettable";
867836SJohn.Forte@Sun.COM 	    break;
877836SJohn.Forte@Sun.COM 	case FC_CAP_SETTABLE:
887836SJohn.Forte@Sun.COM 	    fcioErrorString = "FCA capability settable";
897836SJohn.Forte@Sun.COM 	    break;
907836SJohn.Forte@Sun.COM 	case FC_UNBOUND:
917836SJohn.Forte@Sun.COM 	    fcioErrorString = "unbound stuff";
927836SJohn.Forte@Sun.COM 	    break;
937836SJohn.Forte@Sun.COM 	case FC_NOMEM:
947836SJohn.Forte@Sun.COM 	    fcioErrorString = "allocation error";
957836SJohn.Forte@Sun.COM 	    break;
967836SJohn.Forte@Sun.COM 	case FC_BADPACKET:
977836SJohn.Forte@Sun.COM 	    fcioErrorString = "invalid packet specified/supplied";
987836SJohn.Forte@Sun.COM 	    break;
997836SJohn.Forte@Sun.COM 	case FC_OFFLINE:
1007836SJohn.Forte@Sun.COM 	    fcioErrorString = "I/O resource unavailable";
1017836SJohn.Forte@Sun.COM 	    break;
1027836SJohn.Forte@Sun.COM 	case FC_OLDPORT:
1037836SJohn.Forte@Sun.COM 	    fcioErrorString = "operation on non-loop port";
1047836SJohn.Forte@Sun.COM 	    break;
1057836SJohn.Forte@Sun.COM 	case FC_NO_MAP:
1067836SJohn.Forte@Sun.COM 	    fcioErrorString = "requested map unavailable";
1077836SJohn.Forte@Sun.COM 	    break;
1087836SJohn.Forte@Sun.COM 	case FC_TRANSPORT_ERROR:
1097836SJohn.Forte@Sun.COM 	    fcioErrorString = "unable to transport I/O";
1107836SJohn.Forte@Sun.COM 	    break;
1117836SJohn.Forte@Sun.COM 	case FC_ELS_FREJECT:
1127836SJohn.Forte@Sun.COM 	    fcioErrorString = "ELS rejected by a Fabric";
1137836SJohn.Forte@Sun.COM 	    break;
1147836SJohn.Forte@Sun.COM 	case FC_ELS_PREJECT:
1157836SJohn.Forte@Sun.COM 	    fcioErrorString = "ELS rejected by an N_port";
1167836SJohn.Forte@Sun.COM 	    break;
1177836SJohn.Forte@Sun.COM 	case FC_ELS_BAD:
1187836SJohn.Forte@Sun.COM 	    fcioErrorString = "ELS rejected by FCA/fctl";
1197836SJohn.Forte@Sun.COM 	    break;
1207836SJohn.Forte@Sun.COM 	case FC_ELS_MALFORMED:
1217836SJohn.Forte@Sun.COM 	    fcioErrorString = "poorly formed ELS request";
1227836SJohn.Forte@Sun.COM 	    break;
1237836SJohn.Forte@Sun.COM 	case FC_TOOMANY:
1247836SJohn.Forte@Sun.COM 		fcioErrorString = "resource request too large";
1257836SJohn.Forte@Sun.COM 	    break;
1267836SJohn.Forte@Sun.COM 	case FC_UB_BADTOKEN:
1277836SJohn.Forte@Sun.COM 	    fcioErrorString = "invalid unsolicited buffer token";
1287836SJohn.Forte@Sun.COM 	    break;
1297836SJohn.Forte@Sun.COM 	case FC_UB_ERROR:
1307836SJohn.Forte@Sun.COM 	    fcioErrorString = "invalid unsol buf request";
1317836SJohn.Forte@Sun.COM 	    break;
1327836SJohn.Forte@Sun.COM 	case FC_UB_BUSY:
1337836SJohn.Forte@Sun.COM 	    fcioErrorString = "buffer already in use";
1347836SJohn.Forte@Sun.COM 	    break;
1357836SJohn.Forte@Sun.COM 	case FC_BADULP:
1367836SJohn.Forte@Sun.COM 	    fcioErrorString = "Unknown ulp";
1377836SJohn.Forte@Sun.COM 	    break;
1387836SJohn.Forte@Sun.COM 	case FC_BADTYPE:
1397836SJohn.Forte@Sun.COM 	    fcioErrorString = "ULP not registered to handle this FC4 type";
1407836SJohn.Forte@Sun.COM 	    break;
1417836SJohn.Forte@Sun.COM 	case FC_UNCLAIMED:
1427836SJohn.Forte@Sun.COM 	    fcioErrorString = "request or data not claimed";
1437836SJohn.Forte@Sun.COM 	    break;
1447836SJohn.Forte@Sun.COM 	case FC_ULP_SAMEMODULE:
1457836SJohn.Forte@Sun.COM 	    fcioErrorString = "module already in use";
1467836SJohn.Forte@Sun.COM 	    break;
1477836SJohn.Forte@Sun.COM 	case FC_ULP_SAMETYPE:
1487836SJohn.Forte@Sun.COM 	    fcioErrorString = "FC4 module already in use";
1497836SJohn.Forte@Sun.COM 	    break;
1507836SJohn.Forte@Sun.COM 	case FC_ABORTED:
1517836SJohn.Forte@Sun.COM 	    fcioErrorString = "request aborted";
1527836SJohn.Forte@Sun.COM 	    break;
1537836SJohn.Forte@Sun.COM 	case FC_ABORT_FAILED:
1547836SJohn.Forte@Sun.COM 	    fcioErrorString = "abort request failed";
1557836SJohn.Forte@Sun.COM 	    break;
1567836SJohn.Forte@Sun.COM 	case FC_BADEXCHANGE:
1577836SJohn.Forte@Sun.COM 	    fcioErrorString = "exchange doesn�t exist";
1587836SJohn.Forte@Sun.COM 	    break;
1597836SJohn.Forte@Sun.COM 	case FC_BADWWN:
1607836SJohn.Forte@Sun.COM 	    fcioErrorString = "WWN not recognized";
1617836SJohn.Forte@Sun.COM 	    break;
1627836SJohn.Forte@Sun.COM 	case FC_BADDEV:
1637836SJohn.Forte@Sun.COM 	    fcioErrorString = "device unrecognized";
1647836SJohn.Forte@Sun.COM 	    break;
1657836SJohn.Forte@Sun.COM 	case FC_BADCMD:
1667836SJohn.Forte@Sun.COM 	    fcioErrorString = "invalid command issued";
1677836SJohn.Forte@Sun.COM 	    break;
1687836SJohn.Forte@Sun.COM 	case FC_BADOBJECT:
1697836SJohn.Forte@Sun.COM 	    fcioErrorString = "invalid object requested";
1707836SJohn.Forte@Sun.COM 	    break;
1717836SJohn.Forte@Sun.COM 	case FC_BADPORT:
1727836SJohn.Forte@Sun.COM 	    fcioErrorString = "invalid port specified";
1737836SJohn.Forte@Sun.COM 	    break;
1747836SJohn.Forte@Sun.COM 	case FC_NOTTHISPORT:
1757836SJohn.Forte@Sun.COM 	    fcioErrorString = "resource not at this port";
1767836SJohn.Forte@Sun.COM 	    break;
1777836SJohn.Forte@Sun.COM 	case FC_PREJECT:
1787836SJohn.Forte@Sun.COM 	    fcioErrorString = "reject at remote N_Port";
1797836SJohn.Forte@Sun.COM 	    break;
1807836SJohn.Forte@Sun.COM 	case FC_FREJECT:
1817836SJohn.Forte@Sun.COM 	    fcioErrorString = "reject at remote Fabric";
1827836SJohn.Forte@Sun.COM 	    break;
1837836SJohn.Forte@Sun.COM 	case FC_PBUSY:
1847836SJohn.Forte@Sun.COM 	    fcioErrorString = "remote N_Port busy";
1857836SJohn.Forte@Sun.COM 	    break;
1867836SJohn.Forte@Sun.COM 	case FC_FBUSY:
1877836SJohn.Forte@Sun.COM 	    fcioErrorString = "remote Fabric busy";
1887836SJohn.Forte@Sun.COM 	    break;
1897836SJohn.Forte@Sun.COM 	case FC_ALREADY:
1907836SJohn.Forte@Sun.COM 	    fcioErrorString = "already logged in";
1917836SJohn.Forte@Sun.COM 	    break;
1927836SJohn.Forte@Sun.COM 	case FC_LOGINREQ:
1937836SJohn.Forte@Sun.COM 	    fcioErrorString = "login required";
1947836SJohn.Forte@Sun.COM 	    break;
1957836SJohn.Forte@Sun.COM 	case FC_RESETFAIL:
1967836SJohn.Forte@Sun.COM 	    fcioErrorString = "reset failed";
1977836SJohn.Forte@Sun.COM 	    break;
1987836SJohn.Forte@Sun.COM 	case FC_INVALID_REQUEST:
1997836SJohn.Forte@Sun.COM 	    fcioErrorString = "request is invalid";
2007836SJohn.Forte@Sun.COM 	    break;
2017836SJohn.Forte@Sun.COM 	case FC_OUTOFBOUNDS:
2027836SJohn.Forte@Sun.COM 	    fcioErrorString = "port number is out of bounds";
2037836SJohn.Forte@Sun.COM 	    break;
2047836SJohn.Forte@Sun.COM 	case FC_TRAN_BUSY:
2057836SJohn.Forte@Sun.COM 	    fcioErrorString = "command transport busy";
2067836SJohn.Forte@Sun.COM 	    break;
2077836SJohn.Forte@Sun.COM 	case FC_STATEC_BUSY:
2087836SJohn.Forte@Sun.COM 	    fcioErrorString = "port driver currently busy";
2097836SJohn.Forte@Sun.COM 	    break;
2107836SJohn.Forte@Sun.COM 	case FC_DEVICE_BUSY:
2117836SJohn.Forte@Sun.COM 	    fcioErrorString = "transport working on this device";
2127836SJohn.Forte@Sun.COM 	    break;
2137836SJohn.Forte@Sun.COM 	case FC_DEVICE_NOT_TGT:
2147836SJohn.Forte@Sun.COM 	    fcioErrorString = "device is not a SCSI target";
2157836SJohn.Forte@Sun.COM 	    break;
2167836SJohn.Forte@Sun.COM 	default:
2177836SJohn.Forte@Sun.COM 	    snprintf(message, MAX_FCTIO_MSG_LEN, "Unknown error code 0x%x",
2187836SJohn.Forte@Sun.COM 		fctio_errno);
2197836SJohn.Forte@Sun.COM 	    return;
2207836SJohn.Forte@Sun.COM 	}
2217836SJohn.Forte@Sun.COM 	snprintf(message, MAX_FCTIO_MSG_LEN, "%s", fcioErrorString.c_str());
2227836SJohn.Forte@Sun.COM }
2237836SJohn.Forte@Sun.COM 
TgtFCHBAPort(string thePath)2247836SJohn.Forte@Sun.COM TgtFCHBAPort::TgtFCHBAPort(string thePath) : HBAPort() {
2257836SJohn.Forte@Sun.COM 	Trace log("TgtFCHBAPort::TgtFCHBAPort");
2267836SJohn.Forte@Sun.COM 	log.debug("Initializing HBA port %s", path.c_str());
2277836SJohn.Forte@Sun.COM 	path = thePath;
2287836SJohn.Forte@Sun.COM 
2297836SJohn.Forte@Sun.COM 	// This routine is not index based, so we can discard stateChange
2307836SJohn.Forte@Sun.COM 	uint64_t tmp;
2317836SJohn.Forte@Sun.COM 	HBA_PORTATTRIBUTES attrs = getPortAttributes(tmp);
2327836SJohn.Forte@Sun.COM 	memcpy(&tmp, &attrs.PortWWN, 8);
2337836SJohn.Forte@Sun.COM 	portWWN = ntohll(tmp);
2347836SJohn.Forte@Sun.COM 	memcpy(&tmp, &attrs.NodeWWN, 8);
2357836SJohn.Forte@Sun.COM 	nodeWWN = ntohll(tmp);
2367836SJohn.Forte@Sun.COM 
2377836SJohn.Forte@Sun.COM 	// For reference, here's how to dump WWN's through C++ streams.
2387836SJohn.Forte@Sun.COM 	// cout << "\tPort WWN: " << hex << setfill('0') << setw(16) << portWWN
2397836SJohn.Forte@Sun.COM 	// << endl;
2407836SJohn.Forte@Sun.COM 	// cout << "\tNode WWN: " << hex << setfill('0') << setw(16) << nodeWWN
2417836SJohn.Forte@Sun.COM 	// << endl;
2427836SJohn.Forte@Sun.COM }
2437836SJohn.Forte@Sun.COM 
getPortAttributes(uint64_t & stateChange)2447836SJohn.Forte@Sun.COM HBA_PORTATTRIBUTES TgtFCHBAPort::getPortAttributes(uint64_t &stateChange) {
2457836SJohn.Forte@Sun.COM 	Trace log("TgtFCHBAPort::getPortAttributes");
2467836SJohn.Forte@Sun.COM 
2477836SJohn.Forte@Sun.COM 	HBA_PORTATTRIBUTES	attributes;
2487836SJohn.Forte@Sun.COM 	fctio_t			fctio;
2497836SJohn.Forte@Sun.COM 	fc_tgt_hba_port_attributes_t    attrs;
2507836SJohn.Forte@Sun.COM 
2517836SJohn.Forte@Sun.COM 	memset(&fctio, 0, sizeof (fctio));
2527836SJohn.Forte@Sun.COM 	memset(&attributes, 0, sizeof (attributes));
2537836SJohn.Forte@Sun.COM 
2547836SJohn.Forte@Sun.COM 	uint64_t portwwn = 0;
2557836SJohn.Forte@Sun.COM 	try {
2567836SJohn.Forte@Sun.COM 	    string::size_type offset = path.find_last_of(".");
2577836SJohn.Forte@Sun.COM 	    if (offset >= 0) {
2587836SJohn.Forte@Sun.COM 		string portwwnString = path.substr(offset+1);
2597836SJohn.Forte@Sun.COM 		portwwn = strtoull(portwwnString.c_str(), NULL, 16);
2607836SJohn.Forte@Sun.COM 	    }
2617836SJohn.Forte@Sun.COM 	} catch (...) {
2627836SJohn.Forte@Sun.COM 	    throw BadArgumentException();
2637836SJohn.Forte@Sun.COM 	}
2647836SJohn.Forte@Sun.COM 
2657836SJohn.Forte@Sun.COM 	uint64_t en_wwn = htonll(portwwn);
2667836SJohn.Forte@Sun.COM 
2677836SJohn.Forte@Sun.COM 	fctio.fctio_cmd = FCTIO_GET_ADAPTER_PORT_ATTRIBUTES;
2687836SJohn.Forte@Sun.COM 	fctio.fctio_ilen = 8;
2697836SJohn.Forte@Sun.COM 	fctio.fctio_ibuf = (uint64_t)(uintptr_t)&en_wwn;
2707836SJohn.Forte@Sun.COM 	fctio.fctio_xfer = FCTIO_XFER_READ;
2717836SJohn.Forte@Sun.COM 	fctio.fctio_olen = (uint32_t)(sizeof (attrs));
2727836SJohn.Forte@Sun.COM 	fctio.fctio_obuf = (uint64_t)(uintptr_t)&attrs;
2737836SJohn.Forte@Sun.COM 
2747836SJohn.Forte@Sun.COM 	fct_ioctl(FCTIO_CMD, &fctio);
2757836SJohn.Forte@Sun.COM 
2767836SJohn.Forte@Sun.COM 	stateChange = attrs.lastChange;
2777836SJohn.Forte@Sun.COM 
2787836SJohn.Forte@Sun.COM 	attributes.PortFcId = attrs.PortFcId;
2797836SJohn.Forte@Sun.COM 	attributes.PortType = attrs.PortType;
2807836SJohn.Forte@Sun.COM 	attributes.PortState = attrs.PortState;
2817836SJohn.Forte@Sun.COM 	attributes.PortSupportedClassofService = attrs.PortSupportedClassofService;
2827836SJohn.Forte@Sun.COM 	attributes.PortSupportedSpeed = attrs.PortSupportedSpeed;
2837836SJohn.Forte@Sun.COM 	attributes.PortSpeed = attrs.PortSpeed;
2847836SJohn.Forte@Sun.COM 	attributes.PortMaxFrameSize = attrs.PortMaxFrameSize;
2857836SJohn.Forte@Sun.COM 	attributes.NumberofDiscoveredPorts = attrs.NumberofDiscoveredPorts;
2867836SJohn.Forte@Sun.COM 	memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
2877836SJohn.Forte@Sun.COM 	memcpy(&attributes.PortWWN, &attrs.PortWWN, 8);
2887836SJohn.Forte@Sun.COM 	memcpy(&attributes.FabricName, &attrs.FabricName, 8);
2897836SJohn.Forte@Sun.COM 	memcpy(&attributes.PortSupportedFc4Types, &attrs.PortSupportedFc4Types, 32);
2907836SJohn.Forte@Sun.COM 	memcpy(&attributes.PortActiveFc4Types, &attrs.PortActiveFc4Types, 32);
2917836SJohn.Forte@Sun.COM 	memcpy(&attributes.PortSymbolicName, &attrs.PortSymbolicName, 256);
2927836SJohn.Forte@Sun.COM 
2937836SJohn.Forte@Sun.COM 	strncpy((char *)attributes.OSDeviceName, "Not Applicable", 15);
2947836SJohn.Forte@Sun.COM 	return (attributes);
2957836SJohn.Forte@Sun.COM }
2967836SJohn.Forte@Sun.COM 
getDiscoveredAttributes(HBA_UINT32 discoveredport,uint64_t & stateChange)2977836SJohn.Forte@Sun.COM HBA_PORTATTRIBUTES TgtFCHBAPort::getDiscoveredAttributes(
2987836SJohn.Forte@Sun.COM 	    HBA_UINT32 discoveredport, uint64_t &stateChange) {
2997836SJohn.Forte@Sun.COM 	Trace log("TgtFCHBAPort::getDiscoverdAttributes(i)");
3007836SJohn.Forte@Sun.COM 
3017836SJohn.Forte@Sun.COM 	HBA_PORTATTRIBUTES		attributes;
3027836SJohn.Forte@Sun.COM 	fctio_t			fctio;
3037836SJohn.Forte@Sun.COM 	fc_tgt_hba_port_attributes_t    attrs;
3047836SJohn.Forte@Sun.COM 
3057836SJohn.Forte@Sun.COM 	memset(&fctio, 0, sizeof (fctio));
3067836SJohn.Forte@Sun.COM 	memset(&attributes, 0, sizeof (attributes));
3077836SJohn.Forte@Sun.COM 
3087836SJohn.Forte@Sun.COM 	uint64_t portwwn = 0;
3097836SJohn.Forte@Sun.COM 	try {
3107836SJohn.Forte@Sun.COM 	    string::size_type offset = path.find_last_of(".");
3117836SJohn.Forte@Sun.COM 	    if (offset >= 0) {
3127836SJohn.Forte@Sun.COM 		string portwwnString = path.substr(offset+1);
3137836SJohn.Forte@Sun.COM 		portwwn = strtoull(portwwnString.c_str(), NULL, 16);
3147836SJohn.Forte@Sun.COM 	    }
3157836SJohn.Forte@Sun.COM 	} catch (...) {
3167836SJohn.Forte@Sun.COM 	    throw BadArgumentException();
3177836SJohn.Forte@Sun.COM 	}
3187836SJohn.Forte@Sun.COM 
3197836SJohn.Forte@Sun.COM 	uint64_t en_wwn = htonll(portwwn);
3207836SJohn.Forte@Sun.COM 
3217836SJohn.Forte@Sun.COM 	fctio.fctio_cmd = FCTIO_GET_DISCOVERED_PORT_ATTRIBUTES;
3227836SJohn.Forte@Sun.COM 	fctio.fctio_ilen = 8;
3237836SJohn.Forte@Sun.COM 	fctio.fctio_ibuf = (uint64_t)(uintptr_t)&en_wwn;
3247836SJohn.Forte@Sun.COM 	fctio.fctio_xfer = FCTIO_XFER_READ;
3257836SJohn.Forte@Sun.COM 	fctio.fctio_olen = (uint32_t)(sizeof (attrs));
3267836SJohn.Forte@Sun.COM 	fctio.fctio_obuf = (uint64_t)(uintptr_t)&attrs;
3277836SJohn.Forte@Sun.COM 	fctio.fctio_alen = (uint32_t)(sizeof (discoveredport));
3287836SJohn.Forte@Sun.COM 	fctio.fctio_abuf = (uint64_t)(uintptr_t)&discoveredport;
3297836SJohn.Forte@Sun.COM 
3307836SJohn.Forte@Sun.COM 	fct_ioctl(FCTIO_CMD, &fctio);
3317836SJohn.Forte@Sun.COM 
3327836SJohn.Forte@Sun.COM 	stateChange = attrs.lastChange;
3337836SJohn.Forte@Sun.COM 
3347836SJohn.Forte@Sun.COM 	attributes.PortFcId = attrs.PortFcId;
3357836SJohn.Forte@Sun.COM 	attributes.PortType = attrs.PortType;
3367836SJohn.Forte@Sun.COM 	attributes.PortState = attrs.PortState;
3377836SJohn.Forte@Sun.COM 	attributes.PortSupportedClassofService = attrs.PortSupportedClassofService;
3387836SJohn.Forte@Sun.COM 	attributes.PortSupportedSpeed = attrs.PortSupportedSpeed;
3397836SJohn.Forte@Sun.COM 	attributes.PortSpeed = attrs.PortSpeed;
3407836SJohn.Forte@Sun.COM 	attributes.PortMaxFrameSize = attrs.PortMaxFrameSize;
3417836SJohn.Forte@Sun.COM 	attributes.NumberofDiscoveredPorts = attrs.NumberofDiscoveredPorts;
3427836SJohn.Forte@Sun.COM 	memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
3437836SJohn.Forte@Sun.COM 	memcpy(&attributes.PortWWN, &attrs.PortWWN, 8);
3447836SJohn.Forte@Sun.COM 	memcpy(&attributes.FabricName, &attrs.FabricName, 8);
3457836SJohn.Forte@Sun.COM 	memcpy(&attributes.PortSupportedFc4Types, &attrs.PortSupportedFc4Types, 32);
3467836SJohn.Forte@Sun.COM 	memcpy(&attributes.PortActiveFc4Types, &attrs.PortActiveFc4Types, 32);
3477836SJohn.Forte@Sun.COM 	memcpy(&attributes.PortSymbolicName, &attrs.PortSymbolicName, 256);
3487836SJohn.Forte@Sun.COM 
3497836SJohn.Forte@Sun.COM 
3507836SJohn.Forte@Sun.COM 	return (attributes);
3517836SJohn.Forte@Sun.COM }
3527836SJohn.Forte@Sun.COM 
getDiscoveredAttributes(uint64_t wwn,uint64_t & stateChange)3537836SJohn.Forte@Sun.COM HBA_PORTATTRIBUTES TgtFCHBAPort::getDiscoveredAttributes(
3547836SJohn.Forte@Sun.COM 	    uint64_t wwn, uint64_t &stateChange) {
3557836SJohn.Forte@Sun.COM 	Trace log("TgtFCHBAPort::getDiscoverdAttributes(p)");
3567836SJohn.Forte@Sun.COM 
3577836SJohn.Forte@Sun.COM 	HBA_PORTATTRIBUTES attributes;
3587836SJohn.Forte@Sun.COM 	fctio_t			fctio;
3597836SJohn.Forte@Sun.COM 	fc_tgt_hba_port_attributes_t    attrs;
3607836SJohn.Forte@Sun.COM 
3617836SJohn.Forte@Sun.COM 	memset(&fctio, 0, sizeof (fctio));
3627836SJohn.Forte@Sun.COM 	memset(&attributes, 0, sizeof (attributes));
3637836SJohn.Forte@Sun.COM 
3647836SJohn.Forte@Sun.COM 	uint64_t en_wwn = htonll(wwn);
3657836SJohn.Forte@Sun.COM 
3667836SJohn.Forte@Sun.COM 	fctio.fctio_cmd = FCTIO_GET_PORT_ATTRIBUTES;
3677836SJohn.Forte@Sun.COM 	fctio.fctio_olen = (uint32_t)(sizeof (attrs));
3687836SJohn.Forte@Sun.COM 	fctio.fctio_xfer = FCTIO_XFER_READ;
3697836SJohn.Forte@Sun.COM 	fctio.fctio_obuf = (uint64_t)(uintptr_t)&attrs;
3707836SJohn.Forte@Sun.COM 	fctio.fctio_ilen = (uint32_t)(sizeof (wwn));
3717836SJohn.Forte@Sun.COM 	fctio.fctio_ibuf = (uint64_t)(uintptr_t)&en_wwn;
3727836SJohn.Forte@Sun.COM 
3737836SJohn.Forte@Sun.COM 	fct_ioctl(FCTIO_CMD, &fctio);
3747836SJohn.Forte@Sun.COM 
3757836SJohn.Forte@Sun.COM 	stateChange = attrs.lastChange;
3767836SJohn.Forte@Sun.COM 
3777836SJohn.Forte@Sun.COM 	attributes.PortFcId = attrs.PortFcId;
3787836SJohn.Forte@Sun.COM 	attributes.PortType = attrs.PortType;
3797836SJohn.Forte@Sun.COM 	attributes.PortState = attrs.PortState;
3807836SJohn.Forte@Sun.COM 	attributes.PortSupportedClassofService = attrs.PortSupportedClassofService;
3817836SJohn.Forte@Sun.COM 	attributes.PortSupportedSpeed = attrs.PortSupportedSpeed;
3827836SJohn.Forte@Sun.COM 	attributes.PortSpeed = attrs.PortSpeed;
3837836SJohn.Forte@Sun.COM 	attributes.PortMaxFrameSize = attrs.PortMaxFrameSize;
3847836SJohn.Forte@Sun.COM 	attributes.NumberofDiscoveredPorts = attrs.NumberofDiscoveredPorts;
3857836SJohn.Forte@Sun.COM 	memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
3867836SJohn.Forte@Sun.COM 	memcpy(&attributes.PortWWN, &attrs.PortWWN, 8);
3877836SJohn.Forte@Sun.COM 	memcpy(&attributes.FabricName, &attrs.FabricName, 8);
3887836SJohn.Forte@Sun.COM 	memcpy(&attributes.PortSupportedFc4Types, &attrs.PortSupportedFc4Types, 32);
3897836SJohn.Forte@Sun.COM 	memcpy(&attributes.PortActiveFc4Types, &attrs.PortActiveFc4Types, 32);
3907836SJohn.Forte@Sun.COM 	memcpy(&attributes.PortSymbolicName, &attrs.PortSymbolicName, 256);
3917836SJohn.Forte@Sun.COM 
3927836SJohn.Forte@Sun.COM 
3937836SJohn.Forte@Sun.COM 	return (attributes);
3947836SJohn.Forte@Sun.COM }
3957836SJohn.Forte@Sun.COM 
sendRLS(uint64_t destWWN,void * pRspBuffer,HBA_UINT32 * pRspBufferSize)3967836SJohn.Forte@Sun.COM void TgtFCHBAPort::sendRLS(uint64_t destWWN,
3977836SJohn.Forte@Sun.COM 	    void		*pRspBuffer,
3987836SJohn.Forte@Sun.COM 	    HBA_UINT32		*pRspBufferSize) {
3997836SJohn.Forte@Sun.COM 	Trace log("FCHBAPort::sendRLS");
4007836SJohn.Forte@Sun.COM 
4017836SJohn.Forte@Sun.COM 	fctio_t		fctio;
4027836SJohn.Forte@Sun.COM 	// fc_hba_adapter_port_stats_t	fc_port_stat;
4037836SJohn.Forte@Sun.COM 	uint64_t	en_portWWN;
404*10088SAllan.Ou@Sun.COM 	uint64_t	DestPortID;
4057836SJohn.Forte@Sun.COM 
4067836SJohn.Forte@Sun.COM 	// Validate the arguments
4077836SJohn.Forte@Sun.COM 	if (pRspBuffer == NULL ||
4087836SJohn.Forte@Sun.COM 		pRspBufferSize == NULL) {
4097836SJohn.Forte@Sun.COM 	    log.userError("NULL hba");
4107836SJohn.Forte@Sun.COM 	    throw BadArgumentException();
4117836SJohn.Forte@Sun.COM 	}
4127836SJohn.Forte@Sun.COM 
4137836SJohn.Forte@Sun.COM 	// check to see if we are sending RLS to the HBA
4147836SJohn.Forte@Sun.COM 	HBA_PORTATTRIBUTES attrs;
4157836SJohn.Forte@Sun.COM 	uint64_t tmp;
4167836SJohn.Forte@Sun.COM 	portWWN = getPortWWN();
4177836SJohn.Forte@Sun.COM 	en_portWWN = htonll(portWWN);
4187836SJohn.Forte@Sun.COM 
4197836SJohn.Forte@Sun.COM 	/* The destWWN is either the adapter port or a discovered port. */
4207836SJohn.Forte@Sun.COM 	memset(&fctio, 0, sizeof (fctio));
421*10088SAllan.Ou@Sun.COM 	fctio.fctio_cmd = FCTIO_GET_LINK_STATUS;
4227836SJohn.Forte@Sun.COM 	fctio.fctio_ibuf = (uint64_t)(uintptr_t)&en_portWWN;
4237836SJohn.Forte@Sun.COM 	fctio.fctio_ilen = (uint32_t)(sizeof (en_portWWN));
4247836SJohn.Forte@Sun.COM 	if (portWWN != destWWN) {
4257836SJohn.Forte@Sun.COM 	    attrs = getDiscoveredAttributes(destWWN, tmp);
426*10088SAllan.Ou@Sun.COM 	    DestPortID = (uint64_t)attrs.PortFcId;
427*10088SAllan.Ou@Sun.COM 	    fctio.fctio_abuf = (uint64_t)(uintptr_t)&DestPortID;
428*10088SAllan.Ou@Sun.COM 	    fctio.fctio_alen = (uint32_t)(sizeof (DestPortID));
4297836SJohn.Forte@Sun.COM 	}
4307836SJohn.Forte@Sun.COM 	fctio.fctio_xfer = FCTIO_XFER_READ;
4317836SJohn.Forte@Sun.COM 	fctio.fctio_flags = 0;
4327836SJohn.Forte@Sun.COM 	fctio.fctio_obuf = (uint64_t)(uintptr_t)new uchar_t[*pRspBufferSize];
4337836SJohn.Forte@Sun.COM 	fctio.fctio_olen = *pRspBufferSize;
4347836SJohn.Forte@Sun.COM 
4357836SJohn.Forte@Sun.COM 	if (fctio.fctio_obuf == NULL) {
4367836SJohn.Forte@Sun.COM 	    log.noMemory();
4377836SJohn.Forte@Sun.COM 	    throw InternalError();
4387836SJohn.Forte@Sun.COM 	}
4397836SJohn.Forte@Sun.COM 
4407836SJohn.Forte@Sun.COM 	fct_ioctl(FCTIO_CMD, &fctio);
4417836SJohn.Forte@Sun.COM 	memcpy(pRspBuffer, (uchar_t *)(uintptr_t)fctio.fctio_obuf,
4427836SJohn.Forte@Sun.COM 	       *pRspBufferSize);
4437836SJohn.Forte@Sun.COM 	if (fctio.fctio_obuf != NULL) {
4447836SJohn.Forte@Sun.COM 	    delete((uchar_t *)(uintptr_t)fctio.fctio_obuf);
4457836SJohn.Forte@Sun.COM 	}
4467836SJohn.Forte@Sun.COM }
4477836SJohn.Forte@Sun.COM 
4487836SJohn.Forte@Sun.COM /**
4497836SJohn.Forte@Sun.COM  * @memo	    Validate that the port is still present in the system
4507836SJohn.Forte@Sun.COM  * @exception	    UnavailableException if the port is not present
4517836SJohn.Forte@Sun.COM  * @version	    1.7
4527836SJohn.Forte@Sun.COM  *
4537836SJohn.Forte@Sun.COM  * @doc		    If the port is still present on the system, the routine
4547836SJohn.Forte@Sun.COM  *		    will return normally.  If the port is not present
4557836SJohn.Forte@Sun.COM  *		    an exception will be thrown.
4567836SJohn.Forte@Sun.COM  */
validatePresent()4577836SJohn.Forte@Sun.COM void TgtFCHBAPort::validatePresent() {
4587836SJohn.Forte@Sun.COM 	Trace log("TgtFCHBAPort::validatePresent");
4597836SJohn.Forte@Sun.COM 	// We already got the adapter list through the ioctl
4607836SJohn.Forte@Sun.COM 	// so calling it again to validate it is too expensive.
4617836SJohn.Forte@Sun.COM }
4627836SJohn.Forte@Sun.COM 
fct_ioctl(int cmd,fctio_t * fctio)4637836SJohn.Forte@Sun.COM void TgtFCHBAPort::fct_ioctl(int cmd, fctio_t *fctio) {
4647836SJohn.Forte@Sun.COM 	Trace log("TgtFCHBAPort::fct_ioctl");
4657836SJohn.Forte@Sun.COM 	char fcioErrorString[MAX_FCTIO_MSG_LEN] = "";
4667836SJohn.Forte@Sun.COM 	int fd = HBA::_open(FCT_DRIVER_PATH, O_NDELAY | O_RDONLY);
4677836SJohn.Forte@Sun.COM 	try {
4687836SJohn.Forte@Sun.COM 	    HBA::_ioctl(fd, cmd, (uchar_t *)fctio);
4697836SJohn.Forte@Sun.COM 	    close(fd);
4707836SJohn.Forte@Sun.COM 	    if (fctio->fctio_errno) {
4717836SJohn.Forte@Sun.COM 		throw IOError("IOCTL transport failure");
4727836SJohn.Forte@Sun.COM 	    }
4737836SJohn.Forte@Sun.COM 	} catch (...) {
4747836SJohn.Forte@Sun.COM 	    close(fd);
4757836SJohn.Forte@Sun.COM 	    transportError(fctio->fctio_errno, fcioErrorString);
4767836SJohn.Forte@Sun.COM 	    log.genericIOError("ioctl (0x%x) failed. Transport: \"%s\"", cmd,
4777836SJohn.Forte@Sun.COM 		    fcioErrorString);
4787836SJohn.Forte@Sun.COM 	    switch (fctio->fctio_errno) {
4797836SJohn.Forte@Sun.COM 	    case FC_BADWWN:
4807836SJohn.Forte@Sun.COM 		throw IllegalWWNException();
4817836SJohn.Forte@Sun.COM 	    case FC_BADPORT:
4827836SJohn.Forte@Sun.COM 		throw IllegalWWNException();
4837836SJohn.Forte@Sun.COM 	    case FC_OUTOFBOUNDS:
4847836SJohn.Forte@Sun.COM 		throw IllegalIndexException();
4857836SJohn.Forte@Sun.COM 	    case FC_PBUSY:
4867836SJohn.Forte@Sun.COM 	    case FC_FBUSY:
4877836SJohn.Forte@Sun.COM 	    case FC_TRAN_BUSY:
4887836SJohn.Forte@Sun.COM 	    case FC_STATEC_BUSY:
4897836SJohn.Forte@Sun.COM 	    case FC_DEVICE_BUSY:
4907836SJohn.Forte@Sun.COM 		throw BusyException();
4917836SJohn.Forte@Sun.COM 	    case FC_SUCCESS:
4927836SJohn.Forte@Sun.COM 	    default:
4937836SJohn.Forte@Sun.COM 		throw;
4947836SJohn.Forte@Sun.COM 	    }
4957836SJohn.Forte@Sun.COM 	}
4967836SJohn.Forte@Sun.COM }
497