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 HBA_CloseAdapter(handle); 896 continue; 897 } 898 899 /* process each port on the given adatpter */ 900 for (portIndex = 0; 901 portIndex < attrs.NumberOfPorts; 902 portIndex++) { 903 memset(&port, 0, sizeof (port)); 904 if ((status = HBA_GetAdapterPortAttributes( 905 handle, portIndex, &port)) 906 != HBA_STATUS_OK) { 907 /* 908 * not able to get port attributes. 909 * print out error * message and move 910 * on to the next port 911 */ 912 fprintf(stderr, 913 gettext("Error: Failed to get port " 914 "(%d) attributes reason: "), 915 portIndex); 916 printStatus(status); 917 fprintf(stderr, "\n"); 918 continue; 919 } 920 processHBA(handle, attrs, portIndex, port, 921 NULL, HBA_PORT, processHBA_flags, 922 INITIATOR_MODE); 923 if (printHBANPIVPortInfo(handle, portIndex) 924 != 0) { 925 err_cnt++; 926 } 927 } 928 HBA_CloseAdapter(handle); 929 } 930 } 931 932 /* 933 * Get the info on the target mode FC port if PRINT_TARGET 934 * is specified. 935 */ 936 if ((processHBA_flags & PRINT_TARGET) == PRINT_TARGET) { 937 numTgtAdapters = Sun_HBA_GetNumberOfTgtAdapters(); 938 if (numTgtAdapters == 0 && numAdapters == 0) { 939 fprintf(stdout, 940 gettext("No Adapters Found.\n")); 941 } 942 for (i = 0; i < numTgtAdapters; i++) { 943 status = Sun_HBA_GetTgtAdapterName(i, adapterName); 944 if (status != HBA_STATUS_OK) { 945 fprintf(stderr, gettext( 946 "failed to get adapter %d. Reason: "), i); 947 printStatus(status); 948 fprintf(stderr, "\n"); 949 continue; 950 } 951 if ((handle = Sun_HBA_OpenTgtAdapter(adapterName)) 952 == 0) { 953 fprintf(stderr, gettext( 954 "Failed to open adapter %s.\n"), adapterName); 955 continue; 956 } 957 /* get adapater attributes for the given handle */ 958 memset(&attrs, 0, sizeof (attrs)); 959 if ((status = HBA_GetAdapterAttributes(handle, &attrs)) 960 != HBA_STATUS_OK) { 961 fprintf(stderr, 962 gettext("Failed to get target mode adapter" 963 "attributes handle(%d) Reason: "), 964 handle); 965 printStatus(status); 966 fprintf(stderr, "\n"); 967 continue; 968 } 969 970 /* process each port on the given adatpter */ 971 for (portIndex = 0; 972 portIndex < attrs.NumberOfPorts; 973 portIndex++) { 974 memset(&port, 0, sizeof (port)); 975 if ((status = HBA_GetAdapterPortAttributes( 976 handle, portIndex, &port)) 977 != HBA_STATUS_OK) { 978 /* 979 * not able to get port attributes. 980 * print out error * message and move 981 * on to the next port 982 */ 983 fprintf(stderr, 984 gettext("Error: Failed to get port " 985 "(%d) attributes reason: "), 986 portIndex); 987 printStatus(status); 988 fprintf(stderr, "\n"); 989 continue; 990 } 991 processHBA(handle, attrs, portIndex, port, 992 NULL, HBA_PORT, processHBA_flags, 993 TARGET_MODE); 994 } 995 HBA_CloseAdapter(handle); 996 } 997 } 998 } 999 1000 HBA_FreeLibrary(); 1001 1002 /* 1003 * print additional error msg for partial failure when more than 1004 * one wwn is specified. 1005 */ 1006 if (err_cnt != 0) { 1007 if (wwnCount > 1) { 1008 if (err_cnt == wwnCount) { 1009 fprintf(stderr, gettext( 1010 "Error: All specified HBA ports are not found\n")); 1011 } else { 1012 fprintf(stderr, gettext( 1013 "Error: Some of specified HBA ports are not found\n")); 1014 } 1015 } 1016 return (1); 1017 } 1018 1019 return (0); 1020 } 1021 1022 /* 1023 * Search the existing device list 1024 * 1025 * Take one of two actions: 1026 * 1027 * Add an entry if an entry doesn't exist 1028 * Add WWN data to it if an entry does exist 1029 * 1030 * Arguments: 1031 * devList - OS device path list 1032 * map - target mapping data 1033 * index - index into target mapping data 1034 * initiatorPortWWN - HBA port WWN 1035 * verbose - boolean indicating whether to get additional data 1036 * 1037 * returns: 1038 * none 1039 */ 1040 static void 1041 searchDevice(discoveredDevice **devList, HBA_FCPSCSIENTRYV2 entry, 1042 HBA_WWN initiatorPortWWN, HBA_HANDLE handle, boolean_t verbose) 1043 { 1044 discoveredDevice *discoveredDevList, *newDevice; 1045 portWWNList *WWNList, *newWWN; 1046 tgtPortWWNList *newTgtWWN; 1047 boolean_t foundDevice = B_FALSE, foundWWN; 1048 struct scsi_inquiry inq; 1049 struct scsi_extended_sense sense; 1050 HBA_UINT32 responseSize, senseSize = 0; 1051 HBA_UINT8 inq_status; 1052 HBA_STATUS status; 1053 1054 for (discoveredDevList = *devList; discoveredDevList != NULL; 1055 discoveredDevList = discoveredDevList->next) { 1056 if (strcmp(entry.ScsiId.OSDeviceName, 1057 discoveredDevList->OSDeviceName) == 0) { 1058 /* 1059 * if only device names are requested, 1060 * no reason to go any further 1061 */ 1062 if (verbose == B_FALSE) { 1063 return; 1064 } 1065 foundDevice = B_TRUE; 1066 break; 1067 } 1068 } 1069 if (foundDevice == B_TRUE) { 1070 /* add initiator Port WWN if it doesn't exist */ 1071 for (WWNList = discoveredDevList->HBAPortWWN, 1072 foundWWN = B_FALSE; WWNList != NULL; 1073 WWNList = WWNList->next) { 1074 if (memcmp((void *)&(WWNList->portWWN), 1075 (void *)&initiatorPortWWN, 1076 sizeof (HBA_WWN)) == 0) { 1077 foundWWN = B_TRUE; 1078 break; 1079 } 1080 } 1081 if (discoveredDevList->inqSuccess == B_FALSE) { 1082 responseSize = sizeof (struct scsi_inquiry); 1083 senseSize = sizeof (struct scsi_extended_sense); 1084 memset(&inq, 0, sizeof (struct scsi_inquiry)); 1085 memset(&sense, 0, sizeof (sense)); 1086 status = HBA_ScsiInquiryV2( 1087 handle, 1088 initiatorPortWWN, 1089 entry.FcpId.PortWWN, 1090 entry.FcpId.FcpLun, 1091 0, /* CDB Byte 1 */ 1092 0, /* CDB Byte 2 */ 1093 &inq, &responseSize, 1094 &inq_status, 1095 &sense, &senseSize); 1096 if (status == HBA_STATUS_OK) { 1097 memcpy(discoveredDevList->VID, inq.inq_vid, 1098 sizeof (discoveredDevList->VID)); 1099 memcpy(discoveredDevList->PID, inq.inq_pid, 1100 sizeof (discoveredDevList->PID)); 1101 discoveredDevList->dType = inq.inq_dtype; 1102 discoveredDevList->inqSuccess = B_TRUE; 1103 } 1104 } 1105 1106 if (foundWWN == B_FALSE) { 1107 newWWN = (portWWNList *)calloc(1, sizeof (portWWNList)); 1108 if (newWWN == NULL) { 1109 perror("Out of memory"); 1110 exit(1); 1111 } 1112 1113 /* insert at head */ 1114 newWWN->next = discoveredDevList->HBAPortWWN; 1115 discoveredDevList->HBAPortWWN = newWWN; 1116 memcpy((void *)&(newWWN->portWWN), 1117 (void *)&initiatorPortWWN, 1118 sizeof (newWWN->portWWN)); 1119 /* add Target Port */ 1120 newWWN->tgtPortWWN = (tgtPortWWNList *)calloc(1, 1121 sizeof (tgtPortWWNList)); 1122 if (newWWN->tgtPortWWN == NULL) { 1123 perror("Out of memory"); 1124 exit(1); 1125 } 1126 1127 memcpy((void *)&(newWWN->tgtPortWWN->portWWN), 1128 (void *)&(entry.FcpId.PortWWN), 1129 sizeof (newWWN->tgtPortWWN->portWWN)); 1130 /* Set LUN data */ 1131 newWWN->tgtPortWWN->scsiOSLun = entry.ScsiId.ScsiOSLun; 1132 } else { /* add it to existing */ 1133 newTgtWWN = (tgtPortWWNList *)calloc(1, 1134 sizeof (tgtPortWWNList)); 1135 if (newTgtWWN == NULL) { 1136 perror("Out of memory"); 1137 exit(1); 1138 } 1139 /* insert at head */ 1140 newTgtWWN->next = WWNList->tgtPortWWN; 1141 WWNList->tgtPortWWN = newTgtWWN; 1142 memcpy((void *)&(newTgtWWN->portWWN), 1143 (void *)&(entry.FcpId.PortWWN), 1144 sizeof (newTgtWWN->portWWN)); 1145 /* Set LUN data */ 1146 newTgtWWN->scsiOSLun = entry.ScsiId.ScsiOSLun; 1147 } 1148 } else { /* add new entry */ 1149 newDevice = (discoveredDevice *)calloc(1, 1150 sizeof (discoveredDevice)); 1151 if (newDevice == NULL) { 1152 perror("Out of memory"); 1153 exit(1); 1154 } 1155 newDevice->next = *devList; /* insert at head */ 1156 *devList = newDevice; /* set new head */ 1157 1158 /* Copy device name */ 1159 strncpy(newDevice->OSDeviceName, entry.ScsiId.OSDeviceName, 1160 sizeof (newDevice->OSDeviceName) - 1); 1161 1162 /* 1163 * if only device names are requested, 1164 * no reason to go any further 1165 */ 1166 if (verbose == B_FALSE) { 1167 return; 1168 } 1169 1170 /* 1171 * copy WWN data 1172 */ 1173 newDevice->HBAPortWWN = (portWWNList *)calloc(1, 1174 sizeof (portWWNList)); 1175 if (newDevice->HBAPortWWN == NULL) { 1176 perror("Out of memory"); 1177 exit(1); 1178 } 1179 memcpy((void *)&(newDevice->HBAPortWWN->portWWN), 1180 (void *)&initiatorPortWWN, sizeof (newWWN->portWWN)); 1181 1182 newDevice->HBAPortWWN->tgtPortWWN = 1183 (tgtPortWWNList *)calloc(1, sizeof (tgtPortWWNList)); 1184 if (newDevice->HBAPortWWN->tgtPortWWN == NULL) { 1185 perror("Out of memory"); 1186 exit(1); 1187 } 1188 1189 memcpy((void *)&(newDevice->HBAPortWWN->tgtPortWWN->portWWN), 1190 (void *)&(entry.FcpId.PortWWN), 1191 sizeof (newDevice->HBAPortWWN->tgtPortWWN->portWWN)); 1192 1193 /* Set LUN data */ 1194 newDevice->HBAPortWWN->tgtPortWWN->scsiOSLun = 1195 entry.ScsiId.ScsiOSLun; 1196 1197 responseSize = sizeof (struct scsi_inquiry); 1198 senseSize = sizeof (struct scsi_extended_sense); 1199 memset(&inq, 0, sizeof (struct scsi_inquiry)); 1200 memset(&sense, 0, sizeof (sense)); 1201 status = HBA_ScsiInquiryV2( 1202 handle, 1203 initiatorPortWWN, 1204 entry.FcpId.PortWWN, 1205 entry.FcpId.FcpLun, 1206 0, /* CDB Byte 1 */ 1207 0, /* CDB Byte 2 */ 1208 &inq, &responseSize, 1209 &inq_status, 1210 &sense, &senseSize); 1211 if (status != HBA_STATUS_OK) { 1212 /* initialize VID/PID/dType as "Unknown" */ 1213 strcpy(newDevice->VID, "Unknown"); 1214 strcpy(newDevice->PID, "Unknown"); 1215 newDevice->dType = DTYPE_UNKNOWN; 1216 /* initialize inq status */ 1217 newDevice->inqSuccess = B_FALSE; 1218 } else { 1219 memcpy(newDevice->VID, inq.inq_vid, 1220 sizeof (newDevice->VID)); 1221 memcpy(newDevice->PID, inq.inq_pid, 1222 sizeof (newDevice->PID)); 1223 newDevice->dType = inq.inq_dtype; 1224 /* initialize inq status */ 1225 newDevice->inqSuccess = B_TRUE; 1226 } 1227 } 1228 } 1229 1230 1231 /* 1232 * process the logical-unit object 1233 * 1234 * Arguments: 1235 * luCount - count of the number of device paths in paths_argv 1236 * if pathCount > 0, then we will only print information for 1237 * the device paths listed in paths_argv 1238 * if pathCount == 0, then we will print information on all device 1239 * paths 1240 * luArgv - argument array of device paths 1241 * options - any options specified by the caller 1242 * 1243 * returns: 1244 * 0 if successful 1245 * > 0 otherwise 1246 */ 1247 int 1248 fc_util_list_logicalunit(int luCount, char **luArgv, cmdOptions_t *options) 1249 { 1250 int pathCtr, numAdapters, i, count; 1251 HBA_STATUS status; 1252 char adapterName[256]; 1253 HBA_HANDLE handle; 1254 HBA_PORTATTRIBUTES port; 1255 HBA_ADAPTERATTRIBUTES attrs; 1256 int portIndex = 0; 1257 int ret = 0; 1258 boolean_t verbose = B_FALSE; 1259 HBA_FCPTARGETMAPPINGV2 *map = NULL; 1260 discoveredDevice *devListWalk, *devList = NULL; 1261 boolean_t pathFound; 1262 1263 /* process each of the options */ 1264 for (; options->optval; options++) { 1265 if (options->optval == 'v') { 1266 verbose = B_TRUE; 1267 } 1268 } 1269 1270 if ((status = HBA_LoadLibrary()) != HBA_STATUS_OK) { 1271 fprintf(stderr, 1272 gettext("Failed to load FC-HBA common library\n")); 1273 printStatus(status); 1274 fprintf(stderr, "\n"); 1275 return (1); 1276 } 1277 /* 1278 * Retrieve all device paths. We'll need to traverse the list 1279 * until we find the input paths or all paths if none were given. We 1280 * cannot print as we go since there can be duplicate paths returned 1281 */ 1282 numAdapters = HBA_GetNumberOfAdapters(); 1283 if (numAdapters == 0) { 1284 return (0); 1285 } 1286 for (i = 0; i < numAdapters; i++) { 1287 int times; 1288 status = HBA_GetAdapterName(i, adapterName); 1289 if (status != HBA_STATUS_OK) { 1290 fprintf(stderr, gettext( 1291 "Failed to get adapter %d. Reason: "), i); 1292 printStatus(status); 1293 fprintf(stderr, "\n"); 1294 ret++; 1295 continue; 1296 } 1297 if ((handle = HBA_OpenAdapter(adapterName)) == 0) { 1298 fprintf(stderr, gettext("Failed to open adapter %s\n"), 1299 adapterName); 1300 ret++; 1301 continue; 1302 } 1303 /* get adapter attributes for the given handle */ 1304 memset(&attrs, 0, sizeof (attrs)); 1305 times = 0; 1306 status = HBA_GetAdapterAttributes(handle, &attrs); 1307 while ((status == HBA_STATUS_ERROR_TRY_AGAIN || 1308 status == HBA_STATUS_ERROR_BUSY) && 1309 times++ < HBA_MAX_RETRIES) { 1310 (void) sleep(1); 1311 status = HBA_GetAdapterAttributes(handle, &attrs); 1312 if (status == HBA_STATUS_OK) { 1313 break; 1314 } 1315 } 1316 if (status != HBA_STATUS_OK) { 1317 fprintf(stderr, 1318 gettext("Failed to get adapter attributes " 1319 "handle(%d) Reason: "), handle); 1320 printStatus(status); 1321 fprintf(stderr, "\n"); 1322 ret++; 1323 HBA_CloseAdapter(handle); 1324 continue; 1325 } 1326 1327 /* process each port on adapter */ 1328 for (portIndex = 0; portIndex < attrs.NumberOfPorts; 1329 portIndex++) { 1330 memset(&port, 0, sizeof (port)); 1331 if ((status = HBA_GetAdapterPortAttributes(handle, 1332 portIndex, &port)) != HBA_STATUS_OK) { 1333 /* 1334 * not able to get port attributes. 1335 * print out error message and move 1336 * on to the next port 1337 */ 1338 fprintf(stderr, gettext("Failed to get port " 1339 "(%d) attributes reason: "), 1340 portIndex); 1341 printStatus(status); 1342 fprintf(stderr, "\n"); 1343 ret++; 1344 continue; 1345 } 1346 1347 /* get OS Device Paths */ 1348 getTargetMapping(handle, port.PortWWN, &map); 1349 if (map != NULL) { 1350 for (count = 0; count < map->NumberOfEntries; 1351 count++) { 1352 searchDevice(&devList, 1353 map->entry[count], port.PortWWN, 1354 handle, verbose); 1355 } 1356 } 1357 } 1358 HBA_CloseAdapter(handle); 1359 } 1360 HBA_FreeLibrary(); 1361 1362 if (luCount == 0) { 1363 /* list all paths */ 1364 for (devListWalk = devList; devListWalk != NULL; 1365 devListWalk = devListWalk->next) { 1366 printOSDeviceNameInfo(devListWalk, verbose); 1367 } 1368 } else { 1369 /* 1370 * list any paths not found first 1371 * this gives the user cleaner output 1372 */ 1373 for (pathCtr = 0; pathCtr < luCount; pathCtr++) { 1374 for (devListWalk = devList, pathFound = B_FALSE; 1375 devListWalk != NULL; 1376 devListWalk = devListWalk->next) { 1377 if (strcmp(devListWalk->OSDeviceName, 1378 luArgv[pathCtr]) == 0) { 1379 pathFound = B_TRUE; 1380 } 1381 } 1382 if (pathFound == B_FALSE) { 1383 fprintf(stderr, "%s: no such path\n", 1384 luArgv[pathCtr]); 1385 ret++; 1386 } 1387 } 1388 /* list all paths requested in order requested */ 1389 for (pathCtr = 0; pathCtr < luCount; pathCtr++) { 1390 for (devListWalk = devList; devListWalk != NULL; 1391 devListWalk = devListWalk->next) { 1392 if (strcmp(devListWalk->OSDeviceName, 1393 luArgv[pathCtr]) == 0) { 1394 printOSDeviceNameInfo(devListWalk, 1395 verbose); 1396 } 1397 } 1398 } 1399 } 1400 return (ret); 1401 } 1402