xref: /illumos-gate/usr/src/cmd/fcinfo/printAttrs.c (revision c3937c08b16d32677a7dc955a81325f2e7a61b5d)
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