diff --git a/system/drivers/pci-bus/pci-bus.zig b/system/drivers/pci-bus/pci-bus.zig index 1f540e2..6ce7728 100644 --- a/system/drivers/pci-bus/pci-bus.zig +++ b/system/drivers/pci-bus/pci-bus.zig @@ -21,19 +21,20 @@ const logging = @import("logging"); const device_manager_protocol = @import("device-manager-protocol"); const pci_class = @import("pci-class"); -/// Log a discovered function with its (class / subclass / prog-IF) triple decoded -/// to human names — the boot-log breadcrumb that says *what* the hardware is, so -/// "class 0x01 (Mass Storage Controller) subclass 0x06 (Serial ATA Controller) -/// progif 0x01 (AHCI 1.0)" reads straight off the log when writing a new driver. -/// A dedicated wider buffer than `writeLine`'s, since the decoded names are long. -fn logFunction(bus: u64, dev: u64, function: u64, class_triple: u32) void { +/// Log a discovered function as its would-be /etc/devices.csv columns (bus, base, +/// class, prog_if, vendor, device, subsystem) followed by the human-readable +/// class/subclass/prog-IF names — so a row for a new driver reads straight off the +/// boot log. `subsystem` prints as `*` when the function has none, matching the CSV +/// wildcard. All read unclaimed, through the bridge's ECAM: the enumerator never +/// claims the functions it probes (pci.zig's header — the device-owned pci.Function +/// view is what needs a claim, not this one). A wide buffer: the names are long. +fn logFunction(bus: u64, dev: u64, function: u64, class_triple: u32, vendor_id: u16, product_id: u16, subsystem: u32) void { const cc = pci_class.ClassCode.unpack(@truncate(class_triple)); const pif = pci_class.progIfName(cc.base, cc.subclass, cc.prog_if); - var line: [200]u8 = undefined; - const text = if (pif.len != 0) - std.fmt.bufPrint(&line, "/system/drivers/pci-bus: {d}:{d}.{d} class 0x{x:0>2} ({s}) subclass 0x{x:0>2} ({s}) progif 0x{x:0>2} ({s})\n", .{ bus, dev, function, cc.base, pci_class.className(cc.base), cc.subclass, pci_class.subclassName(cc.base, cc.subclass), cc.prog_if, pif }) catch return - else - std.fmt.bufPrint(&line, "/system/drivers/pci-bus: {d}:{d}.{d} class 0x{x:0>2} ({s}) subclass 0x{x:0>2} ({s}) progif 0x{x:0>2}\n", .{ bus, dev, function, cc.base, pci_class.className(cc.base), cc.subclass, pci_class.subclassName(cc.base, cc.subclass), cc.prog_if }) catch return; + var sub_buffer: [8]u8 = undefined; + const sub = if (subsystem == 0) "*" else std.fmt.bufPrint(&sub_buffer, "{X:0>8}", .{subsystem}) catch "*"; + var line: [320]u8 = undefined; + const text = std.fmt.bufPrint(&line, "/system/drivers/pci-bus: {d}:{d}.{d} bus=pci base={X:0>2} class={X:0>2} prog_if={X:0>2} vendor={X:0>4} device={X:0>4} subsystem={s} — {s} / {s}{s}{s}\n", .{ bus, dev, function, cc.base, cc.subclass, cc.prog_if, vendor_id, product_id, sub, pci_class.className(cc.base), pci_class.subclassName(cc.base, cc.subclass), if (pif.len != 0) " / " else "", pif }) catch return; _ = logging.write(text); } @@ -136,7 +137,6 @@ fn scan() void { if (vendor_device & 0xFFFF == 0xFFFF) continue; const class_revision = configRead(bus, dev, function, 0x08); found += 1; - logFunction(bus, dev, function, class_revision >> 8); registerAndReport(bus, dev, function, class_revision >> 8); } } @@ -221,6 +221,10 @@ fn registerAndReport(bus: u64, dev: u64, function: u64, class_triple: u32) void configWrite16(bus, dev, function, 0x04, command); } + // The devices.csv-column + friendly-name breadcrumb, now that vendor/device/ + // subsystem are read. Every discovered function is logged, matched or not. + logFunction(bus, dev, function, class_triple, descriptor.vendor, descriptor.device, descriptor.subsystem); + const registered = device.register(bridge_id, &descriptor) orelse { std.log.info("register refused for {d}:{d}.{d}", .{ bus, dev, function }); return; diff --git a/system/drivers/usb-xhci-bus/usb-xhci-bus.zig b/system/drivers/usb-xhci-bus/usb-xhci-bus.zig index f8c3efd..af514f0 100644 --- a/system/drivers/usb-xhci-bus/usb-xhci-bus.zig +++ b/system/drivers/usb-xhci-bus/usb-xhci-bus.zig @@ -390,13 +390,16 @@ fn reportInterface(manager: ipc.Handle, port: u32, interface: library.InterfaceI std.log.info("child report for port {d} interface {d} failed", .{ port, interface.number }); return null; }; - std.log.info("port {d} interface {d}: {s} ({d}/{d}/{d}) registered as device {d}", .{ + // The devices.csv columns (bus=usb, and the class triple as base/class/prog_if) + // then the human-readable interface name — a would-be /etc/devices.csv row read + // straight off the boot log. + std.log.info("port {d} interface {d} bus=usb base={X:0>2} class={X:0>2} prog_if={X:0>2} — {s} registered as device {d}", .{ port, interface.number, - usb_ids.interfaceName(interface.class, interface.subclass, interface.protocol), interface.class, interface.subclass, interface.protocol, + usb_ids.interfaceName(interface.class, interface.subclass, interface.protocol), registered, }); return registered; diff --git a/system/services/acpi/acpi.zig b/system/services/acpi/acpi.zig index d84609e..a4807db 100644 --- a/system/services/acpi/acpi.zig +++ b/system/services/acpi/acpi.zig @@ -214,11 +214,13 @@ fn onInit(endpoint: ipc.Handle) bool { while (i < registered_count) : (i += 1) { const entry = registered[i]; const hid = entry.hid[0..entry.hid_len]; + // The devices.csv columns (bus=acpi, hid) then the human-readable name — a + // would-be /etc/devices.csv row read straight off the boot log. const desc = acpi_ids.description(hid); if (desc.len != 0) - std.log.info("reported {s} (device {d}, {d} resources) — {s}", .{ hid, entry.device_id, entry.resource_count, desc }) + std.log.info("device {d} bus=acpi hid={s} — {s} ({d} resources)", .{ entry.device_id, hid, desc, entry.resource_count }) else - std.log.info("reported {s} (device {d}, {d} resources)", .{ hid, entry.device_id, entry.resource_count }); + std.log.info("device {d} bus=acpi hid={s} ({d} resources)", .{ entry.device_id, hid, entry.resource_count }); if (manager) |h| { var report = device_manager_protocol.ChildAdded{ .bus = @intFromEnum(device_manager_protocol.BusKind.acpi), .parent = node_id, .bus_address = entry.device_id, .identity = 0, .device_id = entry.device_id }; @memcpy(report.hid[0..entry.hid_len], entry.hid[0..entry.hid_len]); diff --git a/test/qemu_test.py b/test/qemu_test.py index b8e6291..117c6fb 100644 --- a/test/qemu_test.py +++ b/test/qemu_test.py @@ -628,7 +628,7 @@ CASES = [ {"name": "acpi-ps2", "smp": 4, "timeout": 150, - "expect": r"discovery: reported PNP0303[\s\S]*" + "expect": r"discovery: device \d+\s+bus=acpi hid=PNP0303[\s\S]*" r"device-manager: spawned \S*ps2-bus[\s\S]*" r"ps2-bus: keyboard driver attached", "fail": r"DANOS-TEST-RESULT: FAIL"}, @@ -675,8 +675,8 @@ CASES = [ {"name": "acpi-report", "smp": 4, "timeout": 150, - "expect": r"discovery: reported PNP0303 \(device \d+, 3 resources\)[\s\S]*" - r"discovery: reported PNP0F13 \(device \d+, 1 resources\)", + "expect": r"discovery: device \d+\s+bus=acpi hid=PNP0303[^\n]*\(3 resources\)[\s\S]*" + r"discovery: device \d+\s+bus=acpi hid=PNP0F13[^\n]*\(1 resources\)", "fail": r"DANOS-TEST-RESULT: FAIL"}, # M19.1/M19.3: the ring-3 PCI scan. pci-bus walks the ECAM through its mmio_map # grant and registers every function it finds; the kernel's own walk retired, so