1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #include <ctype.h>
  27 #include <printAttrs.h>
  28 
  29 static SAS_STATE hbastatus_string[] = {
  30         HBA_STATUS_OK,                          "Okay",
  31         HBA_STATUS_ERROR,                       "Error",
  32         HBA_STATUS_ERROR_NOT_SUPPORTED,         "Not Supported",
  33         HBA_STATUS_ERROR_INVALID_HANDLE,        "Invalid Handle",
  34         HBA_STATUS_ERROR_ARG,                   "Argument Error",
  35         HBA_STATUS_ERROR_ILLEGAL_WWN,           "Illegal WWN",
  36         HBA_STATUS_ERROR_ILLEGAL_INDEX,         "Illegal Index",
  37         HBA_STATUS_ERROR_MORE_DATA,             "Not Enough Buffer for Data",
  38         HBA_STATUS_ERROR_STALE_DATA,            "Stale Data",
  39         HBA_STATUS_SCSI_CHECK_CONDITION,        "SCSI Check Condition",
  40         HBA_STATUS_ERROR_BUSY,                  "Busy",
  41         HBA_STATUS_ERROR_TRY_AGAIN,             "Try Again",
  42         HBA_STATUS_ERROR_UNAVAILABLE,           "Unavailable",
  43         HBA_STATUS_ERROR_ELS_REJECT,            "ELS Reject",
  44         HBA_STATUS_ERROR_INVALID_LUN,           "Invalid LUN",
  45         HBA_STATUS_ERROR_INCOMPATIBLE,          "Request Incompatible",
  46         HBA_STATUS_ERROR_AMBIGUOUS_WWN,         "Ambiguous WWN",
  47         HBA_STATUS_ERROR_LOCAL_BUS,             "Local Bus Error",
  48         HBA_STATUS_ERROR_LOCAL_TARGET,          "Local Target Error",
  49         HBA_STATUS_ERROR_LOCAL_LUN,             "Local LUN Error",
  50         HBA_STATUS_ERROR_LOCAL_SCSIID_BOUND,    "Local SCSIID Bound",
  51         HBA_STATUS_ERROR_TARGET_FCID,           "Target FCID Error",
  52         HBA_STATUS_ERROR_TARGET_NODE_WWN,       "Target Node WWN Error",
  53         HBA_STATUS_ERROR_TARGET_PORT_WWN,       "Target Port WWN Error",
  54         HBA_STATUS_ERROR_TARGET_LUN,            "Target LUN Error",
  55         HBA_STATUS_ERROR_TARGET_LUID,           "Target LUID Error",
  56         HBA_STATUS_ERROR_NO_SUCH_BINDING,       "No Such Binding",
  57         HBA_STATUS_ERROR_NOT_A_TARGET,          "Not a Target",
  58         HBA_STATUS_ERROR_UNSUPPORTED_FC4,       "Unsupported FC4",
  59         HBA_STATUS_ERROR_INCAPABLE,             "Incapable",
  60         HBA_STATUS_ERROR_TARGET_BUSY,           "Target Busy",
  61         HBA_STATUS_ERROR_NOT_LOADED,            "Not Loaded",
  62         HBA_STATUS_ERROR_ALREADY_LOADED,        "Alreday Loaded",
  63         HBA_STATUS_ERROR_ILLEGAL_FCID,          "Illegal FCID",
  64         HBA_STATUS_ERROR_NOT_ASCSIDEVICE,       "Not a SCSI Device",
  65         HBA_STATUS_ERROR_INVALID_PROTOCOL_TYPE, "Invalid Protocol Type",
  66         HBA_STATUS_ERROR_BAD_EVENT_TYPE,        "Bad Event Type",
  67         -1,                                     NULL
  68 };
  69 
  70 SAS_STATE porttype_string[] = {
  71         HBA_PORTTYPE_UNKNOWN,           "UNKNOWN",
  72         HBA_PORTTYPE_OTHER,             "OTHER",
  73         HBA_PORTTYPE_NOTPRESENT,        "NOT Present",
  74         HBA_PORTTYPE_SASDEVICE,         "SAS Device",
  75         HBA_PORTTYPE_SATADEVICE,        "SATA Device",
  76         HBA_PORTTYPE_SASEXPANDER,       "SAS Expander",
  77         -1,                             NULL,
  78 };
  79 
  80 SAS_STATE portstate_string[] = {
  81         HBA_PORTSTATE_UNKNOWN,          "unknown",
  82         HBA_PORTSTATE_ONLINE,           "online",
  83         HBA_PORTSTATE_OFFLINE,          "offline",
  84         HBA_PORTSTATE_BYPASSED,         "bypassed",
  85         HBA_PORTSTATE_DIAGNOSTICS,      "diagnostics",
  86         HBA_PORTSTATE_LINKDOWN,         "link Down",
  87         HBA_PORTSTATE_ERROR,            "port Error",
  88         HBA_PORTSTATE_LOOPBACK,         "loopback",
  89         HBA_PORTSTATE_DEGRADED,         "degraded",
  90         -1,                             NULL,
  91 };
  92 
  93 static SAS_STATE phystate_string[] = {
  94         HBA_SASSTATE_UNKNOWN,           "unknown",
  95         HBA_SASSTATE_DISABLED,          "disabled",
  96         HBA_SASSTATE_FAILED,            "failed",
  97         HBA_SASSTATE_SATASPINUP,        "sata-spinup",
  98         HBA_SASSTATE_SATAPORTSEL,       "sata-portselector",
  99         HBA_SASSPEED_1_5GBIT,           "1.5Gbit",
 100         HBA_SASSPEED_3GBIT,             "3Gbit",
 101         HBA_SASSPEED_6GBIT,             "6Gbit",
 102         HBA_SASSPEED_12GBIT,            "12Gbit",
 103         -1,                             NULL,
 104 };
 105 
 106 static SAS_STATE dtype_string[] = {
 107         DTYPE_DIRECT,                   "Disk Device",
 108         DTYPE_SEQUENTIAL,               "Tape Device",
 109         DTYPE_PRINTER,                  "Printer Device",
 110         DTYPE_PROCESSOR,                "Processor Device",
 111         DTYPE_WORM,                     "WORM Device",
 112         DTYPE_RODIRECT,                 "CD/DVD Device",
 113         DTYPE_SCANNER,                  "Scanner Device",
 114         DTYPE_OPTICAL,                  "Optical Memory Device",
 115         DTYPE_CHANGER,                  "Medium Changer Device",
 116         DTYPE_COMM,                     "Communications Device",
 117         DTYPE_ARRAY_CTRL,               "Storage Array Controller Device",
 118         DTYPE_ESI,                      "Enclosure Services Device",
 119         DTYPE_RBC,                      "Simplified Direct-access Device",
 120         DTYPE_OCRW,                     "Optical Card Reader/Writer Device",
 121         DTYPE_BCC,                      "Bridge Controller Commands",
 122         DTYPE_OSD,                      "Object-based Storage Device",
 123         DTYPE_ADC,                      "Automation/Drive Interface",
 124         DTYPE_WELLKNOWN,                "Well Known Logical Unit",
 125         DTYPE_UNKNOWN,                  "Unknown Device",
 126         -1,                             NULL
 127 };
 128 
 129 static char *getPhyStateString(HBA_UINT32 key, phystat_type phyt);
 130 
 131 char *
 132 getIndentSpaces(int number)
 133 {
 134         int             i = 0;
 135         /* the maximum indent with terminator '\0' */
 136         static char     ret[MAXINDENT+1];
 137 
 138         if (number > MAXINDENT)
 139                 number = MAXINDENT;
 140 
 141         for (i = 0; i < number; i++) {
 142                 ret[i] = ' ';
 143         }
 144         ret[i] = '\0';
 145         return (ret);
 146 }
 147 
 148 char *
 149 getStateString(HBA_UINT32 key, SAS_STATE *stat_string)
 150 {
 151         static char ret[64];
 152         while (stat_string->key != -1) {
 153                 if (stat_string->key == key) {
 154                         return ((char *)stat_string->value);
 155                 }
 156                 stat_string++;
 157         }
 158         (void *) sprintf(ret, "Undefined value (%d)", key);
 159         return (ret);
 160 }
 161 
 162 static char *
 163 getPhyStateString(HBA_UINT32 key, phystat_type phyt)
 164 {
 165         int i = 0, len = 0, match = 0;
 166         HBA_UINT32 physpeed[] = {
 167                 HBA_SASSPEED_1_5GBIT,
 168                 HBA_SASSPEED_3GBIT,
 169                 HBA_SASSPEED_6GBIT,
 170                 HBA_SASSPEED_12GBIT
 171         };
 172 
 173         len = sizeof (physpeed) / sizeof (HBA_UINT32);
 174         for (i = 0; i < len; i++) {
 175                 if (key == physpeed[i]) {
 176                         match = 1;
 177                         break;
 178                 }
 179         }
 180 
 181         if (match == 1) {
 182                 if (phyt == PHY_STATE)
 183                         return ("enabled");
 184                 else
 185                         return (getStateString(key, phystate_string));
 186         } else {
 187                 if (phyt == PHY_STATE)
 188                         return (getStateString(key, phystate_string));
 189                 else
 190                         return ("not available");
 191         }
 192 }
 193 
 194 char *
 195 getHBAStatus(HBA_STATUS key)
 196 {
 197         return (getStateString(key, hbastatus_string));
 198 }
 199 
 200 /*
 201  * return device type description
 202  *
 203  * Arguments:
 204  *      dType - Device type returned from Standard INQUIRY
 205  * Returns:
 206  *      char string description for device type
 207  */
 208 char *
 209 getDTypeString(uchar_t dType)
 210 {
 211         return (getStateString((dType & DTYPE_MASK), dtype_string));
 212 }
 213 
 214 uint64_t
 215 wwnConversion(uchar_t *wwn)
 216 {
 217         uint64_t tmp;
 218         (void *) memcpy(&tmp, wwn, sizeof (uint64_t));
 219         return (ntohll(tmp));
 220 }
 221 
 222 /*
 223  * prints out HBA information
 224  */
 225 void
 226 printHBAInfo(SMHBA_ADAPTERATTRIBUTES *attrs, int pflag, int numberOfPorts,
 227     const char *adapterName)
 228 {
 229 
 230         (void *) fprintf(stdout, "%s %s\n", "HBA Name:", adapterName);
 231 
 232         if (pflag & PRINT_VERBOSE) {
 233                 (void *) fprintf(stdout, "%s%s %s\n",
 234                     getIndentSpaces(4), "Manufacturer:",
 235                     attrs->Manufacturer[0] == 0?
 236                     "not available":attrs->Manufacturer);
 237                 (void *) fprintf(stdout, "%s%s %s\n",
 238                     getIndentSpaces(4), "Model: ",
 239                     attrs->Model[0] == 0? "not available":attrs->Model);
 240                 (void *) fprintf(stdout, "%s%s %s\n",
 241                     getIndentSpaces(4),
 242                     "Firmware Version:",
 243                     attrs->FirmwareVersion[0] == 0? "not available":
 244                     attrs->FirmwareVersion);
 245                 (void *) fprintf(stdout, "%s%s %s\n",
 246                     getIndentSpaces(4),
 247                     "FCode/BIOS Version:",
 248                     attrs->OptionROMVersion[0] == 0? "not available":
 249                     attrs->OptionROMVersion);
 250                 (void *) fprintf(stdout, "%s%s %s\n",
 251                     getIndentSpaces(4),
 252                     "Serial Number:",
 253                     attrs->SerialNumber[0] == 0? "not available":
 254                     attrs->SerialNumber);
 255                 (void *) fprintf(stdout, "%s%s %s\n",
 256                     getIndentSpaces(4),
 257                     "Driver Name:",
 258                     attrs->DriverName[0] == 0? "not available":
 259                     attrs->DriverName);
 260                 (void *) fprintf(stdout, "%s%s %s\n",
 261                     getIndentSpaces(4),
 262                     "Driver Version:",
 263                     attrs->DriverVersion[0] == 0? "not available":
 264                     attrs->DriverVersion);
 265                 (void *) fprintf(stdout, "%s%s %d\n",
 266                     getIndentSpaces(4),
 267                     "Number of HBA Ports:",
 268                     numberOfPorts);
 269         }
 270 }
 271 
 272 /*
 273  * prints out all the HBA port information
 274  */
 275 void
 276 printHBAPortInfo(SMHBA_PORTATTRIBUTES *port,
 277     SMHBA_ADAPTERATTRIBUTES *attrs, int pflag) {
 278 
 279         if ((port == NULL) || (attrs == NULL)) {
 280                 return;
 281         }
 282 
 283         (void *) fprintf(stdout, "%s%s %s\n",
 284             getIndentSpaces(2),
 285             "HBA Port Name:",
 286             port->OSDeviceName);
 287 
 288         if (!(pflag & PRINT_VERBOSE)) {
 289                 return;
 290         }
 291 
 292         if (port->PortType != HBA_PORTTYPE_SASDEVICE)
 293                 return;
 294 
 295         (void *) fprintf(stdout, "%s%s %s\n",
 296             getIndentSpaces(4),
 297             "Type:",
 298             getStateString(port->PortType, porttype_string));
 299         (void *) fprintf(stdout, "%s%s %s\n",
 300             getIndentSpaces(4),
 301             "State:",
 302             getStateString(port->PortState, portstate_string));
 303 
 304         (void *) fprintf(stdout, "%s%s %016llx\n",
 305             getIndentSpaces(4),
 306             "Local SAS Address:",
 307             wwnConversion(port->PortSpecificAttribute.SASPort->\
 308             LocalSASAddress.wwn));
 309 
 310         (void *) fprintf(stdout, "%s%s %016llx\n",
 311             getIndentSpaces(4),
 312             "Attached SAS Address:",
 313             wwnConversion(port->PortSpecificAttribute.SASPort->\
 314             AttachedSASAddress.wwn));
 315 
 316         (void *) fprintf(stdout, "%s%s %d\n",
 317             getIndentSpaces(4),
 318             "Number of Phys:",
 319             port->PortSpecificAttribute.SASPort->NumberofPhys);
 320 }
 321 
 322 void
 323 printHBAPortPhyInfo(SMHBA_SAS_PHY *phyinfo)
 324 {
 325         if (phyinfo == NULL)
 326                 return;
 327 
 328         (void *) fprintf(stdout, "%s%s %u\n",
 329             getIndentSpaces(6),
 330             "Identifier:",
 331             phyinfo->PhyIdentifier);
 332 
 333         (void *) fprintf(stdout, "%s%s %s\n",
 334             getIndentSpaces(8),
 335             "State: ",
 336             getPhyStateString(phyinfo->NegotiatedLinkRate, PHY_STATE));
 337         (void *) fprintf(stdout, "%s%s %s/%s\n",
 338             getIndentSpaces(8),
 339             "HardwareLinkRate(Min/Max):",
 340             getPhyStateString(phyinfo->HardwareMinLinkRate, PHY_SPEED),
 341             getPhyStateString(phyinfo->HardwareMaxLinkRate, PHY_SPEED));
 342         (void *) fprintf(stdout, "%s%s %s/%s\n",
 343             getIndentSpaces(8),
 344             "ProgrammedLinkRate(Min/Max):",
 345             getPhyStateString(phyinfo->ProgrammedMinLinkRate, PHY_SPEED),
 346             getPhyStateString(phyinfo->ProgrammedMaxLinkRate, PHY_SPEED));
 347         (void *) fprintf(stdout, "%s%s %s\n",
 348             getIndentSpaces(8),
 349             "NegotiatedLinkRate:",
 350             getPhyStateString(phyinfo->NegotiatedLinkRate, PHY_SPEED));
 351 }
 352 
 353 void
 354 printHBAPortPhyStatistics(SMHBA_SASPHYSTATISTICS *phystat)
 355 {
 356         if (phystat == NULL)
 357                 return;
 358 
 359         (void *) fprintf(stdout, "%s%s\n",
 360             getIndentSpaces(8),
 361             "Link Error Statistics:");
 362         (void *) fprintf(stdout, "%s%s %llu\n",
 363             getIndentSpaces(12),
 364             "Invalid Dword:",
 365             phystat->InvalidDwordCount);
 366         (void *) fprintf(stdout, "%s%s %llu\n",
 367             getIndentSpaces(12),
 368             "Running Disparity Error:",
 369             phystat->RunningDisparityErrorCount);
 370         (void *) fprintf(stdout, "%s%s %llu\n",
 371             getIndentSpaces(12),
 372             "Loss of Dword Sync:",
 373             phystat->LossofDwordSyncCount);
 374         (void *) fprintf(stdout, "%s%s %llu\n",
 375             getIndentSpaces(12),
 376             "Reset Problem:",
 377             phystat->PhyResetProblemCount);
 378 }
 379 
 380 /*
 381  * print the OS device name for the logical-unit object
 382  *
 383  * Arguments:
 384  *      devListWalk - OS device path info
 385  *      verbose - boolean indicating whether to display additional info
 386  *
 387  * returns:
 388  *      0 - we're good.
 389  *      >0 - we met issues.
 390  */
 391 int
 392 printTargetPortInfo(targetPortList_t *TPListWalk, int pflag)
 393 {
 394         targetPortConfig_t      *configList;
 395         targetPortMappingData_t *mapList;
 396         int                     count, i;
 397         int                     ret = 0;
 398 
 399         (void *) fprintf(stdout, "Target Port SAS Address: %016llx\n",
 400             wwnConversion(TPListWalk->sasattr.LocalSASAddress.wwn));
 401         if ((pflag & PRINT_VERBOSE) || (pflag & PRINT_TARGET_SCSI)) {
 402                 (void *) fprintf(stdout, "%sType: %s\n", getIndentSpaces(4),
 403                     getStateString(TPListWalk->targetattr.PortType,
 404                     porttype_string));
 405                 for (configList = TPListWalk->configEntry;
 406                     configList != NULL; configList = configList->next) {
 407                         (void *) fprintf(stdout, "%sHBA Port Name: %s\n",
 408                             getIndentSpaces(4), configList->hbaPortName);
 409                         if (wwnConversion(configList->expanderSASAddr.wwn) !=
 410                             0) {
 411                                 if (configList->expanderValid) {
 412                                         (void *) fprintf(stdout,
 413                                             "%sExpander Device SAS Address:"
 414                                             " %016llx",
 415                                             getIndentSpaces(8),
 416                                             wwnConversion(configList->
 417                                             expanderSASAddr.wwn));
 418                                 } else {
 419                                         (void *) fprintf(stdout,
 420                                             "%sExpander Device SAS Address:"
 421                                             " %016llx (Failed to Validate"
 422                                             " Attached Port.)",
 423                                             getIndentSpaces(8),
 424                                             wwnConversion(configList->
 425                                             expanderSASAddr.wwn));
 426                                         ret++;
 427                                 }
 428                         } else {
 429                                 if (configList->expanderValid) {
 430                                         (void *) fprintf(stdout,
 431                                             "%sExpander Device SAS Address: %s",
 432                                             getIndentSpaces(8),
 433                                             "None (direct attached)");
 434                                 } else {
 435                                         (void *) fprintf(stdout,
 436                                             "%sExpander Device SAS Address: %s",
 437                                             getIndentSpaces(8),
 438                                             "None (Failed to Get"
 439                                             " Attached Port)");
 440                                 }
 441                         }
 442                         (void *) fprintf(stdout, "\n");
 443                         if (pflag & PRINT_TARGET_SCSI) {
 444 
 445                                 if (configList->reportLUNsFailed) {
 446                                         (void *) fprintf(stdout,
 447                                             "%s %016llx\n",
 448                                             gettext("Error: Failed to get "
 449                                             "ReportLun Data on"),
 450                                             wwnConversion(TPListWalk->
 451                                             sasattr.LocalSASAddress.wwn));
 452                                         ret++;
 453                                         continue;
 454                                 }
 455 
 456                                 for (mapList = configList->map;
 457                                     mapList != NULL; mapList = mapList->next) {
 458                                         (void *) fprintf(stdout, "%sLUN : %d\n",
 459                                             getIndentSpaces(12),
 460                                             mapList->osLUN);
 461                                         if (mapList->mappingExist) {
 462                                                 (void *) fprintf(stdout,
 463                                                     "%sOS Device Name : %s\n",
 464                                                     getIndentSpaces(14),
 465                                                     (mapList->osDeviceName[0] ==
 466                                                     '\0') ?  "Not avaialble" :
 467                                                     mapList->osDeviceName);
 468                                         } else {
 469                                                 (void *) fprintf(stdout,
 470                                                     "%sOS Device Name : %s\n",
 471                                                     getIndentSpaces(14), "No "
 472                                                     "matching OS Device "
 473                                                     "found.");
 474                                                 ret++;
 475                                         }
 476                 /* indentation changed here */
 477                 if (mapList->inquiryFailed) {
 478                         (void *) fprintf(stdout, "%s %s LUN %d\n",
 479                             gettext("Error: Failed to get Inquiry Data on"),
 480                             mapList->osDeviceName, mapList->osLUN);
 481                         ret++;
 482                 } else {
 483                         (void *) fprintf(stdout, "%sVendor: ",
 484                             getIndentSpaces(14));
 485                         for (count = sizeof (mapList->inq_vid), i = 0;
 486                             i < count; i++) {
 487                                 if (isprint(mapList->inq_vid[i]))
 488                                         (void *) fprintf(stdout, "%c",
 489                                             mapList->inq_vid[i]);
 490                         }
 491 
 492                         (void *) fprintf(stdout, "\n%sProduct: ",
 493                             getIndentSpaces(14));
 494                         for (count = sizeof (mapList->inq_pid), i = 0;
 495                             i < count; i++) {
 496                                 if (isprint(mapList->inq_pid[i]))
 497                                         (void *) fprintf(stdout, "%c",
 498                                             mapList->inq_pid[i]);
 499                         }
 500 
 501                         (void *) fprintf(stdout, "\n%sDevice Type: %s\n",
 502                             getIndentSpaces(14),
 503                             getDTypeString(mapList->inq_dtype));
 504                 }
 505                 /* indentation changed back */
 506                                 }
 507                         }
 508                 }
 509         }
 510         return (ret);
 511 }
 512 
 513 /*
 514  * print the OS device name for the logical-unit object
 515  *
 516  * Arguments:
 517  *      devListWalk - OS device path info
 518  *      verbose - boolean indicating whether to display additional info
 519  *
 520  * returns:
 521  *      0 - we're good.
 522  *      >0 - we met issues.
 523  */
 524 int
 525 printOSDeviceNameInfo(discoveredDevice *devListWalk, boolean_t verbose)
 526 {
 527         portList                *portElem;
 528         tgtPortWWNList          *tgtWWNList;
 529         int                     i, count;
 530         int                     ret = 0;
 531 
 532         (void *) fprintf(stdout, "OS Device Name: %s\n",
 533             devListWalk->OSDeviceName);
 534         if (verbose == B_TRUE) {
 535                 for (portElem = devListWalk->HBAPortList;
 536                     portElem != NULL; portElem = portElem->next) {
 537                         (void *) fprintf(stdout, "%sHBA Port Name: ",
 538                             getIndentSpaces(4));
 539                         (void *) fprintf(stdout, "%s", portElem->portName);
 540                         for (tgtWWNList = portElem->tgtPortWWN;
 541                             tgtWWNList != NULL; tgtWWNList = tgtWWNList->next) {
 542                                 (void *) fprintf(stdout,
 543                                     "\n%sTarget Port SAS Address: ",
 544                                     getIndentSpaces(8));
 545                                 (void *) fprintf(stdout, "%016llx",
 546                                     wwnConversion(tgtWWNList->portWWN.wwn));
 547                                 (void *) fprintf(stdout, "\n%sLUN: %u",
 548                                     getIndentSpaces(12),
 549                                     tgtWWNList->scsiOSLun);
 550                         }
 551                         (void *) fprintf(stdout, "\n");
 552                 }
 553 
 554                 if (devListWalk->inquiryFailed) {
 555                         (void *) fprintf(stdout, "%s %s\n",
 556                             gettext("Error: Failed to get Inquiry data "
 557                             "on device"), devListWalk->OSDeviceName);
 558                         ret++;
 559                 } else {
 560                         (void *) fprintf(stdout, "%sVendor: ",
 561                             getIndentSpaces(4));
 562                         for (count = sizeof (devListWalk->VID), i = 0;
 563                             i < count; i++) {
 564                                 if (isprint(devListWalk->VID[i]))
 565                                         (void *) fprintf(stdout, "%c",
 566                                             devListWalk->VID[i]);
 567                         }
 568 
 569                         (void *) fprintf(stdout, "\n%sProduct: ",
 570                             getIndentSpaces(4));
 571                         for (count = sizeof (devListWalk->PID), i = 0;
 572                             i < count; i++) {
 573                                 if (isprint(devListWalk->PID[i]))
 574                                         (void *) fprintf(stdout, "%c",
 575                                             devListWalk->PID[i]);
 576                         }
 577 
 578                         (void *) fprintf(stdout, "\n%sDevice Type: %s\n",
 579                             getIndentSpaces(4),
 580                             getDTypeString(devListWalk->dType));
 581                 }
 582         }
 583         return (ret);
 584 }