TX: count the TXDATA bytes, because libogc never writes TWD
Third contract checked against libogc rather than our notes. __bba_link_tx is four transactions -- read NWAYS, ONE register-space write of the whole frame to 0x0048, read NCRA, write NCRA = 0x04 -- with no TWD_LO/TWD_HI anywhere. So the device has to count the bytes it was handed. The NCRA ST fallback queued tx_frame_len, which only TWD sets, so any driver that skips TWD would have transmitted a stale or zero length. BBARegisterFile now keeps txdata_cnt, incremented per byte accepted at 0x0048 and cleared whenever a frame is queued from either path, and the ST path queues that. T11 drives TX in libogc's shape with no TWD write and checks both the queued length and the drained bytes. Mutation-tested: switching the ST path back to tx_frame_len queues length 0, which is exactly the bug. gc_bba_test gains the hardware counterpart, "TX without TWD", which deliberately omits the TWD writes that t_tx makes. The TWD path stays and is still preferred when present: writing the length before streaming is what lets TXFrameDrain consume concurrently and keeps tx_bytes a rate-matching buffer rather than whole-frame storage. Swiss writes TWD, libogc does not, so both are supported. Also recorded: libogc streams the payload with EXI_Dma (32-byte-aligned bulk after PPCDCacheStoreAsync, then EXI_ImmEx for the remainder). CLAUDE.md said EXI DMA writes are avoided for the GC's 1-bit-shift bug; that is true of Swiss, not libogc. Nothing in the gateware changes -- a DMA write is just bytes clocked in -- but the path will be exercised, and if that bug is real it appears as corrupted TX frames that are not fixable here. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1239,6 +1239,44 @@ parallel master is the default — see "W5100 vs W5500".)
|
||||
|
||||
---
|
||||
|
||||
## TX path — libogc writes NO TWD (found 2026-10-10)
|
||||
|
||||
`__bba_link_tx` is **four transactions**:
|
||||
|
||||
| # | transaction |
|
||||
|---|---|
|
||||
| 0 | read reg `0x0031` (NWAYS) — check the link first |
|
||||
| 1 | **one** register-space write to `0x0048`, the whole frame |
|
||||
| 2 | read reg `0x0000` (NCRA) |
|
||||
| 3 | write reg `0x0000` = `0x04` (NCRA ST) |
|
||||
|
||||
⚠️ **There is no `TWD_LO`/`TWD_HI` write anywhere**, so the device has to
|
||||
COUNT the bytes it was handed. `BBARegisterFile` now keeps `txdata_cnt`,
|
||||
incremented per byte accepted at `0x0048`, and the NCRA ST fallback queues
|
||||
**that** rather than `tx_frame_len`. Previously it queued `tx_frame_len`,
|
||||
which a driver that skips TWD never sets — so the frame would have gone out
|
||||
with a stale or zero length. `bba_register_file` **T11** drives TX in libogc's
|
||||
shape with no TWD and is mutation-tested: switching the ST path back to
|
||||
`tx_frame_len` queues length 0. `gc_bba_test` has the hardware counterpart
|
||||
(**TX without TWD**).
|
||||
|
||||
The TWD path stays, and is still preferred when present: writing the length
|
||||
before streaming is what lets `TXFrameDrain` consume concurrently and keeps
|
||||
`tx_bytes` a rate-matching buffer instead of whole-frame storage (see the TWD
|
||||
fix note). Swiss writes TWD; libogc does not. Support both.
|
||||
|
||||
⚠️ **libogc streams the payload with `EXI_Dma`** — the 32-byte-aligned bulk via
|
||||
`EXI_Dma` after a `PPCDCacheStoreAsync`, then `EXI_ImmEx` for the remainder.
|
||||
This file says elsewhere that EXI DMA *writes* are avoided because the GC's
|
||||
DMA-write engine has a 1-bit-shift bug; that is true of **Swiss**, not of
|
||||
libogc, which uses them routinely for TX. From the FPGA's side a DMA write is
|
||||
just bytes clocked in, so nothing in the gateware changes — but it means the
|
||||
DMA-write path WILL be exercised by libogc-based software, and if the shift bug
|
||||
is real it will show up as corrupted TX frames that are not our fault and not
|
||||
fixable here. Worth knowing before chasing it in the gateware.
|
||||
|
||||
---
|
||||
|
||||
## RX Ring Descriptor — the format GC software actually expects
|
||||
|
||||
✅ **Corrected 2026-10-10 from libogc's own driver.** The 4 bytes at each ring
|
||||
|
||||
Reference in New Issue
Block a user