# Can the level-1 HOST PORT test be skipped? — analysis Task: determine whether the level-1 **HOST PORT** test (error 15) can be skipped, suppressed or configured away through anything persistent or configurable — NVRAM, port configuration, a test-selection record, a mode word, a strap — rather than by making it pass. ROMs untouched. Date: 2026-10-16. Inputs: `docs/EK-V1000-SV-002_service-guide.txt`, `harness/mame/hostport_dis34.txt` (linear `dis34` disassembly, firmware **bit** addresses), `harness/mame/{BRINGUP_LOG,DUART_REPORT,CODE22_REPORT}.md`, `harness/mame/vt1200.cpp` / `vt1200_board.*` (read only), and one short empirical run (`reference/l1probe/`). --- ## Address conventions (four, reconciled) | name | formula | example for the level-1 call site | |---|---|---| | firmware **bit** address (what `dis34` prints, what the CPU stores) | `0x3F200000 + file_offset*8` | `0x3F204400` | | file offset (byte) into `vt1200_v22.bin` | `(bit − 0x3F200000)/8` | `0x880` | | Ghidra address | `0x07E40000 + file_offset` | `0x07E40880` | | driver / board-model address | `bit >> 4`, window base `0x06400000` | `0x06400000 + 0x0D` for the firmware's `@0x64000D0` | Throughout this document I quote the **firmware bit address** (as `hostport_dis34.txt` prints it) and give the Ghidra equivalent where useful. A driver handler at `base` receives `(bitaddr − base) >> 4`, so the firmware's `@0x64000D0` is board-model address `0x0640000D`. All "PC" values are the value of the TMS34010 `PC`, i.e. a bit address. --- ## Verdict (short) **There is no persistent, configurable test-selection record that suppresses the level-1 host-port test.** The level-1 batch runs unconditionally at power-up and its per-run test set comes from **hard-coded ROM immediates written into a RAM descriptor**, not from NVRAM. P3 only *modifies* how a test is run. The diagnostics menu's selection is RAM-only and is reached only *after* the power-up tests. There **is** one in-firmware branch that skips the whole level-1 batch: a **board-input gate** at bit `0x3F2042D0`–`0x3F2043B0`. If DUART1's input-port bit 3 (firmware `@0x64000D0` bit 3 = IP3) reads **1** and the 0x6200000 status port has not returned the magic `a3 = 0x55`, the boot jumps straight to the OS cold-start at `0x3F5788C0`, skipping *all* of level 1. This is a hardware-input condition, not a firmware setting; it skips the whole batch (not just the host port); it is undocumented; and it is not reachable on the normal POST path (bit 3 reads 0 in every harness configuration tried). See §6. Practical consequence: to boot past level 1 the harness must make the level-1 tests pass, **or** deliberately assert DUART1 IP3 high (`@0x64000D0` bit 3 = 1) so the boot takes the OS branch. There is no NVRAM/config byte to flip. --- ## Q1. When does level 1 run, and is it conditional? **It runs unconditionally at power-up, as part of the boot ROM itself.** It is not gated on any NVRAM or settings value. Evidence — the boot code calls the level-1 runner directly: ``` 3f2043e0: move a14, -*sp, 1 ; L3F2043E0: the POST "run the suite" loop 3f2043f0: move a3, *a14+, 1 ; arg = a3 3f204400: calla L3FDF72D0 ; <<< the level-1 runner 3f204430: move a8, a10 3f204440: jane L3F208060 ; nonzero return -> blink the board LED code 3f204460: jruc L3F2043E0 ; zero -> loop ``` The runner `L3FDF72D0` is the code that announces level 1: at bit `0x3FDF7770` it calls the reporter `L3FDE55F0` with status `0xFFFF`, which the dispatcher maps to the string **`LEVEL1/2 TESTING ** `** (string bit `0x3FDCA8E8`, file `0x17951D`). It then drives the memory/port tests (it calls `L3FA7C050`, the routine that contains the video-memory self-test `L3F2018B0`, the host test wrapper, etc.). The call site has exactly **one** conditional, at `0x3F2042D0`–`0x3F2043B0`, and it reads a **hardware input port**, not a configuration record: ``` 3f2042d0: move @0x64000d0, a0, 0 ; DUART1 read reg 0x0D = IP (IP0-IP6, bit7=1) 3f204300: btst 3, a0 ; IP3 3f204310: jane L3F204360 ; IP3 == 1 -> check a3 3f204340: clr a3 3f204350: jruc L3F2043E0 ; IP3 == 0 -> run the suite (a3 = 0) L3F204360: 3f204360: cmpi 0x55, a3 3f204380: jaeq L3F2043E0 ; a3 == 0x55 -> run the suite (a3 = 0x55) 3f2043b0: jauc L3F5788C0 ; else -> OS cold-start, skip level 1 ``` `btst` sets Z=1 when the tested bit is **0** (MAME `tms34010.cpp` `BTST_K`: `SET_Z_BIT_LO(~reg,bit)`), so `jane` is taken when **IP3 = 1**. `a3` is set to `0x55` only by the poll at `0x3F2031D0` (a level-0 board-status poll), which on this boot path is **skipped** (`0x3F202660: jaeq L3F204020` jumps over `0x3F202690`–`0x3F20401F`). On the normal harness path, therefore, bit 3 = 0 (measured) and the suite runs unconditionally. The service guide agrees that level 1 is not optional: "Power-up self-tests run each time you turn on the power switch… Level 0 tests run first, followed by level 1 tests" (guide lines 632–641) and the LED sequence (lines 698–703). The guide does not describe any way to disable power-up testing. **Answer:** unconditional. The only readable gate is the DUART1 IP3 hardware input bit, not a stored value. --- ## Q2. Is the host-port test itself conditional (port "not installed")? **No.** The firmware has presence checks for some optional hardware, but none for the host port. Evidence: * Guide Table 2–2 (level-1 list, page 13) lists "Host port test" with no qualifier, in contrast to the two conditional entries: "Option RAM test **(if present)**" and "Image test **(if installed)**". * The firmware's only presence tests are: * **SIMMs / option memory** — port `@0x5000000`, bits 0–2, read at bit `0x3F2C7E70` / `0x3F2C7F50` / `0x3F2C7F90`, printing `Not Present` (string `0x3F2CCDE8`) / `SIMM n installed` (`0x3F2CCEA8`, `0x3F2CD040`, `0x3F2CD1D8`). * **Image Option** — port `@0x62000D0` bit 5, read at bit `0x3F2C80B0` (`btst 5,a11`), printing `Image Option` / `Not Present`. * A ROM-string search finds no "host port … not present/installed" string; the strings are `Host Port Test` / `Host port test` (`0x3F49E780`, `0x3F49E7F8`) and `Host Port Error - 15` (`0x3FAD5B20`), only. The level-1 host test therefore always runs as part of the batch. (The host-port *wrapper* does branch on a bit — `0x3FA84B80: move *a11,a9,1 / btst 10,a9` — but bit 10 (`0x400`) is the test's *selection/status* bit, which the boot sets, not a presence flag; see Q3.) --- ## Q3. Is there a persistent test-selection or mode record? **No persistent record.** Two selection mechanisms exist and neither is stored: **(a) The power-up test set is a hard-coded ROM immediate written into RAM.** The level-1 runner builds the test descriptor with `L3FA904C0` (driver-visible address `0x3FA904C0`), which copies five arguments into a descriptor at RAM `0x0`–`0x220` (`*a11(0x0)`, `+0x20`, `+0x1a0`, `+0x1c0`, `+0x1e0`, `+0x200`). The runner fills those words from immediates: ``` 3fdf7e30: sub a7, a7 3fdf7e40: movi 0x10fefd80, a9 ; default test set (normal power-up path) 3fdf7e70: move a9, *a7, 1 ; RAM 0x00 = 0x10FEFD80 ``` (and `0x3FDF7690: movi 0x50febf80` on the other entry). `0x10FEFD80` has bit 10 (`0x400`) set — that is exactly the code that selects the HOST PORT handler — so the host test is in the default set. Nothing reads these from NVRAM. **(b) The interactive diagnostics menu edits the same RAM words only.** The dispatcher sends status code `0x1FFFF` to the menu printer at bit `0x3FDE5810`, whose first line is `VERSION 2.08 - SELECTED TEST TYPE: ` (string `0x3FDCA990`); it prints the four words at RAM `0x00`, `0x20`, `0x1A0`, `0x1C0` and the A–Z selection list (e.g. `E - DUART1, CHANNEL A (HOST) TEST (00000400h)` at string `0x3FDCB488`, `O - LOOPBACK MODE (TOGGLE) (08000000h)` at `0x3FDCC8D8`). The list values are the **error codes** each test reports, and the words are plain RAM. There is no store-back to NVRAM. This menu is reached only *after* a failure (the running harness lands there when level 0 fails / the whole batch reports), so it cannot change the power-up set of the power-up run. **(c) NVRAM is not consulted by the level-1 path at all.** Every access to the NVRAM window `@0x6000000` in the whole image is the user-settings code (`0x3F4ABFA0`, `0x3F4ACBA0`, `0x3F4AF2D0`) and the NVR access helpers (`0x3FA7FAE0` region, `@0x6000020`/`@0x6000030`). None is on the level-1 path. The guide's NVR contents are user settings only — "group codes, host name or IP address, font paths, and the terminal IP address" (guide lines 2368–2374) — and the `Customize` dialogs (`Customize Host Port`, `Customize Printer Port`, `Customize TCP/IP`, …) contain no test/diagnostic enable switch. **P3 only modifies.** Guide Table 2–5 (page 24, lines 1059–1068): ``` bit 0 (1) External loopback: host port. bit 1 (2) External loopback: printer port. bit 2 (4) External loopback: mouse port. bit 3 (8) LANCE loopback: Ethernet port. bit 4 (16) Test all baud rates. bit 5 (32) Do not exercise modem control signals. ``` These are per-invocation arguments of the NCP `TEST [ ]` command (guide lines 1020–1094). None suppresses or deselects a test; P3 = 0 is "run it normally". Nothing stores P3. --- ## Q4. What does the failure actually gate? **A level-1 failure is fatal to the boot in this ROM: it wedges the machine in the system-board LED error-code loop.** It is not merely a message. Evidence: * The error dispatcher is `0x3FDF0630`. It reads the status code from bit `0x16F0` (frame slot `a13−0x20`) and switches: code `0x400` → `0x3FDE9D70`, the **HOST PORT** handler. That handler prints `LEVEL1/2 ERROR -> HOST PORT - 15 ` (string `0x3FDC9C68`), dumps the port diagnostics, prints `BLINKING SYSTEM BOARD LED` (`0x3FDF50D0`), calls `L3F208660` to blink the LED once, prints `TYPE 'GO' TO CONTINUE` (string `0x3FDCD2A8`), and returns. * The runner then returns a nonzero value to the boot loop, which executes `0x3F204440: jane L3F208060`. `L3F208060` blinks the two-digit LED code and **loops forever**: `0x3F208650: jruc L3F208060`. * Measured (`harness/mame/progress.lua`, `CAP_MAX`/`PROG_FRAMES` runs, 900–3000 frames): the console transcript is exactly `LEVEL1/2 TESTING ** `, `LEVEL1/2 ERROR -> HOST PORT - 15 `, `TYPE 'GO' TO CONTINUE`; and the CPU is parked in the LED loop — the hottest PCs are `0x3F2088B0`, `0x3F208B20`, `0x3F208A80`, `0x3F208950`, all inside `L3F208060`. Nothing else is printed afterwards. This matches `BRINGUP_LOG.md` ("blocked, not slow"). So a level-1 failure does **not** "merely display an error and enter the menu" — the harness's earlier menu entry came from the *level-0* I/O-data-path failure, a different path. Once level 1 itself is entered and fails, the boot stops in the blink loop and never reaches the OS/Terminal Manager. (The guide's sentence "When a level 1 error occurs, the screen displays an error message in the upper-left corner and testing continues" — lines 1863–1866 — describes the diagnostic display sequence; the ROM's own control flow, and the measured result, end the boot at the LED loop.) The `TYPE 'GO' TO CONTINUE` prompt is part of the diagnostic summary, not a skip: the harness has no keyboard to answer it, and even with one the boot proceeds to the blink loop, not to the OS. --- ## Q5. Exact bytes, if a skip exists No NVRAM or settings bytes suppress the test. The **only** lever that bypasses level 1 is the hardware gate in §6: * assert **DUART1 input-port bit 3** high — firmware operand `@0x64000D0`, bit 3 (IP3); board-model/driver address `0x0640000D`, value bit 3; the SCN2681 IP register, `ip3_w(1)`. Keep bit 2 = 0 (the b3=1 path is the one that bypasses) and the monitor-switch bits 4–6 as the VR150 value `0x70`; bit 7 of the IP register is the always-1 marker. In the board model a single override of `0x0640000D` to `0xF8` expresses exactly that. * No NVRAM offset is involved. This is not a per-test suppression (it skips the whole level-1 batch) and it is not a supported setting. --- ## 6. The one bypass branch, in detail ``` L3F2043E0 (run-the-suite entry) arg = a3 calla L3FDF72D0 ; level-1 runner ``` Reached from `0x3F2042D0`: | condition | result | |---|---| | `@0x64000D0` bit 3 = 0 | `clr a3`; `L3F2043E0` — **run level 1** (the harness state) | | bit 3 = 1 and `a3 = 0x55` | `L3F2043E0` — run level 1 | | bit 3 = 1 and `a3 ≠ 0x55` | `jauc 0x3F5788C0` — **skip level 1, go to the OS** | `0x3F5788C0` is the OS cold-start: it disables interrupts, programs the DMA ports (`@0x5900000`, `@0x5800000`), the display (`@0xC0000080`), sets `sp`/`a13`, and calls the OS/X-server init routines. `a3 = 0x55` is produced only by the level-0 board poll at `0x3F2031D0` (`movi 0x55,a3` … `clr a3` on failure). That whole block (`0x3F202690`–`0x3F20401F`) is jumped over when `@0x64000D0` bit 2 = 0 (`0x3F202660: jaeq L3F204020`), which is the case in the harness, so `a3` keeps an earlier value. The measured `a3` at the call site was 0 — so with bit 3 = 1 the bypass condition holds. **Empirical note (honest, and weaker than I would like).** I exercised this via the board-model override `VT1200_BOARD_MAP="0x06200001=0xBEEF;0x0640000D=F8"` (correct key is the driver address `0x0640000D`, *not* the firmware operand `0x0640000D0` printed in the driver header's example). With it, `@0x64000D0` reads `0x00F8` (bit 3 = 1) and execution reads the port from PCs `0x3F3E1170` and `0x3F5FF7A0` that the normal (`0x70`) run never reaches — consistent with `0x3F2043B0` being taken, but confounded by the second override present in the same run. I could not confirm the *end state*: the MAME binary was being rebuilt by another worker during the analysis (its mtime changed between runs and it was momentarily zero-length), a 2500-frame run with `0x0640000D=0xF8` alone still ended in the `0x3F2088B0` LED loop, and I cannot set IP3 through the SCN2681 without a driver change. **So: the branch and its condition are clear statically; whether taking it produces a usable terminal (resolves to the OS/X server rather than a later reset) is unverified.** --- ## 7. What this means for the harness 1. There is no memory (NVRAM/settings) or command (NCP/P3/diagnostics) that turns off the level-1 host-port test, or level 1, or the power-up tests. 2. The host-port test is mandatory in the power-up batch; the port has no "not installed" sense. 3. Because a level-1 failure wedges the boot in the LED-code loop, "ignore the failure" is not an option either. 4. The only escape route that exists in the ROM is the board-input gate: assert DUART1 IP3 (`@0x64000D0` bit 3) high (with bit 2 low) **before the boot reads it at `0x3F2042D0`**, so the boot branches to the OS cold-start `0x3F5788C0`. That skips all of level 1, needs no ROM change, and is exactly a harness-side input assertion (SCN2681 `ip3_w(1)`, or `0x0640000D = 0xF8` in the board model). Its fidelity to real hardware is unknown — no document, log or ROM string describes DUART1 IP3 — and it is all-or-nothing. 5. Otherwise the harness must make every level-1 test that runs pass — the path already taken for VIDEO MEMORY (`VT1200_VRAM`, REFCNT) and now capped at the host-port DUART sub-bit timing. --- ## Reproduce ``` harness/mame/hostport_dis34.txt # dis34, firmware bit addresses grep -n "callers / labels" per section above # empirical capture of the level-1 error path (see reference/l1probe/): reference/l1probe/gate.lua # PC/site probe around the boot gate reference/l1probe/console-transcript.txt # decoded cap.lua console transcript M=/home/arti/code/k-space/mame0289/vt1200 $M vt1200 -rompath harness/mame/roms -video none -sound none -nothrottle \ -debug -debugger none -debuglog \ -autoboot_script harness/mame/progress.lua -autoboot_delay 0 # -> hottest PCs 0x3F2088B0/0x3F208B20 (LED loop) = the wedge ```