usb: [diagnostic] dump the xECP USB2/USB3 port map + all PORTSC
The USB2 companion hub carrying the user's full-speed keyboard never appears — only the SuperSpeed hub (port 19) and SS storage (port 21) connect. To find where the USB2 root ports are and whether the companion is presenting on one, walk the xECP Supported Protocol capabilities (logging each USB 2.0 / 3.0 root-port range) and dump every port's raw PORTSC unconditionally (ccs/ped/pls/pp/speed). QEMU confirms the dump (USB2 ports 5-8, USB3 ports 1-4). Branch-only diagnostic.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user