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 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 *
25 * Copyright 2019 RackTop Systems.
26 */
27
28
29
30 #include <FCHBAPort.h>
31 #include <Exceptions.h>
32 #include <Trace.h>
33 #include <sun_fc.h>
34 #include <iostream>
35 #include <iomanip>
36 #include <sys/types.h>
37 #include <sys/mkdev.h>
38 #include <sys/stat.h>
39 #include <fcntl.h>
40 #include <unistd.h>
41 #include <stropts.h>
42 #include <dirent.h>
43 #include <sys/fibre-channel/fc.h>
44 #include <sys/fibre-channel/fcio.h>
45 #include <sys/fibre-channel/ulp/fcp_util.h>
46 #include <sys/fibre-channel/ulp/fcsm.h>
47 #include <sys/fibre-channel/impl/fc_error.h>
48 #include <sys/fibre-channel/fc_appif.h>
49 #include <sys/scsi/generic/commands.h>
50 #include <sys/scsi/impl/commands.h>
51 #include <sys/scsi/impl/sense.h>
52 #include <sys/scsi/generic/inquiry.h>
53 #include <sys/scsi/generic/status.h>
54 #include <errno.h>
55 #include <FCHBANPIVPort.h>
56
57
58 using namespace std;
59
60 const int FCHBAPort::MAX_FCIO_MSG_LEN = 256;
61 const string FCHBAPort::FCSM_DRIVER_PATH = "/devices/pseudo/fcsm@0:fcsm";
62 const string FCHBAPort::FCP_DRIVER_PATH = "/devices/pseudo/fcp@0:fcp";
63
64 /*
65 * Interpret the error code in the fcio_t structure
66 *
67 * message must be at least MAX_FCIO_MSG_LEN in length.
68 */
69 void
transportError(uint32_t fcio_errno,char * message)70 FCHBAPort::transportError(uint32_t fcio_errno, char *message) {
71 Trace log("transportError");
72 string fcioErrorString;
73 if (message == NULL) {
74 log.internalError("NULL routine argument");
75 return;
76 }
77 switch (fcio_errno) {
78 case (uint32_t)FC_FAILURE:
79 fcioErrorString = "general failure";
80 break;
81 case (uint32_t)FC_FAILURE_SILENT:
82 fcioErrorString = "general failure but fail silently";
83 break;
84 case FC_SUCCESS:
85 fcioErrorString = "successful completion";
86 break;
87 case FC_CAP_ERROR:
88 fcioErrorString = "FCA capability error";
89 break;
90 case FC_CAP_FOUND:
91 fcioErrorString = "FCA capability unsettable";
92 break;
93 case FC_CAP_SETTABLE:
94 fcioErrorString = "FCA capability settable";
95 break;
96 case FC_UNBOUND:
97 fcioErrorString = "unbound stuff";
98 break;
99 case FC_NOMEM:
100 fcioErrorString = "allocation error";
101 break;
102 case FC_BADPACKET:
103 fcioErrorString = "invalid packet specified/supplied";
104 break;
105 case FC_OFFLINE:
106 fcioErrorString = "I/O resource unavailable";
107 break;
108 case FC_OLDPORT:
109 fcioErrorString = "operation on non-loop port";
110 break;
111 case FC_NO_MAP:
112 fcioErrorString = "requested map unavailable";
113 break;
114 case FC_TRANSPORT_ERROR:
115 fcioErrorString = "unable to transport I/O";
116 break;
117 case FC_ELS_FREJECT:
118 fcioErrorString = "ELS rejected by a Fabric";
119 break;
120 case FC_ELS_PREJECT:
121 fcioErrorString = "ELS rejected by an N_port";
122 break;
123 case FC_ELS_BAD:
124 fcioErrorString = "ELS rejected by FCA/fctl";
125 break;
126 case FC_ELS_MALFORMED:
127 fcioErrorString = "poorly formed ELS request";
128 break;
129 case FC_TOOMANY:
130 fcioErrorString = "resource request too large";
131 break;
132 case FC_UB_BADTOKEN:
133 fcioErrorString = "invalid unsolicited buffer token";
134 break;
135 case FC_UB_ERROR:
136 fcioErrorString = "invalid unsol buf request";
137 break;
138 case FC_UB_BUSY:
139 fcioErrorString = "buffer already in use";
140 break;
141 case FC_BADULP:
142 fcioErrorString = "Unknown ulp";
143 break;
144 case FC_BADTYPE:
145 fcioErrorString = "ULP not registered to handle this FC4 type";
146 break;
147 case FC_UNCLAIMED:
148 fcioErrorString = "request or data not claimed";
149 break;
150 case FC_ULP_SAMEMODULE:
151 fcioErrorString = "module already in use";
152 break;
153 case FC_ULP_SAMETYPE:
154 fcioErrorString = "FC4 module already in use";
155 break;
156 case FC_ABORTED:
157 fcioErrorString = "request aborted";
158 break;
159 case FC_ABORT_FAILED:
160 fcioErrorString = "abort request failed";
161 break;
162 case FC_BADEXCHANGE:
163 fcioErrorString = "exchange doesn�t exist";
164 break;
165 case FC_BADWWN:
166 fcioErrorString = "WWN not recognized";
167 break;
168 case FC_BADDEV:
169 fcioErrorString = "device unrecognized";
170 break;
171 case FC_BADCMD:
172 fcioErrorString = "invalid command issued";
173 break;
174 case FC_BADOBJECT:
175 fcioErrorString = "invalid object requested";
176 break;
177 case FC_BADPORT:
178 fcioErrorString = "invalid port specified";
179 break;
180 case FC_NOTTHISPORT:
181 fcioErrorString = "resource not at this port";
182 break;
183 case FC_PREJECT:
184 fcioErrorString = "reject at remote N_Port";
185 break;
186 case FC_FREJECT:
187 fcioErrorString = "reject at remote Fabric";
188 break;
189 case FC_PBUSY:
190 fcioErrorString = "remote N_Port busy";
191 break;
192 case FC_FBUSY:
193 fcioErrorString = "remote Fabric busy";
194 break;
195 case FC_ALREADY:
196 fcioErrorString = "already logged in";
197 break;
198 case FC_LOGINREQ:
199 fcioErrorString = "login required";
200 break;
201 case FC_RESETFAIL:
202 fcioErrorString = "reset failed";
203 break;
204 case FC_INVALID_REQUEST:
205 fcioErrorString = "request is invalid";
206 break;
207 case FC_OUTOFBOUNDS:
208 fcioErrorString = "port number is out of bounds";
209 break;
210 case FC_TRAN_BUSY:
211 fcioErrorString = "command transport busy";
212 break;
213 case FC_STATEC_BUSY:
214 fcioErrorString = "port driver currently busy";
215 break;
216 case FC_DEVICE_BUSY:
217 fcioErrorString = "transport working on this device";
218 break;
219 case FC_DEVICE_NOT_TGT:
220 fcioErrorString = "device is not a SCSI target";
221 break;
222 default:
223 snprintf(message, MAX_FCIO_MSG_LEN, "Unknown error code 0x%x",
224 fcio_errno);
225 return;
226 }
227 snprintf(message, MAX_FCIO_MSG_LEN, "%s", fcioErrorString.c_str());
228 }
229
230 static void
reportSense(struct scsi_extended_sense * sense,const char * routine)231 reportSense(struct scsi_extended_sense *sense, const char *routine) {
232 Trace log("reportSense");
233 string msg;
234 if (!sense) {
235 log.internalError("NULL sense argument passed.");
236 return;
237 }
238 if (!routine) {
239 log.internalError("NULL routine argument passed.");
240 return;
241 }
242 log.genericIOError("SCSI FAILURE");
243 switch (sense->es_key) {
244 case KEY_NO_SENSE:
245 msg = "No sense";
246 break;
247 case KEY_RECOVERABLE_ERROR:
248 msg = "Recoverable error";
249 break;
250 case KEY_NOT_READY:
251 msg = "Not ready";
252 break;
253 case KEY_MEDIUM_ERROR:
254 msg = "Medium error";
255 break;
256 case KEY_HARDWARE_ERROR:
257 msg = "Hardware error";
258 break;
259 case KEY_ILLEGAL_REQUEST:
260 msg = "Illegal request";
261 break;
262 case KEY_UNIT_ATTENTION:
263 msg = "Unit attention";
264 break;
265 case KEY_DATA_PROTECT:
266 msg = "Data protect";
267 break;
268 case KEY_BLANK_CHECK:
269 msg = "Blank check";
270 break;
271 case KEY_VENDOR_UNIQUE:
272 msg = "Vendor Unique";
273 break;
274 case KEY_COPY_ABORTED:
275 msg = "Copy aborted";
276 break;
277 case KEY_ABORTED_COMMAND:
278 msg = "Aborted command";
279 break;
280 case KEY_EQUAL:
281 msg = "Equal";
282 break;
283 case KEY_VOLUME_OVERFLOW:
284 msg = "Volume overflow";
285 break;
286 case KEY_MISCOMPARE:
287 msg = "Miscompare";
288 break;
289 case KEY_RESERVED:
290 msg = "Reserved";
291 break;
292 default:
293 msg = "unknown sense key";
294 }
295 log.genericIOError("\tSense key: %s", msg.c_str());
296 log.genericIOError("\tASC = 0x%x", sense->es_add_code);
297 log.genericIOError("\tASCQ = 0x%x", sense->es_qual_code);
298 }
299
300 /*
301 * Issue a SCSI pass thru command.
302 * Returns a scsi status value.
303 */
sendSCSIPassThru(struct fcp_scsi_cmd * fscsi,HBA_UINT32 * responseSize,HBA_UINT32 * senseSize,HBA_UINT8 * scsiStatus)304 void FCHBAPort::sendSCSIPassThru(struct fcp_scsi_cmd *fscsi,
305 HBA_UINT32 *responseSize, HBA_UINT32 *senseSize,
306 HBA_UINT8 *scsiStatus) {
307 Trace log("FCHBAPort::sendSCSIPassThru");
308 int fd;
309 HBA_STATUS ret;
310 char fcioErrorString[MAX_FCIO_MSG_LEN] = "";
311 hrtime_t start;
312 hrtime_t end;
313 int ioctl_errno;
314 double duration;
315 la_wwn_t wwn;
316
317 if (fscsi == NULL ||
318 responseSize == NULL ||
319 senseSize == NULL ||
320 scsiStatus == NULL) {
321 throw BadArgumentException();
322 }
323
324 memcpy(&wwn, fscsi->scsi_fc_pwwn.raw_wwn, sizeof (la_wwn_t));
325 start = gethrtime();
326 fscsi->scsi_fc_port_num = instanceNumber;
327
328 fd = HBA::_open(FCP_DRIVER_PATH, O_RDONLY | O_NDELAY);
329 ioctl_errno = 0;
330
331 if (ioctl(fd, FCP_TGT_SEND_SCSI, fscsi) != 0) {
332 /* save off errno */
333 ioctl_errno = errno;
334 close(fd);
335 /*
336 * collect SCSI status first regrardless of the value.
337 * 0 is a good status so this should be okay
338 */
339 *scsiStatus = fscsi->scsi_bufstatus & STATUS_MASK;
340 transportError(fscsi->scsi_fc_status, fcioErrorString);
341
342 /* Did we get a check condition? */
343 if ((fscsi->scsi_bufstatus & STATUS_MASK) == STATUS_CHECK) {
344 *senseSize = fscsi->scsi_rqlen;
345 throw CheckConditionException();
346 } else if (fscsi->scsi_fc_status == FC_DEVICE_NOT_TGT) {
347 /*
348 * fcp driver returns FC_DEVICE_NOT_TGT when the node is not
349 * scsi-capable like remote hba nodes.
350 */
351 throw NotATargetException();
352 } else if (fscsi->scsi_fc_status == FC_INVALID_LUN) {
353 throw InvalidLUNException();
354 } else if (ioctl_errno == EBUSY) {
355 throw BusyException();
356 } else if (ioctl_errno == EAGAIN) {
357 throw TryAgainException();
358 } else if (ioctl_errno == ENOTSUP) {
359 throw NotSupportedException();
360 } else if (ioctl_errno == ENOENT) {
361 throw UnavailableException();
362 } else {
363 throw IOError(this, wwnConversion(wwn.raw_wwn),
364 fscsi->scsi_lun);
365 }
366 } else {
367 close(fd);
368 /* Just in case, check for a check-condition state */
369 if ((fscsi->scsi_bufstatus & STATUS_MASK) == STATUS_CHECK) {
370 *scsiStatus = fscsi->scsi_bufstatus & STATUS_MASK;
371 *senseSize = fscsi->scsi_rqlen;
372 throw CheckConditionException();
373 }
374 }
375
376 /* Record the response data */
377 *scsiStatus = fscsi->scsi_bufstatus & STATUS_MASK;
378 *responseSize = fscsi->scsi_buflen;
379 *senseSize = fscsi->scsi_rqlen;
380
381 /* Do some quick duration calcuations */
382 end = gethrtime();
383 duration = end - start;
384 duration /= HR_SECOND;
385 log.debug("Total SCSI IO time for HBA %s "
386 "target %016llx was %.4f seconds", getPath().c_str(),
387 wwnConversion(wwn.raw_wwn), duration);
388
389 #ifdef DEBUG
390 /* Did we have any failure */
391 if (ret != HBA_STATUS_OK) {
392 log.genericIOError(
393 "Ioctl failed for device \"%s\" target %016llx."
394 " Errno: \"%s\"(%d), "
395 "Transport: \"%s\", SCSI Status: 0x%x"
396 "responseSize = %d, senseSize = %d",
397 getPath().c_str(), wwnConversion(fscsi->scsi_fc_pwwn.raw_wwn),
398 strerror(ioctl_errno), ioctl_errno, fcioErrorString,
399 *scsiStatus, *responseSize, *senseSize);
400 /* We may or may not have sense data */
401 reportSense((struct scsi_extended_sense *)fscsi->scsi_rqbufaddr,
402 ROUTINE);
403 }
404 #endif
405
406 }
407
408 /*
409 * constructs the fcp_scsi_cmd struct for SCSI_Inquiry, SendReadCapacity, or
410 * SendReportLUNs
411 */
412 /*#include <fcio.h>
413 #include <fcp_util.h>*/
414 inline void
scsi_cmd_init(struct fcp_scsi_cmd * fscsi,const char * portname,void * reqbuf,size_t req_len,void * responseBuffer,size_t resp_len,void * senseBuffer,size_t sense_len)415 scsi_cmd_init(struct fcp_scsi_cmd *fscsi, const char *portname, void *reqbuf,
416 size_t req_len, void *responseBuffer, size_t resp_len,
417 void *senseBuffer, size_t sense_len) {
418 Trace log("scsi_cmd_init");
419 fscsi->scsi_fc_rspcode = 0;
420 fscsi->scsi_flags = FCP_SCSI_READ;
421 fscsi->scsi_timeout = 10 /* sec */;
422 fscsi->scsi_cdbbufaddr = (char *)reqbuf;
423 fscsi->scsi_cdblen = (uint32_t) req_len;
424 fscsi->scsi_bufaddr = (char *)responseBuffer;
425 fscsi->scsi_buflen = (uint32_t) resp_len;
426 fscsi->scsi_bufresid = 0;
427 fscsi->scsi_bufstatus = 0;
428 fscsi->scsi_rqbufaddr = (char *)senseBuffer;
429 fscsi->scsi_rqlen = (uint32_t) sense_len;
430 fscsi->scsi_rqresid = 0;
431 }
432
433
FCHBAPort(string thePath)434 FCHBAPort::FCHBAPort(string thePath) : HBAPort() {
435 Trace log("FCHBAPort::FCHBAPort");
436 log.debug("Initializing HBA port %s", thePath.c_str());
437 fcio_t fcio;
438 int size = 200;
439 fc_hba_npiv_port_list_t *pathList;
440 bool retry = false;
441 int bufSize;
442
443 try {
444 path = lookupControllerPath(thePath);
445 sscanf(path.c_str(), "/dev/cfg/c%d", &controllerNumber);
446 } catch (...) {
447 log.debug("Unable to lookup controller path and number for %s",
448 thePath.c_str());
449 path = "/devices";
450 path += thePath;
451 path += ":fc";
452 controllerNumber = -1;
453 }
454
455 // Fetch the minor number for later use
456 struct stat sbuf;
457 if (stat(path.c_str(), &sbuf) == -1) {
458 throw IOError("Unable to stat device path: " + path);
459 }
460 instanceNumber = minor(sbuf.st_rdev);
461
462 // This routine is not index based, so we can discard stateChange
463 uint64_t tmp;
464 HBA_PORTATTRIBUTES attrs = getPortAttributes(tmp);
465 memcpy(&tmp, &attrs.PortWWN, 8);
466 portWWN = ntohll(tmp);
467 memcpy(&tmp, &attrs.NodeWWN, 8);
468 nodeWWN = ntohll(tmp);
469
470 // For reference, here's how to dump WWN's through C++ streams.
471 // cout << "\tPort WWN: " << hex << setfill('0') << setw(16) << portWWN
472 // << endl;
473 // cout << "\tNode WWN: " << hex << setfill('0') << setw(16) << nodeWWN
474 // << endl;
475
476 // we should add code here to build NPIVPORT instance
477 // Get Port's NPIV port list ( include nwwn and pwwn and path)
478 memset((caddr_t)&fcio, 0, sizeof (fcio));
479 fcio.fcio_cmd = FCIO_GET_NPIV_PORT_LIST;
480 fcio.fcio_xfer = FCIO_XFER_READ;
481 do {
482 retry = false;
483 bufSize = MAXPATHLEN * (size - 1) + (int) sizeof (fc_hba_npiv_port_list_t);
484 pathList = (fc_hba_npiv_port_list_t *) new uchar_t[bufSize];
485 pathList->numAdapters = size;
486 fcio.fcio_olen = bufSize;
487 fcio.fcio_obuf = (char *)pathList;
488 fp_ioctl(getPath(), FCIO_CMD, &fcio);
489 if (pathList->numAdapters > size) {
490 log.debug("Buffer too small for number of NPIV Port.Retry.");
491 size = pathList->numAdapters;
492 retry = true;
493 delete[] (pathList);
494 }
495 } while (retry);
496 log.debug("Get %d npiv ports", pathList->numAdapters);
497 // Make instance for each NPIV Port
498 for ( int i = 0; i < pathList->numAdapters; i++) {
499 try {
500 addPort(new FCHBANPIVPort(pathList->hbaPaths[i]));
501 } catch (...) {
502 log.debug("Ignoring partial failure");
503 }
504 }
505 delete[] (pathList);
506 }
507
deleteNPIVPort(uint64_t vportwwn)508 uint32_t FCHBAPort::deleteNPIVPort(uint64_t vportwwn) {
509 Trace log("FCHBAPort::deleteNPIVPort");
510 fcio_t fcio;
511 la_wwn_t lawwn[1];
512 int ret = 0;
513
514 memset(&fcio, 0, sizeof(fcio));
515 uint64_t en_wwn = htonll(vportwwn);
516 memcpy(&lawwn[0], &en_wwn, sizeof (en_wwn));
517
518 fcio.fcio_cmd = FCIO_DELETE_NPIV_PORT;
519 fcio.fcio_xfer = FCIO_XFER_WRITE;
520 fcio.fcio_ilen = sizeof (la_wwn_t) * 2;
521 fcio.fcio_ibuf = (caddr_t)&lawwn;
522
523 fp_ioctl(getPath(), FCIO_CMD, &fcio);
524
525 return (ret);
526 }
527
createNPIVPort(uint64_t vnodewwn,uint64_t vportwwn,uint32_t vindex)528 uint32_t FCHBAPort::createNPIVPort(uint64_t vnodewwn, uint64_t vportwwn, uint32_t vindex) {
529 Trace log("FCHBAPort::createNPIVPort");
530 fcio_t fcio;
531 la_wwn_t lawwn[2];
532 uint32_t vportindex = 0;
533 HBA_NPIVCREATEENTRY entrybuf;
534
535 memset(&fcio, 0, sizeof(fcio));
536 uint64_t en_wwn = htonll(vnodewwn);
537 memcpy(&entrybuf.VNodeWWN, &en_wwn, sizeof (en_wwn));
538 en_wwn = htonll(vportwwn);
539 memcpy(&entrybuf.VPortWWN, &en_wwn, sizeof (en_wwn));
540 entrybuf.vindex = vindex;
541
542 fcio.fcio_cmd = FCIO_CREATE_NPIV_PORT;
543 fcio.fcio_xfer = FCIO_XFER_READ;
544 fcio.fcio_olen = sizeof (uint32_t);
545 fcio.fcio_obuf = (caddr_t)&vportindex;
546 fcio.fcio_ilen = sizeof (HBA_NPIVCREATEENTRY);
547 fcio.fcio_ibuf = (caddr_t)&entrybuf;
548
549 fp_ioctl(getPath(), FCIO_CMD, &fcio);
550
551 return (vportindex);
552 }
553
getPortNPIVAttributes(uint64_t & stateChange)554 HBA_PORTNPIVATTRIBUTES FCHBAPort::getPortNPIVAttributes(uint64_t &stateChange) {
555 Trace log("FCHBAPort::getPortNPIVAttributes");
556
557 HBA_PORTNPIVATTRIBUTES attributes;
558 fc_hba_port_npiv_attributes_t attrs;
559 fcio_t fcio;
560
561 memset(&fcio, 0, sizeof(fcio));
562 memset(&attributes, 0, sizeof(attributes));
563
564 fcio.fcio_cmd = FCIO_GET_ADAPTER_PORT_NPIV_ATTRIBUTES;
565 fcio.fcio_olen = sizeof(attrs);
566 fcio.fcio_xfer = FCIO_XFER_READ;
567 fcio.fcio_obuf = (caddr_t)&attrs;
568
569 fp_ioctl(getPath(), FCIO_CMD, &fcio);
570
571 stateChange = attrs.lastChange;
572 attributes.npivflag = attrs.npivflag;
573 memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
574 memcpy(&attributes.PortWWN, &attrs.PortWWN, 8);
575 attributes.MaxNumberOfNPIVPorts = attrs.MaxNumberOfNPIVPorts;
576 attributes.NumberOfNPIVPorts = attrs.NumberOfNPIVPorts;
577
578 return (attributes);
579 }
580
getPortAttributes(uint64_t & stateChange)581 HBA_PORTATTRIBUTES FCHBAPort::getPortAttributes(uint64_t &stateChange) {
582 Trace log("FCHBAPort::getPortAttributes");
583
584 HBA_PORTATTRIBUTES attributes;
585 fcio_t fcio;
586 fc_hba_port_attributes_t attrs;
587
588 memset(&fcio, 0, sizeof (fcio));
589 memset(&attributes, 0, sizeof (attributes));
590
591 fcio.fcio_cmd = FCIO_GET_ADAPTER_PORT_ATTRIBUTES;
592 fcio.fcio_olen = sizeof (attrs);
593 fcio.fcio_xfer = FCIO_XFER_READ;
594 fcio.fcio_obuf = (caddr_t)&attrs;
595
596 fp_ioctl(getPath(), FCIO_CMD, &fcio);
597
598 stateChange = attrs.lastChange;
599
600 attributes.PortFcId = attrs.PortFcId;
601 attributes.PortType = attrs.PortType;
602 attributes.PortState = attrs.PortState;
603 attributes.PortSupportedClassofService = attrs.PortSupportedClassofService;
604 attributes.PortSupportedSpeed = attrs.PortSupportedSpeed;
605 attributes.PortSpeed = attrs.PortSpeed;
606 attributes.PortMaxFrameSize = attrs.PortMaxFrameSize;
607 attributes.NumberofDiscoveredPorts = attrs.NumberofDiscoveredPorts;
608 memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
609 memcpy(&attributes.PortWWN, &attrs.PortWWN, 8);
610 memcpy(&attributes.FabricName, &attrs.FabricName, 8);
611 memcpy(&attributes.PortSupportedFc4Types, &attrs.PortSupportedFc4Types, 32);
612 memcpy(&attributes.PortActiveFc4Types, &attrs.PortActiveFc4Types, 32);
613 memcpy(&attributes.PortSymbolicName, &attrs.PortSymbolicName, 256);
614
615 strncpy((char *)attributes.OSDeviceName, getPath().c_str(), 256);
616 return (attributes);
617 }
618
getDiscoveredAttributes(HBA_UINT32 discoveredport,uint64_t & stateChange)619 HBA_PORTATTRIBUTES FCHBAPort::getDiscoveredAttributes(
620 HBA_UINT32 discoveredport, uint64_t &stateChange) {
621 Trace log("FCHBAPort::getDiscoverdAttributes(i)");
622
623 HBA_PORTATTRIBUTES attributes;
624 fcio_t fcio;
625 fc_hba_port_attributes_t attrs;
626
627 memset(&fcio, 0, sizeof (fcio));
628 memset(&attributes, 0, sizeof (attributes));
629
630 fcio.fcio_cmd = FCIO_GET_DISCOVERED_PORT_ATTRIBUTES;
631 fcio.fcio_olen = sizeof (attrs);
632 fcio.fcio_xfer = FCIO_XFER_READ;
633 fcio.fcio_obuf = (caddr_t)&attrs;
634 fcio.fcio_ilen = sizeof (discoveredport);
635 fcio.fcio_ibuf = (caddr_t)&discoveredport;
636
637 fp_ioctl(getPath(), FCIO_CMD, &fcio);
638
639 stateChange = attrs.lastChange;
640
641 attributes.PortFcId = attrs.PortFcId;
642 attributes.PortType = attrs.PortType;
643 attributes.PortState = attrs.PortState;
644 attributes.PortSupportedClassofService = attrs.PortSupportedClassofService;
645 attributes.PortSupportedSpeed = attrs.PortSupportedSpeed;
646 attributes.PortSpeed = attrs.PortSpeed;
647 attributes.PortMaxFrameSize = attrs.PortMaxFrameSize;
648 attributes.NumberofDiscoveredPorts = attrs.NumberofDiscoveredPorts;
649 memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
650 memcpy(&attributes.PortWWN, &attrs.PortWWN, 8);
651 memcpy(&attributes.FabricName, &attrs.FabricName, 8);
652 memcpy(&attributes.PortSupportedFc4Types, &attrs.PortSupportedFc4Types, 32);
653 memcpy(&attributes.PortActiveFc4Types, &attrs.PortActiveFc4Types, 32);
654 memcpy(&attributes.PortSymbolicName, &attrs.PortSymbolicName, 256);
655
656
657 return (attributes);
658 }
659
getDiscoveredAttributes(uint64_t wwn,uint64_t & stateChange)660 HBA_PORTATTRIBUTES FCHBAPort::getDiscoveredAttributes(
661 uint64_t wwn, uint64_t &stateChange) {
662 Trace log("FCHBAPort::getDiscoverdAttributes(p)");
663
664 HBA_PORTATTRIBUTES attributes;
665 fcio_t fcio;
666 fc_hba_port_attributes_t attrs;
667 la_wwn_t lawwn;
668
669 memset(&fcio, 0, sizeof (fcio));
670 memset(&attributes, 0, sizeof (attributes));
671
672 uint64_t en_wwn = htonll(wwn);
673 memcpy(&lawwn, &en_wwn, sizeof (en_wwn));
674
675 fcio.fcio_cmd = FCIO_GET_PORT_ATTRIBUTES;
676 fcio.fcio_olen = sizeof (attrs);
677 fcio.fcio_xfer = FCIO_XFER_READ;
678 fcio.fcio_obuf = (caddr_t)&attrs;
679 fcio.fcio_ilen = sizeof (wwn);
680 fcio.fcio_ibuf = (caddr_t)&lawwn;
681
682 fp_ioctl(getPath(), FCIO_CMD, &fcio);
683
684 stateChange = attrs.lastChange;
685
686 attributes.PortFcId = attrs.PortFcId;
687 attributes.PortType = attrs.PortType;
688 attributes.PortState = attrs.PortState;
689 attributes.PortSupportedClassofService = attrs.PortSupportedClassofService;
690 attributes.PortSupportedSpeed = attrs.PortSupportedSpeed;
691 attributes.PortSpeed = attrs.PortSpeed;
692 attributes.PortMaxFrameSize = attrs.PortMaxFrameSize;
693 attributes.NumberofDiscoveredPorts = attrs.NumberofDiscoveredPorts;
694 memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
695 memcpy(&attributes.PortWWN, &attrs.PortWWN, 8);
696 memcpy(&attributes.FabricName, &attrs.FabricName, 8);
697 memcpy(&attributes.PortSupportedFc4Types, &attrs.PortSupportedFc4Types, 32);
698 memcpy(&attributes.PortActiveFc4Types, &attrs.PortActiveFc4Types, 32);
699 memcpy(&attributes.PortSymbolicName, &attrs.PortSymbolicName, 256);
700
701
702 return (attributes);
703 }
704
705
getTargetMappings(PHBA_FCPTARGETMAPPINGV2 userMappings)706 void FCHBAPort::getTargetMappings(PHBA_FCPTARGETMAPPINGV2 userMappings) {
707 Trace log("FCHBAPort::getTargetMappings");
708 int i, index;
709 uint_t total_entries = 0;
710
711 struct fcp_ioctl fioctl;
712 fc_hba_target_mappings_t *mappings;
713 int fd;
714 bool zeroLength = false;
715
716
717 if (userMappings == NULL) {
718 log.userError("Null mapping argument ");
719 throw BadArgumentException();
720 }
721
722 /* It's possible they didn't give any space */
723 if (userMappings->NumberOfEntries == 0) {
724 zeroLength = true;
725 userMappings->NumberOfEntries = 1;
726 /* We have to give the driver at least one space */
727 }
728
729 mappings = (fc_hba_target_mappings_t *)new uchar_t[
730 (sizeof (fc_hba_mapping_entry_t)) *
731 (userMappings->NumberOfEntries - 1) +
732 sizeof (fc_hba_target_mappings_t)];
733 if (mappings == NULL) {
734 log.noMemory();
735 throw InternalError();
736 }
737
738
739 fioctl.fp_minor = instanceNumber;
740 fioctl.listlen = ((uint32_t) (sizeof (fc_hba_mapping_entry_t))) *
741 (userMappings->NumberOfEntries - 1) +
742 (uint32_t) sizeof (fc_hba_target_mappings_t);
743 fioctl.list = (caddr_t)mappings;
744
745 fd = HBA::_open(FCP_DRIVER_PATH, O_RDONLY | O_NDELAY);
746
747 log.debug("Performing IOCTL to fetch mappings");
748
749 if (ioctl(fd, FCP_GET_TARGET_MAPPINGS, &fioctl) != 0) {
750 delete[] (mappings);
751 close(fd);
752 if (errno == EBUSY) {
753 throw BusyException();
754 } else if (errno == EAGAIN) {
755 throw TryAgainException();
756 } else if (errno == ENOTSUP) {
757 throw NotSupportedException();
758 } else if (errno == ENOENT) {
759 throw UnavailableException();
760 } else {
761 throw IOError("Unable to fetch target mappings");
762 }
763 }
764
765 close(fd);
766 // Quickly iterate through and copy the data over to the client
767 for (i = 0; i < userMappings->NumberOfEntries && !zeroLength &&
768 i < mappings->numLuns; i++) {
769 string raw = mappings->entries[i].targetDriver;
770
771
772 if (raw.length() <= 0) {
773 log.internalError("Bad target mapping without path, truncating.");
774 break;
775 }
776 /*
777 * Ideally, we'd like to ask some standard Solaris interface
778 * "What is the prefered minor node for this target?"
779 * but no such interface exists today. So, for now,
780 * we just hard-code ":n" for tapes, ":c,raw" for disks,
781 * and ":0" for enclosures.
782 * Devices with other generic names will be presented through
783 * first matching /dev path.
784 */
785 if ((raw.find("/st@") != raw.npos) ||
786 (raw.find("/tape@") != raw.npos)) {
787 raw += ":n";
788 } else if ((raw.find("/ssd@") != raw.npos) ||
789 (raw.find("/sd@") != raw.npos) ||
790 (raw.find("/disk@") != raw.npos)) {
791 raw += ":c,raw";
792 } else if ((raw.find("/ses@") != raw.npos) ||
793 (raw.find("/enclosure@") != raw.npos)) {
794 raw += ":0";
795 } else {
796 log.debug(
797 "Unrecognized target driver (%s), using first matching /dev path",
798 raw.c_str());
799 }
800 snprintf(userMappings->entry[i].ScsiId.OSDeviceName,
801 sizeof (userMappings->entry[i].ScsiId.OSDeviceName),
802 "/devices%s", raw.c_str());
803 userMappings->entry[i].ScsiId.ScsiBusNumber =
804 controllerNumber;
805 userMappings->entry[i].ScsiId.ScsiTargetNumber =
806 mappings->entries[i].targetNumber;
807 userMappings->entry[i].ScsiId.ScsiOSLun =
808 mappings->entries[i].osLUN;
809 userMappings->entry[i].FcpId.FcId =
810 mappings->entries[i].d_id;
811 memcpy(userMappings->entry[i].FcpId.NodeWWN.wwn,
812 mappings->entries[i].NodeWWN.raw_wwn,
813 sizeof (la_wwn_t));
814 memcpy(userMappings->entry[i].FcpId.PortWWN.wwn,
815 mappings->entries[i].PortWWN.raw_wwn,
816 sizeof (la_wwn_t));
817
818 userMappings->entry[i].FcpId.FcpLun =
819 mappings->entries[i].samLUN;
820
821 memcpy(userMappings->entry[i].LUID.buffer,
822 mappings->entries[i].guid,
823 sizeof (userMappings->entry[i].LUID.buffer));
824 }
825
826 log.debug("Total mappings: %d %08x %08x",
827 mappings->numLuns, mappings->entries[i].osLUN, mappings->entries[i].samLUN);
828
829 // If everything is good, convert paths to sym-links
830 if (mappings->numLuns > 0 && !zeroLength) {
831 if (userMappings->NumberOfEntries >= mappings->numLuns) {
832 // User buffer is larger than needed. (All is good)
833 userMappings->NumberOfEntries = mappings->numLuns;
834 convertToShortNames(userMappings);
835 } else {
836 // User buffer is non zero, but too small. Don't bother with links
837 userMappings->NumberOfEntries = mappings->numLuns;
838 delete[] (mappings);
839 throw MoreDataException();
840 }
841 } else if (mappings->numLuns > 0) {
842 // Zero length buffer, but we've got mappings
843 userMappings->NumberOfEntries = mappings->numLuns;
844 delete[] (mappings);
845 throw MoreDataException();
846 } else {
847 // No mappings, no worries
848 userMappings->NumberOfEntries = 0;
849 delete[] (mappings);
850 return;
851 }
852 delete[] (mappings);
853 }
854
getRNIDMgmtInfo(PHBA_MGMTINFO info)855 void FCHBAPort::getRNIDMgmtInfo(PHBA_MGMTINFO info) {
856 Trace log("FCHBAPort::getRNIDMgmtInfo");
857 HBA_STATUS status = HBA_STATUS_OK;
858 fc_rnid_t rnid;
859 fcio_t fcio;
860
861
862 if (info == NULL) {
863 log.userError("NULL port management info");
864 throw BadArgumentException();
865 }
866
867 // Get the RNID information from the first port
868 memset(&rnid, 0, sizeof (fc_rnid_t));
869 memset((caddr_t)&fcio, 0, sizeof (fcio));
870
871 fcio.fcio_cmd = FCIO_GET_NODE_ID;
872 fcio.fcio_olen = sizeof (fc_rnid_t);
873 fcio.fcio_xfer = FCIO_XFER_READ;
874 fcio.fcio_obuf = (caddr_t)&rnid;
875 fp_ioctl(getPath(), FCIO_CMD, &fcio);
876
877 // Copy out the struct members of rnid into PHBA_MGMTINFO struct
878 memcpy(&info->wwn, &(rnid.global_id), sizeof (info->wwn));
879 memcpy(&info->unittype, &(rnid.unit_type), sizeof (info->unittype));
880 memcpy(&info->PortId, &(rnid.port_id), sizeof (info->PortId));
881 memcpy(&info->NumberOfAttachedNodes, &(rnid.num_attached),
882 sizeof (info->NumberOfAttachedNodes));
883 memcpy(&info->IPVersion, &(rnid.ip_version), sizeof (info->IPVersion));
884 memcpy(&info->UDPPort, &(rnid.udp_port), sizeof (info->UDPPort));
885 memcpy(&info->IPAddress, &(rnid.ip_addr), sizeof (info->IPAddress));
886 memcpy(&info->TopologyDiscoveryFlags, &(rnid.topo_flags),
887 sizeof (info->TopologyDiscoveryFlags));
888 }
889
sendCTPassThru(void * requestBuffer,HBA_UINT32 requestSize,void * responseBuffer,HBA_UINT32 * responseSize)890 void FCHBAPort::sendCTPassThru(void *requestBuffer, HBA_UINT32 requestSize,
891 void *responseBuffer, HBA_UINT32 *responseSize) {
892 Trace log("FCHBAPort::sendCTPassThru");
893 fcio_t fcio;
894 struct stat sbuf;
895 minor_t minor_node;
896 hrtime_t start, end;
897 double duration;
898
899 // Validate the arguments
900 if (requestBuffer == NULL) {
901 log.userError("NULL request buffer");
902 throw BadArgumentException();
903 }
904 if (responseBuffer == NULL) {
905 log.userError("NULL response buffer");
906 throw BadArgumentException();
907 }
908
909 minor_node = instanceNumber;
910
911 // construct fcio struct
912 memset(&fcio, 0, sizeof (fcio_t));
913 fcio.fcio_cmd = FCSMIO_CT_CMD;
914 fcio.fcio_xfer = FCIO_XFER_RW;
915
916 fcio.fcio_ilen = requestSize;
917 fcio.fcio_ibuf = (char *)requestBuffer;
918 fcio.fcio_olen = *responseSize;
919 fcio.fcio_obuf = (char *)responseBuffer;
920
921 fcio.fcio_alen = sizeof (minor_t);
922 fcio.fcio_abuf = (char *)&minor_node;
923
924
925 start = gethrtime();
926 fcsm_ioctl(FCSMIO_CMD, &fcio);
927
928 // Do some calculations on the duration of the ioctl.
929 end = gethrtime();
930 duration = end - start;
931 duration /= HR_SECOND;
932 log.debug(
933 "Total CTPASS ioctl call for HBA %s was %.4f seconds",
934 getPath().c_str(), duration);
935 }
936
sendRLS(uint64_t destWWN,void * pRspBuffer,HBA_UINT32 * pRspBufferSize)937 void FCHBAPort::sendRLS(uint64_t destWWN,
938 void *pRspBuffer,
939 HBA_UINT32 *pRspBufferSize) {
940 Trace log("FCHBAPort::sendRLS");
941
942 fcio_t fcio;
943 fc_portid_t rls_req;
944
945
946 // Validate the arguments
947 if (pRspBuffer == NULL ||
948 pRspBufferSize == NULL) {
949 log.userError("NULL hba");
950 throw BadArgumentException();
951 }
952
953 // check to see if we are sending RLS to the HBA
954 HBA_PORTATTRIBUTES attrs;
955 uint64_t tmp;
956 if (getPortWWN() == destWWN) {
957 attrs = getPortAttributes(tmp);
958 } else {
959 attrs = getDiscoveredAttributes(destWWN, tmp);
960 }
961
962 memcpy(&rls_req, &attrs.PortFcId,
963 sizeof (attrs.PortFcId));
964
965 memset((caddr_t)&fcio, 0, sizeof (fcio));
966 fcio.fcio_cmd = FCIO_LINK_STATUS;
967 fcio.fcio_ibuf = (caddr_t)&rls_req;
968 fcio.fcio_ilen = sizeof (rls_req);
969 fcio.fcio_xfer = FCIO_XFER_RW;
970 fcio.fcio_flags = 0;
971 fcio.fcio_cmd_flags = FCIO_CFLAGS_RLS_DEST_NPORT;
972 fcio.fcio_obuf = (char *)new uchar_t[*pRspBufferSize];
973 fcio.fcio_olen = *pRspBufferSize;
974
975 if (fcio.fcio_obuf == NULL) {
976 log.noMemory();
977 throw InternalError();
978 }
979
980 fp_ioctl(getPath(), FCIO_CMD, &fcio);
981 memcpy(pRspBuffer, fcio.fcio_obuf, *pRspBufferSize);
982 if (fcio.fcio_obuf != NULL) {
983 delete(fcio.fcio_obuf);
984 }
985 }
986
sendReportLUNs(uint64_t wwn,void * responseBuffer,HBA_UINT32 * responseSize,HBA_UINT8 * scsiStatus,void * senseBuffer,HBA_UINT32 * senseSize)987 void FCHBAPort::sendReportLUNs(uint64_t wwn,
988 void *responseBuffer, HBA_UINT32 *responseSize,
989 HBA_UINT8 *scsiStatus,
990 void *senseBuffer, HBA_UINT32 *senseSize) {
991 Trace log("FCHBAPort::sendReportLUNs");
992 struct fcp_scsi_cmd fscsi;
993 union scsi_cdb scsi_rl_req;
994 uint64_t targetWwn = htonll(wwn);
995
996 // Validate the arguments
997 if (responseBuffer == NULL ||
998 senseBuffer == NULL ||
999 responseSize == NULL ||
1000 senseSize == NULL) {
1001 throw BadArgumentException();
1002 }
1003
1004 memset(&fscsi, 0, sizeof (fscsi));
1005 memset(&scsi_rl_req, 0, sizeof (scsi_rl_req));
1006 memcpy(fscsi.scsi_fc_pwwn.raw_wwn, &targetWwn, sizeof (la_wwn_t));
1007
1008 scsi_cmd_init(&fscsi, getPath().c_str(), &scsi_rl_req,
1009 sizeof (scsi_rl_req), responseBuffer, *responseSize,
1010 senseBuffer, *senseSize);
1011
1012 fscsi.scsi_lun = 0;
1013 scsi_rl_req.scc_cmd = SCMD_REPORT_LUNS;
1014 FORMG5COUNT(&scsi_rl_req, *responseSize);
1015 sendSCSIPassThru(&fscsi, responseSize, senseSize, scsiStatus);
1016 }
1017
1018 /*
1019 * arguments:
1020 * wwn - remote target WWN where the SCSI Inquiry shall be sent
1021 * fcLun - the SCSI LUN to which the SCSI Inquiry shall be sent
1022 * cdb1 - the second byte of the CDB for the SCSI Inquiry
1023 * cdb2 - the third byte of teh CDB for the SCSI Inquiry
1024 * responseBuffer - shall be a pointer to a buffer to receive the SCSI
1025 * Inquiry command response
1026 * responseSize - a pointer to the size of the buffer to receive
1027 * the SCSI Inquiry.
1028 * scsiStatus - a pointer to a buffer to receive SCSI status
1029 * senseBuffer - pointer to a buffer to receive SCSI sense data
1030 * seneseSize - pointer to the size of the buffer to receive SCSI sense
1031 * data
1032 */
sendScsiInquiry(uint64_t wwn,HBA_UINT64 fcLun,HBA_UINT8 cdb1,HBA_UINT8 cdb2,void * responseBuffer,HBA_UINT32 * responseSize,HBA_UINT8 * scsiStatus,void * senseBuffer,HBA_UINT32 * senseSize)1033 void FCHBAPort::sendScsiInquiry(uint64_t wwn, HBA_UINT64 fcLun,
1034 HBA_UINT8 cdb1, HBA_UINT8 cdb2, void *responseBuffer,
1035 HBA_UINT32 *responseSize, HBA_UINT8 *scsiStatus, void *senseBuffer,
1036 HBA_UINT32 *senseSize) {
1037 Trace log("FCHBAPort::sendScsiInquiry");
1038
1039 struct fcp_scsi_cmd fscsi;
1040 union scsi_cdb scsi_inq_req;
1041 uint64_t targetWwn = htonll(wwn);
1042
1043 // Validate the arguments
1044 if (responseBuffer == NULL ||
1045 senseBuffer == NULL ||
1046 responseSize == NULL ||
1047 senseSize == NULL) {
1048 throw BadArgumentException();
1049 }
1050
1051 memset(&fscsi, 0, sizeof (fscsi));
1052 memset(&scsi_inq_req, 0, sizeof (scsi_inq_req));
1053 memcpy(fscsi.scsi_fc_pwwn.raw_wwn, &targetWwn, sizeof (la_wwn_t));
1054
1055
1056 scsi_cmd_init(&fscsi, getPath().c_str(), &scsi_inq_req,
1057 sizeof (scsi_inq_req), responseBuffer, *responseSize,
1058 senseBuffer, *senseSize);
1059 fscsi.scsi_lun = fcLun;
1060
1061 scsi_inq_req.scc_cmd = SCMD_INQUIRY;
1062 scsi_inq_req.g0_addr1 = cdb2;
1063 scsi_inq_req.g0_addr2 = cdb1;
1064 scsi_inq_req.g0_count0 = *responseSize;
1065
1066
1067 sendSCSIPassThru(&fscsi, responseSize, senseSize, scsiStatus);
1068 }
1069
1070
sendReadCapacity(uint64_t pwwn,HBA_UINT64 fcLun,void * responseBuffer,HBA_UINT32 * responseSize,HBA_UINT8 * scsiStatus,void * senseBuffer,HBA_UINT32 * senseSize)1071 void FCHBAPort::sendReadCapacity(uint64_t pwwn,
1072 HBA_UINT64 fcLun, void *responseBuffer,
1073 HBA_UINT32 *responseSize, HBA_UINT8 *scsiStatus,
1074 void *senseBuffer, HBA_UINT32 *senseSize) {
1075 Trace log("FCHBAPort::sendReadCapacity");
1076
1077 struct fcp_scsi_cmd fscsi;
1078 union scsi_cdb scsi_rc_req;
1079 uint64_t targetWwn = htonll(pwwn);
1080
1081 // Validate the arguments
1082 if (responseBuffer == NULL ||
1083 senseBuffer == NULL ||
1084 responseSize == NULL ||
1085 senseSize == NULL ||
1086 scsiStatus == NULL) {
1087 throw BadArgumentException();
1088 }
1089
1090 memset(&fscsi, 0, sizeof (fscsi));
1091 memset(&scsi_rc_req, 0, sizeof (scsi_rc_req));
1092
1093 scsi_cmd_init(&fscsi, getPath().c_str(), &scsi_rc_req,
1094 sizeof (scsi_rc_req), responseBuffer, *responseSize,
1095 senseBuffer, *senseSize);
1096
1097 memcpy(fscsi.scsi_fc_pwwn.raw_wwn, &targetWwn, sizeof (la_wwn_t));
1098 fscsi.scsi_lun = fcLun;
1099
1100 scsi_rc_req.scc_cmd = SCMD_READ_CAPACITY;
1101 scsi_rc_req.g1_reladdr = 0;
1102
1103 scsi_rc_req.g1_addr3 = 0;
1104 scsi_rc_req.g1_count0 = 0;
1105
1106 sendSCSIPassThru(&fscsi, responseSize, senseSize, scsiStatus);
1107 }
1108
sendRNID(uint64_t destwwn,HBA_UINT32 destfcid,HBA_UINT32 nodeIdDataFormat,void * pRspBuffer,HBA_UINT32 * RspBufferSize)1109 void FCHBAPort::sendRNID(uint64_t destwwn, HBA_UINT32 destfcid,
1110 HBA_UINT32 nodeIdDataFormat, void *pRspBuffer,
1111 HBA_UINT32 *RspBufferSize) {
1112 Trace log("FCHBAPort::sendRNID");
1113 int localportfound, remoteportfound, send;
1114 fcio_t fcio;
1115
1116 // Validate the arguments
1117 if (pRspBuffer == NULL ||
1118 RspBufferSize == NULL) {
1119 throw BadArgumentException();
1120 }
1121 // NodeIdDataFormat must be within the range of 0x00 and 0xff
1122 if (nodeIdDataFormat > 0xff) {
1123 log.userError(
1124 "NodeIdDataFormat must be within the range of 0x00 "
1125 "and 0xFF");
1126 throw BadArgumentException();
1127 }
1128
1129
1130 remoteportfound = 0;
1131 if (destfcid != 0) {
1132 try {
1133 uint64_t tmp;
1134 HBA_PORTATTRIBUTES attrs = getDiscoveredAttributes(destwwn,
1135 tmp);
1136 if (attrs.PortFcId == destfcid) {
1137 send = 1;
1138 remoteportfound = 1;
1139 } else {
1140 send = 0;
1141 remoteportfound = 1;
1142 }
1143 } catch (HBAException &e) {
1144 /*
1145 * Send RNID if destination port not
1146 * present in the discovered ports table
1147 */
1148 }
1149 if (remoteportfound == 0) {
1150 send = 1;
1151 }
1152 } else {
1153 send = 1;
1154 }
1155
1156 if (!send) {
1157 // Can we log something so we can figure out why?
1158 throw BadArgumentException();
1159 }
1160
1161 memset((caddr_t)&fcio, 0, sizeof (fcio));
1162 uint64_t netdestwwn = htonll(destwwn);
1163 fcio.fcio_cmd = FCIO_SEND_NODE_ID;
1164 fcio.fcio_xfer = FCIO_XFER_READ;
1165 fcio.fcio_cmd_flags = nodeIdDataFormat;
1166 fcio.fcio_ilen = sizeof (la_wwn_t);
1167 fcio.fcio_ibuf = (caddr_t)&netdestwwn;
1168 fcio.fcio_olen = *RspBufferSize;
1169 fcio.fcio_obuf = (char *)new uchar_t[*RspBufferSize];
1170
1171
1172 if (fcio.fcio_obuf == NULL) {
1173 log.noMemory();
1174 throw InternalError();
1175 }
1176
1177 fp_ioctl(getPath(), FCIO_CMD, &fcio);
1178
1179 memcpy(pRspBuffer, fcio.fcio_obuf, *RspBufferSize);
1180
1181 if (fcio.fcio_obuf != NULL) {
1182 delete(fcio.fcio_obuf);
1183 }
1184 }
1185
setRNID(HBA_MGMTINFO info)1186 void FCHBAPort::setRNID(HBA_MGMTINFO info) {
1187 Trace log("FCHBAPort::setRNID");
1188 fc_rnid_t rnid;
1189 fcio_t fcio;
1190
1191 memset(&rnid, 0, sizeof (fc_rnid_t));
1192 memset((caddr_t)&fcio, 0, sizeof (fcio));
1193
1194
1195 fcio.fcio_cmd = FCIO_SET_NODE_ID;
1196 fcio.fcio_ilen = sizeof (fc_rnid_t);
1197 fcio.fcio_xfer = FCIO_XFER_WRITE;
1198 fcio.fcio_ibuf = (caddr_t)&rnid;
1199
1200
1201 // Copy the HBA_MGMTINFO into fc_rnid_t struct
1202 memcpy(&(rnid.unit_type), &(info.unittype), sizeof (rnid.unit_type));
1203 memcpy(&(rnid.port_id), &(info.PortId), sizeof (rnid.port_id));
1204 memcpy(&(rnid.global_id), &(info.wwn), sizeof (info.wwn));
1205 memcpy(&(rnid.num_attached), &(info.NumberOfAttachedNodes),
1206 sizeof (rnid.num_attached));
1207 memcpy(&(rnid.ip_version), &(info.IPVersion), sizeof (rnid.ip_version));
1208 memcpy(&(rnid.udp_port), &(info.UDPPort), sizeof (rnid.udp_port));
1209 memcpy(&(rnid.ip_addr), &info.IPAddress, sizeof (rnid.ip_addr));
1210 memcpy(&(rnid.topo_flags), &(info.TopologyDiscoveryFlags),
1211 sizeof (rnid.topo_flags));
1212
1213 fp_ioctl(getPath(), FCIO_CMD, &fcio, O_NDELAY | O_RDONLY | O_EXCL);
1214 }
1215
fp_ioctl(string path,int cmd,fcio_t * fcio,int openflag)1216 void FCHBAPort::fp_ioctl(string path, int cmd, fcio_t *fcio, int openflag) {
1217 Trace log("FCHBAPort::fp_ioctl with openflag");
1218 char fcioErrorString[MAX_FCIO_MSG_LEN] = "";
1219 int fd = HBA::_open(path, openflag);
1220 try {
1221 int times = 0;
1222 HBA::_ioctl(fd, cmd, (uchar_t *)fcio);
1223 while (fcio->fcio_errno == FC_STATEC_BUSY) {
1224 sleep(1);
1225 HBA::_ioctl(fd, cmd, (uchar_t *)fcio);
1226 if (times++ > 10) {
1227 break;
1228 }
1229 }
1230 close(fd);
1231 if (fcio->fcio_errno) {
1232 throw IOError("IOCTL transport failure");
1233 }
1234 } catch (...) {
1235 close(fd);
1236 transportError(fcio->fcio_errno, fcioErrorString);
1237 log.genericIOError("ioctl (0x%x) failed. Transport: \"%s\"", cmd,
1238 fcioErrorString);
1239 switch (fcio->fcio_errno) {
1240 case FC_BADWWN:
1241 throw IllegalWWNException();
1242 case FC_BADPORT:
1243 throw IllegalWWNException();
1244 case FC_OUTOFBOUNDS:
1245 throw IllegalIndexException();
1246 case FC_PBUSY:
1247 case FC_FBUSY:
1248 case FC_TRAN_BUSY:
1249 case FC_STATEC_BUSY:
1250 case FC_DEVICE_BUSY:
1251 throw BusyException();
1252 case FC_SUCCESS:
1253 default:
1254 throw;
1255 }
1256 }
1257 }
1258
fp_ioctl(string path,int cmd,fcio_t * fcio)1259 void FCHBAPort::fp_ioctl(string path, int cmd, fcio_t *fcio) {
1260 Trace log("FCHBAPort::fp_ioctl");
1261 fp_ioctl(path, cmd, fcio, O_NDELAY | O_RDONLY);
1262 }
1263
fcsm_ioctl(int cmd,fcio_t * fcio)1264 void FCHBAPort::fcsm_ioctl(int cmd, fcio_t *fcio) {
1265 // We use the same error handling as fp, so just re-use
1266 fp_ioctl(FCSM_DRIVER_PATH, cmd, fcio);
1267 }
1268