#include "fcinfo.h"
#include <libintl.h>
struct lun {
uchar_t val[8];
};
typedef enum {
HBA_PORT,
REMOTE_PORT,
LOGICAL_UNIT
} resource_type;
typedef struct rep_luns_rsp {
uint32_t length;
uint32_t rsrvd;
struct lun lun[1];
} rep_luns_rsp_t;
static int getTargetMapping(HBA_HANDLE, HBA_WWN myhbaPortWWN,
HBA_FCPTARGETMAPPINGV2 **mapping);
static int processHBA(HBA_HANDLE handle, HBA_ADAPTERATTRIBUTES attrs,
int portIndex, HBA_PORTATTRIBUTES port, HBA_FCPTARGETMAPPINGV2 *map,
int resourceType, int flags, int mode);
static void processRemotePort(HBA_HANDLE handle, HBA_WWN portWWN,
HBA_FCPTARGETMAPPINGV2 *map, int wwnCount, char **wwn_argv, int flags);
static void handleRemotePort(HBA_HANDLE handle, HBA_WWN portWWN,
HBA_WWN myRemotePortWWN, HBA_PORTATTRIBUTES *discPort);
static void printLinkStat(HBA_HANDLE handle, HBA_WWN hbaportWWN,
HBA_WWN destWWN);
static void handleScsiTarget(HBA_HANDLE handle, HBA_WWN hbaPortWWN,
HBA_WWN scsiTargetWWN, HBA_FCPTARGETMAPPINGV2 *map);
static int retrieveAttrs(HBA_HANDLE handle, HBA_WWN hbaPortWWN,
HBA_ADAPTERATTRIBUTES *attrs, HBA_PORTATTRIBUTES *port, int *portIndex);
static void searchDevice(discoveredDevice **devList, HBA_FCPSCSIENTRYV2 entry,
HBA_WWN initiatorPortWWN, HBA_HANDLE handle, boolean_t verbose);
static int
retrieveAttrs(HBA_HANDLE handle, HBA_WWN hbaPortWWN,
HBA_ADAPTERATTRIBUTES *attrs, HBA_PORTATTRIBUTES *port, int *portIndex)
{
HBA_STATUS status;
int portCtr;
int times;
if (attrs == NULL || port == NULL || portIndex == NULL) {
fprintf(stderr, gettext("Error: Invalid arguments to "
"retreiveAttrs\n"));
return (1);
}
memset(attrs, 0, sizeof (HBA_ADAPTERATTRIBUTES));
status = HBA_GetAdapterAttributes(handle, attrs);
times = 0;
while ((status == HBA_STATUS_ERROR_TRY_AGAIN ||
status == HBA_STATUS_ERROR_BUSY) &&
times++ < HBA_MAX_RETRIES) {
(void) sleep(1);
status = HBA_GetAdapterAttributes(handle, attrs);
if (status == HBA_STATUS_OK) {
break;
}
}
if (status != HBA_STATUS_OK) {
fprintf(stderr, gettext("Failed to get adapter "
"attributes handle(%d) Reason: "), handle);
printStatus(status);
fprintf(stderr, "\n");
return (1);
}
memset(port, 0, sizeof (HBA_PORTATTRIBUTES));
for (portCtr = 0; portCtr < attrs->NumberOfPorts; portCtr++) {
if ((status = HBA_GetAdapterPortAttributes(handle,
portCtr, port)) != HBA_STATUS_OK) {
fprintf(stderr,
gettext("Error: Failed to get port (%d) "
"attributes reason: "), portCtr);
printStatus(status);
fprintf(stderr, "\n");
return (1);
}
if (memcmp(hbaPortWWN.wwn, port->PortWWN.wwn,
sizeof (port->PortWWN.wwn)) == 0) {
break;
}
}
if (portCtr >= attrs->NumberOfPorts) {
*portIndex = 0;
return (1);
}
*portIndex = portCtr;
return (0);
}
static int
getTargetMapping(HBA_HANDLE handle, HBA_WWN hbaPortWWN,
HBA_FCPTARGETMAPPINGV2 **mapping)
{
HBA_FCPTARGETMAPPINGV2 *map;
HBA_STATUS status;
int count;
if (mapping == NULL) {
fprintf(stderr, gettext("Internal Error: mapping is NULL"));
return (1);
}
*mapping = NULL;
if ((map = calloc(1, sizeof (HBA_FCPTARGETMAPPINGV2))) == NULL) {
fprintf(stderr,
gettext("Internal Error: Unable to calloc map"));
return (1);
}
status = HBA_GetFcpTargetMappingV2(handle, hbaPortWWN, map);
count = map->NumberOfEntries;
if (status == HBA_STATUS_ERROR_MORE_DATA) {
free(map);
if ((map = calloc(1, (sizeof (HBA_FCPSCSIENTRYV2)*(count-1)) +
sizeof (HBA_FCPTARGETMAPPINGV2))) == NULL) {
fprintf(stderr,
gettext("Unable to calloc map of size: %d"), count);
return (1);
}
map->NumberOfEntries = count;
status = HBA_GetFcpTargetMappingV2(handle, hbaPortWWN, map);
}
if (status != HBA_STATUS_OK) {
fprintf(stderr,
gettext("Error: Unable to get Target Mapping\n"));
printStatus(status);
fprintf(stderr, "\n");
free(map);
return (1);
}
*mapping = map;
return (0);
}
static void
handleRemotePort(HBA_HANDLE handle, HBA_WWN portWWN, HBA_WWN remotePortWWN,
HBA_PORTATTRIBUTES *discPort)
{
HBA_STATUS status;
int scsiTargetType;
uchar_t raw_luns[LUN_LENGTH];
HBA_UINT32 responseSize = LUN_LENGTH;
struct scsi_extended_sense sense;
HBA_UINT32 senseSize = sizeof (struct scsi_extended_sense);
HBA_UINT8 rep_luns_status;
if (discPort == NULL) {
return;
}
memset(raw_luns, 0, sizeof (raw_luns));
status = HBA_ScsiReportLUNsV2(handle, portWWN, remotePortWWN,
(void *)raw_luns, &responseSize, &rep_luns_status,
(void *)&sense, &senseSize);
if (status == HBA_STATUS_OK) {
scsiTargetType = SCSI_TARGET_TYPE_YES;
} else if (status == HBA_STATUS_ERROR_NOT_A_TARGET) {
scsiTargetType = SCSI_TARGET_TYPE_NO;
} else {
scsiTargetType = SCSI_TARGET_TYPE_UNKNOWN;
}
printDiscoPortInfo(discPort, scsiTargetType);
}
static void
printLinkStat(HBA_HANDLE handle, HBA_WWN hbaPortWWN, HBA_WWN destWWN)
{
HBA_STATUS status;
fc_rls_acc_t rls_payload;
uint32_t rls_payload_size;
memset(&rls_payload, 0, sizeof (rls_payload));
rls_payload_size = sizeof (rls_payload);
status = HBA_SendRLS(handle, hbaPortWWN, destWWN,
&rls_payload, &rls_payload_size);
if (status != HBA_STATUS_OK) {
fprintf(stderr, gettext("Error: SendRLS failed for %016llx\n"),
wwnConversion(destWWN.wwn));
} else {
printPortStat(&rls_payload);
}
}
int
printHBANPIVPortInfo(HBA_HANDLE handle, int portindex)
{
HBA_PORTNPIVATTRIBUTES portattrs;
HBA_NPIVATTRIBUTES npivattrs;
HBA_STATUS status;
int index;
int times = 0;
status = Sun_HBA_GetPortNPIVAttributes(handle, portindex, &portattrs);
while (status == HBA_STATUS_ERROR_TRY_AGAIN ||
status == HBA_STATUS_ERROR_BUSY) {
(void) sleep(1);
status = Sun_HBA_GetPortNPIVAttributes(
handle, portindex, &portattrs);
if (times++ > HBA_MAX_RETRIES) {
break;
}
}
if (status == HBA_STATUS_ERROR_NOT_SUPPORTED) {
fprintf(stdout, gettext("\tNPIV Not Supported\n"));
return (0);
}
if (status != HBA_STATUS_OK) {
fprintf(stderr,
gettext("Error: Failed to get port (%d) "
"npiv attributes reason: "), portindex);
printStatus(status);
fprintf(stderr, "\n");
return (1);
}
if (portattrs.MaxNumberOfNPIVPorts) {
fprintf(stdout, gettext("\tMax NPIV Ports: %d\n"),
portattrs.MaxNumberOfNPIVPorts);
} else {
fprintf(stdout, gettext("\tNPIV Not Supported\n"));
return (0);
}
fprintf(stdout, gettext("\tNPIV port list:\n"));
for (index = 0; index < portattrs.NumberOfNPIVPorts; index++) {
int times = 0;
status = Sun_HBA_GetNPIVPortInfo(handle,
portindex, index, &npivattrs);
while (status == HBA_STATUS_ERROR_TRY_AGAIN ||
status == HBA_STATUS_ERROR_BUSY) {
(void) sleep(1);
status = Sun_HBA_GetNPIVPortInfo(handle,
portindex, index, &npivattrs);
if (times++ > HBA_MAX_RETRIES) {
break;
}
}
if (status != HBA_STATUS_OK) {
fprintf(stderr,
gettext("Error: Failed to get npiv port (%d) "
"attributes reason: "), index);
printStatus(status);
fprintf(stderr, "\n");
return (1);
} else {
fprintf(stdout,
gettext("\t Virtual Port%d:\n"), index+1);
fprintf(stdout, gettext("\t\tNode WWN: %016llx\n"),
wwnConversion(npivattrs.NodeWWN.wwn));
fprintf(stdout, gettext("\t\tPort WWN: %016llx\n"),
wwnConversion(npivattrs.PortWWN.wwn));
}
}
return (0);
}
static int
processHBA(HBA_HANDLE handle, HBA_ADAPTERATTRIBUTES attrs, int portIndex,
HBA_PORTATTRIBUTES port, HBA_FCPTARGETMAPPINGV2 *map,
int resourceType, int flags, int mode)
{
HBA_PORTATTRIBUTES discPort;
HBA_STATUS status;
int discPortCount;
if (resourceType == HBA_PORT) {
if ((flags & PRINT_FCOE) == PRINT_FCOE &&
attrs.VendorSpecificID != 0xFC0E) {
return (0);
}
printHBAPortInfo(&port, &attrs, mode);
if ((flags & PRINT_LINKSTAT) == PRINT_LINKSTAT) {
printLinkStat(handle, port.PortWWN, port.PortWWN);
}
return (0);
}
for (discPortCount = 0;
discPortCount < port.NumberofDiscoveredPorts;
discPortCount++) {
status = HBA_GetDiscoveredPortAttributes(handle,
portIndex, discPortCount, &discPort);
if (status != HBA_STATUS_OK) {
fprintf(stderr,
gettext("Failed to get discovered port (%d)"
" attributes reason :"), discPortCount);
printStatus(status);
fprintf(stderr, "\n");
continue;
}
if (resourceType == REMOTE_PORT) {
handleRemotePort(handle, port.PortWWN, discPort.PortWWN,
&discPort);
if ((flags & PRINT_LINKSTAT) == PRINT_LINKSTAT) {
printLinkStat(handle, port.PortWWN,
discPort.PortWWN);
}
if ((flags & PRINT_SCSI_TARGET) == PRINT_SCSI_TARGET) {
handleScsiTarget(handle, port.PortWWN,
discPort.PortWWN, map);
}
}
}
return (0);
}
static void
processRemotePort(HBA_HANDLE handle, HBA_WWN portWWN,
HBA_FCPTARGETMAPPINGV2 *map, int wwnCount, char **wwn_argv, int flags)
{
int remote_wwn_counter;
uint64_t remotePortWWN;
HBA_WWN myremotePortWWN;
HBA_PORTATTRIBUTES discPort;
HBA_STATUS status;
for (remote_wwn_counter = 0;
remote_wwn_counter < wwnCount;
remote_wwn_counter++) {
int times = 0;
sscanf(wwn_argv[remote_wwn_counter], "%016llx",
&remotePortWWN);
remotePortWWN = htonll(remotePortWWN);
memcpy(myremotePortWWN.wwn, &remotePortWWN,
sizeof (remotePortWWN));
memset(&discPort, 0, sizeof (discPort));
status = HBA_GetPortAttributesByWWN(handle, myremotePortWWN,
&discPort);
while (status == HBA_STATUS_ERROR_TRY_AGAIN ||
status == HBA_STATUS_ERROR_BUSY) {
(void) sleep(1);
status = HBA_GetPortAttributesByWWN(handle,
myremotePortWWN, &discPort);
if (times++ > HBA_MAX_RETRIES) {
break;
}
}
if (status != HBA_STATUS_OK) {
fprintf(stderr, gettext("HBA_GetPortAttributesByWWN "
"failed: reason: "));
printStatus(status);
fprintf(stderr, "\n");
continue;
}
handleRemotePort(handle, portWWN, myremotePortWWN, &discPort);
if ((flags & PRINT_LINKSTAT) == PRINT_LINKSTAT) {
printLinkStat(handle, portWWN, myremotePortWWN);
}
if ((flags & PRINT_SCSI_TARGET) == PRINT_SCSI_TARGET) {
handleScsiTarget(handle, portWWN,
myremotePortWWN, map);
}
}
}
static void
handleScsiTarget(HBA_HANDLE handle, HBA_WWN hbaPortWWN, HBA_WWN scsiTargetWWN,
HBA_FCPTARGETMAPPINGV2 *map)
{
HBA_STATUS status;
struct scsi_inquiry inq;
struct scsi_extended_sense sense;
HBA_UINT32 responseSize, senseSize = 0;
HBA_UINT8 inq_status;
uchar_t raw_luns[DEFAULT_LUN_LENGTH], *lun_string;
HBA_UINT8 rep_luns_status;
rep_luns_rsp_t *lun_resp;
uint64_t fcLUN;
int lunNum, numberOfLun, lunCount, count;
uint32_t lunlength, tmp_lunlength;
responseSize = DEFAULT_LUN_LENGTH;
senseSize = sizeof (struct scsi_extended_sense);
memset(&sense, 0, sizeof (sense));
status = HBA_ScsiReportLUNsV2(handle, hbaPortWWN,
scsiTargetWWN, (void *)raw_luns, &responseSize,
&rep_luns_status, (void *)&sense, &senseSize);
if (status == HBA_STATUS_ERROR_NOT_A_TARGET) {
return;
} else if (status != HBA_STATUS_OK) {
fprintf(stderr, gettext("Error has occured. "
"HBA_ScsiReportLUNsV2 failed. reason "));
printStatus(status);
fprintf(stderr, "\n");
return;
}
lun_resp = (rep_luns_rsp_t *)raw_luns;
memcpy(&tmp_lunlength, &(lun_resp->length), sizeof (tmp_lunlength));
lunlength = htonl(tmp_lunlength);
memcpy(&numberOfLun, &lunlength, sizeof (numberOfLun));
for (lunCount = 0; lunCount < (numberOfLun / 8); lunCount++) {
responseSize = sizeof (struct scsi_inquiry);
senseSize = sizeof (struct scsi_extended_sense);
memset(&inq, 0, sizeof (struct scsi_inquiry));
memset(&sense, 0, sizeof (sense));
fcLUN = ntohll(wwnConversion(lun_resp->lun[lunCount].val));
status = HBA_ScsiInquiryV2(
handle,
hbaPortWWN,
scsiTargetWWN,
fcLUN,
0,
0,
&inq, &responseSize,
&inq_status,
&sense, &senseSize);
if (status != HBA_STATUS_OK) {
fprintf(stderr, gettext("Not able to issue Inquiry.\n"));
printStatus(status);
fprintf(stderr, "\n");
strcpy(inq.inq_vid, "Unknown");
strcpy(inq.inq_pid, "Unknown");
}
if (map != NULL) {
for (count = 0; count < map->NumberOfEntries; count++) {
if ((memcmp(map->entry[count].FcpId.PortWWN.wwn,
scsiTargetWWN.wwn,
sizeof (scsiTargetWWN.wwn))
== 0) &&
(memcmp(&(map->entry[count].FcpId.FcpLun),
&fcLUN, sizeof (fcLUN)) == 0)) {
printLUNInfo(&inq,
map->entry[count].ScsiId.ScsiOSLun,
map->entry[count].ScsiId.OSDeviceName);
break;
}
}
if (count == map->NumberOfEntries) {
lun_string = lun_resp->lun[lunCount].val;
lunNum = ((lun_string[0] & 0x3F) << 8) |
lun_string[1];
printLUNInfo(&inq, lunNum, "Unknown");
}
} else {
lun_string = lun_resp->lun[lunCount].val;
lunNum = ((lun_string[0] & 0x3F) << 8) |
lun_string[1];
printLUNInfo(&inq, lunNum, "Unknown");
}
}
}
int
fc_util_list_remoteport(int wwnCount, char **wwn_argv, cmdOptions_t *options)
{
HBA_STATUS status;
HBA_FCPTARGETMAPPINGV2 *map = NULL;
HBA_PORTATTRIBUTES port;
HBA_ADAPTERATTRIBUTES attrs;
HBA_HANDLE handle;
uint64_t hbaPortWWN;
HBA_WWN myhbaPortWWN;
int processHBA_flags = 0, portCount = 0;
int mode;
for (; options->optval; options++) {
if (options->optval == 'p') {
sscanf(options->optarg, "%016llx",
&hbaPortWWN);
} else if (options->optval == 's') {
processHBA_flags |= PRINT_SCSI_TARGET;
} else if (options->optval == 'l') {
processHBA_flags |= PRINT_LINKSTAT;
} else {
fprintf(stderr, gettext("Error: Illegal option: %c.\n"),
options->optval);
return (1);
}
}
if (hbaPortWWN == 0) {
fprintf(stderr,
gettext("Error: -p option was not specified.\n"));
return (1);
}
if ((status = HBA_LoadLibrary()) != HBA_STATUS_OK) {
fprintf(stderr,
gettext("Failed to load FC-HBA common library\n"));
printStatus(status);
fprintf(stderr, "\n");
return (1);
}
hbaPortWWN = htonll(hbaPortWWN);
memcpy(myhbaPortWWN.wwn, &hbaPortWWN, sizeof (hbaPortWWN));
if ((status = HBA_OpenAdapterByWWN(&handle, myhbaPortWWN))
!= HBA_STATUS_OK) {
status = Sun_HBA_OpenTgtAdapterByWWN(&handle, myhbaPortWWN);
if (status != HBA_STATUS_OK) {
fprintf(stderr,
gettext("Error: Failed to open adapter port. Reason "));
printStatus(status);
fprintf(stderr, "\n");
HBA_FreeLibrary();
return (1);
} else {
if ((processHBA_flags & PRINT_SCSI_TARGET) ==
PRINT_SCSI_TARGET) {
fprintf(stderr, gettext(
"Error: Unsupported option for target mode: %c.\n"),
's');
HBA_FreeLibrary();
return (1);
}
mode = TARGET_MODE;
}
} else {
mode = INITIATOR_MODE;
}
if ((processHBA_flags & PRINT_SCSI_TARGET) == PRINT_SCSI_TARGET) {
getTargetMapping(handle, myhbaPortWWN, &map);
}
if (wwnCount == 0) {
memset(&attrs, 0, sizeof (attrs));
memset(&port, 0, sizeof (port));
if (retrieveAttrs(handle, myhbaPortWWN, &attrs, &port,
&portCount) != 0) {
if (map != NULL) {
free(map);
}
HBA_CloseAdapter(handle);
HBA_FreeLibrary();
return (1);
}
processHBA(handle, attrs, portCount, port, map, REMOTE_PORT,
processHBA_flags, mode);
} else {
processRemotePort(handle, myhbaPortWWN, map, wwnCount,
wwn_argv, processHBA_flags);
}
if (map != NULL) {
free(map);
}
HBA_CloseAdapter(handle);
HBA_FreeLibrary();
return (0);
}
int
fc_util_list_hbaport(int wwnCount, char **wwn_argv, cmdOptions_t *options)
{
int port_wwn_counter, numAdapters = 0, numTgtAdapters = 0, i;
HBA_STATUS status;
char adapterName[256];
HBA_HANDLE handle;
uint64_t hbaWWN;
HBA_WWN myWWN;
int processHBA_flags = 0;
HBA_PORTATTRIBUTES port;
HBA_ADAPTERATTRIBUTES attrs;
int portIndex = 0, err_cnt = 0;
int mode;
for (; options->optval; options++) {
if (options->optval == 'l') {
processHBA_flags |= PRINT_LINKSTAT;
} else if (options->optval == 'i') {
processHBA_flags |= PRINT_INITIATOR;
} else if (options->optval == 't') {
processHBA_flags |= PRINT_TARGET;
} else if (options->optval == 'e') {
processHBA_flags |= PRINT_FCOE;
}
}
if (((processHBA_flags & PRINT_INITIATOR) == 0) &&
((processHBA_flags & PRINT_TARGET) == 0)) {
processHBA_flags |= PRINT_INITIATOR | PRINT_TARGET;
}
if ((status = HBA_LoadLibrary()) != HBA_STATUS_OK) {
fprintf(stderr,
gettext("Failed to load FC-HBA common library\n"));
printStatus(status);
fprintf(stderr, "\n");
return (1);
}
if (wwnCount > 0) {
for (port_wwn_counter = 0;
port_wwn_counter < wwnCount;
port_wwn_counter++) {
sscanf(wwn_argv[port_wwn_counter], "%016llx", &hbaWWN);
hbaWWN = htonll(hbaWWN);
memcpy(myWWN.wwn, &hbaWWN, sizeof (hbaWWN));
if ((processHBA_flags & PRINT_INITIATOR) ==
PRINT_INITIATOR) {
int times = 0;
status = HBA_OpenAdapterByWWN(&handle, myWWN);
while (status == HBA_STATUS_ERROR_TRY_AGAIN ||
status == HBA_STATUS_ERROR_BUSY) {
(void) sleep(1);
status = HBA_OpenAdapterByWWN(&handle, myWWN);
if (times++ > HBA_MAX_RETRIES) {
break;
}
}
if (status != HBA_STATUS_OK) {
if ((processHBA_flags & PRINT_TARGET) ==
PRINT_TARGET) {
status =
Sun_HBA_OpenTgtAdapterByWWN(&handle, myWWN);
if (status != HBA_STATUS_OK) {
fprintf(stderr,
gettext(
"Error: HBA port %s: not found\n"),
wwn_argv[port_wwn_counter]);
err_cnt++;
continue;
} else {
mode = TARGET_MODE;
}
} else {
fprintf(stderr,
gettext(
"Error: HBA port %s: not found\n"),
wwn_argv[port_wwn_counter]);
err_cnt++;
continue;
}
} else {
mode = INITIATOR_MODE;
}
} else if ((processHBA_flags & PRINT_TARGET) ==
PRINT_TARGET) {
status =
Sun_HBA_OpenTgtAdapterByWWN(&handle, myWWN);
if (status != HBA_STATUS_OK) {
fprintf(stderr, gettext(
"Error: HBA port %s: not found\n"),
wwn_argv[port_wwn_counter]);
err_cnt++;
continue;
} else {
mode = TARGET_MODE;
}
} else {
fprintf(stderr, gettext(
"Error: HBA port %s: not found\n"),
wwn_argv[port_wwn_counter]);
err_cnt++;
continue;
}
memset(&attrs, 0, sizeof (attrs));
memset(&port, 0, sizeof (port));
if (retrieveAttrs(handle, myWWN, &attrs, &port,
&portIndex) != 0) {
HBA_CloseAdapter(handle);
continue;
}
processHBA(handle, attrs, portIndex, port, NULL,
HBA_PORT, processHBA_flags, mode);
if ((processHBA_flags & PRINT_FCOE) != PRINT_FCOE &&
attrs.VendorSpecificID != 0xFC0E &&
printHBANPIVPortInfo(handle, portIndex) != 0) {
err_cnt++;
}
HBA_CloseAdapter(handle);
}
} else {
if ((processHBA_flags & PRINT_INITIATOR) == PRINT_INITIATOR) {
numAdapters = HBA_GetNumberOfAdapters();
if ((numAdapters == 0) &&
((processHBA_flags & ~PRINT_INITIATOR) == 0)) {
fprintf(stdout, gettext("No Adapters Found.\n"));
}
for (i = 0; i < numAdapters; i++) {
int times = 0;
status = HBA_GetAdapterName(i, adapterName);
if (status != HBA_STATUS_OK) {
fprintf(stderr, gettext(
"failed to get adapter %d. Reason: "), i);
printStatus(status);
fprintf(stderr, "\n");
continue;
}
if ((handle = HBA_OpenAdapter(adapterName)) == 0) {
fprintf(stderr, gettext(
"Failed to open adapter %s.\n"),
adapterName);
continue;
}
memset(&attrs, 0, sizeof (attrs));
status =
Sun_HBA_NPIVGetAdapterAttributes(handle,
&attrs);
while ((status == HBA_STATUS_ERROR_TRY_AGAIN ||
status == HBA_STATUS_ERROR_BUSY) &&
times++ < HBA_MAX_RETRIES) {
(void) sleep(1);
status =
Sun_HBA_NPIVGetAdapterAttributes(handle,
&attrs);
if (status == HBA_STATUS_OK) {
break;
}
}
if (status != HBA_STATUS_OK) {
fprintf(stderr,
gettext("Failed to get adapter attributes "
"handle(%d) Reason: "), handle);
printStatus(status);
fprintf(stderr, "\n");
HBA_CloseAdapter(handle);
continue;
}
for (portIndex = 0;
portIndex < attrs.NumberOfPorts;
portIndex++) {
memset(&port, 0, sizeof (port));
if ((status = HBA_GetAdapterPortAttributes(
handle, portIndex, &port))
!= HBA_STATUS_OK) {
fprintf(stderr,
gettext("Error: Failed to get port "
"(%d) attributes reason: "),
portIndex);
printStatus(status);
fprintf(stderr, "\n");
continue;
}
processHBA(handle, attrs, portIndex, port,
NULL, HBA_PORT, processHBA_flags,
INITIATOR_MODE);
if ((processHBA_flags & PRINT_FCOE) !=
PRINT_FCOE &&
attrs.VendorSpecificID != 0xFC0E &&
printHBANPIVPortInfo(handle,
portIndex) != 0) {
err_cnt++;
}
}
HBA_CloseAdapter(handle);
}
}
if ((processHBA_flags & PRINT_TARGET) == PRINT_TARGET) {
numTgtAdapters = Sun_HBA_GetNumberOfTgtAdapters();
if (numTgtAdapters == 0 && numAdapters == 0) {
fprintf(stdout,
gettext("No Adapters Found.\n"));
}
for (i = 0; i < numTgtAdapters; i++) {
status = Sun_HBA_GetTgtAdapterName(i, adapterName);
if (status != HBA_STATUS_OK) {
fprintf(stderr, gettext(
"failed to get adapter %d. Reason: "), i);
printStatus(status);
fprintf(stderr, "\n");
continue;
}
if ((handle = Sun_HBA_OpenTgtAdapter(adapterName))
== 0) {
fprintf(stderr, gettext(
"Failed to open adapter %s.\n"), adapterName);
continue;
}
memset(&attrs, 0, sizeof (attrs));
if ((status = HBA_GetAdapterAttributes(handle, &attrs))
!= HBA_STATUS_OK) {
fprintf(stderr,
gettext("Failed to get target mode adapter"
"attributes handle(%d) Reason: "),
handle);
printStatus(status);
fprintf(stderr, "\n");
continue;
}
for (portIndex = 0;
portIndex < attrs.NumberOfPorts;
portIndex++) {
memset(&port, 0, sizeof (port));
if ((status = HBA_GetAdapterPortAttributes(
handle, portIndex, &port))
!= HBA_STATUS_OK) {
fprintf(stderr,
gettext("Error: Failed to get port "
"(%d) attributes reason: "),
portIndex);
printStatus(status);
fprintf(stderr, "\n");
continue;
}
processHBA(handle, attrs, portIndex, port,
NULL, HBA_PORT, processHBA_flags,
TARGET_MODE);
}
HBA_CloseAdapter(handle);
}
}
}
HBA_FreeLibrary();
if (err_cnt != 0) {
if (wwnCount > 1) {
if (err_cnt == wwnCount) {
fprintf(stderr, gettext(
"Error: All specified HBA ports are not found\n"));
} else {
fprintf(stderr, gettext(
"Error: Some of specified HBA ports are not found\n"));
}
}
return (1);
}
return (0);
}
static void
searchDevice(discoveredDevice **devList, HBA_FCPSCSIENTRYV2 entry,
HBA_WWN initiatorPortWWN, HBA_HANDLE handle, boolean_t verbose)
{
discoveredDevice *discoveredDevList, *newDevice;
portWWNList *WWNList, *newWWN;
tgtPortWWNList *newTgtWWN;
boolean_t foundDevice = B_FALSE, foundWWN;
struct scsi_inquiry inq;
struct scsi_extended_sense sense;
HBA_UINT32 responseSize, senseSize = 0;
HBA_UINT8 inq_status;
HBA_STATUS status;
for (discoveredDevList = *devList; discoveredDevList != NULL;
discoveredDevList = discoveredDevList->next) {
if (strcmp(entry.ScsiId.OSDeviceName,
discoveredDevList->OSDeviceName) == 0) {
if (verbose == B_FALSE) {
return;
}
foundDevice = B_TRUE;
break;
}
}
if (foundDevice == B_TRUE) {
for (WWNList = discoveredDevList->HBAPortWWN,
foundWWN = B_FALSE; WWNList != NULL;
WWNList = WWNList->next) {
if (memcmp((void *)&(WWNList->portWWN),
(void *)&initiatorPortWWN,
sizeof (HBA_WWN)) == 0) {
foundWWN = B_TRUE;
break;
}
}
if (discoveredDevList->inqSuccess == B_FALSE) {
responseSize = sizeof (struct scsi_inquiry);
senseSize = sizeof (struct scsi_extended_sense);
memset(&inq, 0, sizeof (struct scsi_inquiry));
memset(&sense, 0, sizeof (sense));
status = HBA_ScsiInquiryV2(
handle,
initiatorPortWWN,
entry.FcpId.PortWWN,
entry.FcpId.FcpLun,
0,
0,
&inq, &responseSize,
&inq_status,
&sense, &senseSize);
if (status == HBA_STATUS_OK) {
memcpy(discoveredDevList->VID, inq.inq_vid,
sizeof (discoveredDevList->VID));
memcpy(discoveredDevList->PID, inq.inq_pid,
sizeof (discoveredDevList->PID));
discoveredDevList->dType = inq.inq_dtype;
discoveredDevList->inqSuccess = B_TRUE;
}
}
if (foundWWN == B_FALSE) {
newWWN = (portWWNList *)calloc(1, sizeof (portWWNList));
if (newWWN == NULL) {
perror("Out of memory");
exit(1);
}
newWWN->next = discoveredDevList->HBAPortWWN;
discoveredDevList->HBAPortWWN = newWWN;
memcpy((void *)&(newWWN->portWWN),
(void *)&initiatorPortWWN,
sizeof (newWWN->portWWN));
newWWN->tgtPortWWN = (tgtPortWWNList *)calloc(1,
sizeof (tgtPortWWNList));
if (newWWN->tgtPortWWN == NULL) {
perror("Out of memory");
exit(1);
}
memcpy((void *)&(newWWN->tgtPortWWN->portWWN),
(void *)&(entry.FcpId.PortWWN),
sizeof (newWWN->tgtPortWWN->portWWN));
newWWN->tgtPortWWN->scsiOSLun = entry.ScsiId.ScsiOSLun;
} else {
newTgtWWN = (tgtPortWWNList *)calloc(1,
sizeof (tgtPortWWNList));
if (newTgtWWN == NULL) {
perror("Out of memory");
exit(1);
}
newTgtWWN->next = WWNList->tgtPortWWN;
WWNList->tgtPortWWN = newTgtWWN;
memcpy((void *)&(newTgtWWN->portWWN),
(void *)&(entry.FcpId.PortWWN),
sizeof (newTgtWWN->portWWN));
newTgtWWN->scsiOSLun = entry.ScsiId.ScsiOSLun;
}
} else {
newDevice = (discoveredDevice *)calloc(1,
sizeof (discoveredDevice));
if (newDevice == NULL) {
perror("Out of memory");
exit(1);
}
newDevice->next = *devList;
*devList = newDevice;
strncpy(newDevice->OSDeviceName, entry.ScsiId.OSDeviceName,
sizeof (newDevice->OSDeviceName) - 1);
if (verbose == B_FALSE) {
return;
}
newDevice->HBAPortWWN = (portWWNList *)calloc(1,
sizeof (portWWNList));
if (newDevice->HBAPortWWN == NULL) {
perror("Out of memory");
exit(1);
}
memcpy((void *)&(newDevice->HBAPortWWN->portWWN),
(void *)&initiatorPortWWN, sizeof (newWWN->portWWN));
newDevice->HBAPortWWN->tgtPortWWN =
(tgtPortWWNList *)calloc(1, sizeof (tgtPortWWNList));
if (newDevice->HBAPortWWN->tgtPortWWN == NULL) {
perror("Out of memory");
exit(1);
}
memcpy((void *)&(newDevice->HBAPortWWN->tgtPortWWN->portWWN),
(void *)&(entry.FcpId.PortWWN),
sizeof (newDevice->HBAPortWWN->tgtPortWWN->portWWN));
newDevice->HBAPortWWN->tgtPortWWN->scsiOSLun =
entry.ScsiId.ScsiOSLun;
responseSize = sizeof (struct scsi_inquiry);
senseSize = sizeof (struct scsi_extended_sense);
memset(&inq, 0, sizeof (struct scsi_inquiry));
memset(&sense, 0, sizeof (sense));
status = HBA_ScsiInquiryV2(
handle,
initiatorPortWWN,
entry.FcpId.PortWWN,
entry.FcpId.FcpLun,
0,
0,
&inq, &responseSize,
&inq_status,
&sense, &senseSize);
if (status != HBA_STATUS_OK) {
strcpy(newDevice->VID, "Unknown");
strcpy(newDevice->PID, "Unknown");
newDevice->dType = DTYPE_UNKNOWN;
newDevice->inqSuccess = B_FALSE;
} else {
memcpy(newDevice->VID, inq.inq_vid,
sizeof (newDevice->VID));
memcpy(newDevice->PID, inq.inq_pid,
sizeof (newDevice->PID));
newDevice->dType = inq.inq_dtype;
newDevice->inqSuccess = B_TRUE;
}
}
}
int
fc_util_list_logicalunit(int luCount, char **luArgv, cmdOptions_t *options)
{
int pathCtr, numAdapters, i, count;
HBA_STATUS status;
char adapterName[256];
HBA_HANDLE handle;
HBA_PORTATTRIBUTES port;
HBA_ADAPTERATTRIBUTES attrs;
int portIndex = 0;
int ret = 0;
boolean_t verbose = B_FALSE;
HBA_FCPTARGETMAPPINGV2 *map = NULL;
discoveredDevice *devListWalk, *devList = NULL;
boolean_t pathFound;
for (; options->optval; options++) {
if (options->optval == 'v') {
verbose = B_TRUE;
}
}
if ((status = HBA_LoadLibrary()) != HBA_STATUS_OK) {
fprintf(stderr,
gettext("Failed to load FC-HBA common library\n"));
printStatus(status);
fprintf(stderr, "\n");
return (1);
}
numAdapters = HBA_GetNumberOfAdapters();
if (numAdapters == 0) {
return (0);
}
for (i = 0; i < numAdapters; i++) {
int times;
status = HBA_GetAdapterName(i, adapterName);
if (status != HBA_STATUS_OK) {
fprintf(stderr, gettext(
"Failed to get adapter %d. Reason: "), i);
printStatus(status);
fprintf(stderr, "\n");
ret++;
continue;
}
if ((handle = HBA_OpenAdapter(adapterName)) == 0) {
fprintf(stderr, gettext("Failed to open adapter %s\n"),
adapterName);
ret++;
continue;
}
memset(&attrs, 0, sizeof (attrs));
times = 0;
status = HBA_GetAdapterAttributes(handle, &attrs);
while ((status == HBA_STATUS_ERROR_TRY_AGAIN ||
status == HBA_STATUS_ERROR_BUSY) &&
times++ < HBA_MAX_RETRIES) {
(void) sleep(1);
status = HBA_GetAdapterAttributes(handle, &attrs);
if (status == HBA_STATUS_OK) {
break;
}
}
if (status != HBA_STATUS_OK) {
fprintf(stderr,
gettext("Failed to get adapter attributes "
"handle(%d) Reason: "), handle);
printStatus(status);
fprintf(stderr, "\n");
ret++;
HBA_CloseAdapter(handle);
continue;
}
for (portIndex = 0; portIndex < attrs.NumberOfPorts;
portIndex++) {
memset(&port, 0, sizeof (port));
if ((status = HBA_GetAdapterPortAttributes(handle,
portIndex, &port)) != HBA_STATUS_OK) {
fprintf(stderr, gettext("Failed to get port "
"(%d) attributes reason: "),
portIndex);
printStatus(status);
fprintf(stderr, "\n");
ret++;
continue;
}
getTargetMapping(handle, port.PortWWN, &map);
if (map != NULL) {
for (count = 0; count < map->NumberOfEntries;
count++) {
searchDevice(&devList,
map->entry[count], port.PortWWN,
handle, verbose);
}
}
}
HBA_CloseAdapter(handle);
}
HBA_FreeLibrary();
if (luCount == 0) {
for (devListWalk = devList; devListWalk != NULL;
devListWalk = devListWalk->next) {
printOSDeviceNameInfo(devListWalk, verbose);
}
} else {
for (pathCtr = 0; pathCtr < luCount; pathCtr++) {
for (devListWalk = devList, pathFound = B_FALSE;
devListWalk != NULL;
devListWalk = devListWalk->next) {
if (strcmp(devListWalk->OSDeviceName,
luArgv[pathCtr]) == 0) {
pathFound = B_TRUE;
}
}
if (pathFound == B_FALSE) {
fprintf(stderr, "%s: no such path\n",
luArgv[pathCtr]);
ret++;
}
}
for (pathCtr = 0; pathCtr < luCount; pathCtr++) {
for (devListWalk = devList; devListWalk != NULL;
devListWalk = devListWalk->next) {
if (strcmp(devListWalk->OSDeviceName,
luArgv[pathCtr]) == 0) {
printOSDeviceNameInfo(devListWalk,
verbose);
}
}
}
}
return (ret);
}