8814: boot the 3081 MCU — TX + RX on every band#97
Merged
Conversation
#50 TX-silence root cause) The rtw88-mimic fwdl sequence left CPU_DL_READY (REG_MCUFWDL bit15) permanently deasserted: FW bytes landed (DDMA checksum OK) but the 3081 never booted, so host-pushed TX was 0 on-air while RX worked. Replace the fwdl bracket with a verbatim port of the vendor kernel's FirmwareDownload8814A + HalROMDownloadFWRSVDPage8814A (hal/rtl8814a/rtl8814a_hal_init.c), wired through the pre-existing kernel-faithful helpers that were never called: _FWDownloadEnable_8814A(true) RMW 0x0080 bit13|bit0 _3081Disable8814A RMW, hold MCU in reset _DDMAReset8814A 0x1080 BIT16 clear->set toggle HalROM RSVD-page download 1488-byte chunks; beacon-queue state set once (not per-chunk); 0x0205 BIT7 ack poll/clear via RMW; per-section checksum-driven DL_RDY|CHKSUM_OK RMW FW_DW_RDY (0x0081 |= BIT6) only if both section checksums OK _3081Enable8814A release MCU -> fw boots _FWDownloadEnable_8814A(false) RMW clear bit0 poll CPU_DL_READY The rtw88-mimic power-on prefix is retained (it is devourer's only 8814 power-on path), as are the pre-fwdl staging ops whose kernel equivalents live in _InitPowerOn_8814AU/_InitQueueReservedPage. The legacy sequence is preserved bit-for-bit behind DEVOURER_8814_FWDL=rtw88; DEVOURER_8814_FWDL_CHUNK overrides the kernel chunk size. Per-step register-state dumps (_DumpFwdlState8814A) trace the bracket. Hardware-validated on a virgin chip (Vbus power-cycled): - REG_MCUFWDL trajectory 0x...2079 -> 0x...6079 -> 0x...E078 (CPU_DL_READY asserts instantly on _3081Enable) - TX on-air at the kernel-monitor witness: ch6 12844, ch36 10752, ch100 10817 canonical-SA frames (previously 0 at every channel) - 8814 RX at ch6 unaffected; 8812 TX unaffected (8463 frames) - DEVOURER_8814_FWDL=rtw88 still reproduces the failure (0x00606078), a clean causal A/B Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The minimal {}-formatter streamed uint8_t via `oss << value`, inserting a
raw char — register values like 0xF0 became invalid UTF-8 bytes in the
log (e.g. the 8814 RFE pin-select line) and crashed tests/regress.py's
strict-UTF-8 log parsing, zeroing the devourer cells. Widen
unsigned/signed char at the stream site (plain `char` untouched), make
regress.py's parsers errors="replace" tolerant anyway, and widen the
fwdl state-dump reads explicitly.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
README hardware table: 8814 row flips to TX + RX across 2.4 GHz / UNII-1 / UNII-2-3 (regress matrix green at ch6/ch36/ch100); intro no longer lists it as the band-gapped part. CLAUDE.md: chip-status paragraph reflects the 3081-MCU firmware-boot fix (issue #95), the regression section drops the stale broken-cells list and gains the kernel-TX matrix-interpretation caveat (88XXau host-push beacon inject doesn't emit, judge 8814 TX by devourer-TX cells), and the issue #36 passthrough-cycle gotcha is rewritten as resolved/historical. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CLAUDE.md and README describe what the driver does now; git history is the changelog. Drop the resolved-gotcha entry, the "since fix #NNN" phrasing, PR-body references, and the redundant 8812 table note. Keep only operative facts (8814 TX needs the booted 3081 MCU; kernel-TX matrix cells aren't authoritative for 8814). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
e920c13 to
ef06a4d
Compare
This was referenced Jun 11, 2026
josephnef
added a commit
that referenced
this pull request
Jun 11, 2026
…scaffolds (#98) ## Summary Post-port hygiene sweep: the codebase is open source and should be self-explanatory, but comments referenced an internal notes system, files that were never committed (`TODO.md`, `tools/gen_rtw88_mimic.py`), and carried debugging scaffolds from the now-finished 8814 TX investigation. All factual content is preserved in-place; only the pointers and dead scaffolds go. Net **−4,831 lines**. ### Comments rewritten as self-contained - Internal-notes citations → plain statements (8814 RF paths C/D are write-only by HW design; 8821 ch100 wedge is triggered by the second channel-set, not the band-switch) - `TODO.md` pointers → "kernel-vs-devourer register canary diff" provenance - Dropped the `/tmp/rtw88_init.seq` / `gen_rtw88_mimic.py` pointer (never committed) ### Scaffolds removed (superseded or never validated) - `DEVOURER_OOT_REPLAY` + `hal/Hal8814_PostFwdlReplay.h` — 135 KB usbmon replay table; superseded by the kernel-faithful fwdl bracket (#97) - `DEVOURER_8814_DEINIT_BEFORE_INIT` — experimental gate; the warm-state wedge it targeted no longer reproduces - `DEVOURER_PROBE_MCUFWDL` demo probe and the unconditional 18-line "8814A TX-state" init log dump ### Docs - `tests/README.md`: stale "known broken cells (8814 RX, 8821 TX/RX)" claims replaced with the current operative caveat (kernel-TX cells with 8814: `88XXau` host-push beacon injection doesn't emit — judge by devourer-TX cells) - `docs/8814-port-audit.md` deleted — investigation-process report (pending-validation plans); history lives in git Kept deliberately: the 2024-era vendor-port TODOs (inherited-code provenance) and `DEVOURER_USB_SENTINEL` (self-documented, wired to the in-repo usbmon diff tooling). ## Validation - Build green (GCC, all targets) - Hardware smoke after the init-path removals: RTL8814AU TX ch6 → 6,238 frames on-air at the monitor witness; submits clean 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The RTL8814AU's 3081 MCU firmware never booted under devourer —
CPU_DL_READY(REG_MCUFWDL bit15) never asserted — which was the root cause of dead host-pushed TX (#50, #95) while RX worked. (The port-audit groundwork merged separately as #96; this PR is the firmware-boot fix on top.)Firmware-boot fix
The fwdl bracket is now a verbatim port of the vendor kernel's
FirmwareDownload8814A+HalROMDownloadFWRSVDPage8814A, wired through helpers that already existed in-tree but were never called:_FWDownloadEnable_8814A→_3081Disable→ DDMA BIT16 toggle → RSVD-page download (kernel chunking, beacon-queue state set once, per-section checksum-drivenDL_RDY|CHKSUM_OKRMW) → conditionalFW_DW_RDY→_3081Enable→ pollCPU_DL_READY.The rtw88-mimic power-on prefix is retained (devourer's only 8814 power-on path). The legacy fwdl sequence is preserved bit-for-bit behind
DEVOURER_8814_FWDL=rtw88and still reproduces the failure — clean causal A/B.DEVOURER_8814_FWDL_CHUNKoverrides chunk size;_DumpFwdlState8814Atraces each bracket step.Boot trajectory on a virgin chip:
REG_MCUFWDL 0x...2079 → 0x...6079 → 0x...E078(CPU_DL_READYasserts instantly on_3081Enable).Also in this PR
0xF0were landing in logs as invalid UTF-8 and crashingtests/regress.pyparsing); regress parsers made byte-tolerantValidation (real hardware)
Regress matrix, TX=RTL8814AU / RX=RTL8812AU, VM-mode kernel cells:
(kernel-TX cells read 0 at every channel —
88XXauhost-push beacon injection doesn't emit on that driver; its probe-request injection does. Pre-existing, documented in CLAUDE.md.)LIBUSB_ERROR_IO, 10,688 frames on-air, FW boots from the dirty post-passthrough stateFixes #95. Fixes #50. Fixes #36.
🤖 Generated with Claude Code