diff --git a/system/drivers/usb-xhci-bus/usb-xhci-bus.zig b/system/drivers/usb-xhci-bus/usb-xhci-bus.zig index 5a24e70..eef7f91 100644 --- a/system/drivers/usb-xhci-bus/usb-xhci-bus.zig +++ b/system/drivers/usb-xhci-bus/usb-xhci-bus.zig @@ -196,17 +196,9 @@ fn scanPorts(manager: runtime.ipc.Handle) void { }; std.log.info("{d} root-hub ports", .{engine.max_ports}); - // Diagnostic: dump every root port's raw PORTSC (CCS = connect, PED = - // enabled, PLS = link state, speed) so a USB2 companion hub that isn't - // enumerating is visible — is it connected on a port we misread, or absent? - { - var p: u32 = 1; - while (p <= engine.max_ports) : (p += 1) { - const portsc = engine.portStatus(p); - if (portsc & 1 != 0 or (portsc >> 5) & 0xF != 5) // connected, or not in the disabled/disconnected link state - std.log.info("PORTSC[{d}] = 0x{x:0>8} ccs={d} ped={d} pls={d} speed={d}", .{ p, portsc, portsc & 1, (portsc >> 1) & 1, (portsc >> 5) & 0xF, (portsc >> 10) & 0xF }); - } - } + // Diagnostic: the USB2/USB3 root-port map (xECP) + every port's raw PORTSC, + // to find a USB2 companion hub that isn't presenting a connection. + engine.dumpPortTopology(); var port: u32 = 1; var connected: u32 = 0; diff --git a/system/drivers/usb-xhci-bus/usb-xhci-library.zig b/system/drivers/usb-xhci-bus/usb-xhci-library.zig index 3dc3ba8..7b00547 100644 --- a/system/drivers/usb-xhci-bus/usb-xhci-library.zig +++ b/system/drivers/usb-xhci-bus/usb-xhci-library.zig @@ -484,6 +484,39 @@ pub const Controller = struct { } // PORTSC for 1-based port `port`. + /// Diagnostic: walk the xECP list and log each Supported Protocol capability + /// (USB 2.0 vs 3.x, the compatible root-port range), then dump every port's + /// raw PORTSC. Reveals where the USB2 root ports are and their state — for + /// finding a USB2 companion hub that isn't presenting a connection. + pub fn dumpPortTopology(self: *const Controller) void { + const hccparams1 = read32(self.register_base + cap_hccparams1); + var offset: usize = (hccparams1 >> 16) & 0xFFFF; // xECP: dword offset from register_base + var guard: u32 = 0; + while (offset != 0 and guard < 64) : (guard += 1) { + const cap_base = self.register_base + offset * 4; + const dw0 = read32(cap_base); + const id = dw0 & 0xFF; + if (id == 2) { // Supported Protocol + const dw2 = read32(cap_base + 8); + const major = (dw0 >> 24) & 0xFF; + const minor = (dw0 >> 16) & 0xFF; + const port_offset = dw2 & 0xFF; + const port_count = (dw2 >> 8) & 0xFF; + std.log.info("xECP USB {d}.{d}: root ports {d}..{d}", .{ major, minor, port_offset, port_offset + port_count - 1 }); + } + const next = (dw0 >> 8) & 0xFF; + if (next == 0) break; + offset += next; + } + var port: u32 = 1; + while (port <= self.max_ports) : (port += 1) { + const portsc = self.portStatus(port); + std.log.info("PORTSC[{d}] = 0x{x:0>8} ccs={d} ped={d} pls={d} pp={d} speed={d}", .{ + port, portsc, portsc & 1, (portsc >> 1) & 1, (portsc >> 5) & 0xF, (portsc >> 9) & 1, (portsc >> 10) & 0xF, + }); + } + } + pub fn portStatus(self: *const Controller, port: u32) u32 { return read32(self.op_base + op_portsc_base + op_portsc_stride * (port - 1)); }