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 26 27 28 #include <FCHBAPort.h> 29 #include <Exceptions.h> 30 #include <Trace.h> 31 #include <sun_fc.h> 32 #include <iostream> 33 #include <iomanip> 34 #include <sys/types.h> 35 #include <sys/mkdev.h> 36 #include <sys/stat.h> 37 #include <fcntl.h> 38 #include <unistd.h> 39 #include <stropts.h> 40 #include <dirent.h> 41 #include <sys/fibre-channel/fc.h> 42 #include <sys/fibre-channel/fcio.h> 43 #include <sys/fibre-channel/ulp/fcp_util.h> 44 #include <sys/fibre-channel/ulp/fcsm.h> 45 #include <sys/fibre-channel/impl/fc_error.h> 46 #include <sys/fibre-channel/fc_appif.h> 47 #include <sys/scsi/generic/commands.h> 48 #include <sys/scsi/impl/commands.h> 49 #include <sys/scsi/impl/sense.h> 50 #include <sys/scsi/generic/inquiry.h> 51 #include <sys/scsi/generic/status.h> 52 #include <errno.h> 53 #include <FCHBANPIVPort.h> 54 55 56 using namespace std; 57 58 const int FCHBAPort::MAX_FCIO_MSG_LEN = 256; 59 const string FCHBAPort::FCSM_DRIVER_PATH = "/devices/pseudo/fcsm@0:fcsm"; 60 const string FCHBAPort::FCP_DRIVER_PATH = "/devices/pseudo/fcp@0:fcp"; 61 62 /* 63 * Interpret the error code in the fcio_t structure 64 * 65 * message must be at least MAX_FCIO_MSG_LEN in length. 66 */ 67 void 68 FCHBAPort::transportError(uint32_t fcio_errno, char *message) { 69 Trace log("transportError"); 70 string fcioErrorString; 71 if (message == NULL) { 72 log.internalError("NULL routine argument"); 73 return; 74 } 75 switch (fcio_errno) { 76 case (uint32_t)FC_FAILURE: 77 fcioErrorString = "general failure"; 78 break; 79 case (uint32_t)FC_FAILURE_SILENT: 80 fcioErrorString = "general failure but fail silently"; 81 break; 82 case FC_SUCCESS: 83 fcioErrorString = "successful completion"; 84 break; 85 case FC_CAP_ERROR: 86 fcioErrorString = "FCA capability error"; 87 break; 88 case FC_CAP_FOUND: 89 fcioErrorString = "FCA capability unsettable"; 90 break; 91 case FC_CAP_SETTABLE: 92 fcioErrorString = "FCA capability settable"; 93 break; 94 case FC_UNBOUND: 95 fcioErrorString = "unbound stuff"; 96 break; 97 case FC_NOMEM: 98 fcioErrorString = "allocation error"; 99 break; 100 case FC_BADPACKET: 101 fcioErrorString = "invalid packet specified/supplied"; 102 break; 103 case FC_OFFLINE: 104 fcioErrorString = "I/O resource unavailable"; 105 break; 106 case FC_OLDPORT: 107 fcioErrorString = "operation on non-loop port"; 108 break; 109 case FC_NO_MAP: 110 fcioErrorString = "requested map unavailable"; 111 break; 112 case FC_TRANSPORT_ERROR: 113 fcioErrorString = "unable to transport I/O"; 114 break; 115 case FC_ELS_FREJECT: 116 fcioErrorString = "ELS rejected by a Fabric"; 117 break; 118 case FC_ELS_PREJECT: 119 fcioErrorString = "ELS rejected by an N_port"; 120 break; 121 case FC_ELS_BAD: 122 fcioErrorString = "ELS rejected by FCA/fctl"; 123 break; 124 case FC_ELS_MALFORMED: 125 fcioErrorString = "poorly formed ELS request"; 126 break; 127 case FC_TOOMANY: 128 fcioErrorString = "resource request too large"; 129 break; 130 case FC_UB_BADTOKEN: 131 fcioErrorString = "invalid unsolicited buffer token"; 132 break; 133 case FC_UB_ERROR: 134 fcioErrorString = "invalid unsol buf request"; 135 break; 136 case FC_UB_BUSY: 137 fcioErrorString = "buffer already in use"; 138 break; 139 case FC_BADULP: 140 fcioErrorString = "Unknown ulp"; 141 break; 142 case FC_BADTYPE: 143 fcioErrorString = "ULP not registered to handle this FC4 type"; 144 break; 145 case FC_UNCLAIMED: 146 fcioErrorString = "request or data not claimed"; 147 break; 148 case FC_ULP_SAMEMODULE: 149 fcioErrorString = "module already in use"; 150 break; 151 case FC_ULP_SAMETYPE: 152 fcioErrorString = "FC4 module already in use"; 153 break; 154 case FC_ABORTED: 155 fcioErrorString = "request aborted"; 156 break; 157 case FC_ABORT_FAILED: 158 fcioErrorString = "abort request failed"; 159 break; 160 case FC_BADEXCHANGE: 161 fcioErrorString = "exchange doesn�t exist"; 162 break; 163 case FC_BADWWN: 164 fcioErrorString = "WWN not recognized"; 165 break; 166 case FC_BADDEV: 167 fcioErrorString = "device unrecognized"; 168 break; 169 case FC_BADCMD: 170 fcioErrorString = "invalid command issued"; 171 break; 172 case FC_BADOBJECT: 173 fcioErrorString = "invalid object requested"; 174 break; 175 case FC_BADPORT: 176 fcioErrorString = "invalid port specified"; 177 break; 178 case FC_NOTTHISPORT: 179 fcioErrorString = "resource not at this port"; 180 break; 181 case FC_PREJECT: 182 fcioErrorString = "reject at remote N_Port"; 183 break; 184 case FC_FREJECT: 185 fcioErrorString = "reject at remote Fabric"; 186 break; 187 case FC_PBUSY: 188 fcioErrorString = "remote N_Port busy"; 189 break; 190 case FC_FBUSY: 191 fcioErrorString = "remote Fabric busy"; 192 break; 193 case FC_ALREADY: 194 fcioErrorString = "already logged in"; 195 break; 196 case FC_LOGINREQ: 197 fcioErrorString = "login required"; 198 break; 199 case FC_RESETFAIL: 200 fcioErrorString = "reset failed"; 201 break; 202 case FC_INVALID_REQUEST: 203 fcioErrorString = "request is invalid"; 204 break; 205 case FC_OUTOFBOUNDS: 206 fcioErrorString = "port number is out of bounds"; 207 break; 208 case FC_TRAN_BUSY: 209 fcioErrorString = "command transport busy"; 210 break; 211 case FC_STATEC_BUSY: 212 fcioErrorString = "port driver currently busy"; 213 break; 214 case FC_DEVICE_BUSY: 215 fcioErrorString = "transport working on this device"; 216 break; 217 case FC_DEVICE_NOT_TGT: 218 fcioErrorString = "device is not a SCSI target"; 219 break; 220 default: 221 snprintf(message, MAX_FCIO_MSG_LEN, "Unknown error code 0x%x", 222 fcio_errno); 223 return; 224 } 225 snprintf(message, MAX_FCIO_MSG_LEN, "%s", fcioErrorString.c_str()); 226 } 227 228 static void 229 reportSense(struct scsi_extended_sense *sense, const char *routine) { 230 Trace log("reportSense"); 231 string msg; 232 if (!sense) { 233 log.internalError("NULL sense argument passed."); 234 return; 235 } 236 if (!routine) { 237 log.internalError("NULL routine argument passed."); 238 return; 239 } 240 log.genericIOError("SCSI FAILURE"); 241 switch (sense->es_key) { 242 case KEY_NO_SENSE: 243 msg = "No sense"; 244 break; 245 case KEY_RECOVERABLE_ERROR: 246 msg = "Recoverable error"; 247 break; 248 case KEY_NOT_READY: 249 msg = "Not ready"; 250 break; 251 case KEY_MEDIUM_ERROR: 252 msg = "Medium error"; 253 break; 254 case KEY_HARDWARE_ERROR: 255 msg = "Hardware error"; 256 break; 257 case KEY_ILLEGAL_REQUEST: 258 msg = "Illegal request"; 259 break; 260 case KEY_UNIT_ATTENTION: 261 msg = "Unit attention"; 262 break; 263 case KEY_DATA_PROTECT: 264 msg = "Data protect"; 265 break; 266 case KEY_BLANK_CHECK: 267 msg = "Blank check"; 268 break; 269 case KEY_VENDOR_UNIQUE: 270 msg = "Vendor Unique"; 271 break; 272 case KEY_COPY_ABORTED: 273 msg = "Copy aborted"; 274 break; 275 case KEY_ABORTED_COMMAND: 276 msg = "Aborted command"; 277 break; 278 case KEY_EQUAL: 279 msg = "Equal"; 280 break; 281 case KEY_VOLUME_OVERFLOW: 282 msg = "Volume overflow"; 283 break; 284 case KEY_MISCOMPARE: 285 msg = "Miscompare"; 286 break; 287 case KEY_RESERVED: 288 msg = "Reserved"; 289 break; 290 default: 291 msg = "unknown sense key"; 292 } 293 log.genericIOError("\tSense key: %s", msg.c_str()); 294 log.genericIOError("\tASC = 0x%x", sense->es_add_code); 295 log.genericIOError("\tASCQ = 0x%x", sense->es_qual_code); 296 } 297 298 /* 299 * Issue a SCSI pass thru command. 300 * Returns a scsi status value. 301 */ 302 void FCHBAPort::sendSCSIPassThru(struct fcp_scsi_cmd *fscsi, 303 HBA_UINT32 *responseSize, HBA_UINT32 *senseSize, 304 HBA_UINT8 *scsiStatus) { 305 Trace log("FCHBAPort::sendSCSIPassThru"); 306 int fd; 307 HBA_STATUS ret; 308 int count; 309 char fcioErrorString[MAX_FCIO_MSG_LEN] = ""; 310 hrtime_t start; 311 hrtime_t end; 312 int ioctl_errno; 313 double duration; 314 la_wwn_t wwn; 315 316 if (fscsi == NULL || 317 responseSize == NULL || 318 senseSize == NULL || 319 scsiStatus == NULL) { 320 throw BadArgumentException(); 321 } 322 323 memcpy(&wwn, fscsi->scsi_fc_pwwn.raw_wwn, sizeof (la_wwn_t)); 324 start = gethrtime(); 325 fscsi->scsi_fc_port_num = instanceNumber; 326 327 fd = HBA::_open(FCP_DRIVER_PATH, O_RDONLY | O_NDELAY); 328 count = 0; 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 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 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 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 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 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 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 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 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 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 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 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 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 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 */ 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 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 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 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 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 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 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