72 lines
3.1 KiB
Zig
72 lines
3.1 KiB
Zig
//! /system/drivers/usb-xhci-bus — the xHCI (USB 3) host-controller bus driver.
|
|
//! The device manager spawns **one instance per controller** it discovers (a machine
|
|
//! can carry several), passing the controller's device-tree id as argv[1]; this
|
|
//! instance claims that device and no other, so multiple instances never fight over
|
|
//! hardware. This increment proves the plumbing: parse the id, claim the controller,
|
|
//! and report its MMIO window. The next increments map the registers and bring the
|
|
//! controller up (reset, rings, port scan), then enumerate the USB devices on the
|
|
//! bus with the usb-abi request builders and publish each with `device_register`.
|
|
|
|
const std = @import("std");
|
|
const runtime = @import("runtime");
|
|
const device = runtime.device;
|
|
|
|
/// Format one whole log line and emit it in a single `debug_write`, so concurrent
|
|
/// instances (one per controller) can never interleave mid-line.
|
|
fn writeLine(comptime fmt: []const u8, arguments: anytype) void {
|
|
var line: [128]u8 = undefined;
|
|
_ = runtime.system.write(std.fmt.bufPrint(&line, fmt, arguments) catch return);
|
|
}
|
|
|
|
pub fn main(init: runtime.process.Init) void {
|
|
const argument = init.arguments.get(1) orelse {
|
|
_ = runtime.system.write("usb-xhci-bus: missing controller device id (argv[1])\n");
|
|
return;
|
|
};
|
|
const controller_id = std.fmt.parseInt(u64, argument, 10) catch {
|
|
writeLine("usb-xhci-bus: malformed controller device id '{s}'\n", .{argument});
|
|
return;
|
|
};
|
|
|
|
if (!device.claim(controller_id)) {
|
|
writeLine("usb-xhci-bus: unable to claim controller device {d}\n", .{controller_id});
|
|
return;
|
|
}
|
|
|
|
// Fetch our own descriptor back for the controller's resources.
|
|
const buffer = runtime.allocator().alloc(device.DeviceDescriptor, 64) catch {
|
|
_ = runtime.system.write("usb-xhci-bus: out of memory\n");
|
|
return;
|
|
};
|
|
const total = device.enumerate(buffer);
|
|
const descriptor = for (buffer[0..@min(total, buffer.len)]) |d| {
|
|
if (d.id == controller_id) break d;
|
|
} else {
|
|
writeLine("usb-xhci-bus: device {d} not in the device tree\n", .{controller_id});
|
|
return;
|
|
};
|
|
|
|
// The controller's operational registers live behind BAR0, enumerated as the
|
|
// device's first memory resource.
|
|
const register_window = for (descriptor.resources[0..@intCast(descriptor.resource_count)]) |resource| {
|
|
if (resource.kind == @intFromEnum(device.ResourceKind.memory)) break resource;
|
|
} else {
|
|
writeLine("usb-xhci-bus: controller device {d} has no MMIO window\n", .{controller_id});
|
|
return;
|
|
};
|
|
writeLine("usb-xhci-bus: claimed controller device {d} (registers at 0x{x}, {d} bytes)\n", .{
|
|
controller_id,
|
|
register_window.start,
|
|
register_window.len,
|
|
});
|
|
|
|
// Controller bring-up (map the window, reset, rings, port scan) is the next
|
|
// increment; stay resident as the bus's supervisor in the meantime.
|
|
while (true) runtime.system.sleep(1000);
|
|
}
|
|
|
|
pub const panic = runtime.panic;
|
|
comptime {
|
|
_ = &runtime.start._start; // pull the runtime entry shim into the image
|
|
}
|