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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
40 typedef struct rep_luns_rsp
{
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
,
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
);
65 * This function retrieve the adapater attributes, port attributes, and
66 * portIndex for the given handle and hba port WWN.
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.
80 * 0 successfully retrieve all information
84 retrieveAttrs(HBA_HANDLE handle
, HBA_WWN hbaPortWWN
,
85 HBA_ADAPTERATTRIBUTES
*attrs
, HBA_PORTATTRIBUTES
*port
, int *portIndex
)
91 /* argument checking */
92 if (attrs
== NULL
|| port
== NULL
|| portIndex
== NULL
) {
93 fprintf(stderr
, gettext("Error: Invalid arguments to "
98 /* retrieve Adapter attributes */
99 memset(attrs
, 0, sizeof (HBA_ADAPTERATTRIBUTES
));
100 status
= HBA_GetAdapterAttributes(handle
, attrs
);
102 while ((status
== HBA_STATUS_ERROR_TRY_AGAIN
||
103 status
== HBA_STATUS_ERROR_BUSY
) &&
104 times
++ < HBA_MAX_RETRIES
) {
106 status
= HBA_GetAdapterAttributes(handle
, attrs
);
107 if (status
== HBA_STATUS_OK
) {
111 if (status
!= HBA_STATUS_OK
) {
112 fprintf(stderr
, gettext("Failed to get adapter "
113 "attributes handle(%d) Reason: "), handle
);
115 fprintf(stderr
, "\n");
120 * find the corresponding port on the adapter and retrieve
121 * port attributes as well as the port index
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
) {
128 gettext("Error: Failed to get port (%d) "
129 "attributes reason: "), portCtr
);
131 fprintf(stderr
, "\n");
134 if (memcmp(hbaPortWWN
.wwn
, port
->PortWWN
.wwn
,
135 sizeof (port
->PortWWN
.wwn
)) == 0) {
139 if (portCtr
>= attrs
->NumberOfPorts
) {
141 * not able to find corresponding port WWN
147 *portIndex
= portCtr
;
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
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
168 getTargetMapping(HBA_HANDLE handle
, HBA_WWN hbaPortWWN
,
169 HBA_FCPTARGETMAPPINGV2
**mapping
)
171 HBA_FCPTARGETMAPPINGV2
*map
;
175 /* argument sanity checking */
176 if (mapping
== NULL
) {
177 fprintf(stderr
, gettext("Internal Error: mapping is NULL"));
181 if ((map
= calloc(1, sizeof (HBA_FCPTARGETMAPPINGV2
))) == NULL
) {
183 gettext("Internal Error: Unable to calloc map"));
186 status
= HBA_GetFcpTargetMappingV2(handle
, hbaPortWWN
, map
);
187 count
= map
->NumberOfEntries
;
188 if (status
== HBA_STATUS_ERROR_MORE_DATA
) {
190 if ((map
= calloc(1, (sizeof (HBA_FCPSCSIENTRYV2
)*(count
-1)) +
191 sizeof (HBA_FCPTARGETMAPPINGV2
))) == NULL
) {
193 gettext("Unable to calloc map of size: %d"), count
);
196 map
->NumberOfEntries
= count
;
197 status
= HBA_GetFcpTargetMappingV2(handle
, hbaPortWWN
, map
);
199 if (status
!= HBA_STATUS_OK
) {
201 gettext("Error: Unable to get Target Mapping\n"));
203 fprintf(stderr
, "\n");
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.
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
219 * remotePortWWN - the port WWN we will be issuing the report lun call to
220 * discPort - PORTATTRIBUTES structure for the remotePortWWN
223 handleRemotePort(HBA_HANDLE handle
, HBA_WWN portWWN
, HBA_WWN remotePortWWN
,
224 HBA_PORTATTRIBUTES
*discPort
)
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
;
234 /* argument checking */
235 if (discPort
== NULL
) {
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
;
249 scsiTargetType
= SCSI_TARGET_TYPE_UNKNOWN
;
251 printDiscoPortInfo(discPort
, scsiTargetType
);
255 * This function will issue the RLS and print out the port statistics for
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
264 printLinkStat(HBA_HANDLE handle
, HBA_WWN hbaPortWWN
, HBA_WWN destWWN
)
267 fc_rls_acc_t rls_payload
;
268 uint32_t rls_payload_size
;
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
));
278 printPortStat(&rls_payload
);
283 printHBANPIVPortInfo(HBA_HANDLE handle
, int portindex
)
285 HBA_PORTNPIVATTRIBUTES portattrs
;
286 HBA_NPIVATTRIBUTES npivattrs
;
291 status
= Sun_HBA_GetPortNPIVAttributes(handle
, portindex
, &portattrs
);
292 while (status
== HBA_STATUS_ERROR_TRY_AGAIN
||
293 status
== HBA_STATUS_ERROR_BUSY
) {
295 status
= Sun_HBA_GetPortNPIVAttributes(
296 handle
, portindex
, &portattrs
);
297 if (times
++ > HBA_MAX_RETRIES
) {
302 if (status
== HBA_STATUS_ERROR_NOT_SUPPORTED
) {
303 fprintf(stdout
, gettext("\tNPIV Not Supported\n"));
307 if (status
!= HBA_STATUS_OK
) {
309 gettext("Error: Failed to get port (%d) "
310 "npiv attributes reason: "), portindex
);
312 fprintf(stderr
, "\n");
315 if (portattrs
.MaxNumberOfNPIVPorts
) {
316 fprintf(stdout
, gettext("\tMax NPIV Ports: %d\n"),
317 portattrs
.MaxNumberOfNPIVPorts
);
319 fprintf(stdout
, gettext("\tNPIV Not Supported\n"));
322 fprintf(stdout
, gettext("\tNPIV port list:\n"));
323 for (index
= 0; index
< portattrs
.NumberOfNPIVPorts
; index
++) {
325 status
= Sun_HBA_GetNPIVPortInfo(handle
,
326 portindex
, index
, &npivattrs
);
327 while (status
== HBA_STATUS_ERROR_TRY_AGAIN
||
328 status
== HBA_STATUS_ERROR_BUSY
) {
330 status
= Sun_HBA_GetNPIVPortInfo(handle
,
331 portindex
, index
, &npivattrs
);
332 if (times
++ > HBA_MAX_RETRIES
) {
337 if (status
!= HBA_STATUS_OK
) {
339 gettext("Error: Failed to get npiv port (%d) "
340 "attributes reason: "), index
);
342 fprintf(stderr
, "\n");
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
));
357 * This function will process hba port, remote port and scsi-target information
358 * for the given handle.
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
367 * 0 sucessfully processed handle
368 * 1 error has occured
371 processHBA(HBA_HANDLE handle
, HBA_ADAPTERATTRIBUTES attrs
, int portIndex
,
372 HBA_PORTATTRIBUTES port
, HBA_FCPTARGETMAPPINGV2
*map
,
373 int resourceType
, int flags
, int mode
)
375 HBA_PORTATTRIBUTES discPort
;
379 if (resourceType
== HBA_PORT
) {
380 if ((flags
& PRINT_FCOE
) == PRINT_FCOE
&&
381 attrs
.VendorSpecificID
!= 0xFC0E) {
384 printHBAPortInfo(&port
, &attrs
, mode
);
385 if ((flags
& PRINT_LINKSTAT
) == PRINT_LINKSTAT
) {
386 printLinkStat(handle
, port
.PortWWN
, port
.PortWWN
);
391 * process each of the remote targets from this hba port
393 for (discPortCount
= 0;
394 discPortCount
< port
.NumberofDiscoveredPorts
;
396 status
= HBA_GetDiscoveredPortAttributes(handle
,
397 portIndex
, discPortCount
, &discPort
);
398 if (status
!= HBA_STATUS_OK
) {
400 gettext("Failed to get discovered port (%d)"
401 " attributes reason :"), discPortCount
);
403 fprintf(stderr
, "\n");
406 if (resourceType
== REMOTE_PORT
) {
407 handleRemotePort(handle
, port
.PortWWN
, discPort
.PortWWN
,
409 if ((flags
& PRINT_LINKSTAT
) == PRINT_LINKSTAT
) {
410 printLinkStat(handle
, port
.PortWWN
,
413 if ((flags
& PRINT_SCSI_TARGET
) == PRINT_SCSI_TARGET
) {
414 handleScsiTarget(handle
, port
.PortWWN
,
415 discPort
.PortWWN
, map
);
423 * This function will process remote port information for the given handle.
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
429 * wwnCount - the number of wwns in wwn_argv
430 * wwn_argv - argument vector of WWNs
433 processRemotePort(HBA_HANDLE handle
, HBA_WWN portWWN
,
434 HBA_FCPTARGETMAPPINGV2
*map
, int wwnCount
, char **wwn_argv
, int flags
)
436 int remote_wwn_counter
;
437 uint64_t remotePortWWN
;
438 HBA_WWN myremotePortWWN
;
439 HBA_PORTATTRIBUTES discPort
;
442 for (remote_wwn_counter
= 0;
443 remote_wwn_counter
< wwnCount
;
444 remote_wwn_counter
++) {
446 sscanf(wwn_argv
[remote_wwn_counter
], "%016llx",
448 remotePortWWN
= htonll(remotePortWWN
);
449 memcpy(myremotePortWWN
.wwn
, &remotePortWWN
,
450 sizeof (remotePortWWN
));
451 memset(&discPort
, 0, sizeof (discPort
));
452 status
= HBA_GetPortAttributesByWWN(handle
, myremotePortWWN
,
454 while (status
== HBA_STATUS_ERROR_TRY_AGAIN
||
455 status
== HBA_STATUS_ERROR_BUSY
) {
457 status
= HBA_GetPortAttributesByWWN(handle
,
458 myremotePortWWN
, &discPort
);
459 if (times
++ > HBA_MAX_RETRIES
) {
463 if (status
!= HBA_STATUS_OK
) {
464 fprintf(stderr
, gettext("HBA_GetPortAttributesByWWN "
465 "failed: reason: "));
467 fprintf(stderr
, "\n");
470 handleRemotePort(handle
, portWWN
, myremotePortWWN
, &discPort
);
471 if ((flags
& PRINT_LINKSTAT
) == PRINT_LINKSTAT
) {
472 printLinkStat(handle
, portWWN
, myremotePortWWN
);
474 if ((flags
& PRINT_SCSI_TARGET
) == PRINT_SCSI_TARGET
) {
475 handleScsiTarget(handle
, portWWN
,
476 myremotePortWWN
, map
);
482 * This function handles printing Scsi target information for remote ports
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
488 * scsiTargetWWN - target port WWN of the remote target the SCSI call is
490 * map - a pointer to the target mapping structure for the given HBA port
493 handleScsiTarget(HBA_HANDLE handle
, HBA_WWN hbaPortWWN
, HBA_WWN scsiTargetWWN
,
494 HBA_FCPTARGETMAPPINGV2
*map
)
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
;
505 int lunNum
, numberOfLun
, lunCount
, count
;
506 uint32_t lunlength
, tmp_lunlength
;
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
);
515 * if HBA_STATUS_ERROR_NOT_A_TARGET is return, we can assume this is
516 * a remote HBA and move on
518 if (status
== HBA_STATUS_ERROR_NOT_A_TARGET
) {
520 } else if (status
!= HBA_STATUS_OK
) {
521 fprintf(stderr
, gettext("Error has occured. "
522 "HBA_ScsiReportLUNsV2 failed. reason "));
524 fprintf(stderr
, "\n");
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
++) {
533 * now issue standard inquiry to get Vendor
534 * and product information
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(
551 if (status
!= HBA_STATUS_OK
) {
552 fprintf(stderr
, gettext("Not able to issue Inquiry.\n"));
554 fprintf(stderr
, "\n");
555 strcpy(inq
.inq_vid
, "Unknown");
556 strcpy(inq
.inq_pid
, "Unknown");
559 for (count
= 0; count
< map
->NumberOfEntries
; count
++) {
560 if ((memcmp(map
->entry
[count
].FcpId
.PortWWN
.wwn
,
562 sizeof (scsiTargetWWN
.wwn
))
564 (memcmp(&(map
->entry
[count
].FcpId
.FcpLun
),
565 &fcLUN
, sizeof (fcLUN
)) == 0)) {
567 map
->entry
[count
].ScsiId
.ScsiOSLun
,
568 map
->entry
[count
].ScsiId
.OSDeviceName
);
572 if (count
== map
->NumberOfEntries
) {
573 lun_string
= lun_resp
->lun
[lunCount
].val
;
574 lunNum
= ((lun_string
[0] & 0x3F) << 8) |
576 printLUNInfo(&inq
, lunNum
, "Unknown");
579 /* Not able to get any target mapping information */
580 lun_string
= lun_resp
->lun
[lunCount
].val
;
581 lunNum
= ((lun_string
[0] & 0x3F) << 8) |
583 printLUNInfo(&inq
, lunNum
, "Unknown");
589 * function to handle the list remoteport command
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
597 * wwn_argv - argument vector of WWNs
598 * options - any options specified by the caller
605 fc_util_list_remoteport(int wwnCount
, char **wwn_argv
, cmdOptions_t
*options
)
608 HBA_FCPTARGETMAPPINGV2
*map
= NULL
;
609 HBA_PORTATTRIBUTES port
;
610 HBA_ADAPTERATTRIBUTES attrs
;
613 HBA_WWN myhbaPortWWN
;
614 int processHBA_flags
= 0, portCount
= 0;
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",
622 } else if (options
->optval
== 's') {
623 processHBA_flags
|= PRINT_SCSI_TARGET
;
624 } else if (options
->optval
== 'l') {
625 processHBA_flags
|= PRINT_LINKSTAT
;
627 fprintf(stderr
, gettext("Error: Illegal option: %c.\n"),
633 * -h option was not specified, this should not happen either.
634 * cmdparse should catch this problem, but checking anyways
636 if (hbaPortWWN
== 0) {
638 gettext("Error: -p option was not specified.\n"));
641 if ((status
= HBA_LoadLibrary()) != HBA_STATUS_OK
) {
643 gettext("Failed to load FC-HBA common library\n"));
645 fprintf(stderr
, "\n");
648 hbaPortWWN
= htonll(hbaPortWWN
);
649 memcpy(myhbaPortWWN
.wwn
, &hbaPortWWN
, sizeof (hbaPortWWN
));
650 if ((status
= HBA_OpenAdapterByWWN(&handle
, myhbaPortWWN
))
652 status
= Sun_HBA_OpenTgtAdapterByWWN(&handle
, myhbaPortWWN
);
653 if (status
!= HBA_STATUS_OK
) {
655 gettext("Error: Failed to open adapter port. Reason "));
657 fprintf(stderr
, "\n");
661 if ((processHBA_flags
& PRINT_SCSI_TARGET
) ==
663 fprintf(stderr
, gettext(
664 "Error: Unsupported option for target mode: %c.\n"),
672 mode
= INITIATOR_MODE
;
675 if ((processHBA_flags
& PRINT_SCSI_TARGET
) == PRINT_SCSI_TARGET
) {
676 getTargetMapping(handle
, myhbaPortWWN
, &map
);
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
,
687 HBA_CloseAdapter(handle
);
691 processHBA(handle
, attrs
, portCount
, port
, map
, REMOTE_PORT
,
692 processHBA_flags
, mode
);
694 processRemotePort(handle
, myhbaPortWWN
, map
, wwnCount
,
695 wwn_argv
, processHBA_flags
);
700 HBA_CloseAdapter(handle
);
706 * process the hbaport object
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
721 fc_util_list_hbaport(int wwnCount
, char **wwn_argv
, cmdOptions_t
*options
)
723 int port_wwn_counter
, numAdapters
= 0, numTgtAdapters
= 0, i
;
725 char adapterName
[256];
729 int processHBA_flags
= 0;
730 HBA_PORTATTRIBUTES port
;
731 HBA_ADAPTERATTRIBUTES attrs
;
732 int portIndex
= 0, err_cnt
= 0;
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
;
749 * Print both initiator and target if no initiator/target flag
752 if (((processHBA_flags
& PRINT_INITIATOR
) == 0) &&
753 ((processHBA_flags
& PRINT_TARGET
) == 0)) {
754 processHBA_flags
|= PRINT_INITIATOR
| PRINT_TARGET
;
757 if ((status
= HBA_LoadLibrary()) != HBA_STATUS_OK
) {
759 gettext("Failed to load FC-HBA common library\n"));
761 fprintf(stderr
, "\n");
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
) ==
776 status
= HBA_OpenAdapterByWWN(&handle
, myWWN
);
777 while (status
== HBA_STATUS_ERROR_TRY_AGAIN
||
778 status
== HBA_STATUS_ERROR_BUSY
) {
780 status
= HBA_OpenAdapterByWWN(&handle
, myWWN
);
781 if (times
++ > HBA_MAX_RETRIES
) {
785 if (status
!= HBA_STATUS_OK
) {
786 /* now see if it is a target mode FC port */
787 if ((processHBA_flags
& PRINT_TARGET
) ==
790 Sun_HBA_OpenTgtAdapterByWWN(&handle
, myWWN
);
791 if (status
!= HBA_STATUS_OK
) {
794 "Error: HBA port %s: not found\n"),
795 wwn_argv
[port_wwn_counter
]);
799 /* set the port mode. */
805 "Error: HBA port %s: not found\n"),
806 wwn_argv
[port_wwn_counter
]);
811 /* set the port mode. */
812 mode
= INITIATOR_MODE
;
814 /* try target mode discovery if print target is set. */
815 } else if ((processHBA_flags
& PRINT_TARGET
) ==
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
]);
826 /* set the port mode. */
830 /* should not get here. */
831 fprintf(stderr
, gettext(
832 "Error: HBA port %s: not found\n"),
833 wwn_argv
[port_wwn_counter
]);
837 memset(&attrs
, 0, sizeof (attrs
));
838 memset(&port
, 0, sizeof (port
));
839 if (retrieveAttrs(handle
, myWWN
, &attrs
, &port
,
841 HBA_CloseAdapter(handle
);
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) {
851 HBA_CloseAdapter(handle
);
855 * if PRINT_INITIATOR is specified, get the list of initiator
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"));
864 for (i
= 0; i
< numAdapters
; i
++) {
866 status
= HBA_GetAdapterName(i
, adapterName
);
867 if (status
!= HBA_STATUS_OK
) {
868 fprintf(stderr
, gettext(
869 "failed to get adapter %d. Reason: "), i
);
871 fprintf(stderr
, "\n");
874 if ((handle
= HBA_OpenAdapter(adapterName
)) == 0) {
875 fprintf(stderr
, gettext(
876 "Failed to open adapter %s.\n"),
880 /* get adapater attributes for the given handle */
881 memset(&attrs
, 0, sizeof (attrs
));
883 Sun_HBA_NPIVGetAdapterAttributes(handle
,
885 while ((status
== HBA_STATUS_ERROR_TRY_AGAIN
||
886 status
== HBA_STATUS_ERROR_BUSY
) &&
887 times
++ < HBA_MAX_RETRIES
) {
890 Sun_HBA_NPIVGetAdapterAttributes(handle
,
892 if (status
== HBA_STATUS_OK
) {
896 if (status
!= HBA_STATUS_OK
) {
898 gettext("Failed to get adapter attributes "
899 "handle(%d) Reason: "), handle
);
901 fprintf(stderr
, "\n");
902 HBA_CloseAdapter(handle
);
906 /* process each port on the given adatpter */
908 portIndex
< attrs
.NumberOfPorts
;
910 memset(&port
, 0, sizeof (port
));
911 if ((status
= HBA_GetAdapterPortAttributes(
912 handle
, portIndex
, &port
))
915 * not able to get port attributes.
916 * print out error * message and move
917 * on to the next port
920 gettext("Error: Failed to get port "
921 "(%d) attributes reason: "),
924 fprintf(stderr
, "\n");
927 processHBA(handle
, attrs
, portIndex
, port
,
928 NULL
, HBA_PORT
, processHBA_flags
,
930 if ((processHBA_flags
& PRINT_FCOE
) !=
932 attrs
.VendorSpecificID
!= 0xFC0E &&
933 printHBANPIVPortInfo(handle
,
938 HBA_CloseAdapter(handle
);
943 * Get the info on the target mode FC port if PRINT_TARGET
946 if ((processHBA_flags
& PRINT_TARGET
) == PRINT_TARGET
) {
947 numTgtAdapters
= Sun_HBA_GetNumberOfTgtAdapters();
948 if (numTgtAdapters
== 0 && numAdapters
== 0) {
950 gettext("No Adapters Found.\n"));
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
);
958 fprintf(stderr
, "\n");
961 if ((handle
= Sun_HBA_OpenTgtAdapter(adapterName
))
963 fprintf(stderr
, gettext(
964 "Failed to open adapter %s.\n"), adapterName
);
967 /* get adapater attributes for the given handle */
968 memset(&attrs
, 0, sizeof (attrs
));
969 if ((status
= HBA_GetAdapterAttributes(handle
, &attrs
))
972 gettext("Failed to get target mode adapter"
973 "attributes handle(%d) Reason: "),
976 fprintf(stderr
, "\n");
980 /* process each port on the given adatpter */
982 portIndex
< attrs
.NumberOfPorts
;
984 memset(&port
, 0, sizeof (port
));
985 if ((status
= HBA_GetAdapterPortAttributes(
986 handle
, portIndex
, &port
))
989 * not able to get port attributes.
990 * print out error * message and move
991 * on to the next port
994 gettext("Error: Failed to get port "
995 "(%d) attributes reason: "),
998 fprintf(stderr
, "\n");
1001 processHBA(handle
, attrs
, portIndex
, port
,
1002 NULL
, HBA_PORT
, processHBA_flags
,
1005 HBA_CloseAdapter(handle
);
1013 * print additional error msg for partial failure when more than
1014 * one wwn is specified.
1018 if (err_cnt
== wwnCount
) {
1019 fprintf(stderr
, gettext(
1020 "Error: All specified HBA ports are not found\n"));
1022 fprintf(stderr
, gettext(
1023 "Error: Some of specified HBA ports are not found\n"));
1033 * Search the existing device list
1035 * Take one of two actions:
1037 * Add an entry if an entry doesn't exist
1038 * Add WWN data to it if an entry does exist
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
1051 searchDevice(discoveredDevice
**devList
, HBA_FCPSCSIENTRYV2 entry
,
1052 HBA_WWN initiatorPortWWN
, HBA_HANDLE handle
, boolean_t verbose
)
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
;
1064 for (discoveredDevList
= *devList
; discoveredDevList
!= NULL
;
1065 discoveredDevList
= discoveredDevList
->next
) {
1066 if (strcmp(entry
.ScsiId
.OSDeviceName
,
1067 discoveredDevList
->OSDeviceName
) == 0) {
1069 * if only device names are requested,
1070 * no reason to go any further
1072 if (verbose
== B_FALSE
) {
1075 foundDevice
= B_TRUE
;
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) {
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(
1099 entry
.FcpId
.PortWWN
,
1103 &inq
, &responseSize
,
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
;
1116 if (foundWWN
== B_FALSE
) {
1117 newWWN
= (portWWNList
*)calloc(1, sizeof (portWWNList
));
1118 if (newWWN
== NULL
) {
1119 perror("Out of memory");
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");
1137 memcpy((void *)&(newWWN
->tgtPortWWN
->portWWN
),
1138 (void *)&(entry
.FcpId
.PortWWN
),
1139 sizeof (newWWN
->tgtPortWWN
->portWWN
));
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");
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
));
1156 newTgtWWN
->scsiOSLun
= entry
.ScsiId
.ScsiOSLun
;
1158 } else { /* add new entry */
1159 newDevice
= (discoveredDevice
*)calloc(1,
1160 sizeof (discoveredDevice
));
1161 if (newDevice
== NULL
) {
1162 perror("Out of memory");
1165 newDevice
->next
= *devList
; /* insert at head */
1166 *devList
= newDevice
; /* set new head */
1168 /* Copy device name */
1169 strncpy(newDevice
->OSDeviceName
, entry
.ScsiId
.OSDeviceName
,
1170 sizeof (newDevice
->OSDeviceName
) - 1);
1173 * if only device names are requested,
1174 * no reason to go any further
1176 if (verbose
== B_FALSE
) {
1183 newDevice
->HBAPortWWN
= (portWWNList
*)calloc(1,
1184 sizeof (portWWNList
));
1185 if (newDevice
->HBAPortWWN
== NULL
) {
1186 perror("Out of memory");
1189 memcpy((void *)&(newDevice
->HBAPortWWN
->portWWN
),
1190 (void *)&initiatorPortWWN
, sizeof (newWWN
->portWWN
));
1192 newDevice
->HBAPortWWN
->tgtPortWWN
=
1193 (tgtPortWWNList
*)calloc(1, sizeof (tgtPortWWNList
));
1194 if (newDevice
->HBAPortWWN
->tgtPortWWN
== NULL
) {
1195 perror("Out of memory");
1199 memcpy((void *)&(newDevice
->HBAPortWWN
->tgtPortWWN
->portWWN
),
1200 (void *)&(entry
.FcpId
.PortWWN
),
1201 sizeof (newDevice
->HBAPortWWN
->tgtPortWWN
->portWWN
));
1204 newDevice
->HBAPortWWN
->tgtPortWWN
->scsiOSLun
=
1205 entry
.ScsiId
.ScsiOSLun
;
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(
1214 entry
.FcpId
.PortWWN
,
1218 &inq
, &responseSize
,
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
;
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
;
1242 * process the logical-unit object
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
1250 * luArgv - argument array of device paths
1251 * options - any options specified by the caller
1258 fc_util_list_logicalunit(int luCount
, char **luArgv
, cmdOptions_t
*options
)
1260 int pathCtr
, numAdapters
, i
, count
;
1262 char adapterName
[256];
1264 HBA_PORTATTRIBUTES port
;
1265 HBA_ADAPTERATTRIBUTES attrs
;
1268 boolean_t verbose
= B_FALSE
;
1269 HBA_FCPTARGETMAPPINGV2
*map
= NULL
;
1270 discoveredDevice
*devListWalk
, *devList
= NULL
;
1271 boolean_t pathFound
;
1273 /* process each of the options */
1274 for (; options
->optval
; options
++) {
1275 if (options
->optval
== 'v') {
1280 if ((status
= HBA_LoadLibrary()) != HBA_STATUS_OK
) {
1282 gettext("Failed to load FC-HBA common library\n"));
1283 printStatus(status
);
1284 fprintf(stderr
, "\n");
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
1292 numAdapters
= HBA_GetNumberOfAdapters();
1293 if (numAdapters
== 0) {
1296 for (i
= 0; i
< numAdapters
; i
++) {
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");
1307 if ((handle
= HBA_OpenAdapter(adapterName
)) == 0) {
1308 fprintf(stderr
, gettext("Failed to open adapter %s\n"),
1313 /* get adapter attributes for the given handle */
1314 memset(&attrs
, 0, sizeof (attrs
));
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
) {
1321 status
= HBA_GetAdapterAttributes(handle
, &attrs
);
1322 if (status
== HBA_STATUS_OK
) {
1326 if (status
!= HBA_STATUS_OK
) {
1328 gettext("Failed to get adapter attributes "
1329 "handle(%d) Reason: "), handle
);
1330 printStatus(status
);
1331 fprintf(stderr
, "\n");
1333 HBA_CloseAdapter(handle
);
1337 /* process each port on adapter */
1338 for (portIndex
= 0; portIndex
< attrs
.NumberOfPorts
;
1340 memset(&port
, 0, sizeof (port
));
1341 if ((status
= HBA_GetAdapterPortAttributes(handle
,
1342 portIndex
, &port
)) != HBA_STATUS_OK
) {
1344 * not able to get port attributes.
1345 * print out error message and move
1346 * on to the next port
1348 fprintf(stderr
, gettext("Failed to get port "
1349 "(%d) attributes reason: "),
1351 printStatus(status
);
1352 fprintf(stderr
, "\n");
1357 /* get OS Device Paths */
1358 getTargetMapping(handle
, port
.PortWWN
, &map
);
1360 for (count
= 0; count
< map
->NumberOfEntries
;
1362 searchDevice(&devList
,
1363 map
->entry
[count
], port
.PortWWN
,
1368 HBA_CloseAdapter(handle
);
1373 /* list all paths */
1374 for (devListWalk
= devList
; devListWalk
!= NULL
;
1375 devListWalk
= devListWalk
->next
) {
1376 printOSDeviceNameInfo(devListWalk
, verbose
);
1380 * list any paths not found first
1381 * this gives the user cleaner output
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) {
1392 if (pathFound
== B_FALSE
) {
1393 fprintf(stderr
, "%s: no such path\n",
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
,