1*5e91e57eSQi Liu // SPDX-License-Identifier: GPL-2.0
2*5e91e57eSQi Liu /*
3*5e91e57eSQi Liu  * HiSilicon PCIe Trace and Tuning (PTT) support
4*5e91e57eSQi Liu  * Copyright (c) 2022 HiSilicon Technologies Co., Ltd.
5*5e91e57eSQi Liu  */
6*5e91e57eSQi Liu 
7*5e91e57eSQi Liu #include <stdlib.h>
8*5e91e57eSQi Liu #include <stdio.h>
9*5e91e57eSQi Liu #include <string.h>
10*5e91e57eSQi Liu #include <endian.h>
11*5e91e57eSQi Liu #include <byteswap.h>
12*5e91e57eSQi Liu #include <linux/bitops.h>
13*5e91e57eSQi Liu #include <stdarg.h>
14*5e91e57eSQi Liu 
15*5e91e57eSQi Liu #include "../color.h"
16*5e91e57eSQi Liu #include "hisi-ptt-pkt-decoder.h"
17*5e91e57eSQi Liu 
18*5e91e57eSQi Liu /*
19*5e91e57eSQi Liu  * For 8DW format, the bit[31:11] of DW0 is always 0x1fffff, which can be
20*5e91e57eSQi Liu  * used to distinguish the data format.
21*5e91e57eSQi Liu  * 8DW format is like:
22*5e91e57eSQi Liu  *   bits [                 31:11                 ][       10:0       ]
23*5e91e57eSQi Liu  *        |---------------------------------------|-------------------|
24*5e91e57eSQi Liu  *    DW0 [                0x1fffff               ][ Reserved (0x7ff) ]
25*5e91e57eSQi Liu  *    DW1 [                       Prefix                              ]
26*5e91e57eSQi Liu  *    DW2 [                     Header DW0                            ]
27*5e91e57eSQi Liu  *    DW3 [                     Header DW1                            ]
28*5e91e57eSQi Liu  *    DW4 [                     Header DW2                            ]
29*5e91e57eSQi Liu  *    DW5 [                     Header DW3                            ]
30*5e91e57eSQi Liu  *    DW6 [                   Reserved (0x0)                          ]
31*5e91e57eSQi Liu  *    DW7 [                        Time                               ]
32*5e91e57eSQi Liu  *
33*5e91e57eSQi Liu  * 4DW format is like:
34*5e91e57eSQi Liu  *   bits [31:30] [ 29:25 ][24][23][22][21][    20:11   ][    10:0    ]
35*5e91e57eSQi Liu  *        |-----|---------|---|---|---|---|-------------|-------------|
36*5e91e57eSQi Liu  *    DW0 [ Fmt ][  Type  ][T9][T8][TH][SO][   Length   ][    Time    ]
37*5e91e57eSQi Liu  *    DW1 [                     Header DW1                            ]
38*5e91e57eSQi Liu  *    DW2 [                     Header DW2                            ]
39*5e91e57eSQi Liu  *    DW3 [                     Header DW3                            ]
40*5e91e57eSQi Liu  */
41*5e91e57eSQi Liu 
42*5e91e57eSQi Liu enum hisi_ptt_8dw_pkt_field_type {
43*5e91e57eSQi Liu 	HISI_PTT_8DW_CHK_AND_RSV0,
44*5e91e57eSQi Liu 	HISI_PTT_8DW_PREFIX,
45*5e91e57eSQi Liu 	HISI_PTT_8DW_HEAD0,
46*5e91e57eSQi Liu 	HISI_PTT_8DW_HEAD1,
47*5e91e57eSQi Liu 	HISI_PTT_8DW_HEAD2,
48*5e91e57eSQi Liu 	HISI_PTT_8DW_HEAD3,
49*5e91e57eSQi Liu 	HISI_PTT_8DW_RSV1,
50*5e91e57eSQi Liu 	HISI_PTT_8DW_TIME,
51*5e91e57eSQi Liu 	HISI_PTT_8DW_TYPE_MAX
52*5e91e57eSQi Liu };
53*5e91e57eSQi Liu 
54*5e91e57eSQi Liu enum hisi_ptt_4dw_pkt_field_type {
55*5e91e57eSQi Liu 	HISI_PTT_4DW_HEAD1,
56*5e91e57eSQi Liu 	HISI_PTT_4DW_HEAD2,
57*5e91e57eSQi Liu 	HISI_PTT_4DW_HEAD3,
58*5e91e57eSQi Liu 	HISI_PTT_4DW_TYPE_MAX
59*5e91e57eSQi Liu };
60*5e91e57eSQi Liu 
61*5e91e57eSQi Liu static const char * const hisi_ptt_8dw_pkt_field_name[] = {
62*5e91e57eSQi Liu 	[HISI_PTT_8DW_PREFIX]	= "Prefix",
63*5e91e57eSQi Liu 	[HISI_PTT_8DW_HEAD0]	= "Header DW0",
64*5e91e57eSQi Liu 	[HISI_PTT_8DW_HEAD1]	= "Header DW1",
65*5e91e57eSQi Liu 	[HISI_PTT_8DW_HEAD2]	= "Header DW2",
66*5e91e57eSQi Liu 	[HISI_PTT_8DW_HEAD3]	= "Header DW3",
67*5e91e57eSQi Liu 	[HISI_PTT_8DW_TIME]	= "Time"
68*5e91e57eSQi Liu };
69*5e91e57eSQi Liu 
70*5e91e57eSQi Liu static const char * const hisi_ptt_4dw_pkt_field_name[] = {
71*5e91e57eSQi Liu 	[HISI_PTT_4DW_HEAD1]	= "Header DW1",
72*5e91e57eSQi Liu 	[HISI_PTT_4DW_HEAD2]	= "Header DW2",
73*5e91e57eSQi Liu 	[HISI_PTT_4DW_HEAD3]	= "Header DW3",
74*5e91e57eSQi Liu };
75*5e91e57eSQi Liu 
76*5e91e57eSQi Liu union hisi_ptt_4dw {
77*5e91e57eSQi Liu 	struct {
78*5e91e57eSQi Liu 		uint32_t format : 2;
79*5e91e57eSQi Liu 		uint32_t type : 5;
80*5e91e57eSQi Liu 		uint32_t t9 : 1;
81*5e91e57eSQi Liu 		uint32_t t8 : 1;
82*5e91e57eSQi Liu 		uint32_t th : 1;
83*5e91e57eSQi Liu 		uint32_t so : 1;
84*5e91e57eSQi Liu 		uint32_t len : 10;
85*5e91e57eSQi Liu 		uint32_t time : 11;
86*5e91e57eSQi Liu 	};
87*5e91e57eSQi Liu 	uint32_t value;
88*5e91e57eSQi Liu };
89*5e91e57eSQi Liu 
hisi_ptt_print_pkt(const unsigned char * buf,int pos,const char * desc)90*5e91e57eSQi Liu static void hisi_ptt_print_pkt(const unsigned char *buf, int pos, const char *desc)
91*5e91e57eSQi Liu {
92*5e91e57eSQi Liu 	const char *color = PERF_COLOR_BLUE;
93*5e91e57eSQi Liu 	int i;
94*5e91e57eSQi Liu 
95*5e91e57eSQi Liu 	printf(".");
96*5e91e57eSQi Liu 	color_fprintf(stdout, color, "  %08x: ", pos);
97*5e91e57eSQi Liu 	for (i = 0; i < HISI_PTT_FIELD_LENTH; i++)
98*5e91e57eSQi Liu 		color_fprintf(stdout, color, "%02x ", buf[pos + i]);
99*5e91e57eSQi Liu 	for (i = 0; i < HISI_PTT_MAX_SPACE_LEN; i++)
100*5e91e57eSQi Liu 		color_fprintf(stdout, color, "   ");
101*5e91e57eSQi Liu 	color_fprintf(stdout, color, "  %s\n", desc);
102*5e91e57eSQi Liu }
103*5e91e57eSQi Liu 
hisi_ptt_8dw_kpt_desc(const unsigned char * buf,int pos)104*5e91e57eSQi Liu static int hisi_ptt_8dw_kpt_desc(const unsigned char *buf, int pos)
105*5e91e57eSQi Liu {
106*5e91e57eSQi Liu 	int i;
107*5e91e57eSQi Liu 
108*5e91e57eSQi Liu 	for (i = 0; i < HISI_PTT_8DW_TYPE_MAX; i++) {
109*5e91e57eSQi Liu 		/* Do not show 8DW check field and reserved fields */
110*5e91e57eSQi Liu 		if (i == HISI_PTT_8DW_CHK_AND_RSV0 || i == HISI_PTT_8DW_RSV1) {
111*5e91e57eSQi Liu 			pos += HISI_PTT_FIELD_LENTH;
112*5e91e57eSQi Liu 			continue;
113*5e91e57eSQi Liu 		}
114*5e91e57eSQi Liu 
115*5e91e57eSQi Liu 		hisi_ptt_print_pkt(buf, pos, hisi_ptt_8dw_pkt_field_name[i]);
116*5e91e57eSQi Liu 		pos += HISI_PTT_FIELD_LENTH;
117*5e91e57eSQi Liu 	}
118*5e91e57eSQi Liu 
119*5e91e57eSQi Liu 	return hisi_ptt_pkt_size[HISI_PTT_8DW_PKT];
120*5e91e57eSQi Liu }
121*5e91e57eSQi Liu 
hisi_ptt_4dw_print_dw0(const unsigned char * buf,int pos)122*5e91e57eSQi Liu static void hisi_ptt_4dw_print_dw0(const unsigned char *buf, int pos)
123*5e91e57eSQi Liu {
124*5e91e57eSQi Liu 	const char *color = PERF_COLOR_BLUE;
125*5e91e57eSQi Liu 	union hisi_ptt_4dw dw0;
126*5e91e57eSQi Liu 	int i;
127*5e91e57eSQi Liu 
128*5e91e57eSQi Liu 	dw0.value = *(uint32_t *)(buf + pos);
129*5e91e57eSQi Liu 	printf(".");
130*5e91e57eSQi Liu 	color_fprintf(stdout, color, "  %08x: ", pos);
131*5e91e57eSQi Liu 	for (i = 0; i < HISI_PTT_FIELD_LENTH; i++)
132*5e91e57eSQi Liu 		color_fprintf(stdout, color, "%02x ", buf[pos + i]);
133*5e91e57eSQi Liu 	for (i = 0; i < HISI_PTT_MAX_SPACE_LEN; i++)
134*5e91e57eSQi Liu 		color_fprintf(stdout, color, "   ");
135*5e91e57eSQi Liu 
136*5e91e57eSQi Liu 	color_fprintf(stdout, color,
137*5e91e57eSQi Liu 		      "  %s %x %s %x %s %x %s %x %s %x %s %x %s %x %s %x\n",
138*5e91e57eSQi Liu 		      "Format", dw0.format, "Type", dw0.type, "T9", dw0.t9,
139*5e91e57eSQi Liu 		      "T8", dw0.t8, "TH", dw0.th, "SO", dw0.so, "Length",
140*5e91e57eSQi Liu 		      dw0.len, "Time", dw0.time);
141*5e91e57eSQi Liu }
142*5e91e57eSQi Liu 
hisi_ptt_4dw_kpt_desc(const unsigned char * buf,int pos)143*5e91e57eSQi Liu static int hisi_ptt_4dw_kpt_desc(const unsigned char *buf, int pos)
144*5e91e57eSQi Liu {
145*5e91e57eSQi Liu 	int i;
146*5e91e57eSQi Liu 
147*5e91e57eSQi Liu 	hisi_ptt_4dw_print_dw0(buf, pos);
148*5e91e57eSQi Liu 	pos += HISI_PTT_FIELD_LENTH;
149*5e91e57eSQi Liu 
150*5e91e57eSQi Liu 	for (i = 0; i < HISI_PTT_4DW_TYPE_MAX; i++) {
151*5e91e57eSQi Liu 		hisi_ptt_print_pkt(buf, pos, hisi_ptt_4dw_pkt_field_name[i]);
152*5e91e57eSQi Liu 		pos += HISI_PTT_FIELD_LENTH;
153*5e91e57eSQi Liu 	}
154*5e91e57eSQi Liu 
155*5e91e57eSQi Liu 	return hisi_ptt_pkt_size[HISI_PTT_4DW_PKT];
156*5e91e57eSQi Liu }
157*5e91e57eSQi Liu 
hisi_ptt_pkt_desc(const unsigned char * buf,int pos,enum hisi_ptt_pkt_type type)158*5e91e57eSQi Liu int hisi_ptt_pkt_desc(const unsigned char *buf, int pos, enum hisi_ptt_pkt_type type)
159*5e91e57eSQi Liu {
160*5e91e57eSQi Liu 	if (type == HISI_PTT_8DW_PKT)
161*5e91e57eSQi Liu 		return hisi_ptt_8dw_kpt_desc(buf, pos);
162*5e91e57eSQi Liu 
163*5e91e57eSQi Liu 	return hisi_ptt_4dw_kpt_desc(buf, pos);
164*5e91e57eSQi Liu }
165