network: multi-record DaynaPort READ(6) matching real SCSI/Link behavior#399
network: multi-record DaynaPort READ(6) matching real SCSI/Link behavior#399ingpaschke wants to merge 4 commits into
Conversation
scsiNetworkEnqueue advanced writeIndex onto readIndex when the ring filled, which makes a completely full ring indistinguishable from an empty one: the DaynaPort READ(6) handler then reports no packets and every queued packet is dropped at once, showing up as bursts of lost inbound frames and TCP retransmissions under load. Compute the next write index first and drop only the incoming packet when the ring is full.
The 20-slot ring overflows during wifi receive bursts between host READ(6) polls, dropping packets that then cost TCP retransmissions. The Pico 2 W target has the RAM for a deeper ring (~1.5 KB/slot), so set NETWORK_PACKET_QUEUE_SIZE=48 in its target definitions, using the existing override hook (as Pico_Audio_SPDIF already does with 12). Other targets keep the 20-slot default.
|
A bit outside the scope of this PR, and to be clear the gate isn't mine: 7c20579 came in via #350, which is why there was never a thread for it. On the substance: CDB[5] is just how the driver tells the device how it intends to clock bytes off the bus. Why it picks one mode over the other is a host-side decision, and I don't think the firmware should be modelling it. Respecting the request is the right call. This new code does multiple packets per read in polled mode anyway (4 records rather than 1, roughly the real SCSI/Link's 6 KB packet memory) so nothing collapses to a single packet either way. An interesting aside: So your pause timings, which I left untouched, were captured from a real SCSI/Link-3 with a Mac Plus as the host. If the Plus is requesting polled mode, then those numbers characterise polled-mode pacing and we're applying them unchanged to blind hosts, where the requirement is real but the magnitude is unvalidated. I've only tested them on/off: removing them breaks blind-mode on my SE/30 and is worth about 10 KB/s on the Atari Falcon. I never swept the value. Do you know what CDB[5] your Plus actually sends, and did the SCSI/Link pace differently depending on that bit? Could you dump the ROM of the real Dayna SCSI/Link? I just tested Appletalk performance on my SE/30 with VM on on 7.5.5 and it's totally fine with the new code at least. |
|
I found the ROMs for the Dayna SCSI/Link! Will reverse engineer and that will give me an even better understanding what the real hardware did. |
Derived from Dayna SCSI/Link SL003 device firmware (Z180 ROMs v1.3b2 and v2.0; addresses from v2.0). CDB[5] bit 6 selects the host's transfer loop (blind/polled); the ROM dispatches on it at 0x0f3b. - Polled: one record per READ(6), no terminator (ROM 0x0d77). DaynaPORT 7.5.3 requests a single record's allocation and wedges the bus on more. Honor the CDB[1..2] byte offset; dequeue only when the read reached the packet's end or CDB[5] is nonzero (0x0ea2-0x0f17); allocation <= 6 is a header-only peek without dequeue (0x0ea0). - Blind: multi-record batch. Cap at 16 records to bound the bus hold (device ROM: v1.3 unbounded, v2.0 capped at 200, 0x0d5c). Zero terminator record only when a capped batch promised more (0x0c1c); none at end of queue (0x0cb0). Never truncate a mid-batch record; no batching after a peek, offset, partial, or truncated read. - Both modes: 0x10 'more pending' flag reported truthfully from queue occupancy (0x0ca6, 0x0df2); previously never set in polled mode. Allocation-length payload cap applies per record, not cumulatively (0x0cf2, 0x0e8a). Dequeue a ring slot only after its payload left the bus (0x0d4c, 0x0f17), also fixing a concurrent Wi-Fi enqueue overwriting a slot mid-transfer. - 75/300 us gaps unchanged: no timed delays exist in the ROM; the measured gaps (e7d9629) are emergent Z180/DMA overhead that software-timed blind hosts depend on. The host driver selects blind purely on Virtual Memory being off (Gestalt 'vm '), independent of machine type, so a Mac Plus (68000, no VM) always drives blind and relies on these gaps. Measured RX: Mac SE/30 (System 7.5) 90 KB/s polled / 100 KB/s blind; Atari Falcon (FreeMiNT, blind) 100 KB/s. DaynaPORT 7.5.3 sends 0x80 (polled) with VM on, 0xC0 (blind) with VM off.
…[1..2] Per the SL003 device ROM (v2.0 0x1294, v1.3 0x11d7), WRITE(6) dispatches on CDB[5] bit 7: clear = one raw packet of cdb[3..4] bytes, set = the length-prefixed record stream. The previous test (cdb[5] == 0) parsed any other bit-7-clear value as a stream, misreading the first 4 payload bytes as a record header. The record stream format itself (4-byte header, zero-length terminator, cdb[3..4] ignored) matches the ROM exactly as implemented. Also reject writes with nonzero CDB[1..2] as the device does (ROM 0x1281).
7db3dfa to
a884515
Compare
|
Updated with new insights from the complete ROM disassembly. The main difference is that polled mode is now strictly 1 record only as per the original ROM. The Mac polled driver sizes each transfer for a single record and stalls hard if you batch more. The disassembly also pinned down a bug introduced by the mode-gating in 7c20579: in polled mode it forced the loop to exit before computing the header flags, so the "more packets pending" bit (0x10) was always 0. Polled hosts were never told to come back, so they fell to slow timer-polling, that's almost certainly the real cause of the slowdown in #346. With both fixes together (one record per transfer and a truthful pending flag from actual queue occupancy) the host re-reads immediately and polled mode stays fast: measured 90 KB/s on a Mac SE/30 with VM on, vs. single digits when either piece is wrong. |
Started as an effort to improve DaynaPort SCSILink throughput on an Atari Falcon (stuck ~11 KB/s), which led to disassembling Dayna's original Mac
.ENET0driver (DaynaPORT 7.5.3) to see what the real hardware does. The real SCSI/Link returns a stream of[len|flags|payload|crc]records per READ(6) with a per-record "more pending" flag, and the host chains reads until it clears.This makes the handler match that protocol. Three standalone commits:
Pico_2_DaynaPORTonly (RP2350 has the RAM).Measured with the paired FreeMiNT driver:
Ring change is scoped to the Pico 2 W target; RP2040 and Ultra untouched. The record-stream + terminator match what the Mac driver already expects, so existing setups are unaffected (the terminator also fixes a latent stale-buffer read).