//! The **device ABI**: the flat, `extern` device types that cross the system_call //! boundary — what `device_enumerate` hands a user-space driver, what //! `device_register` takes back. This is the devices sub-project's *public //! interface*, exposed as its own `device-abi` module the same way the VFS server //! exposes `vfs-protocol` — so both the kernel and user space depend on the contract //! by name, and neither reaches into the other's files. //! //! It is also the **single source of truth** for `DeviceClass` and `ResourceKind`: //! the kernel's rich, pointer-based device tree (system/kernel/device-model.zig, //! which user space must never import) re-exports these, so the enum that a driver //! matches on and the enum the kernel classifies with are the *same* type — no //! hand-kept "mirror in order" to drift. The core kernel↔user ABI is [[abi]]; the //! loader↔kernel handoff is [[boot-handoff]]. /// A coarse classification of a device, independent of the describing firmware. /// Kept small on purpose; refine as real drivers arrive. `enum(u32)` because the /// `@intFromEnum` value crosses the system_call boundary in `DeviceDescriptor.class`. pub const DeviceClass = enum(u32) { /// The synthetic root every discovered device hangs beneath. root, processor, interrupt_controller, timer, /// A PCI(e) host bridge — the root of a PCI segment (owns an ECAM window). pci_host_bridge, /// A single PCI function. pci_device, /// A device named in the ACPI namespace (from the DSDT/SSDT), carrying a /// hardware ID (`_HID`) and, where static, current resource settings (`_CRS`). acpi_device, /// The ACPI tables themselves, published as one node for the user-space acpi /// service (docs/discovery.md): memory resources over the AML blobs, /// a broad io_port grant for OperationRegion access, and the SCI interrupt. /// The one node whose claimant is trusted to run firmware bytecode. acpi_tables, /// One interface of a USB device, registered by the xHCI bus driver. It owns /// no MMIO — it is reached through its controller — so it carries no /// resources; the (class, subclass, protocol) triple that says what it is /// travels in the bus report's identity, not here. usb_device, /// A scanout framebuffer: a linear region of pixel memory the display service /// claims and maps. Unlike the other classes this one is not firmware-discovered /// — the kernel seeds it from the loader's [[boot-handoff]] framebuffer /// (`devices_broker.seedDisplay`). Its one `memory` resource is the framebuffer, /// flagged write-combining; the geometry to interpret it travels in /// `DeviceDescriptor.display`. display, unknown, }; /// The kind of hardware resource a device occupies. `enum(u32)` for the same /// boundary-crossing reason as `DeviceClass` (see `ResourceDescriptor.kind`). pub const ResourceKind = enum(u32) { /// A memory-mapped I/O window: `start` is the physical base, `len` its size. memory, /// A legacy I/O-port range: `start` is the first port, `len` the count. io_port, /// An interrupt: `start` is the global system interrupt (GSI), `len` is 1. irq, /// A range of bus numbers owned by a bridge: `start`..`start+len`. bus_range, }; /// One device resource, as handed to a user-space driver (flat, extern). pub const ResourceDescriptor = extern struct { kind: u64, // a ResourceKind value start: u64, len: u64, /// A bitmask of `resource_flag_*` hints. Zero for a plain register/RAM window; /// the kernel reads it when it maps the resource. Defaulted so every existing /// literal (which never set flags) keeps compiling and lays out identically. flags: u64 = 0, }; /// `ResourceDescriptor.flags`: map this `memory` resource **write-combining** rather /// than strong-uncacheable — for a framebuffer, where batched bursts to pixel memory /// are the whole point (an uncacheable framebuffer blit is glacial). See /// `mmio_map` (system/kernel/process.zig) and `setupPat` (…/x86_64/paging.zig). pub const resource_flag_write_combining: u64 = 1 << 0; pub const maximum_device_resources = 8; /// The byte order of a display's pixels — mirrors the loader's `PixelFormat` /// ([[boot-handoff]]) with the same numeric values, but lives here so user space /// (which must never import the loader↔kernel handoff) can name it. Only the two /// linear 32-bpp layouts a console can paint into exist; see docs/gop.md. pub const DisplayFormat = enum(u32) { rgbx = 0, // byte 0 = Red, 1 = Green, 2 = Blue, 3 = reserved bgrx = 1, // byte 0 = Blue, 1 = Green, 2 = Red, 3 = reserved }; /// The geometry of a `display` device's framebuffer, carried in its descriptor so a /// claiming driver knows how to interpret the pixel bytes its `memory` resource maps. /// `pitch` is bytes per row (may exceed `width * 4`; see docs/framebuffer.md). pub const DisplayInfo = extern struct { width: u32 = 0, // visible pixels per row height: u32 = 0, // visible rows pitch: u32 = 0, // bytes from one row's start to the next format: u32 = 0, // a DisplayFormat value refresh_hz: u32 = 0, // panel refresh rate from EDID (0 = unknown); see boot-handoff }; /// `DeviceDescriptor.parent` for a device with no parent — a root of the device tree. pub const no_parent: u64 = ~@as(u64, 0); /// `DeviceDescriptor.pci_class` for a device that is not a PCI function. (Zero would be /// ambiguous: 0x000000 is a real class code, "unclassified device".) pub const no_pci_class: u64 = ~@as(u64, 0); /// A device, as snapshotted for user space by `device_enumerate`. A driver scans /// these to find the hardware it owns, claims it, and maps its MMIO. /// /// `parent` makes the table a tree rather than a list, which is what a **bus driver** /// needs: it claims the bus, finds the devices below it, and publishes any it /// discovers itself with `device_register`. A registered child's resources must lie /// within its parent's (the kernel enforces this) — that containment is what makes /// delegation safe, since a device descriptor is otherwise a licence to map physical /// memory. pub const DeviceDescriptor = extern struct { id: u64, parent: u64, // a device id, or `no_parent` class: u64, // a DeviceClass value // The PCI class/subclass/prog-IF triple packed as 0xCCSSPP when this device is a PCI // function, or `no_pci_class` otherwise. This is how a manager tells *what* a // `pci_device` is (an xHCI controller, an AHCI controller) — decode the triple into // names with the pci-class module. pci_class: u64, // Numeric identity beyond the class triple, mirrored in the bus report's // ChildAdded so /system/configuration/devices.csv can bind on it: `vendor`/`device` are the PCI // vendor/device (or USB idVendor/idProduct), `subsystem` is the PCI subsystem id // packed `(subsystem_vendor << 16) | subsystem_device`. Zero where the bus has no // such concept. Defaulted so existing descriptor literals keep compiling and lay // out identically until they choose to set them. vendor: u16 = 0, device: u16 = 0, subsystem: u32 = 0, hid_len: u64, resource_count: u64, hid: [8]u8, resources: [maximum_device_resources]ResourceDescriptor, // Framebuffer geometry, meaningful only when `class` is `DeviceClass.display` // (zeroed otherwise). Kept here — a class-specific field on the shared descriptor — // the same way `pci_class` is meaningful only for `pci_device` and `hid` only for // `acpi_device`. display: DisplayInfo = .{}, };