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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 27 #include "fcinfo.h" 28 #include <libintl.h> 29 30 struct lun { 31 uchar_t val[8]; 32 }; 33 34 typedef enum { 35 HBA_PORT, 36 REMOTE_PORT, 37 LOGICAL_UNIT 38 } resource_type; 39 40 typedef struct rep_luns_rsp { 41 uint32_t length; 42 uint32_t rsrvd; 43 struct lun lun[1]; 44 } rep_luns_rsp_t; 45 46 static int getTargetMapping(HBA_HANDLE, HBA_WWN myhbaPortWWN, 47 HBA_FCPTARGETMAPPINGV2 **mapping); 48 static int processHBA(HBA_HANDLE handle, HBA_ADAPTERATTRIBUTES attrs, 49 int portIndex, HBA_PORTATTRIBUTES port, HBA_FCPTARGETMAPPINGV2 *map, 50 int resourceType, int flags, int mode); 51 static void processRemotePort(HBA_HANDLE handle, HBA_WWN portWWN, 52 HBA_FCPTARGETMAPPINGV2 *map, int wwnCount, char **wwn_argv, int flags); 53 static void handleRemotePort(HBA_HANDLE handle, HBA_WWN portWWN, 54 HBA_WWN myRemotePortWWN, HBA_PORTATTRIBUTES *discPort); 55 static void printLinkStat(HBA_HANDLE handle, HBA_WWN hbaportWWN, 56 HBA_WWN destWWN); 57 static void handleScsiTarget(HBA_HANDLE handle, HBA_WWN hbaPortWWN, 58 HBA_WWN scsiTargetWWN, HBA_FCPTARGETMAPPINGV2 *map); 59 static int retrieveAttrs(HBA_HANDLE handle, HBA_WWN hbaPortWWN, 60 HBA_ADAPTERATTRIBUTES *attrs, HBA_PORTATTRIBUTES *port, int *portIndex); 61 static void searchDevice(discoveredDevice **devList, HBA_FCPSCSIENTRYV2 entry, 62 HBA_WWN initiatorPortWWN, HBA_HANDLE handle, boolean_t verbose); 63 64 /* 65 * This function retrieve the adapater attributes, port attributes, and 66 * portIndex for the given handle and hba port WWN. 67 * 68 * Arguments: 69 * handle an HBA_HANDLE to a adapter 70 * hbaPortWWN WWN of the port on the adapter to which to retrieve 71 * HBA_PORTATTRIBUTES from 72 * attrs pointer to a HBA_ADAPTERATTRIBUTES structure. Upon 73 * successful completion, this structure will be filled in 74 * port pointer to a HBA_PORTATTRIBUTES structure. Upon successful 75 * completion, this structure will be fill in 76 * portIndex the Index count of the port on the adapter that is 77 * associated with the WWN. 78 * 79 * Returns 80 * 0 successfully retrieve all information 81 * >0 otherwise 82 */ 83 static int 84 retrieveAttrs(HBA_HANDLE handle, HBA_WWN hbaPortWWN, 85 HBA_ADAPTERATTRIBUTES *attrs, HBA_PORTATTRIBUTES *port, int *portIndex) 86 { 87 HBA_STATUS status; 88 int portCtr; 89 int times; 90 91 /* argument checking */ 92 if (attrs == NULL || port == NULL || portIndex == NULL) { 93 fprintf(stderr, gettext("Error: Invalid arguments to " 94 "retreiveAttrs\n")); 95 return (1); 96 } 97 98 /* retrieve Adapter attributes */ 99 memset(attrs, 0, sizeof (HBA_ADAPTERATTRIBUTES)); 100 status = HBA_GetAdapterAttributes(handle, attrs); 101 times = 0; 102 while ((status == HBA_STATUS_ERROR_TRY_AGAIN || 103 status == HBA_STATUS_ERROR_BUSY) && 104 times++ < HBA_MAX_RETRIES) { 105 (void) sleep(1); 106 status = HBA_GetAdapterAttributes(handle, attrs); 107 if (status == HBA_STATUS_OK) { 108 break; 109 } 110 } 111 if (status != HBA_STATUS_OK) { 112 fprintf(stderr, gettext("Failed to get adapter " 113 "attributes handle(%d) Reason: "), handle); 114 printStatus(status); 115 fprintf(stderr, "\n"); 116 return (1); 117 } 118 119 /* 120 * find the corresponding port on the adapter and retrieve 121 * port attributes as well as the port index 122 */ 123 memset(port, 0, sizeof (HBA_PORTATTRIBUTES)); 124 for (portCtr = 0; portCtr < attrs->NumberOfPorts; portCtr++) { 125 if ((status = HBA_GetAdapterPortAttributes(handle, 126 portCtr, port)) != HBA_STATUS_OK) { 127 fprintf(stderr, 128 gettext("Error: Failed to get port (%d) " 129 "attributes reason: "), portCtr); 130 printStatus(status); 131 fprintf(stderr, "\n"); 132 return (1); 133 } 134 if (memcmp(hbaPortWWN.wwn, port->PortWWN.wwn, 135 sizeof (port->PortWWN.wwn)) == 0) { 136 break; 137 } 138 } 139 if (portCtr >= attrs->NumberOfPorts) { 140 /* 141 * not able to find corresponding port WWN 142 * returning an error 143 */ 144 *portIndex = 0; 145 return (1); 146 } 147 *portIndex = portCtr; 148 return (0); 149 } 150 151 /* 152 * This function retrieves target mapping information for the HBA port WWN. 153 * This function will allocate space for the mapping structure which the caller 154 * must free when they are finished 155 * 156 * Arguments: 157 * handle - a handle to a HBA that we will be processing 158 * hbaPortWWN - the port WWN for the HBA port to retrieve the mappings for 159 * mapping - a pointer to a pointer for the target mapping structure 160 * Upon successful completion of this function, *mapping will contain 161 * the target mapping information 162 * 163 * returns: 164 * 0 if successful 165 * 1 otherwise 166 */ 167 static int 168 getTargetMapping(HBA_HANDLE handle, HBA_WWN hbaPortWWN, 169 HBA_FCPTARGETMAPPINGV2 **mapping) 170 { 171 HBA_FCPTARGETMAPPINGV2 *map; 172 HBA_STATUS status; 173 int count; 174 175 /* argument sanity checking */ 176 if (mapping == NULL) { 177 fprintf(stderr, gettext("Internal Error: mapping is NULL")); 178 return (1); 179 } 180 *mapping = NULL; 181 if ((map = calloc(1, sizeof (HBA_FCPTARGETMAPPINGV2))) == NULL) { 182 fprintf(stderr, 183 gettext("Internal Error: Unable to calloc map")); 184 return (1); 185 } 186 status = HBA_GetFcpTargetMappingV2(handle, hbaPortWWN, map); 187 count = map->NumberOfEntries; 188 if (status == HBA_STATUS_ERROR_MORE_DATA) { 189 free(map); 190 if ((map = calloc(1, (sizeof (HBA_FCPSCSIENTRYV2)*(count-1)) + 191 sizeof (HBA_FCPTARGETMAPPINGV2))) == NULL) { 192 fprintf(stderr, 193 gettext("Unable to calloc map of size: %d"), count); 194 return (1); 195 } 196 map->NumberOfEntries = count; 197 status = HBA_GetFcpTargetMappingV2(handle, hbaPortWWN, map); 198 } 199 if (status != HBA_STATUS_OK) { 200 fprintf(stderr, 201 gettext("Error: Unable to get Target Mapping\n")); 202 printStatus(status); 203 fprintf(stderr, "\n"); 204 free(map); 205 return (1); 206 } 207 *mapping = map; 208 return (0); 209 } 210 211 /* 212 * This function handles the remoteport object. It will issue a report lun 213 * to determine whether it is a scsi-target and then print the information. 214 * 215 * Arguments: 216 * handle - a handle to a HBA that we will be processing 217 * portWWN - the port WWN for the HBA port we will be issuing the SCSI 218 * ReportLUNS through 219 * remotePortWWN - the port WWN we will be issuing the report lun call to 220 * discPort - PORTATTRIBUTES structure for the remotePortWWN 221 */ 222 static void 223 handleRemotePort(HBA_HANDLE handle, HBA_WWN portWWN, HBA_WWN remotePortWWN, 224 HBA_PORTATTRIBUTES *discPort) 225 { 226 HBA_STATUS status; 227 int scsiTargetType; 228 uchar_t raw_luns[LUN_LENGTH]; 229 HBA_UINT32 responseSize = LUN_LENGTH; 230 struct scsi_extended_sense sense; 231 HBA_UINT32 senseSize = sizeof (struct scsi_extended_sense); 232 HBA_UINT8 rep_luns_status; 233 234 /* argument checking */ 235 if (discPort == NULL) { 236 return; 237 } 238 239 memset(raw_luns, 0, sizeof (raw_luns)); 240 /* going to issue a report lun to check if this is a scsi-target */ 241 status = HBA_ScsiReportLUNsV2(handle, portWWN, remotePortWWN, 242 (void *)raw_luns, &responseSize, &rep_luns_status, 243 (void *)&sense, &senseSize); 244 if (status == HBA_STATUS_OK) { 245 scsiTargetType = SCSI_TARGET_TYPE_YES; 246 } else if (status == HBA_STATUS_ERROR_NOT_A_TARGET) { 247 scsiTargetType = SCSI_TARGET_TYPE_NO; 248 } else { 249 scsiTargetType = SCSI_TARGET_TYPE_UNKNOWN; 250 } 251 printDiscoPortInfo(discPort, scsiTargetType); 252 } 253 254 /* 255 * This function will issue the RLS and print out the port statistics for 256 * the given destWWN 257 * 258 * Arguments 259 * handle - a handle to a HBA that we will be processing 260 * hbaPortWWN - the hba port WWN through which the RLS will be sent 261 * destWWN - the remote port to which the RLS will be sent 262 */ 263 static void 264 printLinkStat(HBA_HANDLE handle, HBA_WWN hbaPortWWN, HBA_WWN destWWN) 265 { 266 HBA_STATUS status; 267 fc_rls_acc_t rls_payload; 268 uint32_t rls_payload_size; 269 270 memset(&rls_payload, 0, sizeof (rls_payload)); 271 rls_payload_size = sizeof (rls_payload); 272 status = HBA_SendRLS(handle, hbaPortWWN, destWWN, 273 &rls_payload, &rls_payload_size); 274 if (status != HBA_STATUS_OK) { 275 fprintf(stderr, gettext("Error: SendRLS failed for %016llx\n"), 276 wwnConversion(destWWN.wwn)); 277 } else { 278 printPortStat(&rls_payload); 279 } 280 } 281 282 int 283 printHBANPIVPortInfo(HBA_HANDLE handle, int portindex) 284 { 285 HBA_PORTNPIVATTRIBUTES portattrs; 286 HBA_NPIVATTRIBUTES npivattrs; 287 HBA_STATUS status; 288 int index; 289 int times = 0; 290 291 status = Sun_HBA_GetPortNPIVAttributes(handle, portindex, &portattrs); 292 while (status == HBA_STATUS_ERROR_TRY_AGAIN || 293 status == HBA_STATUS_ERROR_BUSY) { 294 (void) sleep(1); 295 status = Sun_HBA_GetPortNPIVAttributes( 296 handle, portindex, &portattrs); 297 if (times++ > HBA_MAX_RETRIES) { 298 break; 299 } 300 } 301 302 if (status == HBA_STATUS_ERROR_NOT_SUPPORTED) { 303 fprintf(stdout, gettext("\tNPIV Not Supported\n")); 304 return (0); 305 } 306 307 if (status != HBA_STATUS_OK) { 308 fprintf(stderr, 309 gettext("Error: Failed to get port (%d) " 310 "npiv attributes reason: "), portindex); 311 printStatus(status); 312 fprintf(stderr, "\n"); 313 return (1); 314 } 315 if (portattrs.MaxNumberOfNPIVPorts) { 316 fprintf(stdout, gettext("\tMax NPIV Ports: %d\n"), 317 portattrs.MaxNumberOfNPIVPorts); 318 } else { 319 fprintf(stdout, gettext("\tNPIV Not Supported\n")); 320 return (0); 321 } 322 fprintf(stdout, gettext("\tNPIV port list:\n")); 323 for (index = 0; index < portattrs.NumberOfNPIVPorts; index++) { 324 int times = 0; 325 status = Sun_HBA_GetNPIVPortInfo(handle, 326 portindex, index, &npivattrs); 327 while (status == HBA_STATUS_ERROR_TRY_AGAIN || 328 status == HBA_STATUS_ERROR_BUSY) { 329 (void) sleep(1); 330 status = Sun_HBA_GetNPIVPortInfo(handle, 331 portindex, index, &npivattrs); 332 if (times++ > HBA_MAX_RETRIES) { 333 break; 334 } 335 } 336 337 if (status != HBA_STATUS_OK) { 338 fprintf(stderr, 339 gettext("Error: Failed to get npiv port (%d) " 340 "attributes reason: "), index); 341 printStatus(status); 342 fprintf(stderr, "\n"); 343 return (1); 344 } else { 345 fprintf(stdout, 346 gettext("\t Virtual Port%d:\n"), index+1); 347 fprintf(stdout, gettext("\t\tNode WWN: %016llx\n"), 348 wwnConversion(npivattrs.NodeWWN.wwn)); 349 fprintf(stdout, gettext("\t\tPort WWN: %016llx\n"), 350 wwnConversion(npivattrs.PortWWN.wwn)); 351 } 352 } 353 return (0); 354 } 355 356 /* 357 * This function will process hba port, remote port and scsi-target information 358 * for the given handle. 359 * 360 * Arguments: 361 * handle - a handle to a HBA that we will be processing 362 * resourceType - resourceType flag 363 * possible values include: HBA_PORT, REMOTE_PORT 364 * flags - represents options passed in by the user 365 * 366 * Return Value: 367 * 0 sucessfully processed handle 368 * 1 error has occured 369 */ 370 static int 371 processHBA(HBA_HANDLE handle, HBA_ADAPTERATTRIBUTES attrs, int portIndex, 372 HBA_PORTATTRIBUTES port, HBA_FCPTARGETMAPPINGV2 *map, 373 int resourceType, int flags, int mode) 374 { 375 HBA_PORTATTRIBUTES discPort; 376 HBA_STATUS status; 377 int discPortCount; 378 379 if (resourceType == HBA_PORT) { 380 if ((flags & PRINT_FCOE) == PRINT_FCOE && 381 attrs.VendorSpecificID != 0xFC0E) { 382 return (0); 383 } 384 printHBAPortInfo(&port, &attrs, mode); 385 if ((flags & PRINT_LINKSTAT) == PRINT_LINKSTAT) { 386 printLinkStat(handle, port.PortWWN, port.PortWWN); 387 } 388 return (0); 389 } 390 /* 391 * process each of the remote targets from this hba port 392 */ 393 for (discPortCount = 0; 394 discPortCount < port.NumberofDiscoveredPorts; 395 discPortCount++) { 396 status = HBA_GetDiscoveredPortAttributes(handle, 397 portIndex, discPortCount, &discPort); 398 if (status != HBA_STATUS_OK) { 399 fprintf(stderr, 400 gettext("Failed to get discovered port (%d)" 401 " attributes reason :"), discPortCount); 402 printStatus(status); 403 fprintf(stderr, "\n"); 404 continue; 405 } 406 if (resourceType == REMOTE_PORT) { 407 handleRemotePort(handle, port.PortWWN, discPort.PortWWN, 408 &discPort); 409 if ((flags & PRINT_LINKSTAT) == PRINT_LINKSTAT) { 410 printLinkStat(handle, port.PortWWN, 411 discPort.PortWWN); 412 } 413 if ((flags & PRINT_SCSI_TARGET) == PRINT_SCSI_TARGET) { 414 handleScsiTarget(handle, port.PortWWN, 415 discPort.PortWWN, map); 416 } 417 } 418 } 419 return (0); 420 } 421 422 /* 423 * This function will process remote port information for the given handle. 424 * 425 * Arguments: 426 * handle - a handle to a HBA that we will be processing 427 * portWWN - the port WWN for the HBA port we will be issuing the SCSI 428 * ReportLUNS through 429 * wwnCount - the number of wwns in wwn_argv 430 * wwn_argv - argument vector of WWNs 431 */ 432 static void 433 processRemotePort(HBA_HANDLE handle, HBA_WWN portWWN, 434 HBA_FCPTARGETMAPPINGV2 *map, int wwnCount, char **wwn_argv, int flags) 435 { 436 int remote_wwn_counter; 437 uint64_t remotePortWWN; 438 HBA_WWN myremotePortWWN; 439 HBA_PORTATTRIBUTES discPort; 440 HBA_STATUS status; 441 442 for (remote_wwn_counter = 0; 443 remote_wwn_counter < wwnCount; 444 remote_wwn_counter++) { 445 int times = 0; 446 sscanf(wwn_argv[remote_wwn_counter], "%016llx", 447 &remotePortWWN); 448 remotePortWWN = htonll(remotePortWWN); 449 memcpy(myremotePortWWN.wwn, &remotePortWWN, 450 sizeof (remotePortWWN)); 451 memset(&discPort, 0, sizeof (discPort)); 452 status = HBA_GetPortAttributesByWWN(handle, myremotePortWWN, 453 &discPort); 454 while (status == HBA_STATUS_ERROR_TRY_AGAIN || 455 status == HBA_STATUS_ERROR_BUSY) { 456 (void) sleep(1); 457 status = HBA_GetPortAttributesByWWN(handle, 458 myremotePortWWN, &discPort); 459 if (times++ > HBA_MAX_RETRIES) { 460 break; 461 } 462 } 463 if (status != HBA_STATUS_OK) { 464 fprintf(stderr, gettext("HBA_GetPortAttributesByWWN " 465 "failed: reason: ")); 466 printStatus(status); 467 fprintf(stderr, "\n"); 468 continue; 469 } 470 handleRemotePort(handle, portWWN, myremotePortWWN, &discPort); 471 if ((flags & PRINT_LINKSTAT) == PRINT_LINKSTAT) { 472 printLinkStat(handle, portWWN, myremotePortWWN); 473 } 474 if ((flags & PRINT_SCSI_TARGET) == PRINT_SCSI_TARGET) { 475 handleScsiTarget(handle, portWWN, 476 myremotePortWWN, map); 477 } 478 } 479 } 480 481 /* 482 * This function handles printing Scsi target information for remote ports 483 * 484 * Arguments: 485 * handle - a handle to a HBA that we will be processing 486 * hbaPortWWN - the port WWN for the HBA port through which the SCSI call 487 * is being sent 488 * scsiTargetWWN - target port WWN of the remote target the SCSI call is 489 * being sent to 490 * map - a pointer to the target mapping structure for the given HBA port 491 */ 492 static void 493 handleScsiTarget(HBA_HANDLE handle, HBA_WWN hbaPortWWN, HBA_WWN scsiTargetWWN, 494 HBA_FCPTARGETMAPPINGV2 *map) 495 { 496 HBA_STATUS status; 497 struct scsi_inquiry inq; 498 struct scsi_extended_sense sense; 499 HBA_UINT32 responseSize, senseSize = 0; 500 HBA_UINT8 inq_status; 501 uchar_t raw_luns[DEFAULT_LUN_LENGTH], *lun_string; 502 HBA_UINT8 rep_luns_status; 503 rep_luns_rsp_t *lun_resp; 504 uint64_t fcLUN; 505 int lunNum, numberOfLun, lunCount, count; 506 uint32_t lunlength, tmp_lunlength; 507 508 responseSize = DEFAULT_LUN_LENGTH; 509 senseSize = sizeof (struct scsi_extended_sense); 510 memset(&sense, 0, sizeof (sense)); 511 status = HBA_ScsiReportLUNsV2(handle, hbaPortWWN, 512 scsiTargetWWN, (void *)raw_luns, &responseSize, 513 &rep_luns_status, (void *)&sense, &senseSize); 514 /* 515 * if HBA_STATUS_ERROR_NOT_A_TARGET is return, we can assume this is 516 * a remote HBA and move on 517 */ 518 if (status == HBA_STATUS_ERROR_NOT_A_TARGET) { 519 return; 520 } else if (status != HBA_STATUS_OK) { 521 fprintf(stderr, gettext("Error has occured. " 522 "HBA_ScsiReportLUNsV2 failed. reason ")); 523 printStatus(status); 524 fprintf(stderr, "\n"); 525 return; 526 } 527 lun_resp = (rep_luns_rsp_t *)raw_luns; 528 memcpy(&tmp_lunlength, &(lun_resp->length), sizeof (tmp_lunlength)); 529 lunlength = htonl(tmp_lunlength); 530 memcpy(&numberOfLun, &lunlength, sizeof (numberOfLun)); 531 for (lunCount = 0; lunCount < (numberOfLun / 8); lunCount++) { 532 /* 533 * now issue standard inquiry to get Vendor 534 * and product information 535 */ 536 responseSize = sizeof (struct scsi_inquiry); 537 senseSize = sizeof (struct scsi_extended_sense); 538 memset(&inq, 0, sizeof (struct scsi_inquiry)); 539 memset(&sense, 0, sizeof (sense)); 540 fcLUN = ntohll(wwnConversion(lun_resp->lun[lunCount].val)); 541 status = HBA_ScsiInquiryV2( 542 handle, 543 hbaPortWWN, 544 scsiTargetWWN, 545 fcLUN, 546 0, /* EVPD */ 547 0, 548 &inq, &responseSize, 549 &inq_status, 550 &sense, &senseSize); 551 if (status != HBA_STATUS_OK) { 552 fprintf(stderr, gettext("Not able to issue Inquiry.\n")); 553 printStatus(status); 554 fprintf(stderr, "\n"); 555 strcpy(inq.inq_vid, "Unknown"); 556 strcpy(inq.inq_pid, "Unknown"); 557 } 558 if (map != NULL) { 559 for (count = 0; count < map->NumberOfEntries; count++) { 560 if ((memcmp(map->entry[count].FcpId.PortWWN.wwn, 561 scsiTargetWWN.wwn, 562 sizeof (scsiTargetWWN.wwn)) 563 == 0) && 564 (memcmp(&(map->entry[count].FcpId.FcpLun), 565 &fcLUN, sizeof (fcLUN)) == 0)) { 566 printLUNInfo(&inq, 567 map->entry[count].ScsiId.ScsiOSLun, 568 map->entry[count].ScsiId.OSDeviceName); 569 break; 570 } 571 } 572 if (count == map->NumberOfEntries) { 573 lun_string = lun_resp->lun[lunCount].val; 574 lunNum = ((lun_string[0] & 0x3F) << 8) | 575 lun_string[1]; 576 printLUNInfo(&inq, lunNum, "Unknown"); 577 } 578 } else { 579 /* Not able to get any target mapping information */ 580 lun_string = lun_resp->lun[lunCount].val; 581 lunNum = ((lun_string[0] & 0x3F) << 8) | 582 lun_string[1]; 583 printLUNInfo(&inq, lunNum, "Unknown"); 584 } 585 } 586 } 587 588 /* 589 * function to handle the list remoteport command 590 * 591 * Arguments: 592 * wwnCount - the number of wwns in wwn_argv 593 * if wwnCount == 0, then print information on all 594 * remote ports. wwn_argv will not be used in this case 595 * if wwnCount > 0, then print information for the WWNs 596 * given in wwn_argv 597 * wwn_argv - argument vector of WWNs 598 * options - any options specified by the caller 599 * 600 * returns: 601 * 0 if successful 602 * 1 otherwise 603 */ 604 int 605 fc_util_list_remoteport(int wwnCount, char **wwn_argv, cmdOptions_t *options) 606 { 607 HBA_STATUS status; 608 HBA_FCPTARGETMAPPINGV2 *map = NULL; 609 HBA_PORTATTRIBUTES port; 610 HBA_ADAPTERATTRIBUTES attrs; 611 HBA_HANDLE handle; 612 uint64_t hbaPortWWN; 613 HBA_WWN myhbaPortWWN; 614 int processHBA_flags = 0, portCount = 0; 615 int mode; 616 617 /* grab the hba port wwn from the -p option */ 618 for (; options->optval; options++) { 619 if (options->optval == 'p') { 620 sscanf(options->optarg, "%016llx", 621 &hbaPortWWN); 622 } else if (options->optval == 's') { 623 processHBA_flags |= PRINT_SCSI_TARGET; 624 } else if (options->optval == 'l') { 625 processHBA_flags |= PRINT_LINKSTAT; 626 } else { 627 fprintf(stderr, gettext("Error: Illegal option: %c.\n"), 628 options->optval); 629 return (1); 630 } 631 } 632 /* 633 * -h option was not specified, this should not happen either. 634 * cmdparse should catch this problem, but checking anyways 635 */ 636 if (hbaPortWWN == 0) { 637 fprintf(stderr, 638 gettext("Error: -p option was not specified.\n")); 639 return (1); 640 } 641 if ((status = HBA_LoadLibrary()) != HBA_STATUS_OK) { 642 fprintf(stderr, 643 gettext("Failed to load FC-HBA common library\n")); 644 printStatus(status); 645 fprintf(stderr, "\n"); 646 return (1); 647 } 648 hbaPortWWN = htonll(hbaPortWWN); 649 memcpy(myhbaPortWWN.wwn, &hbaPortWWN, sizeof (hbaPortWWN)); 650 if ((status = HBA_OpenAdapterByWWN(&handle, myhbaPortWWN)) 651 != HBA_STATUS_OK) { 652 status = Sun_HBA_OpenTgtAdapterByWWN(&handle, myhbaPortWWN); 653 if (status != HBA_STATUS_OK) { 654 fprintf(stderr, 655 gettext("Error: Failed to open adapter port. Reason ")); 656 printStatus(status); 657 fprintf(stderr, "\n"); 658 HBA_FreeLibrary(); 659 return (1); 660 } else { 661 if ((processHBA_flags & PRINT_SCSI_TARGET) == 662 PRINT_SCSI_TARGET) { 663 fprintf(stderr, gettext( 664 "Error: Unsupported option for target mode: %c.\n"), 665 's'); 666 HBA_FreeLibrary(); 667 return (1); 668 } 669 mode = TARGET_MODE; 670 } 671 } else { 672 mode = INITIATOR_MODE; 673 } 674 675 if ((processHBA_flags & PRINT_SCSI_TARGET) == PRINT_SCSI_TARGET) { 676 getTargetMapping(handle, myhbaPortWWN, &map); 677 } 678 if (wwnCount == 0) { 679 /* get adapater attributes for the given handle */ 680 memset(&attrs, 0, sizeof (attrs)); 681 memset(&port, 0, sizeof (port)); 682 if (retrieveAttrs(handle, myhbaPortWWN, &attrs, &port, 683 &portCount) != 0) { 684 if (map != NULL) { 685 free(map); 686 } 687 HBA_CloseAdapter(handle); 688 HBA_FreeLibrary(); 689 return (1); 690 } 691 processHBA(handle, attrs, portCount, port, map, REMOTE_PORT, 692 processHBA_flags, mode); 693 } else { 694 processRemotePort(handle, myhbaPortWWN, map, wwnCount, 695 wwn_argv, processHBA_flags); 696 } 697 if (map != NULL) { 698 free(map); 699 } 700 HBA_CloseAdapter(handle); 701 HBA_FreeLibrary(); 702 return (0); 703 } 704 705 /* 706 * process the hbaport object 707 * 708 * Arguments: 709 * wwnCount - count of the number of WWNs in wwn_argv 710 * if wwnCount > 0, then we will only print information for 711 * the hba ports listed in wwn_argv 712 * if wwnCount == 0, then we will print information on all hba ports 713 * wwn_argv - argument array of hba port WWNs 714 * options - any options specified by the caller 715 * 716 * returns: 717 * 0 if successful 718 * 1 otherwise 719 */ 720 int 721 fc_util_list_hbaport(int wwnCount, char **wwn_argv, cmdOptions_t *options) 722 { 723 int port_wwn_counter, numAdapters = 0, numTgtAdapters = 0, i; 724 HBA_STATUS status; 725 char adapterName[256]; 726 HBA_HANDLE handle; 727 uint64_t hbaWWN; 728 HBA_WWN myWWN; 729 int processHBA_flags = 0; 730 HBA_PORTATTRIBUTES port; 731 HBA_ADAPTERATTRIBUTES attrs; 732 int portIndex = 0, err_cnt = 0; 733 int mode; 734 735 /* process each of the options */ 736 for (; options->optval; options++) { 737 if (options->optval == 'l') { 738 processHBA_flags |= PRINT_LINKSTAT; 739 } else if (options->optval == 'i') { 740 processHBA_flags |= PRINT_INITIATOR; 741 } else if (options->optval == 't') { 742 processHBA_flags |= PRINT_TARGET; 743 } else if (options->optval == 'e') { 744 processHBA_flags |= PRINT_FCOE; 745 } 746 } 747 748 /* 749 * Print both initiator and target if no initiator/target flag 750 * specified. 751 */ 752 if (((processHBA_flags & PRINT_INITIATOR) == 0) && 753 ((processHBA_flags & PRINT_TARGET) == 0)) { 754 processHBA_flags |= PRINT_INITIATOR | PRINT_TARGET; 755 } 756 757 if ((status = HBA_LoadLibrary()) != HBA_STATUS_OK) { 758 fprintf(stderr, 759 gettext("Failed to load FC-HBA common library\n")); 760 printStatus(status); 761 fprintf(stderr, "\n"); 762 return (1); 763 } 764 if (wwnCount > 0) { 765 /* list only ports given in wwn_argv */ 766 for (port_wwn_counter = 0; 767 port_wwn_counter < wwnCount; 768 port_wwn_counter++) { 769 sscanf(wwn_argv[port_wwn_counter], "%016llx", &hbaWWN); 770 hbaWWN = htonll(hbaWWN); 771 memcpy(myWWN.wwn, &hbaWWN, sizeof (hbaWWN)); 772 /* first check to see if it is an initiator port. */ 773 if ((processHBA_flags & PRINT_INITIATOR) == 774 PRINT_INITIATOR) { 775 int times = 0; 776 status = HBA_OpenAdapterByWWN(&handle, myWWN); 777 while (status == HBA_STATUS_ERROR_TRY_AGAIN || 778 status == HBA_STATUS_ERROR_BUSY) { 779 (void) sleep(1); 780 status = HBA_OpenAdapterByWWN(&handle, myWWN); 781 if (times++ > HBA_MAX_RETRIES) { 782 break; 783 } 784 } 785 if (status != HBA_STATUS_OK) { 786 /* now see if it is a target mode FC port */ 787 if ((processHBA_flags & PRINT_TARGET) == 788 PRINT_TARGET) { 789 status = 790 Sun_HBA_OpenTgtAdapterByWWN(&handle, myWWN); 791 if (status != HBA_STATUS_OK) { 792 fprintf(stderr, 793 gettext( 794 "Error: HBA port %s: not found\n"), 795 wwn_argv[port_wwn_counter]); 796 err_cnt++; 797 continue; 798 } else { 799 /* set the port mode. */ 800 mode = TARGET_MODE; 801 } 802 } else { 803 fprintf(stderr, 804 gettext( 805 "Error: HBA port %s: not found\n"), 806 wwn_argv[port_wwn_counter]); 807 err_cnt++; 808 continue; 809 } 810 } else { 811 /* set the port mode. */ 812 mode = INITIATOR_MODE; 813 } 814 /* try target mode discovery if print target is set. */ 815 } else if ((processHBA_flags & PRINT_TARGET) == 816 PRINT_TARGET) { 817 status = 818 Sun_HBA_OpenTgtAdapterByWWN(&handle, myWWN); 819 if (status != HBA_STATUS_OK) { 820 fprintf(stderr, gettext( 821 "Error: HBA port %s: not found\n"), 822 wwn_argv[port_wwn_counter]); 823 err_cnt++; 824 continue; 825 } else { 826 /* set the port mode. */ 827 mode = TARGET_MODE; 828 } 829 } else { 830 /* should not get here. */ 831 fprintf(stderr, gettext( 832 "Error: HBA port %s: not found\n"), 833 wwn_argv[port_wwn_counter]); 834 err_cnt++; 835 continue; 836 } 837 memset(&attrs, 0, sizeof (attrs)); 838 memset(&port, 0, sizeof (port)); 839 if (retrieveAttrs(handle, myWWN, &attrs, &port, 840 &portIndex) != 0) { 841 HBA_CloseAdapter(handle); 842 continue; 843 } 844 processHBA(handle, attrs, portIndex, port, NULL, 845 HBA_PORT, processHBA_flags, mode); 846 if ((processHBA_flags & PRINT_FCOE) != PRINT_FCOE && 847 attrs.VendorSpecificID != 0xFC0E && 848 printHBANPIVPortInfo(handle, portIndex) != 0) { 849 err_cnt++; 850 } 851 HBA_CloseAdapter(handle); 852 } 853 } else { 854 /* 855 * if PRINT_INITIATOR is specified, get the list of initiator 856 * mod port. 857 */ 858 if ((processHBA_flags & PRINT_INITIATOR) == PRINT_INITIATOR) { 859 numAdapters = HBA_GetNumberOfAdapters(); 860 if ((numAdapters == 0) && 861 ((processHBA_flags & ~PRINT_INITIATOR) == 0)) { 862 fprintf(stdout, gettext("No Adapters Found.\n")); 863 } 864 for (i = 0; i < numAdapters; i++) { 865 int times = 0; 866 status = HBA_GetAdapterName(i, adapterName); 867 if (status != HBA_STATUS_OK) { 868 fprintf(stderr, gettext( 869 "failed to get adapter %d. Reason: "), i); 870 printStatus(status); 871 fprintf(stderr, "\n"); 872 continue; 873 } 874 if ((handle = HBA_OpenAdapter(adapterName)) == 0) { 875 fprintf(stderr, gettext( 876 "Failed to open adapter %s.\n"), 877 adapterName); 878 continue; 879 } 880 /* get adapater attributes for the given handle */ 881 memset(&attrs, 0, sizeof (attrs)); 882 status = 883 Sun_HBA_NPIVGetAdapterAttributes(handle, 884 &attrs); 885 while ((status == HBA_STATUS_ERROR_TRY_AGAIN || 886 status == HBA_STATUS_ERROR_BUSY) && 887 times++ < HBA_MAX_RETRIES) { 888 (void) sleep(1); 889 status = 890 Sun_HBA_NPIVGetAdapterAttributes(handle, 891 &attrs); 892 if (status == HBA_STATUS_OK) { 893 break; 894 } 895 } 896 if (status != HBA_STATUS_OK) { 897 fprintf(stderr, 898 gettext("Failed to get adapter attributes " 899 "handle(%d) Reason: "), handle); 900 printStatus(status); 901 fprintf(stderr, "\n"); 902 HBA_CloseAdapter(handle); 903 continue; 904 } 905 906 /* process each port on the given adatpter */ 907 for (portIndex = 0; 908 portIndex < attrs.NumberOfPorts; 909 portIndex++) { 910 memset(&port, 0, sizeof (port)); 911 if ((status = HBA_GetAdapterPortAttributes( 912 handle, portIndex, &port)) 913 != HBA_STATUS_OK) { 914 /* 915 * not able to get port attributes. 916 * print out error * message and move 917 * on to the next port 918 */ 919 fprintf(stderr, 920 gettext("Error: Failed to get port " 921 "(%d) attributes reason: "), 922 portIndex); 923 printStatus(status); 924 fprintf(stderr, "\n"); 925 continue; 926 } 927 processHBA(handle, attrs, portIndex, port, 928 NULL, HBA_PORT, processHBA_flags, 929 INITIATOR_MODE); 930 if ((processHBA_flags & PRINT_FCOE) != 931 PRINT_FCOE && 932 attrs.VendorSpecificID != 0xFC0E && 933 printHBANPIVPortInfo(handle, 934 portIndex) != 0) { 935 err_cnt++; 936 } 937 } 938 HBA_CloseAdapter(handle); 939 } 940 } 941 942 /* 943 * Get the info on the target mode FC port if PRINT_TARGET 944 * is specified. 945 */ 946 if ((processHBA_flags & PRINT_TARGET) == PRINT_TARGET) { 947 numTgtAdapters = Sun_HBA_GetNumberOfTgtAdapters(); 948 if (numTgtAdapters == 0 && numAdapters == 0) { 949 fprintf(stdout, 950 gettext("No Adapters Found.\n")); 951 } 952 for (i = 0; i < numTgtAdapters; i++) { 953 status = Sun_HBA_GetTgtAdapterName(i, adapterName); 954 if (status != HBA_STATUS_OK) { 955 fprintf(stderr, gettext( 956 "failed to get adapter %d. Reason: "), i); 957 printStatus(status); 958 fprintf(stderr, "\n"); 959 continue; 960 } 961 if ((handle = Sun_HBA_OpenTgtAdapter(adapterName)) 962 == 0) { 963 fprintf(stderr, gettext( 964 "Failed to open adapter %s.\n"), adapterName); 965 continue; 966 } 967 /* get adapater attributes for the given handle */ 968 memset(&attrs, 0, sizeof (attrs)); 969 if ((status = HBA_GetAdapterAttributes(handle, &attrs)) 970 != HBA_STATUS_OK) { 971 fprintf(stderr, 972 gettext("Failed to get target mode adapter" 973 "attributes handle(%d) Reason: "), 974 handle); 975 printStatus(status); 976 fprintf(stderr, "\n"); 977 continue; 978 } 979 980 /* process each port on the given adatpter */ 981 for (portIndex = 0; 982 portIndex < attrs.NumberOfPorts; 983 portIndex++) { 984 memset(&port, 0, sizeof (port)); 985 if ((status = HBA_GetAdapterPortAttributes( 986 handle, portIndex, &port)) 987 != HBA_STATUS_OK) { 988 /* 989 * not able to get port attributes. 990 * print out error * message and move 991 * on to the next port 992 */ 993 fprintf(stderr, 994 gettext("Error: Failed to get port " 995 "(%d) attributes reason: "), 996 portIndex); 997 printStatus(status); 998 fprintf(stderr, "\n"); 999 continue; 1000 } 1001 processHBA(handle, attrs, portIndex, port, 1002 NULL, HBA_PORT, processHBA_flags, 1003 TARGET_MODE); 1004 } 1005 HBA_CloseAdapter(handle); 1006 } 1007 } 1008 } 1009 1010 HBA_FreeLibrary(); 1011 1012 /* 1013 * print additional error msg for partial failure when more than 1014 * one wwn is specified. 1015 */ 1016 if (err_cnt != 0) { 1017 if (wwnCount > 1) { 1018 if (err_cnt == wwnCount) { 1019 fprintf(stderr, gettext( 1020 "Error: All specified HBA ports are not found\n")); 1021 } else { 1022 fprintf(stderr, gettext( 1023 "Error: Some of specified HBA ports are not found\n")); 1024 } 1025 } 1026 return (1); 1027 } 1028 1029 return (0); 1030 } 1031 1032 /* 1033 * Search the existing device list 1034 * 1035 * Take one of two actions: 1036 * 1037 * Add an entry if an entry doesn't exist 1038 * Add WWN data to it if an entry does exist 1039 * 1040 * Arguments: 1041 * devList - OS device path list 1042 * map - target mapping data 1043 * index - index into target mapping data 1044 * initiatorPortWWN - HBA port WWN 1045 * verbose - boolean indicating whether to get additional data 1046 * 1047 * returns: 1048 * none 1049 */ 1050 static void 1051 searchDevice(discoveredDevice **devList, HBA_FCPSCSIENTRYV2 entry, 1052 HBA_WWN initiatorPortWWN, HBA_HANDLE handle, boolean_t verbose) 1053 { 1054 discoveredDevice *discoveredDevList, *newDevice; 1055 portWWNList *WWNList, *newWWN; 1056 tgtPortWWNList *newTgtWWN; 1057 boolean_t foundDevice = B_FALSE, foundWWN; 1058 struct scsi_inquiry inq; 1059 struct scsi_extended_sense sense; 1060 HBA_UINT32 responseSize, senseSize = 0; 1061 HBA_UINT8 inq_status; 1062 HBA_STATUS status; 1063 1064 for (discoveredDevList = *devList; discoveredDevList != NULL; 1065 discoveredDevList = discoveredDevList->next) { 1066 if (strcmp(entry.ScsiId.OSDeviceName, 1067 discoveredDevList->OSDeviceName) == 0) { 1068 /* 1069 * if only device names are requested, 1070 * no reason to go any further 1071 */ 1072 if (verbose == B_FALSE) { 1073 return; 1074 } 1075 foundDevice = B_TRUE; 1076 break; 1077 } 1078 } 1079 if (foundDevice == B_TRUE) { 1080 /* add initiator Port WWN if it doesn't exist */ 1081 for (WWNList = discoveredDevList->HBAPortWWN, 1082 foundWWN = B_FALSE; WWNList != NULL; 1083 WWNList = WWNList->next) { 1084 if (memcmp((void *)&(WWNList->portWWN), 1085 (void *)&initiatorPortWWN, 1086 sizeof (HBA_WWN)) == 0) { 1087 foundWWN = B_TRUE; 1088 break; 1089 } 1090 } 1091 if (discoveredDevList->inqSuccess == B_FALSE) { 1092 responseSize = sizeof (struct scsi_inquiry); 1093 senseSize = sizeof (struct scsi_extended_sense); 1094 memset(&inq, 0, sizeof (struct scsi_inquiry)); 1095 memset(&sense, 0, sizeof (sense)); 1096 status = HBA_ScsiInquiryV2( 1097 handle, 1098 initiatorPortWWN, 1099 entry.FcpId.PortWWN, 1100 entry.FcpId.FcpLun, 1101 0, /* CDB Byte 1 */ 1102 0, /* CDB Byte 2 */ 1103 &inq, &responseSize, 1104 &inq_status, 1105 &sense, &senseSize); 1106 if (status == HBA_STATUS_OK) { 1107 memcpy(discoveredDevList->VID, inq.inq_vid, 1108 sizeof (discoveredDevList->VID)); 1109 memcpy(discoveredDevList->PID, inq.inq_pid, 1110 sizeof (discoveredDevList->PID)); 1111 discoveredDevList->dType = inq.inq_dtype; 1112 discoveredDevList->inqSuccess = B_TRUE; 1113 } 1114 } 1115 1116 if (foundWWN == B_FALSE) { 1117 newWWN = (portWWNList *)calloc(1, sizeof (portWWNList)); 1118 if (newWWN == NULL) { 1119 perror("Out of memory"); 1120 exit(1); 1121 } 1122 1123 /* insert at head */ 1124 newWWN->next = discoveredDevList->HBAPortWWN; 1125 discoveredDevList->HBAPortWWN = newWWN; 1126 memcpy((void *)&(newWWN->portWWN), 1127 (void *)&initiatorPortWWN, 1128 sizeof (newWWN->portWWN)); 1129 /* add Target Port */ 1130 newWWN->tgtPortWWN = (tgtPortWWNList *)calloc(1, 1131 sizeof (tgtPortWWNList)); 1132 if (newWWN->tgtPortWWN == NULL) { 1133 perror("Out of memory"); 1134 exit(1); 1135 } 1136 1137 memcpy((void *)&(newWWN->tgtPortWWN->portWWN), 1138 (void *)&(entry.FcpId.PortWWN), 1139 sizeof (newWWN->tgtPortWWN->portWWN)); 1140 /* Set LUN data */ 1141 newWWN->tgtPortWWN->scsiOSLun = entry.ScsiId.ScsiOSLun; 1142 } else { /* add it to existing */ 1143 newTgtWWN = (tgtPortWWNList *)calloc(1, 1144 sizeof (tgtPortWWNList)); 1145 if (newTgtWWN == NULL) { 1146 perror("Out of memory"); 1147 exit(1); 1148 } 1149 /* insert at head */ 1150 newTgtWWN->next = WWNList->tgtPortWWN; 1151 WWNList->tgtPortWWN = newTgtWWN; 1152 memcpy((void *)&(newTgtWWN->portWWN), 1153 (void *)&(entry.FcpId.PortWWN), 1154 sizeof (newTgtWWN->portWWN)); 1155 /* Set LUN data */ 1156 newTgtWWN->scsiOSLun = entry.ScsiId.ScsiOSLun; 1157 } 1158 } else { /* add new entry */ 1159 newDevice = (discoveredDevice *)calloc(1, 1160 sizeof (discoveredDevice)); 1161 if (newDevice == NULL) { 1162 perror("Out of memory"); 1163 exit(1); 1164 } 1165 newDevice->next = *devList; /* insert at head */ 1166 *devList = newDevice; /* set new head */ 1167 1168 /* Copy device name */ 1169 strncpy(newDevice->OSDeviceName, entry.ScsiId.OSDeviceName, 1170 sizeof (newDevice->OSDeviceName) - 1); 1171 1172 /* 1173 * if only device names are requested, 1174 * no reason to go any further 1175 */ 1176 if (verbose == B_FALSE) { 1177 return; 1178 } 1179 1180 /* 1181 * copy WWN data 1182 */ 1183 newDevice->HBAPortWWN = (portWWNList *)calloc(1, 1184 sizeof (portWWNList)); 1185 if (newDevice->HBAPortWWN == NULL) { 1186 perror("Out of memory"); 1187 exit(1); 1188 } 1189 memcpy((void *)&(newDevice->HBAPortWWN->portWWN), 1190 (void *)&initiatorPortWWN, sizeof (newWWN->portWWN)); 1191 1192 newDevice->HBAPortWWN->tgtPortWWN = 1193 (tgtPortWWNList *)calloc(1, sizeof (tgtPortWWNList)); 1194 if (newDevice->HBAPortWWN->tgtPortWWN == NULL) { 1195 perror("Out of memory"); 1196 exit(1); 1197 } 1198 1199 memcpy((void *)&(newDevice->HBAPortWWN->tgtPortWWN->portWWN), 1200 (void *)&(entry.FcpId.PortWWN), 1201 sizeof (newDevice->HBAPortWWN->tgtPortWWN->portWWN)); 1202 1203 /* Set LUN data */ 1204 newDevice->HBAPortWWN->tgtPortWWN->scsiOSLun = 1205 entry.ScsiId.ScsiOSLun; 1206 1207 responseSize = sizeof (struct scsi_inquiry); 1208 senseSize = sizeof (struct scsi_extended_sense); 1209 memset(&inq, 0, sizeof (struct scsi_inquiry)); 1210 memset(&sense, 0, sizeof (sense)); 1211 status = HBA_ScsiInquiryV2( 1212 handle, 1213 initiatorPortWWN, 1214 entry.FcpId.PortWWN, 1215 entry.FcpId.FcpLun, 1216 0, /* CDB Byte 1 */ 1217 0, /* CDB Byte 2 */ 1218 &inq, &responseSize, 1219 &inq_status, 1220 &sense, &senseSize); 1221 if (status != HBA_STATUS_OK) { 1222 /* initialize VID/PID/dType as "Unknown" */ 1223 strcpy(newDevice->VID, "Unknown"); 1224 strcpy(newDevice->PID, "Unknown"); 1225 newDevice->dType = DTYPE_UNKNOWN; 1226 /* initialize inq status */ 1227 newDevice->inqSuccess = B_FALSE; 1228 } else { 1229 memcpy(newDevice->VID, inq.inq_vid, 1230 sizeof (newDevice->VID)); 1231 memcpy(newDevice->PID, inq.inq_pid, 1232 sizeof (newDevice->PID)); 1233 newDevice->dType = inq.inq_dtype; 1234 /* initialize inq status */ 1235 newDevice->inqSuccess = B_TRUE; 1236 } 1237 } 1238 } 1239 1240 1241 /* 1242 * process the logical-unit object 1243 * 1244 * Arguments: 1245 * luCount - count of the number of device paths in paths_argv 1246 * if pathCount > 0, then we will only print information for 1247 * the device paths listed in paths_argv 1248 * if pathCount == 0, then we will print information on all device 1249 * paths 1250 * luArgv - argument array of device paths 1251 * options - any options specified by the caller 1252 * 1253 * returns: 1254 * 0 if successful 1255 * > 0 otherwise 1256 */ 1257 int 1258 fc_util_list_logicalunit(int luCount, char **luArgv, cmdOptions_t *options) 1259 { 1260 int pathCtr, numAdapters, i, count; 1261 HBA_STATUS status; 1262 char adapterName[256]; 1263 HBA_HANDLE handle; 1264 HBA_PORTATTRIBUTES port; 1265 HBA_ADAPTERATTRIBUTES attrs; 1266 int portIndex = 0; 1267 int ret = 0; 1268 boolean_t verbose = B_FALSE; 1269 HBA_FCPTARGETMAPPINGV2 *map = NULL; 1270 discoveredDevice *devListWalk, *devList = NULL; 1271 boolean_t pathFound; 1272 1273 /* process each of the options */ 1274 for (; options->optval; options++) { 1275 if (options->optval == 'v') { 1276 verbose = B_TRUE; 1277 } 1278 } 1279 1280 if ((status = HBA_LoadLibrary()) != HBA_STATUS_OK) { 1281 fprintf(stderr, 1282 gettext("Failed to load FC-HBA common library\n")); 1283 printStatus(status); 1284 fprintf(stderr, "\n"); 1285 return (1); 1286 } 1287 /* 1288 * Retrieve all device paths. We'll need to traverse the list 1289 * until we find the input paths or all paths if none were given. We 1290 * cannot print as we go since there can be duplicate paths returned 1291 */ 1292 numAdapters = HBA_GetNumberOfAdapters(); 1293 if (numAdapters == 0) { 1294 return (0); 1295 } 1296 for (i = 0; i < numAdapters; i++) { 1297 int times; 1298 status = HBA_GetAdapterName(i, adapterName); 1299 if (status != HBA_STATUS_OK) { 1300 fprintf(stderr, gettext( 1301 "Failed to get adapter %d. Reason: "), i); 1302 printStatus(status); 1303 fprintf(stderr, "\n"); 1304 ret++; 1305 continue; 1306 } 1307 if ((handle = HBA_OpenAdapter(adapterName)) == 0) { 1308 fprintf(stderr, gettext("Failed to open adapter %s\n"), 1309 adapterName); 1310 ret++; 1311 continue; 1312 } 1313 /* get adapter attributes for the given handle */ 1314 memset(&attrs, 0, sizeof (attrs)); 1315 times = 0; 1316 status = HBA_GetAdapterAttributes(handle, &attrs); 1317 while ((status == HBA_STATUS_ERROR_TRY_AGAIN || 1318 status == HBA_STATUS_ERROR_BUSY) && 1319 times++ < HBA_MAX_RETRIES) { 1320 (void) sleep(1); 1321 status = HBA_GetAdapterAttributes(handle, &attrs); 1322 if (status == HBA_STATUS_OK) { 1323 break; 1324 } 1325 } 1326 if (status != HBA_STATUS_OK) { 1327 fprintf(stderr, 1328 gettext("Failed to get adapter attributes " 1329 "handle(%d) Reason: "), handle); 1330 printStatus(status); 1331 fprintf(stderr, "\n"); 1332 ret++; 1333 HBA_CloseAdapter(handle); 1334 continue; 1335 } 1336 1337 /* process each port on adapter */ 1338 for (portIndex = 0; portIndex < attrs.NumberOfPorts; 1339 portIndex++) { 1340 memset(&port, 0, sizeof (port)); 1341 if ((status = HBA_GetAdapterPortAttributes(handle, 1342 portIndex, &port)) != HBA_STATUS_OK) { 1343 /* 1344 * not able to get port attributes. 1345 * print out error message and move 1346 * on to the next port 1347 */ 1348 fprintf(stderr, gettext("Failed to get port " 1349 "(%d) attributes reason: "), 1350 portIndex); 1351 printStatus(status); 1352 fprintf(stderr, "\n"); 1353 ret++; 1354 continue; 1355 } 1356 1357 /* get OS Device Paths */ 1358 getTargetMapping(handle, port.PortWWN, &map); 1359 if (map != NULL) { 1360 for (count = 0; count < map->NumberOfEntries; 1361 count++) { 1362 searchDevice(&devList, 1363 map->entry[count], port.PortWWN, 1364 handle, verbose); 1365 } 1366 } 1367 } 1368 HBA_CloseAdapter(handle); 1369 } 1370 HBA_FreeLibrary(); 1371 1372 if (luCount == 0) { 1373 /* list all paths */ 1374 for (devListWalk = devList; devListWalk != NULL; 1375 devListWalk = devListWalk->next) { 1376 printOSDeviceNameInfo(devListWalk, verbose); 1377 } 1378 } else { 1379 /* 1380 * list any paths not found first 1381 * this gives the user cleaner output 1382 */ 1383 for (pathCtr = 0; pathCtr < luCount; pathCtr++) { 1384 for (devListWalk = devList, pathFound = B_FALSE; 1385 devListWalk != NULL; 1386 devListWalk = devListWalk->next) { 1387 if (strcmp(devListWalk->OSDeviceName, 1388 luArgv[pathCtr]) == 0) { 1389 pathFound = B_TRUE; 1390 } 1391 } 1392 if (pathFound == B_FALSE) { 1393 fprintf(stderr, "%s: no such path\n", 1394 luArgv[pathCtr]); 1395 ret++; 1396 } 1397 } 1398 /* list all paths requested in order requested */ 1399 for (pathCtr = 0; pathCtr < luCount; pathCtr++) { 1400 for (devListWalk = devList; devListWalk != NULL; 1401 devListWalk = devListWalk->next) { 1402 if (strcmp(devListWalk->OSDeviceName, 1403 luArgv[pathCtr]) == 0) { 1404 printOSDeviceNameInfo(devListWalk, 1405 verbose); 1406 } 1407 } 1408 } 1409 } 1410 return (ret); 1411 } 1412