Commit Graph
15 Commits
Author SHA1 Message Date
Robert Allan JamesandClaude Sonnet 5 d686f28853 Artemis Milestone 2h (foundational): sync wait bridge + SCSI READ CAPACITY(10)
Closes the gap block_subsystem.c needs before any of 2h's real work
(blkio_usb.c, attach wiring, hot-detach) can start: this driver is fully
async/polled with no way for a synchronous caller (blkio_read()/
blkio_info() etc.) to get a result back. xhci_bot_wait_for_idle() is a
bounded busy-wait over xhci_poll_events() -- MUST be called only from
outside xhci_poll_events()'s own call frame, never from within it or a
next_action dispatch (recursion into live Event Ring/ERDP processing,
same class of hazard already documented for doorbell rings in this
driver). xhci_get_dev() exposes the module-static device handle to
outside callers that didn't observe the original hotplug event.

SCSI READ CAPACITY(10) (opcode 0x25) is the other half -- nothing could
learn a device's block size/capacity before this. First attempt sent it
bare and hit the classic first-command UNIT ATTENTION (CSW FAILED); fixed
with the same TUR-guard pattern READ(10) already used, generalized via a
new bot_tur_chain_target field so TEST UNIT READY's PASS handling can
chain into either command. bot_data_buf grown 512->1024 bytes (one Forth
block = two 512-byte SCSI blocks, per block_subsystem.c's own 1KiB-unit
convention).

Verified live via a temporary probe (hot-attached disk/usb-thumbdrive-
test.img via QMP, reverted after capture): TUR-guarded READ CAPACITY10
correctly reported last LBA=0x1ffff, block size=0x200 -- exactly 64MiB,
matching the test image byte for byte -- followed by a TUR-guarded
1024-byte/2-block READ10, both PASS. All three architectures re-verified
clean, probe-free boot to ok> on the reverted tree. FABRIC-2.md Section X
2h updated with the writeup; the blkio_usb.c backend itself is next.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CXjAPTEKrgY2Mrk25KoLDn
2026-08-25 12:27:57 -04:00
Robert Allan JamesandClaude Sonnet 5 65effbd1ba Artemis Milestone 2g: TEST UNIT READY unit-init sequence -- READ(10) now PASSes
Roots out the CSW status FAILED left unexplained in the prior increment: a
freshly attached SCSI target's standing UNIT ATTENTION condition, which a
bare READ(10) with no retry can never clear. xhci_bot_send_test_unit_ready()
sends SCSI TEST UNIT READY (SPC-4 6.33) ahead of the real command; the CSW
handler now tags command kind (bot_cmd_kind) to distinguish a TUR completion
from a READ10 completion, chains TUR PASS into the real READ(10), and
bounded-retries TUR on FAILED/PHASE ERROR (bot_tur_retries, capped at
XHCI_BOT_TUR_MAX_RETRIES). xhci_bot_read_block() is the new intended entry
point tying lba/num_blocks/block_size + the TUR-first sequencing together.

