Use internal sysfs lib to display target and LUN info using fcoeadm -t
or fcoeadm -l.

Signed-off-by: Johannes Thumshirn <[email protected]>
---
 fcoeadm_display.c   | 1114 +++++++++++++++++----------------------------------
 fcoeadm_display.h   |    4 +-
 include/sysfs_hba.h |    6 +
 lib/sysfs_hba.c     |   73 +++-
 4 files changed, 450 insertions(+), 747 deletions(-)

diff --git a/fcoeadm_display.c b/fcoeadm_display.c
index c42cba6..80b2eb9 100644
--- a/fcoeadm_display.c
+++ b/fcoeadm_display.c
@@ -17,6 +17,8 @@
  * Maintained at www.Open-FCoE.org
  */
 
+#define _GNU_SOURCE
+
 #include <sys/param.h>
 #include <sys/ioctl.h>
 #include <linux/types.h>
@@ -25,6 +27,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
+#include <stdbool.h>
 #include <time.h>
 #include <malloc.h>
 #include <pthread.h>
@@ -34,6 +37,7 @@
 #include <net/if.h>
 #include <unistd.h>
 #include <inttypes.h>
+#include <dirent.h>
 
 #include "net_types.h"
 #include "fc_types.h"
@@ -90,6 +94,14 @@ struct hba_name_table_list {
        struct hba_name_table   hba_table[1];
 };
 
