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