diff --git a/system/drivers/usb-xhci-bus/usb-xhci-bus.zig b/system/drivers/usb-xhci-bus/usb-xhci-bus.zig index ee7898a..2bec30a 100644 --- a/system/drivers/usb-xhci-bus/usb-xhci-bus.zig +++ b/system/drivers/usb-xhci-bus/usb-xhci-bus.zig @@ -108,6 +108,22 @@ fn readRegister(offset: usize) u32 { return register.*; } +/// The xHCI default Protocol Speed IDs (the PORTSC port-speed field, bits 13:10) +/// decoded to human names — the boot-log breadcrumb for what actually enumerated on +/// a port, the USB analog of the pci-bus class-code line. A controller may redefine +/// these through its Supported Protocol capability, but the defaults cover every +/// speed QEMU and real hardware report at this (pre-descriptor) stage. +fn speedName(speed: u32) []const u8 { + return switch (speed) { + 1 => "Full-speed (USB 2.0, 12 Mb/s)", + 2 => "Low-speed (USB 2.0, 1.5 Mb/s)", + 3 => "High-speed (USB 2.0, 480 Mb/s)", + 4 => "SuperSpeed (USB 3.0, 5 Gb/s)", + 5 => "SuperSpeedPlus (USB 3.1, 10 Gb/s)", + else => "unknown speed", + }; +} + /// The root-hub port scan: read the capability registers for the port count /// and the operational-register offset, then one PORTSC per port. The connect /// bit (CCS) and the speed field reflect hardware state directly — no @@ -129,7 +145,7 @@ fn scanPorts(manager: runtime.ipc.Handle) void { if (port_status & 1 == 0) continue; // CCS: nothing connected connected += 1; const speed = (port_status >> 10) & 0xF; // the PORTSC port-speed class - writeLine("usb-xhci-bus: port {d} connected (speed class {d})\n", .{ port, speed }); + writeLine("usb-xhci-bus: port {d} connected — {s} (speed class {d})\n", .{ port, speedName(speed), speed }); const report = protocol.ChildAdded{ .parent = controller_id,