4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
30 #include <Exceptions.h>
36 #include <sys/types.h>
41 #include <sys/fibre-channel/fcio.h>
42 #include <sys/fibre-channel/ulp/fcsm.h>
43 #include <FCHBAPort.h>
46 #define EXCPT_RETRY_COUNT 10
49 const string
FCHBA::FCSM_DRIVER_PATH
= "/devices/pseudo/fcsm@0:fcsm";
50 const string
FCHBA::FCSM_DRIVER_PKG
= "SUNWfcsm";
51 const int FCHBA::MAX_FCIO_MSG_LEN
= 256;
53 FCHBA::FCHBA(string path
) : HBA() {
54 Trace
log("FCHBA::FCHBA");
55 log
.debug("Constructing new HBA (%s)", path
.c_str());
58 addPort(new FCHBAPort(path
));
60 name
= "INTERNAL-FAILURE"; // Just in case things go wrong
62 HBA_ADAPTERATTRIBUTES attrs
= getHBAAttributes();
63 name
= attrs
.Manufacturer
;
67 // Grab any other ports on this adapter
68 for (int i
= 1; i
< attrs
.NumberOfPorts
; i
++) {
71 char nextPath
[MAXPATHLEN
];
73 log
.debug("Fetching other port %d", i
);
75 // construct fcio struct
76 memset(&fcio
, 0, sizeof (fcio_t
));
77 memset(nextPath
, 0, sizeof (nextPath
));
78 fcio
.fcio_cmd
= FCIO_GET_OTHER_ADAPTER_PORTS
;
79 fcio
.fcio_xfer
= FCIO_XFER_RW
;
81 fcio
.fcio_olen
= MAXPATHLEN
;
82 fcio
.fcio_obuf
= (char *)nextPath
;
83 fcio
.fcio_ilen
= sizeof (i
);
84 fcio
.fcio_ibuf
= (char *)&i
;
86 // open the fcsm node so we can send the ioctl to
88 HBAPort
*port
= getPortByIndex(0);
89 if ((fd
= open(port
->getPath().c_str(), O_NDELAY
| O_RDONLY
)) ==
91 log
.debug("Unable to open %d opened (%s)", i
,
92 port
->getPath().c_str());
94 throw BusyException();
95 } else if (errno
== EAGAIN
) {
96 throw TryAgainException();
97 } else if (errno
== ENOTSUP
) {
98 throw NotSupportedException();
99 } else if (errno
== ENOENT
) {
100 throw UnavailableException();
102 throw IOError("Unable to open FCSM driver");
105 log
.debug("Other port %d opened", i
);
108 if (ioctl(fd
, FCIO_CMD
, &fcio
) != 0) {
109 // Interpret the fcio error code
110 char fcioErrorString
[MAX_FCIO_MSG_LEN
] = "";
113 "ADAPTER_LIST failed: "
117 if (errno
== EBUSY
) {
118 throw BusyException();
119 } else if (errno
== EAGAIN
) {
120 throw TryAgainException();
121 } else if (errno
== ENOTSUP
) {
122 throw NotSupportedException();
123 } else if (errno
== ENOENT
) {
124 throw UnavailableException();
126 throw IOError("Unable to build HBA list");
130 log
.debug("About to add port %d (%s)", i
, nextPath
);
131 addPort(new FCHBAPort(nextPath
));
133 } catch (BusyException
&e
) {
135 } catch (TryAgainException
&e
) {
137 } catch (UnavailableException
&e
) {
139 } catch (HBAException
&e
) {
141 "Unable to construct HBA.");
146 std::string
FCHBA::getName() {
147 Trace
log("FCHBA::getName");
151 HBA_ADAPTERATTRIBUTES
FCHBA::getHBAAttributes() {
152 Trace
log("FCHBA::getHBAAttributes");
156 HBAPort
*port
= getPortByIndex(0);
157 if ((fd
= open(port
->getPath().c_str(), O_NDELAY
| O_RDONLY
)) == -1) {
159 if (errno
== EBUSY
) {
160 throw BusyException();
161 } else if (errno
== EAGAIN
) {
162 throw TryAgainException();
163 } else if (errno
== ENOTSUP
) {
164 throw NotSupportedException();
170 HBA_ADAPTERATTRIBUTES attributes
;
172 fc_hba_adapter_attributes_t attrs
;
174 memset(&fcio
, 0, sizeof (fcio
));
176 fcio
.fcio_cmd
= FCIO_GET_ADAPTER_ATTRIBUTES
;
177 fcio
.fcio_olen
= sizeof (attrs
);
178 fcio
.fcio_xfer
= FCIO_XFER_READ
;
179 fcio
.fcio_obuf
= (caddr_t
)&attrs
;
183 if (ioctl(fd
, FCIO_CMD
, &fcio
) != 0) {
185 if (errno
== EBUSY
) {
186 throw BusyException();
187 } else if (errno
== EAGAIN
) {
188 throw TryAgainException();
189 } else if (errno
== ENOTSUP
) {
190 throw NotSupportedException();
192 throw IOError("Unable to fetch adapter attributes");
197 /* Now copy over the payload */
198 attributes
.NumberOfPorts
= attrs
.NumberOfPorts
;
199 attributes
.VendorSpecificID
= attrs
.VendorSpecificID
;
200 memcpy(attributes
.Manufacturer
, attrs
.Manufacturer
, 64);
201 memcpy(attributes
.SerialNumber
, attrs
.SerialNumber
, 64);
202 memcpy(attributes
.Model
, attrs
.Model
, 256);
203 memcpy(attributes
.ModelDescription
, attrs
.ModelDescription
, 256);
204 memcpy(attributes
.NodeSymbolicName
, attrs
.NodeSymbolicName
, 256);
205 memcpy(attributes
.HardwareVersion
, attrs
.HardwareVersion
, 256);
206 memcpy(attributes
.DriverVersion
, attrs
.DriverVersion
, 256);
207 memcpy(attributes
.OptionROMVersion
, attrs
.OptionROMVersion
, 256);
208 memcpy(attributes
.FirmwareVersion
, attrs
.FirmwareVersion
, 256);
209 memcpy(attributes
.DriverName
, attrs
.DriverName
, 256);
210 memcpy(&attributes
.NodeWWN
, &attrs
.NodeWWN
, 8);
215 int FCHBA::doForceLip() {
216 Trace
log("FCHBA::doForceLip");
220 HBAPort
*port
= getPortByIndex(0);
223 if ((fd
= open(port
->getPath().c_str(), O_RDONLY
| O_EXCL
)) == -1) {
224 if (errno
== EBUSY
) {
225 throw BusyException();
226 } else if (errno
== EAGAIN
) {
227 throw TryAgainException();
228 } else if (errno
== ENOTSUP
) {
229 throw NotSupportedException();
235 memset(&fcio
, 0, sizeof (fcio
));
236 fcio
.fcio_cmd
= FCIO_RESET_LINK
;
237 fcio
.fcio_xfer
= FCIO_XFER_WRITE
;
238 fcio
.fcio_ilen
= sizeof (wwn
);
239 fcio
.fcio_ibuf
= (caddr_t
)&wwn
;
242 if (ioctl(fd
, FCIO_CMD
, &fcio
) != 0) {
245 if (errno
== EBUSY
) {
246 throw BusyException();
247 } else if (errno
== EAGAIN
) {
248 throw TryAgainException();
249 } else if (errno
== ENOTSUP
) {
250 throw NotSupportedException();
252 throw IOError("Unable to reinitialize the link");
256 return (fcio
.fcio_errno
);
260 HBA_ADAPTERATTRIBUTES
FCHBA::npivGetHBAAttributes() {
261 Trace
log("FCHBA::npivGetHBAAttributes");
265 HBAPort
*port
= getPortByIndex(0);
266 if ((fd
= open(port
->getPath().c_str(), O_NDELAY
| O_RDONLY
)) == -1) {
268 if (errno
== EBUSY
) {
269 throw BusyException();
270 } else if (errno
== EAGAIN
) {
271 throw TryAgainException();
272 } else if (errno
== ENOTSUP
) {
273 throw NotSupportedException();
279 HBA_ADAPTERATTRIBUTES attributes
;
281 fc_hba_adapter_attributes_t attrs
;
283 memset(&fcio
, 0, sizeof (fcio
));
284 fcio
.fcio_cmd
= FCIO_NPIV_GET_ADAPTER_ATTRIBUTES
;
285 fcio
.fcio_olen
= sizeof (attrs
);
286 fcio
.fcio_xfer
= FCIO_XFER_READ
;
287 fcio
.fcio_obuf
= (caddr_t
)&attrs
;
290 if (ioctl(fd
, FCIO_CMD
, &fcio
) != 0) {
292 if (errno
== EBUSY
) {
293 throw BusyException();
294 } else if (errno
== EAGAIN
) {
295 throw TryAgainException();
296 } else if (errno
== ENOTSUP
) {
297 throw NotSupportedException();
299 throw IOError("Unable to fetch adapter attributes");
304 /* Now copy over the payload */
305 attributes
.NumberOfPorts
= attrs
.NumberOfPorts
;
306 attributes
.VendorSpecificID
= attrs
.VendorSpecificID
;
307 memcpy(attributes
.Manufacturer
, attrs
.Manufacturer
, 64);
308 memcpy(attributes
.SerialNumber
, attrs
.SerialNumber
, 64);
309 memcpy(attributes
.Model
, attrs
.Model
, 256);
310 memcpy(attributes
.ModelDescription
, attrs
.ModelDescription
, 256);
311 memcpy(attributes
.NodeSymbolicName
, attrs
.NodeSymbolicName
, 256);
312 memcpy(attributes
.HardwareVersion
, attrs
.HardwareVersion
, 256);
313 memcpy(attributes
.DriverVersion
, attrs
.DriverVersion
, 256);
314 memcpy(attributes
.OptionROMVersion
, attrs
.OptionROMVersion
, 256);
315 memcpy(attributes
.FirmwareVersion
, attrs
.FirmwareVersion
, 256);
316 memcpy(attributes
.DriverName
, attrs
.DriverName
, 256);
317 memcpy(&attributes
.NodeWWN
, &attrs
.NodeWWN
, 8);
322 void FCHBA::loadAdapters(vector
<HBA
*> &list
) {
323 Trace
log("FCHBA::loadAdapters");
325 fc_hba_list_t
*pathList
;
327 int size
= 64; // default first attempt
332 /* Before we do anything, let's see if FCSM is on the system */
334 if (stat(FCSM_DRIVER_PATH
.c_str(), &sb
) != 0) {
335 if (errno
== ENOENT
) {
337 "The %s driver is not present. Unable to issue "
338 "CT commands. Please install the %s package.",
339 FCSM_DRIVER_PATH
.c_str(), FCSM_DRIVER_PKG
.c_str());
340 throw NotSupportedException();
343 "Can not stat the %s driver for reason \"%s\" "
344 "Unable to issue CT commands.",
345 FCSM_DRIVER_PATH
.c_str(), strerror(errno
));
346 throw IOError("Unable to stat FCSM driver");
351 /* construct fcio struct */
352 memset(&fcio
, 0, sizeof (fcio_t
));
353 fcio
.fcio_cmd
= FCSMIO_ADAPTER_LIST
;
354 fcio
.fcio_xfer
= FCIO_XFER_RW
;
357 /* open the fcsm node so we can send the ioctl to */
359 if ((fd
= open(FCSM_DRIVER_PATH
.c_str(), O_RDONLY
)) < 0) {
360 if (errno
== EBUSY
) {
361 throw BusyException();
362 } else if (errno
== EAGAIN
) {
363 throw TryAgainException();
364 } else if (errno
== ENOTSUP
) {
365 throw NotSupportedException();
366 } else if (errno
== ENOENT
) {
367 throw UnavailableException();
369 throw IOError("Unable to open FCSM driver");
376 bufSize
= MAXPATHLEN
* size
+ (int) sizeof (fc_hba_list_t
) - 1;
377 pathList
= (fc_hba_list_t
*)new uchar_t
[bufSize
];
378 pathList
->numAdapters
= size
;
379 fcio
.fcio_olen
= bufSize
;
380 fcio
.fcio_obuf
= (char *)pathList
;
381 if (ioctl(fd
, FCSMIO_CMD
, &fcio
) != 0) {
382 /* Interpret the fcio error code */
383 char fcioErrorString
[MAX_FCIO_MSG_LEN
] = "";
386 "ADAPTER_LIST failed: "
391 if (errno
== EBUSY
) {
392 throw BusyException();
393 } else if (errno
== EAGAIN
) {
394 throw TryAgainException();
395 } else if (errno
== ENOTSUP
) {
396 throw NotSupportedException();
397 } else if (errno
== ENOENT
) {
398 throw UnavailableException();
400 throw IOError("Unable to build HBA list");
403 if (pathList
->numAdapters
> size
) {
405 "Buffer too small for number of HBAs. Retrying.");
406 size
= pathList
->numAdapters
;
413 log
.debug("Detected %d adapters", pathList
->numAdapters
);
414 for (int i
= 0, times
=0; i
< pathList
->numAdapters
;) {
416 HBA
*hba
= new FCHBA(pathList
->hbaPaths
[i
]);
417 list
.insert(list
.begin(), hba
);
419 } catch (BusyException
&e
) {
421 if (times
++ > EXCPT_RETRY_COUNT
) {
426 } catch (TryAgainException
&e
) {
428 if (times
++ > EXCPT_RETRY_COUNT
) {
433 } catch (UnavailableException
&e
) {
435 if (times
++ > EXCPT_RETRY_COUNT
) {
440 } catch (HBAException
&e
) {
444 "Ignoring partial failure while loading an HBA");
447 if (pathList
->numAdapters
> HBAList::HBA_MAX_PER_LIST
) {
450 "Exceeds max number of adapters that VSL supports.");