xref: /freebsd/sys/dev/iwx/if_iwx_debug.c (revision b670c9bafc0e31c7609969bf374b2e80bdc00211)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2015 Adrian Chadd <adrian@FreeBSD.org>
5  * Copyright (c) 2025 The FreeBSD Foundation
6  *
7  * Portions of this software were developed by Tom Jones <thj@FreeBSD.org>
8  * under sponsorship from the FreeBSD Foundation.
9  */
10 
11 #include <sys/param.h>
12 #include <sys/systm.h>
13 #include <net/ethernet.h>
14 
15 #include <net80211/ieee80211.h>
16 
17 #define le32_to_cpup(_a_) (le32toh(*(const uint32_t *)(_a_)))
18 
19 #include <dev/iwx/if_iwxreg.h>
20 #include <dev/iwx/if_iwx_debug.h>
21 
22 static int print_codes[][2] = {
23 #if 0
24 	for example:
25 	IWX_LEGACY_GROUP, IWX_ADD_STA_KEY,
26 	IWX_LEGACY_GROUP, IWX_SCD_QUEUE_CONFIG_CMD,
27 	IWX_LEGACY_GROUP, IWX_ADD_STA,
28 	IWX_LEGACY_GROUP, IWX_REMOVE_STA,
29 #endif
30 };
31 
32 struct opcode_label {
33 	uint8_t opcode;
34 	const char *label;
35 };
36 
37 static struct opcode_label command_group[] = {
38 	{ 0x0, "IWX_LEGACY_GROUP"},
39 	{ 0x1, "IWX_LONG_GROUP"},
40 	{ 0x2, "IWX_SYSTEM_GROUP"},
41 	{ 0x3, "IWX_MAC_CONF_GROUP"},
42 	{ 0x4, "IWX_PHY_OPS_GROUP"},
43 	{ 0x5, "IWX_DATA_PATH_GROUP"},
44 	{ 0xb, "IWX_PROT_OFFLOAD_GROUP"},
45 	{ 0xc, "IWX_REGULATORY_AND_NVM_GROUP"},
46 	{ 0, NULL }
47 };
48 
49 static struct opcode_label legacy_opcodes[] = {
50 	{ 0xc0, "IWX_REPLY_RX_PHY_CMD" },
51 	{ 0xc1, "IWX_REPLY_RX_MPDU_CMD" },
52 	{ 0xc2, "IWX_BAR_FRAME_RELEASE" },
53 	{ 0xc3, "IWX_FRAME_RELEASE" },
54 	{ 0xc5, "IWX_BA_NOTIF" },
55 	{ 0x62, "IWX_TEMPERATURE_NOTIFICATION" },
56 	{ 0xc8, "IWX_MCC_UPDATE_CMD" },
57 	{ 0xc9, "IWX_MCC_CHUB_UPDATE_CMD" },
58 	{ 0x65, "IWX_CALIBRATION_CFG_CMD" },
59 	{ 0x66, "IWX_CALIBRATION_RES_NOTIFICATION" },
60 	{ 0x67, "IWX_CALIBRATION_COMPLETE_NOTIFICATION" },
61 	{ 0x68, "IWX_RADIO_VERSION_NOTIFICATION" },
62 	{ 0x00, "IWX_CMD_DTS_MEASUREMENT_TRIGGER_WIDE" },
63 	{ 0x01, "IWX_SOC_CONFIGURATION_CMD" },
64 	{ 0x02, "IWX_REPLY_ERROR" },
65 	{ 0x03, "IWX_CTDP_CONFIG_CMD" },
66 	{ 0x04, "IWX_INIT_COMPLETE_NOTIF" },
67 	{ 0x05, "IWX_SESSION_PROTECTION_CMD" },
68 	{ 0x5d, "IWX_BT_COEX_CI" },
69 	{ 0x07, "IWX_FW_ERROR_RECOVERY_CMD" },
70 	{ 0x08, "IWX_RLC_CONFIG_CMD" },
71 	{ 0xd0, "IWX_MCAST_FILTER_CMD" },
72 	{ 0xd1, "IWX_REPLY_SF_CFG_CMD" },
73 	{ 0xd2, "IWX_REPLY_BEACON_FILTERING_CMD" },
74 	{ 0xd3, "IWX_D3_CONFIG_CMD" },
75 	{ 0xd4, "IWX_PROT_OFFLOAD_CONFIG_CMD" },
76 	{ 0xd5, "IWX_OFFLOADS_QUERY_CMD" },
77 	{ 0xd6, "IWX_REMOTE_WAKE_CONFIG_CMD" },
78 	{ 0x77, "IWX_POWER_TABLE_CMD" },
79 	{ 0x78, "IWX_PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION" },
80 	{ 0xcc, "IWX_BT_COEX_PRIO_TABLE" },
81 	{ 0xcd, "IWX_BT_COEX_PROT_ENV" },
82 	{ 0xce, "IWX_BT_PROFILE_NOTIFICATION" },
83 	{ 0x6a, "IWX_PHY_CONFIGURATION_CMD" },
84 	{ 0x16, "IWX_RX_BAID_ALLOCATION_CONFIG_CMD" },
85 	{ 0x17, "IWX_ADD_STA_KEY" },
86 	{ 0x18, "IWX_ADD_STA" },
87 	{ 0x19, "IWX_REMOVE_STA" },
88 	{ 0xe0, "IWX_WOWLAN_PATTERNS" },
89 	{ 0xe1, "IWX_WOWLAN_CONFIGURATION" },
90 	{ 0xe2, "IWX_WOWLAN_TSC_RSC_PARAM" },
91 	{ 0xe3, "IWX_WOWLAN_TKIP_PARAM" },
92 	{ 0xe4, "IWX_WOWLAN_KEK_KCK_MATERIAL" },
93 	{ 0xe5, "IWX_WOWLAN_GET_STATUSES" },
94 	{ 0xe6, "IWX_WOWLAN_TX_POWER_PER_DB" },
95 	{ 0x0f, "IWX_SCAN_COMPLETE_UMAC" },
96 	{ 0x88, "IWX_NVM_ACCESS_CMD" },
97 	{ 0x20, "IWX_WEP_KEY" },
98 	{ 0xdc, "IWX_CMD_DTS_MEASUREMENT_TRIGGER" },
99 	{ 0xdd, "IWX_DTS_MEASUREMENT_NOTIFICATION" },
100 	{ 0x28, "IWX_MAC_CONTEXT_CMD" },
101 	{ 0x29, "IWX_TIME_EVENT_CMD" },
102 	{ 0x01, "IWX_ALIVE" },
103 	{ 0xf0, "IWX_REPLY_DEBUG_CMD" },
104 	{ 0x90, "IWX_BEACON_NOTIFICATION" },
105 	{ 0xf5, "IWX_RX_NO_DATA_NOTIF" },
106 	{ 0x08, "IWX_PHY_CONTEXT_CMD" },
107 	{ 0x91, "IWX_BEACON_TEMPLATE_CMD" },
108 	{ 0xf6, "IWX_THERMAL_DUAL_CHAIN_REQUEST" },
109 	{ 0x09, "IWX_DBG_CFG" },
110 	{ 0xf7, "IWX_DEBUG_LOG_MSG" },
111 	{ 0x1c, "IWX_TX_CMD" },
112 	{ 0x1d, "IWX_SCD_QUEUE_CFG" },
113 	{ 0x1e, "IWX_TXPATH_FLUSH" },
114 	{ 0x1f, "IWX_MGMT_MCAST_KEY" },
115 	{ 0x98, "IWX_TX_ANT_CONFIGURATION_CMD" },
116 	{ 0xee, "IWX_LTR_CONFIG" },
117 	{ 0x8e, "IWX_SET_CALIB_DEFAULT_CMD" },
118 	{ 0xFE, "IWX_CT_KILL_NOTIFICATION" },
119 	{ 0xFF, "IWX_DTS_MEASUREMENT_NOTIF_WIDE" },
120 	{ 0x2a, "IWX_TIME_EVENT_NOTIFICATION" },
121 	{ 0x2b, "IWX_BINDING_CONTEXT_CMD" },
122 	{ 0x2c, "IWX_TIME_QUOTA_CMD" },
123 	{ 0x2d, "IWX_NON_QOS_TX_COUNTER_CMD" },
124 	{ 0xa0, "IWX_CARD_STATE_CMD" },
125 	{ 0xa1, "IWX_CARD_STATE_NOTIFICATION" },
126 	{ 0xa2, "IWX_MISSED_BEACONS_NOTIFICATION" },
127 	{ 0x0c, "IWX_SCAN_CFG_CMD" },
128 	{ 0x0d, "IWX_SCAN_REQ_UMAC" },
129 	{ 0xfb, "IWX_SESSION_PROTECTION_NOTIF" },
130 	{ 0x0e, "IWX_SCAN_ABORT_UMAC" },
131 	{ 0xfe, "IWX_PNVM_INIT_COMPLETE" },
132 	{ 0xa9, "IWX_MAC_PM_POWER_TABLE" },
133 	{ 0xff, "IWX_FSEQ_VER_MISMATCH_NOTIFICATION | IWX_REPLY_MAX" },
134 	{ 0x9b, "IWX_BT_CONFIG" },
135 	{ 0x9c, "IWX_STATISTICS_CMD" },
136 	{ 0x9d, "IWX_STATISTICS_NOTIFICATION" },
137 	{ 0x9f, "IWX_REDUCE_TX_POWER_CMD" },
138 	{ 0xb1, "IWX_MFUART_LOAD_NOTIFICATION" },
139 	{ 0xb5, "IWX_SCAN_ITERATION_COMPLETE_UMAC" },
140 	{ 0x54, "IWX_NET_DETECT_CONFIG_CMD" },
141 	{ 0x56, "IWX_NET_DETECT_PROFILES_QUERY_CMD" },
142 	{ 0x57, "IWX_NET_DETECT_PROFILES_CMD" },
143 	{ 0x58, "IWX_NET_DETECT_HOTSPOTS_CMD" },
144 	{ 0x59, "IWX_NET_DETECT_HOTSPOTS_QUERY_CMD" },
145 	{ 0, NULL }
146 };
147 
148 /* SYSTEM_GROUP group subcommand IDs */
149 static struct opcode_label system_opcodes[] = {
150 	{ 0x00, "IWX_SHARED_MEM_CFG_CMD" },
151 	{ 0x01, "IWX_SOC_CONFIGURATION_CMD" },
152 	{ 0x03, "IWX_INIT_EXTENDED_CFG_CMD" },
153 	{ 0x07, "IWX_FW_ERROR_RECOVERY_CMD" },
154 	{ 0xff, "IWX_FSEQ_VER_MISMATCH_NOTIFICATION | IWX_REPLY_MAX" },
155 	{ 0, NULL }
156 };
157 
158 /* MAC_CONF group subcommand IDs */
159 static struct opcode_label macconf_opcodes[] = {
160 	{ 0x05, "IWX_SESSION_PROTECTION_CMD" },
161 	{ 0xfb, "IWX_SESSION_PROTECTION_NOTIF" },
162 	{ 0, NULL }
163 };
164 
165 /* DATA_PATH group subcommand IDs */
166 static struct opcode_label data_opcodes[] = {
167 	{ 0x00, "IWX_DQA_ENABLE_CMD" },
168 	{ 0x08, "IWX_RLC_CONFIG_CMD" },
169 	{ 0x0f, "IWX_TLC_MNG_CONFIG_CMD" },
170 	{ 0x16, "IWX_RX_BAID_ALLOCATION_CONFIG_CMD" },
171 	{ 0x17, "IWX_SCD_QUEUE_CONFIG_CMD" },
172 	{ 0xf5, "IWX_RX_NO_DATA_NOTIF" },
173 	{ 0xf6, "IWX_THERMAL_DUAL_CHAIN_REQUEST" },
174 	{ 0xf7, "IWX_TLC_MNG_UPDATE_NOTIF" },
175 	{ 0, NULL }
176 };
177 
178 /* REGULATORY_AND_NVM group subcommand IDs */
179 static struct opcode_label reg_opcodes[] = {
180 	{ 0x00, "IWX_NVM_ACCESS_COMPLETE" },
181 	{ 0x02, "IWX_NVM_GET_INFO " },
182 	{ 0xfe, "IWX_PNVM_INIT_COMPLETE" },
183 	{ 0, NULL }
184 };
185 
186 /* PHY_OPS subcommand IDs */
187 static struct opcode_label phyops_opcodes[] = {
188 	{0x00, 	"IWX_CMD_DTS_MEASUREMENT_TRIGGER_WIDE"},
189 	{0x03,	"IWX_CTDP_CONFIG_CMD"},
190 	{0x04,	"IWX_TEMP_REPORTING_THRESHOLDS_CMD"},
191 	{0xFE,	"IWX_CT_KILL_NOTIFICATION"},
192 	{0xFF,	"IWX_DTS_MEASUREMENT_NOTIF_WIDE"},
193 };
194 
195 static const char *
196 get_label(struct opcode_label *table, uint8_t opcode)
197 {
198 	struct opcode_label *op = table;
199 	while(op->label != NULL) {
200 		if (op->opcode == opcode)
201 			return op->label;
202 		op++;
203 	}
204 	return "NOT FOUND IN TABLE";
205 }
206 
207 static struct opcode_label *
208 get_table(uint8_t group)
209 {
210 	switch (group)
211 	{
212 	case IWX_LEGACY_GROUP:
213 	case IWX_LONG_GROUP:
214 		return legacy_opcodes;
215 		break;
216 	case IWX_SYSTEM_GROUP:
217 		return system_opcodes;
218 		break;
219 	case IWX_MAC_CONF_GROUP:
220 		return macconf_opcodes;
221 		break;
222 	case IWX_DATA_PATH_GROUP:
223 		return data_opcodes;
224 		break;
225 	case IWX_REGULATORY_AND_NVM_GROUP:
226 		return reg_opcodes;
227 		break;
228 	case IWX_PHY_OPS_GROUP:
229 		return phyops_opcodes;
230 		break;
231 	case IWX_PROT_OFFLOAD_GROUP:
232 		break;
233 	}
234 	return NULL;
235 }
236 
237 void
238 print_opcode(const char *func, int line, uint32_t code)
239 {
240 	int print = 0;
241 	uint8_t opcode = iwx_cmd_opcode(code);
242 	uint8_t group = iwx_cmd_groupid(code);
243 
244 	struct opcode_label *table = get_table(group);
245 	if (table == NULL) {
246 		printf("Couldn't find opcode table for 0x%08x", code);
247 		return;
248 	}
249 
250 	for (int i = 0; i < nitems(print_codes); i++)
251 		if (print_codes[i][0] == group && print_codes[i][1] == opcode)
252 			print = 1;
253 
254 	if (print) {
255 		printf("%s:%d \t%s\t%s\t(0x%08x)\n", func, line,
256 		    get_label(command_group, group),
257 		    get_label(table, opcode), code);
258 	}
259 }
260 
261 void
262 print_ratenflags(const char *func, int line, uint32_t flags, int ver)
263 {
264 	printf("%s:%d\n\t flags 0x%08x ", func, line, flags);
265 
266 	if (ver >= 2) {
267 		printf(" rate_n_flags version 2\n");
268 
269 		uint32_t type = (flags & IWX_RATE_MCS_MOD_TYPE_MSK) >> IWX_RATE_MCS_MOD_TYPE_POS;
270 
271 		switch(type)
272 		{
273 		case 0:
274 			printf("\t(0) Legacy CCK: ");
275 			switch (flags & IWX_RATE_LEGACY_RATE_MSK)
276 			{
277 			case 0:
278 				printf("(0) 0xa - 1 Mbps\n");
279 				break;
280 			case 1:
281 				printf("(1) 0x14 - 2 Mbps\n");
282 				break;
283 			case 2:
284 				printf("(2) 0x37 - 5.5 Mbps\n");
285 				break;
286 			case 3:
287 				printf("(3) 0x6e - 11 nbps\n");
288 				break;
289 			}
290 			break;
291 		case 1:
292 			printf("\t(1) Legacy OFDM \n");
293 			switch (flags & IWX_RATE_LEGACY_RATE_MSK)
294 			{
295 			case 0:
296 				printf("(0) 6 Mbps\n");
297 				break;
298 			case 1:
299 				printf("(1) 9 Mbps\n");
300 				break;
301 			case 2:
302 				printf("(2) 12 Mbps\n");
303 				break;
304 			case 3:
305 				printf("(3) 18 Mbps\n");
306 				break;
307 			case 4:
308 				printf("(4) 24 Mbps\n");
309 				break;
310 			case 5:
311 				printf("(5) 36 Mbps\n");
312 				break;
313 			case 6:
314 				printf("(6) 48 Mbps\n");
315 				break;
316 			case 7:
317 				printf("(7) 54 Mbps\n");
318 				break;
319 			}
320 			break;
321 		case 2:
322 			printf("\t(2) High-throughput (HT)\n");
323 			break;
324 		case 3:
325 			printf("\t(3) Very High-throughput (VHT) \n");
326 			break;
327 		case 4:
328 			printf("\t(4) High-efficiency (HE)\n");
329 			break;
330 		case 5:
331 			printf("\t(5) Extremely High-throughput (EHT)\n");
332 			break;
333 		default:
334 			printf("invalid\n");
335 		}
336 
337 		/* Not a legacy rate. */
338 		if (type > 1) {
339 			printf("\tMCS %d ", IWX_RATE_HT_MCS_INDEX(flags));
340 			switch((flags & IWX_RATE_MCS_CHAN_WIDTH_MSK) >> IWX_RATE_MCS_CHAN_WIDTH_POS)
341 			{
342 			case 0:
343 				printf("20MHz ");
344 				break;
345 			case 1:
346 				printf("40MHz ");
347 				break;
348 			case 2:
349 				printf("80MHz ");
350 				break;
351 			case 3:
352 				printf("160MHz ");
353 				break;
354 			case 4:
355 				printf("320MHz ");
356 				break;
357 
358 			}
359 			printf("antennas: (%s|%s) ",
360 				flags & (1 << 14) ? "A" : " ",
361 				flags & (1 << 15) ? "B" : " ");
362 			if (flags & (1 << 16))
363 				printf("ldpc ");
364 			printf("\n");
365 		}
366 	} else {
367 		printf("%s:%d rate_n_flags versions other than < 2 not implemented",
368 		    __func__, __LINE__);
369 	}
370 }
371