diff --git a/gc_bba_test/source/netboot.c b/gc_bba_test/source/netboot.c index 871ba66..057ac21 100644 --- a/gc_bba_test/source/netboot.c +++ b/gc_bba_test/source/netboot.c @@ -136,6 +136,31 @@ int netboot_receive(void *dst, u32 maxlen, void (*status)(const char *msg)) * ring, so frames arrive at the W5100 and go nowhere. */ if (bba_w8(REG_NCRA, NCRA_SR) < 0) return -1; + /* Establish a KNOWN ring state instead of trusting what we inherited. + * Swiss initialises the BBA before launching us and writes RRP itself, + * and an NCRA reset does not restore the register file's copy of either + * pointer -- their init values only apply at FPGA configuration. So + * RRP can legitimately be anything, including 0, which is outside the + * ring (pages 1-15) and used to abort the whole transfer. + * + * Setting RRP = RWP declares the ring empty and consistent, whatever it + * was, so the first frame we read is genuinely the host's first block. */ + { + u8 wp[2]; + if (bba_read(REG_RWP_LO, wp, 2) < 0) return -1; + if (wp[0] < 1 || wp[0] > 15) { + /* RWP is the gateware's own pointer, so this should not + * happen -- say so loudly rather than papering over it. */ + if (status) { snprintf(line, sizeof(line), + "RWP=%u outside ring pages 1-15", wp[0]); + status(line); } + return -5; + } + if (bba_w8(REG_RRP_LO, wp[0]) < 0) return -1; + if (status) { snprintf(line, sizeof(line), + "ring synced at page %u", wp[0]); status(line); } + } + /* 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. */ @@ -147,8 +172,21 @@ int netboot_receive(void *dst, u32 maxlen, void (*status)(const char *msg)) for (;;) { int n = ring_next(frame, sizeof(frame)); if (n < 0) { - if (status) { snprintf(line, sizeof(line), "ring error %d", n); - status(line); } + /* Report the pointers, not just the code: -1 is an EXI access + * failure, -2 an RRP outside the ring, -3 a descriptor whose + * length is implausible. Which one it is, and what the + * pointers read, is the whole diagnosis. */ + u8 rp[2] = {0xFF, 0xFF}, wp[2] = {0xFF, 0xFF}; + bba_read(REG_RRP_LO, rp, 2); + bba_read(REG_RWP_LO, wp, 2); + if (status) { + snprintf(line, sizeof(line), + "ring error %d (RRP=%u RWP=%u) %s", n, rp[0], wp[0], + n == -1 ? "EXI access failed" : + n == -2 ? "RRP outside pages 1-15" : + "descriptor length implausible"); + status(line); + } return -2; } if (n == 0) {