1 /*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26
27 #include "FCHBANPIVPort.h"
28 #include <Exceptions.h>
29 #include <Trace.h>
30 #include <sun_fc.h>
31 #include <iostream>
32 #include <iomanip>
33 #include <sys/types.h>
34 #include <sys/mkdev.h>
35 #include <sys/stat.h>
36 #include <fcntl.h>
37 #include <unistd.h>
38 #include <stropts.h>
39 #include <dirent.h>
40 #include <sys/fibre-channel/fc.h>
41 #include <sys/fibre-channel/fcio.h>
42 #include <sys/fibre-channel/ulp/fcp_util.h>
43 #include <sys/fibre-channel/ulp/fcsm.h>
44 #include <sys/fibre-channel/impl/fc_error.h>
45 #include <sys/fibre-channel/fc_appif.h>
46 #include <sys/scsi/generic/commands.h>
47 #include <sys/scsi/impl/commands.h>
48 #include <sys/scsi/impl/sense.h>
49 #include <sys/scsi/generic/inquiry.h>
50 #include <sys/scsi/generic/status.h>
51 #include <errno.h>
52
53 using namespace std;
54
55 const int FCHBANPIVPort::MAX_FCIO_MSG_LEN = 256;
56
FCHBANPIVPort(string thePath)57 FCHBANPIVPort::FCHBANPIVPort(string thePath) : HBANPIVPort() {
58 Trace log("FCHBANPIVPort::FCHBANPIVPort");
59 log.debug("Initializing HBA NPIV port %s", thePath.c_str());
60
61 try {
62 path = lookupControllerPath(thePath);
63 } catch (...) {
64 log.debug("Unable to lookup controller path and number for %s",
65 thePath.c_str());
66 path = "/devices";
67 path += thePath;
68 path += ":fc";
69 }
70
71 uint64_t tmp;
72 HBA_NPIVATTRIBUTES attrs = getPortAttributes(tmp);
73 memcpy(&tmp, &attrs.PortWWN, 8);
74 portWWN = ntohll(tmp);
75 memcpy(&tmp, &attrs.NodeWWN, 8);
76 nodeWWN = ntohll(tmp);
77 }
78
79
getPortAttributes(uint64_t & stateChange)80 HBA_NPIVATTRIBUTES FCHBANPIVPort::getPortAttributes(uint64_t &stateChange) {
81 Trace log("FCHBANPIVPort::getPortAttributes");
82
83 HBA_NPIVATTRIBUTES attributes;
84 fcio_t fcio;
85 fc_hba_npiv_attributes_t attrs;
86
87 memset(&fcio, 0, sizeof (fcio));
88 memset(&attributes, 0, sizeof (attributes));
89 fcio.fcio_cmd = FCIO_GET_NPIV_ATTRIBUTES;
90 fcio.fcio_olen = sizeof (attrs);
91 fcio.fcio_xfer = FCIO_XFER_READ;
92 fcio.fcio_obuf = (caddr_t)&attrs;
93 fp_ioctl(getPath(), FCIO_CMD, &fcio);
94
95 stateChange = attrs.lastChange;
96 memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
97 memcpy(&attributes.PortWWN, &attrs.PortWWN, 8);
98
99 return (attributes);
100 }
101
102
fp_ioctl(string path,int cmd,fcio_t * fcio)103 void FCHBANPIVPort::fp_ioctl(string path, int cmd, fcio_t *fcio) {
104 Trace log("FCHBANPIVPort::fp_ioctl");
105
106 char fcioErrorString[MAX_FCIO_MSG_LEN] = "";
107 int fd = HBA::_open(path, O_NDELAY | O_RDONLY);
108
109 try {
110 int times = 0;
111 HBA::_ioctl(fd, cmd, (uchar_t *)fcio);
112 while (fcio->fcio_errno == FC_STATEC_BUSY) {
113 (void) sleep(2);
114 HBA::_ioctl(fd, cmd, (uchar_t *)fcio);
115 if (times++ > 20) {
116 break;
117 }
118 }
119 close(fd);
120 if (fcio->fcio_errno) {
121 throw IOError("IOCTL transport failure");
122 }
123 } catch (...) {
124 close(fd);
125 transportError(fcio->fcio_errno, fcioErrorString);
126 log.genericIOError("NPIV Port ioctl (0x%x) failed. Transport: \"%s\"", cmd,
127 fcioErrorString);
128 switch (fcio->fcio_errno) {
129 case FC_BADWWN:
130 throw IllegalWWNException();
131 case FC_BADPORT:
132 throw IllegalWWNException();
133 case FC_OUTOFBOUNDS:
134 throw IllegalIndexException();
135 case FC_PBUSY:
136 case FC_FBUSY:
137 case FC_TRAN_BUSY:
138 case FC_STATEC_BUSY:
139 case FC_DEVICE_BUSY:
140 throw BusyException();
141 case FC_SUCCESS:
142 default:
143 throw;
144 }
145 }
146 }
147
148
149 /*
150 * Interpret the error code in the fcio_t structure
151 *
152 * message must be at least MAX_FCIO_MSG_LEN in length.
153 */
154 void
transportError(uint32_t fcio_errno,char * message)155 FCHBANPIVPort::transportError(uint32_t fcio_errno, char *message) {
156 Trace log("transportError");
157
158 string fcioErrorString;
159 if (message == NULL) {
160 log.internalError("NULL routine argument");
161 return;
162 }
163 switch (fcio_errno) {
164 case (uint32_t)FC_FAILURE:
165 fcioErrorString = "general failure";
166 break;
167 case (uint32_t)FC_FAILURE_SILENT:
168 fcioErrorString = "general failure but fail silently";
169 break;
170 case FC_SUCCESS:
171 fcioErrorString = "successful completion";
172 break;
173 case FC_CAP_ERROR:
174 fcioErrorString = "FCA capability error";
175 break;
176 case FC_CAP_FOUND:
177 fcioErrorString = "FCA capability unsettable";
178 break;
179 case FC_CAP_SETTABLE:
180 fcioErrorString = "FCA capability settable";
181 break;
182 case FC_UNBOUND:
183 fcioErrorString = "unbound stuff";
184 break;
185 case FC_NOMEM:
186 fcioErrorString = "allocation error";
187 break;
188 case FC_BADPACKET:
189 fcioErrorString = "invalid packet specified/supplied";
190 break;
191 case FC_OFFLINE:
192 fcioErrorString = "I/O resource unavailable";
193 break;
194 case FC_OLDPORT:
195 fcioErrorString = "operation on non-loop port";
196 break;
197 case FC_NO_MAP:
198 fcioErrorString = "requested map unavailable";
199 break;
200 case FC_TRANSPORT_ERROR:
201 fcioErrorString = "unable to transport I/O";
202 break;
203 case FC_ELS_FREJECT:
204 fcioErrorString = "ELS rejected by a Fabric";
205 break;
206 case FC_ELS_PREJECT:
207 fcioErrorString = "ELS rejected by an N_port";
208 break;
209 case FC_ELS_BAD:
210 fcioErrorString = "ELS rejected by FCA/fctl";
211 break;
212 case FC_ELS_MALFORMED:
213 fcioErrorString = "poorly formed ELS request";
214 break;
215 case FC_TOOMANY:
216 fcioErrorString = "resource request too large";
217 break;
218 case FC_UB_BADTOKEN:
219 fcioErrorString = "invalid unsolicited buffer token";
220 break;
221 case FC_UB_ERROR:
222 fcioErrorString = "invalid unsol buf request";
223 break;
224 case FC_UB_BUSY:
225 fcioErrorString = "buffer already in use";
226 break;
227 case FC_BADULP:
228 fcioErrorString = "Unknown ulp";
229 break;
230 case FC_BADTYPE:
231 fcioErrorString = "ULP not registered to handle this FC4 type";
232 break;
233 case FC_UNCLAIMED:
234 fcioErrorString = "request or data not claimed";
235 break;
236 case FC_ULP_SAMEMODULE:
237 fcioErrorString = "module already in use";
238 break;
239 case FC_ULP_SAMETYPE:
240 fcioErrorString = "FC4 module already in use";
241 break;
242 case FC_ABORTED:
243 fcioErrorString = "request aborted";
244 break;
245 case FC_ABORT_FAILED:
246 fcioErrorString = "abort request failed";
247 break;
248 case FC_BADEXCHANGE:
249 fcioErrorString = "exchange doesn\325t exist";
250 break;
251 case FC_BADWWN:
252 fcioErrorString = "WWN not recognized";
253 break;
254 case FC_BADDEV:
255 fcioErrorString = "device unrecognized";
256 break;
257 case FC_BADCMD:
258 fcioErrorString = "invalid command issued";
259 break;
260 case FC_BADOBJECT:
261 fcioErrorString = "invalid object requested";
262 break;
263 case FC_BADPORT:
264 fcioErrorString = "invalid port specified";
265 break;
266 case FC_NOTTHISPORT:
267 fcioErrorString = "resource not at this port";
268 break;
269 case FC_PREJECT:
270 fcioErrorString = "reject at remote N_Port";
271 break;
272 case FC_FREJECT:
273 fcioErrorString = "reject at remote Fabric";
274 break;
275 case FC_PBUSY:
276 fcioErrorString = "remote N_Port busy";
277 break;
278 case FC_FBUSY:
279 fcioErrorString = "remote Fabric busy";
280 break;
281 case FC_ALREADY:
282 fcioErrorString = "already logged in";
283 break;
284 case FC_LOGINREQ:
285 fcioErrorString = "login required";
286 break;
287 case FC_RESETFAIL:
288 fcioErrorString = "reset failed";
289 break;
290 case FC_INVALID_REQUEST:
291 fcioErrorString = "request is invalid";
292 break;
293 case FC_OUTOFBOUNDS:
294 fcioErrorString = "port number is out of bounds";
295 break;
296 case FC_TRAN_BUSY:
297 fcioErrorString = "command transport busy";
298 break;
299 case FC_STATEC_BUSY:
300 fcioErrorString = "port driver currently busy";
301 break;
302 case FC_DEVICE_BUSY:
303 fcioErrorString = "transport working on this device";
304 break;
305 case FC_DEVICE_NOT_TGT:
306 fcioErrorString = "device is not a SCSI target";
307 break;
308 default:
309 snprintf(message, MAX_FCIO_MSG_LEN, "Unknown error code 0x%x",
310 fcio_errno);
311 return;
312 }
313 snprintf(message, MAX_FCIO_MSG_LEN, "%s", fcioErrorString.c_str());
314 }
315
316