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*11617SAllan.Ou@Sun.COM * Copyright 2010 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 <FCHBAPort.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/fibre-channel/fcio.h>
437836SJohn.Forte@Sun.COM #include <sys/fibre-channel/ulp/fcp_util.h>
447836SJohn.Forte@Sun.COM #include <sys/fibre-channel/ulp/fcsm.h>
457836SJohn.Forte@Sun.COM #include <sys/fibre-channel/impl/fc_error.h>
467836SJohn.Forte@Sun.COM #include <sys/fibre-channel/fc_appif.h>
477836SJohn.Forte@Sun.COM #include <sys/scsi/generic/commands.h>
487836SJohn.Forte@Sun.COM #include <sys/scsi/impl/commands.h>
497836SJohn.Forte@Sun.COM #include <sys/scsi/impl/sense.h>
507836SJohn.Forte@Sun.COM #include <sys/scsi/generic/inquiry.h>
517836SJohn.Forte@Sun.COM #include <sys/scsi/generic/status.h>
527836SJohn.Forte@Sun.COM #include <errno.h>
537836SJohn.Forte@Sun.COM #include <FCHBANPIVPort.h>
547836SJohn.Forte@Sun.COM
557836SJohn.Forte@Sun.COM
567836SJohn.Forte@Sun.COM using namespace std;
577836SJohn.Forte@Sun.COM
587836SJohn.Forte@Sun.COM const int FCHBAPort::MAX_FCIO_MSG_LEN = 256;
597836SJohn.Forte@Sun.COM const string FCHBAPort::FCSM_DRIVER_PATH = "/devices/pseudo/fcsm@0:fcsm";
607836SJohn.Forte@Sun.COM const string FCHBAPort::FCP_DRIVER_PATH = "/devices/pseudo/fcp@0:fcp";
617836SJohn.Forte@Sun.COM
627836SJohn.Forte@Sun.COM /*
637836SJohn.Forte@Sun.COM * Interpret the error code in the fcio_t structure
647836SJohn.Forte@Sun.COM *
657836SJohn.Forte@Sun.COM * message must be at least MAX_FCIO_MSG_LEN in length.
667836SJohn.Forte@Sun.COM */
677836SJohn.Forte@Sun.COM void
transportError(uint32_t fcio_errno,char * message)687836SJohn.Forte@Sun.COM FCHBAPort::transportError(uint32_t fcio_errno, char *message) {
697836SJohn.Forte@Sun.COM Trace log("transportError");
707836SJohn.Forte@Sun.COM string fcioErrorString;
717836SJohn.Forte@Sun.COM if (message == NULL) {
727836SJohn.Forte@Sun.COM log.internalError("NULL routine argument");
737836SJohn.Forte@Sun.COM return;
747836SJohn.Forte@Sun.COM }
757836SJohn.Forte@Sun.COM switch (fcio_errno) {
767836SJohn.Forte@Sun.COM case (uint32_t)FC_FAILURE:
777836SJohn.Forte@Sun.COM fcioErrorString = "general failure";
787836SJohn.Forte@Sun.COM break;
797836SJohn.Forte@Sun.COM case (uint32_t)FC_FAILURE_SILENT:
807836SJohn.Forte@Sun.COM fcioErrorString = "general failure but fail silently";
817836SJohn.Forte@Sun.COM break;
827836SJohn.Forte@Sun.COM case FC_SUCCESS:
837836SJohn.Forte@Sun.COM fcioErrorString = "successful completion";
847836SJohn.Forte@Sun.COM break;
857836SJohn.Forte@Sun.COM case FC_CAP_ERROR:
867836SJohn.Forte@Sun.COM fcioErrorString = "FCA capability error";
877836SJohn.Forte@Sun.COM break;
887836SJohn.Forte@Sun.COM case FC_CAP_FOUND:
897836SJohn.Forte@Sun.COM fcioErrorString = "FCA capability unsettable";
907836SJohn.Forte@Sun.COM break;
917836SJohn.Forte@Sun.COM case FC_CAP_SETTABLE:
927836SJohn.Forte@Sun.COM fcioErrorString = "FCA capability settable";
937836SJohn.Forte@Sun.COM break;
947836SJohn.Forte@Sun.COM case FC_UNBOUND:
957836SJohn.Forte@Sun.COM fcioErrorString = "unbound stuff";
967836SJohn.Forte@Sun.COM break;
977836SJohn.Forte@Sun.COM case FC_NOMEM:
987836SJohn.Forte@Sun.COM fcioErrorString = "allocation error";
997836SJohn.Forte@Sun.COM break;
1007836SJohn.Forte@Sun.COM case FC_BADPACKET:
1017836SJohn.Forte@Sun.COM fcioErrorString = "invalid packet specified/supplied";
1027836SJohn.Forte@Sun.COM break;
1037836SJohn.Forte@Sun.COM case FC_OFFLINE:
1047836SJohn.Forte@Sun.COM fcioErrorString = "I/O resource unavailable";
1057836SJohn.Forte@Sun.COM break;
1067836SJohn.Forte@Sun.COM case FC_OLDPORT:
1077836SJohn.Forte@Sun.COM fcioErrorString = "operation on non-loop port";
1087836SJohn.Forte@Sun.COM break;
1097836SJohn.Forte@Sun.COM case FC_NO_MAP:
1107836SJohn.Forte@Sun.COM fcioErrorString = "requested map unavailable";
1117836SJohn.Forte@Sun.COM break;
1127836SJohn.Forte@Sun.COM case FC_TRANSPORT_ERROR:
1137836SJohn.Forte@Sun.COM fcioErrorString = "unable to transport I/O";
1147836SJohn.Forte@Sun.COM break;
1157836SJohn.Forte@Sun.COM case FC_ELS_FREJECT:
1167836SJohn.Forte@Sun.COM fcioErrorString = "ELS rejected by a Fabric";
1177836SJohn.Forte@Sun.COM break;
1187836SJohn.Forte@Sun.COM case FC_ELS_PREJECT:
1197836SJohn.Forte@Sun.COM fcioErrorString = "ELS rejected by an N_port";
1207836SJohn.Forte@Sun.COM break;
1217836SJohn.Forte@Sun.COM case FC_ELS_BAD:
1227836SJohn.Forte@Sun.COM fcioErrorString = "ELS rejected by FCA/fctl";
1237836SJohn.Forte@Sun.COM break;
1247836SJohn.Forte@Sun.COM case FC_ELS_MALFORMED:
1257836SJohn.Forte@Sun.COM fcioErrorString = "poorly formed ELS request";
1267836SJohn.Forte@Sun.COM break;
1277836SJohn.Forte@Sun.COM case FC_TOOMANY:
1287836SJohn.Forte@Sun.COM fcioErrorString = "resource request too large";
1297836SJohn.Forte@Sun.COM break;
1307836SJohn.Forte@Sun.COM case FC_UB_BADTOKEN:
1317836SJohn.Forte@Sun.COM fcioErrorString = "invalid unsolicited buffer token";
1327836SJohn.Forte@Sun.COM break;
1337836SJohn.Forte@Sun.COM case FC_UB_ERROR:
1347836SJohn.Forte@Sun.COM fcioErrorString = "invalid unsol buf request";
1357836SJohn.Forte@Sun.COM break;
1367836SJohn.Forte@Sun.COM case FC_UB_BUSY:
1377836SJohn.Forte@Sun.COM fcioErrorString = "buffer already in use";
1387836SJohn.Forte@Sun.COM break;
1397836SJohn.Forte@Sun.COM case FC_BADULP:
1407836SJohn.Forte@Sun.COM fcioErrorString = "Unknown ulp";
1417836SJohn.Forte@Sun.COM break;
1427836SJohn.Forte@Sun.COM case FC_BADTYPE:
1437836SJohn.Forte@Sun.COM fcioErrorString = "ULP not registered to handle this FC4 type";
1447836SJohn.Forte@Sun.COM break;
1457836SJohn.Forte@Sun.COM case FC_UNCLAIMED:
1467836SJohn.Forte@Sun.COM fcioErrorString = "request or data not claimed";
1477836SJohn.Forte@Sun.COM break;
1487836SJohn.Forte@Sun.COM case FC_ULP_SAMEMODULE:
1497836SJohn.Forte@Sun.COM fcioErrorString = "module already in use";
1507836SJohn.Forte@Sun.COM break;
1517836SJohn.Forte@Sun.COM case FC_ULP_SAMETYPE:
1527836SJohn.Forte@Sun.COM fcioErrorString = "FC4 module already in use";
1537836SJohn.Forte@Sun.COM break;
1547836SJohn.Forte@Sun.COM case FC_ABORTED:
1557836SJohn.Forte@Sun.COM fcioErrorString = "request aborted";
1567836SJohn.Forte@Sun.COM break;
1577836SJohn.Forte@Sun.COM case FC_ABORT_FAILED:
1587836SJohn.Forte@Sun.COM fcioErrorString = "abort request failed";
1597836SJohn.Forte@Sun.COM break;
1607836SJohn.Forte@Sun.COM case FC_BADEXCHANGE:
1617836SJohn.Forte@Sun.COM fcioErrorString = "exchange doesn�t exist";
1627836SJohn.Forte@Sun.COM break;
1637836SJohn.Forte@Sun.COM case FC_BADWWN:
1647836SJohn.Forte@Sun.COM fcioErrorString = "WWN not recognized";
1657836SJohn.Forte@Sun.COM break;
1667836SJohn.Forte@Sun.COM case FC_BADDEV:
1677836SJohn.Forte@Sun.COM fcioErrorString = "device unrecognized";
1687836SJohn.Forte@Sun.COM break;
1697836SJohn.Forte@Sun.COM case FC_BADCMD:
1707836SJohn.Forte@Sun.COM fcioErrorString = "invalid command issued";
1717836SJohn.Forte@Sun.COM break;
1727836SJohn.Forte@Sun.COM case FC_BADOBJECT:
1737836SJohn.Forte@Sun.COM fcioErrorString = "invalid object requested";
1747836SJohn.Forte@Sun.COM break;
1757836SJohn.Forte@Sun.COM case FC_BADPORT:
1767836SJohn.Forte@Sun.COM fcioErrorString = "invalid port specified";
1777836SJohn.Forte@Sun.COM break;
1787836SJohn.Forte@Sun.COM case FC_NOTTHISPORT:
1797836SJohn.Forte@Sun.COM fcioErrorString = "resource not at this port";
1807836SJohn.Forte@Sun.COM break;
1817836SJohn.Forte@Sun.COM case FC_PREJECT:
1827836SJohn.Forte@Sun.COM fcioErrorString = "reject at remote N_Port";
1837836SJohn.Forte@Sun.COM break;
1847836SJohn.Forte@Sun.COM case FC_FREJECT:
1857836SJohn.Forte@Sun.COM fcioErrorString = "reject at remote Fabric";
1867836SJohn.Forte@Sun.COM break;
1877836SJohn.Forte@Sun.COM case FC_PBUSY:
1887836SJohn.Forte@Sun.COM fcioErrorString = "remote N_Port busy";
1897836SJohn.Forte@Sun.COM break;
1907836SJohn.Forte@Sun.COM case FC_FBUSY:
1917836SJohn.Forte@Sun.COM fcioErrorString = "remote Fabric busy";
1927836SJohn.Forte@Sun.COM break;
1937836SJohn.Forte@Sun.COM case FC_ALREADY:
1947836SJohn.Forte@Sun.COM fcioErrorString = "already logged in";
1957836SJohn.Forte@Sun.COM break;
1967836SJohn.Forte@Sun.COM case FC_LOGINREQ:
1977836SJohn.Forte@Sun.COM fcioErrorString = "login required";
1987836SJohn.Forte@Sun.COM break;
1997836SJohn.Forte@Sun.COM case FC_RESETFAIL:
2007836SJohn.Forte@Sun.COM fcioErrorString = "reset failed";
2017836SJohn.Forte@Sun.COM break;
2027836SJohn.Forte@Sun.COM case FC_INVALID_REQUEST:
2037836SJohn.Forte@Sun.COM fcioErrorString = "request is invalid";
2047836SJohn.Forte@Sun.COM break;
2057836SJohn.Forte@Sun.COM case FC_OUTOFBOUNDS:
2067836SJohn.Forte@Sun.COM fcioErrorString = "port number is out of bounds";
2077836SJohn.Forte@Sun.COM break;
2087836SJohn.Forte@Sun.COM case FC_TRAN_BUSY:
2097836SJohn.Forte@Sun.COM fcioErrorString = "command transport busy";
2107836SJohn.Forte@Sun.COM break;
2117836SJohn.Forte@Sun.COM case FC_STATEC_BUSY:
2127836SJohn.Forte@Sun.COM fcioErrorString = "port driver currently busy";
2137836SJohn.Forte@Sun.COM break;
2147836SJohn.Forte@Sun.COM case FC_DEVICE_BUSY:
2157836SJohn.Forte@Sun.COM fcioErrorString = "transport working on this device";
2167836SJohn.Forte@Sun.COM break;
2177836SJohn.Forte@Sun.COM case FC_DEVICE_NOT_TGT:
2187836SJohn.Forte@Sun.COM fcioErrorString = "device is not a SCSI target";
2197836SJohn.Forte@Sun.COM break;
2207836SJohn.Forte@Sun.COM default:
2217836SJohn.Forte@Sun.COM snprintf(message, MAX_FCIO_MSG_LEN, "Unknown error code 0x%x",
2227836SJohn.Forte@Sun.COM fcio_errno);
2237836SJohn.Forte@Sun.COM return;
2247836SJohn.Forte@Sun.COM }
2257836SJohn.Forte@Sun.COM snprintf(message, MAX_FCIO_MSG_LEN, "%s", fcioErrorString.c_str());
2267836SJohn.Forte@Sun.COM }
2277836SJohn.Forte@Sun.COM
2287836SJohn.Forte@Sun.COM static void
reportSense(struct scsi_extended_sense * sense,const char * routine)2297836SJohn.Forte@Sun.COM reportSense(struct scsi_extended_sense *sense, const char *routine) {
2307836SJohn.Forte@Sun.COM Trace log("reportSense");
2317836SJohn.Forte@Sun.COM string msg;
2327836SJohn.Forte@Sun.COM if (!sense) {
2337836SJohn.Forte@Sun.COM log.internalError("NULL sense argument passed.");
2347836SJohn.Forte@Sun.COM return;
2357836SJohn.Forte@Sun.COM }
2367836SJohn.Forte@Sun.COM if (!routine) {
2377836SJohn.Forte@Sun.COM log.internalError("NULL routine argument passed.");
2387836SJohn.Forte@Sun.COM return;
2397836SJohn.Forte@Sun.COM }
2407836SJohn.Forte@Sun.COM log.genericIOError("SCSI FAILURE");
2417836SJohn.Forte@Sun.COM switch (sense->es_key) {
2427836SJohn.Forte@Sun.COM case KEY_NO_SENSE:
2437836SJohn.Forte@Sun.COM msg = "No sense";
2447836SJohn.Forte@Sun.COM break;
2457836SJohn.Forte@Sun.COM case KEY_RECOVERABLE_ERROR:
2467836SJohn.Forte@Sun.COM msg = "Recoverable error";
2477836SJohn.Forte@Sun.COM break;
2487836SJohn.Forte@Sun.COM case KEY_NOT_READY:
2497836SJohn.Forte@Sun.COM msg = "Not ready";
2507836SJohn.Forte@Sun.COM break;
2517836SJohn.Forte@Sun.COM case KEY_MEDIUM_ERROR:
2527836SJohn.Forte@Sun.COM msg = "Medium error";
2537836SJohn.Forte@Sun.COM break;
2547836SJohn.Forte@Sun.COM case KEY_HARDWARE_ERROR:
2557836SJohn.Forte@Sun.COM msg = "Hardware error";
2567836SJohn.Forte@Sun.COM break;
2577836SJohn.Forte@Sun.COM case KEY_ILLEGAL_REQUEST:
2587836SJohn.Forte@Sun.COM msg = "Illegal request";
2597836SJohn.Forte@Sun.COM break;
2607836SJohn.Forte@Sun.COM case KEY_UNIT_ATTENTION:
2617836SJohn.Forte@Sun.COM msg = "Unit attention";
2627836SJohn.Forte@Sun.COM break;
2637836SJohn.Forte@Sun.COM case KEY_DATA_PROTECT:
2647836SJohn.Forte@Sun.COM msg = "Data protect";
2657836SJohn.Forte@Sun.COM break;
2667836SJohn.Forte@Sun.COM case KEY_BLANK_CHECK:
2677836SJohn.Forte@Sun.COM msg = "Blank check";
2687836SJohn.Forte@Sun.COM break;
2697836SJohn.Forte@Sun.COM case KEY_VENDOR_UNIQUE:
2707836SJohn.Forte@Sun.COM msg = "Vendor Unique";
2717836SJohn.Forte@Sun.COM break;
2727836SJohn.Forte@Sun.COM case KEY_COPY_ABORTED:
2737836SJohn.Forte@Sun.COM msg = "Copy aborted";
2747836SJohn.Forte@Sun.COM break;
2757836SJohn.Forte@Sun.COM case KEY_ABORTED_COMMAND:
2767836SJohn.Forte@Sun.COM msg = "Aborted command";
2777836SJohn.Forte@Sun.COM break;
2787836SJohn.Forte@Sun.COM case KEY_EQUAL:
2797836SJohn.Forte@Sun.COM msg = "Equal";
2807836SJohn.Forte@Sun.COM break;
2817836SJohn.Forte@Sun.COM case KEY_VOLUME_OVERFLOW:
2827836SJohn.Forte@Sun.COM msg = "Volume overflow";
2837836SJohn.Forte@Sun.COM break;
2847836SJohn.Forte@Sun.COM case KEY_MISCOMPARE:
2857836SJohn.Forte@Sun.COM msg = "Miscompare";
2867836SJohn.Forte@Sun.COM break;
2877836SJohn.Forte@Sun.COM case KEY_RESERVED:
2887836SJohn.Forte@Sun.COM msg = "Reserved";
2897836SJohn.Forte@Sun.COM break;
2907836SJohn.Forte@Sun.COM default:
2917836SJohn.Forte@Sun.COM msg = "unknown sense key";
2927836SJohn.Forte@Sun.COM }
2937836SJohn.Forte@Sun.COM log.genericIOError("\tSense key: %s", msg.c_str());
2947836SJohn.Forte@Sun.COM log.genericIOError("\tASC = 0x%x", sense->es_add_code);
2957836SJohn.Forte@Sun.COM log.genericIOError("\tASCQ = 0x%x", sense->es_qual_code);
2967836SJohn.Forte@Sun.COM }
2977836SJohn.Forte@Sun.COM
2987836SJohn.Forte@Sun.COM /*
2997836SJohn.Forte@Sun.COM * Issue a SCSI pass thru command.
3007836SJohn.Forte@Sun.COM * Returns a scsi status value.
3017836SJohn.Forte@Sun.COM */
sendSCSIPassThru(struct fcp_scsi_cmd * fscsi,HBA_UINT32 * responseSize,HBA_UINT32 * senseSize,HBA_UINT8 * scsiStatus)3027836SJohn.Forte@Sun.COM void FCHBAPort::sendSCSIPassThru(struct fcp_scsi_cmd *fscsi,
3037836SJohn.Forte@Sun.COM HBA_UINT32 *responseSize, HBA_UINT32 *senseSize,
3047836SJohn.Forte@Sun.COM HBA_UINT8 *scsiStatus) {
3057836SJohn.Forte@Sun.COM Trace log("FCHBAPort::sendSCSIPassThru");
3067836SJohn.Forte@Sun.COM int fd;
3077836SJohn.Forte@Sun.COM HBA_STATUS ret;
3087836SJohn.Forte@Sun.COM int count;
3097836SJohn.Forte@Sun.COM char fcioErrorString[MAX_FCIO_MSG_LEN] = "";
3107836SJohn.Forte@Sun.COM hrtime_t start;
3117836SJohn.Forte@Sun.COM hrtime_t end;
3127836SJohn.Forte@Sun.COM int ioctl_errno;
3137836SJohn.Forte@Sun.COM double duration;
3147836SJohn.Forte@Sun.COM la_wwn_t wwn;
3157836SJohn.Forte@Sun.COM
3167836SJohn.Forte@Sun.COM if (fscsi == NULL ||
3177836SJohn.Forte@Sun.COM responseSize == NULL ||
3187836SJohn.Forte@Sun.COM senseSize == NULL ||
3197836SJohn.Forte@Sun.COM scsiStatus == NULL) {
3207836SJohn.Forte@Sun.COM throw BadArgumentException();
3217836SJohn.Forte@Sun.COM }
3227836SJohn.Forte@Sun.COM
3237836SJohn.Forte@Sun.COM memcpy(&wwn, fscsi->scsi_fc_pwwn.raw_wwn, sizeof (la_wwn_t));
3247836SJohn.Forte@Sun.COM start = gethrtime();
3257836SJohn.Forte@Sun.COM fscsi->scsi_fc_port_num = instanceNumber;
3267836SJohn.Forte@Sun.COM
3277836SJohn.Forte@Sun.COM fd = HBA::_open(FCP_DRIVER_PATH, O_RDONLY | O_NDELAY);
3287836SJohn.Forte@Sun.COM count = 0;
3297836SJohn.Forte@Sun.COM ioctl_errno = 0;
3307836SJohn.Forte@Sun.COM
3317836SJohn.Forte@Sun.COM if (ioctl(fd, FCP_TGT_SEND_SCSI, fscsi) != 0) {
3327836SJohn.Forte@Sun.COM /* save off errno */
3337836SJohn.Forte@Sun.COM ioctl_errno = errno;
3347836SJohn.Forte@Sun.COM close(fd);
3357836SJohn.Forte@Sun.COM /*
3367836SJohn.Forte@Sun.COM * collect SCSI status first regrardless of the value.
3377836SJohn.Forte@Sun.COM * 0 is a good status so this should be okay
3387836SJohn.Forte@Sun.COM */
3397836SJohn.Forte@Sun.COM *scsiStatus = fscsi->scsi_bufstatus & STATUS_MASK;
3407836SJohn.Forte@Sun.COM transportError(fscsi->scsi_fc_status, fcioErrorString);
3417836SJohn.Forte@Sun.COM
3427836SJohn.Forte@Sun.COM /* Did we get a check condition? */
3437836SJohn.Forte@Sun.COM if ((fscsi->scsi_bufstatus & STATUS_MASK) == STATUS_CHECK) {
3447836SJohn.Forte@Sun.COM *senseSize = fscsi->scsi_rqlen;
3457836SJohn.Forte@Sun.COM throw CheckConditionException();
3467836SJohn.Forte@Sun.COM } else if (fscsi->scsi_fc_status == FC_DEVICE_NOT_TGT) {
3477836SJohn.Forte@Sun.COM /*
3487836SJohn.Forte@Sun.COM * fcp driver returns FC_DEVICE_NOT_TGT when the node is not
3497836SJohn.Forte@Sun.COM * scsi-capable like remote hba nodes.
3507836SJohn.Forte@Sun.COM */
3517836SJohn.Forte@Sun.COM throw NotATargetException();
3527836SJohn.Forte@Sun.COM } else if (fscsi->scsi_fc_status == FC_INVALID_LUN) {
3537836SJohn.Forte@Sun.COM throw InvalidLUNException();
3547836SJohn.Forte@Sun.COM } else if (ioctl_errno == EBUSY) {
3557836SJohn.Forte@Sun.COM throw BusyException();
3567836SJohn.Forte@Sun.COM } else if (ioctl_errno == EAGAIN) {
3577836SJohn.Forte@Sun.COM throw TryAgainException();
3587836SJohn.Forte@Sun.COM } else if (ioctl_errno == ENOTSUP) {
3597836SJohn.Forte@Sun.COM throw NotSupportedException();
3607836SJohn.Forte@Sun.COM } else if (ioctl_errno == ENOENT) {
3617836SJohn.Forte@Sun.COM throw UnavailableException();
3627836SJohn.Forte@Sun.COM } else {
3637836SJohn.Forte@Sun.COM throw IOError(this, wwnConversion(wwn.raw_wwn),
3647836SJohn.Forte@Sun.COM fscsi->scsi_lun);
3657836SJohn.Forte@Sun.COM }
3667836SJohn.Forte@Sun.COM } else {
3677836SJohn.Forte@Sun.COM close(fd);
3687836SJohn.Forte@Sun.COM /* Just in case, check for a check-condition state */
3697836SJohn.Forte@Sun.COM if ((fscsi->scsi_bufstatus & STATUS_MASK) == STATUS_CHECK) {
3707836SJohn.Forte@Sun.COM *scsiStatus = fscsi->scsi_bufstatus & STATUS_MASK;
3717836SJohn.Forte@Sun.COM *senseSize = fscsi->scsi_rqlen;
3727836SJohn.Forte@Sun.COM throw CheckConditionException();
3737836SJohn.Forte@Sun.COM }
3747836SJohn.Forte@Sun.COM }
3757836SJohn.Forte@Sun.COM
3767836SJohn.Forte@Sun.COM /* Record the response data */
3777836SJohn.Forte@Sun.COM *scsiStatus = fscsi->scsi_bufstatus & STATUS_MASK;
3787836SJohn.Forte@Sun.COM *responseSize = fscsi->scsi_buflen;
3797836SJohn.Forte@Sun.COM *senseSize = fscsi->scsi_rqlen;
3807836SJohn.Forte@Sun.COM
3817836SJohn.Forte@Sun.COM /* Do some quick duration calcuations */
3827836SJohn.Forte@Sun.COM end = gethrtime();
3837836SJohn.Forte@Sun.COM duration = end - start;
3847836SJohn.Forte@Sun.COM duration /= HR_SECOND;
3857836SJohn.Forte@Sun.COM log.debug("Total SCSI IO time for HBA %s "
3867836SJohn.Forte@Sun.COM "target %016llx was %.4f seconds", getPath().c_str(),
3877836SJohn.Forte@Sun.COM wwnConversion(wwn.raw_wwn), duration);
3887836SJohn.Forte@Sun.COM
3897836SJohn.Forte@Sun.COM #ifdef DEBUG
3907836SJohn.Forte@Sun.COM /* Did we have any failure */
3917836SJohn.Forte@Sun.COM if (ret != HBA_STATUS_OK) {
3927836SJohn.Forte@Sun.COM log.genericIOError(
3937836SJohn.Forte@Sun.COM "Ioctl failed for device \"%s\" target %016llx."
3947836SJohn.Forte@Sun.COM " Errno: \"%s\"(%d), "
3957836SJohn.Forte@Sun.COM "Transport: \"%s\", SCSI Status: 0x%x"
3967836SJohn.Forte@Sun.COM "responseSize = %d, senseSize = %d",
3977836SJohn.Forte@Sun.COM getPath().c_str(), wwnConversion(fscsi->scsi_fc_pwwn.raw_wwn),
3987836SJohn.Forte@Sun.COM strerror(ioctl_errno), ioctl_errno, fcioErrorString,
3997836SJohn.Forte@Sun.COM *scsiStatus, *responseSize, *senseSize);
4007836SJohn.Forte@Sun.COM /* We may or may not have sense data */
4017836SJohn.Forte@Sun.COM reportSense((struct scsi_extended_sense *)fscsi->scsi_rqbufaddr,
4027836SJohn.Forte@Sun.COM ROUTINE);
4037836SJohn.Forte@Sun.COM }
4047836SJohn.Forte@Sun.COM #endif
4057836SJohn.Forte@Sun.COM
4067836SJohn.Forte@Sun.COM }
4077836SJohn.Forte@Sun.COM
4087836SJohn.Forte@Sun.COM /*
4097836SJohn.Forte@Sun.COM * constructs the fcp_scsi_cmd struct for SCSI_Inquiry, SendReadCapacity, or
4107836SJohn.Forte@Sun.COM * SendReportLUNs
4117836SJohn.Forte@Sun.COM */
4127836SJohn.Forte@Sun.COM /*#include <fcio.h>
4137836SJohn.Forte@Sun.COM #include <fcp_util.h>*/
4147836SJohn.Forte@Sun.COM inline void
scsi_cmd_init(struct fcp_scsi_cmd * fscsi,const char * portname,void * reqbuf,size_t req_len,void * responseBuffer,size_t resp_len,void * senseBuffer,size_t sense_len)4157836SJohn.Forte@Sun.COM scsi_cmd_init(struct fcp_scsi_cmd *fscsi, const char *portname, void *reqbuf,
4167836SJohn.Forte@Sun.COM size_t req_len, void *responseBuffer, size_t resp_len,
4177836SJohn.Forte@Sun.COM void *senseBuffer, size_t sense_len) {
4187836SJohn.Forte@Sun.COM Trace log("scsi_cmd_init");
4197836SJohn.Forte@Sun.COM fscsi->scsi_fc_rspcode = 0;
4207836SJohn.Forte@Sun.COM fscsi->scsi_flags = FCP_SCSI_READ;
4217836SJohn.Forte@Sun.COM fscsi->scsi_timeout = 10 /* sec */;
4227836SJohn.Forte@Sun.COM fscsi->scsi_cdbbufaddr = (char *)reqbuf;
4237836SJohn.Forte@Sun.COM fscsi->scsi_cdblen = (uint32_t) req_len;
4247836SJohn.Forte@Sun.COM fscsi->scsi_bufaddr = (char *)responseBuffer;
4257836SJohn.Forte@Sun.COM fscsi->scsi_buflen = (uint32_t) resp_len;
4267836SJohn.Forte@Sun.COM fscsi->scsi_bufresid = 0;
4277836SJohn.Forte@Sun.COM fscsi->scsi_bufstatus = 0;
4287836SJohn.Forte@Sun.COM fscsi->scsi_rqbufaddr = (char *)senseBuffer;
4297836SJohn.Forte@Sun.COM fscsi->scsi_rqlen = (uint32_t) sense_len;
4307836SJohn.Forte@Sun.COM fscsi->scsi_rqresid = 0;
4317836SJohn.Forte@Sun.COM }
4327836SJohn.Forte@Sun.COM
4337836SJohn.Forte@Sun.COM
FCHBAPort(string thePath)4347836SJohn.Forte@Sun.COM FCHBAPort::FCHBAPort(string thePath) : HBAPort() {
4357836SJohn.Forte@Sun.COM Trace log("FCHBAPort::FCHBAPort");
4367836SJohn.Forte@Sun.COM log.debug("Initializing HBA port %s", thePath.c_str());
4377836SJohn.Forte@Sun.COM fcio_t fcio;
4387836SJohn.Forte@Sun.COM int size = 200;
4397836SJohn.Forte@Sun.COM fc_hba_npiv_port_list_t *pathList;
4407836SJohn.Forte@Sun.COM bool retry = false;
4417836SJohn.Forte@Sun.COM int bufSize;
4427836SJohn.Forte@Sun.COM
4437836SJohn.Forte@Sun.COM try {
4447836SJohn.Forte@Sun.COM path = lookupControllerPath(thePath);
4457836SJohn.Forte@Sun.COM sscanf(path.c_str(), "/dev/cfg/c%d", &controllerNumber);
4467836SJohn.Forte@Sun.COM } catch (...) {
4477836SJohn.Forte@Sun.COM log.debug("Unable to lookup controller path and number for %s",
4487836SJohn.Forte@Sun.COM thePath.c_str());
4497836SJohn.Forte@Sun.COM path = "/devices";
4507836SJohn.Forte@Sun.COM path += thePath;
4517836SJohn.Forte@Sun.COM path += ":fc";
4527836SJohn.Forte@Sun.COM controllerNumber = -1;
4537836SJohn.Forte@Sun.COM }
4547836SJohn.Forte@Sun.COM
4557836SJohn.Forte@Sun.COM // Fetch the minor number for later use
4567836SJohn.Forte@Sun.COM struct stat sbuf;
4577836SJohn.Forte@Sun.COM if (stat(path.c_str(), &sbuf) == -1) {
4587836SJohn.Forte@Sun.COM throw IOError("Unable to stat device path: " + path);
4597836SJohn.Forte@Sun.COM }
4607836SJohn.Forte@Sun.COM instanceNumber = minor(sbuf.st_rdev);
4617836SJohn.Forte@Sun.COM
4627836SJohn.Forte@Sun.COM // This routine is not index based, so we can discard stateChange
4637836SJohn.Forte@Sun.COM uint64_t tmp;
4647836SJohn.Forte@Sun.COM HBA_PORTATTRIBUTES attrs = getPortAttributes(tmp);
4657836SJohn.Forte@Sun.COM memcpy(&tmp, &attrs.PortWWN, 8);
4667836SJohn.Forte@Sun.COM portWWN = ntohll(tmp);
4677836SJohn.Forte@Sun.COM memcpy(&tmp, &attrs.NodeWWN, 8);
4687836SJohn.Forte@Sun.COM nodeWWN = ntohll(tmp);
4697836SJohn.Forte@Sun.COM
4707836SJohn.Forte@Sun.COM // For reference, here's how to dump WWN's through C++ streams.
4717836SJohn.Forte@Sun.COM // cout << "\tPort WWN: " << hex << setfill('0') << setw(16) << portWWN
4727836SJohn.Forte@Sun.COM // << endl;
4737836SJohn.Forte@Sun.COM // cout << "\tNode WWN: " << hex << setfill('0') << setw(16) << nodeWWN
4747836SJohn.Forte@Sun.COM // << endl;
4757836SJohn.Forte@Sun.COM
4767836SJohn.Forte@Sun.COM // we should add code here to build NPIVPORT instance
4777836SJohn.Forte@Sun.COM // Get Port's NPIV port list ( include nwwn and pwwn and path)
4787836SJohn.Forte@Sun.COM memset((caddr_t)&fcio, 0, sizeof (fcio));
4797836SJohn.Forte@Sun.COM fcio.fcio_cmd = FCIO_GET_NPIV_PORT_LIST;
4807836SJohn.Forte@Sun.COM fcio.fcio_xfer = FCIO_XFER_READ;
4817836SJohn.Forte@Sun.COM do {
4827836SJohn.Forte@Sun.COM retry = false;
483*11617SAllan.Ou@Sun.COM bufSize = MAXPATHLEN * (size - 1) + (int) sizeof (fc_hba_npiv_port_list_t);
4847836SJohn.Forte@Sun.COM pathList = (fc_hba_npiv_port_list_t *) new uchar_t[bufSize];
4857836SJohn.Forte@Sun.COM pathList->numAdapters = size;
4867836SJohn.Forte@Sun.COM fcio.fcio_olen = bufSize;
4877836SJohn.Forte@Sun.COM fcio.fcio_obuf = (char *)pathList;
4887836SJohn.Forte@Sun.COM fp_ioctl(getPath(), FCIO_CMD, &fcio);
4897836SJohn.Forte@Sun.COM if (pathList->numAdapters > size) {
4907836SJohn.Forte@Sun.COM log.debug("Buffer too small for number of NPIV Port.Retry.");
4917836SJohn.Forte@Sun.COM size = pathList->numAdapters;
4927836SJohn.Forte@Sun.COM retry = true;
4937836SJohn.Forte@Sun.COM delete (pathList);
4947836SJohn.Forte@Sun.COM }
4957836SJohn.Forte@Sun.COM } while (retry);
4967836SJohn.Forte@Sun.COM log.debug("Get %d npiv ports", pathList->numAdapters);
4977836SJohn.Forte@Sun.COM // Make instance for each NPIV Port
4987836SJohn.Forte@Sun.COM for ( int i = 0; i < pathList->numAdapters; i++) {
4997836SJohn.Forte@Sun.COM try {
5007836SJohn.Forte@Sun.COM addPort(new FCHBANPIVPort(pathList->hbaPaths[i]));
5017836SJohn.Forte@Sun.COM } catch (...) {
5027836SJohn.Forte@Sun.COM log.debug("Ignoring partial failure");
5037836SJohn.Forte@Sun.COM }
5047836SJohn.Forte@Sun.COM }
5057836SJohn.Forte@Sun.COM delete (pathList);
5067836SJohn.Forte@Sun.COM }
5077836SJohn.Forte@Sun.COM
deleteNPIVPort(uint64_t vportwwn)5087836SJohn.Forte@Sun.COM uint32_t FCHBAPort::deleteNPIVPort(uint64_t vportwwn) {
5097836SJohn.Forte@Sun.COM Trace log("FCHBAPort::deleteNPIVPort");
5107836SJohn.Forte@Sun.COM fcio_t fcio;
5117836SJohn.Forte@Sun.COM la_wwn_t lawwn[1];
5127836SJohn.Forte@Sun.COM int ret = 0;
5137836SJohn.Forte@Sun.COM
5147836SJohn.Forte@Sun.COM memset(&fcio, 0, sizeof(fcio));
5157836SJohn.Forte@Sun.COM uint64_t en_wwn = htonll(vportwwn);
5167836SJohn.Forte@Sun.COM memcpy(&lawwn[0], &en_wwn, sizeof (en_wwn));
5177836SJohn.Forte@Sun.COM
5187836SJohn.Forte@Sun.COM fcio.fcio_cmd = FCIO_DELETE_NPIV_PORT;
5197836SJohn.Forte@Sun.COM fcio.fcio_xfer = FCIO_XFER_WRITE;
5207836SJohn.Forte@Sun.COM fcio.fcio_ilen = sizeof (la_wwn_t) * 2;
5217836SJohn.Forte@Sun.COM fcio.fcio_ibuf = (caddr_t)&lawwn;
5227836SJohn.Forte@Sun.COM
5237836SJohn.Forte@Sun.COM fp_ioctl(getPath(), FCIO_CMD, &fcio);
5247836SJohn.Forte@Sun.COM
5257836SJohn.Forte@Sun.COM return (ret);
5267836SJohn.Forte@Sun.COM }
5277836SJohn.Forte@Sun.COM
createNPIVPort(uint64_t vnodewwn,uint64_t vportwwn,uint32_t vindex)5287836SJohn.Forte@Sun.COM uint32_t FCHBAPort::createNPIVPort(uint64_t vnodewwn, uint64_t vportwwn, uint32_t vindex) {
5297836SJohn.Forte@Sun.COM Trace log("FCHBAPort::createNPIVPort");
5307836SJohn.Forte@Sun.COM fcio_t fcio;
5317836SJohn.Forte@Sun.COM la_wwn_t lawwn[2];
5327836SJohn.Forte@Sun.COM uint32_t vportindex = 0;
5337836SJohn.Forte@Sun.COM HBA_NPIVCREATEENTRY entrybuf;
5347836SJohn.Forte@Sun.COM
5357836SJohn.Forte@Sun.COM memset(&fcio, 0, sizeof(fcio));
5367836SJohn.Forte@Sun.COM uint64_t en_wwn = htonll(vnodewwn);
5377836SJohn.Forte@Sun.COM memcpy(&entrybuf.VNodeWWN, &en_wwn, sizeof (en_wwn));
5387836SJohn.Forte@Sun.COM en_wwn = htonll(vportwwn);
5397836SJohn.Forte@Sun.COM memcpy(&entrybuf.VPortWWN, &en_wwn, sizeof (en_wwn));
5407836SJohn.Forte@Sun.COM entrybuf.vindex = vindex;
5417836SJohn.Forte@Sun.COM
5427836SJohn.Forte@Sun.COM fcio.fcio_cmd = FCIO_CREATE_NPIV_PORT;
5437836SJohn.Forte@Sun.COM fcio.fcio_xfer = FCIO_XFER_READ;
5447836SJohn.Forte@Sun.COM fcio.fcio_olen = sizeof (uint32_t);
5457836SJohn.Forte@Sun.COM fcio.fcio_obuf = (caddr_t)&vportindex;
5467836SJohn.Forte@Sun.COM fcio.fcio_ilen = sizeof (HBA_NPIVCREATEENTRY);
5477836SJohn.Forte@Sun.COM fcio.fcio_ibuf = (caddr_t)&entrybuf;
5487836SJohn.Forte@Sun.COM
5497836SJohn.Forte@Sun.COM fp_ioctl(getPath(), FCIO_CMD, &fcio);
5507836SJohn.Forte@Sun.COM
5517836SJohn.Forte@Sun.COM return (vportindex);
5527836SJohn.Forte@Sun.COM }
5537836SJohn.Forte@Sun.COM
getPortNPIVAttributes(uint64_t & stateChange)5547836SJohn.Forte@Sun.COM HBA_PORTNPIVATTRIBUTES FCHBAPort::getPortNPIVAttributes(uint64_t &stateChange) {
5557836SJohn.Forte@Sun.COM Trace log("FCHBAPort::getPortNPIVAttributes");
5567836SJohn.Forte@Sun.COM
5577836SJohn.Forte@Sun.COM HBA_PORTNPIVATTRIBUTES attributes;
5587836SJohn.Forte@Sun.COM fc_hba_port_npiv_attributes_t attrs;
5597836SJohn.Forte@Sun.COM fcio_t fcio;
5607836SJohn.Forte@Sun.COM
5617836SJohn.Forte@Sun.COM memset(&fcio, 0, sizeof(fcio));
5627836SJohn.Forte@Sun.COM memset(&attributes, 0, sizeof(attributes));
5637836SJohn.Forte@Sun.COM
5647836SJohn.Forte@Sun.COM fcio.fcio_cmd = FCIO_GET_ADAPTER_PORT_NPIV_ATTRIBUTES;
5657836SJohn.Forte@Sun.COM fcio.fcio_olen = sizeof(attrs);
5667836SJohn.Forte@Sun.COM fcio.fcio_xfer = FCIO_XFER_READ;
5677836SJohn.Forte@Sun.COM fcio.fcio_obuf = (caddr_t)&attrs;
5687836SJohn.Forte@Sun.COM
5697836SJohn.Forte@Sun.COM fp_ioctl(getPath(), FCIO_CMD, &fcio);
5707836SJohn.Forte@Sun.COM
5717836SJohn.Forte@Sun.COM stateChange = attrs.lastChange;
5727836SJohn.Forte@Sun.COM attributes.npivflag = attrs.npivflag;
5737836SJohn.Forte@Sun.COM memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
5747836SJohn.Forte@Sun.COM memcpy(&attributes.PortWWN, &attrs.PortWWN, 8);
5757836SJohn.Forte@Sun.COM attributes.MaxNumberOfNPIVPorts = attrs.MaxNumberOfNPIVPorts;
5767836SJohn.Forte@Sun.COM attributes.NumberOfNPIVPorts = attrs.NumberOfNPIVPorts;
5777836SJohn.Forte@Sun.COM
5787836SJohn.Forte@Sun.COM return (attributes);
5797836SJohn.Forte@Sun.COM }
5807836SJohn.Forte@Sun.COM
getPortAttributes(uint64_t & stateChange)5817836SJohn.Forte@Sun.COM HBA_PORTATTRIBUTES FCHBAPort::getPortAttributes(uint64_t &stateChange) {
5827836SJohn.Forte@Sun.COM Trace log("FCHBAPort::getPortAttributes");
5837836SJohn.Forte@Sun.COM
5847836SJohn.Forte@Sun.COM HBA_PORTATTRIBUTES attributes;
5857836SJohn.Forte@Sun.COM fcio_t fcio;
5867836SJohn.Forte@Sun.COM fc_hba_port_attributes_t attrs;
5877836SJohn.Forte@Sun.COM
5887836SJohn.Forte@Sun.COM memset(&fcio, 0, sizeof (fcio));
5897836SJohn.Forte@Sun.COM memset(&attributes, 0, sizeof (attributes));
5907836SJohn.Forte@Sun.COM
5917836SJohn.Forte@Sun.COM fcio.fcio_cmd = FCIO_GET_ADAPTER_PORT_ATTRIBUTES;
5927836SJohn.Forte@Sun.COM fcio.fcio_olen = sizeof (attrs);
5937836SJohn.Forte@Sun.COM fcio.fcio_xfer = FCIO_XFER_READ;
5947836SJohn.Forte@Sun.COM fcio.fcio_obuf = (caddr_t)&attrs;
5957836SJohn.Forte@Sun.COM
5967836SJohn.Forte@Sun.COM fp_ioctl(getPath(), FCIO_CMD, &fcio);
5977836SJohn.Forte@Sun.COM
5987836SJohn.Forte@Sun.COM stateChange = attrs.lastChange;
5997836SJohn.Forte@Sun.COM
6007836SJohn.Forte@Sun.COM attributes.PortFcId = attrs.PortFcId;
6017836SJohn.Forte@Sun.COM attributes.PortType = attrs.PortType;
6027836SJohn.Forte@Sun.COM attributes.PortState = attrs.PortState;
6037836SJohn.Forte@Sun.COM attributes.PortSupportedClassofService = attrs.PortSupportedClassofService;
6047836SJohn.Forte@Sun.COM attributes.PortSupportedSpeed = attrs.PortSupportedSpeed;
6057836SJohn.Forte@Sun.COM attributes.PortSpeed = attrs.PortSpeed;
6067836SJohn.Forte@Sun.COM attributes.PortMaxFrameSize = attrs.PortMaxFrameSize;
6077836SJohn.Forte@Sun.COM attributes.NumberofDiscoveredPorts = attrs.NumberofDiscoveredPorts;
6087836SJohn.Forte@Sun.COM memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
6097836SJohn.Forte@Sun.COM memcpy(&attributes.PortWWN, &attrs.PortWWN, 8);
6107836SJohn.Forte@Sun.COM memcpy(&attributes.FabricName, &attrs.FabricName, 8);
6117836SJohn.Forte@Sun.COM memcpy(&attributes.PortSupportedFc4Types, &attrs.PortSupportedFc4Types, 32);
6127836SJohn.Forte@Sun.COM memcpy(&attributes.PortActiveFc4Types, &attrs.PortActiveFc4Types, 32);
6137836SJohn.Forte@Sun.COM memcpy(&attributes.PortSymbolicName, &attrs.PortSymbolicName, 256);
6147836SJohn.Forte@Sun.COM
6157836SJohn.Forte@Sun.COM strncpy((char *)attributes.OSDeviceName, getPath().c_str(), 256);
6167836SJohn.Forte@Sun.COM return (attributes);
6177836SJohn.Forte@Sun.COM }
6187836SJohn.Forte@Sun.COM
getDiscoveredAttributes(HBA_UINT32 discoveredport,uint64_t & stateChange)6197836SJohn.Forte@Sun.COM HBA_PORTATTRIBUTES FCHBAPort::getDiscoveredAttributes(
6207836SJohn.Forte@Sun.COM HBA_UINT32 discoveredport, uint64_t &stateChange) {
6217836SJohn.Forte@Sun.COM Trace log("FCHBAPort::getDiscoverdAttributes(i)");
6227836SJohn.Forte@Sun.COM
6237836SJohn.Forte@Sun.COM HBA_PORTATTRIBUTES attributes;
6247836SJohn.Forte@Sun.COM fcio_t fcio;
6257836SJohn.Forte@Sun.COM fc_hba_port_attributes_t attrs;
6267836SJohn.Forte@Sun.COM
6277836SJohn.Forte@Sun.COM memset(&fcio, 0, sizeof (fcio));
6287836SJohn.Forte@Sun.COM memset(&attributes, 0, sizeof (attributes));
6297836SJohn.Forte@Sun.COM
6307836SJohn.Forte@Sun.COM fcio.fcio_cmd = FCIO_GET_DISCOVERED_PORT_ATTRIBUTES;
6317836SJohn.Forte@Sun.COM fcio.fcio_olen = sizeof (attrs);
6327836SJohn.Forte@Sun.COM fcio.fcio_xfer = FCIO_XFER_READ;
6337836SJohn.Forte@Sun.COM fcio.fcio_obuf = (caddr_t)&attrs;
6347836SJohn.Forte@Sun.COM fcio.fcio_ilen = sizeof (discoveredport);
6357836SJohn.Forte@Sun.COM fcio.fcio_ibuf = (caddr_t)&discoveredport;
6367836SJohn.Forte@Sun.COM
6377836SJohn.Forte@Sun.COM fp_ioctl(getPath(), FCIO_CMD, &fcio);
6387836SJohn.Forte@Sun.COM
6397836SJohn.Forte@Sun.COM stateChange = attrs.lastChange;
6407836SJohn.Forte@Sun.COM
6417836SJohn.Forte@Sun.COM attributes.PortFcId = attrs.PortFcId;
6427836SJohn.Forte@Sun.COM attributes.PortType = attrs.PortType;
6437836SJohn.Forte@Sun.COM attributes.PortState = attrs.PortState;
6447836SJohn.Forte@Sun.COM attributes.PortSupportedClassofService = attrs.PortSupportedClassofService;
6457836SJohn.Forte@Sun.COM attributes.PortSupportedSpeed = attrs.PortSupportedSpeed;
6467836SJohn.Forte@Sun.COM attributes.PortSpeed = attrs.PortSpeed;
6477836SJohn.Forte@Sun.COM attributes.PortMaxFrameSize = attrs.PortMaxFrameSize;
6487836SJohn.Forte@Sun.COM attributes.NumberofDiscoveredPorts = attrs.NumberofDiscoveredPorts;
6497836SJohn.Forte@Sun.COM memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
6507836SJohn.Forte@Sun.COM memcpy(&attributes.PortWWN, &attrs.PortWWN, 8);
6517836SJohn.Forte@Sun.COM memcpy(&attributes.FabricName, &attrs.FabricName, 8);
6527836SJohn.Forte@Sun.COM memcpy(&attributes.PortSupportedFc4Types, &attrs.PortSupportedFc4Types, 32);
6537836SJohn.Forte@Sun.COM memcpy(&attributes.PortActiveFc4Types, &attrs.PortActiveFc4Types, 32);
6547836SJohn.Forte@Sun.COM memcpy(&attributes.PortSymbolicName, &attrs.PortSymbolicName, 256);
6557836SJohn.Forte@Sun.COM
6567836SJohn.Forte@Sun.COM
6577836SJohn.Forte@Sun.COM return (attributes);
6587836SJohn.Forte@Sun.COM }
6597836SJohn.Forte@Sun.COM
getDiscoveredAttributes(uint64_t wwn,uint64_t & stateChange)6607836SJohn.Forte@Sun.COM HBA_PORTATTRIBUTES FCHBAPort::getDiscoveredAttributes(
6617836SJohn.Forte@Sun.COM uint64_t wwn, uint64_t &stateChange) {
6627836SJohn.Forte@Sun.COM Trace log("FCHBAPort::getDiscoverdAttributes(p)");
6637836SJohn.Forte@Sun.COM
6647836SJohn.Forte@Sun.COM HBA_PORTATTRIBUTES attributes;
6657836SJohn.Forte@Sun.COM fcio_t fcio;
6667836SJohn.Forte@Sun.COM fc_hba_port_attributes_t attrs;
6677836SJohn.Forte@Sun.COM la_wwn_t lawwn;
6687836SJohn.Forte@Sun.COM
6697836SJohn.Forte@Sun.COM memset(&fcio, 0, sizeof (fcio));
6707836SJohn.Forte@Sun.COM memset(&attributes, 0, sizeof (attributes));
6717836SJohn.Forte@Sun.COM
6727836SJohn.Forte@Sun.COM uint64_t en_wwn = htonll(wwn);
6737836SJohn.Forte@Sun.COM memcpy(&lawwn, &en_wwn, sizeof (en_wwn));
6747836SJohn.Forte@Sun.COM
6757836SJohn.Forte@Sun.COM fcio.fcio_cmd = FCIO_GET_PORT_ATTRIBUTES;
6767836SJohn.Forte@Sun.COM fcio.fcio_olen = sizeof (attrs);
6777836SJohn.Forte@Sun.COM fcio.fcio_xfer = FCIO_XFER_READ;
6787836SJohn.Forte@Sun.COM fcio.fcio_obuf = (caddr_t)&attrs;
6797836SJohn.Forte@Sun.COM fcio.fcio_ilen = sizeof (wwn);
6807836SJohn.Forte@Sun.COM fcio.fcio_ibuf = (caddr_t)&lawwn;
6817836SJohn.Forte@Sun.COM
6827836SJohn.Forte@Sun.COM fp_ioctl(getPath(), FCIO_CMD, &fcio);
6837836SJohn.Forte@Sun.COM
6847836SJohn.Forte@Sun.COM stateChange = attrs.lastChange;
6857836SJohn.Forte@Sun.COM
6867836SJohn.Forte@Sun.COM attributes.PortFcId = attrs.PortFcId;
6877836SJohn.Forte@Sun.COM attributes.PortType = attrs.PortType;
6887836SJohn.Forte@Sun.COM attributes.PortState = attrs.PortState;
6897836SJohn.Forte@Sun.COM attributes.PortSupportedClassofService = attrs.PortSupportedClassofService;
6907836SJohn.Forte@Sun.COM attributes.PortSupportedSpeed = attrs.PortSupportedSpeed;
6917836SJohn.Forte@Sun.COM attributes.PortSpeed = attrs.PortSpeed;
6927836SJohn.Forte@Sun.COM attributes.PortMaxFrameSize = attrs.PortMaxFrameSize;
6937836SJohn.Forte@Sun.COM attributes.NumberofDiscoveredPorts = attrs.NumberofDiscoveredPorts;
6947836SJohn.Forte@Sun.COM memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
6957836SJohn.Forte@Sun.COM memcpy(&attributes.PortWWN, &attrs.PortWWN, 8);
6967836SJohn.Forte@Sun.COM memcpy(&attributes.FabricName, &attrs.FabricName, 8);
6977836SJohn.Forte@Sun.COM memcpy(&attributes.PortSupportedFc4Types, &attrs.PortSupportedFc4Types, 32);
6987836SJohn.Forte@Sun.COM memcpy(&attributes.PortActiveFc4Types, &attrs.PortActiveFc4Types, 32);
6997836SJohn.Forte@Sun.COM memcpy(&attributes.PortSymbolicName, &attrs.PortSymbolicName, 256);
7007836SJohn.Forte@Sun.COM
7017836SJohn.Forte@Sun.COM
7027836SJohn.Forte@Sun.COM return (attributes);
7037836SJohn.Forte@Sun.COM }
7047836SJohn.Forte@Sun.COM
7057836SJohn.Forte@Sun.COM
getTargetMappings(PHBA_FCPTARGETMAPPINGV2 userMappings)7067836SJohn.Forte@Sun.COM void FCHBAPort::getTargetMappings(PHBA_FCPTARGETMAPPINGV2 userMappings) {
7077836SJohn.Forte@Sun.COM Trace log("FCHBAPort::getTargetMappings");
7087836SJohn.Forte@Sun.COM int i, index;
7097836SJohn.Forte@Sun.COM uint_t total_entries = 0;
7107836SJohn.Forte@Sun.COM
7117836SJohn.Forte@Sun.COM struct fcp_ioctl fioctl;
7127836SJohn.Forte@Sun.COM fc_hba_target_mappings_t *mappings;
7137836SJohn.Forte@Sun.COM int fd;
7147836SJohn.Forte@Sun.COM bool zeroLength = false;
7157836SJohn.Forte@Sun.COM
7167836SJohn.Forte@Sun.COM
7177836SJohn.Forte@Sun.COM if (userMappings == NULL) {
7187836SJohn.Forte@Sun.COM log.userError("Null mapping argument ");
7197836SJohn.Forte@Sun.COM throw BadArgumentException();
7207836SJohn.Forte@Sun.COM }
7217836SJohn.Forte@Sun.COM
7227836SJohn.Forte@Sun.COM /* It's possible they didn't give any space */
7237836SJohn.Forte@Sun.COM if (userMappings->NumberOfEntries == 0) {
7247836SJohn.Forte@Sun.COM zeroLength = true;
7257836SJohn.Forte@Sun.COM userMappings->NumberOfEntries = 1;
7267836SJohn.Forte@Sun.COM /* We have to give the driver at least one space */
7277836SJohn.Forte@Sun.COM }
7287836SJohn.Forte@Sun.COM
7297836SJohn.Forte@Sun.COM mappings = (fc_hba_target_mappings_t *)new uchar_t[
7307836SJohn.Forte@Sun.COM (sizeof (fc_hba_mapping_entry_t)) *
7317836SJohn.Forte@Sun.COM (userMappings->NumberOfEntries - 1) +
7327836SJohn.Forte@Sun.COM sizeof (fc_hba_target_mappings_t)];
7337836SJohn.Forte@Sun.COM if (mappings == NULL) {
7347836SJohn.Forte@Sun.COM log.noMemory();
7357836SJohn.Forte@Sun.COM throw InternalError();
7367836SJohn.Forte@Sun.COM }
7377836SJohn.Forte@Sun.COM
7387836SJohn.Forte@Sun.COM
7397836SJohn.Forte@Sun.COM fioctl.fp_minor = instanceNumber;
7407836SJohn.Forte@Sun.COM fioctl.listlen = ((uint32_t) (sizeof (fc_hba_mapping_entry_t))) *
7417836SJohn.Forte@Sun.COM (userMappings->NumberOfEntries - 1) +
7427836SJohn.Forte@Sun.COM (uint32_t) sizeof (fc_hba_target_mappings_t);
7437836SJohn.Forte@Sun.COM fioctl.list = (caddr_t)mappings;
7447836SJohn.Forte@Sun.COM
7457836SJohn.Forte@Sun.COM fd = HBA::_open(FCP_DRIVER_PATH, O_RDONLY | O_NDELAY);
7467836SJohn.Forte@Sun.COM
7477836SJohn.Forte@Sun.COM log.debug("Performing IOCTL to fetch mappings");
7487836SJohn.Forte@Sun.COM
7497836SJohn.Forte@Sun.COM if (ioctl(fd, FCP_GET_TARGET_MAPPINGS, &fioctl) != 0) {
7507836SJohn.Forte@Sun.COM delete (mappings);
7517836SJohn.Forte@Sun.COM close(fd);
7527836SJohn.Forte@Sun.COM if (errno == EBUSY) {
7537836SJohn.Forte@Sun.COM throw BusyException();
7547836SJohn.Forte@Sun.COM } else if (errno == EAGAIN) {
7557836SJohn.Forte@Sun.COM throw TryAgainException();
7567836SJohn.Forte@Sun.COM } else if (errno == ENOTSUP) {
7577836SJohn.Forte@Sun.COM throw NotSupportedException();
7587836SJohn.Forte@Sun.COM } else if (errno == ENOENT) {
7597836SJohn.Forte@Sun.COM throw UnavailableException();
7607836SJohn.Forte@Sun.COM } else {
7617836SJohn.Forte@Sun.COM throw IOError("Unable to fetch target mappings");
7627836SJohn.Forte@Sun.COM }
7637836SJohn.Forte@Sun.COM }
7647836SJohn.Forte@Sun.COM
7657836SJohn.Forte@Sun.COM close(fd);
7667836SJohn.Forte@Sun.COM // Quickly iterate through and copy the data over to the client
7677836SJohn.Forte@Sun.COM for (i = 0; i < userMappings->NumberOfEntries && !zeroLength &&
7687836SJohn.Forte@Sun.COM i < mappings->numLuns; i++) {
7697836SJohn.Forte@Sun.COM string raw = mappings->entries[i].targetDriver;
7707836SJohn.Forte@Sun.COM
7717836SJohn.Forte@Sun.COM
7727836SJohn.Forte@Sun.COM if (raw.length() <= 0) {
7737836SJohn.Forte@Sun.COM log.internalError("Bad target mapping without path, truncating.");
7747836SJohn.Forte@Sun.COM break;
7757836SJohn.Forte@Sun.COM }
7767836SJohn.Forte@Sun.COM /*
7777836SJohn.Forte@Sun.COM * Ideally, we'd like to ask some standard Solaris interface
7787836SJohn.Forte@Sun.COM * "What is the prefered minor node for this target?"
7797836SJohn.Forte@Sun.COM * but no such interface exists today. So, for now,
7807836SJohn.Forte@Sun.COM * we just hard-code ":n" for tapes, ":c,raw" for disks,
7817836SJohn.Forte@Sun.COM * and ":0" for enclosures.
7827836SJohn.Forte@Sun.COM * Devices with other generic names will be presented through
7837836SJohn.Forte@Sun.COM * first matching /dev path.
7847836SJohn.Forte@Sun.COM */
7857836SJohn.Forte@Sun.COM if ((raw.find("/st@") != raw.npos) ||
7867836SJohn.Forte@Sun.COM (raw.find("/tape@") != raw.npos)) {
7877836SJohn.Forte@Sun.COM raw += ":n";
7887836SJohn.Forte@Sun.COM } else if ((raw.find("/ssd@") != raw.npos) ||
7897836SJohn.Forte@Sun.COM (raw.find("/sd@") != raw.npos) ||
7907836SJohn.Forte@Sun.COM (raw.find("/disk@") != raw.npos)) {
7917836SJohn.Forte@Sun.COM raw += ":c,raw";
7927836SJohn.Forte@Sun.COM } else if ((raw.find("/ses@") != raw.npos) ||
7937836SJohn.Forte@Sun.COM (raw.find("/enclosure@") != raw.npos)) {
7947836SJohn.Forte@Sun.COM raw += ":0";
7957836SJohn.Forte@Sun.COM } else {
7967836SJohn.Forte@Sun.COM log.debug(
7977836SJohn.Forte@Sun.COM "Unrecognized target driver (%s), using first matching /dev path",
7987836SJohn.Forte@Sun.COM raw.c_str());
7997836SJohn.Forte@Sun.COM }
8007836SJohn.Forte@Sun.COM snprintf(userMappings->entry[i].ScsiId.OSDeviceName,
8017836SJohn.Forte@Sun.COM sizeof (userMappings->entry[i].ScsiId.OSDeviceName),
8027836SJohn.Forte@Sun.COM "/devices%s", raw.c_str());
8037836SJohn.Forte@Sun.COM userMappings->entry[i].ScsiId.ScsiBusNumber =
8047836SJohn.Forte@Sun.COM controllerNumber;
8057836SJohn.Forte@Sun.COM userMappings->entry[i].ScsiId.ScsiTargetNumber =
8067836SJohn.Forte@Sun.COM mappings->entries[i].targetNumber;
8077836SJohn.Forte@Sun.COM userMappings->entry[i].ScsiId.ScsiOSLun =
8087836SJohn.Forte@Sun.COM mappings->entries[i].osLUN;
8097836SJohn.Forte@Sun.COM userMappings->entry[i].FcpId.FcId =
8107836SJohn.Forte@Sun.COM mappings->entries[i].d_id;
8117836SJohn.Forte@Sun.COM memcpy(userMappings->entry[i].FcpId.NodeWWN.wwn,
8127836SJohn.Forte@Sun.COM mappings->entries[i].NodeWWN.raw_wwn,
8137836SJohn.Forte@Sun.COM sizeof (la_wwn_t));
8147836SJohn.Forte@Sun.COM memcpy(userMappings->entry[i].FcpId.PortWWN.wwn,
8157836SJohn.Forte@Sun.COM mappings->entries[i].PortWWN.raw_wwn,
8167836SJohn.Forte@Sun.COM sizeof (la_wwn_t));
8177836SJohn.Forte@Sun.COM
8187836SJohn.Forte@Sun.COM userMappings->entry[i].FcpId.FcpLun =
8197836SJohn.Forte@Sun.COM mappings->entries[i].samLUN;
8207836SJohn.Forte@Sun.COM
8217836SJohn.Forte@Sun.COM memcpy(userMappings->entry[i].LUID.buffer,
8227836SJohn.Forte@Sun.COM mappings->entries[i].guid,
8237836SJohn.Forte@Sun.COM sizeof (userMappings->entry[i].LUID.buffer));
8247836SJohn.Forte@Sun.COM }
8257836SJohn.Forte@Sun.COM
8267836SJohn.Forte@Sun.COM log.debug("Total mappings: %d %08x %08x",
8277836SJohn.Forte@Sun.COM mappings->numLuns, mappings->entries[i].osLUN, mappings->entries[i].samLUN);
8287836SJohn.Forte@Sun.COM
8297836SJohn.Forte@Sun.COM // If everything is good, convert paths to sym-links
8307836SJohn.Forte@Sun.COM if (mappings->numLuns > 0 && !zeroLength) {
8317836SJohn.Forte@Sun.COM if (userMappings->NumberOfEntries >= mappings->numLuns) {
8327836SJohn.Forte@Sun.COM // User buffer is larger than needed. (All is good)
8337836SJohn.Forte@Sun.COM userMappings->NumberOfEntries = mappings->numLuns;
8347836SJohn.Forte@Sun.COM convertToShortNames(userMappings);
8357836SJohn.Forte@Sun.COM } else {
8367836SJohn.Forte@Sun.COM // User buffer is non zero, but too small. Don't bother with links
8377836SJohn.Forte@Sun.COM userMappings->NumberOfEntries = mappings->numLuns;
8387836SJohn.Forte@Sun.COM delete (mappings);
8397836SJohn.Forte@Sun.COM throw MoreDataException();
8407836SJohn.Forte@Sun.COM }
8417836SJohn.Forte@Sun.COM } else if (mappings->numLuns > 0) {
8427836SJohn.Forte@Sun.COM // Zero length buffer, but we've got mappings
8437836SJohn.Forte@Sun.COM userMappings->NumberOfEntries = mappings->numLuns;
8447836SJohn.Forte@Sun.COM delete (mappings);
8457836SJohn.Forte@Sun.COM throw MoreDataException();
8467836SJohn.Forte@Sun.COM } else {
8477836SJohn.Forte@Sun.COM // No mappings, no worries
8487836SJohn.Forte@Sun.COM userMappings->NumberOfEntries = 0;
8497836SJohn.Forte@Sun.COM delete (mappings);
8507836SJohn.Forte@Sun.COM return;
8517836SJohn.Forte@Sun.COM }
8527836SJohn.Forte@Sun.COM delete (mappings);
8537836SJohn.Forte@Sun.COM }
8547836SJohn.Forte@Sun.COM
getRNIDMgmtInfo(PHBA_MGMTINFO info)8557836SJohn.Forte@Sun.COM void FCHBAPort::getRNIDMgmtInfo(PHBA_MGMTINFO info) {
8567836SJohn.Forte@Sun.COM Trace log("FCHBAPort::getRNIDMgmtInfo");
8577836SJohn.Forte@Sun.COM HBA_STATUS status = HBA_STATUS_OK;
8587836SJohn.Forte@Sun.COM fc_rnid_t rnid;
8597836SJohn.Forte@Sun.COM fcio_t fcio;
8607836SJohn.Forte@Sun.COM
8617836SJohn.Forte@Sun.COM
8627836SJohn.Forte@Sun.COM if (info == NULL) {
8637836SJohn.Forte@Sun.COM log.userError("NULL port management info");
8647836SJohn.Forte@Sun.COM throw BadArgumentException();
8657836SJohn.Forte@Sun.COM }
8667836SJohn.Forte@Sun.COM
8677836SJohn.Forte@Sun.COM // Get the RNID information from the first port
8687836SJohn.Forte@Sun.COM memset(&rnid, 0, sizeof (fc_rnid_t));
8697836SJohn.Forte@Sun.COM memset((caddr_t)&fcio, 0, sizeof (fcio));
8707836SJohn.Forte@Sun.COM
8717836SJohn.Forte@Sun.COM fcio.fcio_cmd = FCIO_GET_NODE_ID;
8727836SJohn.Forte@Sun.COM fcio.fcio_olen = sizeof (fc_rnid_t);
8737836SJohn.Forte@Sun.COM fcio.fcio_xfer = FCIO_XFER_READ;
8747836SJohn.Forte@Sun.COM fcio.fcio_obuf = (caddr_t)&rnid;
8757836SJohn.Forte@Sun.COM fp_ioctl(getPath(), FCIO_CMD, &fcio);
8767836SJohn.Forte@Sun.COM
8777836SJohn.Forte@Sun.COM // Copy out the struct members of rnid into PHBA_MGMTINFO struct
8787836SJohn.Forte@Sun.COM memcpy(&info->wwn, &(rnid.global_id), sizeof (info->wwn));
8797836SJohn.Forte@Sun.COM memcpy(&info->unittype, &(rnid.unit_type), sizeof (info->unittype));
8807836SJohn.Forte@Sun.COM memcpy(&info->PortId, &(rnid.port_id), sizeof (info->PortId));
8817836SJohn.Forte@Sun.COM memcpy(&info->NumberOfAttachedNodes, &(rnid.num_attached),
8827836SJohn.Forte@Sun.COM sizeof (info->NumberOfAttachedNodes));
8837836SJohn.Forte@Sun.COM memcpy(&info->IPVersion, &(rnid.ip_version), sizeof (info->IPVersion));
8847836SJohn.Forte@Sun.COM memcpy(&info->UDPPort, &(rnid.udp_port), sizeof (info->UDPPort));
8857836SJohn.Forte@Sun.COM memcpy(&info->IPAddress, &(rnid.ip_addr), sizeof (info->IPAddress));
8867836SJohn.Forte@Sun.COM memcpy(&info->TopologyDiscoveryFlags, &(rnid.topo_flags),
8877836SJohn.Forte@Sun.COM sizeof (info->TopologyDiscoveryFlags));
8887836SJohn.Forte@Sun.COM }
8897836SJohn.Forte@Sun.COM
sendCTPassThru(void * requestBuffer,HBA_UINT32 requestSize,void * responseBuffer,HBA_UINT32 * responseSize)8907836SJohn.Forte@Sun.COM void FCHBAPort::sendCTPassThru(void *requestBuffer, HBA_UINT32 requestSize,
8917836SJohn.Forte@Sun.COM void *responseBuffer, HBA_UINT32 *responseSize) {
8927836SJohn.Forte@Sun.COM Trace log("FCHBAPort::sendCTPassThru");
8937836SJohn.Forte@Sun.COM fcio_t fcio;
8947836SJohn.Forte@Sun.COM struct stat sbuf;
8957836SJohn.Forte@Sun.COM minor_t minor_node;
8967836SJohn.Forte@Sun.COM hrtime_t start, end;
8977836SJohn.Forte@Sun.COM double duration;
8987836SJohn.Forte@Sun.COM
8997836SJohn.Forte@Sun.COM // Validate the arguments
9007836SJohn.Forte@Sun.COM if (requestBuffer == NULL) {
9017836SJohn.Forte@Sun.COM log.userError("NULL request buffer");
9027836SJohn.Forte@Sun.COM throw BadArgumentException();
9037836SJohn.Forte@Sun.COM }
9047836SJohn.Forte@Sun.COM if (responseBuffer == NULL) {
9057836SJohn.Forte@Sun.COM log.userError("NULL response buffer");
9067836SJohn.Forte@Sun.COM throw BadArgumentException();
9077836SJohn.Forte@Sun.COM }
9087836SJohn.Forte@Sun.COM
9097836SJohn.Forte@Sun.COM minor_node = instanceNumber;
9107836SJohn.Forte@Sun.COM
9117836SJohn.Forte@Sun.COM // construct fcio struct
9127836SJohn.Forte@Sun.COM memset(&fcio, 0, sizeof (fcio_t));
9137836SJohn.Forte@Sun.COM fcio.fcio_cmd = FCSMIO_CT_CMD;
9147836SJohn.Forte@Sun.COM fcio.fcio_xfer = FCIO_XFER_RW;
9157836SJohn.Forte@Sun.COM
9167836SJohn.Forte@Sun.COM fcio.fcio_ilen = requestSize;
9177836SJohn.Forte@Sun.COM fcio.fcio_ibuf = (char *)requestBuffer;
9187836SJohn.Forte@Sun.COM fcio.fcio_olen = *responseSize;
9197836SJohn.Forte@Sun.COM fcio.fcio_obuf = (char *)responseBuffer;
9207836SJohn.Forte@Sun.COM
9217836SJohn.Forte@Sun.COM fcio.fcio_alen = sizeof (minor_t);
9227836SJohn.Forte@Sun.COM fcio.fcio_abuf = (char *)&minor_node;
9237836SJohn.Forte@Sun.COM
9247836SJohn.Forte@Sun.COM
9257836SJohn.Forte@Sun.COM start = gethrtime();
9267836SJohn.Forte@Sun.COM fcsm_ioctl(FCSMIO_CMD, &fcio);
9277836SJohn.Forte@Sun.COM
9287836SJohn.Forte@Sun.COM // Do some calculations on the duration of the ioctl.
9297836SJohn.Forte@Sun.COM end = gethrtime();
9307836SJohn.Forte@Sun.COM duration = end - start;
9317836SJohn.Forte@Sun.COM duration /= HR_SECOND;
9327836SJohn.Forte@Sun.COM log.debug(
9337836SJohn.Forte@Sun.COM "Total CTPASS ioctl call for HBA %s was %.4f seconds",
9347836SJohn.Forte@Sun.COM getPath().c_str(), duration);
9357836SJohn.Forte@Sun.COM }
9367836SJohn.Forte@Sun.COM
sendRLS(uint64_t destWWN,void * pRspBuffer,HBA_UINT32 * pRspBufferSize)9377836SJohn.Forte@Sun.COM void FCHBAPort::sendRLS(uint64_t destWWN,
9387836SJohn.Forte@Sun.COM void *pRspBuffer,
9397836SJohn.Forte@Sun.COM HBA_UINT32 *pRspBufferSize) {
9407836SJohn.Forte@Sun.COM Trace log("FCHBAPort::sendRLS");
9417836SJohn.Forte@Sun.COM
9427836SJohn.Forte@Sun.COM fcio_t fcio;
9437836SJohn.Forte@Sun.COM fc_portid_t rls_req;
9447836SJohn.Forte@Sun.COM
9457836SJohn.Forte@Sun.COM
9467836SJohn.Forte@Sun.COM // Validate the arguments
9477836SJohn.Forte@Sun.COM if (pRspBuffer == NULL ||
9487836SJohn.Forte@Sun.COM pRspBufferSize == NULL) {
9497836SJohn.Forte@Sun.COM log.userError("NULL hba");
9507836SJohn.Forte@Sun.COM throw BadArgumentException();
9517836SJohn.Forte@Sun.COM }
9527836SJohn.Forte@Sun.COM
9537836SJohn.Forte@Sun.COM // check to see if we are sending RLS to the HBA
9547836SJohn.Forte@Sun.COM HBA_PORTATTRIBUTES attrs;
9557836SJohn.Forte@Sun.COM uint64_t tmp;
9567836SJohn.Forte@Sun.COM if (getPortWWN() == destWWN) {
9577836SJohn.Forte@Sun.COM attrs = getPortAttributes(tmp);
9587836SJohn.Forte@Sun.COM } else {
9597836SJohn.Forte@Sun.COM attrs = getDiscoveredAttributes(destWWN, tmp);
9607836SJohn.Forte@Sun.COM }
9617836SJohn.Forte@Sun.COM
9627836SJohn.Forte@Sun.COM memcpy(&rls_req, &attrs.PortFcId,
9637836SJohn.Forte@Sun.COM sizeof (attrs.PortFcId));
9647836SJohn.Forte@Sun.COM
9657836SJohn.Forte@Sun.COM memset((caddr_t)&fcio, 0, sizeof (fcio));
9667836SJohn.Forte@Sun.COM fcio.fcio_cmd = FCIO_LINK_STATUS;
9677836SJohn.Forte@Sun.COM fcio.fcio_ibuf = (caddr_t)&rls_req;
9687836SJohn.Forte@Sun.COM fcio.fcio_ilen = sizeof (rls_req);
9697836SJohn.Forte@Sun.COM fcio.fcio_xfer = FCIO_XFER_RW;
9707836SJohn.Forte@Sun.COM fcio.fcio_flags = 0;
9717836SJohn.Forte@Sun.COM fcio.fcio_cmd_flags = FCIO_CFLAGS_RLS_DEST_NPORT;
9727836SJohn.Forte@Sun.COM fcio.fcio_obuf = (char *)new uchar_t[*pRspBufferSize];
9737836SJohn.Forte@Sun.COM fcio.fcio_olen = *pRspBufferSize;
9747836SJohn.Forte@Sun.COM
9757836SJohn.Forte@Sun.COM if (fcio.fcio_obuf == NULL) {
9767836SJohn.Forte@Sun.COM log.noMemory();
9777836SJohn.Forte@Sun.COM throw InternalError();
9787836SJohn.Forte@Sun.COM }
9797836SJohn.Forte@Sun.COM
9807836SJohn.Forte@Sun.COM fp_ioctl(getPath(), FCIO_CMD, &fcio);
9817836SJohn.Forte@Sun.COM memcpy(pRspBuffer, fcio.fcio_obuf, *pRspBufferSize);
9827836SJohn.Forte@Sun.COM if (fcio.fcio_obuf != NULL) {
9837836SJohn.Forte@Sun.COM delete(fcio.fcio_obuf);
9847836SJohn.Forte@Sun.COM }
9857836SJohn.Forte@Sun.COM }
9867836SJohn.Forte@Sun.COM
sendReportLUNs(uint64_t wwn,void * responseBuffer,HBA_UINT32 * responseSize,HBA_UINT8 * scsiStatus,void * senseBuffer,HBA_UINT32 * senseSize)9877836SJohn.Forte@Sun.COM void FCHBAPort::sendReportLUNs(uint64_t wwn,
9887836SJohn.Forte@Sun.COM void *responseBuffer, HBA_UINT32 *responseSize,
9897836SJohn.Forte@Sun.COM HBA_UINT8 *scsiStatus,
9907836SJohn.Forte@Sun.COM void *senseBuffer, HBA_UINT32 *senseSize) {
9917836SJohn.Forte@Sun.COM Trace log("FCHBAPort::sendReportLUNs");
9927836SJohn.Forte@Sun.COM struct fcp_scsi_cmd fscsi;
9937836SJohn.Forte@Sun.COM union scsi_cdb scsi_rl_req;
9947836SJohn.Forte@Sun.COM uint64_t targetWwn = htonll(wwn);
9957836SJohn.Forte@Sun.COM
9967836SJohn.Forte@Sun.COM // Validate the arguments
9977836SJohn.Forte@Sun.COM if (responseBuffer == NULL ||
9987836SJohn.Forte@Sun.COM senseBuffer == NULL ||
9997836SJohn.Forte@Sun.COM responseSize == NULL ||
10007836SJohn.Forte@Sun.COM senseSize == NULL) {
10017836SJohn.Forte@Sun.COM throw BadArgumentException();
10027836SJohn.Forte@Sun.COM }
10037836SJohn.Forte@Sun.COM
10047836SJohn.Forte@Sun.COM memset(&fscsi, 0, sizeof (fscsi));
10057836SJohn.Forte@Sun.COM memset(&scsi_rl_req, 0, sizeof (scsi_rl_req));
10067836SJohn.Forte@Sun.COM memcpy(fscsi.scsi_fc_pwwn.raw_wwn, &targetWwn, sizeof (la_wwn_t));
10077836SJohn.Forte@Sun.COM
10087836SJohn.Forte@Sun.COM scsi_cmd_init(&fscsi, getPath().c_str(), &scsi_rl_req,
10097836SJohn.Forte@Sun.COM sizeof (scsi_rl_req), responseBuffer, *responseSize,
10107836SJohn.Forte@Sun.COM senseBuffer, *senseSize);
10117836SJohn.Forte@Sun.COM
10127836SJohn.Forte@Sun.COM fscsi.scsi_lun = 0;
10137836SJohn.Forte@Sun.COM scsi_rl_req.scc_cmd = SCMD_REPORT_LUNS;
10147836SJohn.Forte@Sun.COM FORMG5COUNT(&scsi_rl_req, *responseSize);
10157836SJohn.Forte@Sun.COM sendSCSIPassThru(&fscsi, responseSize, senseSize, scsiStatus);
10167836SJohn.Forte@Sun.COM }
10177836SJohn.Forte@Sun.COM
10187836SJohn.Forte@Sun.COM /*
10197836SJohn.Forte@Sun.COM * arguments:
10207836SJohn.Forte@Sun.COM * wwn - remote target WWN where the SCSI Inquiry shall be sent
10217836SJohn.Forte@Sun.COM * fcLun - the SCSI LUN to which the SCSI Inquiry shall be sent
10227836SJohn.Forte@Sun.COM * cdb1 - the second byte of the CDB for the SCSI Inquiry
10237836SJohn.Forte@Sun.COM * cdb2 - the third byte of teh CDB for the SCSI Inquiry
10247836SJohn.Forte@Sun.COM * responseBuffer - shall be a pointer to a buffer to receive the SCSI
10257836SJohn.Forte@Sun.COM * Inquiry command response
10267836SJohn.Forte@Sun.COM * responseSize - a pointer to the size of the buffer to receive
10277836SJohn.Forte@Sun.COM * the SCSI Inquiry.
10287836SJohn.Forte@Sun.COM * scsiStatus - a pointer to a buffer to receive SCSI status
10297836SJohn.Forte@Sun.COM * senseBuffer - pointer to a buffer to receive SCSI sense data
10307836SJohn.Forte@Sun.COM * seneseSize - pointer to the size of the buffer to receive SCSI sense
10317836SJohn.Forte@Sun.COM * data
10327836SJohn.Forte@Sun.COM */
sendScsiInquiry(uint64_t wwn,HBA_UINT64 fcLun,HBA_UINT8 cdb1,HBA_UINT8 cdb2,void * responseBuffer,HBA_UINT32 * responseSize,HBA_UINT8 * scsiStatus,void * senseBuffer,HBA_UINT32 * senseSize)10337836SJohn.Forte@Sun.COM void FCHBAPort::sendScsiInquiry(uint64_t wwn, HBA_UINT64 fcLun,
10347836SJohn.Forte@Sun.COM HBA_UINT8 cdb1, HBA_UINT8 cdb2, void *responseBuffer,
10357836SJohn.Forte@Sun.COM HBA_UINT32 *responseSize, HBA_UINT8 *scsiStatus, void *senseBuffer,
10367836SJohn.Forte@Sun.COM HBA_UINT32 *senseSize) {
10377836SJohn.Forte@Sun.COM Trace log("FCHBAPort::sendScsiInquiry");
10387836SJohn.Forte@Sun.COM
10397836SJohn.Forte@Sun.COM struct fcp_scsi_cmd fscsi;
10407836SJohn.Forte@Sun.COM union scsi_cdb scsi_inq_req;
10417836SJohn.Forte@Sun.COM uint64_t targetWwn = htonll(wwn);
10427836SJohn.Forte@Sun.COM
10437836SJohn.Forte@Sun.COM // Validate the arguments
10447836SJohn.Forte@Sun.COM if (responseBuffer == NULL ||
10457836SJohn.Forte@Sun.COM senseBuffer == NULL ||
10467836SJohn.Forte@Sun.COM responseSize == NULL ||
10477836SJohn.Forte@Sun.COM senseSize == NULL) {
10487836SJohn.Forte@Sun.COM throw BadArgumentException();
10497836SJohn.Forte@Sun.COM }
10507836SJohn.Forte@Sun.COM
10517836SJohn.Forte@Sun.COM memset(&fscsi, 0, sizeof (fscsi));
10527836SJohn.Forte@Sun.COM memset(&scsi_inq_req, 0, sizeof (scsi_inq_req));
10537836SJohn.Forte@Sun.COM memcpy(fscsi.scsi_fc_pwwn.raw_wwn, &targetWwn, sizeof (la_wwn_t));
10547836SJohn.Forte@Sun.COM
10557836SJohn.Forte@Sun.COM
10567836SJohn.Forte@Sun.COM scsi_cmd_init(&fscsi, getPath().c_str(), &scsi_inq_req,
10577836SJohn.Forte@Sun.COM sizeof (scsi_inq_req), responseBuffer, *responseSize,
10587836SJohn.Forte@Sun.COM senseBuffer, *senseSize);
10597836SJohn.Forte@Sun.COM fscsi.scsi_lun = fcLun;
10607836SJohn.Forte@Sun.COM
10617836SJohn.Forte@Sun.COM scsi_inq_req.scc_cmd = SCMD_INQUIRY;
10627836SJohn.Forte@Sun.COM scsi_inq_req.g0_addr1 = cdb2;
10637836SJohn.Forte@Sun.COM scsi_inq_req.g0_addr2 = cdb1;
10647836SJohn.Forte@Sun.COM scsi_inq_req.g0_count0 = *responseSize;
10657836SJohn.Forte@Sun.COM
10667836SJohn.Forte@Sun.COM
10677836SJohn.Forte@Sun.COM sendSCSIPassThru(&fscsi, responseSize, senseSize, scsiStatus);
10687836SJohn.Forte@Sun.COM }
10697836SJohn.Forte@Sun.COM
10707836SJohn.Forte@Sun.COM
sendReadCapacity(uint64_t pwwn,HBA_UINT64 fcLun,void * responseBuffer,HBA_UINT32 * responseSize,HBA_UINT8 * scsiStatus,void * senseBuffer,HBA_UINT32 * senseSize)10717836SJohn.Forte@Sun.COM void FCHBAPort::sendReadCapacity(uint64_t pwwn,
10727836SJohn.Forte@Sun.COM HBA_UINT64 fcLun, void *responseBuffer,
10737836SJohn.Forte@Sun.COM HBA_UINT32 *responseSize, HBA_UINT8 *scsiStatus,
10747836SJohn.Forte@Sun.COM void *senseBuffer, HBA_UINT32 *senseSize) {
10757836SJohn.Forte@Sun.COM Trace log("FCHBAPort::sendReadCapacity");
10767836SJohn.Forte@Sun.COM
10777836SJohn.Forte@Sun.COM struct fcp_scsi_cmd fscsi;
10787836SJohn.Forte@Sun.COM union scsi_cdb scsi_rc_req;
10797836SJohn.Forte@Sun.COM uint64_t targetWwn = htonll(pwwn);
10807836SJohn.Forte@Sun.COM
10817836SJohn.Forte@Sun.COM // Validate the arguments
10827836SJohn.Forte@Sun.COM if (responseBuffer == NULL ||
10837836SJohn.Forte@Sun.COM senseBuffer == NULL ||
10847836SJohn.Forte@Sun.COM responseSize == NULL ||
10857836SJohn.Forte@Sun.COM senseSize == NULL ||
10867836SJohn.Forte@Sun.COM scsiStatus == NULL) {
10877836SJohn.Forte@Sun.COM throw BadArgumentException();
10887836SJohn.Forte@Sun.COM }
10897836SJohn.Forte@Sun.COM
10907836SJohn.Forte@Sun.COM memset(&fscsi, 0, sizeof (fscsi));
10917836SJohn.Forte@Sun.COM memset(&scsi_rc_req, 0, sizeof (scsi_rc_req));
10927836SJohn.Forte@Sun.COM
10937836SJohn.Forte@Sun.COM scsi_cmd_init(&fscsi, getPath().c_str(), &scsi_rc_req,
10947836SJohn.Forte@Sun.COM sizeof (scsi_rc_req), responseBuffer, *responseSize,
10957836SJohn.Forte@Sun.COM senseBuffer, *senseSize);
10967836SJohn.Forte@Sun.COM
10977836SJohn.Forte@Sun.COM memcpy(fscsi.scsi_fc_pwwn.raw_wwn, &targetWwn, sizeof (la_wwn_t));
10987836SJohn.Forte@Sun.COM fscsi.scsi_lun = fcLun;
10997836SJohn.Forte@Sun.COM
11007836SJohn.Forte@Sun.COM scsi_rc_req.scc_cmd = SCMD_READ_CAPACITY;
11017836SJohn.Forte@Sun.COM scsi_rc_req.g1_reladdr = 0;
11027836SJohn.Forte@Sun.COM
11037836SJohn.Forte@Sun.COM scsi_rc_req.g1_addr3 = 0;
11047836SJohn.Forte@Sun.COM scsi_rc_req.g1_count0 = 0;
11057836SJohn.Forte@Sun.COM
11067836SJohn.Forte@Sun.COM sendSCSIPassThru(&fscsi, responseSize, senseSize, scsiStatus);
11077836SJohn.Forte@Sun.COM }
11087836SJohn.Forte@Sun.COM
sendRNID(uint64_t destwwn,HBA_UINT32 destfcid,HBA_UINT32 nodeIdDataFormat,void * pRspBuffer,HBA_UINT32 * RspBufferSize)11097836SJohn.Forte@Sun.COM void FCHBAPort::sendRNID(uint64_t destwwn, HBA_UINT32 destfcid,
11107836SJohn.Forte@Sun.COM HBA_UINT32 nodeIdDataFormat, void *pRspBuffer,
11117836SJohn.Forte@Sun.COM HBA_UINT32 *RspBufferSize) {
11127836SJohn.Forte@Sun.COM Trace log("FCHBAPort::sendRNID");
11137836SJohn.Forte@Sun.COM int localportfound, remoteportfound, send;
11147836SJohn.Forte@Sun.COM fcio_t fcio;
11157836SJohn.Forte@Sun.COM
11167836SJohn.Forte@Sun.COM // Validate the arguments
11177836SJohn.Forte@Sun.COM if (pRspBuffer == NULL ||
11187836SJohn.Forte@Sun.COM RspBufferSize == NULL) {
11197836SJohn.Forte@Sun.COM throw BadArgumentException();
11207836SJohn.Forte@Sun.COM }
11217836SJohn.Forte@Sun.COM // NodeIdDataFormat must be within the range of 0x00 and 0xff
11227836SJohn.Forte@Sun.COM if (nodeIdDataFormat > 0xff) {
11237836SJohn.Forte@Sun.COM log.userError(
11247836SJohn.Forte@Sun.COM "NodeIdDataFormat must be within the range of 0x00 "
11257836SJohn.Forte@Sun.COM "and 0xFF");
11267836SJohn.Forte@Sun.COM throw BadArgumentException();
11277836SJohn.Forte@Sun.COM }
11287836SJohn.Forte@Sun.COM
11297836SJohn.Forte@Sun.COM
11307836SJohn.Forte@Sun.COM remoteportfound = 0;
11317836SJohn.Forte@Sun.COM if (destfcid != 0) {
11327836SJohn.Forte@Sun.COM try {
11337836SJohn.Forte@Sun.COM uint64_t tmp;
11347836SJohn.Forte@Sun.COM HBA_PORTATTRIBUTES attrs = getDiscoveredAttributes(destwwn,
11357836SJohn.Forte@Sun.COM tmp);
11367836SJohn.Forte@Sun.COM if (attrs.PortFcId == destfcid) {
11377836SJohn.Forte@Sun.COM send = 1;
11387836SJohn.Forte@Sun.COM remoteportfound = 1;
11397836SJohn.Forte@Sun.COM } else {
11407836SJohn.Forte@Sun.COM send = 0;
11417836SJohn.Forte@Sun.COM remoteportfound = 1;
11427836SJohn.Forte@Sun.COM }
11437836SJohn.Forte@Sun.COM } catch (HBAException &e) {
11447836SJohn.Forte@Sun.COM /*
11457836SJohn.Forte@Sun.COM * Send RNID if destination port not
11467836SJohn.Forte@Sun.COM * present in the discovered ports table
11477836SJohn.Forte@Sun.COM */
11487836SJohn.Forte@Sun.COM }
11497836SJohn.Forte@Sun.COM if (remoteportfound == 0) {
11507836SJohn.Forte@Sun.COM send = 1;
11517836SJohn.Forte@Sun.COM }
11527836SJohn.Forte@Sun.COM } else {
11537836SJohn.Forte@Sun.COM send = 1;
11547836SJohn.Forte@Sun.COM }
11557836SJohn.Forte@Sun.COM
11567836SJohn.Forte@Sun.COM if (!send) {
11577836SJohn.Forte@Sun.COM // Can we log something so we can figure out why?
11587836SJohn.Forte@Sun.COM throw BadArgumentException();
11597836SJohn.Forte@Sun.COM }
11607836SJohn.Forte@Sun.COM
11617836SJohn.Forte@Sun.COM memset((caddr_t)&fcio, 0, sizeof (fcio));
11627836SJohn.Forte@Sun.COM uint64_t netdestwwn = htonll(destwwn);
11637836SJohn.Forte@Sun.COM fcio.fcio_cmd = FCIO_SEND_NODE_ID;
11647836SJohn.Forte@Sun.COM fcio.fcio_xfer = FCIO_XFER_READ;
11657836SJohn.Forte@Sun.COM fcio.fcio_cmd_flags = nodeIdDataFormat;
11667836SJohn.Forte@Sun.COM fcio.fcio_ilen = sizeof (la_wwn_t);
11677836SJohn.Forte@Sun.COM fcio.fcio_ibuf = (caddr_t)&netdestwwn;
11687836SJohn.Forte@Sun.COM fcio.fcio_olen = *RspBufferSize;
11697836SJohn.Forte@Sun.COM fcio.fcio_obuf = (char *)new uchar_t[*RspBufferSize];
11707836SJohn.Forte@Sun.COM
11717836SJohn.Forte@Sun.COM
11727836SJohn.Forte@Sun.COM if (fcio.fcio_obuf == NULL) {
11737836SJohn.Forte@Sun.COM log.noMemory();
11747836SJohn.Forte@Sun.COM throw InternalError();
11757836SJohn.Forte@Sun.COM }
11767836SJohn.Forte@Sun.COM
11777836SJohn.Forte@Sun.COM fp_ioctl(getPath(), FCIO_CMD, &fcio);
11787836SJohn.Forte@Sun.COM
11797836SJohn.Forte@Sun.COM memcpy(pRspBuffer, fcio.fcio_obuf, *RspBufferSize);
11807836SJohn.Forte@Sun.COM
11817836SJohn.Forte@Sun.COM if (fcio.fcio_obuf != NULL) {
11827836SJohn.Forte@Sun.COM delete(fcio.fcio_obuf);
11837836SJohn.Forte@Sun.COM }
11847836SJohn.Forte@Sun.COM }
11857836SJohn.Forte@Sun.COM
setRNID(HBA_MGMTINFO info)11867836SJohn.Forte@Sun.COM void FCHBAPort::setRNID(HBA_MGMTINFO info) {
11877836SJohn.Forte@Sun.COM Trace log("FCHBAPort::setRNID");
11887836SJohn.Forte@Sun.COM fc_rnid_t rnid;
11897836SJohn.Forte@Sun.COM fcio_t fcio;
11907836SJohn.Forte@Sun.COM
11917836SJohn.Forte@Sun.COM memset(&rnid, 0, sizeof (fc_rnid_t));
11927836SJohn.Forte@Sun.COM memset((caddr_t)&fcio, 0, sizeof (fcio));
11937836SJohn.Forte@Sun.COM
11947836SJohn.Forte@Sun.COM
11957836SJohn.Forte@Sun.COM fcio.fcio_cmd = FCIO_SET_NODE_ID;
11967836SJohn.Forte@Sun.COM fcio.fcio_ilen = sizeof (fc_rnid_t);
11977836SJohn.Forte@Sun.COM fcio.fcio_xfer = FCIO_XFER_WRITE;
11987836SJohn.Forte@Sun.COM fcio.fcio_ibuf = (caddr_t)&rnid;
11997836SJohn.Forte@Sun.COM
12007836SJohn.Forte@Sun.COM
12017836SJohn.Forte@Sun.COM // Copy the HBA_MGMTINFO into fc_rnid_t struct
12027836SJohn.Forte@Sun.COM memcpy(&(rnid.unit_type), &(info.unittype), sizeof (rnid.unit_type));
12037836SJohn.Forte@Sun.COM memcpy(&(rnid.port_id), &(info.PortId), sizeof (rnid.port_id));
12047836SJohn.Forte@Sun.COM memcpy(&(rnid.global_id), &(info.wwn), sizeof (info.wwn));
12057836SJohn.Forte@Sun.COM memcpy(&(rnid.num_attached), &(info.NumberOfAttachedNodes),
12067836SJohn.Forte@Sun.COM sizeof (rnid.num_attached));
12077836SJohn.Forte@Sun.COM memcpy(&(rnid.ip_version), &(info.IPVersion), sizeof (rnid.ip_version));
12087836SJohn.Forte@Sun.COM memcpy(&(rnid.udp_port), &(info.UDPPort), sizeof (rnid.udp_port));
12097836SJohn.Forte@Sun.COM memcpy(&(rnid.ip_addr), &info.IPAddress, sizeof (rnid.ip_addr));
12107836SJohn.Forte@Sun.COM memcpy(&(rnid.topo_flags), &(info.TopologyDiscoveryFlags),
12117836SJohn.Forte@Sun.COM sizeof (rnid.topo_flags));
12127836SJohn.Forte@Sun.COM
12137836SJohn.Forte@Sun.COM fp_ioctl(getPath(), FCIO_CMD, &fcio, O_NDELAY | O_RDONLY | O_EXCL);
12147836SJohn.Forte@Sun.COM }
12157836SJohn.Forte@Sun.COM
fp_ioctl(string path,int cmd,fcio_t * fcio,int openflag)12167836SJohn.Forte@Sun.COM void FCHBAPort::fp_ioctl(string path, int cmd, fcio_t *fcio, int openflag) {
12177836SJohn.Forte@Sun.COM Trace log("FCHBAPort::fp_ioctl with openflag");
12187836SJohn.Forte@Sun.COM char fcioErrorString[MAX_FCIO_MSG_LEN] = "";
12197836SJohn.Forte@Sun.COM int fd = HBA::_open(path, openflag);
12207836SJohn.Forte@Sun.COM try {
12217836SJohn.Forte@Sun.COM int times = 0;
12227836SJohn.Forte@Sun.COM HBA::_ioctl(fd, cmd, (uchar_t *)fcio);
12237836SJohn.Forte@Sun.COM while (fcio->fcio_errno == FC_STATEC_BUSY) {
12247836SJohn.Forte@Sun.COM sleep(1);
12257836SJohn.Forte@Sun.COM HBA::_ioctl(fd, cmd, (uchar_t *)fcio);
12267836SJohn.Forte@Sun.COM if (times++ > 10) {
12277836SJohn.Forte@Sun.COM break;
12287836SJohn.Forte@Sun.COM }
12297836SJohn.Forte@Sun.COM }
12307836SJohn.Forte@Sun.COM close(fd);
12317836SJohn.Forte@Sun.COM if (fcio->fcio_errno) {
12327836SJohn.Forte@Sun.COM throw IOError("IOCTL transport failure");
12337836SJohn.Forte@Sun.COM }
12347836SJohn.Forte@Sun.COM } catch (...) {
12357836SJohn.Forte@Sun.COM close(fd);
12367836SJohn.Forte@Sun.COM transportError(fcio->fcio_errno, fcioErrorString);
12377836SJohn.Forte@Sun.COM log.genericIOError("ioctl (0x%x) failed. Transport: \"%s\"", cmd,
12387836SJohn.Forte@Sun.COM fcioErrorString);
12397836SJohn.Forte@Sun.COM switch (fcio->fcio_errno) {
12407836SJohn.Forte@Sun.COM case FC_BADWWN:
12417836SJohn.Forte@Sun.COM throw IllegalWWNException();
12427836SJohn.Forte@Sun.COM case FC_BADPORT:
12437836SJohn.Forte@Sun.COM throw IllegalWWNException();
12447836SJohn.Forte@Sun.COM case FC_OUTOFBOUNDS:
12457836SJohn.Forte@Sun.COM throw IllegalIndexException();
12467836SJohn.Forte@Sun.COM case FC_PBUSY:
12477836SJohn.Forte@Sun.COM case FC_FBUSY:
12487836SJohn.Forte@Sun.COM case FC_TRAN_BUSY:
12497836SJohn.Forte@Sun.COM case FC_STATEC_BUSY:
12507836SJohn.Forte@Sun.COM case FC_DEVICE_BUSY:
12517836SJohn.Forte@Sun.COM throw BusyException();
12527836SJohn.Forte@Sun.COM case FC_SUCCESS:
12537836SJohn.Forte@Sun.COM default:
12547836SJohn.Forte@Sun.COM throw;
12557836SJohn.Forte@Sun.COM }
12567836SJohn.Forte@Sun.COM }
12577836SJohn.Forte@Sun.COM }
12587836SJohn.Forte@Sun.COM
fp_ioctl(string path,int cmd,fcio_t * fcio)12597836SJohn.Forte@Sun.COM void FCHBAPort::fp_ioctl(string path, int cmd, fcio_t *fcio) {
12607836SJohn.Forte@Sun.COM Trace log("FCHBAPort::fp_ioctl");
12617836SJohn.Forte@Sun.COM fp_ioctl(path, cmd, fcio, O_NDELAY | O_RDONLY);
12627836SJohn.Forte@Sun.COM }
12637836SJohn.Forte@Sun.COM
fcsm_ioctl(int cmd,fcio_t * fcio)12647836SJohn.Forte@Sun.COM void FCHBAPort::fcsm_ioctl(int cmd, fcio_t *fcio) {
12657836SJohn.Forte@Sun.COM // We use the same error handling as fp, so just re-use
12667836SJohn.Forte@Sun.COM fp_ioctl(FCSM_DRIVER_PATH, cmd, fcio);
12677836SJohn.Forte@Sun.COM }
1268