2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
2N/A * Use is subject to license terms.
2N/A */
2N/A
2N/A
2N/A#include "FCHBANPIVPort.h"
2N/A#include <Exceptions.h>
2N/A#include <Trace.h>
2N/A#include <sun_fc.h>
2N/A#include <iostream>
2N/A#include <iomanip>
2N/A#include <sys/types.h>
2N/A#include <sys/mkdev.h>
2N/A#include <sys/stat.h>
2N/A#include <fcntl.h>
2N/A#include <unistd.h>
2N/A#include <stropts.h>
2N/A#include <dirent.h>
2N/A#include <sys/fibre-channel/fc.h>
2N/A#include <sys/fibre-channel/fcio.h>
2N/A#include <sys/fibre-channel/ulp/fcp_util.h>
2N/A#include <sys/fibre-channel/ulp/fcsm.h>
2N/A#include <sys/fibre-channel/impl/fc_error.h>
2N/A#include <sys/fibre-channel/fc_appif.h>
2N/A#include <sys/scsi/generic/commands.h>
2N/A#include <sys/scsi/impl/commands.h>
2N/A#include <sys/scsi/impl/sense.h>
2N/A#include <sys/scsi/generic/inquiry.h>
2N/A#include <sys/scsi/generic/status.h>
2N/A#include <errno.h>
2N/A
2N/Ausing namespace std;
2N/A
2N/Aconst int FCHBANPIVPort::MAX_FCIO_MSG_LEN = 256;
2N/A
2N/AFCHBANPIVPort::FCHBANPIVPort(string thePath) : HBANPIVPort() {
2N/A Trace log("FCHBANPIVPort::FCHBANPIVPort");
2N/A log.debug("Initializing HBA NPIV port %s", thePath.c_str());
2N/A
2N/A try {
2N/A path = lookupControllerPath(thePath);
2N/A } catch (...) {
2N/A log.debug("Unable to lookup controller path and number for %s",
2N/A thePath.c_str());
2N/A path = "/devices";
2N/A path += thePath;
2N/A path += ":fc";
2N/A }
2N/A
2N/A uint64_t tmp;
2N/A HBA_NPIVATTRIBUTES attrs = getPortAttributes(tmp);
2N/A memcpy(&tmp, &attrs.PortWWN, 8);
2N/A portWWN = ntohll(tmp);
2N/A memcpy(&tmp, &attrs.NodeWWN, 8);
2N/A nodeWWN = ntohll(tmp);
2N/A}
2N/A
2N/A
2N/AHBA_NPIVATTRIBUTES FCHBANPIVPort::getPortAttributes(uint64_t &stateChange) {
2N/A Trace log("FCHBANPIVPort::getPortAttributes");
2N/A
2N/A HBA_NPIVATTRIBUTES attributes;
2N/A fcio_t fcio;
2N/A fc_hba_npiv_attributes_t attrs;
2N/A
2N/A memset(&fcio, 0, sizeof (fcio));
2N/A memset(&attributes, 0, sizeof (attributes));
2N/A fcio.fcio_cmd = FCIO_GET_NPIV_ATTRIBUTES;
2N/A fcio.fcio_olen = sizeof (attrs);
2N/A fcio.fcio_xfer = FCIO_XFER_READ;
2N/A fcio.fcio_obuf = (caddr_t)&attrs;
2N/A fp_ioctl(getPath(), FCIO_CMD, &fcio);
2N/A
2N/A stateChange = attrs.lastChange;
2N/A memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
2N/A memcpy(&attributes.PortWWN, &attrs.PortWWN, 8);
2N/A
2N/A return (attributes);
2N/A}
2N/A
2N/A
2N/Avoid FCHBANPIVPort::fp_ioctl(string path, int cmd, fcio_t *fcio) {
2N/A Trace log("FCHBANPIVPort::fp_ioctl");
2N/A
2N/A char fcioErrorString[MAX_FCIO_MSG_LEN] = "";
2N/A int fd = HBA::_open(path, O_NDELAY | O_RDONLY);
2N/A
2N/A try {
2N/A int times = 0;
2N/A HBA::_ioctl(fd, cmd, (uchar_t *)fcio);
2N/A while (fcio->fcio_errno == FC_STATEC_BUSY) {
2N/A (void) sleep(2);
2N/A HBA::_ioctl(fd, cmd, (uchar_t *)fcio);
2N/A if (times++ > 20) {
2N/A break;
2N/A }
2N/A }
2N/A close(fd);
2N/A if (fcio->fcio_errno) {
2N/A throw IOError("IOCTL transport failure");
2N/A }
2N/A } catch (...) {
2N/A close(fd);
2N/A transportError(fcio->fcio_errno, fcioErrorString);
2N/A log.genericIOError("NPIV Port ioctl (0x%x) failed. Transport: \"%s\"", cmd,
2N/A fcioErrorString);
2N/A switch (fcio->fcio_errno) {
2N/A case FC_BADWWN:
2N/A throw IllegalWWNException();
2N/A case FC_BADPORT:
2N/A throw IllegalWWNException();
2N/A case FC_OUTOFBOUNDS:
2N/A throw IllegalIndexException();
2N/A case FC_PBUSY:
2N/A case FC_FBUSY:
2N/A case FC_TRAN_BUSY:
2N/A case FC_STATEC_BUSY:
2N/A case FC_DEVICE_BUSY:
2N/A throw BusyException();
2N/A case FC_SUCCESS:
2N/A default:
2N/A throw;
2N/A }
2N/A }
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Interpret the error code in the fcio_t structure
2N/A *
2N/A * message must be at least MAX_FCIO_MSG_LEN in length.
2N/A */
2N/Avoid
2N/AFCHBANPIVPort::transportError(uint32_t fcio_errno, char *message) {
2N/A Trace log("transportError");
2N/A
2N/A string fcioErrorString;
2N/A if (message == NULL) {
2N/A log.internalError("NULL routine argument");
2N/A return;
2N/A }
2N/A switch (fcio_errno) {
2N/A case (uint32_t)FC_FAILURE:
2N/A fcioErrorString = "general failure";
2N/A break;
2N/A case (uint32_t)FC_FAILURE_SILENT:
2N/A fcioErrorString = "general failure but fail silently";
2N/A break;
2N/A case FC_SUCCESS:
2N/A fcioErrorString = "successful completion";
2N/A break;
2N/A case FC_CAP_ERROR:
2N/A fcioErrorString = "FCA capability error";
2N/A break;
2N/A case FC_CAP_FOUND:
2N/A fcioErrorString = "FCA capability unsettable";
2N/A break;
2N/A case FC_CAP_SETTABLE:
2N/A fcioErrorString = "FCA capability settable";
2N/A break;
2N/A case FC_UNBOUND:
2N/A fcioErrorString = "unbound stuff";
2N/A break;
2N/A case FC_NOMEM:
2N/A fcioErrorString = "allocation error";
2N/A break;
2N/A case FC_BADPACKET:
2N/A fcioErrorString = "invalid packet specified/supplied";
2N/A break;
2N/A case FC_OFFLINE:
2N/A fcioErrorString = "I/O resource unavailable";
2N/A break;
2N/A case FC_OLDPORT:
2N/A fcioErrorString = "operation on non-loop port";
2N/A break;
2N/A case FC_NO_MAP:
2N/A fcioErrorString = "requested map unavailable";
2N/A break;
2N/A case FC_TRANSPORT_ERROR:
2N/A fcioErrorString = "unable to transport I/O";
2N/A break;
2N/A case FC_ELS_FREJECT:
2N/A fcioErrorString = "ELS rejected by a Fabric";
2N/A break;
2N/A case FC_ELS_PREJECT:
2N/A fcioErrorString = "ELS rejected by an N_port";
2N/A break;
2N/A case FC_ELS_BAD:
2N/A fcioErrorString = "ELS rejected by FCA/fctl";
2N/A break;
2N/A case FC_ELS_MALFORMED:
2N/A fcioErrorString = "poorly formed ELS request";
2N/A break;
2N/A case FC_TOOMANY:
2N/A fcioErrorString = "resource request too large";
2N/A break;
2N/A case FC_UB_BADTOKEN:
2N/A fcioErrorString = "invalid unsolicited buffer token";
2N/A break;
2N/A case FC_UB_ERROR:
2N/A fcioErrorString = "invalid unsol buf request";
2N/A break;
2N/A case FC_UB_BUSY:
2N/A fcioErrorString = "buffer already in use";
2N/A break;
2N/A case FC_BADULP:
2N/A fcioErrorString = "Unknown ulp";
2N/A break;
2N/A case FC_BADTYPE:
2N/A fcioErrorString = "ULP not registered to handle this FC4 type";
2N/A break;
2N/A case FC_UNCLAIMED:
2N/A fcioErrorString = "request or data not claimed";
2N/A break;
2N/A case FC_ULP_SAMEMODULE:
2N/A fcioErrorString = "module already in use";
2N/A break;
2N/A case FC_ULP_SAMETYPE:
2N/A fcioErrorString = "FC4 module already in use";
2N/A break;
2N/A case FC_ABORTED:
2N/A fcioErrorString = "request aborted";
2N/A break;
2N/A case FC_ABORT_FAILED:
2N/A fcioErrorString = "abort request failed";
2N/A break;
2N/A case FC_BADEXCHANGE:
2N/A fcioErrorString = "exchange doesn\325t exist";
2N/A break;
2N/A case FC_BADWWN:
2N/A fcioErrorString = "WWN not recognized";
2N/A break;
2N/A case FC_BADDEV:
2N/A fcioErrorString = "device unrecognized";
2N/A break;
2N/A case FC_BADCMD:
2N/A fcioErrorString = "invalid command issued";
2N/A break;
2N/A case FC_BADOBJECT:
2N/A fcioErrorString = "invalid object requested";
2N/A break;
2N/A case FC_BADPORT:
2N/A fcioErrorString = "invalid port specified";
2N/A break;
2N/A case FC_NOTTHISPORT:
2N/A fcioErrorString = "resource not at this port";
2N/A break;
2N/A case FC_PREJECT:
2N/A fcioErrorString = "reject at remote N_Port";
2N/A break;
2N/A case FC_FREJECT:
2N/A fcioErrorString = "reject at remote Fabric";
2N/A break;
2N/A case FC_PBUSY:
2N/A fcioErrorString = "remote N_Port busy";
2N/A break;
2N/A case FC_FBUSY:
2N/A fcioErrorString = "remote Fabric busy";
2N/A break;
2N/A case FC_ALREADY:
2N/A fcioErrorString = "already logged in";
2N/A break;
2N/A case FC_LOGINREQ:
2N/A fcioErrorString = "login required";
2N/A break;
2N/A case FC_RESETFAIL:
2N/A fcioErrorString = "reset failed";
2N/A break;
2N/A case FC_INVALID_REQUEST:
2N/A fcioErrorString = "request is invalid";
2N/A break;
2N/A case FC_OUTOFBOUNDS:
2N/A fcioErrorString = "port number is out of bounds";
2N/A break;
2N/A case FC_TRAN_BUSY:
2N/A fcioErrorString = "command transport busy";
2N/A break;
2N/A case FC_STATEC_BUSY:
2N/A fcioErrorString = "port driver currently busy";
2N/A break;
2N/A case FC_DEVICE_BUSY:
2N/A fcioErrorString = "transport working on this device";
2N/A break;
2N/A case FC_DEVICE_NOT_TGT:
2N/A fcioErrorString = "device is not a SCSI target";
2N/A break;
2N/A default:
2N/A snprintf(message, MAX_FCIO_MSG_LEN, "Unknown error code 0x%x",
2N/A fcio_errno);
2N/A return;
2N/A }
2N/A snprintf(message, MAX_FCIO_MSG_LEN, "%s", fcioErrorString.c_str());
2N/A}
2N/A