<feed xmlns='http://www.w3.org/2005/Atom'>
<title>rs-dos/DEBUG_NOTES.md, branch qemu</title>
<subtitle>Simple, kernel-only, 64bit OS, early stage.
</subtitle>
<id>https://git.2137697.xyz/rs-dos/atom?h=qemu</id>
<link rel='self' href='https://git.2137697.xyz/rs-dos/atom?h=qemu'/>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/'/>
<updated>2026-11-01T16:09:59Z</updated>
<entry>
<title>ehci: bound all init waits; stop auto-rescanning; wider boot watchdog</title>
<updated>2026-11-01T16:09:59Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-11-01T16:09:59Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=d99906b48698c1bd722a1fa5f2270b76317ec661'/>
<id>urn:sha1:d99906b48698c1bd722a1fa5f2270b76317ec661</id>
<content type='text'>
Hardware run 3 showed the same PED=0 SETUP halt and then never reached the
prompt.  Two boot-time hazards explain the death:

- reset_port polled PED with a 2,000,000-iteration MMIO loop (seconds on real
  silicon) and the reset retry ran it twice per port, so the port scan alone
  exceeded the boot watchdog window (task 0 in one frame for 7.5 s panics).
- while no HID was found the cursor task re-ran the whole EHCI scan, port
  resets included, every second -- a rate-matching hub never settles.

Changes:
- every EHCI wait is wall-clock bounded: halt/reset/run 500 ms, PED 200 ms
- control-transfer timeout 5 s -&gt; 500 ms
- per-controller 3 s port-scan budget; no automatic re-scan (explicit
  `usb rescan` only)
- 300 ms power-up settle before the reset walk (RMH bring-up)
- boot-phase watchdog 750 -&gt; 2000 ticks (20 s), room for hub bring-up
- xHCI gets the same persistent bottom-row port/device summary
</content>
</entry>
<entry>
<title>ehci: diagnostics + hardening for the port-not-enabled case</title>
<updated>2026-11-01T15:55:14Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-11-01T15:55:14Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=e53161d6b9191533caeea0ef6148f247f4e22441'/>
<id>urn:sha1:e53161d6b9191533caeea0ef6148f247f4e22441</id>
<content type='text'>
Second OptiPlex QR: the Host System Error is gone (the 64-bit QH/qTD layout
fix worked), but the SETUP qTD now halts with TBYTES=0, C_ERR=3 and no
XactErr/Babble/DBE -- a split transaction with no valid response.  PORTSC
shows CCS=1, PP=1 but PED=0, i.e. the port never enabled, so the split has no
TT to address.  On Intel PCH a healthy USB2 port shows the rate-matching hub
as high-speed (PED=1), so the next step is to see every port's state.

- settle 100 ms after powering ports and clear stale change bits before the
  reset walk (RMHs come up slower than direct devices)
- retry the port reset once after settling
- log a clear line when a connected port remains disabled
- retry a failed full-speed device as low-speed (the PORTSC speed field is
  only valid once the port is enabled)
- persistent bottom-row summary: controller count, caps64, USB legacy handoff
  result, every connected port's PORTSC and the HID device count.  A hardware
  run without serial now reports the whole picture instead of one QR.
</content>
</entry>
<entry>
<title>ehci: reserve the 64-bit QH/qTD layout (fixes hardware HSE)</title>
<updated>2026-11-01T15:48:40Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-11-01T15:48:40Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=12549dabf96bd6eb08c6834134fedf9edc7452b5'/>
<id>urn:sha1:12549dabf96bd6eb08c6834134fedf9edc7452b5</id>
<content type='text'>
First OptiPlex run: the controller halted with HSE (USBSTS bit4) 20 ms into
the first control transfer, with otherwise valid QH/qTD fields (control QH,
DTC, MPS 8, split hub 0/port 1, active qTD).

The PCH EHCI advertises HCCPARAMS bit0 (64-bit addressing capability), which
extends every QH with bufptr_hi[5] (17 dwords / 68 B) and every qTD the same
way (13 dwords / 52 B).  Packing them 32-bit-style (48/32 B) made the
controller read the next qTD as the overlay's high buffer pointer and DMA to
a bogus 64-bit address -&gt; Host System Error.

Space every structure for the 64-bit variant (32-bit controllers ignore the
tail): HID qTD at QH+0x80; control qTDs at QH+0x100/0x140/0x180 with the
setup packet at +0x1C0.  The failure QR now reports the capability and the
DMA bases so the next hardware iteration is self-describing.
</content>
</entry>
<entry>
<title>scripts: add test-usb; fix duplicate -bios in the test harness</title>
<updated>2026-11-01T15:33:09Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-11-01T15:33:09Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=363e24bcd18a28948f63fa78ac8a4eaa8784fe59'/>
<id>urn:sha1:363e24bcd18a28948f63fa78ac8a4eaa8784fe59</id>
<content type='text'>
- test-usb boots an EHCI and an xHCI controller with a mouse + keyboard and
  asserts enumeration, report decoding, and input reaching the shell.  The
  EHCI case asserts one key end-to-end (QEMU's EHCI model delivers only the
  first report through root-port split transactions); the xHCI case asserts a
  whole typed command.
- lib.sh: qemu_args() already supplies -bios, so the fresh OVMF varstore copy
  was silently overridden by the system firmware.  Pass the copy last (QEMU
  honours the last -bios) so tests really boot clean NVRAM.
- DEBUG_NOTES: document why USB never worked on the OptiPlex (EHCI shipped
  with DEBUG_MATRIX enabled, no RMH/hub support, only the first controller,
  no boot protocol, unbounded DMA), the success/failure log to look for on
  hardware, and the QEMU coverage limits.
