libibmad: updated based on merge feedback
[mirror/winof/.git] / ulp / libibmad / src / dump.c
1 /*
2  * Copyright (c) 2004-2008 Voltaire Inc.  All rights reserved.
3  * Copyright (c) 2007 Xsigo Systems Inc.  All rights reserved.
4  *
5  * This software is available to you under a choice of one of two
6  * licenses.  You may choose to be licensed under the terms of the GNU
7  * General Public License (GPL) Version 2, available from the file
8  * COPYING in the main directory of this source tree, or the
9  * OpenIB.org BSD license below:
10  *
11  *     Redistribution and use in source and binary forms, with or
12  *     without modification, are permitted provided that the following
13  *     conditions are met:
14  *
15  *      - Redistributions of source code must retain the above
16  *        copyright notice, this list of conditions and the following
17  *        disclaimer.
18  *
19  *      - Redistributions in binary form must reproduce the above
20  *        copyright notice, this list of conditions and the following
21  *        disclaimer in the documentation and/or other materials
22  *        provided with the distribution.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31  * SOFTWARE.
32  *
33  */
34
35 #if HAVE_CONFIG_H
36 #  include <config.h>
37 #endif /* HAVE_CONFIG_H */
38
39 #include <mad.h>
40
41 void
42 mad_dump_int(char *buf, int bufsz, void *val, int valsz)
43 {
44         switch (valsz) {
45         case 1:
46                 snprintf(buf, bufsz, "%d", *(uint8_t *)val);
47                 break;
48         case 2:
49                 snprintf(buf, bufsz, "%d", *(uint16_t *)val);
50                 break;
51         case 3:
52         case 4:
53                 snprintf(buf, bufsz, "%d", *(uint32_t *)val);
54                 break;
55         case 5:
56         case 6:
57         case 7:
58         case 8:
59                 snprintf(buf, bufsz, "%" PRIu64, *(uint64_t *)val);
60                 break;
61         default:
62                 IBWARN("bad int sz %d", valsz);
63                 buf[0] = 0;
64         }
65 }
66
67 void
68 mad_dump_uint(char *buf, int bufsz, void *val, int valsz)
69 {
70         switch (valsz) {
71         case 1:
72                 snprintf(buf, bufsz, "%u", *(uint8_t *)val);
73                 break;
74         case 2:
75                 snprintf(buf, bufsz, "%u", *(uint16_t *)val);
76                 break;
77         case 3:
78         case 4:
79                 snprintf(buf, bufsz, "%u", *(uint32_t *)val);
80                 break;
81         case 5:
82         case 6:
83         case 7:
84         case 8:
85                 snprintf(buf, bufsz, "%" PRIu64, *(uint64_t *)val);
86                 break;
87         default:
88                 IBWARN("bad int sz %u", valsz);
89                 buf[0] = 0;
90         }
91 }
92
93 void
94 mad_dump_hex(char *buf, int bufsz, void *val, int valsz)
95 {
96         switch (valsz) {
97         case 1:
98                 snprintf(buf, bufsz, "0x%02x", *(uint8_t *)val);
99                 break;
100         case 2:
101                 snprintf(buf, bufsz, "0x%04x", *(uint16_t *)val);
102                 break;
103         case 3:
104                 snprintf(buf, bufsz, "0x%06x", *(uint32_t *)val & 0xffffff);
105                 break;
106         case 4:
107                 snprintf(buf, bufsz, "0x%08x", *(uint32_t *)val);
108                 break;
109         case 5:
110                 snprintf(buf, bufsz, "0x%010" PRIx64, *(uint64_t *)val & (uint64_t) 0xffffffffffULL);
111                 break;
112         case 6:
113                 snprintf(buf, bufsz, "0x%012" PRIx64, *(uint64_t *)val & (uint64_t) 0xffffffffffffULL);
114                 break;
115         case 7:
116                 snprintf(buf, bufsz, "0x%014" PRIx64, *(uint64_t *)val & (uint64_t) 0xffffffffffffffULL);
117                 break;
118         case 8:
119                 snprintf(buf, bufsz, "0x%016" PRIx64, *(uint64_t *)val);
120                 break;
121         default:
122                 IBWARN("bad int sz %d", valsz);
123                 buf[0] = 0;
124         }
125 }
126
127 void
128 mad_dump_rhex(char *buf, int bufsz, void *val, int valsz)
129 {
130         switch (valsz) {
131         case 1:
132                 snprintf(buf, bufsz, "%02x", *(uint8_t *)val);
133                 break;
134         case 2:
135                 snprintf(buf, bufsz, "%04x", *(uint16_t *)val);
136                 break;
137         case 3:
138                 snprintf(buf, bufsz, "%06x", *(uint32_t *)val & 0xffffff);
139                 break;
140         case 4:
141                 snprintf(buf, bufsz, "%08x", *(uint32_t *)val);
142                 break;
143         case 5:
144                 snprintf(buf, bufsz, "%010" PRIx64, *(uint64_t *)val & (uint64_t) 0xffffffffffULL);
145                 break;
146         case 6:
147                 snprintf(buf, bufsz, "%012" PRIx64, *(uint64_t *)val & (uint64_t) 0xffffffffffffULL);
148                 break;
149         case 7:
150                 snprintf(buf, bufsz, "%014" PRIx64, *(uint64_t *)val & (uint64_t) 0xffffffffffffffULL);
151                 break;
152         case 8:
153                 snprintf(buf, bufsz, "%016" PRIx64, *(uint64_t *)val);
154                 break;
155         default:
156                 IBWARN("bad int sz %d", valsz);
157                 buf[0] = 0;
158         }
159 }
160
161 void
162 mad_dump_linkwidth(char *buf, int bufsz, void *val, int valsz)
163 {
164         int width = *(int *)val;
165
166         switch (width) {
167         case 1:
168                 snprintf(buf, bufsz, "1X");
169                 break;
170         case 2:
171                 snprintf(buf, bufsz, "4X");
172                 break;
173         case 4:
174                 snprintf(buf, bufsz, "8X");
175                 break;
176         case 8:
177                 snprintf(buf, bufsz, "12X");
178                 break;
179         default:
180                 IBWARN("bad width %d", width);
181                 buf[0] = 0;
182         }
183 }
184
185 static void
186 dump_linkwidth(char *buf, int bufsz, int width)
187 {
188         int n = 0;
189
190         if (width & 0x1)
191                 n += snprintf(buf + n, bufsz - n, "1X or ");
192         if (n < bufsz && (width & 0x2))
193                 n += snprintf(buf + n, bufsz - n, "4X or ");
194         if (n < bufsz && (width & 0x4))
195                 n += snprintf(buf + n, bufsz - n, "8X or ");
196         if (n < bufsz && (width & 0x8))
197                 n += snprintf(buf + n, bufsz - n, "12X or ");
198
199         if (n >= bufsz)
200                 return;
201         else if (width == 0 || (width >> 4))
202                 snprintf(buf + n, bufsz - n, "undefined (%d)", width);
203         else if (bufsz > 3)
204                 buf[n-4] = '\0';
205 }
206
207 void
208 mad_dump_linkwidthsup(char *buf, int bufsz, void *val, int valsz)
209 {
210         int width = *(int *)val;
211
212         dump_linkwidth(buf, bufsz, width);
213
214         switch(width) {
215         case 1:
216         case 3:
217         case 7:
218         case 11:
219         case 15:
220                 break;
221
222         default:
223                 if (!(width >> 4))
224                         snprintf(buf + strlen(buf), bufsz - strlen(buf),
225                                  " (IBA extension)");
226                 break;
227         }
228 }
229
230 void
231 mad_dump_linkwidthen(char *buf, int bufsz, void *val, int valsz)
232 {
233         int width = *(int *)val;
234
235         dump_linkwidth(buf, bufsz, width);
236 }
237
238 void
239 mad_dump_linkspeed(char *buf, int bufsz, void *val, int valsz)
240 {
241         int speed = *(int *)val;
242
243         switch (speed) {
244         case 1:
245                 snprintf(buf, bufsz, "2.5 Gbps");
246                 break;
247         case 2:
248                 snprintf(buf, bufsz, "5.0 Gbps");
249                 break;
250         case 4:
251                 snprintf(buf, bufsz, "10.0 Gbps");
252                 break;
253         default:
254                 snprintf(buf, bufsz, "undefined (%d)", speed);
255                 break;
256         }
257 }
258
259 static void
260 dump_linkspeed(char *buf, int bufsz, int speed)
261 {
262         int n = 0;
263
264         if (speed & 0x1)
265                 n += snprintf(buf + n, bufsz - n, "2.5 Gbps or ");
266         if (n < bufsz && (speed & 0x2))
267                 n += snprintf(buf + n, bufsz - n, "5.0 Gbps or ");
268         if (n < bufsz && (speed & 0x4))
269                 n += snprintf(buf + n, bufsz - n, "10.0 Gbps or ");
270
271         if (n >= bufsz)
272                 return;
273         else if (speed == 0 || (speed >> 3)) {
274                 n += snprintf(buf + n, bufsz - n, "undefined (%d)", speed);
275                 if (n >= bufsz)
276                         return;
277         } else if (bufsz > 3) {
278                 buf[n-4] = '\0';
279                 n -= 4;
280         }
281
282         switch (speed) {
283         case 1:
284         case 3:
285         case 5:
286         case 7:
287                 break;
288         default:
289                 if (!(speed >> 3))
290                         snprintf(buf + n, bufsz - n, " (IBA extension)");
291                 break;
292         }
293 }
294
295 void
296 mad_dump_linkspeedsup(char *buf, int bufsz, void *val, int valsz)
297 {
298         int speed = *(int *)val;
299
300         dump_linkspeed(buf, bufsz, speed);
301 }
302
303 void
304 mad_dump_linkspeeden(char *buf, int bufsz, void *val, int valsz)
305 {
306         int speed = *(int *)val;
307
308         dump_linkspeed(buf, bufsz, speed);
309 }
310
311 void
312 mad_dump_portstate(char *buf, int bufsz, void *val, int valsz)
313 {
314         int state = *(int *)val;
315
316         switch (state) {
317         case 0:
318                 snprintf(buf, bufsz, "NoChange");
319                 break;
320         case 1:
321                 snprintf(buf, bufsz, "Down");
322                 break;
323         case 2:
324                 snprintf(buf, bufsz, "Initialize");
325                 break;
326         case 3:
327                 snprintf(buf, bufsz, "Armed");
328                 break;
329         case 4:
330                 snprintf(buf, bufsz, "Active");
331                 break;
332         default:
333                 snprintf(buf, bufsz, "?(%d)", state);
334         }
335 }
336
337 void
338 mad_dump_linkdowndefstate(char *buf, int bufsz, void *val, int valsz)
339 {
340         int state = *(int *)val;
341
342         switch(state) {
343         case 0:
344                 snprintf(buf, bufsz, "NoChange");
345                 break;
346         case 1:
347                 snprintf(buf, bufsz, "Sleep");
348                 break;
349         case 2:
350                 snprintf(buf, bufsz, "Polling");
351                 break;
352         default:
353                 snprintf(buf, bufsz, "?(%d)", state);
354                 break;
355         }
356 }
357
358 void
359 mad_dump_physportstate(char *buf, int bufsz, void *val, int valsz)
360 {
361         int state = *(int *)val;
362
363         switch (state) {
364         case 0:
365                 snprintf(buf, bufsz, "NoChange");
366                 break;
367         case 1:
368                 snprintf(buf, bufsz, "Sleep");
369                 break;
370         case 2:
371                 snprintf(buf, bufsz, "Polling");
372                 break;
373         case 3:
374                 snprintf(buf, bufsz, "Disabled");
375                 break;
376         case 4:
377                 snprintf(buf, bufsz, "PortConfigurationTraining");
378                 break;
379         case 5:
380                 snprintf(buf, bufsz, "LinkUp");
381                 break;
382         case 6:
383                 snprintf(buf, bufsz, "LinkErrorRecovery");
384                 break;
385         case 7:
386                 snprintf(buf, bufsz, "PhyTest");
387                 break;
388         default:
389                 snprintf(buf, bufsz, "?(%d)", state);
390         }
391 }
392
393 void
394 mad_dump_mtu(char *buf, int bufsz, void *val, int valsz)
395 {
396         int mtu = *(int *)val;
397
398         switch (mtu) {
399         case 1:
400                 snprintf(buf, bufsz, "256");
401                 break;
402         case 2:
403                 snprintf(buf, bufsz, "512");
404                 break;
405         case 3:
406                 snprintf(buf, bufsz, "1024");
407                 break;
408         case 4:
409                 snprintf(buf, bufsz, "2048");
410                 break;
411         case 5:
412                 snprintf(buf, bufsz, "4096");
413                 break;
414         default:
415                 snprintf(buf, bufsz, "?(%d)", mtu);
416                 buf[0] = 0;
417         }
418 }
419
420 void
421 mad_dump_vlcap(char *buf, int bufsz, void *val, int valsz)
422 {
423         int vlcap = *(int *)val;
424
425         switch (vlcap) {
426         case 1:
427                 snprintf(buf, bufsz, "VL0");
428                 break;
429         case 2:
430                 snprintf(buf, bufsz, "VL0-1");
431                 break;
432         case 3:
433                 snprintf(buf, bufsz, "VL0-3");
434                 break;
435         case 4:
436                 snprintf(buf, bufsz, "VL0-7");
437                 break;
438         case 5:
439                 snprintf(buf, bufsz, "VL0-14");
440                 break;
441         default:
442                 snprintf(buf, bufsz, "?(%d)", vlcap);
443         }
444 }
445
446 void
447 mad_dump_opervls(char *buf, int bufsz, void *val, int valsz)
448 {
449         int opervls = *(int *)val;
450
451         switch (opervls) {
452         case 0:
453                 snprintf(buf, bufsz, "No change");
454                 break;
455         case 1:
456                 snprintf(buf, bufsz, "VL0");
457                 break;
458         case 2:
459                 snprintf(buf, bufsz, "VL0-1");
460                 break;
461         case 3:
462                 snprintf(buf, bufsz, "VL0-3");
463                 break;
464         case 4:
465                 snprintf(buf, bufsz, "VL0-7");
466                 break;
467         case 5:
468                 snprintf(buf, bufsz, "VL0-14");
469                 break;
470         default:
471                 snprintf(buf, bufsz, "?(%d)", opervls);
472         }
473 }
474
475 void
476 mad_dump_portcapmask(char *buf, int bufsz, void *val, int valsz)
477 {
478         unsigned mask = *(unsigned *)val;
479         char *s = buf;
480
481         s += sprintf(s, "0x%x\n", mask);
482         if (mask & (1 << 1))
483                 s += sprintf(s, "\t\t\t\tIsSM\n");
484         if (mask & (1 << 2))
485                 s += sprintf(s, "\t\t\t\tIsNoticeSupported\n");
486         if (mask & (1 << 3))
487                 s += sprintf(s, "\t\t\t\tIsTrapSupported\n");
488         if (mask & (1 << 5))
489                 s += sprintf(s, "\t\t\t\tIsAutomaticMigrationSupported\n");
490         if (mask & (1 << 6))
491                 s += sprintf(s, "\t\t\t\tIsSLMappingSupported\n");
492         if (mask & (1 << 7))
493                 s += sprintf(s, "\t\t\t\tIsMKeyNVRAM\n");
494         if (mask & (1 << 8))
495                 s += sprintf(s, "\t\t\t\tIsPKeyNVRAM\n");
496         if (mask & (1 << 9))
497                 s += sprintf(s, "\t\t\t\tIsLedInfoSupported\n");
498         if (mask & (1 << 10))
499                 s += sprintf(s, "\t\t\t\tIsSMdisabled\n");
500         if (mask & (1 << 11))
501                 s += sprintf(s, "\t\t\t\tIsSystemImageGUIDsupported\n");
502         if (mask & (1 << 12))
503                 s += sprintf(s, "\t\t\t\tIsPkeySwitchExternalPortTrapSupported\n");
504         if (mask & (1 << 16))
505                 s += sprintf(s, "\t\t\t\tIsCommunicatonManagementSupported\n");
506         if (mask & (1 << 17))
507                 s += sprintf(s, "\t\t\t\tIsSNMPTunnelingSupported\n");
508         if (mask & (1 << 18))
509                 s += sprintf(s, "\t\t\t\tIsReinitSupported\n");
510         if (mask & (1 << 19))
511                 s += sprintf(s, "\t\t\t\tIsDeviceManagementSupported\n");
512         if (mask & (1 << 20))
513                 s += sprintf(s, "\t\t\t\tIsVendorClassSupported\n");
514         if (mask & (1 << 21))
515                 s += sprintf(s, "\t\t\t\tIsDRNoticeSupported\n");
516         if (mask & (1 << 22))
517                 s += sprintf(s, "\t\t\t\tIsCapabilityMaskNoticeSupported\n");
518         if (mask & (1 << 23))
519                 s += sprintf(s, "\t\t\t\tIsBootManagementSupported\n");
520         if (mask & (1 << 24))
521                 s += sprintf(s, "\t\t\t\tIsLinkRoundTripLatencySupported\n");
522         if (mask & (1 << 25))
523                 s += sprintf(s, "\t\t\t\tIsClientRegistrationSupported\n");
524         if (mask & (1 << 26))
525                 s += sprintf(s, "\t\t\t\tIsOtherLocalChangesNoticeSupported\n");
526         if (mask & (1 << 27))
527                 s += sprintf(s, "\t\t\t\tIsLinkSpeedWidthPairsTableSupported\n");
528
529         if (s != buf)
530                 *(--s) = 0;
531 }
532
533 void
534 mad_dump_bitfield(char *buf, int bufsz, void *val, int valsz)
535 {
536         snprintf(buf, bufsz, "0x%x", *(uint32_t *)val);
537 }
538
539 void
540 mad_dump_array(char *buf, int bufsz, void *val, int valsz)
541 {
542         uint8_t *p = val, *e;
543         char *s = buf;
544
545         if (bufsz < valsz*2)
546                 valsz = bufsz/2;
547
548         for (p = val, e = p + valsz; p < e; p++, s += 2)
549                 sprintf(s, "%02x", *p);
550 }
551
552 void
553 mad_dump_string(char *buf, int bufsz, void *val, int valsz)
554 {
555         if (bufsz < valsz)
556                 valsz = bufsz;
557
558         snprintf(buf, valsz, "'%s'", (char *)val);
559 }
560
561 void
562 mad_dump_node_type(char *buf, int bufsz, void *val, int valsz)
563 {
564         int nodetype = *(int*)val;
565
566         switch (nodetype) {
567         case 1:
568                 snprintf(buf, bufsz, "Channel Adapter");
569                 break;
570         case 2:
571                 snprintf(buf, bufsz, "Switch");
572                 break;
573         case 3:
574                 snprintf(buf, bufsz, "Router");
575                 break;
576         default:
577                 snprintf(buf, bufsz, "?(%d)?", nodetype);
578                 break;
579         }
580 }
581
582 #define IB_MAX_NUM_VLS 16
583 #define IB_MAX_NUM_VLS_TO_U8 ((IB_MAX_NUM_VLS)/2)
584
585 typedef struct _ib_slvl_table {
586         uint8_t vl_by_sl_num[IB_MAX_NUM_VLS_TO_U8];
587 } ib_slvl_table_t;
588
589 static inline void
590 ib_slvl_get_i(ib_slvl_table_t *tbl, int i, uint8_t *vl)
591 {
592         *vl = (tbl->vl_by_sl_num[i >> 1] >> ((!(i&1)) << 2)) & 0xf;
593 }
594
595 #define IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK 32
596
597 typedef struct _ib_vl_arb_table {
598         struct {
599                 uint8_t res_vl;
600                 uint8_t weight;
601         } vl_entry[IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK];
602 } ib_vl_arb_table_t;
603
604 static inline void
605 ib_vl_arb_get_vl(uint8_t res_vl, uint8_t *const vl )
606 {
607         *vl = res_vl & 0x0F;
608 }
609
610 void
611 mad_dump_sltovl(char *buf, int bufsz, void *val, int valsz)
612 {
613         ib_slvl_table_t* p_slvl_tbl = val;
614         uint8_t vl;
615         int i, n = 0;
616         n = snprintf(buf, bufsz, "|");
617         for (i = 0; i < 16; i++) {
618                 ib_slvl_get_i(p_slvl_tbl, i, &vl);
619                 n += snprintf(buf + n, bufsz - n, "%2u|", vl);
620                 if (n >= bufsz)
621                         break;
622         }
623         snprintf(buf + n, bufsz - n, "\n");
624 }
625
626 void
627 mad_dump_vlarbitration(char *buf, int bufsz, void *val, int num)
628 {
629         ib_vl_arb_table_t* p_vla_tbl = val;
630         int i, n;
631         uint8_t vl;
632
633         num /= sizeof(p_vla_tbl->vl_entry[0]);
634
635         n = snprintf(buf, bufsz, "\nVL    : |");
636         if (n >= bufsz)
637                 return;
638         for (i = 0; i < num; i++) {
639                 ib_vl_arb_get_vl(p_vla_tbl->vl_entry[i].res_vl, &vl);
640                 n += snprintf(buf + n, bufsz - n, "0x%-2X|", vl);
641                 if (n >= bufsz)
642                         return;
643         }
644
645         n += snprintf(buf + n, bufsz - n, "\nWEIGHT: |");
646         if (n >= bufsz)
647                 return;
648         for (i = 0; i < num; i++) {
649                 n += snprintf(buf + n, bufsz - n, "0x%-2X|",
650                               p_vla_tbl->vl_entry[i].weight);
651                 if (n >= bufsz)
652                         return;
653         }
654
655         snprintf(buf + n, bufsz - n, "\n");
656 }
657
658 static int
659 _dump_fields(char *buf, int bufsz, void *data, int start, int end)
660 {
661         char val[64];
662         char *s = buf;
663         int n, field;
664
665         for (field = start; field < end && bufsz > 0; field++) {
666                 mad_decode_field(data, field, val);
667                 if (!mad_dump_field(field, s, bufsz, val))
668                         return -1;
669                 n = strlen(s);
670                 s += n;
671                 *s++ = '\n';
672                 *s = 0;
673                 n++;
674                 bufsz -= n;
675         }
676
677         return (int)(s - buf);
678 }
679
680 void
681 mad_dump_nodedesc(char *buf, int bufsz, void *val, int valsz)
682 {
683         strncpy(buf, val, bufsz);
684
685         if (valsz < bufsz)
686                 buf[valsz] = 0;
687 }
688
689 void
690 mad_dump_nodeinfo(char *buf, int bufsz, void *val, int valsz)
691 {
692         _dump_fields(buf, bufsz, val, IB_NODE_FIRST_F, IB_NODE_LAST_F);
693 }
694
695 void
696 mad_dump_portinfo(char *buf, int bufsz, void *val, int valsz)
697 {
698         _dump_fields(buf, bufsz, val, IB_PORT_FIRST_F, IB_PORT_LAST_F);
699 }
700
701 void
702 mad_dump_portstates(char *buf, int bufsz, void *val, int valsz)
703 {
704         _dump_fields(buf, bufsz, val, IB_PORT_STATE_F, IB_PORT_LINK_DOWN_DEF_F);
705 }
706
707 void
708 mad_dump_switchinfo(char *buf, int bufsz, void *val, int valsz)
709 {
710         _dump_fields(buf, bufsz, val, IB_SW_FIRST_F, IB_SW_LAST_F);
711 }
712
713 void
714 mad_dump_perfcounters(char *buf, int bufsz, void *val, int valsz)
715 {
716         _dump_fields(buf, bufsz, val, IB_PC_FIRST_F, IB_PC_LAST_F);
717 }
718
719 void
720 mad_dump_perfcounters_ext(char *buf, int bufsz, void *val, int valsz)
721 {
722         _dump_fields(buf, bufsz, val, IB_PC_EXT_FIRST_F, IB_PC_EXT_LAST_F);
723 }
724
725 void xdump(FILE *file, char *msg, void *p, int size)
726 {
727 #define HEX(x)  ((x) < 10 ? '0' + (x) : 'a' + ((x) -10))
728         uint8_t *cp = p;
729         int i;
730
731         if (msg)
732                 fputs(msg, file);
733
734         for (i = 0; i < size;) {
735                 fputc(HEX(*cp >> 4), file);
736                 fputc(HEX(*cp & 0xf), file);
737                 if (++i >= size)
738                         break;
739                 fputc(HEX(cp[1] >> 4), file);
740                 fputc(HEX(cp[1] & 0xf), file);
741                 if ((++i) % 16)
742                         fputc(' ', file);
743                 else
744                         fputc('\n', file);
745                 cp += 2;
746         }
747         if (i % 16) {
748                 fputc('\n', file);
749         }
750 }