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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * Copyright 2020 RackTop Systems, Inc. 25 */ 26 27 28 29 #include <stdio.h> 30 #include <hbaapi.h> 31 #include <string.h> 32 #include <sys/types.h> 33 #include <netinet/in.h> 34 #include <inttypes.h> 35 #include <ctype.h> 36 #include "fcinfo.h" 37 38 #ifdef _BIG_ENDIAN 39 #define htonll(x) (x) 40 #define ntohll(x) (x) 41 #else 42 #define htonll(x) ((((unsigned long long)htonl(x)) << 32) + htonl(x >> 32)) 43 #define ntohll(x) ((((unsigned long long)ntohl(x)) << 32) + ntohl(x >> 32)) 44 #endif 45 46 /* Fc4 Types Format */ 47 #define FC4_TYPE_WORD_POS(x) ((uint_t)((uint_t)(x) >> 5)) 48 #define FC4_TYPE_BIT_POS(x) ((uchar_t)(x) & 0x1F) 49 50 #define TYPE_IP_FC 0x05 51 #define TYPE_SCSI_FCP 0x08 52 53 static int fc4_map_is_set(uint32_t *map, uchar_t ulp_type); 54 static char *getPortType(HBA_PORTTYPE portType); 55 static char *getPortState(HBA_PORTSTATE portState); 56 static void printPortSpeed(HBA_PORTSPEED portSpeed); 57 static char *getDTypeString(uchar_t dType); 58 59 uint64_t wwnConversion(uchar_t *wwn) { 60 uint64_t tmp; 61 memcpy(&tmp, wwn, sizeof (uint64_t)); 62 return (ntohll(tmp)); 63 } 64 65 static char * 66 getPortType(HBA_PORTTYPE portType) { 67 switch (portType) { 68 case HBA_PORTTYPE_UNKNOWN: 69 return ("unknown"); 70 case HBA_PORTTYPE_OTHER: 71 return ("other"); 72 case HBA_PORTTYPE_NOTPRESENT: 73 return ("not present"); 74 case HBA_PORTTYPE_NPORT: 75 return ("N-port"); 76 case HBA_PORTTYPE_NLPORT: 77 return ("NL-port"); 78 case HBA_PORTTYPE_FLPORT: 79 return ("FL-port"); 80 case HBA_PORTTYPE_FPORT: 81 return ("F-port"); 82 case HBA_PORTTYPE_LPORT: 83 return ("L-port"); 84 case HBA_PORTTYPE_PTP: 85 return ("point-to-point"); 86 default: 87 return ("unrecognized type"); 88 } 89 } 90 91 static char * 92 getPortState(HBA_PORTSTATE portState) { 93 switch (portState) { 94 case HBA_PORTSTATE_UNKNOWN: 95 return ("unknown"); 96 case HBA_PORTSTATE_ONLINE: 97 return ("online"); 98 case HBA_PORTSTATE_OFFLINE: 99 return ("offline"); 100 case HBA_PORTSTATE_BYPASSED: 101 return ("bypassed"); 102 case HBA_PORTSTATE_DIAGNOSTICS: 103 return ("diagnostics"); 104 case HBA_PORTSTATE_LINKDOWN: 105 return ("link down"); 106 case HBA_PORTSTATE_ERROR: 107 return ("error"); 108 case HBA_PORTSTATE_LOOPBACK: 109 return ("loopback"); 110 default: 111 return ("unrecognized state"); 112 } 113 } 114 115 static void 116 printPortSpeed(HBA_PORTSPEED portSpeed) { 117 int foundSpeed = 0; 118 119 if ((portSpeed & HBA_PORTSPEED_1GBIT) == HBA_PORTSPEED_1GBIT) { 120 fprintf(stdout, "1Gb "); 121 foundSpeed = 1; 122 } 123 if ((portSpeed & HBA_PORTSPEED_2GBIT) == HBA_PORTSPEED_2GBIT) { 124 fprintf(stdout, "2Gb "); 125 foundSpeed = 1; 126 } 127 if ((portSpeed & HBA_PORTSPEED_4GBIT) == HBA_PORTSPEED_4GBIT) { 128 fprintf(stdout, "4Gb "); 129 foundSpeed = 1; 130 } 131 if ((portSpeed & HBA_PORTSPEED_8GBIT) == HBA_PORTSPEED_8GBIT) { 132 fprintf(stdout, "8Gb "); 133 foundSpeed = 1; 134 } 135 if ((portSpeed & HBA_PORTSPEED_10GBIT) == HBA_PORTSPEED_10GBIT) { 136 fprintf(stdout, "10Gb "); 137 foundSpeed = 1; 138 } 139 if ((portSpeed & HBA_PORTSPEED_16GBIT) == HBA_PORTSPEED_16GBIT) { 140 fprintf(stdout, "16Gb "); 141 foundSpeed = 1; 142 } 143 if ((portSpeed & HBA_PORTSPEED_32GBIT) == HBA_PORTSPEED_32GBIT) { 144 fprintf(stdout, "32Gb "); 145 foundSpeed = 1; 146 } 147 if ((portSpeed & HBA_PORTSPEED_NOT_NEGOTIATED) 148 == HBA_PORTSPEED_NOT_NEGOTIATED) { 149 fprintf(stdout, "not established "); 150 foundSpeed = 1; 151 } 152 if (foundSpeed == 0) { 153 fprintf(stdout, "not established "); 154 } 155 } 156 157 void 158 printDiscoPortInfo(HBA_PORTATTRIBUTES *discoPort, int scsiTargetType) { 159 int fc4_types = 0; 160 161 fprintf(stdout, gettext("Remote Port WWN: %016llx\n"), 162 wwnConversion(discoPort->PortWWN.wwn)); 163 fprintf(stdout, gettext("\tActive FC4 Types: ")); 164 if (fc4_map_is_set( 165 (uint32_t *)discoPort->PortActiveFc4Types.bits, 166 TYPE_SCSI_FCP)) { 167 fprintf(stdout, gettext("SCSI")); 168 fc4_types++; 169 } 170 if (fc4_map_is_set( 171 (uint32_t *)discoPort->PortActiveFc4Types.bits, 172 TYPE_IP_FC)) { 173 if (fc4_types != 0) { 174 fprintf(stdout, ","); 175 } 176 fprintf(stdout, gettext("IP")); 177 fc4_types++; 178 } 179 fprintf(stdout, "\n"); 180 181 /* print out scsi target type information */ 182 fprintf(stdout, gettext("\tSCSI Target: ")); 183 if (scsiTargetType == SCSI_TARGET_TYPE_YES) { 184 fprintf(stdout, gettext("yes\n")); 185 } else if (scsiTargetType == SCSI_TARGET_TYPE_NO) { 186 fprintf(stdout, gettext("no\n")); 187 } else { 188 fprintf(stdout, gettext("unknown\n")); 189 } 190 fprintf(stdout, gettext("\tPort Symbolic Name: %s\n"), 191 discoPort->PortSymbolicName); 192 fprintf(stdout, gettext("\tNode WWN: %016llx\n"), 193 wwnConversion(discoPort->NodeWWN.wwn)); 194 } 195 196 /* 197 * scan the bitmap array for the specifed ULP type. The bit map array 198 * is 32 bytes long 199 */ 200 static int 201 fc4_map_is_set(uint32_t *map, uchar_t ulp_type) 202 { 203 204 map += FC4_TYPE_WORD_POS(ulp_type) * 4; 205 206 if (ntohl((*(uint32_t *)map)) & (1 << FC4_TYPE_BIT_POS(ulp_type))) { 207 return (1); 208 } 209 210 return (0); 211 } 212 213 /* 214 * prints out all the HBA port information 215 */ 216 void 217 printHBAPortInfo(HBA_PORTATTRIBUTES *port, 218 HBA_ADAPTERATTRIBUTES *attrs, int mode) { 219 if (attrs == NULL || port == NULL) { 220 return; 221 } 222 fprintf(stdout, gettext("HBA Port WWN: %016llx\n"), 223 wwnConversion(port->PortWWN.wwn)); 224 fprintf(stdout, gettext("\tPort Mode: %s\n"), 225 (mode == INITIATOR_MODE) ? "Initiator" : "Target"); 226 fprintf(stdout, gettext("\tPort ID: %x\n"), 227 port->PortFcId); 228 fprintf(stdout, gettext("\tOS Device Name: %s\n"), port->OSDeviceName); 229 230 fprintf(stdout, gettext("\tManufacturer: %s\n"), 231 attrs->Manufacturer); 232 fprintf(stdout, gettext("\tModel: %s\n"), attrs->Model); 233 fprintf(stdout, gettext("\tFirmware Version: %s\n"), 234 attrs->FirmwareVersion); 235 fprintf(stdout, gettext("\tFCode/BIOS Version: %s\n"), 236 attrs->OptionROMVersion); 237 fprintf(stdout, gettext("\tSerial Number: %s\n"), 238 attrs->SerialNumber[0] == 0? "not available":attrs->SerialNumber); 239 240 fprintf(stdout, gettext("\tDriver Name: %s\n"), 241 attrs->DriverName[0] == 0? "not available":attrs->DriverName); 242 fprintf(stdout, gettext("\tDriver Version: %s\n"), 243 attrs->DriverVersion[0] == 0? "not available":attrs->DriverVersion); 244 245 fprintf(stdout, gettext("\tType: %s\n"), 246 getPortType(port->PortType)); 247 fprintf(stdout, gettext("\tState: %s\n"), 248 getPortState(port->PortState)); 249 250 fprintf(stdout, gettext("\tSupported Speeds: ")); 251 printPortSpeed(port->PortSupportedSpeed); 252 fprintf(stdout, "\n"); 253 254 fprintf(stdout, gettext("\tCurrent Speed: ")); 255 printPortSpeed(port->PortSpeed); 256 fprintf(stdout, "\n"); 257 258 fprintf(stdout, gettext("\tNode WWN: %016llx\n"), 259 wwnConversion(port->NodeWWN.wwn)); 260 } 261 262 void 263 printStatus(HBA_STATUS status) { 264 switch (status) { 265 case HBA_STATUS_OK: 266 fprintf(stderr, gettext("OK")); 267 return; 268 case HBA_STATUS_ERROR: 269 fprintf(stderr, gettext("ERROR")); 270 return; 271 case HBA_STATUS_ERROR_NOT_SUPPORTED: 272 fprintf(stderr, gettext("NOT SUPPORTED")); 273 return; 274 case HBA_STATUS_ERROR_INVALID_HANDLE: 275 fprintf(stderr, gettext("INVALID HANDLE")); 276 return; 277 case HBA_STATUS_ERROR_ARG: 278 fprintf(stderr, gettext("ERROR ARG")); 279 return; 280 case HBA_STATUS_ERROR_ILLEGAL_WWN: 281 fprintf(stderr, gettext("ILLEGAL WWN")); 282 return; 283 case HBA_STATUS_ERROR_ILLEGAL_INDEX: 284 fprintf(stderr, gettext("ILLEGAL INDEX")); 285 return; 286 case HBA_STATUS_ERROR_MORE_DATA: 287 fprintf(stderr, gettext("MORE DATA")); 288 return; 289 case HBA_STATUS_ERROR_STALE_DATA: 290 fprintf(stderr, gettext("STALE DATA")); 291 return; 292 case HBA_STATUS_SCSI_CHECK_CONDITION: 293 fprintf(stderr, gettext("SCSI CHECK CONDITION")); 294 return; 295 case HBA_STATUS_ERROR_BUSY: 296 fprintf(stderr, gettext("BUSY")); 297 return; 298 case HBA_STATUS_ERROR_TRY_AGAIN: 299 fprintf(stderr, gettext("TRY AGAIN")); 300 return; 301 case HBA_STATUS_ERROR_UNAVAILABLE: 302 fprintf(stderr, gettext("UNAVAILABLE")); 303 return; 304 default: 305 fprintf(stderr, "%s %d", 306 gettext("Undefined error code "), status); 307 return; 308 } 309 } 310 311 void 312 printLUNInfo(struct scsi_inquiry *inq, HBA_UINT32 scsiLUN, char *devpath) { 313 fprintf(stdout, "\tLUN: %d\n", scsiLUN); 314 fprintf(stdout, "\t Vendor: %c%c%c%c%c%c%c%c\n", 315 inq->inq_vid[0], 316 inq->inq_vid[1], 317 inq->inq_vid[2], 318 inq->inq_vid[3], 319 inq->inq_vid[4], 320 inq->inq_vid[5], 321 inq->inq_vid[6], 322 inq->inq_vid[7]); 323 fprintf(stdout, "\t Product: %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", 324 inq->inq_pid[0], 325 inq->inq_pid[1], 326 inq->inq_pid[2], 327 inq->inq_pid[3], 328 inq->inq_pid[4], 329 inq->inq_pid[5], 330 inq->inq_pid[6], 331 inq->inq_pid[7], 332 inq->inq_pid[8], 333 inq->inq_pid[9], 334 inq->inq_pid[10], 335 inq->inq_pid[11], 336 inq->inq_pid[12], 337 inq->inq_pid[13], 338 inq->inq_pid[14], 339 inq->inq_pid[15]); 340 fprintf(stdout, gettext("\t OS Device Name: %s\n"), devpath); 341 } 342 343 void 344 printPortStat(fc_rls_acc_t *rls_payload) { 345 fprintf(stdout, gettext("\tLink Error Statistics:\n")); 346 fprintf(stdout, gettext("\t\tLink Failure Count: %u\n"), 347 rls_payload->rls_link_fail); 348 fprintf(stdout, gettext("\t\tLoss of Sync Count: %u\n"), 349 rls_payload->rls_sync_loss); 350 fprintf(stdout, gettext("\t\tLoss of Signal Count: %u\n"), 351 rls_payload->rls_sig_loss); 352 fprintf(stdout, gettext("\t\tPrimitive Seq Protocol Error Count: %u\n"), 353 rls_payload->rls_prim_seq_err); 354 fprintf(stdout, gettext("\t\tInvalid Tx Word Count: %u\n"), 355 rls_payload->rls_invalid_word); 356 fprintf(stdout, gettext("\t\tInvalid CRC Count: %u\n"), 357 rls_payload->rls_invalid_crc); 358 } 359 360 /* 361 * return device type description 362 * 363 * Arguments: 364 * dType - Device type returned from Standard INQUIRY 365 * Returns: 366 * char string description for device type 367 */ 368 static char * 369 getDTypeString(uchar_t dType) 370 { 371 switch (dType & DTYPE_MASK) { 372 case DTYPE_DIRECT: 373 return ("Disk Device"); 374 case DTYPE_SEQUENTIAL: 375 return ("Tape Device"); 376 case DTYPE_PRINTER: 377 return ("Printer Device"); 378 case DTYPE_PROCESSOR: 379 return ("Processor Device"); 380 case DTYPE_WORM: 381 return ("WORM Device"); 382 case DTYPE_RODIRECT: 383 return ("CD/DVD Device"); 384 case DTYPE_SCANNER: 385 return ("Scanner Device"); 386 case DTYPE_OPTICAL: 387 return ("Optical Memory Device"); 388 case DTYPE_CHANGER: 389 return ("Medium Changer Device"); 390 case DTYPE_COMM: 391 return ("Communications Device"); 392 case DTYPE_ARRAY_CTRL: 393 return ("Storage Array Controller Device"); 394 case DTYPE_ESI: 395 return ("Enclosure Services Device"); 396 case DTYPE_RBC: 397 return ("Simplified Direct-access Device"); 398 case DTYPE_OCRW: 399 return ("Optical Card Reader/Writer Device"); 400 case DTYPE_BCC: 401 return ("Bridge Controller Commands"); 402 case DTYPE_OSD: 403 return ("Object-based Storage Device"); 404 case DTYPE_ADC: 405 return ("Automation/Drive Interface"); 406 case DTYPE_WELLKNOWN: 407 return ("Well Known Logical Unit"); 408 case DTYPE_UNKNOWN: 409 return ("Unknown Device"); 410 default: 411 return ("Undefined"); 412 } 413 } 414 415 /* 416 * print the OS device name for the logical-unit object 417 * 418 * Arguments: 419 * devListWalk - OS device path info 420 * verbose - boolean indicating whether to display additional info 421 * 422 * returns: 423 * none 424 */ 425 void 426 printOSDeviceNameInfo(discoveredDevice *devListWalk, boolean_t verbose) 427 { 428 portWWNList *WWNList; 429 tgtPortWWNList *tgtWWNList; 430 int i, count; 431 432 fprintf(stdout, "OS Device Name: %s\n", devListWalk->OSDeviceName); 433 if (verbose == B_TRUE) { 434 for (WWNList = devListWalk->HBAPortWWN; 435 WWNList != NULL; WWNList = WWNList->next) { 436 fprintf(stdout, "\tHBA Port WWN: "); 437 fprintf(stdout, "%016llx", 438 wwnConversion(WWNList->portWWN.wwn)); 439 for (tgtWWNList = WWNList->tgtPortWWN; 440 tgtWWNList != NULL; tgtWWNList = tgtWWNList->next) { 441 fprintf(stdout, "\n\t\tRemote Port WWN: "); 442 fprintf(stdout, "%016llx", 443 wwnConversion(tgtWWNList->portWWN.wwn)); 444 fprintf(stdout, "\n\t\t\tLUN: %d", 445 tgtWWNList->scsiOSLun); 446 } 447 fprintf(stdout, "\n"); 448 } 449 450 fprintf(stdout, "\tVendor: "); 451 for (count = sizeof (devListWalk->VID), i = 0; i < count; i++) { 452 if (isprint(devListWalk->VID[i])) 453 fprintf(stdout, "%c", devListWalk->VID[i]); 454 } 455 456 fprintf(stdout, "\n\tProduct: "); 457 for (count = sizeof (devListWalk->PID), i = 0; i < count; i++) { 458 if (isprint(devListWalk->PID[i])) 459 fprintf(stdout, "%c", devListWalk->PID[i]); 460 } 461 462 fprintf(stdout, "\n\tDevice Type: %s\n", 463 getDTypeString(devListWalk->dType)); 464 } 465 } 466