Roflin 0d100eb84f Implement the COMMAND-level interrupt: without it no driver sees a frame
The BBA has two interrupt levels and we implemented only one.  Both drivers'
handlers are identical in shape -- libogc2's bba_event_handler and Swiss's
exi_coroutine:

  status = bba_cmd_in8(0x03);            /* COMMAND level */
  bba_cmd_out8(0x02, BBA_CMD_IRMASKALL);
  if (status & 0x80) bba_interrupt();    /* ONLY then the MAC level */

and bba_interrupt() is what reads register-space IR/IMR and calls
bba_start_rx().  Bit 7 of command register 0x03 means "a MAC interrupt is
pending".  r_cmd_ir was write-1-clear with nothing ever setting it, so a
command read of 0x03 returned 0x00, every branch of both handlers fell through,
and NEITHER DRIVER WOULD EVER HAVE PROCESSED A RECEIVED FRAME.

Our own tooling could not have caught it: gc_bba_test and netboot poll RWP/IR
directly and never use the interrupt path, so the whole command-level mechanism
was untested and unused.  Green suite, dead interface.

cmd_ir[7] is now a live level equal to (IR & IMR) != 0, and INT_N is
(cmd_ir & cmd_imr) != 0.  A level rather than a latch because both drivers
clear the MAC IR inside bba_interrupt() and only then write-1-clear command
0x03: a latched bit would be cleared by that write even if a new frame had
arrived in between, while a level stays asserted as long as the condition does.
INT_N honouring the command-level mask is what stops the line re-asserting
while a handler runs (IRMASKALL on entry, IRMASKNONE on exit).  r_cmd_imr
resets to 0xF8 since the real power-on value is unknown and both drivers set it
explicitly first thing.

T13 and T13b cover it, both mutation-tested: reading the latched bits only
leaves 0x00 after an RI, and ignoring the command mask leaves INT_N asserted
through IRMASKALL.

Also records in CLAUDE.md which driver actually talks to us, since Swiss has
several back-ends and it is easy to read the wrong one: cube/patches/bba/ has
one file per chip (bba.c is ours; enc28j60.c, w5500.c, w6100.c, w6300.c are
other adapters), Swiss's menu networking goes through libogc2's gcif.c, and
cube/patches/bba/bba.c is the in-game patch driver.  Detection is by EXI device
ID, so returning 04 02 02 00 is what gets us handed to the BBA path at all.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-10 11:11:55 +02:00
2026-06-13 19:02:58 +02:00
2026-08-28 10:29:41 +02:00
2026-06-16 14:59:18 +02:00
2026-08-28 10:29:41 +02:00
S
Description
No description provided
60 MiB
Languages
Python 84.9%
C 12.4%
Shell 1.1%
Dockerfile 0.7%
Makefile 0.4%
Other 0.5%