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