SCSI-TRACE How-To — Capturing an ENTER-DIRECTORY (mount) transaction¶
Purpose: Toggleable [SCSI-TRACE] logging in the RetroCore ND-100 SCSI emulator so
the full mount transaction (SINTRAN ENTER-DIRECTORY) can be captured to disk and the
"SCSI disk won't mount" failure diagnosed.
Provenance: SCSI-MOUNT-FIX-PLAN.md
1. What was instrumented¶
Trace lines are all prefixed [SCSI-TRACE] and are guarded by a single if (ScsiTrace)
flag, so they cost nothing when disabled. They live in two C# files (outside NDInsight):
| Area | File | Method |
|---|---|---|
| IOX register R/W boundary | Emulated.HW/ND/CPU/NDBUS/NDBusDiscControllerSCSI.cs |
Read(int), Write(int,ushort) |
| NCR completion interrupt | NDBusDiscControllerSCSI.cs |
Ncr5386_OnInterrupt, StepGoState |
| RITRG interrupt ack | NDBusDiscControllerSCSI.cs |
Read (case RITRG) |
| DMA -> ND memory summary | NDBusDiscControllerSCSI.cs |
StepGoState (DMA drain loop) |
| SCSI CDB dispatch | Emulated.HW/Common/SCSI/SCSIHDD.cs |
scsi_command |
| READ CAPACITY response | SCSIHDD.cs |
CommandReadCapacity |
| MODE SELECT 6 | SCSIHDD.cs |
scsi_command (SC_MODE_SELECT_6) |
| Block data + hex dump | SCSIHDD.cs |
readBlock / TraceBlock |
The flag itself and the hex-dump helper live on the SCSI base class
Emulated.HW/Common/SCSI/SCSIDevice.cs (public static bool ScsiTrace, HexDump(...)),
so a single toggle drives both the controller and the disk traces.
2. How to enable¶
2a. Turn the trace flag on¶
Set this once at startup (or from the debugger immediate window):
NDBusDiscControllerSCSI.ScsiTrace = true;
That property forwards to SCSIDevice.ScsiTrace, so both the controller and disk traces
switch on together. (Equivalently you may set SCSIDevice.ScsiTrace = true directly.)
2b. Make the log actually appear¶
[SCSI-TRACE] lines are emitted at log level Device, and the logger is Disabled
by default. You must lower the level to Device (or below) AND pick a destination:
// Easiest: file output
Logger.EnableLogger(Logger.LogLevel.Device, Logger.LogDestination.File);
// Or console
Logger.EnableLogger(Logger.LogLevel.Device, Logger.LogDestination.Console);
2c. Where the log goes¶
- File destination writes to:
%LOCALAPPDATA%\trace\file-trace.txt(appended; delete it first for a clean capture). Each line is prefixedDevice; SCSI Bus N: [SCSI-TRACE] .... - Console destination prints to stdout.
- Trace destination is viewable with SysInternals DebugView.
To capture one mount: delete the old file-trace.txt, enable tracing, run
ENTER-DIRECTORY,,DISC-SCSI-1,0 in SINTRAN, then inspect the file.
3. Reading the trace — GOOD mount vs BAD mount¶
The mount reads the master block (LBA 0). The decisive datum is block 0: at byte
2016 SINTRAN expects a printable volume/master-block name, with the block-0 checksum at
byte 2000. (Note: a single ND sector is 1024 bytes, so the [2000..2047] dump only
appears if the returned buffer is >= 2048 bytes; otherwise a "block0 len < 2048" note is
logged instead — that in itself tells you the read granularity.)
Key lines to grep¶
grep "SCSI-TRACE" file-trace.txt
Then focus on these four:
| Grep for | GOOD mount | BAD mount |
|---|---|---|
READ CAPACITY -> |
blockSize=1024 (ND requires 1024-byte sectors) |
blockSize=512 or other -> wrong geometry, mount rejected |
readBlock lba=0 bytes[0..31]= |
plausible structured header, not all 00/FF |
all zeros or all FF = empty/garbage medium |
block0 bytes[2000..2047]= (or the len<2048 note) |
printable ASCII around offset 2016 (the master-block name) | random bytes / zeros = page 0 garbage -> the root cause of a failed mount |
completion: + RITRG ack: |
completion fires (-> SetInterruptBit), then RITRG ack: cleared intFromNCR |
completion never logged, or no IRQ (int disabled) -> lost IRQ, RSTAU-poll loop, mount timeout |
The RSTAU / RITRG interrupt pattern¶
A healthy transaction shows, in order:
IOX W reg=WCONT ...with the active bit -> command starts.- Repeated
IOX R reg=RSTAU ...polls (SINTRAN waiting for the transfer). NCR interrupt raised ...when the NCR5386 finishes.completion: active->false rft->true intEnabled=True -> SetInterruptBit.IOX R reg=RITRG ...followed byRITRG ack: cleared intFromNCR.
If step 3/4/5 never appear while RSTAU polling continues forever, the completion IRQ is being lost — that is the classic mount-timeout / BUS-RESET loop this trace was built to catch. (The interrupt is acknowledged on RITRG, never on RSTAU — see fix #1 in the plan.)
The DMA payload¶
DMA->ND xfer bytes=... first16=... shows how many bytes reached ND memory and the first
16. For the master block read this should be a full sector; bytes=0 or a truncated count
means the data phase stalled.
4. Turning it off¶
Set NDBusDiscControllerSCSI.ScsiTrace = false; (the default). No rebuild toggle needed —
it is a runtime flag.