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/fctio.h>
42 #include <sys/fibre-channel/impl/fc_error.h>
43 #include <TgtFCHBAPort.h>
49 const string
TgtFCHBA::FCT_DRIVER_PATH
= "/devices/pseudo/fct@0:admin";
50 const string
TgtFCHBA::FCT_ADAPTER_NAME_PREFIX
= "/devices/pseudo/fct@0";
51 const string
TgtFCHBA::FCT_DRIVER_PKG
= "SUNWfct";
52 const int TgtFCHBA::MAX_FCTIO_MSG_LEN
= 256;
54 TgtFCHBA::TgtFCHBA(string path
) : HBA()
56 Trace
log("TgtFCHBA::TgtFCHBA");
57 log
.debug("Constructing new Target mode HBA (%s)", path
.c_str());
59 // Add a target FCHBA port. With fct driver architecuture, all target mode
60 // FCHBA will have a single port regardless of the multiport support on
62 addPort(new TgtFCHBAPort(path
));
63 name
= "INTERNAL-FAILURE"; // Just in case things go wrong
65 HBA_ADAPTERATTRIBUTES attrs
= getHBAAttributes();
66 name
= attrs
.Manufacturer
;
71 } catch (HBAException
&e
) {
73 "Failed to get HBA attribute for %s", path
.c_str());
78 std::string
TgtFCHBA::getName()
80 Trace
log("TgtFCHBA::getName");
84 HBA_ADAPTERATTRIBUTES
TgtFCHBA::getHBAAttributes()
86 Trace
log("TgtFCHBA::getHBAAttributes");
90 HBAPort
*port
= getPortByIndex(0);
92 HBA_ADAPTERATTRIBUTES attributes
;
94 fc_tgt_hba_adapter_attributes_t attrs
;
97 if ((fd
= open(FCT_DRIVER_PATH
.c_str(), O_NDELAY
| O_RDONLY
)) == -1) {
100 throw BusyException();
101 } else if (errno
== EAGAIN
) {
102 throw TryAgainException();
103 } else if (errno
== ENOTSUP
) {
104 throw NotSupportedException();
111 std::string path
= port
->getPath();
112 string::size_type offset
= path
.find_last_of(".");
114 string portwwnString
= path
.substr(offset
+1);
115 portwwn
= strtoull(portwwnString
.c_str(), NULL
, 16);
118 throw BadArgumentException();
121 uint64_t en_wwn
= htonll(portwwn
);
123 memset(&fctio
, 0, sizeof (fctio
));
124 fctio
.fctio_cmd
= FCTIO_GET_ADAPTER_ATTRIBUTES
;
125 fctio
.fctio_olen
= (uint32_t)(sizeof (attrs
));
126 fctio
.fctio_xfer
= FCTIO_XFER_READ
;
127 fctio
.fctio_obuf
= (uint64_t)(uintptr_t)&attrs
;
128 fctio
.fctio_ilen
= 8;
129 fctio
.fctio_ibuf
= (uint64_t)(uintptr_t)&en_wwn
;
132 if (ioctl(fd
, FCTIO_CMD
, &fctio
) != 0) {
134 if (errno
== EBUSY
) {
135 throw BusyException();
136 } else if (errno
== EAGAIN
) {
137 throw TryAgainException();
138 } else if (errno
== ENOTSUP
) {
139 throw NotSupportedException();
141 throw IOError("Unable to fetch adapter attributes");
146 /* Now copy over the payload */
147 attributes
.NumberOfPorts
= attrs
.NumberOfPorts
;
148 attributes
.VendorSpecificID
= attrs
.VendorSpecificID
;
149 memcpy(attributes
.Manufacturer
, attrs
.Manufacturer
, 64);
150 memcpy(attributes
.SerialNumber
, attrs
.SerialNumber
, 64);
151 memcpy(attributes
.Model
, attrs
.Model
, 256);
152 memcpy(attributes
.ModelDescription
, attrs
.ModelDescription
, 256);
153 memcpy(attributes
.NodeSymbolicName
, attrs
.NodeSymbolicName
, 256);
154 memcpy(attributes
.HardwareVersion
, attrs
.HardwareVersion
, 256);
155 memcpy(attributes
.DriverVersion
, attrs
.DriverVersion
, 256);
156 memcpy(attributes
.OptionROMVersion
, attrs
.OptionROMVersion
, 256);
157 memcpy(attributes
.FirmwareVersion
, attrs
.FirmwareVersion
, 256);
158 memcpy(attributes
.DriverName
, attrs
.DriverName
, 256);
159 memcpy(&attributes
.NodeWWN
, &attrs
.NodeWWN
, 8);
164 int TgtFCHBA::doForceLip()
166 Trace
log("TgtFCHBA::doForceLip");
168 HBAPort
*port
= getPortByIndex(0);
173 if ((fd
= open(FCT_DRIVER_PATH
.c_str(), O_NDELAY
| O_RDONLY
)) == -1) {
174 if (errno
== EBUSY
) {
175 throw BusyException();
176 } else if (errno
== EAGAIN
) {
177 throw TryAgainException();
178 } else if (errno
== ENOTSUP
) {
179 throw NotSupportedException();
186 std::string path
= port
->getPath();
187 string::size_type offset
= path
.find_last_of(".");
189 string portwwnString
= path
.substr(offset
+1);
190 portwwn
= strtoull(portwwnString
.c_str(), NULL
, 16);
193 throw BadArgumentException();
196 uint64_t en_wwn
= htonll(portwwn
);
197 memset(&fctio
, 0, sizeof (fctio
));
198 fctio
.fctio_cmd
= FCTIO_FORCE_LIP
;
199 fctio
.fctio_xfer
= FCTIO_XFER_READ
;
200 fctio
.fctio_ilen
= 8;
201 fctio
.fctio_ibuf
= (uint64_t)(uintptr_t)&en_wwn
;
204 if (ioctl(fd
, FCTIO_CMD
, &fctio
) != 0) {
206 if (errno
== EBUSY
) {
207 throw BusyException();
208 } else if (errno
== EAGAIN
) {
209 throw TryAgainException();
210 } else if (errno
== ENOTSUP
) {
211 throw NotSupportedException();
213 throw IOError("Unable to reinitialize the link");
217 return ((int)fctio
.fctio_errno
);
221 void TgtFCHBA::loadAdapters(vector
<HBA
*> &list
)
223 Trace
log("TgtFCHBA::loadAdapters");
225 fc_tgt_hba_list_t
*tgthbaList
;
227 int size
= 64; // default first attempt
233 /* Before we do anything, let's see if FCT is on the system */
235 if (stat(FCT_DRIVER_PATH
.c_str(), &sb
) != 0) {
236 if (errno
== ENOENT
) {
238 "The %s driver is not present."
239 " Please install the %s package.",
240 FCT_DRIVER_PATH
.c_str(), FCT_DRIVER_PKG
.c_str());
241 throw NotSupportedException();
244 "Can not stat the %s driver for reason \"%s\" "
245 "Unable to get target mode FC adapters.",
246 FCT_DRIVER_PATH
.c_str(), strerror(errno
));
247 throw IOError("Unable to stat FCSM driver");
252 /* construct fcio struct */
253 memset(&fctio
, 0, sizeof (fctio_t
));
254 fctio
.fctio_cmd
= FCTIO_ADAPTER_LIST
;
255 fctio
.fctio_xfer
= FCTIO_XFER_RW
;
257 /* open the fcsm node so we can send the ioctl to */
259 if ((fd
= open(FCT_DRIVER_PATH
.c_str(), O_RDONLY
)) < 0) {
260 if (errno
== EBUSY
) {
261 throw BusyException();
262 } else if (errno
== EAGAIN
) {
263 throw TryAgainException();
264 } else if (errno
== ENOTSUP
) {
265 throw NotSupportedException();
266 } else if (errno
== ENOENT
) {
267 throw UnavailableException();
269 throw IOError("Unable to open FCT driver");
276 bufSize
= 8 * (size
- 1) + (int) sizeof (fc_tgt_hba_list_t
);
277 tgthbaList
= (fc_tgt_hba_list_t
*)new uchar_t
[bufSize
];
278 tgthbaList
->numPorts
= size
;
279 fctio
.fctio_olen
= bufSize
;
280 fctio
.fctio_obuf
= (uint64_t)(uintptr_t)tgthbaList
;
281 if (ioctl(fd
, FCTIO_CMD
, &fctio
) != 0) {
282 /* Interpret the fcio error code */
283 char fcioErrorString
[MAX_FCTIO_MSG_LEN
] = "";
286 "TGT_ADAPTER_LIST failed: "
291 if (errno
== EBUSY
) {
292 throw BusyException();
293 } else if (errno
== EAGAIN
) {
294 throw TryAgainException();
295 } else if (errno
== ENOTSUP
) {
296 throw NotSupportedException();
297 } else if (errno
== ENOENT
) {
298 throw UnavailableException();
300 throw IOError("Unable to build HBA list");
303 if (tgthbaList
->numPorts
> size
) {
305 "Buffer too small for number of target mode HBAs. Retrying.");
306 size
= tgthbaList
->numPorts
;
313 log
.debug("Detected %d target mode adapters", tgthbaList
->numPorts
);
314 for (int i
= 0; i
< tgthbaList
->numPorts
; i
++) {
316 std::string hbapath
= FCT_ADAPTER_NAME_PREFIX
.c_str();
318 // move the row with two dimentional uint8 array for WWN
319 uint64_t tmp
= ntohll(*((uint64_t *)&tgthbaList
->port_wwn
[i
][0]));
320 sprintf(wwnStr
, "%llx", tmp
);
323 HBA
*hba
= new TgtFCHBA(hbapath
);
324 list
.insert(list
.begin(), hba
);
327 "Ignoring partial failure while loading an HBA");
330 if (tgthbaList
->numPorts
> HBAList::HBA_MAX_PER_LIST
) {
333 "Exceeds max number of adapters that VSL supports.");