- Makefile: add test-usb and include it in `make test`.
</content>
</entry>
<entry>
<title>USB2/1.1 (EHCI/UHCI) drivers + real-hardware bring-up hardening</title>
<updated>2026-08-17T12:53:52Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-17T12:53:52Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=be868a43185826b02bf6d091019bb779678525bb'/>
<id>urn:sha1:be868a43185826b02bf6d091019bb779678525bb</id>
<content type='text'>
- Add polled EHCI (USB2) and UHCI (USB1.1) host-controller drivers with
  HID boot mouse support, wired into cursor polling and the 'usb' shell cmd
- Add USB Legacy ownership handoff (claim_usb_legacy) plus config_write_byte
- Harden boot: verify the PIT/timer ticks before shell entry, EOI stray
  interrupts in the LAPIC to stop interrupt storms, bound PS/2 controller
  waits, and INTx-disable AHCI (polled driver)
- Add boot stage markers, klog screen echo, and QR lock; scheduler
  mark_shell_running; NO_USB stopgap to keep BIOS USB-Legacy input alive
- alloc_pages_above for DMA buffers that must avoid low conventional memory
- Expand DEBUG_NOTES with EHCI/QEMU bring-up findings
</content>
</entry>
<entry>
<title>v0.5.10: USB HID mouse via polled xHCI (rsnix/src/usb.rs)</title>
<updated>2026-08-04T01:06:06Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-04T01:06:06Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=5e1bdc12bd298a9751da4285b7e93c68b1314332'/>
<id>urn:sha1:5e1bdc12bd298a9751da4285b7e93c68b1314332</id>
<content type='text'>
Polled xHCI driver (mouse-only): controller bring-up, port reset,
enable-slot -&gt; address-device -&gt; config-descriptor walk -&gt; HID boot
mouse IN endpoint, one outstanding IN TRB drained on poll.  Cursor
task polls usb first, PS/2 second.  New 'usb'/'usb rescan' shell cmds.

Verified in QEMU (q35 + OVMF + qemu-xhci + usb-mouse): movement and
all three buttons tracked exactly; heap stays clean.

Fixes en route: MaxPorts=HCSPARAMS1[31:24]; operational regs CRCR=0x18
DCBAAP=0x30 CONFIG=0x38; pass input-context ptr in Address-Device;
Input Control Context DW0=Drop DW1=Add; HID walker bInterfaceClass at
+5; async discovery from cursor task.
</content>
</entry>
<entry>
<title>v0.5.9: fix OptiPlex heap crash — EBS retry must not rebuild the free list</title>
<updated>2026-08-03T23:44:05Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-03T23:44:05Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=3e2261d83176752f3ea21e0c97f330b4c1757437'/>
<id>urn:sha1:3e2261d83176752f3ea21e0c97f330b4c1757437</id>
<content type='text'>
Root cause: on real hardware SetMode can invalidate the pre-captured
ExitBootServices map key, so EBS fails and the retry refreshed the map
via capture_memory_map -&gt; init_heap, which REBUILT the free list from
the raw map and wiped the allocation state of every pre-EBS live object
(the display shadow and the vt grids). Their spans became free while
still live, later allocations carved inside the shadow, and the display
writes clobbered them — zeroed back-pointers (family A ptr=0x404443e0
block=0x0) and gray glyph pixels (family B 0xaaaaaa00aaaaaa = 0x00AAAAAA
= PALETTE[7] fg-7 text colour, not a firmware scrub).

Fix: refresh_and_exit now re-captures the map and returns a fresh EBS
key without rebuilding the free list (refresh_map_key); the free list is
the authoritative live-allocation state. Verified in QEMU under a forced
EBS failure (SIMULATE_EBS_FAILURE test hook): verify ok, probe NOT free,
flhead outside the shadow — identical to a clean boot, and the full
shell sequence is crash-free.

Also: removed the crash-family debug markers from the screen (boot-time
heapdbg lines, vt verify marker, shadow marker) — the vt grid self-check
stays serial-only. Version 0.5.8 -&gt; 0.5.9.
</content>
</entry>
<entry>
<title>v0.5.7: fix vt verify content check — expect BLANK (0x70020), not zero</title>
<updated>2026-08-02T23:34:31Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-02T23:34:31Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=d5f41d6e057300c82b83653b4afadeffb45a9f19'/>
<id>urn:sha1:d5f41d6e057300c82b83653b4afadeffb45a9f19</id>
<content type='text'>
The pre-verify 0x70020 'mystery' was a debug artifact, not corruption:
BLANK = {ch:32, fg:7, bg:0} = raw 0x70020, and vec![BLANK; n] fills both
grids with it at init.  The old check compared cells against 0 and its
probe loop break-ed on the first non-zero cell, so probes 1-3 stayed at
their zero-initialized slots — c=[0x70020,0,0,0] was bogus on every
healthy boot.  A full-grid dump proves QEMU grids are 100% BLANK at
shell entry (nz=3700 blank=3700).

Fix: probes compare against blank_raw (0x70020), record all four values
(no early break), probe both cells and rendered, and add a full-grid
nz/blank summary line.  The OptiPlex firmware 0x00AAAAAA scrub remains
cleanly distinguishable (scrub != blank).

Markers: the shell banner occupies grid rows 0-1 and the prompt row 2
(proven by screendump), and a stale crash.log replays at rows 2+, so the
shadow and vt markers moved to the bottom of the screen via the new
gop::text_rows()/bottom_row(off) helpers instead of rows 1-2.

QEMU verified: verify: ok every boot; test-msg + test-fault PASS; debug
and release builds 0 warnings.
</content>
</entry>
</feed>
