summaryrefslogtreecommitdiff
path: root/usr/src/lib/sun_fc/common/FCHBA.cc
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/sun_fc/common/FCHBA.cc')
-rw-r--r--usr/src/lib/sun_fc/common/FCHBA.cc376
1 files changed, 376 insertions, 0 deletions
diff --git a/usr/src/lib/sun_fc/common/FCHBA.cc b/usr/src/lib/sun_fc/common/FCHBA.cc
new file mode 100644
index 0000000000..aba53f0b88
--- /dev/null
+++ b/usr/src/lib/sun_fc/common/FCHBA.cc
@@ -0,0 +1,376 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+
+#include <unistd.h>
+
+#include <FCHBA.h>
+#include <Exceptions.h>
+#include <Trace.h>
+#include <iostream>
+#include <iomanip>
+#include <cerrno>
+#include <cstring>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stropts.h>
+#include <sys/fibre-channel/fcio.h>
+#include <sys/fibre-channel/ulp/fcsm.h>
+#include <FCHBAPort.h>
+#include <HBAList.h>
+
+using namespace std;
+const string FCHBA::FCSM_DRIVER_PATH = "/devices/pseudo/fcsm@0:fcsm";
+const string FCHBA::FCSM_DRIVER_PKG = "SUNWfcsm";
+const int FCHBA::MAX_FCIO_MSG_LEN = 256;
+
+FCHBA::FCHBA(string path) : HBA() {
+ Trace log("FCHBA::FCHBA");
+ log.debug("Constructing new HBA (%s)", path.c_str());
+
+ // Add first port
+ addPort(new FCHBAPort(path));
+
+ name = "INTERNAL-FAILURE"; // Just in case things go wrong
+ try {
+ HBA_ADAPTERATTRIBUTES attrs = getHBAAttributes();
+ name = attrs.Manufacturer;
+ name += "-";
+ name += attrs.Model;
+
+ // Grab any other ports on this adapter
+ for (int i = 1; i < attrs.NumberOfPorts; i++) {
+ fcio_t fcio;
+ int fd;
+ char nextPath[MAXPATHLEN];
+
+ log.debug("Fetching other port %d", i);
+
+ // construct fcio struct
+ memset(&fcio, 0, sizeof (fcio_t));
+ memset(nextPath, 0, sizeof (nextPath));
+ fcio.fcio_cmd = FCIO_GET_OTHER_ADAPTER_PORTS;
+ fcio.fcio_xfer = FCIO_XFER_RW;
+
+ fcio.fcio_olen = MAXPATHLEN;
+ fcio.fcio_obuf = (char *)nextPath;
+ fcio.fcio_ilen = sizeof (i);
+ fcio.fcio_ibuf = (char *)&i;
+
+ // open the fcsm node so we can send the ioctl to
+ errno = 0;
+ HBAPort *port = getPortByIndex(0);
+ if ((fd = open(port->getPath().c_str(), O_NDELAY | O_RDONLY)) ==
+ -1) {
+ log.debug("Unable to open %d opened (%s)", i,
+ port->getPath().c_str());
+ if (errno == EBUSY) {
+ throw BusyException();
+ } else if (errno == EAGAIN) {
+ throw TryAgainException();
+ } else if (errno == ENOTSUP) {
+ throw NotSupportedException();
+ } else if (errno == ENOENT) {
+ throw UnavailableException();
+ } else {
+ throw IOError("Unable to open FCSM driver");
+ }
+ }
+ log.debug("Other port %d opened", i);
+
+ errno = 0;
+ if (ioctl(fd, FCIO_CMD, &fcio) != 0) {
+ // Interpret the fcio error code
+ char fcioErrorString[MAX_FCIO_MSG_LEN] = "";
+
+ log.genericIOError(
+ "ADAPTER_LIST failed: "
+ "Errno: \"%s\"",
+ strerror(errno));
+ close(fd);
+ if (errno == EBUSY) {
+ throw BusyException();
+ } else if (errno == EAGAIN) {
+ throw TryAgainException();
+ } else if (errno == ENOTSUP) {
+ throw NotSupportedException();
+ } else if (errno == ENOENT) {
+ throw UnavailableException();
+ } else {
+ throw IOError("Unable to build HBA list");
+ }
+ }
+ close(fd);
+ log.debug("About to add port %d (%s)", i, nextPath);
+ addPort(new FCHBAPort(nextPath));
+ }
+ } catch (HBAException &e) {
+ log.internalError(
+ "Unable to construct HBA.");
+ throw e;
+ }
+}
+
+std::string FCHBA::getName() {
+ Trace log("FCHBA::getName");
+ return (name);
+}
+
+HBA_ADAPTERATTRIBUTES FCHBA::getHBAAttributes() {
+ Trace log("FCHBA::getHBAAttributes");
+ int fd;
+
+ errno = 0;
+ HBAPort *port = getPortByIndex(0);
+ if ((fd = open(port->getPath().c_str(), O_NDELAY | O_RDONLY)) == -1) {
+ // Why did we fail?
+ if (errno == EBUSY) {
+ throw BusyException();
+ } else if (errno == EAGAIN) {
+ throw TryAgainException();
+ } else if (errno == ENOTSUP) {
+ throw NotSupportedException();
+ } else {
+ throw IOError(port);
+ }
+ }
+
+ HBA_ADAPTERATTRIBUTES attributes;
+ fcio_t fcio;
+ fc_hba_adapter_attributes_t attrs;
+
+ memset(&fcio, 0, sizeof (fcio));
+
+ fcio.fcio_cmd = FCIO_GET_ADAPTER_ATTRIBUTES;
+ fcio.fcio_olen = sizeof (attrs);
+ fcio.fcio_xfer = FCIO_XFER_READ;
+ fcio.fcio_obuf = (caddr_t)&attrs;
+
+
+ errno = 0;
+ if (ioctl(fd, FCIO_CMD, &fcio) != 0) {
+ close(fd);
+ if (errno == EBUSY) {
+ throw BusyException();
+ } else if (errno == EAGAIN) {
+ throw TryAgainException();
+ } else if (errno == ENOTSUP) {
+ throw NotSupportedException();
+ } else {
+ throw IOError("Unable to fetch adapter attributes");
+ }
+ }
+ close(fd);
+
+ /* Now copy over the payload */
+ attributes.NumberOfPorts = attrs.NumberOfPorts;
+ attributes.VendorSpecificID = attrs.VendorSpecificID;
+ memcpy(attributes.Manufacturer, attrs.Manufacturer, 64);
+ memcpy(attributes.SerialNumber, attrs.SerialNumber, 64);
+ memcpy(attributes.Model, attrs.Model, 256);
+ memcpy(attributes.ModelDescription, attrs.ModelDescription, 256);
+ memcpy(attributes.NodeSymbolicName, attrs.NodeSymbolicName, 256);
+ memcpy(attributes.HardwareVersion, attrs.HardwareVersion, 256);
+ memcpy(attributes.DriverVersion, attrs.DriverVersion, 256);
+ memcpy(attributes.OptionROMVersion, attrs.OptionROMVersion, 256);
+ memcpy(attributes.FirmwareVersion, attrs.FirmwareVersion, 256);
+ memcpy(attributes.DriverName, attrs.DriverName, 256);
+ memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
+
+ return (attributes);
+}
+
+HBA_ADAPTERATTRIBUTES FCHBA::npivGetHBAAttributes() {
+ Trace log("FCHBA::npivGetHBAAttributes");
+ int fd;
+
+ errno = 0;
+ HBAPort *port = getPortByIndex(0);
+ if ((fd = open(port->getPath().c_str(), O_NDELAY | O_RDONLY)) == -1) {
+ // Why did we fail?
+ if (errno == EBUSY) {
+ throw BusyException();
+ } else if (errno == EAGAIN) {
+ throw TryAgainException();
+ } else if (errno == ENOTSUP) {
+ throw NotSupportedException();
+ } else {
+ throw IOError(port);
+ }
+ }
+
+ HBA_ADAPTERATTRIBUTES attributes;
+ fcio_t fcio;
+ fc_hba_adapter_attributes_t attrs;
+
+ memset(&fcio, 0, sizeof (fcio));
+ fcio.fcio_cmd = FCIO_NPIV_GET_ADAPTER_ATTRIBUTES;
+ fcio.fcio_olen = sizeof (attrs);
+ fcio.fcio_xfer = FCIO_XFER_READ;
+ fcio.fcio_obuf = (caddr_t)&attrs;
+ errno = 0;
+
+ if (ioctl(fd, FCIO_CMD, &fcio) != 0) {
+ close(fd);
+ if (errno == EBUSY) {
+ throw BusyException();
+ } else if (errno == EAGAIN) {
+ throw TryAgainException();
+ } else if (errno == ENOTSUP) {
+ throw NotSupportedException();
+ } else {
+ throw IOError("Unable to fetch adapter attributes");
+ }
+ }
+ close(fd);
+
+ /* Now copy over the payload */
+ attributes.NumberOfPorts = attrs.NumberOfPorts;
+ attributes.VendorSpecificID = attrs.VendorSpecificID;
+ memcpy(attributes.Manufacturer, attrs.Manufacturer, 64);
+ memcpy(attributes.SerialNumber, attrs.SerialNumber, 64);
+ memcpy(attributes.Model, attrs.Model, 256);
+ memcpy(attributes.ModelDescription, attrs.ModelDescription, 256);
+ memcpy(attributes.NodeSymbolicName, attrs.NodeSymbolicName, 256);
+ memcpy(attributes.HardwareVersion, attrs.HardwareVersion, 256);
+ memcpy(attributes.DriverVersion, attrs.DriverVersion, 256);
+ memcpy(attributes.OptionROMVersion, attrs.OptionROMVersion, 256);
+ memcpy(attributes.FirmwareVersion, attrs.FirmwareVersion, 256);
+ memcpy(attributes.DriverName, attrs.DriverName, 256);
+ memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
+
+ return (attributes);
+}
+
+void FCHBA::loadAdapters(vector<HBA*> &list) {
+ Trace log("FCHBA::loadAdapters");
+ fcio_t fcio;
+ fc_hba_list_t *pathList;
+ int fd;
+ int size = 64; // default first attempt
+ bool retry = false;
+ struct stat sb;
+ int bufSize;
+
+ /* Before we do anything, let's see if FCSM is on the system */
+ errno = 0;
+ if (stat(FCSM_DRIVER_PATH.c_str(), &sb) != 0) {
+ if (errno == ENOENT) {
+ log.genericIOError(
+ "The %s driver is not present. Unable to issue "
+ "CT commands. Please install the %s package.",
+ FCSM_DRIVER_PATH.c_str(), FCSM_DRIVER_PKG.c_str());
+ throw NotSupportedException();
+ } else {
+ log.genericIOError(
+ "Can not stat the %s driver for reason \"%s\" "
+ "Unable to issue CT commands.",
+ FCSM_DRIVER_PATH.c_str(), strerror(errno));
+ throw IOError("Unable to stat FCSM driver");
+ }
+ }
+
+
+ /* construct fcio struct */
+ memset(&fcio, 0, sizeof (fcio_t));
+ fcio.fcio_cmd = FCSMIO_ADAPTER_LIST;
+ fcio.fcio_xfer = FCIO_XFER_RW;
+
+
+ /* open the fcsm node so we can send the ioctl to */
+ errno = 0;
+ if ((fd = open(FCSM_DRIVER_PATH.c_str(), O_RDONLY)) < 0) {
+ if (errno == EBUSY) {
+ throw BusyException();
+ } else if (errno == EAGAIN) {
+ throw TryAgainException();
+ } else if (errno == ENOTSUP) {
+ throw NotSupportedException();
+ } else if (errno == ENOENT) {
+ throw UnavailableException();
+ } else {
+ throw IOError("Unable to open FCSM driver");
+ }
+ }
+
+ do {
+ retry = false;
+ errno = 0;
+ bufSize = MAXPATHLEN * size + (int) sizeof (fc_hba_list_t) - 1;
+ pathList = (fc_hba_list_t *)new uchar_t[bufSize];
+ pathList->numAdapters = size;
+ fcio.fcio_olen = bufSize;
+ fcio.fcio_obuf = (char *)pathList;
+ if (ioctl(fd, FCSMIO_CMD, &fcio) != 0) {
+ /* Interpret the fcio error code */
+ char fcioErrorString[MAX_FCIO_MSG_LEN] = "";
+
+ log.genericIOError(
+ "ADAPTER_LIST failed: "
+ "Errno: \"%s\"",
+ strerror(errno));
+ delete (pathList);
+ close(fd);
+ if (errno == EBUSY) {
+ throw BusyException();
+ } else if (errno == EAGAIN) {
+ throw TryAgainException();
+ } else if (errno == ENOTSUP) {
+ throw NotSupportedException();
+ } else if (errno == ENOENT) {
+ throw UnavailableException();
+ } else {
+ throw IOError("Unable to build HBA list");
+ }
+ }
+ if (pathList->numAdapters > size) {
+ log.debug(
+ "Buffer too small for number of HBAs. Retrying.");
+ size = pathList->numAdapters;
+ retry = true;
+ delete (pathList);
+ }
+ } while (retry);
+
+ close(fd);
+ log.debug("Detected %d adapters", pathList->numAdapters);
+ for (int i = 0; i < pathList->numAdapters; i++) {
+ try {
+ HBA *hba = new FCHBA(pathList->hbaPaths[i]);
+ list.insert(list.begin(), hba);
+ } catch (...) {
+ log.debug(
+ "Ignoring partial failure while loading an HBA");
+ }
+ }
+ if (pathList->numAdapters > HBAList::HBA_MAX_PER_LIST) {
+ delete(pathList);
+ throw InternalError(
+ "Exceeds max number of adatpers that VSL supports.");
+ }
+ delete (pathList);
+}