+/*
+ * Options for displaying target/LUN info.
+ */
+struct target_info_arguments {
+       char *ifname;
+       enum disp_style style;
+};
+
 struct sa_nameval port_states[] = {
        { "Not Present",    HBA_PORTSTATE_UNKNOWN },
        { "Online",         HBA_PORTSTATE_ONLINE },
@@ -104,6 +116,15 @@ struct sa_nameval port_states[] = {
        { NULL, 0 }
 };
 
+#define HBA_PORTSPEED_4GBIT            0x0008  /* 4 GBit/sec */
+#define HBA_PORTSPEED_8GBIT            0x0010  /* 8 GBit/sec */
+#define HBA_PORTSPEED_16GBIT           0x0020  /* 16 GBit/sec */
+#define HBA_PORTSPEED_32GBIT           0x0040  /* 32 GBit/sec */
+#define HBA_PORTSPEED_20GBIT           0x0080  /* 20 GBit/sec */
+#define HBA_PORTSPEED_40GBIT           0x0100  /* 40 GBit/sec */
+#define HBA_PORTSPEED_NOT_NEGOTIATED   (1 << 15) /* Speed not established */
+
+
 /*
  * table of /sys port speed strings to HBA-API values.
  */
@@ -122,37 +143,14 @@ struct sa_nameval port_speeds[] = {
        { NULL, 0 }
 };
 
-static void
-sa_dump_wwn(void *Data, int Length, int Break)
-{
-       unsigned char *pc = (unsigned char *)Data;
-       int i;
-
-       for (i = 1; i <= Length; i++) {
-               printf("%02X", (int)*pc++);
-               if ((Break != 0) && (!(i % Break)))
-                       printf("     ");
-       }
-}
-
-static int is_fcp_target(HBA_PORTATTRIBUTES *rp_info)
+static int is_fcp_target(struct port_attributes *rp_info)
 {
-       char buf[MAX_STR_LEN];
-
-       if (sa_sys_read_line(rp_info->OSDeviceName, "roles", buf, sizeof(buf)))
-               return -EINVAL;
-
-       if (!strncmp(buf, FCP_TARG_STR, strlen(FCP_TARG_STR)))
+       if (!strncmp(rp_info->roles, FCP_TARG_STR, strlen(FCP_TARG_STR)))
                return 0;
 
        return -EINVAL;
 }
 
-static void show_wwn(unsigned char *pWwn)
-{
-       sa_dump_wwn(pWwn, 8, 0);
-}
-
 static void show_hba_info(struct hba_info *hba_info)
 {
        printf("    Description:      %s\n", hba_info->model_description);
@@ -191,7 +189,7 @@ static void show_port_info(struct port_attributes *lp_info)
        printf("        MaxFrameSize:      %s\n",
               lp_info->maxframe_size);
 
-       printf("        FC-ID (Port ID):   0x%s\n",
+       printf("        FC-ID (Port ID):   %s\n",
               lp_info->port_id);
 
        printf("        State:             %s\n",
@@ -200,403 +198,68 @@ static void show_port_info(struct port_attributes 
*lp_info)
 }
 
 static void show_target_info(const char *symbolic_name,
-                            HBA_PORTATTRIBUTES *rp_info)
+                            struct port_attributes *rp_info)
 {
-       char buf[256];
-       int tgt_id;
-       int rc;
        char *ifname;
 
        ifname = get_ifname_from_symbolic_name(symbolic_name);
 
-       rc = sa_sys_read_line(rp_info->OSDeviceName, "roles", buf, sizeof(buf));
-       if (rc)
-               strncpy(buf, "Unknown", sizeof(buf));
        printf("    Interface:        %s\n", ifname);
-       printf("    Roles:            %s\n", buf);
-
-       printf("    Node Name:        0x");
-       show_wwn(rp_info->NodeWWN.wwn);
-       printf("\n");
-
-       printf("    Port Name:        0x");
-       show_wwn(rp_info->PortWWN.wwn);
-       printf("\n");
-
-       rc = sa_sys_read_int(rp_info->OSDeviceName, "scsi_target_id", &tgt_id);
-       printf("    Target ID:        ");
-       if (rc)
-               printf("Unknown\n");
-       else if (tgt_id != -1)
-               printf("%d\n", tgt_id);
-       else
-               printf("Unset\n");
-
-       printf("    MaxFrameSize:     %d\n", rp_info->PortMaxFrameSize);
-
-       printf("    OS Device Name:   %s\n",
-              strrchr(rp_info->OSDeviceName, '/') + 1);
-
-       printf("    FC-ID (Port ID):  0x%06X\n", rp_info->PortFcId);
-
-       sa_enum_decode(buf, sizeof(buf), port_states, rp_info->PortState);
-       printf("    State:            %s\n", buf);
+       printf("    Roles:            %s\n", rp_info->roles);
+       printf("    Node Name:        %s\n", rp_info->node_name);
+       printf("    Port Name:        %s\n", rp_info->port_name);
+       printf("    Target ID:        %s\n", rp_info->scsi_target_id);
+       printf("    MaxFrameSize:     %s\n", rp_info->maxframe_size);
+       printf("    OS Device Name:   %s\n", rp_info->device_name);
+       printf("    FC-ID (Port ID):  %s\n", rp_info->port_id);
+       printf("    State:            %s\n", rp_info->port_state);
        printf("\n");
 }
 
 static void
-show_sense_data(char *dev, char *sense, int slen)
-{
-       printf("%s", dev);
-       if (slen >= 3)
-               printf("    Sense Key=0x%02x", sense[2]);
-       if (slen >= 13)
-               printf(" ASC=0x%02x", sense[12]);
-       if (slen >= 14)
-               printf(" ASCQ=0x%02x\n", sense[13]);
-       printf("\n");
-}
-
-#ifdef TEST_HBAAPI_V1
-static HBA_STATUS
-get_inquiry_data_v1(HBA_HANDLE hba_handle,
-                   HBA_FCPSCSIENTRY *ep,
-                   char *inqbuf, size_t inqlen)
-{
-       char sense[128];
-       HBA_UINT32 rlen;
-       HBA_UINT32 slen;
-       HBA_STATUS status;
-
-       memset(inqbuf, 0, inqlen);
-       memset(sense, 0, sizeof(sense));
-       rlen = (HBA_UINT32) inqlen;
-       slen = (HBA_UINT32) sizeof(sense);
-       status = HBA_SendScsiInquiry(hba_handle,
-                                    ep->FcpId.PortWWN,
-                                    ep->FcpId.FcpLun,
-                                    0,
-                                    0,
-                                    inqbuf,
-                                    rlen,
-                                    sense,
-                                    slen);
-       if ((status != HBA_STATUS_OK) ||
-           (rlen < MIN_INQ_DATA_SIZE)) {
-               fprintf(stderr,
-                       "%s: HBA_SendScsiInquiry failed, "
-                       "status=0x%x, rlen=%d\n",
-                       __func__, status, rlen);
-               show_sense_data(ep->ScsiId.OSDeviceName, sense, slen);
-               return HBA_STATUS_ERROR;
-       }
-       return HBA_STATUS_OK;
-}
-#else
-static HBA_STATUS
-get_inquiry_data_v2(HBA_HANDLE hba_handle,
-                   HBA_PORTATTRIBUTES *lp_info,
-                   HBA_FCPSCSIENTRYV2 *ep,
-                   char *inqbuf, size_t inqlen)
+show_short_lun_info_header(void)
 {
-       char sense[128];
-       HBA_UINT32 rlen;
-       HBA_UINT32 slen;
-       HBA_STATUS status;
-       HBA_UINT8 sstat;
-
-       memset(inqbuf, 0, inqlen);
-       memset(sense, 0, sizeof(sense));
-       rlen = (HBA_UINT32) inqlen;
-       slen = (HBA_UINT32) sizeof(sense);
-       sstat = SCSI_ST_GOOD;
-       status = HBA_ScsiInquiryV2(hba_handle,
-                                  lp_info->PortWWN,
-                                  ep->FcpId.PortWWN,
-                                  ep->FcpId.FcpLun,
-                                  0,
-                                  0,
-                                  inqbuf,
-                                  &rlen,
-                                  &sstat,
-                                  sense,
-                                  &slen);
-       if ((status != HBA_STATUS_OK) ||
-           (sstat != SCSI_ST_GOOD) ||
-           (rlen < MIN_INQ_DATA_SIZE)) {
-               fprintf(stderr,
-                       "%s: HBA_ScsiInquiryV2 failed, "
-                       "status=0x%x, sstat=0x%x, rlen=%d\n",
-                       __func__, status, sstat, rlen);
-               if (sstat != SCSI_ST_GOOD)
-                       show_sense_data(ep->ScsiId.OSDeviceName, sense, slen);
-               return HBA_STATUS_ERROR;
-       }
-       return HBA_STATUS_OK;
+       printf("    LUN ID  Device Name   Capacity   "
+              "Block Size  Description\n");
+       printf("    ------  -----------  ----------  ----------  "
+              "----------------------------\n");
 }
-#endif
 
-#ifdef TEST_HBAAPI_V1
-static HBA_STATUS
-get_device_capacity_v1(HBA_HANDLE hba_handle,
-                      HBA_FCPSCSIENTRY *ep,
-                      char *buf, size_t len)
-{
-       char sense[128];
-       HBA_UINT32 rlen;
-       HBA_UINT32 slen;
-       HBA_STATUS status;
-       int retry_count = 10;
-
-       while (retry_count--) {
-               memset(buf, 0, len);
-               memset(sense, 0, sizeof(sense));
-               rlen = (HBA_UINT32)len;
-               slen = (HBA_UINT32)sizeof(sense);
-               status = HBA_SendReadCapacity(hba_handle,
-                                             ep->FcpId.PortWWN,
-                                             ep->FcpId.FcpLun,
-                                             buf,
-                                             rlen,
-                                             sense,
-                                             slen);
-               if (status == HBA_STATUS_OK)
-                       return HBA_STATUS_OK;
-               if (sense[2] == 0x06)
-                       continue;
-               fprintf(stderr,
-                       "%s: HBA_SendReadCapacity failed, "
-                       "status=0x%x, slen=%d\n",
-                       __func__, status, slen);
-               show_sense_data(ep->ScsiId.OSDeviceName, sense, slen);
-               return HBA_STATUS_ERROR;
-       }
-       /* retry count exhausted */
-       return HBA_STATUS_ERROR;
-}
-#else
-static HBA_STATUS
-get_device_capacity_v2(HBA_HANDLE hba_handle,
-                      HBA_PORTATTRIBUTES *lp_info,
-                      HBA_FCPSCSIENTRYV2 *ep,
-                      char *buf, size_t len)
+static void sa_dir_crawl(char *dir_name,
+                        void (*func)(char *dirname, enum disp_style style),
+                        enum disp_style style)
 {
-       char sense[128];
-       HBA_UINT32 rlen;
-       HBA_UINT32 slen;
-       HBA_STATUS status;
-       HBA_UINT8 sstat;
-       int retry_count = 10;
-
-       while (retry_count--) {
-               memset(buf, 0, len);
-               memset(sense, 0, sizeof(sense));
-               rlen = (HBA_UINT32)len;
-               slen = (HBA_UINT32)sizeof(sense);
-               sstat = SCSI_ST_GOOD;
-               status = HBA_ScsiReadCapacityV2(hba_handle,
-                                               lp_info->PortWWN,
-                                               ep->FcpId.PortWWN,
-                                               ep->FcpId.FcpLun,
-                                               buf,
-                                               &rlen,
-                                               &sstat,
-                                               sense,
-                                               &slen);
-               if ((status == HBA_STATUS_OK) && (sstat == SCSI_ST_GOOD))
-                       return HBA_STATUS_OK;
-               if (sstat == SCSI_ST_CHECK)
-                       continue;
-               fprintf(stderr,
-                       "%s: HBA_ScsiReadCapacityV2 failed, "
-                       "status=0x%x, sstat=0x%x, slen=%d\n",
-                       __func__, status, sstat, slen);
-               if (sstat != SCSI_ST_GOOD)
-                       show_sense_data(ep->ScsiId.OSDeviceName, sense, slen);
-               return HBA_STATUS_ERROR;
-       }
-       /* retry count exhausted */
-       return HBA_STATUS_ERROR;
-}
-#endif
+       DIR *dir;
+       struct dirent *dp;
+       void (*f)(char *dirname, enum disp_style style);
+       char path[1024];
 
-#ifdef TEST_DEV_SERIAL_NO
-static HBA_STATUS
-get_device_serial_number(HBA_HANDLE hba_handle,
-                        HBA_FCPSCSIENTRYV2 *ep,
-                        char *buf, size_t buflen)
-{
-       struct scsi_inquiry_unit_sn *unit_sn;
-       char rspbuf[256];
-       char sense[128];
-       HBA_UINT32 rlen;
-       HBA_UINT32 slen;
-       HBA_STATUS status;
-
-       memset(rspbuf, 0, sizeof(rspbuf));
-       memset(sense, 0, sizeof(sense));
-       rlen = (HBA_UINT32) sizeof(rspbuf);
-       slen = (HBA_UINT32) sizeof(sense);
-       status = HBA_SendScsiInquiry(hba_handle,
-                                    ep->FcpId.PortWWN,
-                                    ep->FcpId.FcpLun,
-                                    SCSI_INQF_EVPD,
-                                    SCSI_INQP_UNIT_SN,
-                                    rspbuf,
-                                    rlen,
-                                    sense,
-                                    slen);
-       if (status != HBA_STATUS_OK) {
-               fprintf(stderr,
-                       "%s: inquiry page 0x80 failed, status=0x%x\n",
-                       __func__, status);
-               show_sense_data(ep->ScsiId.OSDeviceName, sense, slen);
-               return HBA_STATUS_ERROR;
-       }
-       unit_sn = (struct scsi_inquiry_unit_sn *)rspbuf;
-       unit_sn->is_serial[unit_sn->is_page_len] = '\0';
-       sa_strncpy_safe(buf, buflen, (char *)unit_sn->is_serial,
-                       (size_t)unit_sn->is_page_len);
-       return HBA_STATUS_OK;
-}
-#endif
+       f = func;
 
-#ifdef TEST_REPORT_LUNS
-static void
-show_report_luns_data(char *rspbuf)
-{
-       struct scsi_report_luns_resp *rp;
-       int list_len;
-       net64_t *lp;
-       u_int64_t lun_id;
-
-       rp = (struct scsi_report_luns_resp *)rspbuf;
-       list_len = net32_get(&rp->rl_len);
-       printf("\tTotal Number of LUNs=%lu\n", list_len/sizeof(u_int64_t));
-
-       for (lp = rp->rl_lun; list_len > 0; lp++, list_len -= sizeof(*lp)) {
-               lun_id = net64_get(lp);
-               if (!(lun_id & ((0xfc01ULL << 48) - 1)))
-                       printf("\tLUN %u\n", (u_int32_t)(lun_id >> 48));
-               else
-                       printf("\tLUN %lx\n", (u_int64_t)lun_id);
-       }
-}
+       dir = opendir(dir_name);
+       if (!dir)
+               return;
 
-static HBA_STATUS
-get_report_luns_data_v1(HBA_HANDLE hba_handle, HBA_FCPSCSIENTRYV2 *ep)
-{
-       HBA_STATUS status;
-       char rspbuf[512 * sizeof(u_int64_t)]; /* max 512 luns */
-       char sense[128];
-       HBA_UINT32 rlen;
-       HBA_UINT32 slen;
-       int retry_count = 10;
-
-       while (retry_count--) {
-               memset(rspbuf, 0, sizeof(rspbuf));
-               memset(sense, 0, sizeof(sense));
-               rlen = (HBA_UINT32) sizeof(rspbuf);
-               slen = (HBA_UINT32) sizeof(sense);
-               status = HBA_SendReportLUNs(hba_handle,
-                                           ep->FcpId.PortWWN,
-                                           rspbuf,
-                                           rlen,
-                                           sense,
-                                           slen);
-               if (status == HBA_STATUS_OK) {
-                       show_report_luns_data(rspbuf);
-                       return HBA_STATUS_OK;
-               }
-               if (sense[2] == 0x06)
+       while ((dp = readdir(dir)) != NULL) {
+               if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' ||
+                  (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
                        continue;
-               fprintf(stderr,
-                       "%s: HBA_SendReportLUNs failed, "
-                       "status=0x%x, slen=%d\n",
-                       __func__, status, slen);
-               show_sense_data(ep->ScsiId.OSDeviceName, sense, slen);
-               return HBA_STATUS_ERROR;
-       }
-       /* retry count exhausted */
-       return HBA_STATUS_ERROR;
-}
+               snprintf(path, sizeof(path), "%s/%s", dir_name, dp->d_name);
 
-static HBA_STATUS
-get_report_luns_data_v2(HBA_HANDLE hba_handle,
-                       HBA_PORTATTRIBUTES *lp_info,
-                       HBA_FCPSCSIENTRYV2 *ep)
-{
-       HBA_STATUS status;
-       char rspbuf[512 * sizeof(u_int64_t)]; /* max 512 luns */
-       char sense[128];
-       HBA_UINT32 rlen;
-       HBA_UINT32 slen;
-       HBA_UINT8 sstat;
-       int retry_count = 10;
-
-       while (retry_count--) {
-               memset(rspbuf, 0, sizeof(rspbuf));
-               memset(sense, 0, sizeof(sense));
-               rlen = (HBA_UINT32) sizeof(rspbuf);
-               slen = (HBA_UINT32) sizeof(sense);
-               sstat = SCSI_ST_GOOD;
-               status = HBA_ScsiReportLUNsV2(hba_handle,
-                                             lp_info->PortWWN,
-                                             ep->FcpId.PortWWN,
-                                             rspbuf,
-                                             &rlen,
-                                             &sstat,
-                                             sense,
-                                             &slen);
-               if ((status == HBA_STATUS_OK) && (sstat == SCSI_ST_GOOD)) {
-                       show_report_luns_data(rspbuf);
-                       return HBA_STATUS_OK;
-               }
-               if ((sstat == SCSI_ST_CHECK) && (sense[2] == 0x06))
-                       continue;
-               fprintf(stderr,
-                       "%s: HBA_ScsiReportLUNsV2 failed, "
-                       "status=0x%x, sstat=0x%x, slen=%d\n",
-                       __func__, status, sstat, slen);
-               if (sstat != SCSI_ST_GOOD)
-                       show_sense_data(ep->ScsiId.OSDeviceName, sense, slen);
-               return HBA_STATUS_ERROR;
+               f(path, style);
        }
-       /* retry count exhausted */
-       return HBA_STATUS_ERROR;
+       closedir(dir);
 }
-#endif
 
-static void
-show_short_lun_info_header(void)
+static char *format_capstr(uint64_t size, unsigned int blksize)
 {
-       printf("    LUN ID  Device Name   Capacity   "
-              "Block Size  Description\n");
-       printf("    ------  -----------  ----------  ----------  "
-              "----------------------------\n");
-}
-
-static void
-show_short_lun_info(HBA_FCP_SCSI_ENTRY *ep, char *inqbuf,
-                   u_int32_t blksize,
-                   u_int64_t lba)
-{
-       struct scsi_inquiry_std *inq = (struct scsi_inquiry_std *)inqbuf;
-       char vendor[10];
-       char model[20];
-       char capstr[32];
-       char rev[16];
-       u_int64_t cap;
        double cap_abbr;
+       char *capstr;
+       uint64_t cap;
        char *abbr;
+       int ret;
 
-       memset(vendor, 0, sizeof(vendor));
-       memset(model, 0, sizeof(model));
-       memset(capstr, 0, sizeof(capstr));
-       memset(rev, 0, sizeof(rev));
-
-       /* Get device capacity */
-       cap = (u_int64_t)blksize * lba;
+       cap = size * blksize;
 
        cap_abbr = cap / (1024.0 * 1024.0);
        abbr = "MiB";
@@ -612,323 +275,228 @@ show_short_lun_info(HBA_FCP_SCSI_ENTRY *ep, char 
*inqbuf,
                cap_abbr /= 1024.0;
                abbr = "PiB";
        }
-       snprintf(capstr, sizeof(capstr), "%0.2f %s", cap_abbr, abbr);
 
-       /* Get the device description */
-       sa_strncpy_safe(vendor, sizeof(vendor),
-                       inq->is_vendor_id, sizeof(inq->is_vendor_id));
-       sa_strncpy_safe(model, sizeof(model),
-                       inq->is_product, sizeof(inq->is_product));
-       sa_strncpy_safe(rev, sizeof(rev), inq->is_rev_level,
-                       sizeof(inq->is_rev_level));
+       ret = asprintf(&capstr, "%0.2f %s", cap_abbr, abbr);
+       if (ret == -1)
+               return "Unknown";
 
-       /* Show the LUN info */
-       printf("%10d  %-11s  %10s  %7d     %s %s (rev %s)\n",
-              ep->ScsiId.ScsiOSLun, ep->ScsiId.OSDeviceName,
-              capstr, blksize,
-              vendor, model, rev);
+       return capstr;
 }
 
-static void
-show_full_lun_info(UNUSED HBA_HANDLE hba_handle,
-                  HBA_PORTATTRIBUTES *lp_info,
-                  HBA_PORTATTRIBUTES *rp_info,
-                  HBA_FCP_SCSI_ENTRY *ep,
-                  char *inqbuf,
-                  u_int32_t blksize,
-                  u_int64_t lba)
+static void show_full_lun_info(unsigned int hba, unsigned int port,
+                               unsigned int tgt, unsigned int lun)
 {
-       struct scsi_inquiry_std *inq = (struct scsi_inquiry_std *)inqbuf;
-       char vendor[10];
-       char model[20];
-       char capstr[32];
-       char rev[16];
-       double cap_abbr;
-       char *abbr;
-       u_int64_t cap;
-       u_int32_t tgt_id;
-       u_int8_t pqual;
-#ifdef TEST_DEV_SERIAL_NO
-       HBA_STATUS status;
-       char serial_number[32];
-#endif
+       char vendor[256];
+       char model[256];
+       char rev[256];
+       char *osname;
+       char *capstr;
+       uint64_t lba = 0;
+       uint32_t blksize = 0;
+       char path[1024];
+       char npath[1024];
+       DIR *dir;
+       struct dirent *dp;
+       struct port_attributes *rport_attrs;
+       struct port_attributes *port_attrs;
 
-       memset(vendor, 0, sizeof(vendor));
-       memset(model, 0, sizeof(model));
-       memset(capstr, 0, sizeof(capstr));
-       memset(rev, 0, sizeof(rev));
+       snprintf(path, sizeof(path),
+               "/sys/class/scsi_device/%u:%u:%u:%u",
+               hba, port, tgt, lun);
 
-       /* Get device description */
-       sa_strncpy_safe(vendor, sizeof(vendor),
-                       inq->is_vendor_id, sizeof(inq->is_vendor_id));
-       sa_strncpy_safe(model, sizeof(model),
-                       inq->is_product, sizeof(inq->is_product));
-       sa_strncpy_safe(rev, sizeof(rev), inq->is_rev_level,
-                       sizeof(inq->is_rev_level));
+       rport_attrs = get_rport_attribs_by_device(path);
+       if (!rport_attrs)
+               return;
 
-       /* Get device capacity */
-       cap = (u_int64_t)blksize * lba;
+       port_attrs = get_port_attribs_by_device(path);
+       if (!port_attrs)
+               goto free_rport;
 
-       cap_abbr = cap / (1024.0 * 1024.0);
-       abbr = "MiB";
-       if (cap_abbr >= 1024) {
-               cap_abbr /= 1024.0;
-               abbr = "GiB";
-       }
-       if (cap_abbr >= 1024) {
-               cap_abbr /= 1024.0;
-               abbr = "TiB";
-       }
-       if (cap_abbr >= 1024) {
-               cap_abbr /= 1024.0;
-               abbr = "PiB";
+       strncat(path, "/device/", sizeof(path));
+
+       sa_sys_read_line(path, "rev", rev, sizeof(rev));
+       sa_sys_read_line(path, "model", model, sizeof(model));
+       sa_sys_read_line(path, "vendor", vendor, sizeof(vendor));
+
+       strncat(path, "block", sizeof(path));
+
+       dir = opendir(path);
+       if (!dir)
+               goto free_port;
+
+       while ((dp = readdir(dir)) != NULL) {
+               if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' ||
+                  (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
+                       continue;
+
+
+               osname = dp->d_name;
+
+               snprintf(npath, sizeof(npath), "%s/%s/", path, osname);
+               sa_sys_read_u64(npath, "size", &lba);
+
+               snprintf(npath, sizeof(npath), "%s/%s/queue/", path, osname);
+               sa_sys_read_u32(npath, "hw_sector_size", &blksize);
        }
-       snprintf(capstr, sizeof(capstr), "%0.2f %s", cap_abbr, abbr);
 
-       /* Get SCSI target ID */
-       sa_sys_read_u32(rp_info->OSDeviceName,
-                       "scsi_target_id", &tgt_id);
+       closedir(dir);
 
        /* Show lun info */
-       printf("    LUN #%d Information:\n", ep->ScsiId.ScsiOSLun);
+       printf("    LUN #%d Information:\n", lun);
        printf("        OS Device Name:     %s\n",
-              ep->ScsiId.OSDeviceName);
+              osname);
        printf("        Description:        %s %s (rev %s)\n",
               vendor, model, rev);
-       printf("        Ethernet Port FCID: 0x%06X\n",
-              lp_info->PortFcId);
-       printf("        Target FCID:        0x%06X\n",
-              rp_info->PortFcId);
-       if (tgt_id == 0xFFFFFFFFU)
+       printf("        Ethernet Port FCID: %s\n",
+              port_attrs->port_id);
+       printf("        Target FCID:        %s\n",
+               rport_attrs->port_id);
+       if (tgt == 0xFFFFFFFFU)
                printf("        Target ID:          (None)\n");
        else
-               printf("        Target ID:          %u\n", tgt_id);
-       printf("        LUN ID:             %d\n",
-              ep->ScsiId.ScsiOSLun);
+               printf("        Target ID:          %u\n", tgt);
+       printf("        LUN ID:             %d\n", lun);
 
+       capstr = format_capstr(lba, blksize);
        printf("        Capacity:           %s\n", capstr);
        printf("        Capacity in Blocks: %" PRIu64 "\n", lba);
        printf("        Block Size:         %" PRIu32 " bytes\n", blksize);
-       pqual = inq->is_periph & SCSI_INQ_PQUAL_MASK;
-       if (pqual == SCSI_PQUAL_ATT)
-               printf("        Status:             Attached\n");
-       else if (pqual == SCSI_PQUAL_DET)
-               printf("        Status:             Detached\n");
-       else if (pqual == SCSI_PQUAL_NC)
-               printf("        Status:             "
-                      "Not capable of attachment\n");
-
-#ifdef TEST_DEV_SERIAL_NO
-       /* Show the serial number of the device */
-       status = get_device_serial_number(hba_handle, ep,
-                                         serial_number, sizeof(serial_number));
-       if (status == HBA_STATUS_OK)
-               printf("        Serial Number:      %s\n", serial_number);
-#endif
+       printf("        Status:             Attached\n");
 
        printf("\n");
+
+free_rport:
+       free(rport_attrs);
+free_port:
+       free(port_attrs);
 }
 
-/* Compare two LUN mappings for qsort */
-static int
-lun_compare(const void *arg1, const void *arg2)
+static void show_short_lun_info(unsigned int hba, unsigned int port,
+                               unsigned int tgt, unsigned int lun)
 {
-       const HBA_FCP_SCSI_ENTRY *e1 = arg1;
-       const HBA_FCP_SCSI_ENTRY *e2 = arg2;
-       int diff;
+       struct dirent *dp;
+       char vendor[256];
+       char path[1024];
+       char npath[1024];
+       char model[256];
+       char rev[256];
+       DIR *dir;
+       uint32_t blksize = 0;
+       char *capstr = "Unknown";
+       char *osname = "Unknown";
+       uint64_t size;
+
+       snprintf(path, sizeof(path),
+               "/sys/class/scsi_device/%u:%u:%u:%u/device/",
+               hba, port, tgt, lun);
+
+       sa_sys_read_line(path, "rev", rev, sizeof(rev));
+       sa_sys_read_line(path, "model", model, sizeof(model));
+       sa_sys_read_line(path, "vendor", vendor, sizeof(vendor));
+
+       strncat(path, "block", sizeof(path));
+
+       dir = opendir(path);
+       if (!dir)
+               return;
 
-       diff = e2->FcpId.FcId - e1->FcpId.FcId;
-       if (diff == 0)
-               diff = e1->ScsiId.ScsiOSLun - e2->ScsiId.ScsiOSLun;
+       while ((dp = readdir(dir)) != NULL) {
+               if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' ||
+                  (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
+                       continue;
 
-       return diff;
-}
 
-static HBA_STATUS
-get_device_map(HBA_HANDLE hba_handle, HBA_PORTATTRIBUTES *lp_info,
-              HBA_FCP_TARGET_MAPPING **tgtmap, u_int32_t *lun_count)
-{
-       HBA_STATUS status;
-       HBA_FCP_TARGET_MAPPING *map = NULL;
-       HBA_FCP_SCSI_ENTRY *ep;
-       u_int32_t limit;
-       u_int32_t i;
+               osname = dp->d_name;
 
-#define LUN_COUNT_START     8       /* number of LUNs to start with */
-#define LUN_COUNT_INCR      4       /* excess to allocate */
+               snprintf(npath, sizeof(npath), "%s/%s/", path, osname);
+               sa_sys_read_u64(npath, "size", &size);
 
-       /*
-        * Get buffer large enough to retrieve all the mappings.
-        * If they don't fit, increase the size of the buffer and retry.
-        */
-       *lun_count = 0;
-       limit = LUN_COUNT_START;
-       for (;;) {
-               i = (limit - 1) * sizeof(*ep) +  sizeof(*map);
-               map = malloc(i);
-               if (map == NULL) {
-                       fprintf(stderr, "%s: malloc failed\n", __func__);
-                       return HBA_STATUS_ERROR;
-               }
-               memset((char *)map, 0, i);
-               map->NumberOfEntries = limit;
-#ifdef TEST_HBAAPI_V1
-               status = HBA_GetFcpTargetMapping(hba_handle, map);
-#else
-               status = HBA_GetFcpTargetMappingV2(
-                       hba_handle, lp_info->PortWWN, map);
-#endif
-               if (map->NumberOfEntries > limit) {
-                       limit = map->NumberOfEntries + LUN_COUNT_INCR;
-                       free(map);
-                       continue;
-               }
-               if (status != HBA_STATUS_OK) {
-                       fprintf(stderr,
-                               "%s: HBA_GetFcpTargetMappingV2 failed\n",
-                               __func__);
-                       free(map);
-                       return HBA_STATUS_ERROR;
-               }
-               break;
+               snprintf(npath, sizeof(npath), "%s/%s/queue/", path, osname);
+               sa_sys_read_u32(npath, "hw_sector_size", &blksize);
        }
 
-       if (map == NULL) {
-               fprintf(stderr, "%s: map == NULL\n", __func__);
-               return HBA_STATUS_ERROR;
-       }
+       closedir(dir);
 
-       if (map->NumberOfEntries > limit) {
-               fprintf(stderr, "%s: map->NumberOfEntries=%d too big\n",
-                       __func__, map->NumberOfEntries);
-               return HBA_STATUS_ERROR;
-       }
+       capstr = format_capstr(size, blksize);
+
+       /* Show the LUN info */
+       printf("%10d  %-11s  %10s  %7d     %s %s (rev %s)\n",
+              lun, osname,
+              capstr, blksize,
+              vendor, model, rev);
 
-       ep = map->entry;
-       limit = map->NumberOfEntries;
+       free(capstr);
+       return;
+}
 
-       /* Sort the response by LUN number */
-       qsort(ep, limit, sizeof(*ep), lun_compare);
+static void list_scsi_device(char *d_name, enum disp_style style)
+{
+       unsigned int port;
+       unsigned int hba;
+       unsigned int tgt;
+       unsigned int lun;
+       char *last;
 
-       *lun_count = limit;
-       *tgtmap = map;
-       return HBA_STATUS_OK;
+       last = strrchr(d_name, '/');
+
+       if (sscanf(last, "/%u:%u:%u:%u", &hba, &port, &tgt, &lun) != 4)
+               return;
+
+
+       if (style == DISP_TARG)
+               show_short_lun_info(hba, port, tgt, lun);
+       else
+               show_full_lun_info(hba, port, tgt, lun);
 }
 
-static void
-scan_device_map(HBA_HANDLE hba_handle,
-               HBA_PORTATTRIBUTES *lp_info,
-               HBA_PORTATTRIBUTES *rp_info,
-               enum disp_style style)
+static void search_rport_targets(char *d_name, enum disp_style style)
 {
-       HBA_STATUS status;
-       HBA_FCP_TARGET_MAPPING *map = NULL;
-       u_int32_t limit;
-       HBA_FCP_SCSI_ENTRY *ep;
-       u_int32_t i;
-       char *dev;
-       char inqbuf[256];
-       struct scsi_rcap10_resp rcap_resp;
-       struct scsi_rcap16_resp rcap16_resp;
-       u_int64_t lba;
-       u_int32_t blksize;
-       int lun_count = 0;
-       int print_header = 0;
-
-       status = get_device_map(hba_handle, lp_info, &map, &limit);
-       if (status != HBA_STATUS_OK) {
-               fprintf(stderr, "%s: get_device_map() failed\n", __func__);
+       if (!strstr(d_name, "target"))
                return;
-       }
 
-       ep = map->entry;
-       for (i = 0; i < limit; i++, ep++) {
-               if (ep->FcpId.FcId != rp_info->PortFcId)
-                       continue;
+       sa_dir_crawl(d_name, list_scsi_device, style);
+}
 
-               dev = ep->ScsiId.OSDeviceName;
-               if (strstr(dev, "/dev/") == dev)
-                       dev += 5;
+static void list_luns_by_rport(char *rport, enum disp_style style)
+{
+       char path[1024];
+       char link[1024];
+       char *substr;
+       int len;
+       int ret;
 
-               /* Issue standard inquiry */
-#ifdef TEST_HBAAPI_V1
-               status = get_inquiry_data_v1(hba_handle, ep,
-                                            inqbuf, sizeof(inqbuf));
-#else
-               status = get_inquiry_data_v2(hba_handle, lp_info,
-                                            ep, inqbuf, sizeof(inqbuf));
-#endif
-               if (status != HBA_STATUS_OK)
-                       continue;
-               lun_count++;
+       snprintf(path, sizeof(path), "/sys/class/fc_remote_ports/%s", rport);
 
-               /* Issue read capacity */
-#ifdef TEST_HBAAPI_V1
-               status = get_device_capacity_v1(hba_handle, ep,
-                                               (char *)&rcap_resp,
-                                               sizeof(rcap_resp));
-#else
-               status = get_device_capacity_v2(hba_handle, lp_info,
-                                               ep, (char *)&rcap_resp,
-                                               sizeof(rcap_resp));
-#endif
-               if (status != HBA_STATUS_OK)
-                       continue;
+       ret = readlink(path, link, sizeof(link));
+       if (ret== -1)
+               return;
 
-               if (net32_get(&rcap_resp.rc_lba) == 0xFFFFFFFFUL) {
-                       /* Issue read capacity (16) */
-#ifdef TEST_HBAAPI_V1
-                       status = get_device_capacity_v1(hba_handle, ep,
-                                                       (char *)&rcap16_resp,
-                                                       sizeof(rcap16_resp));
-#else
-                       status = get_device_capacity_v2(hba_handle, lp_info,
-                                                       ep, (char 
*)&rcap16_resp,
-                                                       sizeof(rcap16_resp));
-#endif
-                       if (status != HBA_STATUS_OK)
-                               continue;
-
-                       blksize = net32_get(&rcap16_resp.rc_block_len);
-                       lba = (u_int64_t)net64_get(&rcap16_resp.rc_lba);
-               } else {
-                       blksize = net32_get(&rcap_resp.rc_block_len);
-                       lba = (u_int64_t)net32_get(&rcap_resp.rc_lba);
-               }
+       if (link[ret] != '\0')
+               link[ret] = '\0';
 
-               /* Total Number of Blocks */
-               lba = lba + 1;
+       substr = strstr(link, "net");
+       snprintf(path, sizeof(path), "/sys/class/%s", substr);
 
-               switch (style) {
-               case DISP_TARG:
-                       if (!print_header) {
-                               show_short_lun_info_header();
-                               print_header = 1;
-                       }
-                       show_short_lun_info(ep, inqbuf, blksize, lba);
-                       break;
-               case DISP_LUN:
-                       show_full_lun_info(hba_handle, lp_info,
-                                          rp_info, ep, inqbuf, blksize, lba);
-                       break;
-               }
+       substr = strstr(path, "fc_remote_ports");
 
-#ifdef TEST_REPORT_LUNS
-               if (i == 0) {   /* only issue report luns to the first LUN */
-#ifdef TEST_HBAAPI_V1
-                       get_report_luns_data_v1(hba_handle, ep);
-#else
-                       get_report_luns_data_v2(hba_handle, lp_info, ep);
-#endif
-               }
-#endif
-       }
+       len = strlen(path) - strlen(substr);
+       path[len] = '\0';
+
+       sa_dir_crawl(path, search_rport_targets, style);
+
+       return;
+}
+
+static void scan_device_map(char *port, char *rport, enum disp_style style)
+{
+       if (style == DISP_TARG)
+               show_short_lun_info_header();
+
+       list_luns_by_rport(rport, style);
 
        /* Newline at the end of the short lun report */
        if (style == DISP_TARG)
                printf("\n");
-
-       free(map);
 }
 
 static void show_port_stats_header(const char *ifname, int interval)
@@ -1186,7 +754,7 @@ out:
        return rc;
 }
 
-static enum fcoe_status display_one_adapter_info(const char *ifname)
+static enum fcoe_status display_one_adapter_info(char *ifname)
 {
        struct port_attributes *port_attrs;
        struct hba_info *hba_info;
@@ -1234,7 +802,7 @@ static int search_fc_adapter(struct dirent *dp, void *arg)
        return 0;
 }
 
-enum fcoe_status display_adapter_info(const char *ifname)
+enum fcoe_status display_adapter_info(char *ifname)
 {
        enum fcoe_status rc = SUCCESS;
        int num_hbas;
@@ -1254,101 +822,161 @@ enum fcoe_status display_adapter_info(const char 
*ifname)
        return rc;
 }
 
-enum fcoe_status display_target_info(const char *ifname,
-                                    enum disp_style style)
+
+static char *get_ifname_from_rport(char *rport)
 {
-       HBA_STATUS retval;
-       HBA_PORTATTRIBUTES rport_attrs;
-       struct hba_name_table_list *hba_table_list = NULL;
-       int i, num_hbas = 0;
-       unsigned int target_index;
+       char link[1024];
+       char ifname[32];
+       ssize_t ret;
+       char *path;
+       char *offs;
+       int err;
+       int i = 0;
+
+       err = asprintf(&path, "%s/%s", "/sys/class/fc_remote_ports", rport);
+       if (err == -1)
+               return false;
+
+       ret = readlink(path, link, sizeof(link));
+       free(path);
+       if (ret == -1)
+               return false;
+
+       if (link[ret] != '\0')
+               link[ret] = '\0';
+
+       offs = strstr(link, "/net/");
+
+       offs = offs + 5;
+
+       for (i = 0; offs[i] != '\0'; i++)
+               if (offs[i] == '/')
+                       break;
+
+       strncpy(ifname, offs, i);
+       if (ifname[i] != '\0')
+               ifname[i] = '\0';
+
+       return strdup(ifname);
+}
+
+static enum fcoe_status display_one_target_info(char *ifname, char *rport,
+                                               enum disp_style style)
+{
+       struct port_attributes *rport_attrs;
+       struct port_attributes *port_attrs;
        enum fcoe_status rc = SUCCESS;
-       HBA_HANDLE hba_handle;
-       HBA_PORTATTRIBUTES *port_attrs;
+       char *host;
 
-       if (fcoeadm_loadhba())
-               return EHBAAPIERR;
+       rport_attrs = get_rport_attribs(rport);
+       if (!rport_attrs)
+               return EINTERR;
 
-       num_hbas = hba_table_list_init(&hba_table_list);
-       if (!num_hbas)
-               goto out;
+       /*
+        * Skip any targets that are not FCP targets
+        */
+       if (is_fcp_target(rport_attrs))
+               goto free_rport_attribs;
 
-       if (num_hbas < 0) {
-               rc = EINTERR;
-               goto out;
-       }
+       rc = EINTERR;
+       host = get_host_from_netdev(ifname);
+       if (!host)
+               goto free_rport_attribs;
+
+       port_attrs = get_port_attribs(host);
+       if (!port_attrs)
+               goto free_host;
+
+       show_target_info(port_attrs->symbolic_name,
+               rport_attrs);
+
+       if (strncmp(port_attrs->port_state, "Online", 6))
+               goto free_port_attribs;
 
        /*
-        * Loop through each HBA entry and for each serial number
-        * not already printed print the header and each sub-port
-        * on that adapter.
+        * This will print the LUN table
+        * under the target.
         */
-       for (i = 0 ; i < num_hbas ; i++) {
-               if (hba_table_list->hba_table[i].failed ||
-                   hba_table_list->hba_table[i].displayed)
-                       continue;
+       scan_device_map(ifname, rport, style);
 
-               hba_handle = hba_table_list->hba_table[i].hba_handle;
-               port_attrs = &hba_table_list->hba_table[i].port_attrs;
+free_port_attribs:
+       free(port_attrs);
+free_host:
+       free(host);
+free_rport_attribs:
+       free(rport_attrs);
 
-               if (ifname && check_symbolic_name_for_interface(
-                           port_attrs->PortSymbolicName,
-                           ifname)) {
-                       /*
-                        * Overloading 'displayed' to indicate
-                        * that the HBA/Port should be skipped.
-                        */
-                       hba_table_list->hba_table[i].displayed = 1;
-                       continue;
-               }
+       return rc;
+}
 
-               for (target_index = 0;
-                    target_index < port_attrs->NumberofDiscoveredPorts;
-                    target_index++) {
-
-                       /* TODO: Second arg might be incorrect */
-                       retval = HBA_GetDiscoveredPortAttributes(
-                               hba_handle,
-                               0, target_index,
-                               &rport_attrs);
-
-                       if (retval != HBA_STATUS_OK) {
-                               fprintf(stderr,
-                                       "HBA_GetDiscoveredPortAttributes "
-                                       "failed for target_index=%d, "
-                                       "status=%d\n", target_index, retval);
-                               hba_table_list->hba_table[i].failed = 1;
-                               continue;
-                       }
-
-                       /*
-                        * Skip any targets that are not FCP targets
-                        */
-                       if (is_fcp_target(&rport_attrs))
-                               continue;
-
-                       show_target_info(
-                               port_attrs->PortSymbolicName,
-                               &rport_attrs);
-
-                       if (port_attrs->PortState != HBA_PORTSTATE_ONLINE)
-                               continue;
-
-                       /*
-                        * This will print the LUN table
-                        * under the target.
-                        */
-                       scan_device_map(hba_handle,
-                                       port_attrs,
-                                       &rport_attrs, style);
-               }
+static bool rport_is_child(const char *rport, const char *ifname)
+{
+
+       char link[1024];
+       ssize_t ret;
+       char *path;
+       char *offs;
+       int err;
+
+       err = asprintf(&path, "%s/%s", "/sys/class/fc_remote_ports", rport);
+       if (err == -1)
+               return false;
+
+       ret = readlink(path, link, sizeof(link));
+       free(path);
+       if (ret == -1)
+               return false;
+
+       offs = strstr(link, ifname);
+
+       return offs ? true : false;
+}
+
+static int search_rports(struct dirent *dp, void *arg)
+{
+       struct target_info_arguments *ta;
+       bool allocated = false; /* ifname is malloc()ed? */
+       char *ifname;
+       char *rport;
+
+
+       ta = arg;
+       rport = dp->d_name;
+       ifname = ta->ifname;
+
+       if (ifname) {
+               bool child;
+
+               child = rport_is_child(rport, ifname);
+               if (!child)
+                       return 0;
+       } else {
+               ifname = get_ifname_from_rport(rport);
+               if (!ifname)
+                       return -ENOMEM;
+               allocated = true;
        }
 
-       hba_table_list_destroy(hba_table_list);
-out:
-       HBA_FreeLibrary();
+       display_one_target_info(ifname, rport, ta->style);
+
+       if (allocated)
+               free(ifname);
+
+       return 0;
+}
+
+enum fcoe_status display_target_info(char *ifname,
+                                    enum disp_style style)
+{
+       struct target_info_arguments args;
+
+       args.ifname = ifname;
+       args.style = style;
+
+       sa_dir_read("/sys/class/fc_remote_ports/", search_rports, (void *) 
&args);
+
+       return SUCCESS;
 
-       return rc;
 }
 
 static struct sa_table fcoe_ctlr_table;
diff --git a/fcoeadm_display.h b/fcoeadm_display.h
index 358abf3..689c6bc 100644
--- a/fcoeadm_display.h
+++ b/fcoeadm_display.h
@@ -27,9 +27,9 @@ enum disp_style {
        DISP_TARG,
 };
 
-enum fcoe_status display_adapter_info(const char *ifname);
+enum fcoe_status display_adapter_info(char *ifname);
 enum fcoe_status display_fcf_info(const char *ifname);
-enum fcoe_status display_target_info(const char *ifname,
+enum fcoe_status display_target_info(char *ifname,
                                     enum disp_style style);
 enum fcoe_status display_port_stats(const char *ifname,
                                    int stat_interval);
diff --git a/include/sysfs_hba.h b/include/sysfs_hba.h
index 1e62477..ff6dbaf 100644
--- a/include/sysfs_hba.h
+++ b/include/sysfs_hba.h
@@ -42,6 +42,9 @@ struct port_attributes {
        char maxframe_size[256];
        char port_id[256];
        char port_state[256];
+       char scsi_target_id[256];
+       char supported_classes[256];
+       char roles[256];
 };
 
 struct hba_info {
@@ -58,6 +61,9 @@ struct hba_info {
 int get_number_of_adapters(void);
 struct hba_info *get_hbainfo_by_pcidev(const char *pcidev);
 struct port_attributes *get_port_attribs(const char *host);
+struct port_attributes *get_port_attribs_by_device(char *path);
+struct port_attributes *get_rport_attribs(const char *rport);
+struct port_attributes *get_rport_attribs_by_device(char *path);
 char *get_pci_dev_from_netdev(const char *netdev);
 char *get_host_from_netdev(const char *netdev);
 
diff --git a/lib/sysfs_hba.c b/lib/sysfs_hba.c
index e7f3e0b..8b92989 100644
--- a/lib/sysfs_hba.c
+++ b/lib/sysfs_hba.c
@@ -35,8 +35,47 @@
 #include "sysfs_hba.h"
 #include "fcoemon_utils.h"
 
-#define SYSFS_HOST_DIR "/sys/class/fc_host"
-#define SYSFS_NET_DIR  "/sys/class/net"
+#define SYSFS_HOST_DIR         "/sys/class/fc_host"
+#define SYSFS_NET_DIR          "/sys/class/net"
+#define SYSFS_RPORT_DIR                "/sys/class/fc_remote_ports"
+
+struct port_attributes *get_port_attribs_by_device(char *path)
+{
+       char link[1024];
+       char *host;
+       char *rport;
+       int ret;
+
+       ret = readlink(path, link, sizeof(link));
+       if (ret == -1)
+               return NULL;
+
+       host = strstr(link, "host");
+       rport = strstr(link, "rport");
+
+       host[strlen(host) - strlen(rport) - 1] = '\0';
+
+       return get_port_attribs(host);
+}
+
+struct port_attributes *get_rport_attribs_by_device(char *path)
+{
+       char link[1024];
+       char *target;
+       char *rport;
+       int ret;
+
+       ret = readlink(path, link, sizeof(link));
+       if (ret == -1)
+               return NULL;
+
+       target = strstr(link, "target");
+       rport = strstr(link, "rport");
+
+       rport[strlen(rport) - strlen(target) - 1] = '\0';
+
+       return get_rport_attribs(rport);
+}
 
 static void get_device_serial_number(struct pci_device *dev,
                                     struct hba_info *info)
@@ -222,6 +261,36 @@ struct hba_info *get_hbainfo_by_pcidev(const char *pcidev)
        return info;
 }
 
+struct port_attributes *get_rport_attribs(const char *rport)
+{
+       struct port_attributes *pa;
+       char *path;
+       int err;
+
+       err = asprintf(&path,"%s/%s", SYSFS_RPORT_DIR, rport);
+       if (err == -1)
+               return NULL;
+
+       pa = calloc(1, sizeof(*pa));
+       if (!pa)
+               goto free_path;
+
+       strncpy(pa->device_name, rport, sizeof(pa->device_name));
+       sa_sys_read_line(path, "node_name", pa->node_name, 
sizeof(pa->node_name));
+       sa_sys_read_line(path, "port_name", pa->port_name, 
sizeof(pa->port_name));
+       sa_sys_read_line(path, "port_id", pa->port_id, sizeof(pa->port_id));
+       sa_sys_read_line(path, "scsi_target_id", pa->scsi_target_id, 
sizeof(pa->scsi_target_id));
+       sa_sys_read_line(path, "maxframe_size", pa->maxframe_size, 
sizeof(pa->maxframe_size));
+       sa_sys_read_line(path, "port_state", pa->port_state, 
sizeof(pa->port_state));
+       sa_sys_read_line(path, "supported_classes", pa->supported_classes, 
sizeof(pa->supported_classes));
+       sa_sys_read_line(path, "roles", pa->roles, sizeof(pa->roles));
+
+free_path:
+       free(path);
+
+       return pa;
+}
+
 struct port_attributes *get_port_attribs(const char *host)
 {
        struct port_attributes *pa;
-- 
2.5.0

_______________________________________________
fcoe-devel mailing list
[email protected]
http://lists.open-fcoe.org/mailman/listinfo/fcoe-devel

Reply via email to