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