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         -1,                             NULL,
 103 };
 104 
 105 static SAS_STATE dtype_string[] = {
 106         DTYPE_DIRECT,                   "Disk Device",
 107         DTYPE_SEQUENTIAL,               "Tape Device",
 108         DTYPE_PRINTER,                  "Printer Device",
 109         DTYPE_PROCESSOR,                "Processor Device",
 110         DTYPE_WORM,                     "WORM Device",
 111         DTYPE_RODIRECT,                 "CD/DVD Device",
 112         DTYPE_SCANNER,                  "Scanner Device",
 113         DTYPE_OPTICAL,                  "Optical Memory Device",
 114         DTYPE_CHANGER,                  "Medium Changer Device",
 115         DTYPE_COMM,                     "Communications Device",
 116         DTYPE_ARRAY_CTRL,               "Storage Array Controller Device",
 117         DTYPE_ESI,                      "Enclosure Services Device",
 118         DTYPE_RBC,                      "Simplified Direct-access Device",
 119         DTYPE_OCRW,                     "Optical Card Reader/Writer Device",
 120         DTYPE_BCC,                      "Bridge Controller Commands",
 121         DTYPE_OSD,                      "Object-based Storage Device",
 122         DTYPE_ADC,                      "Automation/Drive Interface",
 123         DTYPE_WELLKNOWN,                "Well Known Logical Unit",
 124         DTYPE_UNKNOWN,                  "Unknown Device",
 125         -1,                             NULL
 126 };
 127 
 128 static char *getPhyStateString(HBA_UINT32 key, phystat_type phyt);
 129 
 130 char *
 131 getIndentSpaces(int number)
 132 {
 133         int             i = 0;
 134         /* the maximum indent with terminator '\0' */
 135         static char     ret[MAXINDENT+1];
 136 
 137         if (number > MAXINDENT)
 138                 number = MAXINDENT;
 139 
 140         for (i = 0; i < number; i++) {
 141                 ret[i] = ' ';
 142         }
 143         ret[i] = '\0';
 144         return (ret);
 145 }
 146 
 147 char *
 148 getStateString(HBA_UINT32 key, SAS_STATE *stat_string)
 149 {
 150         static char ret[64];
 151         while (stat_string->key != -1) {
 152                 if (stat_string->key == key) {
 153                         return ((char *)stat_string->value);
 154                 }
 155                 stat_string++;
 156         }
 157         (void *) sprintf(ret, "Undefined value (%d)", key);
 158         return (ret);
 159 }
 160 
 161 static char *
 162 getPhyStateString(HBA_UINT32 key, phystat_type phyt)
 163 {
 164         int i = 0, len = 0, match = 0;
 165         HBA_UINT32 physpeed[] = {
 166                 HBA_SASSPEED_1_5GBIT,
 167                 HBA_SASSPEED_3GBIT,
 168                 HBA_SASSPEED_6GBIT
 169         };
 170 
 171         len = sizeof (physpeed) / sizeof (HBA_UINT32);
 172         for (i = 0; i < len; i++) {
 173                 if (key == physpeed[i]) {
 174                         match = 1;
 175                         break;
 176                 }
 177         }
 178 
 179         if (match == 1) {
 180                 if (phyt == PHY_STATE)
 181                         return ("enabled");
 182                 else
 183                         return (getStateString(key, phystate_string));
 184         } else {
 185                 if (phyt == PHY_STATE)
 186                         return (getStateString(key, phystate_string));
 187                 else
 188                         return ("not available");
 189         }
 190 }
 191 
 192 char *
 193 getHBAStatus(HBA_STATUS key)
 194 {
 195         return (getStateString(key, hbastatus_string));
 196 }
 197 
 198 /*
 199  * return device type description
 200  *
 201  * Arguments:
 202  *      dType - Device type returned from Standard INQUIRY
 203  * Returns:
 204  *      char string description for device type
 205  */
 206 char *
 207 getDTypeString(uchar_t dType)
 208 {
 209         return (getStateString((dType & DTYPE_MASK), dtype_string));
 210 }
 211 
 212 uint64_t
 213 wwnConversion(uchar_t *wwn)
 214 {
 215         uint64_t tmp;
 216         (void *) memcpy(&tmp, wwn, sizeof (uint64_t));
 217         return (ntohll(tmp));
 218 }
 219 
 220 /*
 221  * prints out HBA information
 222  */
 223 void
 224 printHBAInfo(SMHBA_ADAPTERATTRIBUTES *attrs, int pflag, int numberOfPorts,
 225     const char *adapterName)
 226 {
 227 
 228         (void *) fprintf(stdout, "%s %s\n", "HBA Name:", adapterName);
 229 
 230         if (pflag & PRINT_VERBOSE) {
 231                 (void *) fprintf(stdout, "%s%s %s\n",
 232                     getIndentSpaces(4), "Manufacturer:",
 233                     attrs->Manufacturer[0] == 0?
 234                     "not available":attrs->Manufacturer);
 235                 (void *) fprintf(stdout, "%s%s %s\n",
 236                     getIndentSpaces(4), "Model: ",
 237                     attrs->Model[0] == 0? "not available":attrs->Model);
 238                 (void *) fprintf(stdout, "%s%s %s\n",
 239                     getIndentSpaces(4),
 240                     "Firmware Version:",
 241                     attrs->FirmwareVersion[0] == 0? "not available":
 242                     attrs->FirmwareVersion);
 243                 (void *) fprintf(stdout, "%s%s %s\n",
 244                     getIndentSpaces(4),
 245                     "FCode/BIOS Version:",
 246                     attrs->OptionROMVersion[0] == 0? "not available":
 247                     attrs->OptionROMVersion);
 248                 (void *) fprintf(stdout, "%s%s %s\n",
 249                     getIndentSpaces(4),
 250                     "Serial Number:",
 251                     attrs->SerialNumber[0] == 0? "not available":
 252                     attrs->SerialNumber);
 253                 (void *) fprintf(stdout, "%s%s %s\n",
 254                     getIndentSpaces(4),
 255                     "Driver Name:",
 256                     attrs->DriverName[0] == 0? "not available":
 257                     attrs->DriverName);
 258                 (void *) fprintf(stdout, "%s%s %s\n",
 259                     getIndentSpaces(4),
 260                     "Driver Version:",
 261                     attrs->DriverVersion[0] == 0? "not available":
 262                     attrs->DriverVersion);
 263                 (void *) fprintf(stdout, "%s%s %d\n",
 264                     getIndentSpaces(4),
 265                     "Number of HBA Ports:",
 266                     numberOfPorts);
 267         }
 268 }
 269 
 270 /*
 271  * prints out all the HBA port information
 272  */
 273 void
 274 printHBAPortInfo(SMHBA_PORTATTRIBUTES *port,
 275     SMHBA_ADAPTERATTRIBUTES *attrs, int pflag) {
 276 
 277         if ((port == NULL) || (attrs == NULL)) {
 278                 return;
 279         }
 280 
 281         (void *) fprintf(stdout, "%s%s %s\n",
 282             getIndentSpaces(2),
 283             "HBA Port Name:",
 284             port->OSDeviceName);
 285 
 286         if (!(pflag & PRINT_VERBOSE)) {
 287                 return;
 288         }
 289 
 290         if (port->PortType != HBA_PORTTYPE_SASDEVICE)
 291                 return;
 292 
 293         (void *) fprintf(stdout, "%s%s %s\n",
 294             getIndentSpaces(4),
 295             "Type:",
 296             getStateString(port->PortType, porttype_string));
 297         (void *) fprintf(stdout, "%s%s %s\n",
 298             getIndentSpaces(4),
 299             "State:",
 300             getStateString(port->PortState, portstate_string));
 301 
 302         (void *) fprintf(stdout, "%s%s %016llx\n",
 303             getIndentSpaces(4),
 304             "Local SAS Address:",
 305             wwnConversion(port->PortSpecificAttribute.SASPort->\
 306             LocalSASAddress.wwn));
 307 
 308         (void *) fprintf(stdout, "%s%s %016llx\n",
 309             getIndentSpaces(4),
 310             "Attached SAS Address:",
 311             wwnConversion(port->PortSpecificAttribute.SASPort->\
 312             AttachedSASAddress.wwn));
 313 
 314         (void *) fprintf(stdout, "%s%s %d\n",
 315             getIndentSpaces(4),
 316             "Number of Phys:",
 317             port->PortSpecificAttribute.SASPort->NumberofPhys);
 318 }
 319 
 320 void
 321 printHBAPortPhyInfo(SMHBA_SAS_PHY *phyinfo)
 322 {
 323         if (phyinfo == NULL)
 324                 return;
 325 
 326         (void *) fprintf(stdout, "%s%s %u\n",
 327             getIndentSpaces(6),
 328             "Identifier:",
 329             phyinfo->PhyIdentifier);
 330 
 331         (void *) fprintf(stdout, "%s%s %s\n",
 332             getIndentSpaces(8),
 333             "State: ",
 334             getPhyStateString(phyinfo->NegotiatedLinkRate, PHY_STATE));
 335         (void *) fprintf(stdout, "%s%s %s/%s\n",
 336             getIndentSpaces(8),
 337             "HardwareLinkRate(Min/Max):",
 338             getPhyStateString(phyinfo->HardwareMinLinkRate, PHY_SPEED),
 339             getPhyStateString(phyinfo->HardwareMaxLinkRate, PHY_SPEED));
 340         (void *) fprintf(stdout, "%s%s %s/%s\n",
 341             getIndentSpaces(8),
 342             "ProgrammedLinkRate(Min/Max):",
 343             getPhyStateString(phyinfo->ProgrammedMinLinkRate, PHY_SPEED),
 344             getPhyStateString(phyinfo->ProgrammedMaxLinkRate, PHY_SPEED));
 345         (void *) fprintf(stdout, "%s%s %s\n",
 346             getIndentSpaces(8),
 347             "NegotiatedLinkRate:",
 348             getPhyStateString(phyinfo->NegotiatedLinkRate, PHY_SPEED));
 349 }
 350 
 351 void
 352 printHBAPortPhyStatistics(SMHBA_SASPHYSTATISTICS *phystat)
 353 {
 354         if (phystat == NULL)
 355                 return;
 356 
 357         (void *) fprintf(stdout, "%s%s\n",
 358             getIndentSpaces(8),
 359             "Link Error Statistics:");
 360         (void *) fprintf(stdout, "%s%s %llu\n",
 361             getIndentSpaces(12),
 362             "Invalid Dword:",
 363             phystat->InvalidDwordCount);
 364         (void *) fprintf(stdout, "%s%s %llu\n",
 365             getIndentSpaces(12),
 366             "Running Disparity Error:",
 367             phystat->RunningDisparityErrorCount);
 368         (void *) fprintf(stdout, "%s%s %llu\n",
 369             getIndentSpaces(12),
 370             "Loss of Dword Sync:",
 371             phystat->LossofDwordSyncCount);
 372         (void *) fprintf(stdout, "%s%s %llu\n",
 373             getIndentSpaces(12),
 374             "Reset Problem:",
 375             phystat->PhyResetProblemCount);
 376 }
 377 
 378 /*
 379  * print the OS device name for the logical-unit object
 380  *
 381  * Arguments:
 382  *      devListWalk - OS device path info
 383  *      verbose - boolean indicating whether to display additional info
 384  *
 385  * returns:
 386  *      0 - we're good.
 387  *      >0 - we met issues.
 388  */
 389 int
 390 printTargetPortInfo(targetPortList_t *TPListWalk, int pflag)
 391 {
 392         targetPortConfig_t      *configList;
 393         targetPortMappingData_t *mapList;
 394         int                     count, i;
 395         int                     ret = 0;
 396 
 397         (void *) fprintf(stdout, "Target Port SAS Address: %016llx\n",
 398             wwnConversion(TPListWalk->sasattr.LocalSASAddress.wwn));
 399         if ((pflag & PRINT_VERBOSE) || (pflag & PRINT_TARGET_SCSI)) {
 400                 (void *) fprintf(stdout, "%sType: %s\n", getIndentSpaces(4),
 401                     getStateString(TPListWalk->targetattr.PortType,
 402                     porttype_string));
 403                 for (configList = TPListWalk->configEntry;
 404                     configList != NULL; configList = configList->next) {
 405                         (void *) fprintf(stdout, "%sHBA Port Name: %s\n",
 406                             getIndentSpaces(4), configList->hbaPortName);
 407                         if (wwnConversion(configList->expanderSASAddr.wwn) !=
 408                             0) {
 409                                 if (configList->expanderValid) {
 410                                         (void *) fprintf(stdout,
 411                                             "%sExpander Device SAS Address:"
 412                                             " %016llx",
 413                                             getIndentSpaces(8),
 414                                             wwnConversion(configList->
 415                                             expanderSASAddr.wwn));
 416                                 } else {
 417                                         (void *) fprintf(stdout,
 418                                             "%sExpander Device SAS Address:"
 419                                             " %016llx (Failed to Validate"
 420                                             " Attached Port.)",
 421                                             getIndentSpaces(8),
 422                                             wwnConversion(configList->
 423                                             expanderSASAddr.wwn));
 424                                         ret++;
 425                                 }
 426                         } else {
 427                                 if (configList->expanderValid) {
 428                                         (void *) fprintf(stdout,
 429                                             "%sExpander Device SAS Address: %s",
 430                                             getIndentSpaces(8),
 431                                             "None (direct attached)");
 432                                 } else {
 433                                         (void *) fprintf(stdout,
 434                                             "%sExpander Device SAS Address: %s",
 435                                             getIndentSpaces(8),
 436                                             "None (Failed to Get"
 437                                             " Attached Port)");
 438                                 }
 439                         }
 440                         (void *) fprintf(stdout, "\n");
 441                         if (pflag & PRINT_TARGET_SCSI) {
 442 
 443                                 if (configList->reportLUNsFailed) {
 444                                         (void *) fprintf(stdout,
 445                                             "%s %016llx\n",
 446                                             gettext("Error: Failed to get "
 447                                             "ReportLun Data on"),
 448                                             wwnConversion(TPListWalk->
 449                                             sasattr.LocalSASAddress.wwn));
 450                                         ret++;
 451                                         continue;
 452                                 }
 453 
 454                                 for (mapList = configList->map;
 455                                     mapList != NULL; mapList = mapList->next) {
 456                                         (void *) fprintf(stdout, "%sLUN : %d\n",
 457                                             getIndentSpaces(12),
 458                                             mapList->osLUN);
 459                                         if (mapList->mappingExist) {
 460                                                 (void *) fprintf(stdout,
 461                                                     "%sOS Device Name : %s\n",
 462                                                     getIndentSpaces(14),
 463                                                     (mapList->osDeviceName[0] ==
 464                                                     '\0') ?  "Not avaialble" :
 465                                                     mapList->osDeviceName);
 466                                         } else {
 467                                                 (void *) fprintf(stdout,
 468                                                     "%sOS Device Name : %s\n",
 469                                                     getIndentSpaces(14), "No "
 470                                                     "matching OS Device "
 471                                                     "found.");
 472                                                 ret++;
 473                                         }
 474                 /* indentation changed here */
 475                 if (mapList->inquiryFailed) {
 476                         (void *) fprintf(stdout, "%s %s LUN %d\n",
 477                             gettext("Error: Failed to get Inquiry Data on"),
 478                             mapList->osDeviceName, mapList->osLUN);
 479                         ret++;
 480                 } else {
 481                         (void *) fprintf(stdout, "%sVendor: ",
 482                             getIndentSpaces(14));
 483                         for (count = sizeof (mapList->inq_vid), i = 0;
 484                             i < count; i++) {
 485                                 if (isprint(mapList->inq_vid[i]))
 486                                         (void *) fprintf(stdout, "%c",
 487                                             mapList->inq_vid[i]);
 488                         }
 489 
 490                         (void *) fprintf(stdout, "\n%sProduct: ",
 491                             getIndentSpaces(14));
 492                         for (count = sizeof (mapList->inq_pid), i = 0;
 493                             i < count; i++) {
 494                                 if (isprint(mapList->inq_pid[i]))
 495                                         (void *) fprintf(stdout, "%c",
 496                                             mapList->inq_pid[i]);
 497                         }
 498 
 499                         (void *) fprintf(stdout, "\n%sDevice Type: %s\n",
 500                             getIndentSpaces(14),
 501                             getDTypeString(mapList->inq_dtype));
 502                 }
 503                 /* indentation changed back */
 504                                 }
 505                         }
 506                 }
 507         }
 508         return (ret);
 509 }
 510 
 511 /*
 512  * print the OS device name for the logical-unit object
 513  *
 514  * Arguments:
 515  *      devListWalk - OS device path info
 516  *      verbose - boolean indicating whether to display additional info
 517  *
 518  * returns:
 519  *      0 - we're good.
 520  *      >0 - we met issues.
 521  */
 522 int
 523 printOSDeviceNameInfo(discoveredDevice *devListWalk, boolean_t verbose)
 524 {
 525         portList                *portElem;
 526         tgtPortWWNList          *tgtWWNList;
 527         int                     i, count;
 528         int                     ret = 0;
 529 
 530         (void *) fprintf(stdout, "OS Device Name: %s\n",
 531             devListWalk->OSDeviceName);
 532         if (verbose == B_TRUE) {
 533                 for (portElem = devListWalk->HBAPortList;
 534                     portElem != NULL; portElem = portElem->next) {
 535                         (void *) fprintf(stdout, "%sHBA Port Name: ",
 536                             getIndentSpaces(4));
 537                         (void *) fprintf(stdout, "%s", portElem->portName);
 538                         for (tgtWWNList = portElem->tgtPortWWN;
 539                             tgtWWNList != NULL; tgtWWNList = tgtWWNList->next) {
 540                                 (void *) fprintf(stdout,
 541                                     "\n%sTarget Port SAS Address: ",
 542                                     getIndentSpaces(8));
 543                                 (void *) fprintf(stdout, "%016llx",
 544                                     wwnConversion(tgtWWNList->portWWN.wwn));
 545                                 (void *) fprintf(stdout, "\n%sLUN: %u",
 546                                     getIndentSpaces(12),
 547                                     tgtWWNList->scsiOSLun);
 548                         }
 549                         (void *) fprintf(stdout, "\n");
 550                 }
 551 
 552                 if (devListWalk->inquiryFailed) {
 553                         (void *) fprintf(stdout, "%s %s\n",
 554                             gettext("Error: Failed to get Inquiry data "
 555                             "on device"), devListWalk->OSDeviceName);
 556                         ret++;
 557                 } else {
 558                         (void *) fprintf(stdout, "%sVendor: ",
 559                             getIndentSpaces(4));
 560                         for (count = sizeof (devListWalk->VID), i = 0;
 561                             i < count; i++) {
 562                                 if (isprint(devListWalk->VID[i]))
 563                                         (void *) fprintf(stdout, "%c",
 564                                             devListWalk->VID[i]);
 565                         }
 566 
 567                         (void *) fprintf(stdout, "\n%sProduct: ",
 568                             getIndentSpaces(4));
 569                         for (count = sizeof (devListWalk->PID), i = 0;
 570                             i < count; i++) {
 571                                 if (isprint(devListWalk->PID[i]))
 572                                         (void *) fprintf(stdout, "%c",
 573                                             devListWalk->PID[i]);
 574                         }
 575 
 576                         (void *) fprintf(stdout, "\n%sDevice Type: %s\n",
 577                             getIndentSpaces(4),
 578                             getDTypeString(devListWalk->dType));
 579                 }
 580         }
 581         return (ret);
 582 }