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