"Fossies" - the Fresh Open Source Software Archive

Member "open-fcoe-3.19/fcoe-utils/fcoeadm_display.c" (15 Apr 2015, 38806 Bytes) of package /linux/misc/open-fcoe-3.19.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "fcoeadm_display.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.11_vs_3.19.

    1 /*
    2  * Copyright(c) 2010 Intel Corporation. All rights reserved.
    3  *
    4  * This program is free software; you can redistribute it and/or modify it
    5  * under the terms and conditions of the GNU General Public License,
    6  * version 2, as published by the Free Software Foundation.
    7  *
    8  * This program is distributed in the hope it will be useful, but WITHOUT
    9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   11  * more details.
   12  *
   13  * You should have received a copy of the GNU General Public License along with
   14  * this program; if not, write to the Free Software Foundation, Inc.,
   15  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
   16  *
   17  * Maintained at www.Open-FCoE.org
   18  */
   19 
   20 #include <sys/param.h>
   21 #include <sys/ioctl.h>
   22 #include <linux/types.h>
   23 #include <ctype.h>
   24 #include <stddef.h>
   25 #include <stdio.h>
   26 #include <stdlib.h>
   27 #include <stdarg.h>
   28 #include <time.h>
   29 #include <malloc.h>
   30 #include <pthread.h>
   31 #include <limits.h>
   32 #include <scsi/sg.h>
   33 #include <byteswap.h>
   34 #include <net/if.h>
   35 #include <unistd.h>
   36 #include <inttypes.h>
   37 
   38 #include "net_types.h"
   39 #include "fc_types.h"
   40 #include "fc_scsi.h"
   41 #include "hbaapi.h"
   42 #include "fcoeadm_display.h"
   43 #include "fcoe_utils.h"
   44 #include "fcoemon_utils.h"
   45 #include "libopenfcoe.h"
   46 
   47 /* #define TEST_HBAAPI_V1 */
   48 #ifdef TEST_HBAAPI_V1
   49 #define HBA_FCP_SCSI_ENTRY   HBA_FCPSCSIENTRY
   50 #define HBA_FCP_TARGET_MAPPING HBA_FCPTARGETMAPPING
   51 #else
   52 #define HBA_FCP_SCSI_ENTRY   HBA_FCPSCSIENTRYV2
   53 #define HBA_FCP_TARGET_MAPPING HBA_FCPTARGETMAPPINGV2
   54 #endif
   55 /* #define TEST_REPORT_LUNS */
   56 /* #define TEST_READ_CAP_V1 */
   57 /* #define TEST_DEV_SERIAL_NO */
   58 
   59 /* Define FC4 Type */
   60 #define FC_TYPE_FCP        0x08 /* SCSI FCP */
   61 
   62 /* Constant defined in fcoe_def.h of fcoe driver */
   63 #define FCOE_WORD_TO_BYTE  4
   64 
   65 /* Minimum byte size of the received inquiry data */
   66 #define MIN_INQ_DATA_SIZE       36
   67 
   68 #define FCP_TARG_STR "FCP Target"
   69 
   70 #define SYSFS_HOST_DIR     "/sys/class/fc_host"
   71 
   72 /*
   73  * HBA and port objects are one-to-one since there
   74  * is one host created per Ethernet port (vlan).
   75  */
   76 struct hba_name_table {
   77     HBA_HANDLE            hba_handle;
   78     HBA_ADAPTERATTRIBUTES hba_attrs;
   79     HBA_PORTATTRIBUTES    port_attrs;
   80     int                   failed;
   81     int                   displayed;
   82 };
   83 
   84 /*
   85  * List of HBA objects.
   86  */
   87 struct hba_name_table_list {
   88     int         hba_count;
   89     struct hba_name_table   hba_table[1];
   90 };
   91 
   92 struct sa_nameval port_states[] = {
   93     { "Not Present",    HBA_PORTSTATE_UNKNOWN },
   94     { "Online",         HBA_PORTSTATE_ONLINE },
   95     { "Offline",        HBA_PORTSTATE_OFFLINE },
   96     { "Blocked",        HBA_PORTSTATE_UNKNOWN },
   97     { "Bypassed",       HBA_PORTSTATE_BYPASSED },
   98     { "Diagnostics",    HBA_PORTSTATE_DIAGNOSTICS },
   99     { "Linkdown",       HBA_PORTSTATE_LINKDOWN },
  100     { "Error",          HBA_PORTSTATE_ERROR },
  101     { "Loopback",       HBA_PORTSTATE_LOOPBACK },
  102     { "Deleted",        HBA_PORTSTATE_UNKNOWN },
  103     { NULL, 0 }
  104 };
  105 
  106 /*
  107  * table of /sys port speed strings to HBA-API values.
  108  */
  109 struct sa_nameval port_speeds[] = {
  110     { "Unknown",        HBA_PORTSPEED_UNKNOWN },
  111     { "1 Gbit",         HBA_PORTSPEED_1GBIT },
  112     { "2 Gbit",         HBA_PORTSPEED_2GBIT },
  113     { "4 Gbit",         HBA_PORTSPEED_4GBIT },
  114     { "10 Gbit",        HBA_PORTSPEED_10GBIT },
  115     { "8 Gbit",         HBA_PORTSPEED_8GBIT },
  116     { "16 Gbit",        HBA_PORTSPEED_16GBIT },
  117     { "32 Gbit",        HBA_PORTSPEED_32GBIT },
  118     { "20 Gbit",        HBA_PORTSPEED_20GBIT },
  119     { "40 Gbit",        HBA_PORTSPEED_40GBIT },
  120     { "Not Negotiated", HBA_PORTSPEED_NOT_NEGOTIATED },
  121     { NULL, 0 }
  122 };
  123 
  124 /** sa_enum_decode_speed(buf, len, val)
  125  *
  126  * @param buf buffer for result (may be used or not).
  127  * @param len size of buffer (at least 32 bytes recommended).
  128  * @param val value to be decoded into a name.
  129  * @returns pointer to name string.  Unknown values are put into buffer in hex.
  130  * Uses the port_speeds table to decode speed from value
  131  */
  132 static const char *
  133 sa_enum_decode_speed(char *buf, size_t buflen,
  134              u_int32_t val)
  135 {
  136     char *prefix = "";
  137     size_t len;
  138     struct sa_nameval *tp = port_speeds;
  139     char *cp = buf;
  140 
  141     snprintf(buf, buflen, "Unknown");
  142     for (; tp->nv_name != NULL; tp++) {
  143         if (tp->nv_val & val) {
  144             len = snprintf(cp, buflen, "%s%s", prefix, tp->nv_name);
  145             if (len == 0 || len >= buflen)
  146                 break;
  147             cp += len;
  148             buflen -= len;
  149             prefix = ", ";
  150         }
  151     }
  152 
  153     return buf;
  154 }
  155 
  156 static void
  157 sa_dump_wwn(void *Data, int Length, int Break)
  158 {
  159     unsigned char *pc = (unsigned char *)Data;
  160     int i;
  161 
  162     for (i = 1; i <= Length; i++) {
  163         printf("%02X", (int)*pc++);
  164         if ((Break != 0) && (!(i % Break)))
  165             printf("     ");
  166     }
  167 }
  168 
  169 static int is_fcp_target(HBA_PORTATTRIBUTES *rp_info)
  170 {
  171     char buf[MAX_STR_LEN];
  172 
  173     if (sa_sys_read_line(rp_info->OSDeviceName, "roles", buf, sizeof(buf)))
  174         return -EINVAL;
  175 
  176     if (!strncmp(buf, FCP_TARG_STR, strlen(FCP_TARG_STR)))
  177         return 0;
  178 
  179     return -EINVAL;
  180 }
  181 
  182 static void show_wwn(unsigned char *pWwn)
  183 {
  184     sa_dump_wwn(pWwn, 8, 0);
  185 }
  186 
  187 static void show_hba_info(HBA_ADAPTERATTRIBUTES *hba_info)
  188 {
  189     printf("    Description:      %s\n", hba_info->ModelDescription);
  190     printf("    Revision:         %s\n", hba_info->HardwareVersion);
  191     printf("    Manufacturer:     %s\n", hba_info->Manufacturer);
  192     printf("    Serial Number:    %s\n", hba_info->SerialNumber);
  193     printf("    Driver:           %s %s\n", hba_info->DriverName,
  194            hba_info->DriverVersion);
  195     printf("    Number of Ports:  %d\n", hba_info->NumberOfPorts);
  196     printf("\n");
  197 }
  198 
  199 static void show_port_info(HBA_PORTATTRIBUTES *lp_info)
  200 {
  201     char buf[256];
  202     int len = sizeof(buf);
  203 
  204     printf("        Symbolic Name:     %s\n",
  205            lp_info->PortSymbolicName);
  206 
  207     printf("        OS Device Name:    %s\n",
  208            lp_info->OSDeviceName);
  209 
  210     printf("        Node Name:         0x");
  211     show_wwn(lp_info->NodeWWN.wwn);
  212     printf("\n");
  213 
  214     printf("        Port Name:         0x");
  215     show_wwn(lp_info->PortWWN.wwn);
  216     printf("\n");
  217 
  218     printf("        FabricName:        0x");
  219     show_wwn(lp_info->FabricName.wwn);
  220     printf("\n");
  221 
  222     memset(buf, '\0', len);
  223     sa_enum_decode_speed(buf, len, lp_info->PortSpeed);
  224     printf("        Speed:             %s\n", buf);
  225 
  226     memset(buf, '\0', len);
  227     sa_enum_decode_speed(buf, len, lp_info->PortSupportedSpeed);
  228     printf("        Supported Speed:   %s\n", buf);
  229 
  230     printf("        MaxFrameSize:      %d\n",
  231            lp_info->PortMaxFrameSize);
  232 
  233     printf("        FC-ID (Port ID):   0x%06X\n",
  234            lp_info->PortFcId);
  235 
  236     sa_enum_decode(buf, sizeof(buf), port_states, lp_info->PortState);
  237     printf("        State:             %s\n", buf);
  238     printf("\n");
  239     /* TODO: Display PortSupportedFc4Types and PortActiveFc4Types */
  240 }
  241 
  242 static void show_target_info(const char *symbolic_name,
  243                  HBA_PORTATTRIBUTES *rp_info)
  244 {
  245     char buf[256];
  246     int tgt_id;
  247     int rc;
  248     char *ifname;
  249 
  250     ifname = get_ifname_from_symbolic_name(symbolic_name);
  251 
  252     rc = sa_sys_read_line(rp_info->OSDeviceName, "roles", buf, sizeof(buf));
  253     if (rc)
  254         strncpy(buf, "Unknown", sizeof(buf));
  255     printf("    Interface:        %s\n", ifname);
  256     printf("    Roles:            %s\n", buf);
  257 
  258     printf("    Node Name:        0x");
  259     show_wwn(rp_info->NodeWWN.wwn);
  260     printf("\n");
  261 
  262     printf("    Port Name:        0x");
  263     show_wwn(rp_info->PortWWN.wwn);
  264     printf("\n");
  265 
  266     rc = sa_sys_read_int(rp_info->OSDeviceName, "scsi_target_id", &tgt_id);
  267     printf("    Target ID:        ");
  268     if (rc)
  269         printf("Unknown\n");
  270     else if (tgt_id != -1)
  271         printf("%d\n", tgt_id);
  272     else
  273         printf("Unset\n");
  274 
  275     printf("    MaxFrameSize:     %d\n", rp_info->PortMaxFrameSize);
  276 
  277     printf("    OS Device Name:   %s\n",
  278            strrchr(rp_info->OSDeviceName, '/') + 1);
  279 
  280     printf("    FC-ID (Port ID):  0x%06X\n", rp_info->PortFcId);
  281 
  282     sa_enum_decode(buf, sizeof(buf), port_states, rp_info->PortState);
  283     printf("    State:            %s\n", buf);
  284     printf("\n");
  285 }
  286 
  287 static void
  288 show_sense_data(char *dev, char *sense, int slen)
  289 {
  290     printf("%s", dev);
  291     if (slen >= 3)
  292         printf("    Sense Key=0x%02x", sense[2]);
  293     if (slen >= 13)
  294         printf(" ASC=0x%02x", sense[12]);
  295     if (slen >= 14)
  296         printf(" ASCQ=0x%02x\n", sense[13]);
  297     printf("\n");
  298 }
  299 
  300 #ifdef TEST_HBAAPI_V1
  301 static HBA_STATUS
  302 get_inquiry_data_v1(HBA_HANDLE hba_handle,
  303             HBA_FCPSCSIENTRY *ep,
  304             char *inqbuf, size_t inqlen)
  305 {
  306     char sense[128];
  307     HBA_UINT32 rlen;
  308     HBA_UINT32 slen;
  309     HBA_STATUS status;
  310 
  311     memset(inqbuf, 0, inqlen);
  312     memset(sense, 0, sizeof(sense));
  313     rlen = (HBA_UINT32) inqlen;
  314     slen = (HBA_UINT32) sizeof(sense);
  315     status = HBA_SendScsiInquiry(hba_handle,
  316                      ep->FcpId.PortWWN,
  317                      ep->FcpId.FcpLun,
  318                      0,
  319                      0,
  320                      inqbuf,
  321                      rlen,
  322                      sense,
  323                      slen);
  324     if ((status != HBA_STATUS_OK) ||
  325         (rlen < MIN_INQ_DATA_SIZE)) {
  326         fprintf(stderr,
  327             "%s: HBA_SendScsiInquiry failed, "
  328             "status=0x%x, rlen=%d\n",
  329             __func__, status, rlen);
  330         show_sense_data(ep->ScsiId.OSDeviceName, sense, slen);
  331         return HBA_STATUS_ERROR;
  332     }
  333     return HBA_STATUS_OK;
  334 }
  335 #else
  336 static HBA_STATUS
  337 get_inquiry_data_v2(HBA_HANDLE hba_handle,
  338             HBA_PORTATTRIBUTES *lp_info,
  339             HBA_FCPSCSIENTRYV2 *ep,
  340             char *inqbuf, size_t inqlen)
  341 {
  342     char sense[128];
  343     HBA_UINT32 rlen;
  344     HBA_UINT32 slen;
  345     HBA_STATUS status;
  346     HBA_UINT8 sstat;
  347 
  348     memset(inqbuf, 0, inqlen);
  349     memset(sense, 0, sizeof(sense));
  350     rlen = (HBA_UINT32) inqlen;
  351     slen = (HBA_UINT32) sizeof(sense);
  352     sstat = SCSI_ST_GOOD;
  353     status = HBA_ScsiInquiryV2(hba_handle,
  354                    lp_info->PortWWN,
  355                    ep->FcpId.PortWWN,
  356                    ep->FcpId.FcpLun,
  357                    0,
  358                    0,
  359                    inqbuf,
  360                    &rlen,
  361                    &sstat,
  362                    sense,
  363                    &slen);
  364     if ((status != HBA_STATUS_OK) ||
  365         (sstat != SCSI_ST_GOOD) ||
  366         (rlen < MIN_INQ_DATA_SIZE)) {
  367         fprintf(stderr,
  368             "%s: HBA_ScsiInquiryV2 failed, "
  369             "status=0x%x, sstat=0x%x, rlen=%d\n",
  370             __func__, status, sstat, rlen);
  371         if (sstat != SCSI_ST_GOOD)
  372             show_sense_data(ep->ScsiId.OSDeviceName, sense, slen);
  373         return HBA_STATUS_ERROR;
  374     }
  375     return HBA_STATUS_OK;
  376 }
  377 #endif
  378 
  379 #ifdef TEST_HBAAPI_V1
  380 static HBA_STATUS
  381 get_device_capacity_v1(HBA_HANDLE hba_handle,
  382                HBA_FCPSCSIENTRY *ep,
  383                char *buf, size_t len)
  384 {
  385     char sense[128];
  386     HBA_UINT32 rlen;
  387     HBA_UINT32 slen;
  388     HBA_STATUS status;
  389     int retry_count = 10;
  390 
  391     while (retry_count--) {
  392         memset(buf, 0, len);
  393         memset(sense, 0, sizeof(sense));
  394         rlen = (HBA_UINT32)len;
  395         slen = (HBA_UINT32)sizeof(sense);
  396         status = HBA_SendReadCapacity(hba_handle,
  397                           ep->FcpId.PortWWN,
  398                           ep->FcpId.FcpLun,
  399                           buf,
  400                           rlen,
  401                           sense,
  402                           slen);
  403         if (status == HBA_STATUS_OK)
  404             return HBA_STATUS_OK;
  405         if (sense[2] == 0x06)
  406             continue;
  407         fprintf(stderr,
  408             "%s: HBA_SendReadCapacity failed, "
  409             "status=0x%x, slen=%d\n",
  410             __func__, status, slen);
  411         show_sense_data(ep->ScsiId.OSDeviceName, sense, slen);
  412         return HBA_STATUS_ERROR;
  413     }
  414     /* retry count exhausted */
  415     return HBA_STATUS_ERROR;
  416 }
  417 #else
  418 static HBA_STATUS
  419 get_device_capacity_v2(HBA_HANDLE hba_handle,
  420                HBA_PORTATTRIBUTES *lp_info,
  421                HBA_FCPSCSIENTRYV2 *ep,
  422                char *buf, size_t len)
  423 {
  424     char sense[128];
  425     HBA_UINT32 rlen;
  426     HBA_UINT32 slen;
  427     HBA_STATUS status;
  428     HBA_UINT8 sstat;
  429     int retry_count = 10;
  430 
  431     while (retry_count--) {
  432         memset(buf, 0, len);
  433         memset(sense, 0, sizeof(sense));
  434         rlen = (HBA_UINT32)len;
  435         slen = (HBA_UINT32)sizeof(sense);
  436         sstat = SCSI_ST_GOOD;
  437         status = HBA_ScsiReadCapacityV2(hba_handle,
  438                         lp_info->PortWWN,
  439                         ep->FcpId.PortWWN,
  440                         ep->FcpId.FcpLun,
  441                         buf,
  442                         &rlen,
  443                         &sstat,
  444                         sense,
  445                         &slen);
  446         if ((status == HBA_STATUS_OK) && (sstat == SCSI_ST_GOOD))
  447             return HBA_STATUS_OK;
  448         if (sstat == SCSI_ST_CHECK)
  449             continue;
  450         fprintf(stderr,
  451             "%s: HBA_ScsiReadCapacityV2 failed, "
  452             "status=0x%x, sstat=0x%x, slen=%d\n",
  453             __func__, status, sstat, slen);
  454         if (sstat != SCSI_ST_GOOD)
  455             show_sense_data(ep->ScsiId.OSDeviceName, sense, slen);
  456         return HBA_STATUS_ERROR;
  457     }
  458     /* retry count exhausted */
  459     return HBA_STATUS_ERROR;
  460 }
  461 #endif
  462 
  463 #ifdef TEST_DEV_SERIAL_NO
  464 static HBA_STATUS
  465 get_device_serial_number(HBA_HANDLE hba_handle,
  466              HBA_FCPSCSIENTRYV2 *ep,
  467              char *buf, size_t buflen)
  468 {
  469     struct scsi_inquiry_unit_sn *unit_sn;
  470     char rspbuf[256];
  471     char sense[128];
  472     HBA_UINT32 rlen;
  473     HBA_UINT32 slen;
  474     HBA_STATUS status;
  475 
  476     memset(rspbuf, 0, sizeof(rspbuf));
  477     memset(sense, 0, sizeof(sense));
  478     rlen = (HBA_UINT32) sizeof(rspbuf);
  479     slen = (HBA_UINT32) sizeof(sense);
  480     status = HBA_SendScsiInquiry(hba_handle,
  481                      ep->FcpId.PortWWN,
  482                      ep->FcpId.FcpLun,
  483                      SCSI_INQF_EVPD,
  484                      SCSI_INQP_UNIT_SN,
  485                      rspbuf,
  486                      rlen,
  487                      sense,
  488                      slen);
  489     if (status != HBA_STATUS_OK) {
  490         fprintf(stderr,
  491             "%s: inquiry page 0x80 failed, status=0x%x\n",
  492             __func__, status);
  493         show_sense_data(ep->ScsiId.OSDeviceName, sense, slen);
  494         return HBA_STATUS_ERROR;
  495     }
  496     unit_sn = (struct scsi_inquiry_unit_sn *)rspbuf;
  497     unit_sn->is_serial[unit_sn->is_page_len] = '\0';
  498     sa_strncpy_safe(buf, buflen, (char *)unit_sn->is_serial,
  499             (size_t)unit_sn->is_page_len);
  500     return HBA_STATUS_OK;
  501 }
  502 #endif
  503 
  504 #ifdef TEST_REPORT_LUNS
  505 static void
  506 show_report_luns_data(char *rspbuf)
  507 {
  508     struct scsi_report_luns_resp *rp;
  509     int list_len;
  510     net64_t *lp;
  511     u_int64_t lun_id;
  512 
  513     rp = (struct scsi_report_luns_resp *)rspbuf;
  514     list_len = net32_get(&rp->rl_len);
  515     printf("\tTotal Number of LUNs=%lu\n", list_len/sizeof(u_int64_t));
  516 
  517     for (lp = rp->rl_lun; list_len > 0; lp++, list_len -= sizeof(*lp)) {
  518         lun_id = net64_get(lp);
  519         if (!(lun_id & ((0xfc01ULL << 48) - 1)))
  520             printf("\tLUN %u\n", (u_int32_t)(lun_id >> 48));
  521         else
  522             printf("\tLUN %lx\n", (u_int64_t)lun_id);
  523     }
  524 }
  525 
  526 static HBA_STATUS
  527 get_report_luns_data_v1(HBA_HANDLE hba_handle, HBA_FCPSCSIENTRYV2 *ep)
  528 {
  529     HBA_STATUS status;
  530     char rspbuf[512 * sizeof(u_int64_t)]; /* max 512 luns */
  531     char sense[128];
  532     HBA_UINT32 rlen;
  533     HBA_UINT32 slen;
  534     int retry_count = 10;
  535 
  536     while (retry_count--) {
  537         memset(rspbuf, 0, sizeof(rspbuf));
  538         memset(sense, 0, sizeof(sense));
  539         rlen = (HBA_UINT32) sizeof(rspbuf);
  540         slen = (HBA_UINT32) sizeof(sense);
  541         status = HBA_SendReportLUNs(hba_handle,
  542                         ep->FcpId.PortWWN,
  543                         rspbuf,
  544                         rlen,
  545                         sense,
  546                         slen);
  547         if (status == HBA_STATUS_OK) {
  548             show_report_luns_data(rspbuf);
  549             return HBA_STATUS_OK;
  550         }
  551         if (sense[2] == 0x06)
  552             continue;
  553         fprintf(stderr,
  554             "%s: HBA_SendReportLUNs failed, "
  555             "status=0x%x, slen=%d\n",
  556             __func__, status, slen);
  557         show_sense_data(ep->ScsiId.OSDeviceName, sense, slen);
  558         return HBA_STATUS_ERROR;
  559     }
  560     /* retry count exhausted */
  561     return HBA_STATUS_ERROR;
  562 }
  563 
  564 static HBA_STATUS
  565 get_report_luns_data_v2(HBA_HANDLE hba_handle,
  566             HBA_PORTATTRIBUTES *lp_info,
  567             HBA_FCPSCSIENTRYV2 *ep)
  568 {
  569     HBA_STATUS status;
  570     char rspbuf[512 * sizeof(u_int64_t)]; /* max 512 luns */
  571     char sense[128];
  572     HBA_UINT32 rlen;
  573     HBA_UINT32 slen;
  574     HBA_UINT8 sstat;
  575     int retry_count = 10;
  576 
  577     while (retry_count--) {
  578         memset(rspbuf, 0, sizeof(rspbuf));
  579         memset(sense, 0, sizeof(sense));
  580         rlen = (HBA_UINT32) sizeof(rspbuf);
  581         slen = (HBA_UINT32) sizeof(sense);
  582         sstat = SCSI_ST_GOOD;
  583         status = HBA_ScsiReportLUNsV2(hba_handle,
  584                           lp_info->PortWWN,
  585                           ep->FcpId.PortWWN,
  586                           rspbuf,
  587                           &rlen,
  588                           &sstat,
  589                           sense,
  590                           &slen);
  591         if ((status == HBA_STATUS_OK) && (sstat == SCSI_ST_GOOD)) {
  592             show_report_luns_data(rspbuf);
  593             return HBA_STATUS_OK;
  594         }
  595         if ((sstat == SCSI_ST_CHECK) && (sense[2] == 0x06))
  596             continue;
  597         fprintf(stderr,
  598             "%s: HBA_ScsiReportLUNsV2 failed, "
  599             "status=0x%x, sstat=0x%x, slen=%d\n",
  600             __func__, status, sstat, slen);
  601         if (sstat != SCSI_ST_GOOD)
  602             show_sense_data(ep->ScsiId.OSDeviceName, sense, slen);
  603         return HBA_STATUS_ERROR;
  604     }
  605     /* retry count exhausted */
  606     return HBA_STATUS_ERROR;
  607 }
  608 #endif
  609 
  610 static void
  611 show_short_lun_info_header(void)
  612 {
  613     printf("    LUN ID  Device Name   Capacity   "
  614            "Block Size  Description\n");
  615     printf("    ------  -----------  ----------  ----------  "
  616            "----------------------------\n");
  617 }
  618 
  619 static void
  620 show_short_lun_info(HBA_FCP_SCSI_ENTRY *ep, char *inqbuf,
  621             u_int32_t blksize,
  622             u_int64_t lba)
  623 {
  624     struct scsi_inquiry_std *inq = (struct scsi_inquiry_std *)inqbuf;
  625     char vendor[10];
  626     char model[20];
  627     char capstr[32];
  628     char rev[16];
  629     u_int64_t cap;
  630     double cap_abbr;
  631     char *abbr;
  632 
  633     memset(vendor, 0, sizeof(vendor));
  634     memset(model, 0, sizeof(model));
  635     memset(capstr, 0, sizeof(capstr));
  636     memset(rev, 0, sizeof(rev));
  637 
  638     /* Get device capacity */
  639     cap = (u_int64_t)blksize * lba;
  640 
  641     cap_abbr = cap / (1024.0 * 1024.0);
  642     abbr = "MiB";
  643     if (cap_abbr >= 1024) {
  644         cap_abbr /= 1024.0;
  645         abbr = "GiB";
  646     }
  647     if (cap_abbr >= 1024) {
  648         cap_abbr /= 1024.0;
  649         abbr = "TiB";
  650     }
  651     if (cap_abbr >= 1024) {
  652         cap_abbr /= 1024.0;
  653         abbr = "PiB";
  654     }
  655     snprintf(capstr, sizeof(capstr), "%0.2f %s", cap_abbr, abbr);
  656 
  657     /* Get the device description */
  658     sa_strncpy_safe(vendor, sizeof(vendor),
  659             inq->is_vendor_id, sizeof(inq->is_vendor_id));
  660     sa_strncpy_safe(model, sizeof(model),
  661             inq->is_product, sizeof(inq->is_product));
  662     sa_strncpy_safe(rev, sizeof(rev), inq->is_rev_level,
  663             sizeof(inq->is_rev_level));
  664 
  665     /* Show the LUN info */
  666     printf("%10d  %-11s  %10s  %7d     %s %s (rev %s)\n",
  667            ep->ScsiId.ScsiOSLun, ep->ScsiId.OSDeviceName,
  668            capstr, blksize,
  669            vendor, model, rev);
  670 }
  671 
  672 static void
  673 show_full_lun_info(UNUSED HBA_HANDLE hba_handle,
  674            HBA_PORTATTRIBUTES *lp_info,
  675            HBA_PORTATTRIBUTES *rp_info,
  676            HBA_FCP_SCSI_ENTRY *ep,
  677            char *inqbuf,
  678            u_int32_t blksize,
  679            u_int64_t lba)
  680 {
  681     struct scsi_inquiry_std *inq = (struct scsi_inquiry_std *)inqbuf;
  682     char vendor[10];
  683     char model[20];
  684     char capstr[32];
  685     char rev[16];
  686     double cap_abbr;
  687     char *abbr;
  688     u_int64_t cap;
  689     u_int32_t tgt_id;
  690     u_int8_t pqual;
  691 #ifdef TEST_DEV_SERIAL_NO
  692     HBA_STATUS status;
  693     char serial_number[32];
  694 #endif
  695 
  696     memset(vendor, 0, sizeof(vendor));
  697     memset(model, 0, sizeof(model));
  698     memset(capstr, 0, sizeof(capstr));
  699     memset(rev, 0, sizeof(rev));
  700 
  701     /* Get device description */
  702     sa_strncpy_safe(vendor, sizeof(vendor),
  703             inq->is_vendor_id, sizeof(inq->is_vendor_id));
  704     sa_strncpy_safe(model, sizeof(model),
  705             inq->is_product, sizeof(inq->is_product));
  706     sa_strncpy_safe(rev, sizeof(rev), inq->is_rev_level,
  707             sizeof(inq->is_rev_level));
  708 
  709     /* Get device capacity */
  710     cap = (u_int64_t)blksize * lba;
  711 
  712     cap_abbr = cap / (1024.0 * 1024.0);
  713     abbr = "MiB";
  714     if (cap_abbr >= 1024) {
  715         cap_abbr /= 1024.0;
  716         abbr = "GiB";
  717     }
  718     if (cap_abbr >= 1024) {
  719         cap_abbr /= 1024.0;
  720         abbr = "TiB";
  721     }
  722     if (cap_abbr >= 1024) {
  723         cap_abbr /= 1024.0;
  724         abbr = "PiB";
  725     }
  726     snprintf(capstr, sizeof(capstr), "%0.2f %s", cap_abbr, abbr);
  727 
  728     /* Get SCSI target ID */
  729     sa_sys_read_u32(rp_info->OSDeviceName,
  730             "scsi_target_id", &tgt_id);
  731 
  732     /* Show lun info */
  733     printf("    LUN #%d Information:\n", ep->ScsiId.ScsiOSLun);
  734     printf("        OS Device Name:     %s\n",
  735            ep->ScsiId.OSDeviceName);
  736     printf("        Description:        %s %s (rev %s)\n",
  737            vendor, model, rev);
  738     printf("        Ethernet Port FCID: 0x%06X\n",
  739            lp_info->PortFcId);
  740     printf("        Target FCID:        0x%06X\n",
  741            rp_info->PortFcId);
  742     if (tgt_id == 0xFFFFFFFFU)
  743         printf("        Target ID:          (None)\n");
  744     else
  745         printf("        Target ID:          %u\n", tgt_id);
  746     printf("        LUN ID:             %d\n",
  747            ep->ScsiId.ScsiOSLun);
  748 
  749     printf("        Capacity:           %s\n", capstr);
  750     printf("        Capacity in Blocks: %" PRIu64 "\n", lba);
  751     printf("        Block Size:         %" PRIu32 " bytes\n", blksize);
  752     pqual = inq->is_periph & SCSI_INQ_PQUAL_MASK;
  753     if (pqual == SCSI_PQUAL_ATT)
  754         printf("        Status:             Attached\n");
  755     else if (pqual == SCSI_PQUAL_DET)
  756         printf("        Status:             Detached\n");
  757     else if (pqual == SCSI_PQUAL_NC)
  758         printf("        Status:             "
  759                "Not capable of attachment\n");
  760 
  761 #ifdef TEST_DEV_SERIAL_NO
  762     /* Show the serial number of the device */
  763     status = get_device_serial_number(hba_handle, ep,
  764                       serial_number, sizeof(serial_number));
  765     if (status == HBA_STATUS_OK)
  766         printf("        Serial Number:      %s\n", serial_number);
  767 #endif
  768 
  769     printf("\n");
  770 }
  771 
  772 /* Compare two LUN mappings for qsort */
  773 static int
  774 lun_compare(const void *arg1, const void *arg2)
  775 {
  776     const HBA_FCP_SCSI_ENTRY *e1 = arg1;
  777     const HBA_FCP_SCSI_ENTRY *e2 = arg2;
  778     int diff;
  779 
  780     diff = e2->FcpId.FcId - e1->FcpId.FcId;
  781     if (diff == 0)
  782         diff = e1->ScsiId.ScsiOSLun - e2->ScsiId.ScsiOSLun;
  783 
  784     return diff;
  785 }
  786 
  787 static HBA_STATUS
  788 get_device_map(HBA_HANDLE hba_handle, HBA_PORTATTRIBUTES *lp_info,
  789            HBA_FCP_TARGET_MAPPING **tgtmap, u_int32_t *lun_count)
  790 {
  791     HBA_STATUS status;
  792     HBA_FCP_TARGET_MAPPING *map = NULL;
  793     HBA_FCP_SCSI_ENTRY *ep;
  794     u_int32_t limit;
  795     u_int32_t i;
  796 
  797 #define LUN_COUNT_START     8       /* number of LUNs to start with */
  798 #define LUN_COUNT_INCR      4       /* excess to allocate */
  799 
  800     /*
  801      * Get buffer large enough to retrieve all the mappings.
  802      * If they don't fit, increase the size of the buffer and retry.
  803      */
  804     *lun_count = 0;
  805     limit = LUN_COUNT_START;
  806     for (;;) {
  807         i = (limit - 1) * sizeof(*ep) +  sizeof(*map);
  808         map = malloc(i);
  809         if (map == NULL) {
  810             fprintf(stderr, "%s: malloc failed\n", __func__);
  811             return HBA_STATUS_ERROR;
  812         }
  813         memset((char *)map, 0, i);
  814         map->NumberOfEntries = limit;
  815 #ifdef TEST_HBAAPI_V1
  816         status = HBA_GetFcpTargetMapping(hba_handle, map);
  817 #else
  818         status = HBA_GetFcpTargetMappingV2(
  819             hba_handle, lp_info->PortWWN, map);
  820 #endif
  821         if (map->NumberOfEntries > limit) {
  822             limit = map->NumberOfEntries + LUN_COUNT_INCR;
  823             free(map);
  824             continue;
  825         }
  826         if (status != HBA_STATUS_OK) {
  827             fprintf(stderr,
  828                 "%s: HBA_GetFcpTargetMappingV2 failed\n",
  829                 __func__);
  830             free(map);
  831             return HBA_STATUS_ERROR;
  832         }
  833         break;
  834     }
  835 
  836     if (map == NULL) {
  837         fprintf(stderr, "%s: map == NULL\n", __func__);
  838         return HBA_STATUS_ERROR;
  839     }
  840 
  841     if (map->NumberOfEntries > limit) {
  842         fprintf(stderr, "%s: map->NumberOfEntries=%d too big\n",
  843             __func__, map->NumberOfEntries);
  844         return HBA_STATUS_ERROR;
  845     }
  846 
  847     ep = map->entry;
  848     limit = map->NumberOfEntries;
  849 
  850     /* Sort the response by LUN number */
  851     qsort(ep, limit, sizeof(*ep), lun_compare);
  852 
  853     *lun_count = limit;
  854     *tgtmap = map;
  855     return HBA_STATUS_OK;
  856 }
  857 
  858 static void
  859 scan_device_map(HBA_HANDLE hba_handle,
  860         HBA_PORTATTRIBUTES *lp_info,
  861         HBA_PORTATTRIBUTES *rp_info,
  862         enum disp_style style)
  863 {
  864     HBA_STATUS status;
  865     HBA_FCP_TARGET_MAPPING *map = NULL;
  866     u_int32_t limit;
  867     HBA_FCP_SCSI_ENTRY *ep;
  868     u_int32_t i;
  869     char *dev;
  870     char inqbuf[256];
  871     struct scsi_rcap10_resp rcap_resp;
  872     struct scsi_rcap16_resp rcap16_resp;
  873     u_int64_t lba;
  874     u_int32_t blksize;
  875     int lun_count = 0;
  876     int print_header = 0;
  877 
  878     status = get_device_map(hba_handle, lp_info, &map, &limit);
  879     if (status != HBA_STATUS_OK) {
  880         fprintf(stderr, "%s: get_device_map() failed\n", __func__);
  881         return;
  882     }
  883 
  884     ep = map->entry;
  885     for (i = 0; i < limit; i++, ep++) {
  886         if (ep->FcpId.FcId != rp_info->PortFcId)
  887             continue;
  888 
  889         dev = ep->ScsiId.OSDeviceName;
  890         if (strstr(dev, "/dev/") == dev)
  891             dev += 5;
  892 
  893         /* Issue standard inquiry */
  894 #ifdef TEST_HBAAPI_V1
  895         status = get_inquiry_data_v1(hba_handle, ep,
  896                          inqbuf, sizeof(inqbuf));
  897 #else
  898         status = get_inquiry_data_v2(hba_handle, lp_info,
  899                          ep, inqbuf, sizeof(inqbuf));
  900 #endif
  901         if (status != HBA_STATUS_OK)
  902             continue;
  903         lun_count++;
  904 
  905         /* Issue read capacity */
  906 #ifdef TEST_HBAAPI_V1
  907         status = get_device_capacity_v1(hba_handle, ep,
  908                         (char *)&rcap_resp,
  909                         sizeof(rcap_resp));
  910 #else
  911         status = get_device_capacity_v2(hba_handle, lp_info,
  912                         ep, (char *)&rcap_resp,
  913                         sizeof(rcap_resp));
  914 #endif
  915         if (status != HBA_STATUS_OK)
  916             continue;
  917 
  918         if (net32_get(&rcap_resp.rc_lba) == 0xFFFFFFFFUL) {
  919             /* Issue read capacity (16) */
  920 #ifdef TEST_HBAAPI_V1
  921             status = get_device_capacity_v1(hba_handle, ep,
  922                             (char *)&rcap16_resp,
  923                             sizeof(rcap16_resp));
  924 #else
  925             status = get_device_capacity_v2(hba_handle, lp_info,
  926                             ep, (char *)&rcap16_resp,
  927                             sizeof(rcap16_resp));
  928 #endif
  929             if (status != HBA_STATUS_OK)
  930                 continue;
  931 
  932             blksize = net32_get(&rcap16_resp.rc_block_len);
  933             lba = (u_int64_t)net64_get(&rcap16_resp.rc_lba);
  934         } else {
  935             blksize = net32_get(&rcap_resp.rc_block_len);
  936             lba = (u_int64_t)net32_get(&rcap_resp.rc_lba);
  937         }
  938 
  939         /* Total Number of Blocks */
  940         lba = lba + 1;
  941 
  942         switch (style) {
  943         case DISP_TARG:
  944             if (!print_header) {
  945                 show_short_lun_info_header();
  946                 print_header = 1;
  947             }
  948             show_short_lun_info(ep, inqbuf, blksize, lba);
  949             break;
  950         case DISP_LUN:
  951             show_full_lun_info(hba_handle, lp_info,
  952                        rp_info, ep, inqbuf, blksize, lba);
  953             break;
  954         }
  955 
  956 #ifdef TEST_REPORT_LUNS
  957         if (i == 0) {   /* only issue report luns to the first LUN */
  958 #ifdef TEST_HBAAPI_V1
  959             get_report_luns_data_v1(hba_handle, ep);
  960 #else
  961             get_report_luns_data_v2(hba_handle, lp_info, ep);
  962 #endif
  963         }
  964 #endif
  965     }
  966 
  967     /* Newline at the end of the short lun report */
  968     if (style == DISP_TARG)
  969         printf("\n");
  970 
  971     free(map);
  972 }
  973 
  974 static void show_port_stats_header(const char *ifname, int interval)
  975 {
  976     printf("\n");
  977     printf("%-7s interval: %-2d                                    Err  Inv  "
  978            "IvTx Link Cntl Input     Input     Output    Output\n",
  979            ifname, interval);
  980     printf("Seconds TxFrames  TxBytes      RxFrames  RxBytes        "
  981            "Frms CRC  Byte Fail Reqs Requests  MBytes    "
  982            "Requests  MBytes\n");
  983     printf("------- --------- ------------ --------- -------------- "
  984            "---- ---- ---- ---- ---- --------- --------- "
  985            "--------- ---------\n");
  986 }
  987 
  988 static void
  989 show_port_stats_in_row(HBA_INT64 start_time,
  990                HBA_PORTSTATISTICS *port_stats,
  991                HBA_FC4STATISTICS *port_fc4stats)
  992 {
  993     printf("%-7lld ", port_stats->SecondsSinceLastReset - start_time);
  994     printf("%-9lld ", port_stats->TxFrames);
  995     printf("%-12lld ", port_stats->TxWords * FCOE_WORD_TO_BYTE);
  996     printf("%-9lld ", port_stats->RxFrames);
  997     printf("%-14lld ", port_stats->RxWords * FCOE_WORD_TO_BYTE);
  998     printf("%-4lld ", port_stats->ErrorFrames);
  999     printf("%-4lld ", port_stats->InvalidCRCCount);
 1000     printf("%-4lld ", port_stats->InvalidTxWordCount * FCOE_WORD_TO_BYTE);
 1001     printf("%-4lld ", port_stats->LinkFailureCount);
 1002     printf("%-4lld ", port_fc4stats->ControlRequests);
 1003     printf("%-9lld ", port_fc4stats->InputRequests);
 1004     printf("%-9lld ", port_fc4stats->InputMegabytes);
 1005     printf("%-9lld ", port_fc4stats->OutputRequests);
 1006     printf("%-9lld ", port_fc4stats->OutputMegabytes);
 1007     printf("\n");
 1008 }
 1009 
 1010 static void hba_table_list_destroy(struct hba_name_table_list *hba_table_list)
 1011 {
 1012     int i;
 1013 
 1014     if (!hba_table_list)
 1015         return;
 1016 
 1017     for (i = 0 ; i < hba_table_list->hba_count ; i++)
 1018         HBA_CloseAdapter(hba_table_list->hba_table[i].hba_handle);
 1019 
 1020     free(hba_table_list);
 1021     hba_table_list = NULL;
 1022 }
 1023 
 1024 static enum fcoe_status fcoeadm_loadhba(void)
 1025 {
 1026     if (HBA_STATUS_OK != HBA_LoadLibrary())
 1027         return EHBAAPIERR;
 1028 
 1029     return SUCCESS;
 1030 }
 1031 
 1032 /*
 1033  * This routine leaves all adapters fd's open.
 1034  */
 1035 static int hba_table_list_init(struct hba_name_table_list **hba_table_list)
 1036 {
 1037     HBA_STATUS retval;
 1038     char namebuf[1024];
 1039     int i, num_hbas = 0;
 1040     struct hba_name_table_list *hba_table_list_temp = NULL;
 1041     struct hba_name_table *hba_table = NULL;
 1042     int size = 0;
 1043 
 1044     num_hbas = HBA_GetNumberOfAdapters();
 1045     if (!num_hbas) {
 1046         fprintf(stderr, "No FCoE interfaces created.\n");
 1047         return num_hbas;
 1048     }
 1049 
 1050     size = sizeof(struct hba_name_table_list) + \
 1051             (num_hbas - 1)*sizeof(struct hba_name_table);
 1052 
 1053     hba_table_list_temp = (struct hba_name_table_list *)calloc(1, size);
 1054     if (!hba_table_list_temp) {
 1055         fprintf(stderr,
 1056             "Failure allocating memory.\n");
 1057         return -1;
 1058     }
 1059 
 1060     hba_table_list_temp->hba_count = num_hbas;
 1061 
 1062     /*
 1063      * Fill out the HBA table.
 1064      */
 1065     for (i = 0; i < num_hbas ; i++) {
 1066         retval = HBA_GetAdapterName(i, namebuf);
 1067         if (retval != HBA_STATUS_OK) {
 1068             fprintf(stderr,
 1069                 "Failure of HBA_GetAdapterName: %d\n", retval);
 1070             continue;
 1071         }
 1072 
 1073         hba_table = &hba_table_list_temp->hba_table[i];
 1074         hba_table->hba_handle = HBA_OpenAdapter(namebuf);
 1075         if (!hba_table->hba_handle) {
 1076             hba_table->failed = 1;
 1077             fprintf(stderr, "HBA_OpenAdapter failed\n");
 1078             perror("HBA_OpenAdapter");
 1079             continue;
 1080         }
 1081 
 1082         retval = HBA_GetAdapterAttributes(hba_table->hba_handle,
 1083                           &hba_table->hba_attrs);
 1084         if (retval != HBA_STATUS_OK) {
 1085             HBA_CloseAdapter(hba_table->hba_handle);
 1086             hba_table->failed = 1;
 1087             fprintf(stderr,
 1088                 "HBA_GetAdapterAttributes failed, retval=%d\n",
 1089                 retval);
 1090             perror("HBA_GetAdapterAttributes");
 1091             continue;
 1092         }
 1093 
 1094         retval = HBA_GetAdapterPortAttributes(hba_table->hba_handle,
 1095                               0,
 1096                               &hba_table->port_attrs);
 1097         if (retval != HBA_STATUS_OK) {
 1098             HBA_CloseAdapter(hba_table->hba_handle);
 1099             hba_table->failed = 1;
 1100             fprintf(stderr,
 1101                 "HBA_GetAdapterPortAttributes failed, "
 1102                 "retval=%d\n", retval);
 1103             continue;
 1104         }
 1105     }
 1106 
 1107     *hba_table_list = hba_table_list_temp;
 1108 
 1109     return num_hbas;
 1110 }
 1111 
 1112 /*
 1113  * This routine expects a valid interface name.
 1114  */
 1115 static int get_index_for_ifname(struct hba_name_table_list *hba_table_list,
 1116                 const char *ifname)
 1117 {
 1118     HBA_PORTATTRIBUTES *port_attrs;
 1119     int i;
 1120 
 1121     for (i = 0 ; i < hba_table_list->hba_count ; i++) {
 1122 
 1123         port_attrs = &hba_table_list->hba_table[i].port_attrs;
 1124 
 1125         if (!check_symbolic_name_for_interface(
 1126                 port_attrs->PortSymbolicName,
 1127                 ifname))
 1128             return i;
 1129     }
 1130 
 1131     return -EINVAL;
 1132 }
 1133 
 1134 enum fcoe_status display_port_stats(const char *ifname, int interval)
 1135 {
 1136     HBA_STATUS retval;
 1137     HBA_HANDLE hba_handle;
 1138     HBA_PORTATTRIBUTES *port_attrs;
 1139     HBA_PORTSTATISTICS port_stats;
 1140     HBA_FC4STATISTICS port_fc4stats;
 1141     HBA_INT64 start_time = 0;
 1142     struct hba_name_table_list *hba_table_list = NULL;
 1143     enum fcoe_status rc = SUCCESS;
 1144     int i, num_hbas;
 1145 
 1146     if (fcoeadm_loadhba())
 1147         return EHBAAPIERR;
 1148 
 1149     num_hbas = hba_table_list_init(&hba_table_list);
 1150     if (!num_hbas)
 1151         goto out;
 1152 
 1153     if (num_hbas < 0) {
 1154         rc = EINTERR;
 1155         goto out;
 1156     }
 1157 
 1158     i = get_index_for_ifname(hba_table_list, ifname);
 1159 
 1160     /*
 1161      * Return error code if a valid index wasn't returned.
 1162      */
 1163     if (i < 0) {
 1164         hba_table_list_destroy(hba_table_list);
 1165         HBA_FreeLibrary();
 1166         return EHBAAPIERR;
 1167     }
 1168 
 1169     hba_handle = hba_table_list->hba_table[i].hba_handle;
 1170     port_attrs = &hba_table_list->hba_table[i].port_attrs;
 1171 
 1172     i = 0;
 1173     while (1) {
 1174         unsigned int secs_left;
 1175 
 1176         retval = HBA_GetPortStatistics(hba_handle,
 1177                            0, &port_stats);
 1178         if (retval != HBA_STATUS_OK &&
 1179             retval != HBA_STATUS_ERROR_NOT_SUPPORTED) {
 1180             fprintf(stderr,
 1181                 "HBA_GetPortStatistics failed, status=%d\n",
 1182                 retval);
 1183             break;
 1184         }
 1185         if (retval == HBA_STATUS_ERROR_NOT_SUPPORTED) {
 1186             fprintf(stderr,
 1187                 "Port Statistics not supported by %s\n",
 1188                 ifname);
 1189             break;
 1190         }
 1191 
 1192         if (!start_time)
 1193             start_time = port_stats.SecondsSinceLastReset;
 1194 
 1195         retval = HBA_GetFC4Statistics(hba_handle,
 1196                           port_attrs->PortWWN,
 1197                           FC_TYPE_FCP,
 1198                           &port_fc4stats);
 1199         if (retval != HBA_STATUS_OK &&
 1200             retval != HBA_STATUS_ERROR_NOT_SUPPORTED) {
 1201             fprintf(stderr, "HBA_GetFC4Statistics failed, "
 1202                 "status=%d\n", retval);
 1203             break;
 1204         }
 1205         if (retval == HBA_STATUS_ERROR_NOT_SUPPORTED) {
 1206             fprintf(stderr,
 1207                 "Port FC4 Statistics not supported by %s\n",
 1208                 ifname);
 1209             break;
 1210         }
 1211         if (!(i % 52))
 1212             show_port_stats_header(ifname, interval);
 1213         show_port_stats_in_row(start_time, &port_stats, &port_fc4stats);
 1214         i++;
 1215 
 1216         /* wait for the requested time interval in seconds */
 1217         secs_left = interval;
 1218         do {
 1219             secs_left = sleep(secs_left);
 1220         } while (secs_left);
 1221     }
 1222 
 1223     hba_table_list_destroy(hba_table_list);
 1224 out:
 1225     HBA_FreeLibrary();
 1226     return rc;
 1227 }
 1228 
 1229 enum fcoe_status display_adapter_info(const char *ifname)
 1230 {
 1231     struct hba_name_table_list *hba_table_list = NULL;
 1232     enum fcoe_status rc = SUCCESS;
 1233     int i, j, num_hbas = 0;
 1234     HBA_PORTATTRIBUTES *port_attrs;
 1235     HBA_PORTATTRIBUTES *sport_attrs;
 1236     HBA_ADAPTERATTRIBUTES *hba_attrs;
 1237     HBA_ADAPTERATTRIBUTES *shba_attrs;
 1238 
 1239     if (fcoeadm_loadhba())
 1240         return EHBAAPIERR;
 1241 
 1242     num_hbas = hba_table_list_init(&hba_table_list);
 1243     if (!num_hbas)
 1244         goto out;
 1245 
 1246     if (num_hbas < 0) {
 1247         rc = EINTERR;
 1248         goto out;
 1249     }
 1250 
 1251     /*
 1252      * Loop through each HBA entry and for each serial number
 1253      * not already printed print the header and each sub-port
 1254      * on that adapter.
 1255      */
 1256     for (i = 0 ; i < num_hbas ; i++) {
 1257         if (hba_table_list->hba_table[i].failed ||
 1258             hba_table_list->hba_table[i].displayed)
 1259             continue;
 1260 
 1261         port_attrs = &hba_table_list->hba_table[i].port_attrs;
 1262         hba_attrs = &hba_table_list->hba_table[i].hba_attrs;
 1263 
 1264         if (ifname && check_symbolic_name_for_interface(
 1265                 port_attrs->PortSymbolicName,
 1266                 ifname)) {
 1267             /*
 1268              * Overloading 'displayed' to indicate
 1269              * that the HBA/Port should be skipped.
 1270              */
 1271             hba_table_list->hba_table[i].displayed = 1;
 1272             continue;
 1273         }
 1274 
 1275         /*
 1276          * Display the adapter header.
 1277          */
 1278         show_hba_info(hba_attrs);
 1279 
 1280         /*
 1281          * Loop through HBAs again to print sub-ports.
 1282          */
 1283         for (j = 0; j < num_hbas ; j++) {
 1284             sport_attrs = &hba_table_list->hba_table[j].port_attrs;
 1285             shba_attrs = &hba_table_list->hba_table[j].hba_attrs;
 1286             if (ifname && check_symbolic_name_for_interface(
 1287                     sport_attrs->PortSymbolicName,
 1288                     ifname)) {
 1289                 /*
 1290                  * Overloading 'displayed' to indicate
 1291                  * that the HBA/Port should be skipped.
 1292                  */
 1293                 hba_table_list->hba_table[i].displayed = 1;
 1294                 continue;
 1295             }
 1296 
 1297             if (!strncmp(hba_attrs->SerialNumber,
 1298                      shba_attrs->SerialNumber,
 1299                      strlen(hba_attrs->SerialNumber))) {
 1300                 show_port_info(sport_attrs);
 1301                 hba_table_list->hba_table[j].displayed = 1;
 1302             }
 1303         }
 1304     }
 1305 
 1306     hba_table_list_destroy(hba_table_list);
 1307 out:
 1308     HBA_FreeLibrary();
 1309 
 1310     return rc;
 1311 }
 1312 
 1313 enum fcoe_status display_target_info(const char *ifname,
 1314                      enum disp_style style)
 1315 {
 1316     HBA_STATUS retval;
 1317     HBA_PORTATTRIBUTES rport_attrs;
 1318     struct hba_name_table_list *hba_table_list = NULL;
 1319     int i, num_hbas = 0;
 1320     unsigned int target_index;
 1321     enum fcoe_status rc = SUCCESS;
 1322     HBA_HANDLE hba_handle;
 1323     HBA_PORTATTRIBUTES *port_attrs;
 1324 
 1325     if (fcoeadm_loadhba())
 1326         return EHBAAPIERR;
 1327 
 1328     num_hbas = hba_table_list_init(&hba_table_list);
 1329     if (!num_hbas)
 1330         goto out;
 1331 
 1332     if (num_hbas < 0) {
 1333         rc = EINTERR;
 1334         goto out;
 1335     }
 1336 
 1337     /*
 1338      * Loop through each HBA entry and for each serial number
 1339      * not already printed print the header and each sub-port
 1340      * on that adapter.
 1341      */
 1342     for (i = 0 ; i < num_hbas ; i++) {
 1343         if (hba_table_list->hba_table[i].failed ||
 1344             hba_table_list->hba_table[i].displayed)
 1345             continue;
 1346 
 1347         hba_handle = hba_table_list->hba_table[i].hba_handle;
 1348         port_attrs = &hba_table_list->hba_table[i].port_attrs;
 1349 
 1350         if (ifname && check_symbolic_name_for_interface(
 1351                 port_attrs->PortSymbolicName,
 1352                 ifname)) {
 1353             /*
 1354              * Overloading 'displayed' to indicate
 1355              * that the HBA/Port should be skipped.
 1356              */
 1357             hba_table_list->hba_table[i].displayed = 1;
 1358             continue;
 1359         }
 1360 
 1361         for (target_index = 0;
 1362              target_index < port_attrs->NumberofDiscoveredPorts;
 1363              target_index++) {
 1364 
 1365             /* TODO: Second arg might be incorrect */
 1366             retval = HBA_GetDiscoveredPortAttributes(
 1367                 hba_handle,
 1368                 0, target_index,
 1369                 &rport_attrs);
 1370 
 1371             if (retval != HBA_STATUS_OK) {
 1372                 fprintf(stderr,
 1373                     "HBA_GetDiscoveredPortAttributes "
 1374                     "failed for target_index=%d, "
 1375                     "status=%d\n", target_index, retval);
 1376                 hba_table_list->hba_table[i].failed = 1;
 1377                 continue;
 1378             }
 1379 
 1380             /*
 1381              * Skip any targets that are not FCP targets
 1382              */
 1383             if (is_fcp_target(&rport_attrs))
 1384                 continue;
 1385 
 1386             show_target_info(
 1387                 port_attrs->PortSymbolicName,
 1388                 &rport_attrs);
 1389 
 1390             if (port_attrs->PortState != HBA_PORTSTATE_ONLINE)
 1391                 continue;
 1392 
 1393             /*
 1394              * This will print the LUN table
 1395              * under the target.
 1396              */
 1397             scan_device_map(hba_handle,
 1398                     port_attrs,
 1399                     &rport_attrs, style);
 1400         }
 1401     }
 1402 
 1403     hba_table_list_destroy(hba_table_list);
 1404 out:
 1405     HBA_FreeLibrary();
 1406 
 1407     return rc;
 1408 }
 1409 
 1410 static struct sa_table fcoe_ctlr_table;
 1411 
 1412 static void print_fcoe_fcf_device(void *ep, UNUSED void *arg)
 1413 {
 1414     struct fcoe_fcf_device *fcf = (struct fcoe_fcf_device *)ep;
 1415     char temp[MAX_STR_LEN];
 1416     char mac[MAX_STR_LEN];
 1417     int len = sizeof(temp);
 1418     const char *buf;
 1419 
 1420     printf("\n");
 1421     printf("    FCF #%u Information\n", fcf->index);
 1422     buf = sa_enum_decode(temp, len, fcf_state_table, fcf->state);
 1423     if (!buf)
 1424         buf = temp;
 1425     printf("        Connection Mode:  %s\n", buf);
 1426     printf("        Fabric Name:      0x%016" PRIx64 "\n", fcf->fabric_name);
 1427     printf("        Switch Name       0x%016" PRIx64 "\n", fcf->switch_name);
 1428     mac2str(fcf->mac, mac, MAX_STR_LEN);
 1429     printf("        MAC Address:      %s\n", mac);
 1430     printf("        FCF Priority:     %u\n", fcf->priority);
 1431     printf("        FKA Period:       %u seconds\n", fcf->fka_period);
 1432     printf("        Selected:         ");
 1433     (fcf->selected == 1) ? printf("Yes\n") : printf("No\n");
 1434     printf("        VLAN ID:          %u\n", fcf->vlan_id);
 1435     printf("\n");
 1436 }
 1437 
 1438 static void print_interface_fcoe_fcf_device(void *ep, void *arg)
 1439 {
 1440     struct fcoe_ctlr_device *ctlr = (struct fcoe_ctlr_device *)ep;
 1441     const char *ifname = arg;
 1442     const char *buf;
 1443     char temp[MAX_STR_LEN];
 1444     int len = sizeof(temp);
 1445 
 1446     if (!ifname || !strncmp(ifname, ctlr->ifname, IFNAMSIZ)) {
 1447         printf("    Interface:        %s\n", ctlr->ifname);
 1448         buf = sa_enum_decode(temp, len, fip_conn_type_table,
 1449                      ctlr->mode);
 1450         if (!buf)
 1451             buf = temp;
 1452         printf("    Connection Type:  %s\n", buf);
 1453 
 1454         sa_table_iterate(&ctlr->fcfs, print_fcoe_fcf_device, NULL);
 1455     }
 1456 }
 1457 
 1458 /*
 1459  * NULL ifname indicates to dispaly all fcfs
 1460  */
 1461 enum fcoe_status display_fcf_info(const char *ifname)
 1462 {
 1463     enum fcoe_status rc = SUCCESS;
 1464 
 1465     sa_table_init(&fcoe_ctlr_table);
 1466     read_fcoe_ctlr(&fcoe_ctlr_table);
 1467 
 1468     sa_table_iterate(&fcoe_ctlr_table, print_interface_fcoe_fcf_device,
 1469              (void *)ifname);
 1470     sa_table_iterate(&fcoe_ctlr_table, free_fcoe_ctlr_device, NULL);
 1471 
 1472     return rc;
 1473 }
 1474 
 1475 static void print_interface_fcoe_lesb_stats(void *ep, void *arg)
 1476 {
 1477     struct fcoe_ctlr_device *ctlr = (struct fcoe_ctlr_device *)ep;
 1478     const char *ifname = arg;
 1479 
 1480     if (!ifname || !strncmp(ifname, ctlr->ifname, IFNAMSIZ)) {
 1481         printf("%-8u ", ctlr->lesb_link_fail);
 1482         printf("%-9u ", ctlr->lesb_vlink_fail);
 1483         printf("%-7u ", ctlr->lesb_miss_fka);
 1484         printf("%-7u ", ctlr->lesb_symb_err);
 1485         printf("%-9u ", ctlr->lesb_err_block);
 1486         printf("%-9u ", ctlr->lesb_fcs_error);
 1487         printf("\n");
 1488     }
 1489 }
 1490 
 1491 static void
 1492 print_interface_fcoe_lesb_stats_header(const char *ifname, int interval)
 1493 {
 1494     printf("\n");
 1495     printf("%-7s interval: %-2d\n", ifname, interval);
 1496     printf("LinkFail VLinkFail MissFKA SymbErr ErrBlkCnt FCSErrCnt\n");
 1497     printf("-------- --------- ------- ------- --------- ---------\n");
 1498 }
 1499 
 1500 enum fcoe_status display_port_lesb_stats(const char *ifname,
 1501                      int interval)
 1502 {
 1503     enum fcoe_status rc = SUCCESS;
 1504     int i = 0;
 1505 
 1506     while (1) {
 1507         unsigned int secs_left;
 1508 
 1509         sa_table_init(&fcoe_ctlr_table);
 1510         read_fcoe_ctlr(&fcoe_ctlr_table);
 1511 
 1512         if (!(i % 52))
 1513             print_interface_fcoe_lesb_stats_header(ifname,
 1514                                    interval);
 1515 
 1516         sa_table_iterate(&fcoe_ctlr_table,
 1517                  print_interface_fcoe_lesb_stats,
 1518                  (void *)ifname);
 1519 
 1520         sa_table_iterate(&fcoe_ctlr_table,
 1521                  free_fcoe_ctlr_device, NULL);
 1522 
 1523         i++;
 1524 
 1525         secs_left = interval;
 1526         do {
 1527             secs_left = sleep(secs_left);
 1528         } while (secs_left);
 1529     }
 1530 
 1531     return rc;
 1532 }