6f151cd1ff
Reading one byte and getting 0x00 cannot distinguish 'decode is wrong' from 'reply is late' -- a one-byte window has nowhere for a late answer to show up. These two probes clock EIGHT data bytes and print every slot, so the position of 0x17 (NWAYS) or 0x04 (device ID) gives the latency directly, the same way bit-shift analysis turned 00 00 00 10 into 'correct, 22 bits late'. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
93 lines
3.3 KiB
C
93 lines
3.3 KiB
C
/* bba.h — raw EXI transport to the re-bba-rb adapter in Serial Port 1.
|
|
*
|
|
* Deliberately NOT libogc's bba network driver: this talks to the register
|
|
* file directly so every check gets its own pass/fail and a failure points at
|
|
* a specific register rather than at "networking".
|
|
*/
|
|
#ifndef BBA_H
|
|
#define BBA_H
|
|
|
|
#include <gccore.h>
|
|
|
|
/* Serial Port 1 == EXI channel 0, device 2. */
|
|
#define BBA_EXI_CHAN EXI_CHANNEL_0
|
|
#define BBA_EXI_DEV EXI_DEVICE_2
|
|
|
|
/* Register map (see CLAUDE.md "Key Registers"). */
|
|
#define REG_NCRA 0x00
|
|
#define REG_IMR 0x08
|
|
#define REG_IR 0x09
|
|
#define REG_RWP_LO 0x16
|
|
#define REG_RWP_HI 0x17
|
|
#define REG_RRP_LO 0x18
|
|
#define REG_PAR0 0x20
|
|
#define REG_PAR4 0x24
|
|
#define REG_NWAYS 0x31
|
|
#define REG_TWD_LO 0x34
|
|
#define REG_TWD_HI 0x35
|
|
#define REG_HIPR 0x3A
|
|
#define REG_TXDATA 0x48
|
|
#define SPRAM_BASE 0x0100
|
|
|
|
/* NCRA bits */
|
|
#define NCRA_RESET 0x01
|
|
#define NCRA_ST0 0x02
|
|
#define NCRA_SR 0x08
|
|
|
|
/* IR bits */
|
|
#define IR_RI 0x02
|
|
#define IR_TI 0x04
|
|
|
|
/* Expected constants */
|
|
#define NWAYS_LINKUP 0x17
|
|
#define HIPR_PRESENT 0x01
|
|
|
|
/* EXI clock index, EXI_SPEED1MHZ(0) .. EXI_SPEED32MHZ(5). The nominal 32 MHz
|
|
* index is really ~27 MHz on hardware (see CLAUDE.md); the capture domain
|
|
* oversamples it 2x at 54 MHz. Settable so the suite can sweep it. */
|
|
extern u32 bba_speed;
|
|
|
|
/* Microseconds to hold the clock idle between the header write and the data
|
|
* phase, with CS still asserted. The register file decodes the header and
|
|
* PROACTIVELY pushes the response into its TX FIFO during this gap; until the
|
|
* first byte reaches the FIFO head the device drives MISO low. Measured on
|
|
* hardware 2026-10-03: at EXI index 5 the reply arrived 22 bit-times (~815 ns)
|
|
* late with no explicit gap, so a 4-byte read returned 00 00 00 10 -- the
|
|
* correct stream, just shifted out of the window. 0 = whatever gap libogc's
|
|
* inter-call overhead happens to give. */
|
|
extern u32 bba_gap_us;
|
|
|
|
/* All return 0 on success, negative on an EXI-layer failure. */
|
|
|
|
/* REGISTER-space read: 4-byte header [0x80, ah, al, 0x00] then `len` bytes.
|
|
* The real protocol has NO length field -- the data phase runs until CS, so
|
|
* `len` is unbounded. The trailing 0x00 header byte is the device's prefetch
|
|
* window. See docs/exi_protocol_real.md. */
|
|
int bba_read(u16 addr, void *buf, u32 len);
|
|
|
|
/* REGISTER-space write: 4-byte header [0xC0, ah, al, 0x00] then `len` bytes. */
|
|
int bba_write(u16 addr, const void *buf, u32 len);
|
|
|
|
/* EXI_GetID: write 0x0000 (two bytes) then read 4. Returns the device ID,
|
|
* which is a ONE-SHOT -- the first NCRA reset clears it until power cycle. */
|
|
int bba_devid(u8 id[4]);
|
|
|
|
/* Raw transaction framing, for probes that build their own byte sequence. */
|
|
int begin_raw(void);
|
|
void end_raw(void);
|
|
|
|
/* Convenience single-byte helpers. bba_r8 returns the byte, or <0 on error. */
|
|
int bba_r8(u16 addr);
|
|
int bba_w8(u16 addr, u8 val);
|
|
|
|
/* SPRAM / DMA-style read: any address >= 0x0100 streams until CS deasserts,
|
|
* so `len` may exceed 4 and the header's 2-bit length field is ignored. */
|
|
int bba_stream(u16 addr, void *buf, u32 len);
|
|
|
|
/* Stream `len` bytes into the TXDATA port. One byte per EXI transaction:
|
|
* the register file's effective address auto-increments per data byte, so a
|
|
* multi-byte write to 0x48 would spill into 0x49+ instead of the FIFO. */
|
|
int bba_tx_bytes(const u8 *buf, u32 len);
|
|
|
|
#endif
|