gc_bba_test: fix inverted EXI error checks; builds clean

libogc's EXI functions return '1 on success, <=0 on error', but every call
site tested '== 0'.  A -1 error return therefore read as success, so a failed
EXI_Lock or EXI_Select would fall through and the subsequent transfer would
produce garbage reported as a misleading test failure rather than an EXI
error.  All six call sites now test <= 0.

Also retries EXI_Lock for ~100 ms: it fails outright rather than blocking when
another subsystem holds the channel, and Swiss or a libogc driver may hold it
briefly -- without the retry a transient collision surfaces as a test failure.

Builds clean with devkitPPC 16.1.0 / GCC 16, no warnings: 172 KB .dol.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-10-03 11:24:47 +02:00
parent ccf4eb4996
commit d8725392a5
5 changed files with 54 additions and 21 deletions
+17 -7
View File
@@ -1,5 +1,6 @@
#include "bba.h"
#include <string.h>
#include <unistd.h>
u32 bba_speed = EXI_SPEED32MHZ; /* nominal name; ~27 MHz in reality */
@@ -17,8 +18,17 @@ static u16 hdr(u16 addr, u32 len, int write)
static int begin(void)
{
if (EXI_Lock(BBA_EXI_CHAN, BBA_EXI_DEV, NULL) == 0) return -1;
if (EXI_Select(BBA_EXI_CHAN, BBA_EXI_DEV, bba_speed) == 0) {
int tries;
/* EXI_Lock fails outright (rather than blocking) when another subsystem
* holds the channel -- Swiss or a libogc driver may have it briefly.
* Retry for ~100 ms before giving up so a transient collision does not
* surface as a test failure. */
for (tries = 0; tries < 100; tries++) {
if (EXI_Lock(BBA_EXI_CHAN, BBA_EXI_DEV, NULL) > 0) break;
usleep(1000);
}
if (tries == 100) return -1;
if (EXI_Select(BBA_EXI_CHAN, BBA_EXI_DEV, bba_speed) <= 0) {
EXI_Unlock(BBA_EXI_CHAN);
return -2;
}
@@ -34,8 +44,8 @@ static void end(void)
static int put_hdr(u16 addr, u32 len, int write)
{
u16 h = hdr(addr, len, write);
if (EXI_Imm(BBA_EXI_CHAN, &h, 2, EXI_WRITE, NULL) == 0) return -3;
if (EXI_Sync(BBA_EXI_CHAN) == 0) return -4;
if (EXI_Imm(BBA_EXI_CHAN, &h, 2, EXI_WRITE, NULL) <= 0) return -3;
if (EXI_Sync(BBA_EXI_CHAN) <= 0) return -4;
return 0;
}
@@ -49,7 +59,7 @@ int bba_read(u16 addr, void *buf, u32 len)
* header and prefetches the response into its TX FIFO. Separate EXI_Imm
* calls give us that gap for free. */
memset(buf, 0, len);
if (EXI_ImmEx(BBA_EXI_CHAN, buf, len, EXI_READ) == 0) { end(); return -5; }
if (EXI_ImmEx(BBA_EXI_CHAN, buf, len, EXI_READ) <= 0) { end(); return -5; }
end();
return 0;
}
@@ -62,7 +72,7 @@ int bba_write(u16 addr, const void *buf, u32 len)
memcpy(tmp, buf, len);
if ((rc = begin()) < 0) return rc;
if ((rc = put_hdr(addr, len, 1)) < 0) { end(); return rc; }
if (EXI_ImmEx(BBA_EXI_CHAN, tmp, len, EXI_WRITE) == 0) { end(); return -6; }
if (EXI_ImmEx(BBA_EXI_CHAN, tmp, len, EXI_WRITE) <= 0) { end(); return -6; }
end();
return 0;
}
@@ -89,7 +99,7 @@ int bba_stream(u16 addr, void *buf, u32 len)
* bytes as we actually want. */
if ((rc = put_hdr(addr, 4, 0)) < 0) { end(); return rc; }
memset(buf, 0, len);
if (EXI_ImmEx(BBA_EXI_CHAN, buf, len, EXI_READ) == 0) { end(); return -5; }
if (EXI_ImmEx(BBA_EXI_CHAN, buf, len, EXI_READ) <= 0) { end(); return -5; }
end();
return 0;
}