reorg: relocate device/service clients (C3/C4)
- device.zig + device-manager.zig -> library/device/driver/driver.zig (module
"driver"): the driver author's whole interface — device access (claim/mmioMap/
irqBind/...) plus the device-manager hello() handshake, folded into one import.
- block.zig -> library/device/block/block.zig (a device type).
- display.zig/input.zig -> library/client/{display,input}/ (userspace-service
clients — they talk to services, not the kernel).
build.zig module graph updated; the runtime shim now maps runtime.device and
runtime.device_manager onto "driver", so consumers stay untouched (migrated in C2).
zig build green; driver-restart, usb-storage, display-native, input pass.
This commit is contained in:
parent
60f32ee9ff
commit
dded46726b
22
build.zig
22
build.zig
|
|
@ -481,32 +481,31 @@ pub fn build(b: *std.Build) void {
|
|||
.root_source_file = b.path("library/kernel/start.zig"),
|
||||
.imports = &.{ .{ .name = "process", .module = process_module }, .{ .name = "logging", .module = logging_module } },
|
||||
});
|
||||
const device_module = b.addModule("device", .{
|
||||
.root_source_file = b.path("library/kernel/device.zig"),
|
||||
// The driver author's interface (library/device/driver): device access + the
|
||||
// device-manager hello handshake, folded together.
|
||||
const driver_module = b.addModule("driver", .{
|
||||
.root_source_file = b.path("library/device/driver/driver.zig"),
|
||||
.imports = &.{
|
||||
.{ .name = "abi", .module = abi_module },
|
||||
.{ .name = "device-abi", .module = device_abi_module },
|
||||
.{ .name = "system-call", .module = system_call_module },
|
||||
},
|
||||
});
|
||||
const device_manager_client_module = b.addModule("device-manager", .{
|
||||
.root_source_file = b.path("library/kernel/device-manager.zig"),
|
||||
.imports = &.{
|
||||
.{ .name = "ipc", .module = ipc_module },
|
||||
.{ .name = "time", .module = time_module },
|
||||
.{ .name = "device-manager-protocol", .module = device_manager_protocol_module },
|
||||
},
|
||||
});
|
||||
// The block-device client — a device type, so library/device/block.
|
||||
const block_client_module = b.addModule("block", .{
|
||||
.root_source_file = b.path("library/kernel/block.zig"),
|
||||
.root_source_file = b.path("library/device/block/block.zig"),
|
||||
.imports = &.{
|
||||
.{ .name = "ipc", .module = ipc_module },
|
||||
.{ .name = "time", .module = time_module },
|
||||
.{ .name = "block-protocol", .module = block_protocol_module },
|
||||
},
|
||||
});
|
||||
// Userspace-service clients live in library/client (they talk to services, not the kernel).
|
||||
const display_client_module = b.addModule("display", .{
|
||||
.root_source_file = b.path("library/kernel/display.zig"),
|
||||
.root_source_file = b.path("library/client/display/display.zig"),
|
||||
.imports = &.{
|
||||
.{ .name = "ipc", .module = ipc_module },
|
||||
.{ .name = "time", .module = time_module },
|
||||
|
|
@ -514,7 +513,7 @@ pub fn build(b: *std.Build) void {
|
|||
},
|
||||
});
|
||||
const input_client_module = b.addModule("input", .{
|
||||
.root_source_file = b.path("library/kernel/input.zig"),
|
||||
.root_source_file = b.path("library/client/input/input.zig"),
|
||||
.imports = &.{
|
||||
.{ .name = "ipc", .module = ipc_module },
|
||||
.{ .name = "time", .module = time_module },
|
||||
|
|
@ -546,8 +545,7 @@ pub fn build(b: *std.Build) void {
|
|||
.{ .name = "logging", .module = logging_module },
|
||||
.{ .name = "file-system", .module = file_system_module },
|
||||
.{ .name = "start", .module = start_module },
|
||||
.{ .name = "device", .module = device_module },
|
||||
.{ .name = "device-manager", .module = device_manager_client_module },
|
||||
.{ .name = "driver", .module = driver_module },
|
||||
.{ .name = "input", .module = input_client_module },
|
||||
.{ .name = "block", .module = block_client_module },
|
||||
.{ .name = "display", .module = display_client_module },
|
||||
|
|
|
|||
|
|
@ -1,12 +1,15 @@
|
|||
//! User-space device access: enumerate the kernel's device table, claim a device,
|
||||
//! map its MMIO, and bind its interrupt. A driver uses these to find and take
|
||||
//! ownership of its hardware; the claim is the capability the kernel checks before
|
||||
//! mapping registers or routing an IRQ.
|
||||
//! library/device/driver — the driver author's interface: enumerate the kernel's device
|
||||
//! table, claim a device, map its MMIO, bind its interrupt (the claim is the capability the
|
||||
//! kernel checks before mapping registers or routing an IRQ), and say `hello` to the device
|
||||
//! manager at startup. The whole kernel + manager surface a driver needs, in one import.
|
||||
|
||||
const std = @import("std");
|
||||
const abi = @import("abi");
|
||||
const device_abi = @import("device-abi");
|
||||
const sc = @import("system-call");
|
||||
const ipc = @import("ipc");
|
||||
const time = @import("time");
|
||||
const device_manager_protocol = @import("device-manager-protocol");
|
||||
|
||||
pub const DeviceDescriptor = device_abi.DeviceDescriptor;
|
||||
pub const ResourceDescriptor = device_abi.ResourceDescriptor;
|
||||
|
|
@ -129,3 +132,42 @@ pub fn findDeviceDescriptorByHid(buffer: []DeviceDescriptor, hid_needle: []const
|
|||
|
||||
return null;
|
||||
}
|
||||
|
||||
// --- device-manager handshake (folded in from the former device-manager.zig) ---
|
||||
|
||||
/// What kind of driver is announcing itself (a bus that reports children, or a leaf
|
||||
/// device). Re-exported so callers name it without importing the protocol.
|
||||
pub const Role = device_manager_protocol.Role;
|
||||
|
||||
const lookup_attempts: u32 = 100;
|
||||
const lookup_pause_ms: u64 = 20;
|
||||
|
||||
/// Say hello to the device manager and return its endpoint, or null if there is no manager
|
||||
/// (best-effort standalone bring-up) or it refused the handshake. Bus drivers keep the handle
|
||||
/// to report children through; a driver that runs fine unsupervised discards it with `_ =`,
|
||||
/// and one that requires supervision bails on null. Logs the outcome itself.
|
||||
pub fn hello(role: Role, device_id: u64) ?ipc.Handle {
|
||||
var attempts: u32 = 0;
|
||||
const manager = while (attempts < lookup_attempts) : (attempts += 1) {
|
||||
if (ipc.lookup(.device_manager)) |handle| break handle;
|
||||
time.sleepMillis(lookup_pause_ms);
|
||||
} else {
|
||||
std.log.info("no device manager to hello", .{});
|
||||
return null;
|
||||
};
|
||||
|
||||
const message = device_manager_protocol.Hello{ .role = @intFromEnum(role), .device_id = device_id };
|
||||
var reply: [device_manager_protocol.reply_size]u8 = undefined;
|
||||
const length = ipc.call(manager, std.mem.asBytes(&message), &reply) catch {
|
||||
std.log.info("hello call failed", .{});
|
||||
return null;
|
||||
};
|
||||
if (length < device_manager_protocol.reply_size or
|
||||
std.mem.bytesToValue(device_manager_protocol.HelloReply, reply[0..device_manager_protocol.reply_size]).status != 0)
|
||||
{
|
||||
std.log.info("hello refused", .{});
|
||||
return null;
|
||||
}
|
||||
std.log.info("hello acknowledged", .{});
|
||||
return manager;
|
||||
}
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
//! Client side of the device-manager protocol (docs/device-manager.md): the
|
||||
//! calls a supervised driver makes *to* the manager, as opposed to
|
||||
//! `device-manager-protocol.zig`, which is the wire contract both sides share.
|
||||
//!
|
||||
//! Today this is just the hello handshake every spawned driver owes. The
|
||||
//! manager arms a hello deadline when it spawns a driver
|
||||
//! (system/services/device-manager/device-manager.zig): a driver that stays
|
||||
//! silent past it is assumed wedged before `main` and stopped, so every driver
|
||||
//! calls `hello` early in its startup. The retry-lookup-call-check this used to
|
||||
//! be — copied byte-for-byte into each bus and class driver — lives here once.
|
||||
|
||||
const std = @import("std");
|
||||
const ipc = @import("ipc");
|
||||
const time = @import("time");
|
||||
const device_manager_protocol = @import("device-manager-protocol");
|
||||
|
||||
/// What kind of driver is announcing itself (a bus that reports children, or a
|
||||
/// leaf device). Re-exported so callers name it without importing the protocol.
|
||||
pub const Role = device_manager_protocol.Role;
|
||||
|
||||
/// Endpoint lookups while the manager is still registering, and the pause
|
||||
/// between them: 100 x 20 ms = ~2 s, comfortably inside the manager's 3 s hello
|
||||
/// deadline (device-manager.zig `hello_deadline_ms`).
|
||||
const lookup_attempts: u32 = 100;
|
||||
const lookup_pause_ms: u64 = 20;
|
||||
|
||||
/// Say hello to the device manager and return its endpoint, or null if there is
|
||||
/// no manager (best-effort standalone bring-up) or it refused the handshake
|
||||
/// (version mismatch, unknown sender). Bus drivers keep the returned handle to
|
||||
/// report children through; a driver that runs fine unsupervised discards it
|
||||
/// with `_ =`, and a driver that requires supervision bails on null.
|
||||
///
|
||||
/// Logs the outcome itself (attribution is the kernel's, via the process's
|
||||
/// binary path), so callers stay a single line.
|
||||
pub fn hello(role: Role, device_id: u64) ?ipc.Handle {
|
||||
var attempts: u32 = 0;
|
||||
const manager = while (attempts < lookup_attempts) : (attempts += 1) {
|
||||
if (ipc.lookup(.device_manager)) |handle| break handle;
|
||||
time.sleepMillis(lookup_pause_ms);
|
||||
} else {
|
||||
std.log.info("no device manager to hello", .{});
|
||||
return null;
|
||||
};
|
||||
|
||||
const message = device_manager_protocol.Hello{ .role = @intFromEnum(role), .device_id = device_id };
|
||||
var reply: [device_manager_protocol.reply_size]u8 = undefined;
|
||||
const length = ipc.call(manager, std.mem.asBytes(&message), &reply) catch {
|
||||
std.log.info("hello call failed", .{});
|
||||
return null;
|
||||
};
|
||||
if (length < device_manager_protocol.reply_size or
|
||||
std.mem.bytesToValue(device_manager_protocol.HelloReply, reply[0..device_manager_protocol.reply_size]).status != 0)
|
||||
{
|
||||
std.log.info("hello refused", .{});
|
||||
return null;
|
||||
}
|
||||
std.log.info("hello acknowledged", .{});
|
||||
return manager;
|
||||
}
|
||||
|
|
@ -20,9 +20,9 @@ pub const fs = @import("file-system");
|
|||
pub const start = @import("start");
|
||||
pub const panic = start.panic;
|
||||
|
||||
// Device / service clients (relocated to library/device and library/client in C3/C4).
|
||||
pub const device = @import("device");
|
||||
pub const device_manager = @import("device-manager");
|
||||
// Device / service clients (now in library/device/driver, library/device/block, library/client).
|
||||
pub const device = @import("driver");
|
||||
pub const device_manager = @import("driver"); // hello() folded into driver
|
||||
pub const input = @import("input");
|
||||
pub const block = @import("block");
|
||||
pub const display = @import("display");
|
||||
|
|
|
|||
Loading…
Reference in New Issue