xref: /illumos-gate/usr/src/lib/sun_fc/common/FCHBA.cc (revision b3385a70)
1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
8fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte /*
22a7949318SReed  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23fcf3ce44SJohn Forte  * Use is subject to license terms.
24fcf3ce44SJohn Forte  */
25fcf3ce44SJohn Forte 
26fcf3ce44SJohn Forte 
27fcf3ce44SJohn Forte #include <unistd.h>
28fcf3ce44SJohn Forte 
29fcf3ce44SJohn Forte #include <FCHBA.h>
30fcf3ce44SJohn Forte #include <Exceptions.h>
31fcf3ce44SJohn Forte #include <Trace.h>
32fcf3ce44SJohn Forte #include <iostream>
33fcf3ce44SJohn Forte #include <iomanip>
34fcf3ce44SJohn Forte #include <cerrno>
35fcf3ce44SJohn Forte #include <cstring>
36fcf3ce44SJohn Forte #include <sys/types.h>
37fcf3ce44SJohn Forte #include <sys/stat.h>
38fcf3ce44SJohn Forte #include <fcntl.h>
39fcf3ce44SJohn Forte #include <unistd.h>
40fcf3ce44SJohn Forte #include <stropts.h>
41fcf3ce44SJohn Forte #include <sys/fibre-channel/fcio.h>
42fcf3ce44SJohn Forte #include <sys/fibre-channel/ulp/fcsm.h>
43fcf3ce44SJohn Forte #include <FCHBAPort.h>
44fcf3ce44SJohn Forte #include <HBAList.h>
45fcf3ce44SJohn Forte 
461770502eSYu Renia Miao #define EXCPT_RETRY_COUNT    10
471770502eSYu Renia Miao 
48fcf3ce44SJohn Forte using namespace std;
49fcf3ce44SJohn Forte const string FCHBA::FCSM_DRIVER_PATH = "/devices/pseudo/fcsm@0:fcsm";
50fcf3ce44SJohn Forte const string FCHBA::FCSM_DRIVER_PKG	= "SUNWfcsm";
51fcf3ce44SJohn Forte const int FCHBA::MAX_FCIO_MSG_LEN = 256;
52fcf3ce44SJohn Forte 
FCHBA(string path)53fcf3ce44SJohn Forte FCHBA::FCHBA(string path) : HBA() {
54fcf3ce44SJohn Forte     Trace log("FCHBA::FCHBA");
55fcf3ce44SJohn Forte     log.debug("Constructing new HBA (%s)", path.c_str());
56fcf3ce44SJohn Forte 
57fcf3ce44SJohn Forte     // Add first port
58fcf3ce44SJohn Forte     addPort(new FCHBAPort(path));
59fcf3ce44SJohn Forte 
60fcf3ce44SJohn Forte     name = "INTERNAL-FAILURE"; // Just in case things go wrong
61fcf3ce44SJohn Forte     try {
62fcf3ce44SJohn Forte 	HBA_ADAPTERATTRIBUTES attrs = getHBAAttributes();
63fcf3ce44SJohn Forte 	name = attrs.Manufacturer;
64fcf3ce44SJohn Forte 	name += "-";
65fcf3ce44SJohn Forte 	name += attrs.Model;
66fcf3ce44SJohn Forte 
67fcf3ce44SJohn Forte 	// Grab any other ports on this adapter
68fcf3ce44SJohn Forte 	for (int i = 1; i < attrs.NumberOfPorts; i++) {
69fcf3ce44SJohn Forte 	    fcio_t			fcio;
70fcf3ce44SJohn Forte 	    int			fd;
71fcf3ce44SJohn Forte 	    char		nextPath[MAXPATHLEN];
72fcf3ce44SJohn Forte 
73fcf3ce44SJohn Forte 	    log.debug("Fetching other port %d", i);
74fcf3ce44SJohn Forte 
75fcf3ce44SJohn Forte 	    // construct fcio struct
76fcf3ce44SJohn Forte 	    memset(&fcio, 0, sizeof (fcio_t));
77fcf3ce44SJohn Forte 	    memset(nextPath, 0, sizeof (nextPath));
78fcf3ce44SJohn Forte 	    fcio.fcio_cmd	= FCIO_GET_OTHER_ADAPTER_PORTS;
79fcf3ce44SJohn Forte 	    fcio.fcio_xfer	= FCIO_XFER_RW;
80fcf3ce44SJohn Forte 
81fcf3ce44SJohn Forte 	    fcio.fcio_olen	= MAXPATHLEN;
82fcf3ce44SJohn Forte 	    fcio.fcio_obuf	= (char *)nextPath;
83fcf3ce44SJohn Forte 	    fcio.fcio_ilen	= sizeof (i);
84fcf3ce44SJohn Forte 	    fcio.fcio_ibuf	= (char *)&i;
85fcf3ce44SJohn Forte 
86fcf3ce44SJohn Forte 	    // open the fcsm node so we can send the ioctl to
87fcf3ce44SJohn Forte 	    errno = 0;
88fcf3ce44SJohn Forte 	    HBAPort *port = getPortByIndex(0);
89fcf3ce44SJohn Forte 	    if ((fd = open(port->getPath().c_str(), O_NDELAY | O_RDONLY)) ==
90fcf3ce44SJohn Forte 		    -1) {
91fcf3ce44SJohn Forte 		log.debug("Unable to open %d opened (%s)", i,
92fcf3ce44SJohn Forte 		port->getPath().c_str());
93fcf3ce44SJohn Forte 		if (errno == EBUSY) {
94fcf3ce44SJohn Forte 		    throw BusyException();
95fcf3ce44SJohn Forte 		} else if (errno == EAGAIN) {
96fcf3ce44SJohn Forte 		    throw TryAgainException();
97fcf3ce44SJohn Forte 		} else if (errno == ENOTSUP) {
98fcf3ce44SJohn Forte 		    throw NotSupportedException();
99fcf3ce44SJohn Forte 		} else if (errno == ENOENT) {
100fcf3ce44SJohn Forte 		    throw UnavailableException();
101fcf3ce44SJohn Forte 		} else {
102fcf3ce44SJohn Forte 		    throw IOError("Unable to open FCSM driver");
103fcf3ce44SJohn Forte 		}
104fcf3ce44SJohn Forte 	    }
105fcf3ce44SJohn Forte 	    log.debug("Other port %d opened", i);
106fcf3ce44SJohn Forte 
107fcf3ce44SJohn Forte 	    errno = 0;
108fcf3ce44SJohn Forte 	    if (ioctl(fd, FCIO_CMD, &fcio) != 0) {
109fcf3ce44SJohn Forte 		// Interpret the fcio error code
110fcf3ce44SJohn Forte 		char fcioErrorString[MAX_FCIO_MSG_LEN] = "";
111fcf3ce44SJohn Forte 
112fcf3ce44SJohn Forte 		log.genericIOError(
113fcf3ce44SJohn Forte 		    "ADAPTER_LIST failed: "
114fcf3ce44SJohn Forte 		    "Errno: \"%s\"",
115fcf3ce44SJohn Forte 		    strerror(errno));
116fcf3ce44SJohn Forte 		close(fd);
117fcf3ce44SJohn Forte 		if (errno == EBUSY) {
118fcf3ce44SJohn Forte 		    throw BusyException();
119fcf3ce44SJohn Forte 		} else if (errno == EAGAIN) {
120fcf3ce44SJohn Forte 		    throw TryAgainException();
121fcf3ce44SJohn Forte 		} else if (errno == ENOTSUP) {
122fcf3ce44SJohn Forte 		    throw NotSupportedException();
123fcf3ce44SJohn Forte 		} else if (errno == ENOENT) {
124fcf3ce44SJohn Forte 		    throw UnavailableException();
125fcf3ce44SJohn Forte 		} else {
126fcf3ce44SJohn Forte 		    throw IOError("Unable to build HBA list");
127fcf3ce44SJohn Forte 		}
128fcf3ce44SJohn Forte 	    }
129fcf3ce44SJohn Forte 	    close(fd);
130fcf3ce44SJohn Forte 	    log.debug("About to add port %d (%s)", i, nextPath);
131fcf3ce44SJohn Forte 	    addPort(new FCHBAPort(nextPath));
132fcf3ce44SJohn Forte 	}
1331770502eSYu Renia Miao     } catch (BusyException &e) {
1341770502eSYu Renia Miao         throw e;
1351770502eSYu Renia Miao     } catch (TryAgainException &e) {
1361770502eSYu Renia Miao 	throw e;
1371770502eSYu Renia Miao     } catch (UnavailableException &e) {
1381770502eSYu Renia Miao 	throw e;
139fcf3ce44SJohn Forte     } catch (HBAException &e) {
140fcf3ce44SJohn Forte 	log.internalError(
141fcf3ce44SJohn Forte 		"Unable to construct HBA.");
142fcf3ce44SJohn Forte 	throw e;
143fcf3ce44SJohn Forte     }
144fcf3ce44SJohn Forte }
145fcf3ce44SJohn Forte 
getName()146fcf3ce44SJohn Forte std::string FCHBA::getName() {
147fcf3ce44SJohn Forte     Trace log("FCHBA::getName");
148fcf3ce44SJohn Forte     return (name);
149fcf3ce44SJohn Forte }
150fcf3ce44SJohn Forte 
getHBAAttributes()151fcf3ce44SJohn Forte HBA_ADAPTERATTRIBUTES FCHBA::getHBAAttributes() {
152fcf3ce44SJohn Forte     Trace log("FCHBA::getHBAAttributes");
153fcf3ce44SJohn Forte     int fd;
154fcf3ce44SJohn Forte 
155fcf3ce44SJohn Forte     errno = 0;
156fcf3ce44SJohn Forte     HBAPort *port = getPortByIndex(0);
157fcf3ce44SJohn Forte     if ((fd = open(port->getPath().c_str(), O_NDELAY | O_RDONLY)) == -1) {
158fcf3ce44SJohn Forte 	// Why did we fail?
159fcf3ce44SJohn Forte 	if (errno == EBUSY) {
160fcf3ce44SJohn Forte 	    throw BusyException();
161fcf3ce44SJohn Forte 	} else if (errno == EAGAIN) {
162fcf3ce44SJohn Forte 	    throw TryAgainException();
163fcf3ce44SJohn Forte 	} else if (errno == ENOTSUP) {
164fcf3ce44SJohn Forte 	    throw NotSupportedException();
165fcf3ce44SJohn Forte 	} else {
166fcf3ce44SJohn Forte 	    throw IOError(port);
167fcf3ce44SJohn Forte 	}
168fcf3ce44SJohn Forte     }
169fcf3ce44SJohn Forte 
170fcf3ce44SJohn Forte     HBA_ADAPTERATTRIBUTES attributes;
171fcf3ce44SJohn Forte     fcio_t			    fcio;
172fcf3ce44SJohn Forte     fc_hba_adapter_attributes_t	    attrs;
173fcf3ce44SJohn Forte 
174fcf3ce44SJohn Forte     memset(&fcio, 0, sizeof (fcio));
175fcf3ce44SJohn Forte 
176fcf3ce44SJohn Forte     fcio.fcio_cmd = FCIO_GET_ADAPTER_ATTRIBUTES;
177fcf3ce44SJohn Forte     fcio.fcio_olen = sizeof (attrs);
178fcf3ce44SJohn Forte     fcio.fcio_xfer = FCIO_XFER_READ;
179fcf3ce44SJohn Forte     fcio.fcio_obuf = (caddr_t)&attrs;
180fcf3ce44SJohn Forte 
181fcf3ce44SJohn Forte 
182fcf3ce44SJohn Forte     errno = 0;
183fcf3ce44SJohn Forte     if (ioctl(fd, FCIO_CMD, &fcio) != 0) {
184fcf3ce44SJohn Forte 	close(fd);
185fcf3ce44SJohn Forte 	if (errno == EBUSY) {
186fcf3ce44SJohn Forte 	    throw BusyException();
187fcf3ce44SJohn Forte 	} else if (errno == EAGAIN) {
188fcf3ce44SJohn Forte 	    throw TryAgainException();
189fcf3ce44SJohn Forte 	} else if (errno == ENOTSUP) {
190fcf3ce44SJohn Forte 	    throw NotSupportedException();
191fcf3ce44SJohn Forte 	} else {
192fcf3ce44SJohn Forte 	    throw IOError("Unable to fetch adapter attributes");
193fcf3ce44SJohn Forte 	}
194fcf3ce44SJohn Forte     }
195fcf3ce44SJohn Forte     close(fd);
196fcf3ce44SJohn Forte 
197fcf3ce44SJohn Forte     /* Now copy over the payload */
198fcf3ce44SJohn Forte     attributes.NumberOfPorts = attrs.NumberOfPorts;
199fcf3ce44SJohn Forte     attributes.VendorSpecificID = attrs.VendorSpecificID;
200fcf3ce44SJohn Forte     memcpy(attributes.Manufacturer, attrs.Manufacturer, 64);
201fcf3ce44SJohn Forte     memcpy(attributes.SerialNumber, attrs.SerialNumber, 64);
202fcf3ce44SJohn Forte     memcpy(attributes.Model, attrs.Model, 256);
203fcf3ce44SJohn Forte     memcpy(attributes.ModelDescription, attrs.ModelDescription, 256);
204fcf3ce44SJohn Forte     memcpy(attributes.NodeSymbolicName, attrs.NodeSymbolicName, 256);
205fcf3ce44SJohn Forte     memcpy(attributes.HardwareVersion, attrs.HardwareVersion, 256);
206fcf3ce44SJohn Forte     memcpy(attributes.DriverVersion, attrs.DriverVersion, 256);
207fcf3ce44SJohn Forte     memcpy(attributes.OptionROMVersion, attrs.OptionROMVersion, 256);
208fcf3ce44SJohn Forte     memcpy(attributes.FirmwareVersion, attrs.FirmwareVersion, 256);
209fcf3ce44SJohn Forte     memcpy(attributes.DriverName, attrs.DriverName, 256);
210fcf3ce44SJohn Forte     memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
211fcf3ce44SJohn Forte 
212fcf3ce44SJohn Forte     return (attributes);
213fcf3ce44SJohn Forte }
214fcf3ce44SJohn Forte 
doForceLip()215a7949318SReed int FCHBA::doForceLip() {
216a7949318SReed     Trace	 log("FCHBA::doForceLip");
217a7949318SReed     int		 fd;
218a7949318SReed     fcio_t	 fcio;
219a7949318SReed     uint64_t	 wwn  = 0;
220a7949318SReed     HBAPort	*port = getPortByIndex(0);
221a7949318SReed 
222a7949318SReed     errno = 0;
223a7949318SReed     if ((fd = open(port->getPath().c_str(), O_RDONLY | O_EXCL)) == -1) {
224a7949318SReed 	if (errno == EBUSY) {
225a7949318SReed 	    throw BusyException();
226a7949318SReed 	} else if (errno == EAGAIN) {
227a7949318SReed 	    throw TryAgainException();
228a7949318SReed 	} else if (errno == ENOTSUP) {
229a7949318SReed 	    throw NotSupportedException();
230a7949318SReed 	} else {
231a7949318SReed 	    throw IOError(port);
232a7949318SReed 	}
233a7949318SReed     }
234a7949318SReed 
235a7949318SReed     memset(&fcio, 0, sizeof (fcio));
236a7949318SReed     fcio.fcio_cmd = FCIO_RESET_LINK;
237a7949318SReed     fcio.fcio_xfer = FCIO_XFER_WRITE;
238a7949318SReed     fcio.fcio_ilen = sizeof (wwn);
239a7949318SReed     fcio.fcio_ibuf = (caddr_t)&wwn;
240a7949318SReed 
241a7949318SReed     errno = 0;
242a7949318SReed     if (ioctl(fd, FCIO_CMD, &fcio) != 0) {
243a7949318SReed 	close(fd);
244a7949318SReed 
245a7949318SReed 	if (errno == EBUSY) {
246a7949318SReed 	    throw BusyException();
247a7949318SReed 	} else if (errno == EAGAIN) {
248a7949318SReed 	    throw TryAgainException();
249a7949318SReed 	} else if (errno == ENOTSUP) {
250a7949318SReed 	    throw NotSupportedException();
251a7949318SReed 	} else {
252a7949318SReed 	    throw IOError("Unable to reinitialize the link");
253a7949318SReed 	}
254a7949318SReed     } else {
255a7949318SReed         close(fd);
256a7949318SReed 	return (fcio.fcio_errno);
257a7949318SReed     }
258a7949318SReed }
259a7949318SReed 
npivGetHBAAttributes()260fcf3ce44SJohn Forte HBA_ADAPTERATTRIBUTES FCHBA::npivGetHBAAttributes() {
261fcf3ce44SJohn Forte 	Trace log("FCHBA::npivGetHBAAttributes");
262fcf3ce44SJohn Forte 	int fd;
263fcf3ce44SJohn Forte 
264fcf3ce44SJohn Forte 	errno = 0;
265fcf3ce44SJohn Forte 	HBAPort *port = getPortByIndex(0);
266fcf3ce44SJohn Forte 	if ((fd = open(port->getPath().c_str(), O_NDELAY | O_RDONLY)) == -1) {
267fcf3ce44SJohn Forte 		// Why did we fail?
268fcf3ce44SJohn Forte 		if (errno == EBUSY) {
269fcf3ce44SJohn Forte 			throw BusyException();
270fcf3ce44SJohn Forte 		} else if (errno == EAGAIN) {
271fcf3ce44SJohn Forte 			throw TryAgainException();
272fcf3ce44SJohn Forte 		} else if (errno == ENOTSUP) {
273fcf3ce44SJohn Forte 			throw NotSupportedException();
274fcf3ce44SJohn Forte 		} else {
275fcf3ce44SJohn Forte 			throw IOError(port);
276fcf3ce44SJohn Forte 		}
277fcf3ce44SJohn Forte 	}
278fcf3ce44SJohn Forte 
279fcf3ce44SJohn Forte 	HBA_ADAPTERATTRIBUTES attributes;
280fcf3ce44SJohn Forte 	fcio_t fcio;
281fcf3ce44SJohn Forte 	fc_hba_adapter_attributes_t attrs;
282fcf3ce44SJohn Forte 
283fcf3ce44SJohn Forte 	memset(&fcio, 0, sizeof (fcio));
284fcf3ce44SJohn Forte 	fcio.fcio_cmd = FCIO_NPIV_GET_ADAPTER_ATTRIBUTES;
285fcf3ce44SJohn Forte 	fcio.fcio_olen = sizeof (attrs);
286fcf3ce44SJohn Forte 	fcio.fcio_xfer = FCIO_XFER_READ;
287fcf3ce44SJohn Forte 	fcio.fcio_obuf = (caddr_t)&attrs;
288fcf3ce44SJohn Forte 	errno = 0;
289fcf3ce44SJohn Forte 
290fcf3ce44SJohn Forte 	if (ioctl(fd, FCIO_CMD, &fcio) != 0) {
291fcf3ce44SJohn Forte 		close(fd);
292fcf3ce44SJohn Forte 		if (errno == EBUSY) {
293fcf3ce44SJohn Forte 			throw BusyException();
294fcf3ce44SJohn Forte 		} else if (errno == EAGAIN) {
295fcf3ce44SJohn Forte 			throw TryAgainException();
296fcf3ce44SJohn Forte 		} else if (errno == ENOTSUP) {
297fcf3ce44SJohn Forte 			throw NotSupportedException();
298fcf3ce44SJohn Forte 		} else {
299fcf3ce44SJohn Forte 			throw IOError("Unable to fetch adapter attributes");
300fcf3ce44SJohn Forte 		}
301fcf3ce44SJohn Forte 	}
302fcf3ce44SJohn Forte 	close(fd);
303fcf3ce44SJohn Forte 
304fcf3ce44SJohn Forte 	/* Now copy over the payload */
305fcf3ce44SJohn Forte 	attributes.NumberOfPorts = attrs.NumberOfPorts;
306fcf3ce44SJohn Forte 	attributes.VendorSpecificID = attrs.VendorSpecificID;
307fcf3ce44SJohn Forte 	memcpy(attributes.Manufacturer, attrs.Manufacturer, 64);
308fcf3ce44SJohn Forte 	memcpy(attributes.SerialNumber, attrs.SerialNumber, 64);
309fcf3ce44SJohn Forte 	memcpy(attributes.Model, attrs.Model, 256);
310fcf3ce44SJohn Forte 	memcpy(attributes.ModelDescription, attrs.ModelDescription, 256);
311fcf3ce44SJohn Forte 	memcpy(attributes.NodeSymbolicName, attrs.NodeSymbolicName, 256);
312fcf3ce44SJohn Forte 	memcpy(attributes.HardwareVersion, attrs.HardwareVersion, 256);
313fcf3ce44SJohn Forte 	memcpy(attributes.DriverVersion, attrs.DriverVersion, 256);
314fcf3ce44SJohn Forte 	memcpy(attributes.OptionROMVersion, attrs.OptionROMVersion, 256);
315fcf3ce44SJohn Forte 	memcpy(attributes.FirmwareVersion, attrs.FirmwareVersion, 256);
316fcf3ce44SJohn Forte 	memcpy(attributes.DriverName, attrs.DriverName, 256);
317fcf3ce44SJohn Forte 	memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
318fcf3ce44SJohn Forte 
319fcf3ce44SJohn Forte 	return (attributes);
320fcf3ce44SJohn Forte }
321fcf3ce44SJohn Forte 
loadAdapters(vector<HBA * > & list)322fcf3ce44SJohn Forte void FCHBA::loadAdapters(vector<HBA*> &list) {
323fcf3ce44SJohn Forte     Trace log("FCHBA::loadAdapters");
324fcf3ce44SJohn Forte     fcio_t			fcio;
325fcf3ce44SJohn Forte     fc_hba_list_t		*pathList;
326fcf3ce44SJohn Forte     int			fd;
327fcf3ce44SJohn Forte     int			size = 64; // default first attempt
328fcf3ce44SJohn Forte     bool		retry = false;
329fcf3ce44SJohn Forte     struct stat		sb;
330fcf3ce44SJohn Forte     int bufSize;
331fcf3ce44SJohn Forte 
332fcf3ce44SJohn Forte     /* Before we do anything, let's see if FCSM is on the system */
333fcf3ce44SJohn Forte     errno = 0;
334fcf3ce44SJohn Forte     if (stat(FCSM_DRIVER_PATH.c_str(), &sb) != 0) {
335fcf3ce44SJohn Forte 	if (errno == ENOENT) {
336fcf3ce44SJohn Forte 	    log.genericIOError(
337fcf3ce44SJohn Forte 		"The %s driver is not present. Unable to issue "
338fcf3ce44SJohn Forte 		"CT commands. Please install the %s package.",
339fcf3ce44SJohn Forte 		FCSM_DRIVER_PATH.c_str(), FCSM_DRIVER_PKG.c_str());
340fcf3ce44SJohn Forte 	    throw NotSupportedException();
341fcf3ce44SJohn Forte 	} else {
342fcf3ce44SJohn Forte 	    log.genericIOError(
343fcf3ce44SJohn Forte 		"Can not stat the %s driver for reason \"%s\" "
344fcf3ce44SJohn Forte 		"Unable to issue CT commands.",
345fcf3ce44SJohn Forte 		FCSM_DRIVER_PATH.c_str(), strerror(errno));
346fcf3ce44SJohn Forte 	    throw IOError("Unable to stat FCSM driver");
347fcf3ce44SJohn Forte 	}
348fcf3ce44SJohn Forte     }
349fcf3ce44SJohn Forte 
350fcf3ce44SJohn Forte 
351fcf3ce44SJohn Forte     /* construct fcio struct */
352fcf3ce44SJohn Forte     memset(&fcio, 0, sizeof (fcio_t));
353fcf3ce44SJohn Forte     fcio.fcio_cmd	= FCSMIO_ADAPTER_LIST;
354fcf3ce44SJohn Forte     fcio.fcio_xfer	= FCIO_XFER_RW;
355fcf3ce44SJohn Forte 
356fcf3ce44SJohn Forte 
357fcf3ce44SJohn Forte     /* open the fcsm node so we can send the ioctl to */
358fcf3ce44SJohn Forte     errno = 0;
359fcf3ce44SJohn Forte     if ((fd = open(FCSM_DRIVER_PATH.c_str(), O_RDONLY)) < 0) {
360fcf3ce44SJohn Forte 	if (errno == EBUSY) {
361fcf3ce44SJohn Forte 	    throw BusyException();
362fcf3ce44SJohn Forte 	} else if (errno == EAGAIN) {
363fcf3ce44SJohn Forte 	    throw TryAgainException();
364fcf3ce44SJohn Forte 	} else if (errno == ENOTSUP) {
365fcf3ce44SJohn Forte 	    throw NotSupportedException();
366fcf3ce44SJohn Forte 	} else if (errno == ENOENT) {
367fcf3ce44SJohn Forte 	    throw UnavailableException();
368fcf3ce44SJohn Forte 	} else {
369fcf3ce44SJohn Forte 	    throw IOError("Unable to open FCSM driver");
370fcf3ce44SJohn Forte 	}
371fcf3ce44SJohn Forte     }
372fcf3ce44SJohn Forte 
373fcf3ce44SJohn Forte     do {
374fcf3ce44SJohn Forte 	retry = false;
375fcf3ce44SJohn Forte 	errno = 0;
376fcf3ce44SJohn Forte 	bufSize = MAXPATHLEN * size + (int) sizeof (fc_hba_list_t) - 1;
377fcf3ce44SJohn Forte 	pathList = (fc_hba_list_t *)new uchar_t[bufSize];
378fcf3ce44SJohn Forte 	pathList->numAdapters = size;
379fcf3ce44SJohn Forte 	fcio.fcio_olen	= bufSize;
380fcf3ce44SJohn Forte 	fcio.fcio_obuf	= (char *)pathList;
381fcf3ce44SJohn Forte 	if (ioctl(fd, FCSMIO_CMD, &fcio) != 0) {
382fcf3ce44SJohn Forte 	    /* Interpret the fcio error code */
383fcf3ce44SJohn Forte 	    char fcioErrorString[MAX_FCIO_MSG_LEN] = "";
384fcf3ce44SJohn Forte 
385fcf3ce44SJohn Forte 	    log.genericIOError(
386fcf3ce44SJohn Forte 		"ADAPTER_LIST failed: "
387fcf3ce44SJohn Forte 		"Errno: \"%s\"",
388fcf3ce44SJohn Forte 		strerror(errno));
389*b3385a70SToomas Soome 	    delete[] (pathList);
390fcf3ce44SJohn Forte 	    close(fd);
391fcf3ce44SJohn Forte 	    if (errno == EBUSY) {
392fcf3ce44SJohn Forte 		throw BusyException();
393fcf3ce44SJohn Forte 	    } else if (errno == EAGAIN) {
394fcf3ce44SJohn Forte 		throw TryAgainException();
395fcf3ce44SJohn Forte 	    } else if (errno == ENOTSUP) {
396fcf3ce44SJohn Forte 		throw NotSupportedException();
397fcf3ce44SJohn Forte 	    } else if (errno == ENOENT) {
398fcf3ce44SJohn Forte 		throw UnavailableException();
399fcf3ce44SJohn Forte 	    } else {
400fcf3ce44SJohn Forte 		throw IOError("Unable to build HBA list");
401fcf3ce44SJohn Forte 	    }
402fcf3ce44SJohn Forte 	}
403fcf3ce44SJohn Forte 	if (pathList->numAdapters > size) {
404fcf3ce44SJohn Forte 	    log.debug(
405fcf3ce44SJohn Forte 		"Buffer too small for number of HBAs. Retrying.");
406fcf3ce44SJohn Forte 	    size = pathList->numAdapters;
407fcf3ce44SJohn Forte 	    retry = true;
408*b3385a70SToomas Soome 	    delete[] (pathList);
409fcf3ce44SJohn Forte 	}
410fcf3ce44SJohn Forte     } while (retry);
411fcf3ce44SJohn Forte 
412fcf3ce44SJohn Forte     close(fd);
413fcf3ce44SJohn Forte     log.debug("Detected %d adapters", pathList->numAdapters);
4141770502eSYu Renia Miao     for (int i = 0, times =0; i < pathList->numAdapters;) {
415fcf3ce44SJohn Forte 	try {
416fcf3ce44SJohn Forte 	    HBA *hba = new FCHBA(pathList->hbaPaths[i]);
417fcf3ce44SJohn Forte 	    list.insert(list.begin(), hba);
4181770502eSYu Renia Miao 	    i++;
4191770502eSYu Renia Miao 	} catch (BusyException &e) {
4201770502eSYu Renia Miao             sleep(1);
4211770502eSYu Renia Miao             if (times++ > EXCPT_RETRY_COUNT) {
422*b3385a70SToomas Soome                 i++;
4231770502eSYu Renia Miao                 times = 0;
4241770502eSYu Renia Miao             }
4251770502eSYu Renia Miao 	    continue;
4261770502eSYu Renia Miao 	} catch (TryAgainException &e) {
4271770502eSYu Renia Miao 	    sleep(1);
4281770502eSYu Renia Miao 	    if (times++ > EXCPT_RETRY_COUNT) {
429*b3385a70SToomas Soome 		i++;
4301770502eSYu Renia Miao 		times = 0;
431*b3385a70SToomas Soome 	    }
4321770502eSYu Renia Miao 	    continue;
4331770502eSYu Renia Miao 	} catch (UnavailableException &e) {
4341770502eSYu Renia Miao 	    sleep(1);
4351770502eSYu Renia Miao 	    if (times++ > EXCPT_RETRY_COUNT) {
436*b3385a70SToomas Soome 		i++;
4371770502eSYu Renia Miao 		times = 0;
438*b3385a70SToomas Soome 	    }
4391770502eSYu Renia Miao 	    continue;
4401770502eSYu Renia Miao 	} catch (HBAException &e) {
4411770502eSYu Renia Miao 	    i++;
4421770502eSYu Renia Miao 	    times = 0;
443fcf3ce44SJohn Forte 	    log.debug(
444fcf3ce44SJohn Forte 		"Ignoring partial failure while loading an HBA");
445fcf3ce44SJohn Forte 	}
446fcf3ce44SJohn Forte     }
447fcf3ce44SJohn Forte     if (pathList->numAdapters > HBAList::HBA_MAX_PER_LIST) {
448*b3385a70SToomas Soome 	delete[](pathList);
449fcf3ce44SJohn Forte 	throw InternalError(
4500778188fSHengqing Hu 	    "Exceeds max number of adapters that VSL supports.");
451fcf3ce44SJohn Forte     }
452*b3385a70SToomas Soome     delete[] (pathList);
453fcf3ce44SJohn Forte }
454