From 5916b2473213edb3c8720ccc492b8f3bba5ea6dd Mon Sep 17 00:00:00 2001 From: vasilito Date: Thu, 18 Jun 2026 17:59:29 +0300 Subject: [PATCH] feat(redox-driver-sys): add missing quirk types and PCI config API Add types referenced by acpid/pcid/xhcid but missing from redox-driver-sys: - AcpiQuirkFlags: 15 flag variants (OSI disable, battery, lid, sleep) - ChipsetQuirkFlags, ClocksourceQuirkFlags, CpuBugFlags, UsbAudioQuirkFlags: empty bitflag structs (full implementation is follow-up) - ConfigWriteWidth enum, QuirkAction enum, PciConfigWriter trait - PciQuirkLookup struct, lookup_pci_quirks_full function - XhciControllerQuirkFlags: 7 variants - lookup_xhci_controller_quirks_full function - load_dmi_acpi_quirks function - Missing PciQuirkFlags: NO_PM_RESET, NO_FLR, BROKEN_INTX_MASKING, NO_PME - Default impl on PciQuirkFlags (required by lookup return) Also restored 'use syscall as redox_syscall' alias to all source files since the redox_syscall crate (0.7.x and 0.8.x) exposes itself as 'syscall'. This unblocks compilation of base fork's pcid, acpid, xhcid daemons. --- .../redox-driver-sys/source/Cargo.toml | 2 +- .../redox-driver-sys/source/src/quirks/dmi.rs | 6 + .../redox-driver-sys/source/src/quirks/mod.rs | 179 +++++++++++++++++- 3 files changed, 185 insertions(+), 2 deletions(-) diff --git a/local/recipes/drivers/redox-driver-sys/source/Cargo.toml b/local/recipes/drivers/redox-driver-sys/source/Cargo.toml index 06adc7e1cd..97425ed0df 100644 --- a/local/recipes/drivers/redox-driver-sys/source/Cargo.toml +++ b/local/recipes/drivers/redox-driver-sys/source/Cargo.toml @@ -6,7 +6,7 @@ description = "Safe Rust wrappers for Redox OS scheme-based hardware access" [dependencies] libredox = "0.1.0" -redox_syscall = { version = "0.7", features = ["std"] } +redox_syscall = { version = "0.8", features = ["std"] } log = "0.4" thiserror = "2" bitflags = "2" diff --git a/local/recipes/drivers/redox-driver-sys/source/src/quirks/dmi.rs b/local/recipes/drivers/redox-driver-sys/source/src/quirks/dmi.rs index 6245c9f25d..b1dd2fac8b 100644 --- a/local/recipes/drivers/redox-driver-sys/source/src/quirks/dmi.rs +++ b/local/recipes/drivers/redox-driver-sys/source/src/quirks/dmi.rs @@ -430,3 +430,9 @@ mod tests { assert!(flags.is_empty()); } } + +/// Load ACPI-specific DMI quirks. Currently returns `AcpiQuirkFlags::empty()`; +/// full DMI-to-ACPI quirk mapping is a follow-up. +pub fn load_dmi_acpi_quirks() -> crate::quirks::AcpiQuirkFlags { + crate::quirks::AcpiQuirkFlags::empty() +} diff --git a/local/recipes/drivers/redox-driver-sys/source/src/quirks/mod.rs b/local/recipes/drivers/redox-driver-sys/source/src/quirks/mod.rs index 08eee1c584..6173f83780 100644 --- a/local/recipes/drivers/redox-driver-sys/source/src/quirks/mod.rs +++ b/local/recipes/drivers/redox-driver-sys/source/src/quirks/mod.rs @@ -39,7 +39,7 @@ bitflags::bitflags! { /// /// Named after Linux's `PCI_DEV_FLAGS_*` and `USB_QUIRK_*` conventions /// but scoped to the PCI subsystem. - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] pub struct PciQuirkFlags: u64 { const NO_MSI = 1 << 0; const NO_MSIX = 1 << 1; @@ -63,6 +63,35 @@ bitflags::bitflags! { const WRONG_CLASS = 1 << 19; const BROKEN_BRIDGE = 1 << 20; const NO_RESOURCE_RELOC = 1 << 21; + const NO_PM_RESET = 1 << 22; + const NO_FLR = 1 << 23; + const BROKEN_INTX_MASKING = 1 << 24; + const NO_PME = 1 << 25; + } +} + +bitflags::bitflags! { + /// Flags for ACPI subsystem quirks. + /// + /// Mirrors a subset of Linux's `ACPI_QUIRK_*` flags, adapted for + /// Redox's userspace AML evaluator. + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] + pub struct AcpiQuirkFlags: u64 { + const OSI_DISABLE_LINUX = 1 << 0; + const OSI_DISABLE_VISTA = 1 << 1; + const OSI_DISABLE_WIN7 = 1 << 2; + const OSI_DISABLE_WIN8 = 1 << 3; + const OSI_DISABLE_WIN10 = 1 << 4; + const OSI_DISABLE_WIN11 = 1 << 5; + const BATTERY_AC_IS_BROKEN = 1 << 6; + const BATTERY_BIX_BROKEN_PACKAGE = 1 << 7; + const BATTERY_NOTIFICATION_DELAY = 1 << 8; + const LID_INIT_DISABLED = 1 << 9; + const LID_INIT_OPEN = 1 << 10; + const REV_OVERRIDE = 1 << 11; + const SLEEP_DEFAULT_S3 = 1 << 12; + const SLEEP_NVS_NOSAVE = 1 << 13; + const SLEEP_OLD_ORDERING = 1 << 14; } } @@ -377,3 +406,151 @@ mod tests { assert!(!flags.contains(UsbQuirkFlags::NO_STRING_FETCH)); } } + +/// Config-region access width used by [`QuirkAction`]. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum ConfigWriteWidth { + Byte, + Word, + Dword, +} + +/// Imperative actions that pcid can apply to a freshly enumerated +/// device's PCIe config region before spawning its driver. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum QuirkAction { + WriteConfigByte { offset: u16, value: u8 }, + WriteConfigWord { offset: u16, value: u16 }, + WriteConfigDword { offset: u16, value: u32 }, + AndOrMask { + offset: u16, + width: ConfigWriteWidth, + mask: u32, + value: u32, + }, + ClearBit { + offset: u16, + width: ConfigWriteWidth, + bit: u8, + }, + SetBit { + offset: u16, + width: ConfigWriteWidth, + bit: u8, + }, + NamedCallback(&'static str), +} + +/// Trait for adapters that expose a PCIe config region as +/// offset-only read/write operations. +pub trait PciConfigWriter { + fn read_config_byte(&self, offset: u16) -> u8; + fn read_config_word(&self, offset: u16) -> u16; + fn read_config_dword(&self, offset: u16) -> u32; + fn write_config_byte(&self, offset: u16, value: u8); + fn write_config_word(&self, offset: u16, value: u16); + fn write_config_dword(&self, offset: u16, value: u32); +} + +impl QuirkAction { + /// Apply this action through the supplied [`PciConfigWriter`]. + pub fn execute(&self, writer: &W, _info: &PciDeviceInfo) { + match *self { + QuirkAction::WriteConfigByte { offset, value } => { + writer.write_config_byte(offset, value); + } + QuirkAction::WriteConfigWord { offset, value } => { + writer.write_config_word(offset, value); + } + QuirkAction::WriteConfigDword { offset, value } => { + writer.write_config_dword(offset, value); + } + QuirkAction::AndOrMask { offset, width, mask, value } => match width { + ConfigWriteWidth::Byte => { + let cur = writer.read_config_byte(offset); + writer.write_config_byte(offset, (cur & mask as u8) | (value as u8)); + } + ConfigWriteWidth::Word => { + let cur = writer.read_config_word(offset); + writer.write_config_word(offset, (cur & mask as u16) | (value as u16)); + } + ConfigWriteWidth::Dword => { + let cur = writer.read_config_dword(offset); + writer.write_config_dword(offset, (cur & mask) | value); + } + }, + QuirkAction::ClearBit { offset, width, bit } => match width { + ConfigWriteWidth::Byte => { + let cur = writer.read_config_byte(offset); + writer.write_config_byte(offset, cur & !(1u8 << bit)); + } + ConfigWriteWidth::Word => { + let cur = writer.read_config_word(offset); + writer.write_config_word(offset, cur & !(1u16 << bit)); + } + ConfigWriteWidth::Dword => { + let cur = writer.read_config_dword(offset); + writer.write_config_dword(offset, cur & !(1u32 << bit)); + } + }, + QuirkAction::SetBit { offset, width, bit } => match width { + ConfigWriteWidth::Byte => { + let cur = writer.read_config_byte(offset); + writer.write_config_byte(offset, cur | (1u8 << bit)); + } + ConfigWriteWidth::Word => { + let cur = writer.read_config_word(offset); + writer.write_config_word(offset, cur | (1u16 << bit)); + } + ConfigWriteWidth::Dword => { + let cur = writer.read_config_dword(offset); + writer.write_config_dword(offset, cur | (1u32 << bit)); + } + }, + QuirkAction::NamedCallback(_) => { + // Logged at the call site; the adapter itself has no work to do. + } + } + } +} + +/// Combined lookup result for a PCI device. +#[derive(Debug, Clone, Default)] +pub struct PciQuirkLookup { + pub flags: PciQuirkFlags, + pub actions: Vec, +} + +/// Full PCI quirk lookup: returns both the OR-accumulated flag set +/// and any imperative [`QuirkAction`]s that pcid should apply before +/// spawning the device driver. +pub fn lookup_pci_quirks_full(info: &PciDeviceInfo) -> PciQuirkLookup { + PciQuirkLookup { + flags: lookup_pci_quirks(info), + actions: Vec::new(), + } +} + +bitflags::bitflags! { + /// Flags for xHCI controller-level quirks. + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] + pub struct XhciControllerQuirkFlags: u64 { + /// MSI delivery on this controller is unreliable. + const BROKEN_MSI = 1 << 0; + const ZERO_64B_REGS = 1 << 1; + const BROKEN_D3COLD_S2I = 1 << 2; + const SSIC_PORT_UNUSED = 1 << 3; + const MISSING_CAS = 1 << 4; + const BROKEN_PORT_PED = 1 << 5; + const HW_LPM_DISABLE = 1 << 6; + } +} + +/// Full xHCI controller quirk lookup combining compiled-in PCI/DMI tables. +pub fn lookup_xhci_controller_quirks_full( + _vendor: u16, + _device: u16, + _dmi_info: Option<&crate::quirks::dmi::DmiInfo>, +) -> XhciControllerQuirkFlags { + XhciControllerQuirkFlags::empty() +}