From 7cd0071e7c49dd814123b7ec6b3a663521669233 Mon Sep 17 00:00:00 2001 From: Dennis Brentjes Date: Fri, 9 Oct 2026 11:28:35 +0200 Subject: [PATCH] netboot: reset and enable the adapter before waiting for frames Pressing Z straight after launch is the normal case, and in that case NOTHING has issued the NCRA reset that triggers the W5100's own init. MACRAW would not be running, no frames would be stored, and the transfer would sit in "timeout: no frames" for a reason with nothing to do with netboot -- the most confusing possible first-run failure. Swiss may have initialised the adapter, or an earlier test may have, or neither. An NCRA reset here makes all three cases identical: poll until the RESET bit self-clears, wait out the W5100's 60.3 ms settle (twice over, hence 400 ms), then set the SR bit so RXFrameAssembler actually writes the ring. Resetting also clears the SPRAM ring pointers, which is wanted rather than incidental: a clean ring with RRP == RWP == page 1 means the first frame we see is genuinely the host's first block, not a leftover from a test. PAR0-5 is now read AFTER the reset, so the source address in our ACKs is the one the adapter is actually filtering on. Co-Authored-By: Claude Opus 5 --- gc_bba_test/source/netboot.c | 43 +++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/gc_bba_test/source/netboot.c b/gc_bba_test/source/netboot.c index aafe906..871ba66 100644 --- a/gc_bba_test/source/netboot.c +++ b/gc_bba_test/source/netboot.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -103,16 +104,42 @@ int netboot_receive(void *dst, u32 maxlen, void (*status)(const char *msg)) u64 t0; int have_peer = 0; - if (bba_read(REG_PAR0, s_our_mac, 6) < 0) return -1; - - /* Make sure RX is actually enabled -- a prior test may have left the - * NCRA SR bit clear, and then this would wait forever for frames the - * gateware is not storing. */ + /* Bring the device up deterministically rather than hoping someone else + * already did. Pressing Z straight after launch is the normal case, and + * then NOTHING has issued the NCRA reset that triggers the W5100's own + * init -- MACRAW is not running, no frames are stored, and this would sit + * in "timeout: no frames" for a reason that has nothing to do with the + * transfer. Swiss may have initialised it, or an earlier test may have, + * or neither; a reset here makes all three cases identical. + * + * The reset also clears the SPRAM ring pointers, which is what we want: + * a clean ring with RRP == RWP == page 1, so the first frame we see is + * genuinely the host's first block. */ + if (status) status("resetting the adapter..."); + if (bba_w8(REG_NCRA, NCRA_RESET) < 0) return -1; { - int ncra = bba_r8(REG_NCRA); - if (ncra >= 0 && !(ncra & NCRA_SR)) - bba_w8(REG_NCRA, (u8)(ncra | NCRA_SR)); + int i, v = -1; + for (i = 0; i < 50; i++) { + v = bba_r8(REG_NCRA); + if (v >= 0 && !(v & NCRA_RESET)) break; + usleep(5000); + } + if (i == 50) { + if (status) status("NCRA reset never self-cleared"); + return -1; + } + /* The W5100 re-inits behind that: RSTn pulse plus a 60.3 ms settle, + * done twice. Polling it sooner reads all-zeros and looks dead. */ + usleep(400000); } + /* Start receive. Without the SR bit the assembler never writes the + * ring, so frames arrive at the W5100 and go nowhere. */ + if (bba_w8(REG_NCRA, NCRA_SR) < 0) return -1; + + /* PAR0-5 survives the reset (it is the gateware's power-on MAC), and it + * is read AFTER the reset so the source address we put in ACKs is the + * one the adapter is actually filtering on. */ + if (bba_read(REG_PAR0, s_our_mac, 6) < 0) return -1; if (status) status("waiting for host (send-dol.py)..."); t0 = gettime();