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();