//! 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/devices/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, 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, }; pub const maximum_device_resources = 8; /// `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, hid_len: u64, resource_count: u64, hid: [8]u8, resources: [maximum_device_resources]ResourceDescriptor, };