Files
vt1200/harness
arti 0563cb08e8 udpstream: LANCE command payload -- peek/poke/jump/reboot, benchmark, driver-matched RX
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.
2026-10-30 16:57:15 +02:00
..