diff --git a/src/RadioManagementModule.cpp b/src/RadioManagementModule.cpp index 0375c7c..22360b4 100644 --- a/src/RadioManagementModule.cpp +++ b/src/RadioManagementModule.cpp @@ -302,65 +302,75 @@ void RadioManagementModule::phy_SwChnlAndSetBwMode8812() { * temperatures. Capture both dumps within a few seconds for clean * parity. */ if (std::getenv("DEVOURER_DUMP_CANARY")) { - static const uint16_t bb_canary[] = { - /* PHY/AGC anchors */ + /* Per-chip canary set. Each Jaguar variant has a different active + * RF/path footprint: + * - 8821AU is 1T1R AC: only path-A exists physically. Path-B BB-AGC + * mirror (0xe20-0xe40) and RF[B] reads return BB-init defaults + * or sentinel zero — including them just clutters the diff. + * - 8812AU is 2T2R: paths A + B are both active. + * - 8814AU is 4T4R: paths A + B + C + D BB-table state is active. + * RF[C]/RF[D] are write-only by HW design (kaeru cite "RTL8814AU + * RF read mechanism — paths C/D write-only by HW design") so we + * skip RF reads for paths C and D. + * The MAC anchor set is chip-independent (same regs across the + * family). */ + + /* Shared anchors — PHY anchors + MAC: same for every Jaguar chip. */ + static const uint16_t bb_anchors[] = { 0x808, 0x80c, 0x82c, 0x830, 0x834, 0x838, 0x84c, 0x860, 0x8ac, - 0x8b0, 0x8c4, - /* Page-C path A: TX-AGC + AGC core */ + 0x8b0, 0x8c4}; + static const uint16_t bb_pathA[] = { + /* Page-C path A: TX-AGC + AGC core + IQK/DPK output regs */ 0xc00, 0xc1c, 0xc20, 0xc24, 0xc28, 0xc2c, 0xc30, 0xc34, 0xc38, 0xc3c, 0xc40, 0xc50, 0xc54, 0xc60, 0xc64, 0xc68, 0xc6c, 0xc70, - /* IQK / DPK output regs (path A): rOFDM0_X*TxIQImbalance, - * IQC matrix coefficients, IQK readback registers. */ - 0xc10, 0xc14, 0xc90, 0xc94, - /* Page-C path B: TX-AGC mirror of 0xc20-0xc40 (path-A AGC table - * is mirrored to path-B at 0xe20-0xe40 by PHY_SetTxPowerIndex_8812A - * for 2T2R chips; divergence here would surface a path-B-specific - * port bug we'd otherwise miss). */ + 0xc10, 0xc14, 0xc90, 0xc94}; + static const uint16_t bb_pathB[] = { + /* Page-C path B: TX-AGC mirror of path-A + IQK/DPK output regs */ 0xe1c, 0xe20, 0xe24, 0xe28, 0xe2c, 0xe30, 0xe34, 0xe38, 0xe3c, - 0xe40, 0xe50, 0xe54, - /* IQK / DPK output regs (path B). */ - 0xe10, 0xe14, 0xe90, 0xe94}; + 0xe40, 0xe50, 0xe54, 0xe10, 0xe14, 0xe90, 0xe94}; + static const uint16_t bb_pathC[] = { + /* 8814A path-C BB-table (0x18xx range, see hal/Hal8814PhyReg.h) */ + 0x1820, 0x1824, 0x1828, 0x182c, 0x1830, 0x1834, 0x1838, 0x183c, + 0x1840, 0x181c, 0x1850}; + static const uint16_t bb_pathD[] = { + /* 8814A path-D BB-table (0x1Axx range, see hal/Hal8814PhyReg.h) */ + 0x1a20, 0x1a24, 0x1a28, 0x1a2c, 0x1a30, 0x1a34, 0x1a38, 0x1a3c, + 0x1a40, 0x1a1c, 0x1a50}; static const uint16_t mac_canary[] = {0x40, 0xcf, 0xf0, 0x100, 0x102, 0x420, 0x4c8, 0x508, 0x522, 0x550, 0x560, 0x610, 0x614}; static const uint32_t rf_canary[] = {0x00, 0x05, 0x18, 0x42, 0x65, 0x8f}; + + /* Chip-dependent path mask. */ + const auto ictype = _eepromManager->version_id.ICType; + const bool has_pathB = (ictype != CHIP_8821); + const bool has_pathCD = (ictype == CHIP_8814A); + _logger->info("=== DEVOURER_DUMP_CANARY (post channel-set ch={}) ===", unsigned(_currentChannel)); - for (uint16_t a : bb_canary) + for (uint16_t a : bb_anchors) + _logger->info("BB 0x{:03x} = 0x{:08X}", a, _device.rtw_read32(a)); + for (uint16_t a : bb_pathA) _logger->info("BB 0x{:03x} = 0x{:08X}", a, _device.rtw_read32(a)); + if (has_pathB) + for (uint16_t a : bb_pathB) + _logger->info("BB 0x{:03x} = 0x{:08X}", a, _device.rtw_read32(a)); + if (has_pathCD) { + for (uint16_t a : bb_pathC) + _logger->info("BB 0x{:04x} = 0x{:08X}", a, _device.rtw_read32(a)); + for (uint16_t a : bb_pathD) + _logger->info("BB 0x{:04x} = 0x{:08X}", a, _device.rtw_read32(a)); + } for (uint16_t a : mac_canary) _logger->info("MAC 0x{:03x} = 0x{:08X}", a, _device.rtw_read32(a)); for (uint32_t a : rf_canary) _logger->info("RF[A] 0x{:02x} = 0x{:05X}", a, phy_query_rf_reg(RfPath::RF_PATH_A, a, 0xfffffu)); - for (uint32_t a : rf_canary) - _logger->info("RF[B] 0x{:02x} = 0x{:05X}", a, - phy_query_rf_reg(RfPath::RF_PATH_B, a, 0xfffffu)); - - /* 8814AU extension: dump path-C/D BB-AGC + IGI + BB-swing. Paths C/D - * exist at BB-register-table level (0x18xx for path C, 0x1Axx for - * path D, see hal/Hal8814PhyReg.h). NB: the corresponding RF - * registers for paths C/D are write-only by HW design on 8814AU - * (see kaeru cite "RTL8814AU RF read mechanism — paths C/D - * write-only by HW design") — read attempts return undefined - * data, so we skip RF[C]/RF[D]. The BB-table state IS readable - * and is the canary surface for path-C/D init drift. */ - if (_eepromManager->version_id.ICType == CHIP_8814A) { - static const uint16_t bb_canary_8814_pathCD[] = { - /* Path-C TX-AGC table */ - 0x1820, 0x1824, 0x1828, 0x182c, 0x1830, 0x1834, 0x1838, 0x183c, - 0x1840, - /* Path-C BB-swing + IGI */ - 0x181c, 0x1850, - /* Path-D TX-AGC table */ - 0x1a20, 0x1a24, 0x1a28, 0x1a2c, 0x1a30, 0x1a34, 0x1a38, 0x1a3c, - 0x1a40, - /* Path-D BB-swing + IGI */ - 0x1a1c, 0x1a50}; - for (uint16_t a : bb_canary_8814_pathCD) - _logger->info("BB 0x{:04x} = 0x{:08X}", a, _device.rtw_read32(a)); - } + if (has_pathB) + for (uint32_t a : rf_canary) + _logger->info("RF[B] 0x{:02x} = 0x{:05X}", a, + phy_query_rf_reg(RfPath::RF_PATH_B, a, 0xfffffu)); _logger->info("=== END DEVOURER_DUMP_CANARY ==="); } diff --git a/tools/canary_kernel_dump.sh b/tools/canary_kernel_dump.sh index 0927e78..02bf6db 100755 --- a/tools/canary_kernel_dump.sh +++ b/tools/canary_kernel_dump.sh @@ -39,7 +39,7 @@ set -euo pipefail if [[ $# -lt 2 ]]; then echo "Usage: $0 [chip]" >&2 - echo " chip: 8812 (default) | 8814" >&2 + echo " chip: 8812 (default) | 8821 | 8814" >&2 exit 1 fi @@ -47,6 +47,24 @@ IFACE="$1" CHANNEL="$2" CHIP="${3:-8812}" +case "$CHIP" in + 8812|8821|8814) ;; + *) + echo "unknown chip '$CHIP' — must be 8812, 8821 or 8814" >&2 + exit 1 + ;; +esac + +# Per-chip path mask — mirrors the chip-aware dump in +# RadioManagementModule::phy_SwChnlAndSetBwMode8812. 8821 is 1T1R so +# path-B BB-AGC mirror + RF[B] reads return sentinel/default; skip +# them. 8814 has additional path-C/D BB-table state (RF[C]/RF[D] are +# HW write-only so RF is still A+B only). +HAS_PATHB=1 +HAS_PATHCD=0 +if [[ "$CHIP" = "8821" ]]; then HAS_PATHB=0; fi +if [[ "$CHIP" = "8814" ]]; then HAS_PATHCD=1; fi + if ! ip -o link show "$IFACE" >/dev/null 2>&1; then echo "iface '$IFACE' not found — did you modprobe 88XXau?" >&2 exit 1 @@ -69,42 +87,58 @@ rfread() { echo "=== DEVOURER_DUMP_CANARY (post channel-set ch=$CHANNEL) ===" -# BB canary set — same list as `RadioManagementModule::phy_SwChnlAndSetBwMode8812` -# emits when DEVOURER_DUMP_CANARY=1 is set. Keep the two lists in sync. +# Order matches `RadioManagementModule::phy_SwChnlAndSetBwMode8812`'s +# DEVOURER_DUMP_CANARY block exactly — keep the two in sync so the +# kernel + devourer captures line-diff cleanly. + +# Shared anchors — PHY/AGC anchors common to every Jaguar chip. for ADDR in 0x808 0x80c 0x82c 0x830 0x834 0x838 0x84c 0x860 0x8ac \ - 0x8b0 0x8c4 \ - 0xc00 0xc1c 0xc20 0xc24 0xc28 0xc2c 0xc30 \ + 0x8b0 0x8c4; do + printf "BB %s = %s\n" "$ADDR" "$(readreg $ADDR)" +done + +# Path-A BB: TX-AGC + AGC core + IQK/DPK output regs. +for ADDR in 0xc00 0xc1c 0xc20 0xc24 0xc28 0xc2c 0xc30 \ 0xc34 0xc38 0xc3c 0xc40 0xc50 0xc54 0xc60 0xc64 0xc68 \ 0xc6c 0xc70 \ - 0xc10 0xc14 0xc90 0xc94 \ - 0xe1c 0xe20 0xe24 0xe28 0xe2c 0xe30 0xe34 0xe38 0xe3c \ - 0xe40 0xe50 0xe54 \ - 0xe10 0xe14 0xe90 0xe94; do + 0xc10 0xc14 0xc90 0xc94; do printf "BB %s = %s\n" "$ADDR" "$(readreg $ADDR)" done +# Path-B BB: TX-AGC mirror + IQK/DPK output. Skipped on 1T1R 8821. +if [[ "$HAS_PATHB" = "1" ]]; then + for ADDR in 0xe1c 0xe20 0xe24 0xe28 0xe2c 0xe30 0xe34 0xe38 0xe3c \ + 0xe40 0xe50 0xe54 \ + 0xe10 0xe14 0xe90 0xe94; do + printf "BB %s = %s\n" "$ADDR" "$(readreg $ADDR)" + done +fi + +# Path-C/D BB-AGC + BB-swing + IGI. 8814AU only. +if [[ "$HAS_PATHCD" = "1" ]]; then + for ADDR in 0x1820 0x1824 0x1828 0x182c 0x1830 0x1834 0x1838 0x183c \ + 0x1840 0x181c 0x1850 \ + 0x1a20 0x1a24 0x1a28 0x1a2c 0x1a30 0x1a34 0x1a38 0x1a3c \ + 0x1a40 0x1a1c 0x1a50; do + printf "BB %s = %s\n" "$ADDR" "$(readreg $ADDR)" + done +fi + +# MAC anchors — chip-independent. for ADDR in 0x040 0x0cf 0x0f0 0x100 0x102 0x420 0x4c8 0x508 \ 0x522 0x550 0x560 0x610 0x614; do printf "MAC %s = %s\n" "$ADDR" "$(readreg $ADDR)" done -for PATH_IDX in 0 1; do +# RF: path A always; path B skipped on 1T1R; paths C/D never (write-only +# by HW design on 8814). +PATHS="0" +if [[ "$HAS_PATHB" = "1" ]]; then PATHS="0 1"; fi +for PATH_IDX in $PATHS; do PATH_LBL=$([ "$PATH_IDX" = "0" ] && echo "A" || echo "B") for RF in 0x00 0x05 0x18 0x42 0x65 0x8f; do printf "RF[%s] %s = %s\n" "$PATH_LBL" "$RF" "$(rfread $PATH_IDX $RF)" done done -# 8814AU extension: path-C/D BB-AGC + IGI + BB-swing. RF[C]/RF[D] -# are write-only by HW design on 8814AU (read attempts return undefined -# data), so we only dump BB-table state for paths C/D. -if [[ "$CHIP" = "8814" ]]; then - for ADDR in 0x1820 0x1824 0x1828 0x182c 0x1830 0x1834 0x1838 0x183c \ - 0x1840 0x181c 0x1850 \ - 0x1a20 0x1a24 0x1a28 0x1a2c 0x1a30 0x1a34 0x1a38 0x1a3c \ - 0x1a40 0x1a1c 0x1a50; do - printf "BB %s = %s\n" "$ADDR" "$(readreg $ADDR)" - done -fi - echo "=== END DEVOURER_DUMP_CANARY ==="