Filter RX to own-MAC + broadcast: unfiltered MACRAW hung Swiss
Compat TODO item 1. S0_MR now sets the MACRAW MF bit, so the W5100 delivers
frames addressed to SHAR or broadcast only -- what the real BBA does, since
libogc2 configures NCRB = AB|CA|2_PACKETS_PER_INT (PR=0, PM=0, AB=1).
NCRB.PR (bit 0) clears MF if the GC asks for promiscuous, sampled when socket 0
is OPENed, so a later PR change applies on the next NCRA reset.
This was not a performance issue, it was a HANG. Swiss sat on "Initialising
Network" forever. libogc2's bba_interrupt() loops
while (status) { clear IR; start_rx; status = IR & IMR; }
which only exits when IR & IMR reaches zero. Unfiltered, every frame on the
segment set RI, re-asserting faster than the loop could clear it, so it never
exited. Unplugging the ethernet cable let Swiss run all the way through and
then fail DHCP for want of a server -- a one-minute experiment that identified
it after a lot of theorising about descriptors and interrupts.
Filtering against SHAR turned out to be safe for this path after all. The
earlier worry was that MF filters on SHAR, which we write only at init, so a
driver WRITING PAR0-5 would leave it stale and MF would drop everything.
libogc2 READS the MAC out of PAR0-5 instead, so SHAR -- written from reg.par in
that same init -- cannot go stale underneath it. Broadcast still passes MF and
a DHCP OFFER unicast to our MAC passes too.
Left open and recorded: refreshing SHAR on a PAR0-5 write plus a socket
re-open, for a driver that does write it (the official SDK driver is unread).
The W5500 back-end is unchanged, being the unused alternate path; it would need
the same Sn_MR treatment if revived.
T1 expects S0_MR = MACRAW|MF in the init sequence, T1b checks promisc high
re-inits with MF clear. Mutation-tested: never setting MF fails both.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+44
-2
@@ -25,9 +25,51 @@ The register map referenced throughout is the one in libogc2's `gcif.c`
|
||||
|
||||
---
|
||||
|
||||
## 1. No hardware RX filtering — **the consequential one**
|
||||
## 1. No hardware RX filtering — **it hung Swiss**
|
||||
|
||||
**Status: OPEN. Needs a decision, not just code.**
|
||||
**Status: ✅ DONE 2026-10-10** — `S0_MR` now sets the MACRAW **MF** bit, so the
|
||||
W5100 delivers own-MAC (`SHAR`) + broadcast only, matching what the real BBA
|
||||
does. `NCRB.PR` (bit 0) clears MF if the GC asks for promiscuous, sampled when
|
||||
socket 0 is OPENed (i.e. at init, so a later `PR` change takes effect on the
|
||||
next NCRA reset).
|
||||
|
||||
**How it presented, which is worth knowing because it does not look like a
|
||||
filtering problem.** Swiss hung forever on "Initialising Network". libogc2's
|
||||
`bba_interrupt()` is
|
||||
|
||||
```c
|
||||
ir = bba_in8(BBA_IR); imr = bba_in8(BBA_IMR); status = ir & imr;
|
||||
while (status) { bba_out8(BBA_IR, status); ... start_rx ...; status = ir & imr; }
|
||||
```
|
||||
|
||||
— it only exits when `IR & IMR` reaches zero. Unfiltered, every frame on the
|
||||
segment set `RI`, which re-asserted faster than the loop could clear it, so it
|
||||
**never exited**. Not slow: livelocked. Unplugging the ethernet cable let Swiss
|
||||
get all the way through (then fail DHCP, there being no server), which is what
|
||||
identified it — a one-minute experiment after a lot of theorising.
|
||||
|
||||
**Why filtering against `SHAR` was safe after all.** The earlier worry was that
|
||||
MF filters on `SHAR`, which we write only during init, so a driver that WRITES
|
||||
PAR0–5 would leave it stale and MF would drop everything. libogc2 **reads** the
|
||||
MAC out of PAR0–5 rather than writing it, so for this path `SHAR` (written from
|
||||
`reg.par` in the same init) cannot go stale. Broadcast still passes MF, and a
|
||||
DHCP OFFER unicast to our MAC passes too.
|
||||
|
||||
⚠️ **Still to do for a driver that writes PAR0–5 after init:** refresh `SHAR`
|
||||
on a PAR write and re-open the socket, otherwise MF filters on the old MAC.
|
||||
Nothing we have seen does this, but the official SDK driver is unread.
|
||||
|
||||
⚠️ **The W5500 back-end was NOT changed** — it is the alternate path and
|
||||
unused. If it is ever revived it needs the same treatment (`Sn_MR` MF bit).
|
||||
|
||||
Tests: `w5100_parallel_master` **T1** (the init sequence expects
|
||||
`S0_MR = MACRAW|MF`) and **T1b** (`promisc` high re-inits with MF clear).
|
||||
Mutation-tested: never setting MF fails both, with the message naming the
|
||||
Swiss hang.
|
||||
|
||||
### Original analysis, kept for the reasoning
|
||||
|
||||
**Was: OPEN. Needs a decision, not just code.**
|
||||
|
||||
The real BBA filters received frames. libogc2 configures
|
||||
`NCRB = AB|CA|2_PACKETS_PER_INT` = `0x52`, i.e. `PR=0` (not promiscuous),
|
||||
|
||||
Reference in New Issue
Block a user