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 } 583