Two driver-model milestones plus a tree-wide naming pass. Suite 35/35 (QEMU) + host tests green. M11 — IRQ-as-IPC. A ring-3 driver now sleeps until its device interrupts it. New src/kernel/irq.zig: per-GSI endpoint bindings, comptime per-vector trampolines, dispatch = mask GSI -> LAPIC EOI -> notifyLocked, all under one lock region. irq_bind/irq_ack syscalls, gated by the device claim like mmio_map. interruptDispatch no longer EOIs — each handler owns its EOI, because a level line must be masked before it is acknowledged (irq_ack is the unmask). Bindings are keyed on the owning task and released on exit (a shared endpoint's siblings survive). hpetd rewritten interrupt-driven. Tests: hpet (rewritten, reads back the I/O APIC routing) and irqfree. M12 — bus drivers. DeviceDesc gains a parent, making the device table a tree. dev_register (device_register) lets a process publish children below a device it claimed; the kernel enforces resource containment (a child's resources must nest in its parent's), so a descriptor can't fabricate a window over kernel RAM. Descriptor copied in via copyFromUser (physmap walk — an unmapped user pointer fails the call instead of faulting the kernel). Per-parent child cap bounds table exhaustion. sbin/busd.zig is a worked bus driver. Test: bus. Naming — per docs/coding-standards.md: non-acronym abbreviations spelled out (message, descriptor, device_service, scheduler, runtime, physical, interpreter, ...); acronyms kept (IPC, MMIO, DMA, HCD, ...); files are kebab-case (ipc-synchronous.zig, device-service.zig, vfs-protocol.zig, ...). Exceptions: POSIX/C ABI names and Zig idioms (init/len/ptr) kept. Module collisions resolved by specific naming (config -> parameters, device.zig alias -> device_model). AML op/Op disambiguated: op = opcode, Op = operation; per-opcode parse handlers renamed opX -> parseX. New driver docs: drivers.md, driver-model.md (bus/class/HCD shapes + the proposed M13–M16 ABI), coding-standards.md.
54 lines
1.8 KiB
Zig
54 lines
1.8 KiB
Zig
//! The VFS wire protocol — the message format spoken between a client (via the
|
|
//! `runtime` file API) and the user-space VFS server over IPC. A request is a fixed
|
|
//! `Request` header followed by an inline payload (a path, or write bytes); a
|
|
//! reply is a fixed `Reply` header followed by an inline payload (read bytes, or
|
|
//! a Stat). Everything fits in one IPC message (<= ipc MESSAGE_MAXIMUM = 256 bytes).
|
|
//!
|
|
//! This is user-space only — the kernel knows nothing of files or paths; it only
|
|
//! moves the bytes. Shared by lib/unistd.zig (client) and sbin/vfs.zig (server).
|
|
|
|
pub const Op = enum(u32) {
|
|
open, // open(path) -> node id
|
|
close, // close(node)
|
|
read, // read(node, offset, len) -> bytes
|
|
write, // write(node, offset, bytes) -> count
|
|
stat, // stat(node) -> Stat
|
|
};
|
|
|
|
/// Request header. `node` is the server-side open-file id (from a prior open);
|
|
/// for `open` the path is the payload and `len` is its length. `offset`/`len`
|
|
/// carry the read/write position and count.
|
|
pub const Request = extern struct {
|
|
op: Op,
|
|
node: u64,
|
|
offset: u64,
|
|
len: u32,
|
|
flags: u32,
|
|
};
|
|
|
|
/// Reply header. `status` is 0 on success or a negative errno; `node` is the new
|
|
/// open-file id (for `open`); `len` is the payload length (bytes read, or the
|
|
/// Stat size).
|
|
pub const Reply = extern struct {
|
|
status: i32,
|
|
_pad: u32 = 0,
|
|
node: u64 = 0,
|
|
len: u32 = 0,
|
|
_pad2: u32 = 0,
|
|
};
|
|
|
|
pub const Stat = extern struct {
|
|
size: u64,
|
|
kind: u32,
|
|
_pad: u32 = 0,
|
|
};
|
|
|
|
pub const message_maximum: usize = 256;
|
|
pub const req_size: usize = @sizeOf(Request);
|
|
pub const reply_size: usize = @sizeOf(Reply);
|
|
/// Largest inline payload that still fits one IPC message alongside a header.
|
|
pub const maximum_payload: usize = message_maximum - req_size;
|
|
|
|
/// Open flags.
|
|
pub const O_CREAT: u32 = 1;
|