xref: /freebsd/contrib/ofed/libibmad/dump.c (revision 031beb4e239bfce798af17f5fe8dba8bcaf13d99)
1 /*
2  * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
3  * Copyright (c) 2007 Xsigo Systems Inc.  All rights reserved.
4  * Copyright (c) 2009-2011 Mellanox Technologies LTD.  All rights reserved.
5  * Copyright (c) 2009 HNR Consulting.  All rights reserved.
6  *
7  * This software is available to you under a choice of one of two
8  * licenses.  You may choose to be licensed under the terms of the GNU
9  * General Public License (GPL) Version 2, available from the file
10  * COPYING in the main directory of this source tree, or the
11  * OpenIB.org BSD license below:
12  *
13  *     Redistribution and use in source and binary forms, with or
14  *     without modification, are permitted provided that the following
15  *     conditions are met:
16  *
17  *      - Redistributions of source code must retain the above
18  *        copyright notice, this list of conditions and the following
19  *        disclaimer.
20  *
21  *      - Redistributions in binary form must reproduce the above
22  *        copyright notice, this list of conditions and the following
23  *        disclaimer in the documentation and/or other materials
24  *        provided with the distribution.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33  * SOFTWARE.
34  *
35  */
36 
37 #if HAVE_CONFIG_H
38 #  include <config.h>
39 #endif				/* HAVE_CONFIG_H */
40 
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 
45 #include <infiniband/mad.h>
46 
47 void mad_dump_int(char *buf, int bufsz, void *val, int valsz)
48 {
49 	switch (valsz) {
50 	case 1:
51 		snprintf(buf, bufsz, "%d", *(uint32_t *) val & 0xff);
52 		break;
53 	case 2:
54 		snprintf(buf, bufsz, "%d", *(uint32_t *) val & 0xffff);
55 		break;
56 	case 3:
57 	case 4:
58 		snprintf(buf, bufsz, "%d", *(uint32_t *) val);
59 		break;
60 	case 5:
61 	case 6:
62 	case 7:
63 	case 8:
64 		snprintf(buf, bufsz, "%" PRIu64, *(uint64_t *) val);
65 		break;
66 	default:
67 		IBWARN("bad int sz %d", valsz);
68 		buf[0] = 0;
69 	}
70 }
71 
72 void mad_dump_uint(char *buf, int bufsz, void *val, int valsz)
73 {
74 	switch (valsz) {
75 	case 1:
76 		snprintf(buf, bufsz, "%u", *(uint32_t *) val & 0xff);
77 		break;
78 	case 2:
79 		snprintf(buf, bufsz, "%u", *(uint32_t *) val & 0xffff);
80 		break;
81 	case 3:
82 	case 4:
83 		snprintf(buf, bufsz, "%u", *(uint32_t *) val);
84 		break;
85 	case 5:
86 	case 6:
87 	case 7:
88 	case 8:
89 		snprintf(buf, bufsz, "%" PRIu64, *(uint64_t *) val);
90 		break;
91 	default:
92 		IBWARN("bad int sz %u", valsz);
93 		buf[0] = 0;
94 	}
95 }
96 
97 void mad_dump_hex(char *buf, int bufsz, void *val, int valsz)
98 {
99 	switch (valsz) {
100 	case 1:
101 		snprintf(buf, bufsz, "0x%02x", *(uint32_t *) val & 0xff);
102 		break;
103 	case 2:
104 		snprintf(buf, bufsz, "0x%04x", *(uint32_t *) val & 0xffff);
105 		break;
106 	case 3:
107 		snprintf(buf, bufsz, "0x%06x", *(uint32_t *) val & 0xffffff);
108 		break;
109 	case 4:
110 		snprintf(buf, bufsz, "0x%08x", *(uint32_t *) val);
111 		break;
112 	case 5:
113 		snprintf(buf, bufsz, "0x%010" PRIx64,
114 			 *(uint64_t *) val & (uint64_t) 0xffffffffffULL);
115 		break;
116 	case 6:
117 		snprintf(buf, bufsz, "0x%012" PRIx64,
118 			 *(uint64_t *) val & (uint64_t) 0xffffffffffffULL);
119 		break;
120 	case 7:
121 		snprintf(buf, bufsz, "0x%014" PRIx64,
122 			 *(uint64_t *) val & (uint64_t) 0xffffffffffffffULL);
123 		break;
124 	case 8:
125 		snprintf(buf, bufsz, "0x%016" PRIx64, *(uint64_t *) val);
126 		break;
127 	default:
128 		IBWARN("bad int sz %d", valsz);
129 		buf[0] = 0;
130 	}
131 }
132 
133 void mad_dump_rhex(char *buf, int bufsz, void *val, int valsz)
134 {
135 	switch (valsz) {
136 	case 1:
137 		snprintf(buf, bufsz, "%02x", *(uint32_t *) val & 0xff);
138 		break;
139 	case 2:
140 		snprintf(buf, bufsz, "%04x", *(uint32_t *) val & 0xffff);
141 		break;
142 	case 3:
143 		snprintf(buf, bufsz, "%06x", *(uint32_t *) val & 0xffffff);
144 		break;
145 	case 4:
146 		snprintf(buf, bufsz, "%08x", *(uint32_t *) val);
147 		break;
148 	case 5:
149 		snprintf(buf, bufsz, "%010" PRIx64,
150 			 *(uint64_t *) val & (uint64_t) 0xffffffffffULL);
151 		break;
152 	case 6:
153 		snprintf(buf, bufsz, "%012" PRIx64,
154 			 *(uint64_t *) val & (uint64_t) 0xffffffffffffULL);
155 		break;
156 	case 7:
157 		snprintf(buf, bufsz, "%014" PRIx64,
158 			 *(uint64_t *) val & (uint64_t) 0xffffffffffffffULL);
159 		break;
160 	case 8:
161 		snprintf(buf, bufsz, "%016" PRIx64, *(uint64_t *) val);
162 		break;
163 	default:
164 		IBWARN("bad int sz %d", valsz);
165 		buf[0] = 0;
166 	}
167 }
168 
169 void mad_dump_linkwidth(char *buf, int bufsz, void *val, int valsz)
170 {
171 	int width = *(int *)val;
172 
173 	switch (width) {
174 	case 1:
175 		snprintf(buf, bufsz, "1X");
176 		break;
177 	case 2:
178 		snprintf(buf, bufsz, "4X");
179 		break;
180 	case 4:
181 		snprintf(buf, bufsz, "8X");
182 		break;
183 	case 8:
184 		snprintf(buf, bufsz, "12X");
185 		break;
186 	case 16:
187 		snprintf(buf, bufsz, "2X");
188 		break;
189 	default:
190 		IBWARN("bad width %d", width);
191 		snprintf(buf, bufsz, "undefined (%d)", width);
192 		break;
193 	}
194 }
195 
196 static void dump_linkwidth(char *buf, int bufsz, int width)
197 {
198 	int n = 0;
199 
200 	if (width & 0x1)
201 		n += snprintf(buf + n, bufsz - n, "1X or ");
202 	if (n < bufsz && (width & 0x2))
203 		n += snprintf(buf + n, bufsz - n, "4X or ");
204 	if (n < bufsz && (width & 0x4))
205 		n += snprintf(buf + n, bufsz - n, "8X or ");
206 	if (n < bufsz && (width & 0x8))
207 		n += snprintf(buf + n, bufsz - n, "12X or ");
208 	if (n < bufsz && (width & 0x10))
209 		n += snprintf(buf + n, bufsz - n, "2X or ");
210 
211 	if (n >= bufsz)
212 		return;
213 	else if (width == 0 || (width >> 5))
214 		snprintf(buf + n, bufsz - n, "undefined (%d)", width);
215 	else if (bufsz > 3)
216 		buf[n - 4] = '\0';
217 }
218 
219 void mad_dump_linkwidthsup(char *buf, int bufsz, void *val, int valsz)
220 {
221 	int width = *(int *)val;
222 
223 	dump_linkwidth(buf, bufsz, width);
224 
225 	switch (width) {
226 	case 1:
227 	case 3:
228 	case 7:
229 	case 11:
230 	case 15:
231 	case 17:
232 	case 19:
233 	case 23:
234 	case 27:
235 	case 31:
236 		break;
237 
238 	default:
239 		if (!(width >> 5))
240 			snprintf(buf + strlen(buf), bufsz - strlen(buf),
241 				 " (IBA extension)");
242 		break;
243 	}
244 }
245 
246 void mad_dump_linkwidthen(char *buf, int bufsz, void *val, int valsz)
247 {
248 	int width = *(int *)val;
249 
250 	dump_linkwidth(buf, bufsz, width);
251 }
252 
253 void mad_dump_linkspeed(char *buf, int bufsz, void *val, int valsz)
254 {
255 	int speed = *(int *)val;
256 
257 	switch (speed) {
258 	case 0:
259 		snprintf(buf, bufsz, "Extended speed");
260 		break;
261 	case 1:
262 		snprintf(buf, bufsz, "2.5 Gbps");
263 		break;
264 	case 2:
265 		snprintf(buf, bufsz, "5.0 Gbps");
266 		break;
267 	case 4:
268 		snprintf(buf, bufsz, "10.0 Gbps");
269 		break;
270 	default:
271 		snprintf(buf, bufsz, "undefined (%d)", speed);
272 		break;
273 	}
274 }
275 
276 static void dump_linkspeed(char *buf, int bufsz, int speed)
277 {
278 	int n = 0;
279 
280 	if (speed & 0x1)
281 		n += snprintf(buf + n, bufsz - n, "2.5 Gbps or ");
282 	if (n < bufsz && (speed & 0x2))
283 		n += snprintf(buf + n, bufsz - n, "5.0 Gbps or ");
284 	if (n < bufsz && (speed & 0x4))
285 		n += snprintf(buf + n, bufsz - n, "10.0 Gbps or ");
286 
287 	if (n >= bufsz)
288 		return;
289 	else if (speed == 0 || (speed >> 3)) {
290 		n += snprintf(buf + n, bufsz - n, "undefined (%d)", speed);
291 		if (n >= bufsz)
292 			return;
293 	} else if (bufsz > 3) {
294 		buf[n - 4] = '\0';
295 		n -= 4;
296 	}
297 
298 	switch (speed) {
299 	case 1:
300 	case 3:
301 	case 5:
302 	case 7:
303 		break;
304 	default:
305 		if (!(speed >> 3))
306 			snprintf(buf + n, bufsz - n, " (IBA extension)");
307 		break;
308 	}
309 }
310 
311 void mad_dump_linkspeedsup(char *buf, int bufsz, void *val, int valsz)
312 {
313 	int speed = *(int *)val;
314 
315 	dump_linkspeed(buf, bufsz, speed);
316 }
317 
318 void mad_dump_linkspeeden(char *buf, int bufsz, void *val, int valsz)
319 {
320 	int speed = *(int *)val;
321 
322 	dump_linkspeed(buf, bufsz, speed);
323 }
324 
325 void mad_dump_linkspeedext(char *buf, int bufsz, void *val, int valsz)
326 {
327 	int speed = *(int *)val;
328 
329 	switch (speed) {
330 	case 0:
331 		snprintf(buf, bufsz, "No Extended Speed");
332 		break;
333 	case 1:
334 		snprintf(buf, bufsz, "14.0625 Gbps");
335 		break;
336 	case 2:
337 		snprintf(buf, bufsz, "25.78125 Gbps");
338 		break;
339 	default:
340 		snprintf(buf, bufsz, "undefined (%d)", speed);
341 		break;
342 	}
343 }
344 
345 static void dump_linkspeedext(char *buf, int bufsz, int speed)
346 {
347 	int n = 0;
348 
349 	if (speed == 0) {
350 		sprintf(buf, "%d", speed);
351 		return;
352 	}
353 
354 	if (speed & 0x1)
355 		n += snprintf(buf + n, bufsz - n, "14.0625 Gbps or ");
356 	if (n < bufsz && speed & 0x2)
357 		n += snprintf(buf + n, bufsz - n, "25.78125 Gbps or ");
358 	if (n >= bufsz) {
359 		if (bufsz > 3)
360 			buf[n - 4] = '\0';
361 		return;
362 	}
363 
364 	if (speed >> 2) {
365 		n += snprintf(buf + n, bufsz - n, "undefined (%d)", speed);
366 		return;
367 	} else if (bufsz > 3)
368 		buf[n - 4] = '\0';
369 }
370 
371 void mad_dump_linkspeedextsup(char *buf, int bufsz, void *val, int valsz)
372 {
373 	int speed = *(int *)val;
374 
375 	dump_linkspeedext(buf, bufsz, speed);
376 }
377 
378 void mad_dump_linkspeedexten(char *buf, int bufsz, void *val, int valsz)
379 {
380 	int speed = *(int *)val;
381 
382 	if (speed == 30) {
383 		sprintf(buf, "%s", "Extended link speeds disabled");
384 		return;
385 	}
386 	dump_linkspeedext(buf, bufsz, speed);
387 }
388 
389 void mad_dump_portstate(char *buf, int bufsz, void *val, int valsz)
390 {
391 	int state = *(int *)val;
392 
393 	switch (state) {
394 	case 0:
395 		snprintf(buf, bufsz, "NoChange");
396 		break;
397 	case 1:
398 		snprintf(buf, bufsz, "Down");
399 		break;
400 	case 2:
401 		snprintf(buf, bufsz, "Initialize");
402 		break;
403 	case 3:
404 		snprintf(buf, bufsz, "Armed");
405 		break;
406 	case 4:
407 		snprintf(buf, bufsz, "Active");
408 		break;
409 	default:
410 		snprintf(buf, bufsz, "?(%d)", state);
411 	}
412 }
413 
414 void mad_dump_linkdowndefstate(char *buf, int bufsz, void *val, int valsz)
415 {
416 	int state = *(int *)val;
417 
418 	switch (state) {
419 	case 0:
420 		snprintf(buf, bufsz, "NoChange");
421 		break;
422 	case 1:
423 		snprintf(buf, bufsz, "Sleep");
424 		break;
425 	case 2:
426 		snprintf(buf, bufsz, "Polling");
427 		break;
428 	default:
429 		snprintf(buf, bufsz, "?(%d)", state);
430 		break;
431 	}
432 }
433 
434 void mad_dump_physportstate(char *buf, int bufsz, void *val, int valsz)
435 {
436 	int state = *(int *)val;
437 
438 	switch (state) {
439 	case 0:
440 		snprintf(buf, bufsz, "NoChange");
441 		break;
442 	case 1:
443 		snprintf(buf, bufsz, "Sleep");
444 		break;
445 	case 2:
446 		snprintf(buf, bufsz, "Polling");
447 		break;
448 	case 3:
449 		snprintf(buf, bufsz, "Disabled");
450 		break;
451 	case 4:
452 		snprintf(buf, bufsz, "PortConfigurationTraining");
453 		break;
454 	case 5:
455 		snprintf(buf, bufsz, "LinkUp");
456 		break;
457 	case 6:
458 		snprintf(buf, bufsz, "LinkErrorRecovery");
459 		break;
460 	case 7:
461 		snprintf(buf, bufsz, "PhyTest");
462 		break;
463 	default:
464 		snprintf(buf, bufsz, "?(%d)", state);
465 	}
466 }
467 
468 void mad_dump_mtu(char *buf, int bufsz, void *val, int valsz)
469 {
470 	int mtu = *(int *)val;
471 
472 	switch (mtu) {
473 	case 1:
474 		snprintf(buf, bufsz, "256");
475 		break;
476 	case 2:
477 		snprintf(buf, bufsz, "512");
478 		break;
479 	case 3:
480 		snprintf(buf, bufsz, "1024");
481 		break;
482 	case 4:
483 		snprintf(buf, bufsz, "2048");
484 		break;
485 	case 5:
486 		snprintf(buf, bufsz, "4096");
487 		break;
488 	default:
489 		snprintf(buf, bufsz, "?(%d)", mtu);
490 	}
491 }
492 
493 void mad_dump_vlcap(char *buf, int bufsz, void *val, int valsz)
494 {
495 	int vlcap = *(int *)val;
496 
497 	switch (vlcap) {
498 	case 1:
499 		snprintf(buf, bufsz, "VL0");
500 		break;
501 	case 2:
502 		snprintf(buf, bufsz, "VL0-1");
503 		break;
504 	case 3:
505 		snprintf(buf, bufsz, "VL0-3");
506 		break;
507 	case 4:
508 		snprintf(buf, bufsz, "VL0-7");
509 		break;
510 	case 5:
511 		snprintf(buf, bufsz, "VL0-14");
512 		break;
513 	default:
514 		snprintf(buf, bufsz, "?(%d)", vlcap);
515 	}
516 }
517 
518 void mad_dump_opervls(char *buf, int bufsz, void *val, int valsz)
519 {
520 	int opervls = *(int *)val;
521 
522 	switch (opervls) {
523 	case 0:
524 		snprintf(buf, bufsz, "No change");
525 		break;
526 	case 1:
527 		snprintf(buf, bufsz, "VL0");
528 		break;
529 	case 2:
530 		snprintf(buf, bufsz, "VL0-1");
531 		break;
532 	case 3:
533 		snprintf(buf, bufsz, "VL0-3");
534 		break;
535 	case 4:
536 		snprintf(buf, bufsz, "VL0-7");
537 		break;
538 	case 5:
539 		snprintf(buf, bufsz, "VL0-14");
540 		break;
541 	default:
542 		snprintf(buf, bufsz, "?(%d)", opervls);
543 	}
544 }
545 
546 void mad_dump_portcapmask(char *buf, int bufsz, void *val, int valsz)
547 {
548 	unsigned mask = *(unsigned *)val;
549 	char *s = buf;
550 
551 	s += sprintf(s, "0x%x\n", mask);
552 	if (mask & (1 << 1))
553 		s += sprintf(s, "\t\t\t\tIsSM\n");
554 	if (mask & (1 << 2))
555 		s += sprintf(s, "\t\t\t\tIsNoticeSupported\n");
556 	if (mask & (1 << 3))
557 		s += sprintf(s, "\t\t\t\tIsTrapSupported\n");
558 	if (mask & (1 << 4))
559 		s += sprintf(s, "\t\t\t\tIsOptionalIPDSupported\n");
560 	if (mask & (1 << 5))
561 		s += sprintf(s, "\t\t\t\tIsAutomaticMigrationSupported\n");
562 	if (mask & (1 << 6))
563 		s += sprintf(s, "\t\t\t\tIsSLMappingSupported\n");
564 	if (mask & (1 << 7))
565 		s += sprintf(s, "\t\t\t\tIsMKeyNVRAM\n");
566 	if (mask & (1 << 8))
567 		s += sprintf(s, "\t\t\t\tIsPKeyNVRAM\n");
568 	if (mask & (1 << 9))
569 		s += sprintf(s, "\t\t\t\tIsLedInfoSupported\n");
570 	if (mask & (1 << 10))
571 		s += sprintf(s, "\t\t\t\tIsSMdisabled\n");
572 	if (mask & (1 << 11))
573 		s += sprintf(s, "\t\t\t\tIsSystemImageGUIDsupported\n");
574 	if (mask & (1 << 12))
575 		s += sprintf(s,
576 			     "\t\t\t\tIsPkeySwitchExternalPortTrapSupported\n");
577 	if (mask & (1 << 14))
578 		s += sprintf(s, "\t\t\t\tIsExtendedSpeedsSupported\n");
579 	if (mask & (1 << 15))
580 		s += sprintf(s, "\t\t\t\tIsCapabilityMask2Supported\n");
581 	if (mask & (1 << 16))
582 		s += sprintf(s, "\t\t\t\tIsCommunicatonManagementSupported\n");
583 	if (mask & (1 << 17))
584 		s += sprintf(s, "\t\t\t\tIsSNMPTunnelingSupported\n");
585 	if (mask & (1 << 18))
586 		s += sprintf(s, "\t\t\t\tIsReinitSupported\n");
587 	if (mask & (1 << 19))
588 		s += sprintf(s, "\t\t\t\tIsDeviceManagementSupported\n");
589 	if (mask & (1 << 20))
590 		s += sprintf(s, "\t\t\t\tIsVendorClassSupported\n");
591 	if (mask & (1 << 21))
592 		s += sprintf(s, "\t\t\t\tIsDRNoticeSupported\n");
593 	if (mask & (1 << 22))
594 		s += sprintf(s, "\t\t\t\tIsCapabilityMaskNoticeSupported\n");
595 	if (mask & (1 << 23))
596 		s += sprintf(s, "\t\t\t\tIsBootManagementSupported\n");
597 	if (mask & (1 << 24))
598 		s += sprintf(s, "\t\t\t\tIsLinkRoundTripLatencySupported\n");
599 	if (mask & (1 << 25))
600 		s += sprintf(s, "\t\t\t\tIsClientRegistrationSupported\n");
601 	if (mask & (1 << 26))
602 		s += sprintf(s, "\t\t\t\tIsOtherLocalChangesNoticeSupported\n");
603 	if (mask & (1 << 27))
604 		s += sprintf(s,
605 			     "\t\t\t\tIsLinkSpeedWidthPairsTableSupported\n");
606 	if (mask & (1 << 28))
607 		s += sprintf(s, "\t\t\t\tIsVendorSpecificMadsTableSupported\n");
608 	if (mask & (1 << 29))
609 		s += sprintf(s, "\t\t\t\tIsMcastPkeyTrapSuppressionSupported\n");
610 	if (mask & (1 << 30))
611 		s += sprintf(s, "\t\t\t\tIsMulticastFDBTopSupported\n");
612 	if (mask & (1 << 31))
613 		s += sprintf(s, "\t\t\t\tIsHierarchyInfoSupported\n");
614 
615 	if (s != buf)
616 		*(--s) = 0;
617 }
618 
619 void mad_dump_portcapmask2(char *buf, int bufsz, void *val, int valsz)
620 {
621 	int mask = *(int *)val;
622 	char *s = buf;
623 
624 	s += sprintf(s, "0x%x\n", mask);
625 	if (mask & (1 << 0))
626 		s += sprintf(s, "\t\t\t\tIsSetNodeDescriptionSupported\n");
627 	if (mask & (1 << 1))
628 		s += sprintf(s, "\t\t\t\tIsPortInfoExtendedSupported\n");
629 	if (mask & (1 << 2))
630 		s += sprintf(s, "\t\t\t\tIsVirtualizationSupported\n");
631 	if (mask & (1 << 3))
632 		s += sprintf(s, "\t\t\t\tIsSwitchPortStateTableSupported\n");
633 	if (mask & (1 << 4))
634 		s += sprintf(s, "\t\t\t\tIsLinkWidth2xSupported\n");
635 
636 	if (s != buf)
637 		*(--s) = 0;
638 }
639 
640 void mad_dump_bitfield(char *buf, int bufsz, void *val, int valsz)
641 {
642 	snprintf(buf, bufsz, "0x%x", *(uint32_t *) val);
643 }
644 
645 void mad_dump_array(char *buf, int bufsz, void *val, int valsz)
646 {
647 	uint8_t *p = val, *e;
648 	char *s = buf;
649 
650 	if (bufsz < valsz * 2)
651 		valsz = bufsz / 2;
652 
653 	for (p = val, e = p + valsz; p < e; p++, s += 2)
654 		sprintf(s, "%02x", *p);
655 }
656 
657 void mad_dump_string(char *buf, int bufsz, void *val, int valsz)
658 {
659 	if (bufsz < valsz)
660 		valsz = bufsz;
661 
662 	snprintf(buf, valsz, "'%s'", (char *)val);
663 }
664 
665 void mad_dump_node_type(char *buf, int bufsz, void *val, int valsz)
666 {
667 	int nodetype = *(int *)val;
668 
669 	switch (nodetype) {
670 	case 1:
671 		snprintf(buf, bufsz, "Channel Adapter");
672 		break;
673 	case 2:
674 		snprintf(buf, bufsz, "Switch");
675 		break;
676 	case 3:
677 		snprintf(buf, bufsz, "Router");
678 		break;
679 	default:
680 		snprintf(buf, bufsz, "?(%d)?", nodetype);
681 		break;
682 	}
683 }
684 
685 #define IB_MAX_NUM_VLS 16
686 #define IB_MAX_NUM_VLS_TO_U8 ((IB_MAX_NUM_VLS)/2)
687 
688 typedef struct _ib_slvl_table {
689 	uint8_t vl_by_sl_num[IB_MAX_NUM_VLS_TO_U8];
690 } ib_slvl_table_t;
691 
692 static inline void ib_slvl_get_i(ib_slvl_table_t * tbl, int i, uint8_t * vl)
693 {
694 	*vl = (tbl->vl_by_sl_num[i >> 1] >> ((!(i & 1)) << 2)) & 0xf;
695 }
696 
697 #define IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK 32
698 
699 typedef struct _ib_vl_arb_table {
700 	struct {
701 		uint8_t res_vl;
702 		uint8_t weight;
703 	} vl_entry[IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK];
704 } ib_vl_arb_table_t;
705 
706 static inline void ib_vl_arb_get_vl(uint8_t res_vl, uint8_t * const vl)
707 {
708 	*vl = res_vl & 0x0F;
709 }
710 
711 void mad_dump_sltovl(char *buf, int bufsz, void *val, int valsz)
712 {
713 	ib_slvl_table_t *p_slvl_tbl = val;
714 	uint8_t vl;
715 	int i, n = 0;
716 	n = snprintf(buf, bufsz, "|");
717 	for (i = 0; i < 16; i++) {
718 		ib_slvl_get_i(p_slvl_tbl, i, &vl);
719 		n += snprintf(buf + n, bufsz - n, "%2u|", vl);
720 		if (n >= bufsz)
721 			break;
722 	}
723 	snprintf(buf + n, bufsz - n, "\n");
724 }
725 
726 void mad_dump_vlarbitration(char *buf, int bufsz, void *val, int num)
727 {
728 	ib_vl_arb_table_t *p_vla_tbl = val;
729 	int i, n;
730 	uint8_t vl;
731 
732 	num /= sizeof(p_vla_tbl->vl_entry[0]);
733 
734 	n = snprintf(buf, bufsz, "\nVL    : |");
735 	if (n >= bufsz)
736 		return;
737 	for (i = 0; i < num; i++) {
738 		ib_vl_arb_get_vl(p_vla_tbl->vl_entry[i].res_vl, &vl);
739 		n += snprintf(buf + n, bufsz - n, "0x%-2X|", vl);
740 		if (n >= bufsz)
741 			return;
742 	}
743 
744 	n += snprintf(buf + n, bufsz - n, "\nWEIGHT: |");
745 	if (n >= bufsz)
746 		return;
747 	for (i = 0; i < num; i++) {
748 		n += snprintf(buf + n, bufsz - n, "0x%-2X|",
749 			      p_vla_tbl->vl_entry[i].weight);
750 		if (n >= bufsz)
751 			return;
752 	}
753 
754 	snprintf(buf + n, bufsz - n, "\n");
755 }
756 
757 static int _dump_fields(char *buf, int bufsz, void *data, int start, int end)
758 {
759 	char val[64];
760 	char *s = buf;
761 	int n, field;
762 
763 	for (field = start; field < end && bufsz > 0; field++) {
764 		mad_decode_field(data, field, val);
765 		if (!mad_dump_field(field, s, bufsz-1, val))
766 			return -1;
767 		n = strlen(s);
768 		s += n;
769 		*s++ = '\n';
770 		*s = 0;
771 		n++;
772 		bufsz -= n;
773 	}
774 
775 	return (int)(s - buf);
776 }
777 
778 void mad_dump_fields(char *buf, int bufsz, void *val, int valsz, int start,
779 		     int end)
780 {
781 	_dump_fields(buf, bufsz, val, start, end);
782 }
783 
784 void mad_dump_nodedesc(char *buf, int bufsz, void *val, int valsz)
785 {
786 	strncpy(buf, val, bufsz);
787 
788 	if (valsz < bufsz)
789 		buf[valsz] = 0;
790 }
791 
792 void mad_dump_nodeinfo(char *buf, int bufsz, void *val, int valsz)
793 {
794 	_dump_fields(buf, bufsz, val, IB_NODE_FIRST_F, IB_NODE_LAST_F);
795 }
796 
797 void mad_dump_portinfo(char *buf, int bufsz, void *val, int valsz)
798 {
799 	int cnt;
800 
801 	cnt = _dump_fields(buf, bufsz, val, IB_PORT_FIRST_F, IB_PORT_LAST_F);
802 	if (cnt < 0)
803 		return;
804 
805 	_dump_fields(buf + cnt, bufsz - cnt, val,
806 		     IB_PORT_CAPMASK2_F, IB_PORT_LINK_SPEED_EXT_LAST_F);
807 }
808 
809 void mad_dump_portstates(char *buf, int bufsz, void *val, int valsz)
810 {
811 	_dump_fields(buf, bufsz, val, IB_PORT_STATE_F, IB_PORT_LINK_DOWN_DEF_F);
812 }
813 
814 void mad_dump_switchinfo(char *buf, int bufsz, void *val, int valsz)
815 {
816 	_dump_fields(buf, bufsz, val, IB_SW_FIRST_F, IB_SW_LAST_F);
817 }
818 
819 void mad_dump_perfcounters(char *buf, int bufsz, void *val, int valsz)
820 {
821 	int cnt, cnt2;
822 
823 	cnt = _dump_fields(buf, bufsz, val,
824 			   IB_PC_FIRST_F, IB_PC_VL15_DROPPED_F);
825 	if (cnt < 0)
826 		return;
827 
828 	cnt2 = _dump_fields(buf + cnt, bufsz - cnt, val,
829 			    IB_PC_QP1_DROP_F, IB_PC_QP1_DROP_F + 1);
830 	if (cnt2 < 0)
831 		return;
832 
833 	_dump_fields(buf + cnt + cnt2, bufsz - cnt - cnt2, val,
834 		     IB_PC_VL15_DROPPED_F, IB_PC_LAST_F);
835 }
836 
837 void mad_dump_perfcounters_ext(char *buf, int bufsz, void *val, int valsz)
838 {
839 	int cnt;
840 
841 	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_FIRST_F, IB_PC_EXT_LAST_F);
842 	if (cnt < 0)
843 		return;
844 
845 	 _dump_fields(buf + cnt, bufsz - cnt, val,
846 		      IB_PC_EXT_COUNTER_SELECT2_F, IB_PC_EXT_ERR_LAST_F);
847 }
848 
849 void mad_dump_perfcounters_xmt_sl(char *buf, int bufsz, void *val, int valsz)
850 {
851 	int cnt;
852 
853 	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
854 			   IB_PC_EXT_XMT_BYTES_F);
855 	if (cnt < 0)
856 		return;
857 
858 	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_XMT_DATA_SL_FIRST_F,
859 		     IB_PC_XMT_DATA_SL_LAST_F);
860 }
861 
862 void mad_dump_perfcounters_rcv_sl(char *buf, int bufsz, void *val, int valsz)
863 {
864 	int cnt;
865 
866 	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
867 			   IB_PC_EXT_XMT_BYTES_F);
868 	if (cnt < 0)
869 		return;
870 
871 	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_RCV_DATA_SL_FIRST_F,
872 		     IB_PC_RCV_DATA_SL_LAST_F);
873 }
874 
875 void mad_dump_perfcounters_xmt_disc(char *buf, int bufsz, void *val, int valsz)
876 {
877 	int cnt;
878 
879 	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
880 			   IB_PC_EXT_XMT_BYTES_F);
881 	if (cnt < 0)
882 		return;
883 
884 	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_XMT_INACT_DISC_F,
885 		     IB_PC_XMT_DISC_LAST_F);
886 }
887 
888 void mad_dump_perfcounters_rcv_err(char *buf, int bufsz, void *val, int valsz)
889 {
890 	int cnt;
891 
892 	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
893 			   IB_PC_EXT_XMT_BYTES_F);
894 	if (cnt < 0)
895 		return;
896 
897 	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_RCV_LOCAL_PHY_ERR_F,
898 		     IB_PC_RCV_ERR_LAST_F);
899 }
900 
901 void mad_dump_portsamples_control(char *buf, int bufsz, void *val, int valsz)
902 {
903 	_dump_fields(buf, bufsz, val, IB_PSC_OPCODE_F, IB_PSC_LAST_F);
904 }
905 
906 void mad_dump_port_ext_speeds_counters_rsfec_active(char *buf, int bufsz,
907 						    void *val, int valsz)
908 {
909 	_dump_fields(buf, bufsz, val, IB_PESC_RSFEC_PORT_SELECT_F,
910 		     IB_PESC_RSFEC_LAST_F);
911 }
912 
913 void mad_dump_port_ext_speeds_counters(char *buf, int bufsz, void *val, int valsz)
914 {
915 	_dump_fields(buf, bufsz, val, IB_PESC_PORT_SELECT_F, IB_PESC_LAST_F);
916 }
917 
918 void mad_dump_perfcounters_port_op_rcv_counters(char *buf, int bufsz, void *val, int valsz)
919 {
920 	int cnt;
921 
922 	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
923 			   IB_PC_EXT_XMT_BYTES_F);
924 	if (cnt < 0)
925 		return;
926 
927 	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_PORT_OP_RCV_COUNTERS_FIRST_F,
928 		     IB_PC_PORT_OP_RCV_COUNTERS_LAST_F);
929 }
930 
931 void mad_dump_perfcounters_port_flow_ctl_counters(char *buf, int bufsz, void *val, int valsz)
932 {
933 	int cnt;
934 
935 	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
936 			   IB_PC_EXT_XMT_BYTES_F);
937 	if (cnt < 0)
938 		return;
939 
940 	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_PORT_FLOW_CTL_COUNTERS_FIRST_F,
941 		     IB_PC_PORT_FLOW_CTL_COUNTERS_LAST_F);
942 }
943 
944 void mad_dump_perfcounters_port_vl_op_packet(char *buf, int bufsz, void *val, int valsz)
945 {
946 	int cnt;
947 
948 	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
949 			   IB_PC_EXT_XMT_BYTES_F);
950 	if (cnt < 0)
951 		return;
952 
953 	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_PORT_VL_OP_PACKETS_FIRST_F,
954 		     IB_PC_PORT_VL_OP_PACKETS_LAST_F);
955 }
956 
957 void mad_dump_perfcounters_port_vl_op_data(char *buf, int bufsz, void *val, int valsz)
958 {
959 	int cnt;
960 
961 	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
962 			   IB_PC_EXT_XMT_BYTES_F);
963 	if (cnt < 0)
964 		return;
965 
966 	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_PORT_VL_OP_DATA_FIRST_F,
967 		     IB_PC_PORT_VL_OP_DATA_LAST_F);
968 }
969 
970 void mad_dump_perfcounters_port_vl_xmit_flow_ctl_update_errors(char *buf, int bufsz, void *val, int valsz)
971 {
972 	int cnt;
973 
974 	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
975 			   IB_PC_EXT_XMT_BYTES_F);
976 	if (cnt < 0)
977 		return;
978 
979 	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS_FIRST_F,
980 		     IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS_LAST_F);
981 }
982 
983 void mad_dump_perfcounters_port_vl_xmit_wait_counters(char *buf, int bufsz, void *val, int valsz)
984 {
985 	int cnt;
986 
987 	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
988 			   IB_PC_EXT_XMT_BYTES_F);
989 	if (cnt < 0)
990 		return;
991 
992 	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_PORT_VL_XMIT_WAIT_COUNTERS_FIRST_F,
993 		     IB_PC_PORT_VL_XMIT_WAIT_COUNTERS_LAST_F);
994 }
995 
996 void mad_dump_perfcounters_sw_port_vl_congestion(char *buf, int bufsz, void *val, int valsz)
997 {
998 	int cnt;
999 
1000 	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
1001 			   IB_PC_EXT_XMT_BYTES_F);
1002 	if (cnt < 0)
1003 		return;
1004 
1005 	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_SW_PORT_VL_CONGESTION_FIRST_F,
1006 		     IB_PC_SW_PORT_VL_CONGESTION_LAST_F);
1007 }
1008 
1009 void mad_dump_perfcounters_rcv_con_ctrl(char *buf, int bufsz, void *val, int valsz)
1010 {
1011 	int cnt;
1012 
1013 	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
1014 			   IB_PC_EXT_XMT_BYTES_F);
1015 	if (cnt < 0)
1016 		return;
1017 
1018 	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_RCV_CON_CTRL_FIRST_F,
1019 		     IB_PC_RCV_CON_CTRL_LAST_F);
1020 }
1021 
1022 
1023 void mad_dump_perfcounters_sl_rcv_fecn(char *buf, int bufsz, void *val, int valsz)
1024 {
1025 	int cnt;
1026 
1027 	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
1028 			   IB_PC_EXT_XMT_BYTES_F);
1029 	if (cnt < 0)
1030 		return;
1031 
1032 	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_SL_RCV_FECN_FIRST_F,
1033 		     IB_PC_SL_RCV_FECN_LAST_F);
1034 }
1035 
1036 void mad_dump_perfcounters_sl_rcv_becn(char *buf, int bufsz, void *val, int valsz)
1037 {
1038 	int cnt;
1039 
1040 	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
1041 			   IB_PC_EXT_XMT_BYTES_F);
1042 	if (cnt < 0)
1043 		return;
1044 
1045 	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_SL_RCV_BECN_FIRST_F,
1046 		     IB_PC_SL_RCV_BECN_LAST_F);
1047 }
1048 
1049 void mad_dump_perfcounters_xmit_con_ctrl(char *buf, int bufsz, void *val, int valsz)
1050 {
1051 	int cnt;
1052 
1053 	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
1054 			   IB_PC_EXT_XMT_BYTES_F);
1055 	if (cnt < 0)
1056 		return;
1057 
1058 	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_XMIT_CON_CTRL_FIRST_F,
1059 		     IB_PC_XMIT_CON_CTRL_LAST_F);
1060 }
1061 
1062 void mad_dump_perfcounters_vl_xmit_time_cong(char *buf, int bufsz, void *val, int valsz)
1063 {
1064 	int cnt;
1065 
1066 	cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
1067 			   IB_PC_EXT_XMT_BYTES_F);
1068 	if (cnt < 0)
1069 		return;
1070 
1071 	_dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_VL_XMIT_TIME_CONG_FIRST_F,
1072 		     IB_PC_VL_XMIT_TIME_CONG_LAST_F);
1073 }
1074 
1075 void mad_dump_mlnx_ext_port_info(char *buf, int bufsz, void *val, int valsz)
1076 {
1077 	_dump_fields(buf, bufsz, val, IB_MLNX_EXT_PORT_STATE_CHG_ENABLE_F,
1078 		     IB_MLNX_EXT_PORT_LAST_F);
1079 }
1080 
1081 void mad_dump_portsamples_result(char *buf, int bufsz, void *val, int valsz)
1082 {
1083 	_dump_fields(buf, bufsz, val, IB_PSR_TAG_F, IB_PSR_LAST_F);
1084 }
1085 
1086 void mad_dump_cc_congestioninfo(char *buf, int bufsz, void *val, int valsz)
1087 {
1088 	_dump_fields(buf, bufsz, val, IB_CC_CONGESTION_INFO_FIRST_F,
1089 		     IB_CC_CONGESTION_INFO_LAST_F);
1090 }
1091 
1092 void mad_dump_cc_congestionkeyinfo(char *buf, int bufsz, void *val, int valsz)
1093 {
1094 	_dump_fields(buf, bufsz, val, IB_CC_CONGESTION_KEY_INFO_FIRST_F,
1095 		     IB_CC_CONGESTION_KEY_INFO_LAST_F);
1096 }
1097 
1098 void mad_dump_cc_congestionlog(char *buf, int bufsz, void *val, int valsz)
1099 {
1100 	_dump_fields(buf, bufsz, val, IB_CC_CONGESTION_LOG_FIRST_F,
1101 		     IB_CC_CONGESTION_LOG_LAST_F);
1102 }
1103 
1104 void mad_dump_cc_congestionlogswitch(char *buf, int bufsz, void *val, int valsz)
1105 {
1106 	_dump_fields(buf, bufsz, val, IB_CC_CONGESTION_LOG_SWITCH_FIRST_F,
1107 		     IB_CC_CONGESTION_LOG_SWITCH_LAST_F);
1108 }
1109 
1110 void mad_dump_cc_congestionlogentryswitch(char *buf, int bufsz, void *val, int valsz)
1111 {
1112 	_dump_fields(buf, bufsz, val, IB_CC_CONGESTION_LOG_ENTRY_SWITCH_FIRST_F,
1113 		     IB_CC_CONGESTION_LOG_ENTRY_SWITCH_LAST_F);
1114 }
1115 
1116 void mad_dump_cc_congestionlogca(char *buf, int bufsz, void *val, int valsz)
1117 {
1118 	_dump_fields(buf, bufsz, val, IB_CC_CONGESTION_LOG_CA_FIRST_F,
1119 		     IB_CC_CONGESTION_LOG_CA_LAST_F);
1120 }
1121 
1122 void mad_dump_cc_congestionlogentryca(char *buf, int bufsz, void *val, int valsz)
1123 {
1124 	_dump_fields(buf, bufsz, val, IB_CC_CONGESTION_LOG_ENTRY_CA_FIRST_F,
1125 		     IB_CC_CONGESTION_LOG_ENTRY_CA_LAST_F);
1126 }
1127 
1128 void mad_dump_cc_switchcongestionsetting(char *buf, int bufsz, void *val, int valsz)
1129 {
1130 	_dump_fields(buf, bufsz, val, IB_CC_SWITCH_CONGESTION_SETTING_FIRST_F,
1131 		     IB_CC_SWITCH_CONGESTION_SETTING_LAST_F);
1132 }
1133 
1134 void mad_dump_cc_switchportcongestionsettingelement(char *buf, int bufsz, void *val, int valsz)
1135 {
1136 	_dump_fields(buf, bufsz, val, IB_CC_SWITCH_PORT_CONGESTION_SETTING_ELEMENT_FIRST_F,
1137 		     IB_CC_SWITCH_PORT_CONGESTION_SETTING_ELEMENT_LAST_F);
1138 }
1139 
1140 void mad_dump_cc_cacongestionsetting(char *buf, int bufsz, void *val, int valsz)
1141 {
1142 	_dump_fields(buf, bufsz, val, IB_CC_CA_CONGESTION_SETTING_FIRST_F,
1143 		     IB_CC_CA_CONGESTION_SETTING_LAST_F);
1144 }
1145 
1146 void mad_dump_cc_cacongestionentry(char *buf, int bufsz, void *val, int valsz)
1147 {
1148 	_dump_fields(buf, bufsz, val, IB_CC_CA_CONGESTION_ENTRY_FIRST_F,
1149 		     IB_CC_CA_CONGESTION_ENTRY_LAST_F);
1150 }
1151 
1152 void mad_dump_cc_congestioncontroltable(char *buf, int bufsz, void *val, int valsz)
1153 {
1154 	_dump_fields(buf, bufsz, val, IB_CC_CONGESTION_CONTROL_TABLE_FIRST_F,
1155 		     IB_CC_CONGESTION_CONTROL_TABLE_LAST_F);
1156 }
1157 
1158 void mad_dump_cc_congestioncontroltableentry(char *buf, int bufsz, void *val, int valsz)
1159 {
1160 	_dump_fields(buf, bufsz, val, IB_CC_CONGESTION_CONTROL_TABLE_ENTRY_FIRST_F,
1161 		     IB_CC_CONGESTION_CONTROL_TABLE_ENTRY_LAST_F);
1162 }
1163 
1164 void mad_dump_cc_timestamp(char *buf, int bufsz, void *val, int valsz)
1165 {
1166 	_dump_fields(buf, bufsz, val, IB_CC_TIMESTAMP_FIRST_F,
1167 		     IB_CC_TIMESTAMP_LAST_F);
1168 }
1169 
1170 void mad_dump_classportinfo(char *buf, int bufsz, void *val, int valsz)
1171 {
1172 	/* no FIRST_F and LAST_F for CPI field enums, must do a hack */
1173 	_dump_fields(buf, bufsz, val, IB_CPI_BASEVER_F, IB_CPI_TRAP_QKEY_F + 1);
1174 }
1175 
1176 void mad_dump_portmirror_route(char *buf, int bufsz, void *val, int valsz)
1177 {
1178 	_dump_fields(buf, bufsz, val, IB_PMR_FIRST_F, IB_PMR_LAST_F);
1179 }
1180 
1181 void mad_dump_portmirror_filter(char *buf, int bufsz, void *val, int valsz)
1182 {
1183 	_dump_fields(buf, bufsz, val, IB_PMF_FIRST_F, IB_PMF_LAST_F);
1184 }
1185 
1186 void mad_dump_portmirror_ports(char *buf, int bufsz, void *val, int valsz)
1187 {
1188 	_dump_fields(buf, bufsz, val, IB_PMP_FIRST_F, IB_PMP_LAST_F);
1189 }
1190 
1191 void mad_dump_portinfo_ext(char *buf, int bufsz, void *val, int valsz)
1192 {
1193 	_dump_fields(buf, bufsz, val, IB_PORT_EXT_CAPMASK_F,
1194 		     IB_PORT_EXT_LAST_F);
1195 }
1196 
1197 void xdump(FILE * file, char *msg, void *p, int size)
1198 {
1199 #define HEX(x)  ((x) < 10 ? '0' + (x) : 'a' + ((x) -10))
1200 	uint8_t *cp = p;
1201 	int i;
1202 
1203 	if (msg)
1204 		fputs(msg, file);
1205 
1206 	for (i = 0; i < size;) {
1207 		fputc(HEX(*cp >> 4), file);
1208 		fputc(HEX(*cp & 0xf), file);
1209 		if (++i >= size)
1210 			break;
1211 		fputc(HEX(cp[1] >> 4), file);
1212 		fputc(HEX(cp[1] & 0xf), file);
1213 		if ((++i) % 16)
1214 			fputc(' ', file);
1215 		else
1216 			fputc('\n', file);
1217 		cp += 2;
1218 	}
1219 	if (i % 16)
1220 		fputc('\n', file);
1221 }
1222