mirror of
https://git.k-space.ee/arti/vt1200.git
synced 2026-10-31 12:05:05 +02:00
lance_bcast.c drives the chip entirely on its own -- init block, PADR/LADRF, eight TX and eight RX descriptors, INIT/IDON/STRT, TDMD, completion polling -- and test-bcast.sh runs it in MAME and reports: TXD=6 RXF=5 ET=0x88B5 source MAC 0xC6FC ok=1 PASS The tap capture separates the directions: six 60-byte 0x88b5 broadcasts from 08:00:2b:16:4b:5a (our payload) and 49 from the host. RXF counts host frames (early stop at five) and the recorded source MAC is the host's. Fixes behind it: per-frame TX descriptor (the chip advances its own ring position), cfg-net needed for a tap to exist at all, pkill -x instead of -f, and two bit-vs-byte addressing bugs.
122 lines
4.5 KiB
Bash
Executable File
122 lines
4.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# test-bcast.sh -- run the raw-Ethernet broadcast payload in MAME and report
|
|
# what it sent and received.
|
|
#
|
|
# harness/udpstream/test-bcast.sh [payload.coff]
|
|
#
|
|
# Everything the earlier manual runs got wrong is handled here:
|
|
# * stale MAME is killed with `pkill -x` (a `pkill -f` pattern also matches
|
|
# this script's own command line and kills the test itself)
|
|
# * the network interface choice lives in harness/mame/cfg-net -- an empty
|
|
# cfg dir means MAME never opens a tap, so the LANCE sees no carrier and
|
|
# reports TMD3_LCAR
|
|
# * the host's tap only has carrier once MAME has attached it, so the script
|
|
# waits for LOWER_UP before sending anything
|
|
# * host frames are sent while the payload is inside its listen window
|
|
#
|
|
# Exit status 0 only if the payload reported transmitting and receiving.
|
|
set -uo pipefail
|
|
|
|
ROOT=$(cd "$(dirname "$0")/../.." && pwd)
|
|
M=${MAME:-/home/arti/code/k-space/mame0289/vt1200}
|
|
COFF=${1:-$ROOT/harness/udpstream/build/lance_bcast.coff}
|
|
RUN=${RUN:-/tmp/vt1200-bcast}
|
|
MARK=0x018D0000 # must match #define MARK in the payload
|
|
LOADER_AT=${LOADER_AT:-400}
|
|
LOADER_END=${LOADER_END:-2500}
|
|
DUMP_AT=${DUMP_AT:-1200} # payload now holds after its panel, so any later frame works
|
|
HOST_FRAMES=${HOST_FRAMES:-60}
|
|
|
|
[ -x "$M" ] || { echo "no MAME binary at $M (set MAME=...)" >&2; exit 1; }
|
|
[ -f "$COFF" ] || { echo "no payload at $COFF" >&2; exit 1; }
|
|
|
|
echo "== setting up =="
|
|
pkill -9 -x vt1200 2>/dev/null
|
|
sleep 2
|
|
sudo -n ip link set vt1200 up 2>/dev/null
|
|
|
|
rm -rf "$RUN"
|
|
mkdir -p "$RUN/cfg" "$RUN/nvram"
|
|
cp "$ROOT/harness/mame/cfg-net/vt1200.cfg" "$RUN/cfg/" 2>/dev/null \
|
|
|| { echo "missing harness/mame/cfg-net/vt1200.cfg (the taptun selection)" >&2; exit 1; }
|
|
|
|
TAP=$(ip -o link show 2>/dev/null | sed -n 's/^[0-9]*: \(tap-mess-[^:]*\):.*/\1/p' | head -1)
|
|
[ -n "$TAP" ] || { echo "no tap-mess-* interface -- start MAME once so it exists" >&2; exit 1; }
|
|
echo " tap: $TAP"
|
|
|
|
CAP="$RUN/frames.cap"
|
|
sudo -n timeout 70 tcpdump -i "$TAP" -e -n ether proto 0x88b5 > "$CAP" 2>&1 &
|
|
|
|
VT1200_SKIP_LEVEL1=1 \
|
|
LOADER_AT=$LOADER_AT LOADER_END=$LOADER_END \
|
|
LOADER_BIN="$ROOT/dwt/loader/build/loader.bin" \
|
|
LOADER_COFF="$COFF" LOADER_OUT="$RUN" \
|
|
VT1200_DUMP_RAM=$DUMP_AT VT1200_DUMP_DIR="$RUN" \
|
|
timeout 110 "$M" vt1200 \
|
|
-rompath "$ROOT/harness/mame/roms" -video none -sound none -skip_gameinfo \
|
|
-networkprovider taptun -nvram_directory "$RUN/nvram" -cfg_directory "$RUN/cfg" \
|
|
-debug -debugger none -autoboot_script /tmp/opencode/loader_probe_l3.lua \
|
|
-autoboot_delay 0 > "$RUN/mame.log" 2>&1 &
|
|
|
|
echo "== waiting for link =="
|
|
for i in $(seq 1 60); do
|
|
if ip -o link show "$TAP" 2>/dev/null | grep -q LOWER_UP; then
|
|
echo " carrier up after ${i}s"
|
|
break
|
|
fi
|
|
sleep 1
|
|
done
|
|
ip -o link show "$TAP" 2>/dev/null | grep -q LOWER_UP \
|
|
|| echo " WARNING: no carrier on $TAP -- the chip will report LCAR"
|
|
|
|
echo "== waiting for the payload to start (frame $LOADER_AT ~ $((LOADER_AT / 60))s) =="
|
|
sleep $((LOADER_AT / 60 + 2))
|
|
|
|
echo "== sending $HOST_FRAMES host broadcast frames =="
|
|
for i in $(seq 1 "$HOST_FRAMES"); do
|
|
sudo -n python3 "$ROOT/harness/udpstream/sendraw.py" --iface vt1200 --count 1 --gap 0 >/dev/null 2>&1
|
|
sleep 0.25
|
|
done
|
|
|
|
echo "== waiting for the payload to finish =="
|
|
sleep 8
|
|
pkill -9 -x vt1200 2>/dev/null
|
|
|
|
echo "== results =="
|
|
DUMP=$(ls -1 "$RUN"/vt1200-ram-*.bin 2>/dev/null | head -1)
|
|
if [ -n "$DUMP" ]; then
|
|
python3 - "$DUMP" "$MARK" <<'PY'
|
|
import struct, sys
|
|
d = open(sys.argv[1], 'rb').read()
|
|
base = int(sys.argv[2], 16) >> 3
|
|
def cell(bitoff): # cell() offsets are BIT offsets in the payload
|
|
o = base + (bitoff >> 3)
|
|
return struct.unpack("<I", d[o: o + 4])[0]
|
|
txd, rxf, ok, et, m0 = cell(0x160), cell(0x180), cell(0x1A0), cell(0x200), cell(0x220)
|
|
print(" TXD (frames transmitted) = %d" % txd)
|
|
print(" RXF (frames received) = %d" % rxf)
|
|
print(" last ethertype = 0x%04X" % et)
|
|
print(" last source MAC hi word = 0x%04X" % m0)
|
|
print(" ok = %d" % ok)
|
|
unwritten = (txd == 0x55555555 or rxf == 0x55555555)
|
|
if unwritten:
|
|
print(" markers not written (dump landed outside the run)")
|
|
sys.exit(0 if (not unwritten and txd > 0 and rxf > 0) else 1)
|
|
PY
|
|
RC=$?
|
|
else
|
|
echo " no RAM dump in $RUN"
|
|
RC=1
|
|
fi
|
|
|
|
CAPN=$(grep -c 88b5 "$CAP" 2>/dev/null)
|
|
[ -n "$CAPN" ] || CAPN=0
|
|
echo " payload broadcasts seen on $TAP: $CAPN"
|
|
[ "$CAPN" -gt 0 ] || RC=1
|
|
|
|
echo
|
|
if [ "$RC" = 0 ]; then echo "== PASS =="; else echo "== FAIL =="; fi
|
|
echo " log: $RUN/mame.log"
|
|
echo " pcap: $CAP"
|
|
exit $RC
|