1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 27 #include "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 printHBAPortInfo(&port, &attrs, mode); 381 if ((flags & PRINT_LINKSTAT) == PRINT_LINKSTAT) { 382 printLinkStat(handle, port.PortWWN, port.PortWWN); 383 } 384 return (0); 385 } 386 /* 387 * process each of the remote targets from this hba port 388 */ 389 for (discPortCount = 0; 390 discPortCount < port.NumberofDiscoveredPorts; 391 discPortCount++) { 392 status = HBA_GetDiscoveredPortAttributes(handle, 393 portIndex, discPortCount, &discPort); 394 if (status != HBA_STATUS_OK) { 395 fprintf(stderr, 396 gettext("Failed to get discovered port (%d)" 397 " attributes reason :"), discPortCount); 398 printStatus(status); 399 fprintf(stderr, "\n"); 400 continue; 401 } 402 if (resourceType == REMOTE_PORT) { 403 handleRemotePort(handle, port.PortWWN, discPort.PortWWN, 404 &discPort); 405 if ((flags & PRINT_LINKSTAT) == PRINT_LINKSTAT) { 406 printLinkStat(handle, port.PortWWN, 407 discPort.PortWWN); 408 } 409 if ((flags & PRINT_SCSI_TARGET) == PRINT_SCSI_TARGET) { 410 handleScsiTarget(handle, port.PortWWN, 411 discPort.PortWWN, map); 412 } 413 } 414 } 415 return (0); 416 } 417 418 /* 419 * This function will process remote port information for the given handle. 420 * 421 * Arguments: 422 * handle - a handle to a HBA that we will be processing 423 * portWWN - the port WWN for the HBA port we will be issuing the SCSI 424 * ReportLUNS through 425 * wwnCount - the number of wwns in wwn_argv 426 * wwn_argv - argument vector of WWNs 427 */ 428 static void 429 processRemotePort(HBA_HANDLE handle, HBA_WWN portWWN, 430 HBA_FCPTARGETMAPPINGV2 *map, int wwnCount, char **wwn_argv, int flags) 431 { 432 int remote_wwn_counter; 433 uint64_t remotePortWWN; 434 HBA_WWN myremotePortWWN; 435 HBA_PORTATTRIBUTES discPort; 436 HBA_STATUS status; 437 438 for (remote_wwn_counter = 0; 439 remote_wwn_counter < wwnCount; 440 remote_wwn_counter++) { 441 int times = 0; 442 sscanf(wwn_argv[remote_wwn_counter], "%016llx", 443 &remotePortWWN); 444 remotePortWWN = htonll(remotePortWWN); 445 memcpy(myremotePortWWN.wwn, &remotePortWWN, 446 sizeof (remotePortWWN)); 447 memset(&discPort, 0, sizeof (discPort)); 448 status = HBA_GetPortAttributesByWWN(handle, myremotePortWWN, 449 &discPort); 450 while (status == HBA_STATUS_ERROR_TRY_AGAIN || 451 status == HBA_STATUS_ERROR_BUSY) { 452 (void) sleep(1); 453 status = HBA_GetPortAttributesByWWN(handle, 454 myremotePortWWN, &discPort); 455 if (times++ > HBA_MAX_RETRIES) { 456 break; 457 } 458 } 459 if (status != HBA_STATUS_OK) { 460 fprintf(stderr, gettext("HBA_GetPortAttributesByWWN " 461 "failed: reason: ")); 462 printStatus(status); 463 fprintf(stderr, "\n"); 464 continue; 465 } 466 handleRemotePort(handle, portWWN, myremotePortWWN, &discPort); 467 if ((flags & PRINT_LINKSTAT) == PRINT_LINKSTAT) { 468 printLinkStat(handle, portWWN, myremotePortWWN); 469 } 470 if ((flags & PRINT_SCSI_TARGET) == PRINT_SCSI_TARGET) { 471 handleScsiTarget(handle, portWWN, 472 myremotePortWWN, map); 473 } 474 } 475 } 476 477 /* 478 * This function handles printing Scsi target information for remote ports 479 * 480 * Arguments: 481 * handle - a handle to a HBA that we will be processing 482 * hbaPortWWN - the port WWN for the HBA port through which the SCSI call 483 * is being sent 484 * scsiTargetWWN - target port WWN of the remote target the SCSI call is 485 * being sent to 486 * map - a pointer to the target mapping structure for the given HBA port 487 */ 488 static void 489 handleScsiTarget(HBA_HANDLE handle, HBA_WWN hbaPortWWN, HBA_WWN scsiTargetWWN, 490 HBA_FCPTARGETMAPPINGV2 *map) 491 { 492 HBA_STATUS status; 493 struct scsi_inquiry inq; 494 struct scsi_extended_sense sense; 495 HBA_UINT32 responseSize, senseSize = 0; 496 HBA_UINT8 inq_status; 497 uchar_t raw_luns[DEFAULT_LUN_LENGTH], *lun_string; 498 HBA_UINT8 rep_luns_status; 499 rep_luns_rsp_t *lun_resp; 500 uint64_t fcLUN; 501 int lunNum, numberOfLun, lunCount, count; 502 uint32_t lunlength, tmp_lunlength; 503 504 responseSize = DEFAULT_LUN_LENGTH; 505 senseSize = sizeof (struct scsi_extended_sense); 506 memset(&sense, 0, sizeof (sense)); 507 status = HBA_ScsiReportLUNsV2(handle, hbaPortWWN, 508 scsiTargetWWN, (void *)raw_luns, &responseSize, 509 &rep_luns_status, (void *)&sense, &senseSize); 510 /* 511 * if HBA_STATUS_ERROR_NOT_A_TARGET is return, we can assume this is 512 * a remote HBA and move on 513 */ 514 if (status == HBA_STATUS_ERROR_NOT_A_TARGET) { 515 return; 516 } else if (status != HBA_STATUS_OK) { 517 fprintf(stderr, gettext("Error has occured. " 518 "HBA_ScsiReportLUNsV2 failed. reason ")); 519 printStatus(status); 520 fprintf(stderr, "\n"); 521 return; 522 } 523 lun_resp = (rep_luns_rsp_t *)raw_luns; 524 memcpy(&tmp_lunlength, &(lun_resp->length), sizeof (tmp_lunlength)); 525 lunlength = htonl(tmp_lunlength); 526 memcpy(&numberOfLun, &lunlength, sizeof (numberOfLun)); 527 for (lunCount = 0; lunCount < (numberOfLun / 8); lunCount++) { 528 /* 529 * now issue standard inquiry to get Vendor 530 * and product information 531 */ 532 responseSize = sizeof (struct scsi_inquiry); 533 senseSize = sizeof (struct scsi_extended_sense); 534 memset(&inq, 0, sizeof (struct scsi_inquiry)); 535 memset(&sense, 0, sizeof (sense)); 536 fcLUN = ntohll(wwnConversion(lun_resp->lun[lunCount].val)); 537 status = HBA_ScsiInquiryV2( 538 handle, 539 hbaPortWWN, 540 scsiTargetWWN, 541 fcLUN, 542 0, /* EVPD */ 543 0, 544 &inq, &responseSize, 545 &inq_status, 546 &sense, &senseSize); 547 if (status != HBA_STATUS_OK) { 548 fprintf(stderr, gettext("Not able to issue Inquiry.\n")); 549 printStatus(status); 550 fprintf(stderr, "\n"); 551 strcpy(inq.inq_vid, "Unknown"); 552 strcpy(inq.inq_pid, "Unknown"); 553 } 554 if (map != NULL) { 555 for (count = 0; count < map->NumberOfEntries; count++) { 556 if ((memcmp(map->entry[count].FcpId.PortWWN.wwn, 557 scsiTargetWWN.wwn, 558 sizeof (scsiTargetWWN.wwn)) 559 == 0) && 560 (memcmp(&(map->entry[count].FcpId.FcpLun), 561 &fcLUN, sizeof (fcLUN)) == 0)) { 562 printLUNInfo(&inq, 563 map->entry[count].ScsiId.ScsiOSLun, 564 map->entry[count].ScsiId.OSDeviceName); 565 break; 566 } 567 } 568 if (count == map->NumberOfEntries) { 569 lun_string = lun_resp->lun[lunCount].val; 570 lunNum = ((lun_string[0] & 0x3F) << 8) | 571 lun_string[1]; 572 printLUNInfo(&inq, lunNum, "Unknown"); 573 } 574 } else { 575 /* Not able to get any target mapping information */ 576 lun_string = lun_resp->lun[lunCount].val; 577 lunNum = ((lun_string[0] & 0x3F) << 8) | 578 lun_string[1]; 579 printLUNInfo(&inq, lunNum, "Unknown"); 580 } 581 } 582 } 583 584 /* 585 * function to handle the list remoteport command 586 * 587 * Arguments: 588 * wwnCount - the number of wwns in wwn_argv 589 * if wwnCount == 0, then print information on all 590 * remote ports. wwn_argv will not be used in this case 591 * if wwnCount > 0, then print information for the WWNs 592 * given in wwn_argv 593 * wwn_argv - argument vector of WWNs 594 * options - any options specified by the caller 595 * 596 * returns: 597 * 0 if successful 598 * 1 otherwise 599 */ 600 int 601 fc_util_list_remoteport(int wwnCount, char **wwn_argv, cmdOptions_t *options) 602 { 603 HBA_STATUS status; 604 HBA_FCPTARGETMAPPINGV2 *map = NULL; 605 HBA_PORTATTRIBUTES port; 606 HBA_ADAPTERATTRIBUTES attrs; 607 HBA_HANDLE handle; 608 uint64_t hbaPortWWN; 609 HBA_WWN myhbaPortWWN; 610 int processHBA_flags = 0, portCount = 0; 611 int mode; 612 613 /* grab the hba port wwn from the -p option */ 614 for (; options->optval; options++) { 615 if (options->optval == 'p') { 616 sscanf(options->optarg, "%016llx", 617 &hbaPortWWN); 618 } else if (options->optval == 's') { 619 processHBA_flags |= PRINT_SCSI_TARGET; 620 } else if (options->optval == 'l') { 621 processHBA_flags |= PRINT_LINKSTAT; 622 } else { 623 fprintf(stderr, gettext("Error: Illegal option: %c.\n"), 624 options->optval); 625 return (1); 626 } 627 } 628 /* 629 * -h option was not specified, this should not happen either. 630 * cmdparse should catch this problem, but checking anyways 631 */ 632 if (hbaPortWWN == 0) { 633 fprintf(stderr, 634 gettext("Error: -p option was not specified.\n")); 635 return (1); 636 } 637 if ((status = HBA_LoadLibrary()) != HBA_STATUS_OK) { 638 fprintf(stderr, 639 gettext("Failed to load FC-HBA common library\n")); 640 printStatus(status); 641 fprintf(stderr, "\n"); 642 return (1); 643 } 644 hbaPortWWN = htonll(hbaPortWWN); 645 memcpy(myhbaPortWWN.wwn, &hbaPortWWN, sizeof (hbaPortWWN)); 646 if ((status = HBA_OpenAdapterByWWN(&handle, myhbaPortWWN)) 647 != HBA_STATUS_OK) { 648 status = Sun_HBA_OpenTgtAdapterByWWN(&handle, myhbaPortWWN); 649 if (status != HBA_STATUS_OK) { 650 fprintf(stderr, 651 gettext("Error: Failed to open adapter port. Reason ")); 652 printStatus(status); 653 fprintf(stderr, "\n"); 654 HBA_FreeLibrary(); 655 return (1); 656 } else { 657 if ((processHBA_flags & PRINT_SCSI_TARGET) == 658 PRINT_SCSI_TARGET) { 659 fprintf(stderr, gettext( 660 "Error: Unsupported option for target mode: %c.\n"), 661 's'); 662 HBA_FreeLibrary(); 663 return (1); 664 } 665 mode = TARGET_MODE; 666 } 667 } else { 668 mode = INITIATOR_MODE; 669 } 670 671 if ((processHBA_flags & PRINT_SCSI_TARGET) == PRINT_SCSI_TARGET) { 672 getTargetMapping(handle, myhbaPortWWN, &map); 673 } 674 if (wwnCount == 0) { 675 /* get adapater attributes for the given handle */ 676 memset(&attrs, 0, sizeof (attrs)); 677 memset(&port, 0, sizeof (port)); 678 if (retrieveAttrs(handle, myhbaPortWWN, &attrs, &port, 679 &portCount) != 0) { 680 if (map != NULL) { 681 free(map); 682 } 683 HBA_CloseAdapter(handle); 684 HBA_FreeLibrary(); 685 return (1); 686 } 687 processHBA(handle, attrs, portCount, port, map, REMOTE_PORT, 688 processHBA_flags, mode); 689 } else { 690 processRemotePort(handle, myhbaPortWWN, map, wwnCount, 691 wwn_argv, processHBA_flags); 692 } 693 if (map != NULL) { 694 free(map); 695 } 696 HBA_CloseAdapter(handle); 697 HBA_FreeLibrary(); 698 return (0); 699 } 700 701 /* 702 * process the hbaport object 703 * 704 * Arguments: 705 * wwnCount - count of the number of WWNs in wwn_argv 706 * if wwnCount > 0, then we will only print information for 707 * the hba ports listed in wwn_argv 708 * if wwnCount == 0, then we will print information on all hba ports 709 * wwn_argv - argument array of hba port WWNs 710 * options - any options specified by the caller 711 * 712 * returns: 713 * 0 if successful 714 * 1 otherwise 715 */ 716 int 717 fc_util_list_hbaport(int wwnCount, char **wwn_argv, cmdOptions_t *options) 718 { 719 int port_wwn_counter, numAdapters = 0, numTgtAdapters = 0, i; 720 HBA_STATUS status; 721 char adapterName[256]; 722 HBA_HANDLE handle; 723 uint64_t hbaWWN; 724 HBA_WWN myWWN; 725 int processHBA_flags = 0; 726 HBA_PORTATTRIBUTES port; 727 HBA_ADAPTERATTRIBUTES attrs; 728 int portIndex = 0, err_cnt = 0; 729 int mode; 730 731 /* process each of the options */ 732 for (; options->optval; options++) { 733 if (options->optval == 'l') { 734 processHBA_flags |= PRINT_LINKSTAT; 735 } else if (options->optval == 'i') { 736 processHBA_flags |= PRINT_INITIATOR; 737 } else if (options->optval == 't') { 738 processHBA_flags |= PRINT_TARGET; 739 } 740 } 741 742 /* 743 * Print both initiator and target if no initiator/target flag 744 * specified. 745 */ 746 if (((processHBA_flags & PRINT_INITIATOR) == 0) && 747 ((processHBA_flags & PRINT_TARGET) == 0)) { 748 processHBA_flags |= PRINT_INITIATOR | PRINT_TARGET; 749 } 750 751 if ((status = HBA_LoadLibrary()) != HBA_STATUS_OK) { 752 fprintf(stderr, 753 gettext("Failed to load FC-HBA common library\n")); 754 printStatus(status); 755 fprintf(stderr, "\n"); 756 return (1); 757 } 758 if (wwnCount > 0) { 759 /* list only ports given in wwn_argv */ 760 for (port_wwn_counter = 0; 761 port_wwn_counter < wwnCount; 762 port_wwn_counter++) { 763 sscanf(wwn_argv[port_wwn_counter], "%016llx", &hbaWWN); 764 hbaWWN = htonll(hbaWWN); 765 memcpy(myWWN.wwn, &hbaWWN, sizeof (hbaWWN)); 766 /* first check to see if it is an initiator port. */ 767 if ((processHBA_flags & PRINT_INITIATOR) == 768 PRINT_INITIATOR) { 769 int times = 0; 770 status = HBA_OpenAdapterByWWN(&handle, myWWN); 771 while (status == HBA_STATUS_ERROR_TRY_AGAIN || 772 status == HBA_STATUS_ERROR_BUSY) { 773 (void) sleep(1); 774 status = HBA_OpenAdapterByWWN(&handle, myWWN); 775 if (times++ > HBA_MAX_RETRIES) { 776 break; 777 } 778 } 779 if (status != HBA_STATUS_OK) { 780 /* now see if it is a target mode FC port */ 781 if ((processHBA_flags & PRINT_TARGET) == 782 PRINT_TARGET) { 783 status = 784 Sun_HBA_OpenTgtAdapterByWWN(&handle, myWWN); 785 if (status != HBA_STATUS_OK) { 786 fprintf(stderr, 787 gettext( 788 "Error: HBA port %s: not found\n"), 789 wwn_argv[port_wwn_counter]); 790 err_cnt++; 791 continue; 792 } else { 793 /* set the port mode. */ 794 mode = TARGET_MODE; 795 } 796 } else { 797 fprintf(stderr, 798 gettext( 799 "Error: HBA port %s: not found\n"), 800 wwn_argv[port_wwn_counter]); 801 err_cnt++; 802 continue; 803 } 804 } else { 805 /* set the port mode. */ 806 mode = INITIATOR_MODE; 807 } 808 /* try target mode discovery if print target is set. */ 809 } else if ((processHBA_flags & PRINT_TARGET) == 810 PRINT_TARGET) { 811 status = 812 Sun_HBA_OpenTgtAdapterByWWN(&handle, myWWN); 813 if (status != HBA_STATUS_OK) { 814 fprintf(stderr, gettext( 815 "Error: HBA port %s: not found\n"), 816 wwn_argv[port_wwn_counter]); 817 err_cnt++; 818 continue; 819 } else { 820 /* set the port mode. */ 821 mode = TARGET_MODE; 822 } 823 } else { 824 /* should not get here. */ 825 fprintf(stderr, gettext( 826 "Error: HBA port %s: not found\n"), 827 wwn_argv[port_wwn_counter]); 828 err_cnt++; 829 continue; 830 } 831 memset(&attrs, 0, sizeof (attrs)); 832 memset(&port, 0, sizeof (port)); 833 if (retrieveAttrs(handle, myWWN, &attrs, &port, 834 &portIndex) != 0) { 835 HBA_CloseAdapter(handle); 836 continue; 837 } 838 processHBA(handle, attrs, portIndex, port, NULL, 839 HBA_PORT, processHBA_flags, mode); 840 if (printHBANPIVPortInfo(handle, portIndex) 841 != 0) { 842 err_cnt++; 843 } 844 HBA_CloseAdapter(handle); 845 } 846 } else { 847 /* 848 * if PRINT_INITIATOR is specified, get the list of initiator 849 * mod port. 850 */ 851 if ((processHBA_flags & PRINT_INITIATOR) == PRINT_INITIATOR) { 852 numAdapters = HBA_GetNumberOfAdapters(); 853 if ((numAdapters == 0) && 854 ((processHBA_flags & ~PRINT_INITIATOR) == 0)) { 855 fprintf(stdout, gettext("No Adapters Found.\n")); 856 } 857 for (i = 0; i < numAdapters; i++) { 858 int times = 0; 859 status = HBA_GetAdapterName(i, adapterName); 860 if (status != HBA_STATUS_OK) { 861 fprintf(stderr, gettext( 862 "failed to get adapter %d. Reason: "), i); 863 printStatus(status); 864 fprintf(stderr, "\n"); 865 continue; 866 } 867 if ((handle = HBA_OpenAdapter(adapterName)) == 0) { 868 fprintf(stderr, gettext( 869 "Failed to open adapter %s.\n"), 870 adapterName); 871 continue; 872 } 873 /* get adapater attributes for the given handle */ 874 memset(&attrs, 0, sizeof (attrs)); 875 status = 876 Sun_HBA_NPIVGetAdapterAttributes(handle, 877 &attrs); 878 while ((status == HBA_STATUS_ERROR_TRY_AGAIN || 879 status == HBA_STATUS_ERROR_BUSY) && 880 times++ < HBA_MAX_RETRIES) { 881 (void) sleep(1); 882 status = 883 Sun_HBA_NPIVGetAdapterAttributes(handle, 884 &attrs); 885 if (status == HBA_STATUS_OK) { 886 break; 887 } 888 } 889 if (status != HBA_STATUS_OK) { 890 fprintf(stderr, 891 gettext("Failed to get adapter attributes " 892 "handle(%d) Reason: "), handle); 893 printStatus(status); 894 fprintf(stderr, "\n"); 895 continue; 896 } 897 898 /* process each port on the given adatpter */ 899 for (portIndex = 0; 900 portIndex < attrs.NumberOfPorts; 901 portIndex++) { 902 memset(&port, 0, sizeof (port)); 903 if ((status = HBA_GetAdapterPortAttributes( 904 handle, portIndex, &port)) 905 != HBA_STATUS_OK) { 906 /* 907 * not able to get port attributes. 908 * print out error * message and move 909 * on to the next port 910 */ 911 fprintf(stderr, 912 gettext("Error: Failed to get port " 913 "(%d) attributes reason: "), 914 portIndex); 915 printStatus(status); 916 fprintf(stderr, "\n"); 917 continue; 918 } 919 processHBA(handle, attrs, portIndex, port, 920 NULL, HBA_PORT, processHBA_flags, 921 INITIATOR_MODE); 922 if (printHBANPIVPortInfo(handle, portIndex) 923 != 0) { 924 err_cnt++; 925 } 926 } 927 HBA_CloseAdapter(handle); 928 } 929 } 930 931 /* 932 * Get the info on the target mode FC port if PRINT_TARGET 933 * is specified. 934 */ 935 if ((processHBA_flags & PRINT_TARGET) == PRINT_TARGET) { 936 numTgtAdapters = Sun_HBA_GetNumberOfTgtAdapters(); 937 if (numTgtAdapters == 0 && numAdapters == 0) { 938 fprintf(stdout, 939 gettext("No Adapters Found.\n")); 940 } 941 for (i = 0; i < numTgtAdapters; i++) { 942 status = Sun_HBA_GetTgtAdapterName(i, adapterName); 943 if (status != HBA_STATUS_OK) { 944 fprintf(stderr, gettext( 945 "failed to get adapter %d. Reason: "), i); 946 printStatus(status); 947 fprintf(stderr, "\n"); 948 continue; 949 } 950 if ((handle = Sun_HBA_OpenTgtAdapter(adapterName)) 951 == 0) { 952 fprintf(stderr, gettext( 953 "Failed to open adapter %s.\n"), adapterName); 954 continue; 955 } 956 /* get adapater attributes for the given handle */ 957 memset(&attrs, 0, sizeof (attrs)); 958 if ((status = HBA_GetAdapterAttributes(handle, &attrs)) 959 != HBA_STATUS_OK) { 960 fprintf(stderr, 961 gettext("Failed to get target mode adapter" 962 "attributes handle(%d) Reason: "), 963 handle); 964 printStatus(status); 965 fprintf(stderr, "\n"); 966 continue; 967 } 968 969 /* process each port on the given adatpter */ 970 for (portIndex = 0; 971 portIndex < attrs.NumberOfPorts; 972 portIndex++) { 973 memset(&port, 0, sizeof (port)); 974 if ((status = HBA_GetAdapterPortAttributes( 975 handle, portIndex, &port)) 976 != HBA_STATUS_OK) { 977 /* 978 * not able to get port attributes. 979 * print out error * message and move 980 * on to the next port 981 */ 982 fprintf(stderr, 983 gettext("Error: Failed to get port " 984 "(%d) attributes reason: "), 985 portIndex); 986 printStatus(status); 987 fprintf(stderr, "\n"); 988 continue; 989 } 990 processHBA(handle, attrs, portIndex, port, 991 NULL, HBA_PORT, processHBA_flags, 992 TARGET_MODE); 993 } 994 HBA_CloseAdapter(handle); 995 } 996 } 997 } 998 999 HBA_FreeLibrary(); 1000 1001 /* 1002 * print additional error msg for partial failure when more than 1003 * one wwn is specified. 1004 */ 1005 if (err_cnt != 0) { 1006 if (wwnCount > 1) { 1007 if (err_cnt == wwnCount) { 1008 fprintf(stderr, gettext( 1009 "Error: All specified HBA ports are not found\n")); 1010 } else { 1011 fprintf(stderr, gettext( 1012 "Error: Some of specified HBA ports are not found\n")); 1013 } 1014 } 1015 return (1); 1016 } 1017 1018 return (0); 1019 } 1020 1021 /* 1022 * Search the existing device list 1023 * 1024 * Take one of two actions: 1025 * 1026 * Add an entry if an entry doesn't exist 1027 * Add WWN data to it if an entry does exist 1028 * 1029 * Arguments: 1030 * devList - OS device path list 1031 * map - target mapping data 1032 * index - index into target mapping data 1033 * initiatorPortWWN - HBA port WWN 1034 * verbose - boolean indicating whether to get additional data 1035 * 1036 * returns: 1037 * none 1038 */ 1039 static void 1040 searchDevice(discoveredDevice **devList, HBA_FCPSCSIENTRYV2 entry, 1041 HBA_WWN initiatorPortWWN, HBA_HANDLE handle, boolean_t verbose) 1042 { 1043 discoveredDevice *discoveredDevList, *newDevice; 1044 portWWNList *WWNList, *newWWN; 1045 tgtPortWWNList *newTgtWWN; 1046 boolean_t foundDevice = B_FALSE, foundWWN; 1047 struct scsi_inquiry inq; 1048 struct scsi_extended_sense sense; 1049 HBA_UINT32 responseSize, senseSize = 0; 1050 HBA_UINT8 inq_status; 1051 HBA_STATUS status; 1052 1053 for (discoveredDevList = *devList; discoveredDevList != NULL; 1054 discoveredDevList = discoveredDevList->next) { 1055 if (strcmp(entry.ScsiId.OSDeviceName, 1056 discoveredDevList->OSDeviceName) == 0) { 1057 /* 1058 * if only device names are requested, 1059 * no reason to go any further 1060 */ 1061 if (verbose == B_FALSE) { 1062 return; 1063 } 1064 foundDevice = B_TRUE; 1065 break; 1066 } 1067 } 1068 if (foundDevice == B_TRUE) { 1069 /* add initiator Port WWN if it doesn't exist */ 1070 for (WWNList = discoveredDevList->HBAPortWWN, 1071 foundWWN = B_FALSE; WWNList != NULL; 1072 WWNList = WWNList->next) { 1073 if (memcmp((void *)&(WWNList->portWWN), 1074 (void *)&initiatorPortWWN, 1075 sizeof (HBA_WWN)) == 0) { 1076 foundWWN = B_TRUE; 1077 break; 1078 } 1079 } 1080 if (discoveredDevList->inqSuccess == B_FALSE) { 1081 responseSize = sizeof (struct scsi_inquiry); 1082 senseSize = sizeof (struct scsi_extended_sense); 1083 memset(&inq, 0, sizeof (struct scsi_inquiry)); 1084 memset(&sense, 0, sizeof (sense)); 1085 status = HBA_ScsiInquiryV2( 1086 handle, 1087 initiatorPortWWN, 1088 entry.FcpId.PortWWN, 1089 entry.FcpId.FcpLun, 1090 0, /* CDB Byte 1 */ 1091 0, /* CDB Byte 2 */ 1092 &inq, &responseSize, 1093 &inq_status, 1094 &sense, &senseSize); 1095 if (status == HBA_STATUS_OK) { 1096 memcpy(discoveredDevList->VID, inq.inq_vid, 1097 sizeof (discoveredDevList->VID)); 1098 memcpy(discoveredDevList->PID, inq.inq_pid, 1099 sizeof (discoveredDevList->PID)); 1100 discoveredDevList->dType = inq.inq_dtype; 1101 discoveredDevList->inqSuccess = B_TRUE; 1102 } 1103 } 1104 1105 if (foundWWN == B_FALSE) { 1106 newWWN = (portWWNList *)calloc(1, sizeof (portWWNList)); 1107 if (newWWN == NULL) { 1108 perror("Out of memory"); 1109 exit(1); 1110 } 1111 1112 /* insert at head */ 1113 newWWN->next = discoveredDevList->HBAPortWWN; 1114 discoveredDevList->HBAPortWWN = newWWN; 1115 memcpy((void *)&(newWWN->portWWN), 1116 (void *)&initiatorPortWWN, 1117 sizeof (newWWN->portWWN)); 1118 /* add Target Port */ 1119 newWWN->tgtPortWWN = (tgtPortWWNList *)calloc(1, 1120 sizeof (tgtPortWWNList)); 1121 if (newWWN->tgtPortWWN == NULL) { 1122 perror("Out of memory"); 1123 exit(1); 1124 } 1125 1126 memcpy((void *)&(newWWN->tgtPortWWN->portWWN), 1127 (void *)&(entry.FcpId.PortWWN), 1128 sizeof (newWWN->tgtPortWWN->portWWN)); 1129 /* Set LUN data */ 1130 newWWN->tgtPortWWN->scsiOSLun = entry.ScsiId.ScsiOSLun; 1131 } else { /* add it to existing */ 1132 newTgtWWN = (tgtPortWWNList *)calloc(1, 1133 sizeof (tgtPortWWNList)); 1134 if (newTgtWWN == NULL) { 1135 perror("Out of memory"); 1136 exit(1); 1137 } 1138 /* insert at head */ 1139 newTgtWWN->next = WWNList->tgtPortWWN; 1140 WWNList->tgtPortWWN = newTgtWWN; 1141 memcpy((void *)&(newTgtWWN->portWWN), 1142 (void *)&(entry.FcpId.PortWWN), 1143 sizeof (newTgtWWN->portWWN)); 1144 /* Set LUN data */ 1145 newTgtWWN->scsiOSLun = entry.ScsiId.ScsiOSLun; 1146 } 1147 } else { /* add new entry */ 1148 newDevice = (discoveredDevice *)calloc(1, 1149 sizeof (discoveredDevice)); 1150 if (newDevice == NULL) { 1151 perror("Out of memory"); 1152 exit(1); 1153 } 1154 newDevice->next = *devList; /* insert at head */ 1155 *devList = newDevice; /* set new head */ 1156 1157 /* Copy device name */ 1158 strncpy(newDevice->OSDeviceName, entry.ScsiId.OSDeviceName, 1159 sizeof (newDevice->OSDeviceName) - 1); 1160 1161 /* 1162 * if only device names are requested, 1163 * no reason to go any further 1164 */ 1165 if (verbose == B_FALSE) { 1166 return; 1167 } 1168 1169 /* 1170 * copy WWN data 1171 */ 1172 newDevice->HBAPortWWN = (portWWNList *)calloc(1, 1173 sizeof (portWWNList)); 1174 if (newDevice->HBAPortWWN == NULL) { 1175 perror("Out of memory"); 1176 exit(1); 1177 } 1178 memcpy((void *)&(newDevice->HBAPortWWN->portWWN), 1179 (void *)&initiatorPortWWN, sizeof (newWWN->portWWN)); 1180 1181 newDevice->HBAPortWWN->tgtPortWWN = 1182 (tgtPortWWNList *)calloc(1, sizeof (tgtPortWWNList)); 1183 if (newDevice->HBAPortWWN->tgtPortWWN == NULL) { 1184 perror("Out of memory"); 1185 exit(1); 1186 } 1187 1188 memcpy((void *)&(newDevice->HBAPortWWN->tgtPortWWN->portWWN), 1189 (void *)&(entry.FcpId.PortWWN), 1190 sizeof (newDevice->HBAPortWWN->tgtPortWWN->portWWN)); 1191 1192 /* Set LUN data */ 1193 newDevice->HBAPortWWN->tgtPortWWN->scsiOSLun = 1194 entry.ScsiId.ScsiOSLun; 1195 1196 responseSize = sizeof (struct scsi_inquiry); 1197 senseSize = sizeof (struct scsi_extended_sense); 1198 memset(&inq, 0, sizeof (struct scsi_inquiry)); 1199 memset(&sense, 0, sizeof (sense)); 1200 status = HBA_ScsiInquiryV2( 1201 handle, 1202 initiatorPortWWN, 1203 entry.FcpId.PortWWN, 1204 entry.FcpId.FcpLun, 1205 0, /* CDB Byte 1 */ 1206 0, /* CDB Byte 2 */ 1207 &inq, &responseSize, 1208 &inq_status, 1209 &sense, &senseSize); 1210 if (status != HBA_STATUS_OK) { 1211 /* initialize VID/PID/dType as "Unknown" */ 1212 strcpy(newDevice->VID, "Unknown"); 1213 strcpy(newDevice->PID, "Unknown"); 1214 newDevice->dType = DTYPE_UNKNOWN; 1215 /* initialize inq status */ 1216 newDevice->inqSuccess = B_FALSE; 1217 } else { 1218 memcpy(newDevice->VID, inq.inq_vid, 1219 sizeof (newDevice->VID)); 1220 memcpy(newDevice->PID, inq.inq_pid, 1221 sizeof (newDevice->PID)); 1222 newDevice->dType = inq.inq_dtype; 1223 /* initialize inq status */ 1224 newDevice->inqSuccess = B_TRUE; 1225 } 1226 } 1227 } 1228 1229 1230 /* 1231 * process the logical-unit object 1232 * 1233 * Arguments: 1234 * luCount - count of the number of device paths in paths_argv 1235 * if pathCount > 0, then we will only print information for 1236 * the device paths listed in paths_argv 1237 * if pathCount == 0, then we will print information on all device 1238 * paths 1239 * luArgv - argument array of device paths 1240 * options - any options specified by the caller 1241 * 1242 * returns: 1243 * 0 if successful 1244 * > 0 otherwise 1245 */ 1246 int 1247 fc_util_list_logicalunit(int luCount, char **luArgv, cmdOptions_t *options) 1248 { 1249 int pathCtr, numAdapters, i, count; 1250 HBA_STATUS status; 1251 char adapterName[256]; 1252 HBA_HANDLE handle; 1253 HBA_PORTATTRIBUTES port; 1254 HBA_ADAPTERATTRIBUTES attrs; 1255 int portIndex = 0; 1256 int ret = 0; 1257 boolean_t verbose = B_FALSE; 1258 HBA_FCPTARGETMAPPINGV2 *map = NULL; 1259 discoveredDevice *devListWalk, *devList = NULL; 1260 boolean_t pathFound; 1261 1262 /* process each of the options */ 1263 for (; options->optval; options++) { 1264 if (options->optval == 'v') { 1265 verbose = B_TRUE; 1266 } 1267 } 1268 1269 if ((status = HBA_LoadLibrary()) != HBA_STATUS_OK) { 1270 fprintf(stderr, 1271 gettext("Failed to load FC-HBA common library\n")); 1272 printStatus(status); 1273 fprintf(stderr, "\n"); 1274 return (1); 1275 } 1276 /* 1277 * Retrieve all device paths. We'll need to traverse the list 1278 * until we find the input paths or all paths if none were given. We 1279 * cannot print as we go since there can be duplicate paths returned 1280 */ 1281 numAdapters = HBA_GetNumberOfAdapters(); 1282 if (numAdapters == 0) { 1283 return (0); 1284 } 1285 for (i = 0; i < numAdapters; i++) { 1286 int times; 1287 status = HBA_GetAdapterName(i, adapterName); 1288 if (status != HBA_STATUS_OK) { 1289 fprintf(stderr, gettext( 1290 "Failed to get adapter %d. Reason: "), i); 1291 printStatus(status); 1292 fprintf(stderr, "\n"); 1293 ret++; 1294 continue; 1295 } 1296 if ((handle = HBA_OpenAdapter(adapterName)) == 0) { 1297 fprintf(stderr, gettext("Failed to open adapter %s\n"), 1298 adapterName); 1299 ret++; 1300 continue; 1301 } 1302 /* get adapter attributes for the given handle */ 1303 memset(&attrs, 0, sizeof (attrs)); 1304 times = 0; 1305 status = HBA_GetAdapterAttributes(handle, &attrs); 1306 while ((status == HBA_STATUS_ERROR_TRY_AGAIN || 1307 status == HBA_STATUS_ERROR_BUSY) && 1308 times++ < HBA_MAX_RETRIES) { 1309 (void) sleep(1); 1310 status = HBA_GetAdapterAttributes(handle, &attrs); 1311 if (status == HBA_STATUS_OK) { 1312 break; 1313 } 1314 } 1315 if (status != HBA_STATUS_OK) { 1316 fprintf(stderr, 1317 gettext("Failed to get adapter attributes " 1318 "handle(%d) Reason: "), handle); 1319 printStatus(status); 1320 fprintf(stderr, "\n"); 1321 ret++; 1322 continue; 1323 } 1324 1325 /* process each port on adapter */ 1326 for (portIndex = 0; portIndex < attrs.NumberOfPorts; 1327 portIndex++) { 1328 memset(&port, 0, sizeof (port)); 1329 if ((status = HBA_GetAdapterPortAttributes(handle, 1330 portIndex, &port)) != HBA_STATUS_OK) { 1331 /* 1332 * not able to get port attributes. 1333 * print out error message and move 1334 * on to the next port 1335 */ 1336 fprintf(stderr, gettext("Failed to get port " 1337 "(%d) attributes reason: "), 1338 portIndex); 1339 printStatus(status); 1340 fprintf(stderr, "\n"); 1341 ret++; 1342 continue; 1343 } 1344 1345 /* get OS Device Paths */ 1346 getTargetMapping(handle, port.PortWWN, &map); 1347 if (map != NULL) { 1348 for (count = 0; count < map->NumberOfEntries; 1349 count++) { 1350 searchDevice(&devList, 1351 map->entry[count], port.PortWWN, 1352 handle, verbose); 1353 } 1354 } 1355 } 1356 HBA_CloseAdapter(handle); 1357 } 1358 HBA_FreeLibrary(); 1359 1360 if (luCount == 0) { 1361 /* list all paths */ 1362 for (devListWalk = devList; devListWalk != NULL; 1363 devListWalk = devListWalk->next) { 1364 printOSDeviceNameInfo(devListWalk, verbose); 1365 } 1366 } else { 1367 /* 1368 * list any paths not found first 1369 * this gives the user cleaner output 1370 */ 1371 for (pathCtr = 0; pathCtr < luCount; pathCtr++) { 1372 for (devListWalk = devList, pathFound = B_FALSE; 1373 devListWalk != NULL; 1374 devListWalk = devListWalk->next) { 1375 if (strcmp(devListWalk->OSDeviceName, 1376 luArgv[pathCtr]) == 0) { 1377 pathFound = B_TRUE; 1378 } 1379 } 1380 if (pathFound == B_FALSE) { 1381 fprintf(stderr, "%s: no such path\n", 1382 luArgv[pathCtr]); 1383 ret++; 1384 } 1385 } 1386 /* list all paths requested in order requested */ 1387 for (pathCtr = 0; pathCtr < luCount; pathCtr++) { 1388 for (devListWalk = devList; devListWalk != NULL; 1389 devListWalk = devListWalk->next) { 1390 if (strcmp(devListWalk->OSDeviceName, 1391 luArgv[pathCtr]) == 0) { 1392 printOSDeviceNameInfo(devListWalk, 1393 verbose); 1394 } 1395 } 1396 } 1397 } 1398 return (ret); 1399 } 1400