xref: /onnv-gate/usr/src/lib/sun_fc/common/FCHBA.cc (revision 11156:fa5f12909da7)
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 /*
2210275SReed.Liu@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 #include <unistd.h>
287836SJohn.Forte@Sun.COM 
297836SJohn.Forte@Sun.COM #include <FCHBA.h>
307836SJohn.Forte@Sun.COM #include <Exceptions.h>
317836SJohn.Forte@Sun.COM #include <Trace.h>
327836SJohn.Forte@Sun.COM #include <iostream>
337836SJohn.Forte@Sun.COM #include <iomanip>
347836SJohn.Forte@Sun.COM #include <cerrno>
357836SJohn.Forte@Sun.COM #include <cstring>
367836SJohn.Forte@Sun.COM #include <sys/types.h>
377836SJohn.Forte@Sun.COM #include <sys/stat.h>
387836SJohn.Forte@Sun.COM #include <fcntl.h>
397836SJohn.Forte@Sun.COM #include <unistd.h>
407836SJohn.Forte@Sun.COM #include <stropts.h>
417836SJohn.Forte@Sun.COM #include <sys/fibre-channel/fcio.h>
427836SJohn.Forte@Sun.COM #include <sys/fibre-channel/ulp/fcsm.h>
437836SJohn.Forte@Sun.COM #include <FCHBAPort.h>
447836SJohn.Forte@Sun.COM #include <HBAList.h>
457836SJohn.Forte@Sun.COM 
46*11156SRenia.Miao@Sun.COM #define EXCPT_RETRY_COUNT    10
47*11156SRenia.Miao@Sun.COM 
487836SJohn.Forte@Sun.COM using namespace std;
497836SJohn.Forte@Sun.COM const string FCHBA::FCSM_DRIVER_PATH = "/devices/pseudo/fcsm@0:fcsm";
507836SJohn.Forte@Sun.COM const string FCHBA::FCSM_DRIVER_PKG	= "SUNWfcsm";
517836SJohn.Forte@Sun.COM const int FCHBA::MAX_FCIO_MSG_LEN = 256;
527836SJohn.Forte@Sun.COM 
FCHBA(string path)537836SJohn.Forte@Sun.COM FCHBA::FCHBA(string path) : HBA() {
547836SJohn.Forte@Sun.COM     Trace log("FCHBA::FCHBA");
557836SJohn.Forte@Sun.COM     log.debug("Constructing new HBA (%s)", path.c_str());
567836SJohn.Forte@Sun.COM 
577836SJohn.Forte@Sun.COM     // Add first port
587836SJohn.Forte@Sun.COM     addPort(new FCHBAPort(path));
597836SJohn.Forte@Sun.COM 
607836SJohn.Forte@Sun.COM     name = "INTERNAL-FAILURE"; // Just in case things go wrong
617836SJohn.Forte@Sun.COM     try {
627836SJohn.Forte@Sun.COM 	HBA_ADAPTERATTRIBUTES attrs = getHBAAttributes();
637836SJohn.Forte@Sun.COM 	name = attrs.Manufacturer;
647836SJohn.Forte@Sun.COM 	name += "-";
657836SJohn.Forte@Sun.COM 	name += attrs.Model;
667836SJohn.Forte@Sun.COM 
677836SJohn.Forte@Sun.COM 	// Grab any other ports on this adapter
687836SJohn.Forte@Sun.COM 	for (int i = 1; i < attrs.NumberOfPorts; i++) {
697836SJohn.Forte@Sun.COM 	    fcio_t			fcio;
707836SJohn.Forte@Sun.COM 	    int			fd;
717836SJohn.Forte@Sun.COM 	    char		nextPath[MAXPATHLEN];
727836SJohn.Forte@Sun.COM 
737836SJohn.Forte@Sun.COM 	    log.debug("Fetching other port %d", i);
747836SJohn.Forte@Sun.COM 
757836SJohn.Forte@Sun.COM 	    // construct fcio struct
767836SJohn.Forte@Sun.COM 	    memset(&fcio, 0, sizeof (fcio_t));
777836SJohn.Forte@Sun.COM 	    memset(nextPath, 0, sizeof (nextPath));
787836SJohn.Forte@Sun.COM 	    fcio.fcio_cmd	= FCIO_GET_OTHER_ADAPTER_PORTS;
797836SJohn.Forte@Sun.COM 	    fcio.fcio_xfer	= FCIO_XFER_RW;
807836SJohn.Forte@Sun.COM 
817836SJohn.Forte@Sun.COM 	    fcio.fcio_olen	= MAXPATHLEN;
827836SJohn.Forte@Sun.COM 	    fcio.fcio_obuf	= (char *)nextPath;
837836SJohn.Forte@Sun.COM 	    fcio.fcio_ilen	= sizeof (i);
847836SJohn.Forte@Sun.COM 	    fcio.fcio_ibuf	= (char *)&i;
857836SJohn.Forte@Sun.COM 
867836SJohn.Forte@Sun.COM 	    // open the fcsm node so we can send the ioctl to
877836SJohn.Forte@Sun.COM 	    errno = 0;
887836SJohn.Forte@Sun.COM 	    HBAPort *port = getPortByIndex(0);
897836SJohn.Forte@Sun.COM 	    if ((fd = open(port->getPath().c_str(), O_NDELAY | O_RDONLY)) ==
907836SJohn.Forte@Sun.COM 		    -1) {
917836SJohn.Forte@Sun.COM 		log.debug("Unable to open %d opened (%s)", i,
927836SJohn.Forte@Sun.COM 		port->getPath().c_str());
937836SJohn.Forte@Sun.COM 		if (errno == EBUSY) {
947836SJohn.Forte@Sun.COM 		    throw BusyException();
957836SJohn.Forte@Sun.COM 		} else if (errno == EAGAIN) {
967836SJohn.Forte@Sun.COM 		    throw TryAgainException();
977836SJohn.Forte@Sun.COM 		} else if (errno == ENOTSUP) {
987836SJohn.Forte@Sun.COM 		    throw NotSupportedException();
997836SJohn.Forte@Sun.COM 		} else if (errno == ENOENT) {
1007836SJohn.Forte@Sun.COM 		    throw UnavailableException();
1017836SJohn.Forte@Sun.COM 		} else {
1027836SJohn.Forte@Sun.COM 		    throw IOError("Unable to open FCSM driver");
1037836SJohn.Forte@Sun.COM 		}
1047836SJohn.Forte@Sun.COM 	    }
1057836SJohn.Forte@Sun.COM 	    log.debug("Other port %d opened", i);
1067836SJohn.Forte@Sun.COM 
1077836SJohn.Forte@Sun.COM 	    errno = 0;
1087836SJohn.Forte@Sun.COM 	    if (ioctl(fd, FCIO_CMD, &fcio) != 0) {
1097836SJohn.Forte@Sun.COM 		// Interpret the fcio error code
1107836SJohn.Forte@Sun.COM 		char fcioErrorString[MAX_FCIO_MSG_LEN] = "";
1117836SJohn.Forte@Sun.COM 
1127836SJohn.Forte@Sun.COM 		log.genericIOError(
1137836SJohn.Forte@Sun.COM 		    "ADAPTER_LIST failed: "
1147836SJohn.Forte@Sun.COM 		    "Errno: \"%s\"",
1157836SJohn.Forte@Sun.COM 		    strerror(errno));
1167836SJohn.Forte@Sun.COM 		close(fd);
1177836SJohn.Forte@Sun.COM 		if (errno == EBUSY) {
1187836SJohn.Forte@Sun.COM 		    throw BusyException();
1197836SJohn.Forte@Sun.COM 		} else if (errno == EAGAIN) {
1207836SJohn.Forte@Sun.COM 		    throw TryAgainException();
1217836SJohn.Forte@Sun.COM 		} else if (errno == ENOTSUP) {
1227836SJohn.Forte@Sun.COM 		    throw NotSupportedException();
1237836SJohn.Forte@Sun.COM 		} else if (errno == ENOENT) {
1247836SJohn.Forte@Sun.COM 		    throw UnavailableException();
1257836SJohn.Forte@Sun.COM 		} else {
1267836SJohn.Forte@Sun.COM 		    throw IOError("Unable to build HBA list");
1277836SJohn.Forte@Sun.COM 		}
1287836SJohn.Forte@Sun.COM 	    }
1297836SJohn.Forte@Sun.COM 	    close(fd);
1307836SJohn.Forte@Sun.COM 	    log.debug("About to add port %d (%s)", i, nextPath);
1317836SJohn.Forte@Sun.COM 	    addPort(new FCHBAPort(nextPath));
1327836SJohn.Forte@Sun.COM 	}
133*11156SRenia.Miao@Sun.COM     } catch (BusyException &e) {
134*11156SRenia.Miao@Sun.COM         throw e;
135*11156SRenia.Miao@Sun.COM     } catch (TryAgainException &e) {
136*11156SRenia.Miao@Sun.COM 	throw e;
137*11156SRenia.Miao@Sun.COM     } catch (UnavailableException &e) {
138*11156SRenia.Miao@Sun.COM 	throw e;
1397836SJohn.Forte@Sun.COM     } catch (HBAException &e) {
1407836SJohn.Forte@Sun.COM 	log.internalError(
1417836SJohn.Forte@Sun.COM 		"Unable to construct HBA.");
1427836SJohn.Forte@Sun.COM 	throw e;
1437836SJohn.Forte@Sun.COM     }
1447836SJohn.Forte@Sun.COM }
1457836SJohn.Forte@Sun.COM 
getName()1467836SJohn.Forte@Sun.COM std::string FCHBA::getName() {
1477836SJohn.Forte@Sun.COM     Trace log("FCHBA::getName");
1487836SJohn.Forte@Sun.COM     return (name);
1497836SJohn.Forte@Sun.COM }
1507836SJohn.Forte@Sun.COM 
getHBAAttributes()1517836SJohn.Forte@Sun.COM HBA_ADAPTERATTRIBUTES FCHBA::getHBAAttributes() {
1527836SJohn.Forte@Sun.COM     Trace log("FCHBA::getHBAAttributes");
1537836SJohn.Forte@Sun.COM     int fd;
1547836SJohn.Forte@Sun.COM 
1557836SJohn.Forte@Sun.COM     errno = 0;
1567836SJohn.Forte@Sun.COM     HBAPort *port = getPortByIndex(0);
1577836SJohn.Forte@Sun.COM     if ((fd = open(port->getPath().c_str(), O_NDELAY | O_RDONLY)) == -1) {
1587836SJohn.Forte@Sun.COM 	// Why did we fail?
1597836SJohn.Forte@Sun.COM 	if (errno == EBUSY) {
1607836SJohn.Forte@Sun.COM 	    throw BusyException();
1617836SJohn.Forte@Sun.COM 	} else if (errno == EAGAIN) {
1627836SJohn.Forte@Sun.COM 	    throw TryAgainException();
1637836SJohn.Forte@Sun.COM 	} else if (errno == ENOTSUP) {
1647836SJohn.Forte@Sun.COM 	    throw NotSupportedException();
1657836SJohn.Forte@Sun.COM 	} else {
1667836SJohn.Forte@Sun.COM 	    throw IOError(port);
1677836SJohn.Forte@Sun.COM 	}
1687836SJohn.Forte@Sun.COM     }
1697836SJohn.Forte@Sun.COM 
1707836SJohn.Forte@Sun.COM     HBA_ADAPTERATTRIBUTES attributes;
1717836SJohn.Forte@Sun.COM     fcio_t			    fcio;
1727836SJohn.Forte@Sun.COM     fc_hba_adapter_attributes_t	    attrs;
1737836SJohn.Forte@Sun.COM 
1747836SJohn.Forte@Sun.COM     memset(&fcio, 0, sizeof (fcio));
1757836SJohn.Forte@Sun.COM 
1767836SJohn.Forte@Sun.COM     fcio.fcio_cmd = FCIO_GET_ADAPTER_ATTRIBUTES;
1777836SJohn.Forte@Sun.COM     fcio.fcio_olen = sizeof (attrs);
1787836SJohn.Forte@Sun.COM     fcio.fcio_xfer = FCIO_XFER_READ;
1797836SJohn.Forte@Sun.COM     fcio.fcio_obuf = (caddr_t)&attrs;
1807836SJohn.Forte@Sun.COM 
1817836SJohn.Forte@Sun.COM 
1827836SJohn.Forte@Sun.COM     errno = 0;
1837836SJohn.Forte@Sun.COM     if (ioctl(fd, FCIO_CMD, &fcio) != 0) {
1847836SJohn.Forte@Sun.COM 	close(fd);
1857836SJohn.Forte@Sun.COM 	if (errno == EBUSY) {
1867836SJohn.Forte@Sun.COM 	    throw BusyException();
1877836SJohn.Forte@Sun.COM 	} else if (errno == EAGAIN) {
1887836SJohn.Forte@Sun.COM 	    throw TryAgainException();
1897836SJohn.Forte@Sun.COM 	} else if (errno == ENOTSUP) {
1907836SJohn.Forte@Sun.COM 	    throw NotSupportedException();
1917836SJohn.Forte@Sun.COM 	} else {
1927836SJohn.Forte@Sun.COM 	    throw IOError("Unable to fetch adapter attributes");
1937836SJohn.Forte@Sun.COM 	}
1947836SJohn.Forte@Sun.COM     }
1957836SJohn.Forte@Sun.COM     close(fd);
1967836SJohn.Forte@Sun.COM 
1977836SJohn.Forte@Sun.COM     /* Now copy over the payload */
1987836SJohn.Forte@Sun.COM     attributes.NumberOfPorts = attrs.NumberOfPorts;
1997836SJohn.Forte@Sun.COM     attributes.VendorSpecificID = attrs.VendorSpecificID;
2007836SJohn.Forte@Sun.COM     memcpy(attributes.Manufacturer, attrs.Manufacturer, 64);
2017836SJohn.Forte@Sun.COM     memcpy(attributes.SerialNumber, attrs.SerialNumber, 64);
2027836SJohn.Forte@Sun.COM     memcpy(attributes.Model, attrs.Model, 256);
2037836SJohn.Forte@Sun.COM     memcpy(attributes.ModelDescription, attrs.ModelDescription, 256);
2047836SJohn.Forte@Sun.COM     memcpy(attributes.NodeSymbolicName, attrs.NodeSymbolicName, 256);
2057836SJohn.Forte@Sun.COM     memcpy(attributes.HardwareVersion, attrs.HardwareVersion, 256);
2067836SJohn.Forte@Sun.COM     memcpy(attributes.DriverVersion, attrs.DriverVersion, 256);
2077836SJohn.Forte@Sun.COM     memcpy(attributes.OptionROMVersion, attrs.OptionROMVersion, 256);
2087836SJohn.Forte@Sun.COM     memcpy(attributes.FirmwareVersion, attrs.FirmwareVersion, 256);
2097836SJohn.Forte@Sun.COM     memcpy(attributes.DriverName, attrs.DriverName, 256);
2107836SJohn.Forte@Sun.COM     memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
2117836SJohn.Forte@Sun.COM 
2127836SJohn.Forte@Sun.COM     return (attributes);
2137836SJohn.Forte@Sun.COM }
2147836SJohn.Forte@Sun.COM 
doForceLip()21510275SReed.Liu@Sun.COM int FCHBA::doForceLip() {
21610275SReed.Liu@Sun.COM     Trace	 log("FCHBA::doForceLip");
21710275SReed.Liu@Sun.COM     int		 fd;
21810275SReed.Liu@Sun.COM     fcio_t	 fcio;
21910275SReed.Liu@Sun.COM     uint64_t	 wwn  = 0;
22010275SReed.Liu@Sun.COM     HBAPort	*port = getPortByIndex(0);
22110275SReed.Liu@Sun.COM 
22210275SReed.Liu@Sun.COM     errno = 0;
22310275SReed.Liu@Sun.COM     if ((fd = open(port->getPath().c_str(), O_RDONLY | O_EXCL)) == -1) {
22410275SReed.Liu@Sun.COM 	if (errno == EBUSY) {
22510275SReed.Liu@Sun.COM 	    throw BusyException();
22610275SReed.Liu@Sun.COM 	} else if (errno == EAGAIN) {
22710275SReed.Liu@Sun.COM 	    throw TryAgainException();
22810275SReed.Liu@Sun.COM 	} else if (errno == ENOTSUP) {
22910275SReed.Liu@Sun.COM 	    throw NotSupportedException();
23010275SReed.Liu@Sun.COM 	} else {
23110275SReed.Liu@Sun.COM 	    throw IOError(port);
23210275SReed.Liu@Sun.COM 	}
23310275SReed.Liu@Sun.COM     }
23410275SReed.Liu@Sun.COM 
23510275SReed.Liu@Sun.COM     memset(&fcio, 0, sizeof (fcio));
23610275SReed.Liu@Sun.COM     fcio.fcio_cmd = FCIO_RESET_LINK;
23710275SReed.Liu@Sun.COM     fcio.fcio_xfer = FCIO_XFER_WRITE;
23810275SReed.Liu@Sun.COM     fcio.fcio_ilen = sizeof (wwn);
23910275SReed.Liu@Sun.COM     fcio.fcio_ibuf = (caddr_t)&wwn;
24010275SReed.Liu@Sun.COM 
24110275SReed.Liu@Sun.COM     errno = 0;
24210275SReed.Liu@Sun.COM     if (ioctl(fd, FCIO_CMD, &fcio) != 0) {
24310275SReed.Liu@Sun.COM 	close(fd);
24410275SReed.Liu@Sun.COM 
24510275SReed.Liu@Sun.COM 	if (errno == EBUSY) {
24610275SReed.Liu@Sun.COM 	    throw BusyException();
24710275SReed.Liu@Sun.COM 	} else if (errno == EAGAIN) {
24810275SReed.Liu@Sun.COM 	    throw TryAgainException();
24910275SReed.Liu@Sun.COM 	} else if (errno == ENOTSUP) {
25010275SReed.Liu@Sun.COM 	    throw NotSupportedException();
25110275SReed.Liu@Sun.COM 	} else {
25210275SReed.Liu@Sun.COM 	    throw IOError("Unable to reinitialize the link");
25310275SReed.Liu@Sun.COM 	}
25410275SReed.Liu@Sun.COM     } else {
25510275SReed.Liu@Sun.COM         close(fd);
25610275SReed.Liu@Sun.COM 	return (fcio.fcio_errno);
25710275SReed.Liu@Sun.COM     }
25810275SReed.Liu@Sun.COM }
25910275SReed.Liu@Sun.COM 
npivGetHBAAttributes()2607836SJohn.Forte@Sun.COM HBA_ADAPTERATTRIBUTES FCHBA::npivGetHBAAttributes() {
2617836SJohn.Forte@Sun.COM 	Trace log("FCHBA::npivGetHBAAttributes");
2627836SJohn.Forte@Sun.COM 	int fd;
2637836SJohn.Forte@Sun.COM 
2647836SJohn.Forte@Sun.COM 	errno = 0;
2657836SJohn.Forte@Sun.COM 	HBAPort *port = getPortByIndex(0);
2667836SJohn.Forte@Sun.COM 	if ((fd = open(port->getPath().c_str(), O_NDELAY | O_RDONLY)) == -1) {
2677836SJohn.Forte@Sun.COM 		// Why did we fail?
2687836SJohn.Forte@Sun.COM 		if (errno == EBUSY) {
2697836SJohn.Forte@Sun.COM 			throw BusyException();
2707836SJohn.Forte@Sun.COM 		} else if (errno == EAGAIN) {
2717836SJohn.Forte@Sun.COM 			throw TryAgainException();
2727836SJohn.Forte@Sun.COM 		} else if (errno == ENOTSUP) {
2737836SJohn.Forte@Sun.COM 			throw NotSupportedException();
2747836SJohn.Forte@Sun.COM 		} else {
2757836SJohn.Forte@Sun.COM 			throw IOError(port);
2767836SJohn.Forte@Sun.COM 		}
2777836SJohn.Forte@Sun.COM 	}
2787836SJohn.Forte@Sun.COM 
2797836SJohn.Forte@Sun.COM 	HBA_ADAPTERATTRIBUTES attributes;
2807836SJohn.Forte@Sun.COM 	fcio_t fcio;
2817836SJohn.Forte@Sun.COM 	fc_hba_adapter_attributes_t attrs;
2827836SJohn.Forte@Sun.COM 
2837836SJohn.Forte@Sun.COM 	memset(&fcio, 0, sizeof (fcio));
2847836SJohn.Forte@Sun.COM 	fcio.fcio_cmd = FCIO_NPIV_GET_ADAPTER_ATTRIBUTES;
2857836SJohn.Forte@Sun.COM 	fcio.fcio_olen = sizeof (attrs);
2867836SJohn.Forte@Sun.COM 	fcio.fcio_xfer = FCIO_XFER_READ;
2877836SJohn.Forte@Sun.COM 	fcio.fcio_obuf = (caddr_t)&attrs;
2887836SJohn.Forte@Sun.COM 	errno = 0;
2897836SJohn.Forte@Sun.COM 
2907836SJohn.Forte@Sun.COM 	if (ioctl(fd, FCIO_CMD, &fcio) != 0) {
2917836SJohn.Forte@Sun.COM 		close(fd);
2927836SJohn.Forte@Sun.COM 		if (errno == EBUSY) {
2937836SJohn.Forte@Sun.COM 			throw BusyException();
2947836SJohn.Forte@Sun.COM 		} else if (errno == EAGAIN) {
2957836SJohn.Forte@Sun.COM 			throw TryAgainException();
2967836SJohn.Forte@Sun.COM 		} else if (errno == ENOTSUP) {
2977836SJohn.Forte@Sun.COM 			throw NotSupportedException();
2987836SJohn.Forte@Sun.COM 		} else {
2997836SJohn.Forte@Sun.COM 			throw IOError("Unable to fetch adapter attributes");
3007836SJohn.Forte@Sun.COM 		}
3017836SJohn.Forte@Sun.COM 	}
3027836SJohn.Forte@Sun.COM 	close(fd);
3037836SJohn.Forte@Sun.COM 
3047836SJohn.Forte@Sun.COM 	/* Now copy over the payload */
3057836SJohn.Forte@Sun.COM 	attributes.NumberOfPorts = attrs.NumberOfPorts;
3067836SJohn.Forte@Sun.COM 	attributes.VendorSpecificID = attrs.VendorSpecificID;
3077836SJohn.Forte@Sun.COM 	memcpy(attributes.Manufacturer, attrs.Manufacturer, 64);
3087836SJohn.Forte@Sun.COM 	memcpy(attributes.SerialNumber, attrs.SerialNumber, 64);
3097836SJohn.Forte@Sun.COM 	memcpy(attributes.Model, attrs.Model, 256);
3107836SJohn.Forte@Sun.COM 	memcpy(attributes.ModelDescription, attrs.ModelDescription, 256);
3117836SJohn.Forte@Sun.COM 	memcpy(attributes.NodeSymbolicName, attrs.NodeSymbolicName, 256);
3127836SJohn.Forte@Sun.COM 	memcpy(attributes.HardwareVersion, attrs.HardwareVersion, 256);
3137836SJohn.Forte@Sun.COM 	memcpy(attributes.DriverVersion, attrs.DriverVersion, 256);
3147836SJohn.Forte@Sun.COM 	memcpy(attributes.OptionROMVersion, attrs.OptionROMVersion, 256);
3157836SJohn.Forte@Sun.COM 	memcpy(attributes.FirmwareVersion, attrs.FirmwareVersion, 256);
3167836SJohn.Forte@Sun.COM 	memcpy(attributes.DriverName, attrs.DriverName, 256);
3177836SJohn.Forte@Sun.COM 	memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
3187836SJohn.Forte@Sun.COM 
3197836SJohn.Forte@Sun.COM 	return (attributes);
3207836SJohn.Forte@Sun.COM }
3217836SJohn.Forte@Sun.COM 
loadAdapters(vector<HBA * > & list)3227836SJohn.Forte@Sun.COM void FCHBA::loadAdapters(vector<HBA*> &list) {
3237836SJohn.Forte@Sun.COM     Trace log("FCHBA::loadAdapters");
3247836SJohn.Forte@Sun.COM     fcio_t			fcio;
3257836SJohn.Forte@Sun.COM     fc_hba_list_t		*pathList;
3267836SJohn.Forte@Sun.COM     int			fd;
3277836SJohn.Forte@Sun.COM     int			size = 64; // default first attempt
3287836SJohn.Forte@Sun.COM     bool		retry = false;
3297836SJohn.Forte@Sun.COM     struct stat		sb;
3307836SJohn.Forte@Sun.COM     int bufSize;
3317836SJohn.Forte@Sun.COM 
3327836SJohn.Forte@Sun.COM     /* Before we do anything, let's see if FCSM is on the system */
3337836SJohn.Forte@Sun.COM     errno = 0;
3347836SJohn.Forte@Sun.COM     if (stat(FCSM_DRIVER_PATH.c_str(), &sb) != 0) {
3357836SJohn.Forte@Sun.COM 	if (errno == ENOENT) {
3367836SJohn.Forte@Sun.COM 	    log.genericIOError(
3377836SJohn.Forte@Sun.COM 		"The %s driver is not present. Unable to issue "
3387836SJohn.Forte@Sun.COM 		"CT commands. Please install the %s package.",
3397836SJohn.Forte@Sun.COM 		FCSM_DRIVER_PATH.c_str(), FCSM_DRIVER_PKG.c_str());
3407836SJohn.Forte@Sun.COM 	    throw NotSupportedException();
3417836SJohn.Forte@Sun.COM 	} else {
3427836SJohn.Forte@Sun.COM 	    log.genericIOError(
3437836SJohn.Forte@Sun.COM 		"Can not stat the %s driver for reason \"%s\" "
3447836SJohn.Forte@Sun.COM 		"Unable to issue CT commands.",
3457836SJohn.Forte@Sun.COM 		FCSM_DRIVER_PATH.c_str(), strerror(errno));
3467836SJohn.Forte@Sun.COM 	    throw IOError("Unable to stat FCSM driver");
3477836SJohn.Forte@Sun.COM 	}
3487836SJohn.Forte@Sun.COM     }
3497836SJohn.Forte@Sun.COM 
3507836SJohn.Forte@Sun.COM 
3517836SJohn.Forte@Sun.COM     /* construct fcio struct */
3527836SJohn.Forte@Sun.COM     memset(&fcio, 0, sizeof (fcio_t));
3537836SJohn.Forte@Sun.COM     fcio.fcio_cmd	= FCSMIO_ADAPTER_LIST;
3547836SJohn.Forte@Sun.COM     fcio.fcio_xfer	= FCIO_XFER_RW;
3557836SJohn.Forte@Sun.COM 
3567836SJohn.Forte@Sun.COM 
3577836SJohn.Forte@Sun.COM     /* open the fcsm node so we can send the ioctl to */
3587836SJohn.Forte@Sun.COM     errno = 0;
3597836SJohn.Forte@Sun.COM     if ((fd = open(FCSM_DRIVER_PATH.c_str(), O_RDONLY)) < 0) {
3607836SJohn.Forte@Sun.COM 	if (errno == EBUSY) {
3617836SJohn.Forte@Sun.COM 	    throw BusyException();
3627836SJohn.Forte@Sun.COM 	} else if (errno == EAGAIN) {
3637836SJohn.Forte@Sun.COM 	    throw TryAgainException();
3647836SJohn.Forte@Sun.COM 	} else if (errno == ENOTSUP) {
3657836SJohn.Forte@Sun.COM 	    throw NotSupportedException();
3667836SJohn.Forte@Sun.COM 	} else if (errno == ENOENT) {
3677836SJohn.Forte@Sun.COM 	    throw UnavailableException();
3687836SJohn.Forte@Sun.COM 	} else {
3697836SJohn.Forte@Sun.COM 	    throw IOError("Unable to open FCSM driver");
3707836SJohn.Forte@Sun.COM 	}
3717836SJohn.Forte@Sun.COM     }
3727836SJohn.Forte@Sun.COM 
3737836SJohn.Forte@Sun.COM     do {
3747836SJohn.Forte@Sun.COM 	retry = false;
3757836SJohn.Forte@Sun.COM 	errno = 0;
3767836SJohn.Forte@Sun.COM 	bufSize = MAXPATHLEN * size + (int) sizeof (fc_hba_list_t) - 1;
3777836SJohn.Forte@Sun.COM 	pathList = (fc_hba_list_t *)new uchar_t[bufSize];
3787836SJohn.Forte@Sun.COM 	pathList->numAdapters = size;
3797836SJohn.Forte@Sun.COM 	fcio.fcio_olen	= bufSize;
3807836SJohn.Forte@Sun.COM 	fcio.fcio_obuf	= (char *)pathList;
3817836SJohn.Forte@Sun.COM 	if (ioctl(fd, FCSMIO_CMD, &fcio) != 0) {
3827836SJohn.Forte@Sun.COM 	    /* Interpret the fcio error code */
3837836SJohn.Forte@Sun.COM 	    char fcioErrorString[MAX_FCIO_MSG_LEN] = "";
3847836SJohn.Forte@Sun.COM 
3857836SJohn.Forte@Sun.COM 	    log.genericIOError(
3867836SJohn.Forte@Sun.COM 		"ADAPTER_LIST failed: "
3877836SJohn.Forte@Sun.COM 		"Errno: \"%s\"",
3887836SJohn.Forte@Sun.COM 		strerror(errno));
3897836SJohn.Forte@Sun.COM 	    delete (pathList);
3907836SJohn.Forte@Sun.COM 	    close(fd);
3917836SJohn.Forte@Sun.COM 	    if (errno == EBUSY) {
3927836SJohn.Forte@Sun.COM 		throw BusyException();
3937836SJohn.Forte@Sun.COM 	    } else if (errno == EAGAIN) {
3947836SJohn.Forte@Sun.COM 		throw TryAgainException();
3957836SJohn.Forte@Sun.COM 	    } else if (errno == ENOTSUP) {
3967836SJohn.Forte@Sun.COM 		throw NotSupportedException();
3977836SJohn.Forte@Sun.COM 	    } else if (errno == ENOENT) {
3987836SJohn.Forte@Sun.COM 		throw UnavailableException();
3997836SJohn.Forte@Sun.COM 	    } else {
4007836SJohn.Forte@Sun.COM 		throw IOError("Unable to build HBA list");
4017836SJohn.Forte@Sun.COM 	    }
4027836SJohn.Forte@Sun.COM 	}
4037836SJohn.Forte@Sun.COM 	if (pathList->numAdapters > size) {
4047836SJohn.Forte@Sun.COM 	    log.debug(
4057836SJohn.Forte@Sun.COM 		"Buffer too small for number of HBAs. Retrying.");
4067836SJohn.Forte@Sun.COM 	    size = pathList->numAdapters;
4077836SJohn.Forte@Sun.COM 	    retry = true;
4087836SJohn.Forte@Sun.COM 	    delete (pathList);
4097836SJohn.Forte@Sun.COM 	}
4107836SJohn.Forte@Sun.COM     } while (retry);
4117836SJohn.Forte@Sun.COM 
4127836SJohn.Forte@Sun.COM     close(fd);
4137836SJohn.Forte@Sun.COM     log.debug("Detected %d adapters", pathList->numAdapters);
414*11156SRenia.Miao@Sun.COM     for (int i = 0, times =0; i < pathList->numAdapters;) {
4157836SJohn.Forte@Sun.COM 	try {
4167836SJohn.Forte@Sun.COM 	    HBA *hba = new FCHBA(pathList->hbaPaths[i]);
4177836SJohn.Forte@Sun.COM 	    list.insert(list.begin(), hba);
418*11156SRenia.Miao@Sun.COM 	    i++;
419*11156SRenia.Miao@Sun.COM 	} catch (BusyException &e) {
420*11156SRenia.Miao@Sun.COM             sleep(1);
421*11156SRenia.Miao@Sun.COM             if (times++ > EXCPT_RETRY_COUNT) {
422*11156SRenia.Miao@Sun.COM                 i++;
423*11156SRenia.Miao@Sun.COM                 times = 0;
424*11156SRenia.Miao@Sun.COM             }
425*11156SRenia.Miao@Sun.COM 	    continue;
426*11156SRenia.Miao@Sun.COM 	} catch (TryAgainException &e) {
427*11156SRenia.Miao@Sun.COM 	    sleep(1);
428*11156SRenia.Miao@Sun.COM 	    if (times++ > EXCPT_RETRY_COUNT) {
429*11156SRenia.Miao@Sun.COM 		i++;
430*11156SRenia.Miao@Sun.COM 		times = 0;
431*11156SRenia.Miao@Sun.COM 	    }
432*11156SRenia.Miao@Sun.COM 	    continue;
433*11156SRenia.Miao@Sun.COM 	} catch (UnavailableException &e) {
434*11156SRenia.Miao@Sun.COM 	    sleep(1);
435*11156SRenia.Miao@Sun.COM 	    if (times++ > EXCPT_RETRY_COUNT) {
436*11156SRenia.Miao@Sun.COM 		i++;
437*11156SRenia.Miao@Sun.COM 		times = 0;
438*11156SRenia.Miao@Sun.COM 	    }
439*11156SRenia.Miao@Sun.COM 	    continue;
440*11156SRenia.Miao@Sun.COM 	} catch (HBAException &e) {
441*11156SRenia.Miao@Sun.COM 	    i++;
442*11156SRenia.Miao@Sun.COM 	    times = 0;
4437836SJohn.Forte@Sun.COM 	    log.debug(
4447836SJohn.Forte@Sun.COM 		"Ignoring partial failure while loading an HBA");
4457836SJohn.Forte@Sun.COM 	}
4467836SJohn.Forte@Sun.COM     }
4477836SJohn.Forte@Sun.COM     if (pathList->numAdapters > HBAList::HBA_MAX_PER_LIST) {
4487836SJohn.Forte@Sun.COM 	delete(pathList);
4497836SJohn.Forte@Sun.COM 	throw InternalError(
4507836SJohn.Forte@Sun.COM 	    "Exceeds max number of adatpers that VSL supports.");
4517836SJohn.Forte@Sun.COM     }
4527836SJohn.Forte@Sun.COM     delete (pathList);
4537836SJohn.Forte@Sun.COM }
454