fix(usb): the xHCI controller is found by class on any bus, sized, taken from the firmware, and 64-byte contexts laid out

boards/BRINGUP.md A1, FABRIC-3 SXL.  It was matched by QEMU's own IDs on
bus 0 alone, so no real board's was found.  Now pci_find_class() reads
every bus/slot/function; pci_bar_size() sizes BAR0; the USB Legacy Support
capability hands the controller over from the BIOS, SMIs off; CSZ=1
contexts are placed 64 bytes apart instead of refused.  XHCI_QEMU_ARGS
lets QEMU place the controller as real hardware does.

Test first: an NEC controller behind a PCIe root port -- no attach before,
Zuse minted after, on all three ISAs.  Standard acceptance unchanged; five
hot-plugged identities attach.  Not rehearsable: firmware handoff, CSZ=1.
Still open: only the first controller found is used.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rajames
2026-10-14 13:30:50 -04:00
co-authored by Claude Opus 5.5
parent 0e2c60dac3
commit 080b7012ba
24 changed files with 72536 additions and 67 deletions
+15
View File
@@ -72,6 +72,15 @@ int pci_init(void *rsdp);
*/
int pci_find_first(uint16_t vendor_id, uint16_t device_id, PciDevice *out);
/*
* pci_find_class — the index-th function (0 = the first) on any bus,
* slot and function whose class code, subclass and programming interface
* match: e.g. 0x0C 0x03 0x30 is an xHCI controller of any vendor.
* Returns 0 and fills *out, or -1 if there are not that many.
*/
int pci_find_class(uint8_t class_code, uint8_t subclass, uint8_t prog_if,
unsigned index, PciDevice *out);
/* Config space accessors */
uint32_t pci_read32 (const PciDevice *d, uint16_t offset);
uint16_t pci_read16 (const PciDevice *d, uint16_t offset);
@@ -93,6 +102,12 @@ void pci_enable(const PciDevice *d);
*/
uint64_t pci_bar(const PciDevice *d, int bar_idx);
/*
* pci_bar_size — the size of memory BAR bar_idx, by the standard sizing
* probe (decoding off meanwhile). 0 for an I/O BAR or none.
*/
uint64_t pci_bar_size(const PciDevice *d, int bar_idx);
/*
* pci_map_bar — make the BAR MMIO region accessible.
* amd64: calls vmm_map_range(phys, phys, size, WR|CD).
+9 -16
View File
@@ -17,9 +17,9 @@
* byte-wise access. The xHCI spec's register layout is naturally aligned at
* every offset, so this translates directly without padding tricks.
*
* QEMU's `qemu-xhci` device identifies as PCI vendor 0x1B36 (Red Hat, Inc.),
* device 0x000D — confirmed live via QMP `query-pci` against a real running
* instance (not assumed from memory), 2026-08-22.
* The controller is found by its PCI class (0x0C/0x03/0x30, xhci.c), on any
* bus, from any vendor. Until 2026-10-14 it was matched by QEMU's own
* qemu-xhci IDs, 1B36:000D, on bus 0 alone (boards/BRINGUP.md A1).
*/
#ifndef STARKERNEL_XHCI_H
@@ -27,12 +27,6 @@
#include <stdint.h>
/* -------------------------------------------------------------------------
* PCI identification
* ------------------------------------------------------------------------- */
#define XHCI_PCI_VENDOR_ID 0x1B36u /* Red Hat, Inc. (QEMU qemu-xhci) */
#define XHCI_PCI_DEVICE_ID 0x000Du
/* -------------------------------------------------------------------------
* Capability Registers (BAR0 + 0)
@@ -413,13 +407,12 @@ typedef struct {
#define XHCI_PSC_EVT_PORT_ID(parameter) (((uint32_t)(parameter) >> 24) & 0xFFu)
/* -------------------------------------------------------------------------
* Slot Context, Endpoint Context, Input Control Context — 32-byte layout
* only (xHCI 1.2 spec tables 6-6, 6-9, 6-5). HCCPARAMS1.CSZ selects 32- vs
* 64-byte contexts; confirmed live (CSZ=0) against this driver's target
* QEMU qemu-xhci controller (2026-08-22) before writing these -- 64-byte
* contexts (CSZ=1) are NOT implemented here. xhci_cmd_address_device()
* checks CSZ itself and refuses rather than silently mis-laying-out a
* 64-byte-context controller as 32-byte.
* Slot Context, Endpoint Context, Input Control Context — their fields
* (xHCI 1.2 spec tables 6-6, 6-9, 6-5). HCCPARAMS1.CSZ selects 32- vs
* 64-byte contexts; a 64-byte one holds these same fields in its first 32
* bytes, so these structs serve both, and xhci.c places each context 32 or
* 64 bytes apart (xhci_ctx_bytes(); since 2026-10-14 -- a CSZ=1 controller
* was refused before).
* ------------------------------------------------------------------------- */
typedef struct {
+2 -3
View File
@@ -538,9 +538,8 @@ int xhci_cmd_disable_slot(xhci_dev_t *dev, uint32_t slot_id);
* is servicing (xHCI 1.2 spec table 7-13 speed IDs) -- used to pick EP0's
* default Max Packet Size before any device descriptor has been read.
*
* Refuses (-2) if HCCPARAMS1.CSZ indicates 64-byte contexts -- only
* 32-byte contexts are implemented (see xhci.h's own doc comment on
* xhci_slot_ctx32_t).
* Lays the contexts out 32 or 64 bytes apart, as HCCPARAMS1.CSZ says
* (xhci.c's xhci_ctx_bytes(); 64-byte contexts refused until 2026-10-14).
*
* Called from xhci_poll_events()'s Command Completion handling once Enable
* Slot succeeds -- not called directly by other code.