forked from arti/vt1200
lance_cmd.c is a payload that drives the LANCE with its own code (no ROM
calls) and answers a command protocol on ethertype 0x88B6, so a unit whose
chip we have taken over can still be inspected:
read (peek), stats, poke, jump, reboot
The reply path was dead for a while and the cause was not the chip: the RX
ring had been grown to 16 entries (0x3020..0x309F) while TXR stayed at
0x3060, so all eight TX descriptors lay inside the RX ring. The chip's RX
write-back set OWN in what we believed were TX descriptors, and every reply
was discarded by transmit_poll() as "owned but not start of packet"
(r 00309A 8000 / w 00309A 0000 in the DMA log). TX ring moved to 0x30C0,
with a compile-time guard so the rings cannot overlap again.
Receive path aligned with the three drivers available locally (4.4BSD
pmax if_le.c, NetBSD am7990.c, Linux 7990.c):
* STP *and* ENP required on one descriptor, else the frame is counted as
chained and dropped rather than parsed from the middle of a buffer;
* the 4-byte FCS the chip writes into the buffer is subtracted, as all
three do (rmd3 - 4);
* re-arm restores RMD2 and clears RMD3, ownership written last;
* TX kick is TDMD|INEA (no reference driver re-writes STRT);
* a TX slot still owned is skipped instead of clobbered.
RX buffers are 1526 B so a full 1514-byte MTU frame fits one descriptor;
1500 B would have chained it.
vtcmd.py drives all of it; bench-sweep.sh sweeps size x rate. Measured on
the real VT1200 (10 Mbit half-duplex hub): 856-858 fps of 1514-byte frames
at 99.9-100% delivery, i.e. wire limited, and 1500 fps of 60-byte frames at
99.8-99.9%. NETWORK_REPORT.md sections 68-72 record the evidence, including
the 64-descriptor build that died with an illegal opcode on the unit and was
reverted.
38 lines
1.4 KiB
Bash
38 lines
1.4 KiB
Bash
#!/bin/sh
|
|
# bench-sweep.sh -- measure the receive path of the LANCE command payload
|
|
# (harness/udpstream/lance_cmd.c) across frame sizes and offered rates.
|
|
#
|
|
# ./bench-sweep.sh vt1200 # MAME (tap interface)
|
|
# sudo ./bench-sweep.sh enp197s0f3u1 08:00:2b:16:4b:5a # real unit
|
|
#
|
|
# Output is one CSV line per run:
|
|
#
|
|
# size,rate,seconds,sent,frames,bytes,fps,KiB/s,Mbit/s,delivery%,csr0_err,txfull,chained
|
|
#
|
|
# "delivery" below 100% means frames were offered and not received. csr0_err
|
|
# tells you which side lost them: MISS (0x1000) = the chip had no descriptor
|
|
# (ring too small or the loop too slow); no MISS = they never reached the chip
|
|
# (wire, switch, or the sender).
|
|
#
|
|
# The unpaced runs are deliberately last and slowest-to-recover: a 60-byte
|
|
# flood is far above both the wire and the loop, and it exists only to show
|
|
# where the ceiling is.
|
|
set -e
|
|
|
|
IFACE=${1:-vt1200}
|
|
DST=${2:-ff:ff:ff:ff:ff:ff}
|
|
SECS=${SECS:-2}
|
|
HERE=$(cd "$(dirname "$0")" && pwd)
|
|
|
|
echo "size,rate,seconds,sent,frames,bytes,fps,KiB/s,Mbit/s,delivery%,csr0_err,txfull,chained"
|
|
|
|
for size in 60 200 500 1000 1514; do
|
|
for rate in 500 1000 2000 4000; do
|
|
python3 "$HERE/vtcmd.py" bench --iface "$IFACE" --dst "$DST" \
|
|
--size "$size" --rate "$rate" --seconds "$SECS" --terse || break
|
|
done
|
|
# as fast as the host can send
|
|
python3 "$HERE/vtcmd.py" bench --iface "$IFACE" --dst "$DST" \
|
|
--size "$size" --seconds "$SECS" --terse || break
|
|
done
|