Verified live via a temporary probe (hot-attached disk/usb-thumbdrive-test.img
through the running instance's QMP socket), captured on amd64: full chain
CBW(TUR) -> FAILED -> retry -> PASS -> CBW(READ10) -> Data-In -> CSW PASS.
Probe reverted after capture; all three architectures re-verified clean,
probe-free boot to ok>. FABRIC-2.md Section X 2g updated with the writeup.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CXjAPTEKrgY2Mrk25KoLDn
2026-08-25 11:46:55 -04:00
Robert Allan JamesandClaude Sonnet 5 c54ea24aaf Artemis Milestone 2g: Data-In stage read and CSW receive/validation
Completes the CBW -> Data-In -> CSW chain for READ(10) started last
commit. xhci_bot_read_data_in() and xhci_bot_receive_csw(), each a
single Normal TRB on the bulk IN Transfer Ring via a new
xhci_bulk_in_enqueue_and_ring() helper (mirrors the OUT-side helper
from CBW send). All three stages now chain automatically via the
existing deferred next_action pattern: CBW completion defers into
Data-In, Data-In completion defers into CSW receive, CSW completion is
where signature/tag/status validation happens.

Data-In reads into a new fixed 512-byte bot_data_buf -- single-block
scope for this increment, matches QEMU's usb-storage reported block
size; xhci_bot_send_read10() now refuses rather than overflow/truncate
if a request exceeds it. CSW validation (BOT spec section 5.2) checks
dCSWSignature and dCSWTag (a new bot_last_tag field, latched from the
CBW) before trusting bCSWStatus at all, so a garbled/misaligned CSW
read can't be misread as a clean pass. usb_bot_csw_t follows the same
struct-with-explicit-length-not-sizeof discipline as usb_bot_cbw_t.

Verified live via a temporary probe (written, run once, log captured,
reverted per this project's own probe convention), all three
architectures, byte-identical: the full CBW -> Data-In -> CSW exchange
completes cleanly, well-formed CSW with correct signature and echoed
tag, no wedge, clean disconnect immediately after. The SCSI command
itself reports CSW status FAILED against the current test fixture --
expected at this stage (no TEST UNIT READY / UNIT ATTENTION handling
implemented yet, consistent with a fresh-attach unit-attention
condition, not a transport-layer defect) and not root-caused further
here; the BOT mechanism itself is confirmed correct end to end.
Probe-free re-verification afterward on all three architectures.

FABRIC-2.md Section X Milestone 2g's CSW checklist item marked done;
"get one real READ(10) working end to end" stays explicitly open,
distinguishing "the mechanism works" from "the SCSI command succeeds."

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R4VMX6VSKCten8nGgaMkq4
2026-08-25 09:33:17 -04:00
Robert Allan JamesandClaude Sonnet 5 a88c004ecb Artemis Milestone 2g: CBW construction and send for SCSI READ(10)
First real use of the bulk Transfer Rings Configure Endpoint wired up.
xhci_bot_send_read10() builds a 31-byte Command Block Wrapper (USB Mass
Storage Class Bulk-Only Transport spec section 5.1) and submits it as a
single Normal TRB on the bulk OUT ring via a new
xhci_bulk_out_enqueue_and_ring() helper -- a CBW is always exactly one
TRB, so unlike the EP0 helper this one rings its own doorbell rather
than leaving that to a caller assembling a group.

usb_bot_cbw_t is a real struct (every field up to the CDB array is
naturally aligned, and this driver's targets are all little-endian
already assumed everywhere else), but its DMA length is the explicit
USB_BOT_CBW_LENGTH (31) constant, never sizeof(*cbw), since the
compiler may pad the struct to 32 bytes. The SCSI READ(10) CDB itself
is written byte-by-byte since its LBA/Transfer Length fields are
big-endian on the wire, unlike everything else in this driver -- the
one place two byte orders are both live in the same function.

Completion is correlated via the existing pending_transfer_slot_id/
transfer_purpose gate (new XHCI_XFER_CBW_SENT purpose) -- no
ring-specific dispatch needed, since this driver's single-outstanding-
transfer scope already implies which ring produced an event.

This covers construction and send only (one third of a full READ(10):
CBW -> Data-In stage -> CSW) -- reading the Data-In stage and CSW
receive/validation are separate, explicitly not-yet-implemented items.

Verified live via a temporary probe (written, run once, log captured,
reverted per this project's own probe convention) -- all three
architectures, byte-identical: CBW submitted -> CBW send completed,
then a clean disconnect even with the Data-In stage never drained
(confirms no wedge on a dangling BOT transaction). Probe-free
re-verification afterward on all three architectures.

FABRIC-2.md Section X Milestone 2g's CBW checklist item marked done.
Also records a monitoring gotcha hit three times this session: `ls -t`
over the logs/ tree can return a stale leftover log from an earlier
run in the same session -- fixed going forward by reading the log path
off the actual running QEMU process's own command line instead, and a
memory note added so it doesn't recur next session.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R4VMX6VSKCten8nGgaMkq4
2026-08-25 09:07:33 -04:00
Robert Allan JamesandClaude Sonnet 5 92ce1f85dd Artemis Milestone 2g: Configure Endpoint command
Adds the xHCI Configure Endpoint command for the two bulk endpoints
identified by the previous increment, and fixes control-transfer
sequencing to match the spec: xHCI 1.2 section 4.3.5 requires Configure
Endpoint before SET_CONFIGURATION is sent to the device, the reverse of
the order this driver used through 2f (which happened to work against
QEMU's lenient qemu-xhci emulation but wasn't spec-correct).

New XHCI_TRB_TYPE_CONFIGURE_ENDPOINT_CMD, EP Context type constants for
Bulk IN/OUT, and an XHCI_EP_ADDR_TO_DCI() macro (DCI = 2*EndpointNumber
+ Direction) in xhci.h. xhci_cmd_configure_endpoint() builds the Input
Context (Slot + one EP Context per DCI up to the highest bulk endpoint
in use) and submits the command via the existing next_action deferral
mechanism, correlated on completion via a new
XHCI_CONN_AWAIT_CONFIGURE_ENDPOINT connect_state, then chains into the
existing SET_CONFIGURATION path.

Two allocations had to grow beyond what Address Device sized them for:
the Input Context (previously room for one EP Context only) and, less
obviously, the Device Context that DCBAA[slot_id] itself points at --
the controller only touches DCIs named in a command's own Add/Drop
flags, so growing that buffer required copying its existing Slot+EP0
content forward rather than zeroing it, to avoid handing the controller
a blank EP0 out from under an endpoint this command isn't touching.
Bulk Transfer Rings (bulk_in_ring/bulk_out_ring) are allocated and
wired into the new EP Contexts but not yet exercised by an actual
transfer -- CBW/CSW submission is next.

Verified live via QMP hotplug, all three architectures, byte-identical:
bulk endpoint identification -> configure endpoint command submitted ->
configure endpoint succeeded -> the existing set configuration ->
device configured chain, then a clean disconnect/disable-slot teardown
afterward with the larger Device Context installed.

FABRIC-2.md Section X Milestone 2g's endpoint identify+configure
checklist item marked fully done.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R4VMX6VSKCten8nGgaMkq4
2026-08-25 08:40:35 -04:00
Robert Allan JamesandClaude Sonnet 5 96d55fcd87 Artemis Milestone 2g (partial): bulk endpoint discovery + 2e disconnect teardown
Picked up from a crashed session: xhci_driver.h/xhci.h already had the
bulk_in/out_ep_addr/max_packet fields and Endpoint-descriptor offset
macros scaffolded, but the actual walk that populates them was never
written. Added it: after 2f confirms a Mass Storage/SCSI/BOT interface,
a nested walk continues through the Endpoint descriptors that follow it
(bDescriptorType==5, stopping at the next Interface descriptor or end
of stream), keeping only Bulk-type endpoints and splitting IN/OUT by
bEndpointAddress bit 7. Also reset the four new fields in
xhci_bringup(), which the scaffolding had missed.

Also completed 2e's disconnect teardown, which was fully implemented
this session (not scaffolded): a Disable Slot command is now submitted
on a real disconnect, with the port's tracked slot ID captured and
cleared from port_slot_id[] immediately (before the command completes)
so a fresh connect on the same port isn't confused for one already in
progress, and DCBAA[slot_id] cleared only on a successful completion.

Verified live via QMP hotplug (deliberate device_add/device_del against
freshly launched, individually-tracked instances -- not whatever
happened to be attached at boot), all three architectures,
byte-identical: bulk IN endpoint=0x81, bulk OUT endpoint=0x02, then a
clean disconnect -> disable slot succeeded, no wedge. Caught and fixed
a documentation near-miss in the same pass: an initial draft cited the
probe-free three-arch acceptance boots as this feature's verification
evidence, but a stale leftover log directory from a pre-crash orphaned
QEMU process had been picked up by an `ls -dt | head -1` glob during
monitoring and mistaken for this session's own result -- the real
acceptance logs never had a device attached at all. Re-verified against
real PIDs and real log paths before writing FABRIC-2.md's final
writeup.

FABRIC-2.md Section X Milestone 2 updated: 2e's disconnect-teardown
checklist item marked done, 2g's endpoint-identification item marked
partially done (identification only -- Configure Endpoint / EP Context
wiring is still open).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R4VMX6VSKCten8nGgaMkq4
2026-08-25 08:17:50 -04:00
Robert Allan JamesandClaude Sonnet 5 b4bbd043d0 Artemis Milestone 2f: SET_CONFIGURATION -- 2f complete
Chains off a confirmed Mass Storage/SCSI/BOT interface match via the
existing next_action deferral mechanism: device descriptor -> config
descriptor -> SET_CONFIGURATION is now a single automatic sequence.
bConfigurationValue is read directly out of the already-fetched
config_descriptor buffer, no extra transfer needed.

First write control transfer this driver has issued (every prior one was
a read), so it needed its own submission helper,
xhci_ep0_control_write_nodata() -- SET_CONFIGURATION has no Data Stage
(wLength=0), and per USB 2.0 spec 8.5.3 a no-data control transfer's
Status Stage is always IN, the reverse of an OUT-data request's status
stage. XHCI_SETUP_TRT_NO_DATA already existed in xhci.h, unused until now.

Verified live via QMP hotplug, all three architectures, worked first try,
byte-identical: "set configuration submitted" -> "device configured",
guest stays running throughout (checked via QMP query-status). Disconnect
confirmed clean on every arch afterward, no wedge. FABRIC-2.md Section X
Milestone 2f updated -- 2f is now fully complete, 2g (Bulk-Only Transport)
can start.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QPfdtaXs9ay1nbwuMnrscu
2026-08-25 07:40:16 -04:00
Robert Allan JamesandClaude Sonnet 5 b9c540a78b Artemis Milestone 2f: Configuration descriptor read + Mass Storage/BOT class confirmation
Chains off the device descriptor request via a new deferred-action mechanism
on xhci_dev_t (next_action/next_action_slot_id/next_action_length): a short
9-byte Configuration descriptor read learns wTotalLength, then a full read
retrieves Config+Interface+Endpoint descriptors, walked for the Interface
descriptor to confirm bInterfaceClass/SubClass/Protocol == Mass Storage/
SCSI/Bulk-Only Transport.

The deferral exists because ringing the next doorbell synchronously inside
xhci_poll_events()'s event-processing loop -- before the current event's
ERDP write -- hung the guest outright (confirmed live via checkpoint
logging, amd64). Fixed by moving the actual control-transfer submission to
a small dispatch at the end of xhci_poll_events(), after ERDP is updated.

A debug hack that shipped mid-session (forcing a repeated 9-byte read
instead of chaining into the real 44-byte length, to isolate whether the
hang was doorbell-ordering or length-specific) has been reverted: restored
the real length and re-verified live. The doorbell-ordering fix was the
whole story -- the 44-byte read completes cleanly.

Verified live via QMP hotplug, all three architectures, byte-identical
results: wTotalLength=0x2c, bInterfaceClass=0x08, bInterfaceSubClass=0x06,
bInterfaceProtocol=0x50 -- confirmed Mass Storage/SCSI/BOT. Disconnect
confirmed clean on every arch, no wedge. FABRIC-2.md Section X Milestone 2f
updated with the full writeup.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QPfdtaXs9ay1nbwuMnrscu
2026-08-25 07:27:07 -04:00
Robert Allan JamesandClaude Sonnet 5 2c34e45d05 Artemis Milestone 2f: EP0 control transfer, device descriptor request
Adds Setup/Data/Status stage TRB types and control bits (IDT, TRT, DIR)
to xhci.h, and xhci_ep0_enqueue_trb()/xhci_ep0_get_device_descriptor() to
xhci.c -- the first real control transfer this driver has issued.
Follows the same enqueue-then-doorbell-once pattern as the Command Ring,
operating on the EP0 Transfer Ring built during 2e's Address Device work.
Setup Stage uses Immediate Data (parameter IS the 8-byte setup packet);
Data Stage reads into a reused 18-byte device_descriptor buffer; Status
Stage alone carries IOC, so exactly one Transfer Event signals transfer
completion, correlated via a new pending_transfer_slot_id (same
single-outstanding-operation pattern as connect/Enable Slot/Address
Device).

Automatically triggered once Address Device succeeds. Verified live via
QMP hotplug, all three architectures, worked first try with identical
results everywhere: idVendor=0x46f4, idProduct=0x0001, bDeviceClass=0x00
-- the class=0 confirms Mass Storage class detection needs the
Configuration/Interface descriptor (2f's next item), not the device
descriptor.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HZ8kNoTuP63pbQtro4qvrm
2026-08-22 12:59:49 -04:00
Robert Allan JamesandClaude Sonnet 5 2b7743027c Artemis Milestone 2e: Address Device implemented, worked first try, 3-arch
Adds Slot/Endpoint/Input Control Context structs (32-byte layout only --
HCCPARAMS1.CSZ checked live and confirmed 0 against this driver's QEMU
target; 64-byte contexts refuse rather than silently mis-laying-out),
xhci_cmd_address_device(), and a new dev->connect_state
(idle/await-enable-slot/await-address-device) sequencing Enable Slot and
Address Device per connect. Input Context (what the command TRB's
parameter points at) and Device Context (what DCBAA[slot_id] points at)
are separate 64-byte-aligned allocations, lazily created once and reused
across every connect -- single-device driver scope, no free path needed.
A new EP0 Transfer Ring uses the same fixed-ring-plus-Link-TRB pattern as
the Command Ring.

Two facts checked live before writing any context code, not assumed:
HCCPARAMS1.CSZ (32-byte, confirmed) and PORTSC.PED at connect time
(already set -- PORTSC=0x00021203, SuperSpeed -- the test device
self-enables via USB3 link training, so no port-reset state machine was
needed this increment; USB2 would need one, untested). Both diagnostics
also added console_puts/println-based hex logging (xhci_log_hex32()) --
console_println() only takes string literals, no formatted print existed
on this driver's console path before now.

Verified live via QMP hotplug, all three architectures, succeeded on the
first attempt with no debugging needed: "enable slot succeeded" ->
"address device command submitted" -> "address device succeeded" on
every boot.

Also fixes a FABRIC-2.md dependency-direction error from the previous
commit (Address Device is 2f's prerequisite, not the reverse).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HZ8kNoTuP63pbQtro4qvrm
2026-08-22 11:44:15 -04:00
Robert Allan JamesandClaude Sonnet 5 6d330efdd8 Artemis Milestone 2e: real connect drives Enable Slot, slot ID correlated
xhci_poll_events()'s Port Status Change connect branch now calls
xhci_cmd_enable_slot() directly (the earlier boot-time smoke test call is
gone), tracked via a new dev->pending_connect_port_id -- since this
driver only ever has one command outstanding at a time, that alone
identifies which port a later Command Completion Event answers, without
needing to match the Command TRB Pointer yet. On success the returned
Slot ID is recorded in a new dev->port_slot_id[], a fixed
uint32_t[XHCI_MAX_TRACKED_PORTS] (32) indexed by port. Disconnect clears
the port's tracked slot (real teardown -- Disable Slot, DCBAA clear,
Section U callback -- is still a later increment).

Fixed array, not heap-allocated: a first attempt sized port_slot_id
dynamically via kmalloc_aligned(dev->max_ports * sizeof(uint32_t), 64)
inside xhci_bringup() and it crashed amd64 with a page fault (IFETCH at
RIP=CR2=0xA0000, the legacy VGA hole) during the unrelated Mama-VM-birth
phase afterward -- a heap-corruption signature, not chased to root cause.
Switching to a fixed array (matching this driver's existing preference
for fixed over dynamic allocation) made the crash go away; the crashing
boot's log is kept (logs/20260822-102516/) as the evidence trail.

Verified live via QMP hotplug, all three architectures: connect ->
"enable slot command submitted" -> "enable slot succeeded", with a
disconnect/reconnect cycle repeating cleanly and no port wedge.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HZ8kNoTuP63pbQtro4qvrm
2026-08-22 10:33:37 -04:00
Robert Allan JamesandClaude Sonnet 5 dd043bbfeb Artemis Milestone 2e: PORTSC connect/disconnect detection, verified live
xhci_poll_events()'s Port Status Change branch now decodes the Port ID
from the event TRB (XHCI_PSC_EVT_PORT_ID, new in xhci.h), reads that
port's PORTSC.CCS via a new xhci_port_regs() helper, and logs connect vs.
disconnect. Acknowledges by writing back only PP (preserved) and CSC (the
bit being cleared) -- PED/PR/other _C bits written 0 so nothing is
accidentally disabled, reset, or silently cleared, matching the RW1C
discipline already used for ERDP.EHB in 2d.

Verified with the real target scenario via QMP hotplug on all three
architectures: boot with the xHCI controller present but no USB device
attached (confirmed zero port activity at ok>), then live
attach/detach/re-attach of a virtual USB thumb drive
(disk/usb-thumbdrive-test.img via usb-storage on xhci0.0). Full
connect->disconnect->connect cycle confirmed clean (no port wedge) on
amd64; single connect confirmed on aarch64 and riscv64.

Still open: correlating Command Completion Events back to their issuing
command, driving Enable Slot/Address Device from this connect path
(currently only a boot-time smoke test), and the callback surface into
Section U's higher-level code.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HZ8kNoTuP63pbQtro4qvrm
2026-08-22 10:11:47 -04:00
Robert Allan JamesandClaude Sonnet 5 9c8ad8f6ff Artemis Milestone 2e (in progress): xHCI Command Ring write path proven live
Enable Slot command TRB submitted via a new xhci_submit_command()/
xhci_cmd_enable_slot(), ring doorbell 0, confirmed by a real Command
Completion Event on all three architectures -- the first time this driver
has written a TRB rather than only reading the Event Ring (2d). Added the
Command Ring's previously-missing Link TRB (xHCI 1.2 spec sec 4.9.2) for
wraparound correctness.

Port Register connect/disconnect handling, slot-ID/context bookkeeping,
Address Device, and the callback surface into Section U's code are still
open -- this is the discriminating first step, not full 2e.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HZ8kNoTuP63pbQtro4qvrm
2026-08-22 09:37:55 -04:00
Robert Allan JamesandClaude Sonnet 5 c2f1d94c97 Artemis Milestone 2c: xHCI controller bring-up wired, DoE CSV export off by default
xhci_bringup() (HC reset, DCBAA, Command/Event rings, RUN/STOP) was
uncommitted and referenced an XHCI_WAIT_FOR macro that was never defined,
breaking the build. Wired all four wait sites to the existing
xhci_wait_bit() helper instead, matching each register/bit/polarity
needed (halt-before-reset waits for HCH set; HCRST, CNR, and post-RUN
HCH waits all wait for their bit to clear).

Also flipped g_doe_log_enabled's default from 1 to 0 -- the per-tick
[HADES][DOE] CSV export was flooding every boot log and slowing
interactive verification for no reason during ordinary acceptance runs;
HB-ON still re-enables it at the REPL for anyone running an actual DoE
campaign.

Three-arch acceptance: amd64/aarch64/riscv64 all boot clean to ok>,
zero DoE rows in any log. aarch64 and riscv64 both exited cleanly via
BYE with no exception, confirming the earlier SMC->HVC PSCI fix still
holds. Logs and DoE CSV artifacts from this run included.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HZ8kNoTuP63pbQtro4qvrm
2026-08-22 08:33:35 -04:00
Robert Allan JamesandClaude Sonnet 5 94345c24b7 Artemis Milestone 2a complete: xHCI register header, PCI ID confirmed
live via QMP, ring sizing decided

include/starkernel/xhci.h: Capability/Operational/Runtime register
layouts, Port Register Set, Interrupter Register Set, Doorbell Array,
16-byte TRB struct -- all from the xHCI 1.2 spec, no existing
reference in this tree to build from (unlike virtio-blk). volatile
fields, no packed attribute, matching virtio_blk.c's documented
riscv64/QEMU-MMIO precedent. Compile-checked clean, sizeof(xhci_trb_t)
verified == 16.

QEMU qemu-xhci's PCI vendor:device ID (0x1B36:0x000D) confirmed live
via QMP query-pci against a real running instance -- not assumed from
memory, matches the Milestone 1 QMP infrastructure just built.

Ring sizing decided: fixed 256-TRB (one page) Command Ring and Event
Ring, single interrupter -- documented rationale in the header.

Bonus finding: src/starkernel/pci/pci.c already has more reusable
infrastructure than Milestone 2b assumed (pci_find_first is ID-based
lookup already existing; pci_bar/pci_map_bar/pci_enable are already
generic) -- 2b is smaller than originally scoped, noted in the punch
list.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-22 07:53:16 -04:00