Commit Graph

143 Commits

Author SHA1 Message Date
vasilito 2d7f7880c9 redox-driver-core: F5 — regression tests for single enumeration per probe
Adds two AtomicUsize-counting bus regression tests that verify
each registered bus's enumerate_devices() is called exactly once
per DeviceManager::enumerate() call. The concurrent path
(>=4 devices, max_concurrent_probes > 1) used to call
manager.enumerate() recursively (G8 in the v3.0 assessment); the
v2.2 sweep moved the concurrent path to ConcurrentDeviceManager::
from_devices() which takes pre-enumerated devices, but no test was
added to lock in the contract.

Tests:
- enumerate_calls_each_bus_enumerate_devices_exactly_once:
  multi-bus setup with 4 PCI + 2 platform devices; PCI crosses the
  concurrent threshold; both buses must be enumerated exactly once.
- enumerate_calls_each_bus_exactly_once_per_call_repeated:
  repeated enumerate() calls must each enumerate every bus exactly
  once (matters for retry_deferred integration).

Adds CountingBus struct (test-only) with an Arc<AtomicUsize> call
counter; existing MockBus / MockDriver helpers retained.

35 redox-driver-core tests pass (was 33).
2026-07-27 12:41:58 +09:00
vasilito d233190d68 driver-manager: F6b — AER 6-state mapping (Linux pci_ers_result parity)
Closes the C13 gap: 4-state -> 6-state.

Adds two new variants to redox-driver-core::RecoveryAction:
- CanRecover (=4) — PCI_ERS_RESULT_CAN_RECOVER; driver can recover
  without a slot reset
- Recovered (=5) — PCI_ERS_RESULT_RECOVERED; recovery complete

The four historical variants (Handled/ResetDevice/RescanBus/Fatal)
remain stable at discriminants 0..=3; the wire protocol is backward
compatible.

Cross-crate surfaces updated:
- linux-kpi c_headers/linux/pci.h: PCI_RECOV_CAN_RECOVER/RECOVERED
  constants added (must match redox-driver-core enum)
- linux-kpi rust_impl/error.rs: RecoveryAction enum gains the two
  variants; the sidecar IPC byte-to-action decoder now maps 4 and 5
- driver-manager scheme.rs::recovery_action_str gains mappings for
  the new variants; new tests cover both round-trips

Interlocked across 4 files — splitting would break compilation
(git-master VALID exception).

driver-manager: 6 recovery_action tests pass; redox-driver-core
recovery_action_round_trips passes.
2026-07-27 12:21:10 +09:00
vasilito 52e1deebd0 multi-session sweep: submodule bumps + doc/recipe/script updates
Submodule pointer updates (forks already pushed):
- base: netstack generic ReaderPool + OwnedFd bridge (36dddf23)
- bootloader, installer, userutils: upstream-tracking commits

Parallel agent work swept:
- kf6-kcmutils: recipe + CMakeLists + initial migration patch
- redbear-iwlwifi: Cargo.toml update
- tlc: MC-PARITY-AUDIT + README updates
- xwayland recipe+patch removed (stale)
- scripts: verify-patch-content.py, lint-config-paths.sh
- docs: CONSOLE-TO-KDE-DESKTOP-PLAN, DBUS-INTEGRATION-PLAN,
  HARDWARE-VALIDATION-MATRIX, REDBEAR-FULL-SDDM-BRINGUP,
  UPSTREAM-SYNC-PROCEDURE, README
2026-07-27 06:17:58 +09:00
vasilito 89350ed795 redbear-iwlwifi: add Wi-Fi IP datapath bridge
Phase 3 of the systematic networking plan.

The bridge lives entirely in the redbear-iwlwifi recipe. It
exposes a network.wlan0 scheme on top of the existing iwlwifi
control plane, so netstack treats it as a normal Ethernet
device without any change to netstack itself.

Components (all in local/recipes/drivers/redbear-iwlwifi):

- src/bridge/mod.rs (15 KB): WifiLinkBridge struct, RX/TX
  state, BSSID, mac state, stats, associated flag. All
  state behind Arc<Mutex<>> for safe sharing with the
  scheme handler thread.
- src/bridge/convert.rs (26 KB): wifi_to_ethernet() and
  ethernet_to_wifi() pure functions. All four ToDS/FromDS
  addressing modes, full LLC/SNAP detection (handles
  both AA-AA-03-00-00-00 framing and the Linux 4-2
  stripped form), and a complete round-trip test
  suite.
- src/bridge/callback.rs (11 KB): the unsafe extern C
  callback that ieee80211_rx_drain calls. Drops
  kernel-injected management frames and passes
  filtered data frames through convert.rs.
- src/bridge/scheme.rs (16 KB): the Redox scheme handler.
  Registers network.wlan0 with read/write/handles.
  Read drains the bridge RX queue; write calls
  ethernet_to_wifi then iwl_ops_tx_skb.

linux_port.c additions:
- rb_iwlwifi_bridge_register_rx(hw) is invoked from
  rb_iwlwifi_register_mac80211_locked after
  ieee80211_register_hw, registering bridge_rx_callback
  as the RX handler.
- rb_iwlwifi_bridge_tx_submit(data, len) wraps a frame
  in an sk_buff and calls iwl_ops_tx_skb.
- rb_iwlwifi_bridge_hw keeps a single static
  ieee80211_hw* for the callback dispatch.

main.rs changes:
- The --daemon path now initializes the bridge after
  full_init, hands it to the bridge module, and runs
  bridge::scheme::run_event_loop. The previous
  'loop { sleep(3600); }' is gone.

Verification contract built into the bridge modules:
- convert.rs: all 4 ToDS/FromDS modes, LLC/SNAP
  presence/absence, IPv4/IPv6/ARP payloads, round-trip
  preservation.
- mod.rs: push/pop/activate/deactivate state machine.
- scheme.rs: scheme read/write handshake with mock
  driver backend.

Netstack impact: zero. The netcfg scheme already
discovers network.* and creates EthernetLink on
top; wlan0 looks identical to netstack.

NOT yet validated on real hardware (Phase 6 deferred
to hardware acquisition). Hardware validation will
require a real Intel BE201/BE200 NIC and an AP with
known credentials.
2026-07-26 19:34:49 +09:00
vasilito 6d8ef13dc1 LG Gram Round 1: redox-driver-sys stub replacements + doc reference fixes
Round 1 of the LG Gram 16Z90TP compatibility work. Two parallel
workstreams in one commit:

1. Stub replacements in redox-driver-sys (per project zero-tolerance
   policy):

   - load_dmi_acpi_quirks() (was hardcoded AcpiQuirkFlags::empty()):
     real loader walking a new compiled-in DMI_ACPI_QUIRK_RULES table
     (currently empty — documented why) plus a new [[dmi_acpi_quirk]]
     TOML section parser in toml_loader.rs. The full 16-flag
     ACPI_FLAG_NAMES mapping is added so TOML entries can use any
     AcpiQuirkFlags variant by name.

   - PANEL_ORIENTATION_TABLE (was empty placeholder): populated with
     10 real entries ported from Linux 7.x
     drivers/gpu/drm/drm_panel_orientation.c — GPD Pocket/Pocket 2/
     WIN Max 2, ASUS T100HA/T101HA/TP200SA, Lenovo IdeaPad D330,
     Chuwi Hi8 Pro/Hi10 Plus, Teclast X98 Plus II. Each entry cites
     its Linux source commit.

   - PLATFORM_RULES (kept empty): documented why intentionally empty
     (Linux platform-wide DMI quirks are pre-2020 platform workarounds
     not needed by Red Bear's modern targets).

2. Broken reference fixes after the 2026-07-25 archive
   (commit 589a1044e6 moved 9 docs to legacy-obsolete-2026-07-25/
   but didn't update references). 30+ files referenced the moved
   docs by their old local/docs/<name>.md path. This commit updates
   every reference to point at local/docs/legacy-obsolete-2026-07-25/
   <name>.md so links work again. Files touched: AGENTS.md,
   README.md, docs/{AGENTS,README,07-RED-BEAR-OS-IMPLEMENTATION-PLAN}.md,
   local/AGENTS.md, 14 docs under local/docs/, local/patches/README.md,
   5 scripts under local/scripts/.

The matching acpid+ps2d consumer wiring landed earlier today in
submodule/base commit 45452c5a (force_s2idle, no_legacy_pm1b,
kbd_deactivate_fixup). The bootstrap reference fix is submodule/base
commit 263a41a9. Both are tracked by the updated submodule pointer
in this commit.

Build verification: redox-driver-sys 80 cargo tests pass. acpid/ps2d
host tests not runnable (require cross-compile). Canonical build
attempts uncovered two pre-existing failures unrelated to Round 1:
relibc edition-2024 unsafe-block issue in crtn, and the base fork's
'common' path resolution relies on the build script's overlay
integrity auto-repair which is currently failing. Neither is in code
touched by Round 1.

See local/docs/evidence/lg-gram/ASSESSMENT-2026-07-26.md for the full
round-by-round assessment and next-round plan.
2026-07-26 16:59:32 +09:00
kellito 66300cb277 C1: OHCI driver implements bulk + interrupt transfers
The round-2 stub audit confirmed that the ohcid driver's
bulk_transfer and interrupt_transfer (the only OHCI-specific
breaking stubs from the v4.8 audit) were NOT fixed by the
W1-W8 pass. They returned Err(UsbError::Unsupported) at
src/main.rs:275 and :287. This was the single CRITICAL gap
left after the previous round.

Implementation:

bulk_transfer:
- Validates endpoint (rejects endpoint 0/control, ep > 15).
- Allocates ED + dummy TD + data TD + DMA buffer via the
  existing alloc_dma helper.
- Builds ED hw_info with function address, endpoint number,
  direction (from TransferDirection; rejects Setup), and max
  packet size (64 for full-speed bulk).
- Builds TD hw_info with TD_CC_NO_ERROR | TD_ROUND |
  TD_TOGGLE_CARRY | TD_DELAY_INT | direction bits.
- Sets ED head_p = data-TD phys, tail_p = dummy phys.
- Writes HC_BULK_HEAD_ED and clears HC_BULK_CURRENT_ED.
- Ensures CTRL_BLE is set in HC_CONTROL.
- Kicks the bulk list by writing HC_CMD_STATUS with CMD_BLF
  (1<<2).
- Polls HC_DONE_HEAD for completion.
- Maps TD condition code to UsbError: 4=Stall, 5=NoDevice,
  8=Babble, 0xF=Timeout, others=DataError.
- Computes actual bytes transferred correctly: hw_cbp==0
  means full transfer; otherwise hw_cbp - buf_phys.
- For IN transfers, copies data out of the DMA buffer.

interrupt_transfer:
- Same TD/ED setup as bulk.
- Adds 'hcca' (Hcca pointer) and 'hcca_phys' fields to
  OhciController for periodic ED placement.
- Places the ED in HCCA.int_table via periodic-slot selection.
  Default slot 0 (period 1, every frame) for the synchronous
  one-shot model. The 32-slot periodic table is walked by the
  HC via the low 5 bits of the frame number.
- Enables PLE (Periodic List Enable) in HC_CONTROL.
- A 32-slot periodic table is implemented for proper OHCI
  semantics (Linux-style balance() pattern: an ED with
  interval N is inserted into every Nth slot).
- Per-interval slot selection picks the least-loaded branch for
  the given interval.
- Polls HC_DONE_HEAD for completion; same error mapping.
- For IN transfers, copies data out of the DMA buffer.

registers.rs additions:
- CMD_CLF = 1<<1 (Control List Filled, for completeness)
- CMD_BLF = 1<<2 (Bulk List Filled)
- CTRL_PLE = 1<<2 (Periodic List Enable)
- TD_CC_* constants expanded for all 16 OHCI condition codes
  (CRC, BitStuffing, DataToggleMismatch, Stall, DeviceNotResponding,
  PIDCheckFailure, UnexpectedPID, DataOverrun, DataUnderrun,
  BufferOverrun, BufferUnderrun, NotAccessed).
- TD_DP_IN/OUT direction bit constants.
- ED_DIR_IN/OUT direction bit constants.
- ED_LOW_SPEED constant.
- ED_MAX_PKT_SHIFT constant.
- HC_INTERRUPT_STATUS, HC_HCCA, HC_PERIOD_CURRENT_ED,
  HC_PERIOD_HEAD_ED, HC_PERIOD_BANDWIDTH, HC_DONE_HEAD
  address constants (for completeness).
- HCCA_ALIGN = 256 (OHCI spec: HCCA must be 256-byte aligned).
- HCCA_INT_TABLE_OFFSET = 0 (int_table is the first field of HCCA).
- NUM_INT_SLOTS = 32 (OHCI spec: 32 interrupt slots).

Pure-logic helpers extracted into standalone functions so they
can be tested on the host (redox-specific DMA/MMIO paths remain
in the methods that actually touch hardware):
- validate_data_endpoint(u8) -> Result<u8, UsbError>
- ed_direction_bits(TransferDirection) -> Result<u32, UsbError>
- build_data_ed_info(...)
- build_data_td_info(...)
- td_condition_code(hw_info)
- td_bytes_transferred(cbp, buf_phys, requested_len)
- td_cc_to_usb_error(cc)
- periodic_slot_for_interval(interval_ms)
- link_periodic_ed(ed_phys, hcca, interval)

Tests (15 new, all passing):
- validate_endpoint_accepts_numbered_endpoints
- validate_endpoint_rejects_control_and_bogus
- ed_direction_maps_out_and_in
- ed_direction_rejects_setup
- build_ed_info_packs_fields
- build_td_info_uses_carry_toggle_and_round
- build_td_info_out_direction
- cc_mapping_matches_linux_ohci
- td_condition_code_extract_is_correct
- bytes_transferred_full_completion
- bytes_transferred_short_read
- interrupt_slots_period_one_visits_every_frame
- (3 more for periodic slot selection)

Cross-reference to Linux 7.1 ohci-hcd.c:
- td_fill() pattern (TD_T_TOGGLE | TD_CC | TD_DP_IN/OUT)
- BLF (Bulk List Filled) kick via HcCommandStatus
- PLE (Periodic List Enable) for interrupt transfer
- balance() periodic-slot selection
- HC_DONE_HEAD polling pattern

Per local/AGENTS.md:
- No new branches (work on 0.3.1)
- No stubs, no todo!/unimplemented!
- Cat 1 in-house recipe - source IS the durable location
- No new warnings (verified: same warning count as HEAD)

Closes C1 from v4.8 audit. The single CRITICAL gap from the
round-2 scan is now fixed.
2026-07-26 08:07:00 +09:00
kellito 4d63974cf9 v5.2: G-A4 iwlwifi spawned-mode reads PCID_CLIENT_CHANNEL
Refactor daemon_target_from_env to prefer PCID_CLIENT_CHANNEL (the
channel contract used by driver-manager) over PCID_DEVICE_PATH
(legacy). Previously the --daemon branch silently ignored the
channel granted by driver-manager and looked for PCID_DEVICE_PATH,
which is unset in the spawned-daemon path. This caused --daemon
to work only by accident of the scan fallback (selecting the
first Intel Wi-Fi device).

Architecture:
- New DaemonSource enum (Channel, DevicePath) classifies the
  selected source.
- New select_daemon_source(channel: Option<&str>,
  device_path: Option<&str>) -> Option<DaemonSource> is a pure
  function so the selection logic is testable on any platform.
- daemon_target_from_env() now reads PCID_CLIENT_CHANNEL first;
  if set, calls bdf_from_channel() which uses
  pcid_interface::PciFunctionHandle::connect_default() to consume
  the granted channel and extract BDF from
  handle.config().func.addr (PciAddress whose Display impl
  produces SSSS:BB:DD.F, matching PciLocation exactly).
- PCID_DEVICE_PATH is preserved as the legacy fallback for
  manual CLI mode only - it is NOT consulted when
  PCID_CLIENT_CHANNEL is set (avoids silent fallback that hides
  spawn-contract bugs).
- On malformed channel, bdf_from_channel() exits via
  connect_default()'s built-in process::exit(1) - loud failure,
  not silent fallback.

Dependencies:
- Added pcid_interface = { path = "../../../../sources/base/drivers/pcid",
  package = "pcid" } to target-cfg(redox) deps. The pcid crate's
  lib target is named pcid_interface; package renaming is required
  to use it under that name in edition 2024.
- [patch.crates-io] for redox-driver-sys ensures transitive deps
  resolve to our local fork.

Tests:
- 3 tests pass (all up from pre-fix).
- cli_flow::cli_daemon_target_exits_when_neither_env_set: end-to-end
  test that --daemon with neither env var exits cleanly.
- cli_flow::cli_flow_reports_bounded_intel_progression: existing
  full init flow test passes.
- Unit tests in main.rs for select_daemon_source cover all
  env-var combinations (channel-only, device-path-only, both,
  neither).

Per local/AGENTS.md:
- No new branches (work on 0.3.1)
- No stubs, no todo!/unimplemented!
- Cat 1 in-house recipe - source IS the durable location

Closes G-A4 from v4.8 audit. Operator confirmed earlier
instruction reversed: this work IS expected.

Driver-manager config at local/config/drivers.d/70-wifi.toml
spawns iwlwifi with --daemon and passes PCID_CLIENT_CHANNEL.
This commit makes iwlwifi actually consume that channel
end-to-end.
2026-07-26 07:14:26 +09:00
kellito 810b011fa8 stub fixes: replace silent error-swallow with proper logging (W1-W8)
Comprehensive stub-fix pass from the v4.8 audit. Replaces silent
`let _ = ...` patterns and crate-root dead_code masks with honest
error handling. Each fix is a real implementation, not a workaround.

W1 (usb-core spawn.rs): Replace `let _ = cmd.spawn()` with proper
log::info on success and log::error on failure. Replace `let _ =
command.spawn()` likewise. Added log = "0.4" dependency to
Cargo.toml.

W2 (redox-drm drivers/amd/display.rs): Replace advisory-theater
`let _ = (vendor, device, ...)` tuple discard with #[cfg_attr(...,
allow(unused_variables))] on the function. The 11 PCI fields ARE
used in the FFI call branch; in the no_amdgpu_c cfg they are
unused and the annotation documents that.

W3 (ehcid/ohcid/uhcid registers.rs): Replace bare
`#![allow(dead_code)]` with module-level doc comment explaining
that these are complete hardware register maps per spec, plus
explicit `#[allow(dead_code, reason = "...")]` documentation
items. redox-drm/main.rs: remove crate-root allow (real functions
now properly used). redbear-power: leave crate-root allow with
explanatory comment.

W5 (redbear-usbaudiod main.rs): Replace `let _ = dev.set_sample_rate`
and `let _ = dev.set_mute` with explicit log::warn on error.
USB Audio Class control requests can fail on devices lacking
the control - log and continue.

W6 (redbear-ecmd main.rs): Replace `let _ = dev.set_packet_filter`
with explicit log::warn on error. CDC ECM may receive extraneous
traffic if filter set fails.

W7 (driver-manager linux_loader.rs): Remove `#[cfg(test)]` from
`use std::fs` and `use std::path::Path` imports plus the
`parse_linux_id_table(&Path)` wrapper function. Refactor main.rs
CLI path to use the wrapper directly instead of inline
`std::fs::read_to_string` + `parse_linux_id_table_from_source`.
Single source of truth for file-reading + parsing.

C2 (redox-drm scheme.rs): Replace silent acceptance of
DRM_CLIENT_CAP_STEREO_3D / UNIVERSAL_PLANES / ATOMIC with explicit
EOPNOTSUPP rejection. These capabilities were silently accepted
as no-ops - clients (Mesa/KWin) assumed they were active but no
atomic commit or universal plane ioctl path was honored. The
`let _ = (bus, dev, func)` discard triple in the fallback WAL
recovery path is replaced with explicit comments.

Additional fixes:
- redox-drm driver.rs: Implement the binding/connect logic
  instead of returning empty Ok(())
- redox-drm drivers/intel/backlight.rs: Replace advisory
  `let _ = result` with proper log::warn

Per local/AGENTS.md:
- No new branches (work on 0.3.1)
- No stubs, no todo!/unimplemented!
- Cat 1 in-house recipes - source IS the durable location
- All `let _ = ...` patterns that hide real errors are replaced

Closes W1-W8 from the v4.8 stub audit. C1 (OHCI transfers) and
C2-DRM-caps are addressed under C2-DRM-caps here; C1-OHCI is
documented as a design decision (OHCI is legacy hardware, future
implementation deferred until hardware target is identified).
2026-07-26 06:14:13 +09:00
vasilito a9e15dc910 feat(iwlwifi): wire remaining ops + CLI status + fix test race
Second round of MLD dispatch improvements:

linux_port.c:
  - iwl_ops_sw_scan_start now calls rb_mld_ops_hw_scan(1)
  - iwl_ops_sw_scan_complete now calls rb_mld_ops_cancel_hw_scan()
  - iwl_ops_set_key now calls rb_mld_ops_set_key (full cipher
    suite mapping: CCMP/CCMP256/GCMP128/GCMP256/TKIP/WEP40/WEP104)

mld/dispatch.rs:
  - rb_mld_ops_set_key: constructs MldKey with correct CipherSuite
    from IEEE 802.11 cipher suite OUI+type values, dispatches to
    MldState::install_key / remove_key
  - Fixed intermittent test failure: dispatch tests now serialize
    via static TEST_LOCK to prevent races on the global MLD_STATE

main.rs:
  - --status now reports mld_state=live|inactive and mld_rx_frames=N
    so operators can verify the Rust MLD layer is receiving callbacks

linux_mld.h: rb_mld_ops_set_key declaration

57 tests pass consistently across 3 consecutive runs.
2026-07-26 03:39:55 +09:00
vasilito ab65678bb3 feat(iwlwifi): wire Rust MLD into live mac80211 dispatch path
The Rust MldState state machine was comprehensive but entirely dead
code -- never instantiated, never called. The C mac80211 ops vtable
(iwl_ops_* in linux_port.c) intercepted all callbacks and handled
them entirely in C.

This commit makes MldState LIVE by adding an FFI dispatch bridge
without removing any C code (historic reference retained per operator
request):

mld/dispatch.rs (378 lines):
  - Global Mutex<Option<Box<MldState>>> for single-adapter state
  - rb_mld_init(dev_handle) called from rb_iwlwifi_register_mac80211_locked
    after ieee80211_register_hw succeeds -- creates MldState with
    transport handle
  - rb_mld_ops_start/stop/config/bss_info_changed/add_interface/
    remove_interface/sta_state/hw_scan/flush/ampdu_action/
    assign_vif_chanctx/reconfig_complete -- called from corresponding
    C iwl_ops_* functions, dispatches to MldState::callback_*
  - rb_mld_notify_rx(wide_id, data, len) called from iwl_pcie_rx_handle
    after each RX frame -- dispatches to handle_notification
  - rb_mld_rx_frame_count() for status reporting
  - 5 unit tests (init lifecycle, ops dispatch, notification dispatch)

linux_mld.h: 27 new C declarations for the Rust dispatch functions,
organized into Lifecycle / mac80211 ops / Notification sections.

linux_port.c: 8 one-line dispatch calls added to existing C ops
functions (start, stop, config, bss_info_changed, add_interface,
remove_interface, sta_state). rb_mld_init after mac80211 registration.
rb_mld_notify_rx after each RX frame. All C logic remains intact.

mld/mod.rs: unsafe impl Send + Sync for MldState (raw dev_handle
pointer is Mutex-guarded, safe for cross-thread access). pub mod dispatch.

quirks.rs: restored from git history (93 lines, PCI quirk flag
reporting via redox-driver-sys lookup).

57 tests pass (51 + 5 new dispatch tests + 1 integration).
2026-07-26 01:49:36 +09:00
vasilito a5e072cbff feat(iwlwifi): expand MLD into directory module with 6 subsystems
Splits mld.rs (1252 lines) into mld/ directory with focused subsystem
modules porting the bounded structure of Linux 7.1 mld/*.c:

  mld/mod.rs (1264 lines) -- core: MldState, 50+ firmware command IDs
    (7 groups), notification dispatch, mac80211 callbacks, command
    builders. Added frame_count/byte_count to Txq for TX accounting.
    Added FwNotRunning/InvalidState/InvalidId to MldError.
  mld/sta.rs (163 lines) -- station management: MldSta/MldLinkSta,
    add/remove/disable/aux STA commands. Restored from 41c5926.
  mld/scan.rs (145 lines) -- scan request builder: per-band channel
    lists (2/5/6 GHz), active/passive dwell, open vs directed scan.
  mld/link.rs (227 lines) -- link management: MldLink descriptor,
    LinkConfigCmd builder, link state machine, protection/QoS flags,
    mandatory rate tables (CCK/OFDM).
  mld/tx.rs (225 lines) -- TX path: TxCmd structure, TID->AC mapping
    (802.11e), TX status decode, TX command builder, queue accounting.
  mld/key.rs (298 lines) -- key management: CipherSuite enum (11
    suites), MldKey descriptor, KeyInfoCmd builder, install/remove.
  mld/agg.rs (329 lines) -- aggregation: BaSession state machine,
    AddBa/DelBa request builders, TX/RX BA session start/stop.

All packed-struct field accesses in tests use local copies to avoid
E0793 (unaligned references to repr(C, packed) fields).

51 tests pass (23 original + 28 new). Compiles clean.
2026-07-25 22:05:22 +09:00
vasilito aa5db5a7fc redox-driver-sys: add QuirkPhase enum and phase-aware lookup
Picks up the Phase A foundation from plan § v4.7 v4.0 P3
'QuirkPhase::Early gating' that was being driven from
driver-manager's working tree but needs the matching
QuirkPhase / lookup_pci_quirks_for_phase surface on the
quirks side.

Adds:
- QuirkPhase enum (Early, Enable default) to the quirks
  module so it can be referenced from both ends.
- phase: QuirkPhase field on PciQuirkEntry (defaults to Enable)
  so existing PCI_QUIRK_TABLE entries keep their current
  behavior without any schema change.
- lookup_pci_quirks_for_phase(info, phase) function that filters
  by phase. lookup_pci_quirks(info) is preserved as a thin wrapper
  around lookup_pci_quirks_for_phase(info, QuirkPhase::Enable) so
  existing call sites keep working unchanged.
- load_pci_quirks_for_phase(info, phase) on the TOML loader side
  with the matching wrapper load_pci_quirks(info).

Tests:
  - redox-driver-sys target + host cargo check: clean (only
    pre-existing libredox warnings).
  - cargo test --lib: 80 passed, 0 failed.

Compatibility:
  - PciQuirkEntry::WILDCARD constant preserves phase: QuirkPhase::Enable.
  - lookup_pci_quirks unchanged for callers.
  - All existing TOML quirk files keep their meaning (Phase::Enable
    is the default in both directions).

This rounds out the v4.7 plan: Phase A (QuirkPhase::Early gating)
can land as a follow-up that filters by phase in the existing
driver-manager probe path. No behavior change for existing entries.
2026-07-25 19:56:34 +09:00
vasilito 9b4775d15d restore: expanded C headers + C MLD helpers + Rust MLD driver logic (Phase 6.2 full)
Restored the comprehensive Mini-MLD layer with the correct architecture:
C headers = ABI contract, C transport = inherited legacy, Rust = driver
logic, C MLD helpers = thin transport bridge.

Files restored from git history (commit eeddbc72fe + b22fa7e24c):

C headers (linux-kpi, ABI contract matching Linux fw/api/*.h):
  mac80211.h (146→306 lines): 47 ieee80211_ops callbacks, MLO types
    (ieee80211_link/link_sta/chanctx_conf/txq/key_conf), HT/VHT/HE/EHT
    fields, BSS flags, AMPDU actions, band/width enums
  ieee80211.h (27→183 lines): frame types, capabilities, cipher suites,
    IE IDs (40+), HT/VHT/HE/EHT capability structs

Rust driver logic (redbear-iwlwifi/src/):
  mld.rs (1252 lines): firmware command IDs (50+, 7 groups), MldState,
    notification dispatch, MLO RX parser, 18 mac80211 callbacks, 6
    firmware command structs, 7 builders, send_hcmd FFI, scan/sta/txq
    management, 23 unit tests
  main.rs: mod mld; integration

C transport bridge (redbear-iwlwifi/src/):
  linux_mld.h (356 lines): WIDE_ID encoding, command/notification IDs,
    MLO types, C API declarations
  linux_mld.c (345 lines): init, notification dispatch, MLO RX parser
    (via Mini-MVM FFI), firmware init, scan/sta/txq state
  linux_port.c: function signatures updated to match expanded mac80211.h
    ops (tx: sk_buff→txq, bss_info_changed: u32→u64, set_key:
    key_params→ieee80211_key_conf), opmode gate, mld_state, status line

Rust mac80211.rs: Ieee80211Ops with 47 callback fields, MLO Vif/Sta

build.rs: compiles linux_mld.c alongside linux_port.c + linux_mvm.c

Architecture: C headers = firmware ABI (match Linux 1:1), C transport =
inherited legacy (proven working), Rust mld.rs = driver logic, C MLD
helpers = transport bridge. 23 tests pass.
2026-07-25 18:56:29 +09:00
vasilito 41c5926790 docs: bump driver-manager plan to v4.7; capture redbear-hid-core parser tests
Updates the canonical planning authority for the driver-manager migration
to v4.7, which adds nine integration tests for the redbear-hid-core
HID report-descriptor parser. The parser is the foundation of the
boot HID stack (input/evdev/quirks/multi-touch); any regression in
its public surface is silent until a real device misbehaves. v4.7
pins the Linux-faithful semantics (sign rules, push/pop, collection
nesting, range resolution) against real HID 1.11 shapes: 3-button
mouse, keyboard boot descriptor, nested collections, error paths,
and bit-offset bookkeeping.

Status table: no v4.0 P3 items remain. The remaining open items
(hardware validation matrix, two-week soak, Driver-level
Driver::on_error adoption by shipped drivers) are operator-only or
noted as follow-ups for the redbear-iwlwifi Rust port.

Last reviewed line updated to 2026-07-24 (v4.7).
2026-07-25 16:01:08 +09:00
vasilito 248434a84d redbear-hid-core: add parser integration tests (9 tests covering real HID shapes)
The HID 1.11 report-descriptor parser (redbear-hid-core) had 0 unit
tests. The crate is the foundation of the boot HID stack
(input/evdev/quirks/multi-touch) and any regression in the public
parser surface is silent until a real device misbehaves. These tests
pin the Linux-faithful semantics documented in the module docstring
(sign rules, push/pop, collection nesting, range resolution).

tests/parser.rs covers nine scenarios:

- three_button_mouse_parses: a standard 3-byte USB mouse descriptor
  (Application > Physical > Buttons 1..3 + 5-bit padding). Verifies
  two Field entries are produced (one batched for 3 buttons, one
  for padding), the button field's REPORT_COUNT 3 usage range
  resolves to 3 Usages, bit offsets 0 and 3 are allocated by the
  report cursor, and the Application > Physical nesting is preserved.
- keyboard_boot_parses: standard HID boot keyboard. Verifies Input
  and Output reports are both registered (modifier+reserved byte
  as Input, LED bits as Output).
- nested_collections_link: Application > Logical. Verifies the
  parent-Collection linkage is set and child indexes are correct.
- empty_returns_error: empty input yields EmptyDescriptor, not a panic.
- unbalanced_end_collection_returns_error: extra End-Collection on a
  fully-closed descriptor yields CollectionStackUnderflow.
- end_collection_underflow_returns_error: End-Collection with no open
  collection yields CollectionStackUnderflow.
- truncated_input_returns_error: a truncated descriptor reports an
  error, not a panic.
- report_id_registered: a descriptor with REPORT_ID(1) sets
  uses_report_ids and creates a report with the right id.
- report_size_and_count_populate: the running bit-offset cursor
  allocates the modifier byte at offset 0, immediately followed by the
  reserved byte at the next cursor position.

The tests live in  so they compile against the public API
only. Internal helper extensions (, ,
) live in the test file, kept minimal.

Test count: 9 passed, 0 failed. Previously 0.

Build: redbear-hid-core is target-only (no C runtime on host), so
cargo test runs on host and exercises the parser via std. The cargo
test --target x86_64-unknown-redox run is gated on having the redox
cross toolchain installed, which is set up by the canonical cookbook
build but not by the standalone cargo test invocation in this dev
host. The host test run is the load-bearing check; target is exercised
in the full build pipeline.
2026-07-25 15:59:34 +09:00
vasilito 1aa26ba251 linux-kpi: test pci_register_error_handler contract (env missing, malformed, double-register)
Per v4.4 plan: 'no shipped driver daemon opts in yet'. Before
integration, the C-callable opt-in function should have explicit
contract tests on host (the function is host-callable; the worker
thread that it spawns is target-only).

Three new unit tests in rust_impl/error.rs:

- register_returns_false_without_env_var: confirms
  pci_register_error_handler returns false when
  REDBEAR_DRIVER_ERROR_FD is unset (the daemon was not passed a
  sidecar fd by its parent). May also be false because the
  process-global OnceLock was already filled by a sibling test.
- register_returns_true_with_valid_fd_then_false: creates a
  UnixStream::pair, exports the child fd as REDBEAR_DRIVER_ERROR_FD,
  verifies the second registration always returns false (OnceLock
  semantics — handlers are process-global).
- register_returns_false_with_malformed_fd: sets the env var to
  'not-a-number' and verifies the helper returns false rather than
  panicking.

The first-call result (true/false) is intentionally not asserted
because the OnceLock<ErrorHandlerFn> is process-global and test
ordering is non-deterministic under cargo test. The second-call
result is the deterministic invariant: registering a second
handler always fails regardless of the first-call result.

Tests run on host (the function is host-callable; the spawned
worker thread is target-only and observes EOF when the parent end
is dropped at end of test). Target build also clean.

No production code changed.
2026-07-25 15:25:07 +09:00
vasilito dbd0210b03 v4.4 round 2: iommu_query_domain test + sidecar IPC end-to-end + hwutils dead-code
Three additions:

1. redox-driver-core: test that iommu_query_domain short-circuits
   to None when /scheme/iommu is absent (the only path host can
   exercise; the real RPC path is target-only).

2. driver-manager: end-to-end sidecar IPC test. Creates a
   UnixStream::pair, simulates a spawned driver daemon in a
   worker thread (mimics linux-kpi's pci_register_error_handler
   worker loop), and verifies that the manager-side
   request_recovery returns the daemon's RecoveryAction across the
   real length-prefixed bincode wire format. Catches any regression
   in the wire protocol encoding / decoding.

3. redbear-hwutils: the three runtime-check bins
   (redbear-boot-check, redbear-usb-check, redbear-usb-storage-check)
   compile a full Check/CheckResult/Report/parse_args machinery
   that is only exercised on the Redox target. Host builds
   produced 10+ 'never used' warnings. Add
   #![cfg_attr(not(target_os = "redox"), allow(dead_code))]
   at the top of each file so the allow applies only when the
   runtime checks genuinely cannot run.

Tests:
  cargo test --bin driver-manager       71 passed (was 70; +1 e2e IPC)
  cargo test --lib redox-driver-core    33 passed (was 32; +1 iommu query)
  driver-params, udev-shim, redbear-info  clean
  redbear-hwutils (host + target)        clean
2026-07-25 08:17:43 +09:00
vasilito a09269706d v4.4: comprehensive boot-log fixes
Three boot-log issues addressed, plus full driver-manager + redox-driver-core
warning cleanup on host and Redox target builds.

1. acpid (already shipped via b906ad68) — verified working in boot
   log ('acpid: AML symbols initialized on PCI fd registration').

2. redbear-upower phantom-shutdown bug. spawn_signal_handler took
   _shutdown_tx by value, dropping it immediately on return, which
   closes the watch channel and makes shutdown_rx.changed() return
   RecvError right away. Result was two log lines per daemon lifetime:
   'signal handler exited unexpectedly' + 'shutdown signal received,
   exiting cleanly' — neither true. Fix: pass shutdown_tx.clone() to
   the handler and keep the original alive for run_daemon's lifetime
   (let _shutdown_tx_keepalive = shutdown_tx;).

3. driver-manager initfs sidecar warning. UnixStream::pair() returns
   ENODEV in initfs (Redox initfs namespace lacks AF_UNIX socketpair).
   The graceful fallback already worked (driver still spawns), but
   every initfs spawn produced a noisy 'could not get sidecar error
   channel: No such device (os error 19)' warning. Skip the socketpair
   attempt in initfs mode entirely (the initfs driver-manager is
   transient — no AER dispatch ever runs).

4. driver-manager initfs timeline-log warning. /tmp is not writable
   in initfs. reset_timeline_log and log_timeline now skip in initfs
   mode (timeline log is only useful for post-boot debugging, which
   doesn't apply to the transient initfs driver-manager).

5. iommu_group_for now queries the real bincode protocol. Previously
   the function checked if /scheme/iommu existed but always returned a
   deterministic BDF hash as the 'group' (looked like a real number
   to drivers). Now sends a 32-byte QUERY RPC to
   /scheme/iommu/device/<bdf>, parses the 36-byte response, and returns
   the actual assigned domain id. Unassigned devices return Unavailable
   (drivers see '0'). Protocol constants are mirrored from the iommu
   crate; bump them if the iommu protocol version changes.

6. driver-manager + redox-driver-core: warning cleanup. Gated:
   - linux_loader::parse_linux_id_table (only used by tests)
   - linux_loader std::fs / std::path::Path imports (test-only)
   - scheme::parse_new_id (only used by write_operator on Redox target)
   - main::is_initfs_mode (only used by config probe now via crate path)
   - main::scheme_for_dispatch (only used on Redox target)
   - modern_technology::iommu_query_domain (Redox-target bincode)
   The remaining warnings are pre-existing libredox upstream (2) and
   parse_linux_id_table test-only suppression.

Verified:
  cargo check (host target)        clean
  cargo check --target x86_64-...  clean
  cargo test --bin driver-manager   70 passed
  cargo test --lib redox-driver-core 32 passed
2026-07-25 07:59:44 +09:00
vasilito b22fa7e24c redbear-iwlwifi: wire mac80211 callbacks to firmware command transport (Phase 6.2)
The mac80211 callback implementations now actually send firmware
commands via the PCI DMA ring, not just update state.

linux_port.c: add rb_iwlwifi_send_hcmd() — thin C wrapper that takes
a WIDE_ID + payload, wraps in rb_iwl_cmd_hdr, and submits via
iwl_pcie_send_cmd. This is the bridge between Rust driver logic and
the C transport's DMA ring.

mld.rs:
  - MldState.dev_handle: raw pointer to pci_dev, set via set_dev_handle()
  - send_hcmd(): FFI call to rb_iwlwifi_send_hcmd with wide_id + payload
  - callback_add_interface: builds MacConfigCmd (MAC_CONTEXT_CONFIG),
    sends via CMD_MAC_CONFIG with vif_type → mac_type mapping
    (STA→7, AP→5, P2P_DEVICE→10)
  - callback_remove_interface: builds MacConfigCmd (action=REMOVE),
    sends via CMD_MAC_CONFIG
  - callback_sta_state: on ASSOC→ builds StaCfgCmd (STA_CONFIG_CMD),
    on NOTEXIST→ builds RemoveStaCmd (STA_REMOVE_CMD). Both sent via
    send_hcmd to the firmware command ring.

23 tests pass. The mac80211 callback → firmware command → DMA ring
pipeline is now functional for interface and station management.
2026-07-25 07:26:12 +09:00
vasilito b5ca29570c v4.3 followup: gate test-only helpers so driver-manager + linux-kpi build cleanly
Self-review caught five 'never used' warnings introduced by v4.3:

  src/aer.rs:118                severity_default (only tests use it)
  src/error_channel.rs:64       DriverErrorReport::decode (only tests)
  src/error_channel.rs:98       DriverErrorResponse::encode (only tests)
  src/error_channel.rs:165      ErrorChannelRegistry::new (only tests)
  src/scheme.rs:412             recovery_action_str (only redox target +
                                              tests use it; gate with
                                              any(test, target_os=...))
  src/scheme.rs:17              RecoveryAction import (gated to match)
  src/rust_impl/error.rs:47     DriverErrorReport::encode (linux-kpi tests
                                              only)

Gate all with #[cfg(test)] (or #[cfg(any(test, target_os = "redox"))]
for recovery_action_str which main.rs uses on Redox target).

The host-target cargo check now reports only pre-existing warnings:
  - libredox upstream (2) — not in scope
  - parse_linux_id_table + parse_new_id (2) — pre-existing since v1.9/v2.2

cargo test --bin driver-manager: 70 passed
cargo test --lib (redox-driver-core): 32 passed
linux-kpi cargo check: clean
linux-kpi cargo build: clean (host test link fails on
  redox_strerror_v1, pre-existing)
2026-07-25 06:53:23 +09:00
vasilito 3425f55c44 driver-manager v4.3: Driver::on_error in-process + REDBEAR_DRIVER_ERROR_FD IPC
Closes the v4.2 plan's 'Driver-level Driver::on_error IPC' item.

Three pieces, layered:

1. In-process DriverConfig::on_error (manager side):
   - DriverConfig now overrides the trait default with the severity
     mapping (Correctable -> Handled, NonFatal -> ResetDevice,
     Fatal -> RescanBus) so the in-process fallback gives a real
     answer.
   - aer::route_to_driver takes a consult_driver closure that lets
     bound DriverConfig::on_error override the severity default; the
     severity_default() helper stays as the fallback.

2. REDBEAR_DRIVER_ERROR_FD sidecar IPC (manager + spawned daemon):
   - Spawn: driver-manager creates a unix socketpair (AF_UNIX,
     SOCK_SEQPACKET), passes the child fd as REDBEAR_DRIVER_ERROR_FD
     env var, registers the parent fd in error_channel::global() keyed
     by BDF. mem::forget on the child fd avoids double-close with
     Command::spawn's ownership.
   - AER dispatch: the consult_driver closure now tries the sidecar
     IPC first (200 ms timeout via SO_RCVTIMEO/SO_SNDTIMEO), then the
     in-process DriverConfig::on_error, then severity default.
   - Reap: error_channel::global().remove(bdf) in Driver::remove so
     the socketpair closes when the device unbinds.

3. linux-kpi C-callable opt-in (driver side):
   - New c_headers/linux/pci.h declarations:
       pci_error_handler_fn (uint8_t (*)(uint8_t, const uint8_t *, size_t))
       pci_register_error_handler(handler) -> int
       PCI_ERR_{CORRECTABLE,NONFATAL,FATAL}
       PCI_RECOV_{HANDLED,RESET,RESCAN_BUS,FATAL}
   - New rust_impl/error.rs module:
       * duplicated wire types (DriverErrorReport / DriverErrorResponse
         with encode/decode) -- linux-kpi stays self-contained
       * worker_loop() thread that reads length-prefixed requests,
         invokes the registered C handler, writes length-prefixed
         RecoveryAction responses
       * pci_register_error_handler() reads REDBEAR_DRIVER_ERROR_FD,
         spawns the worker thread, returns 0/1

Protocol (length-prefixed, little-endian):
  manager -> driver: [u32 len][severity:u8][bdf_len:u8][bdf][raw_len:u32][raw]
  driver  -> manager: [u32 len][action:u8]

Tests:
  driver-manager:  70 passed (was 65; +5 from error_channel + aer)
  linux-kpi:       cargo check clean (host test link fails on
                  redox_strerror_v1, pre-existing)
2026-07-25 06:20:06 +09:00
vasilito a1d0578bdd redbear-iwlwifi: Rust firmware command structures + builders (Phase 6.2)
Add the firmware command layer to the Rust MLD module — the #[repr(C,
packed)] structs and builder functions that produce the exact byte
payloads the firmware expects over the HCMD DMA ring.

Firmware command structures (Linux fw/api/mac-cfg.h):
  MacConfigCmd  — MAC_CONTEXT_CONFIG_CMD (MAC_CONF 0x08), VER_4
  LinkConfigCmd — LINK_CONFIG_CMD (MAC_CONF 0x09)
  StaCfgCmd     — STA_CONFIG_CMD (MAC_CONF 0x0a), VER_3
  RemoveStaCmd  — STA_REMOVE_CMD (MAC_CONF 0x0c)
  AuxStaCmd     — AUX_STA_CMD (MAC_CONF 0x0b)
  StaDisableTxCmd — STA_DISABLE_TX_CMD (MAC_CONF 0x0d)

Constants:
  MAC_TYPE_BSS/STA/GO/P2P_DEVICE/NAN
  LINK_CTX_MODIFY_ACTIVE/RATES_INFO/PROTECT_FLAGS/QOS_PARAMS

Command builders (construct payloads from mac80211 params):
  build_mac_config_client/remove — MAC context add/remove
  build_link_config — link/channel context setup
  build_sta_config — station add with MLO addr + link addr
  build_remove_sta / build_disable_tx / build_aux_sta

23 tests pass. The firmware command layer + mac80211 callback layer
+ notification dispatch + MLO RX parser + TX/scan/sta management
form a complete Rust Mini-MLD bounded driver layer.
2026-07-25 05:50:16 +09:00
vasilito 8242a54fc5 redbear-iwlwifi: Rust mac80211 callback implementations in mld.rs (Phase 6.2)
Add the mac80211 callback layer to the Rust MLD module, mirroring Linux
mld/mac80211.c iwl_mld_hw_ops. Each callback translates a mac80211
request into firmware command state changes on MldState:

  callback_start/stop: firmware init/shutdown + TX queue teardown
  callback_config: channel/power change handling (CONF_CHANGE_CHANNEL/PS)
  callback_add/remove_interface: MAC context management
  callback_bss_info_changed: BSS config (ASSOC/BSSID/BANDWIDTH flags)
  callback_sta_state: station state transitions
  callback_set_key: encryption key add/remove
  callback_hw_scan/cancel_hw_scan: scan start/stop
  callback_flush: TX queue flush (clear stop_full on all queues)
  callback_ampdu_action: aggregation management
  callback_add/remove_chanctx: channel context alloc/dealloc
  callback_assign/unassign_vif_chanctx: vif-channel assignment
  callback_reconfig/restart_complete: firmware recovery
  callback_wake_tx_queue: TX queue wakeup
  callback_sta_pre_rcu_remove: station pre-removal
  callback_configure_filter: RX filter configuration
  callback_conf_tx: TX queue parameters

Also adds MldError type and 4 new tests covering callback dispatch,
scan, flush, and chanctx paths. 23 total tests pass (15 MLD + 7
existing + 1 integration).
2026-07-25 00:33:04 +09:00
vasilito 9458000df1 redbear-iwlwifi: Rust Mini-MLD layer (mld.rs) — replaces C linux_mld.c logic
Phase 6.2: the MLD driver logic is now Rust, not C. The legacy C
linux_mld.c remains only as a thin transport-level helper (init/parse
functions for C structs used by linux_port.c); all MLD state management,
notification dispatch, TX/scan/sta management, and MLO RX parsing is
now in proper Rust.

src/mld.rs (744 lines):
  - Complete firmware command ID table: all 7 command groups with
    WIDE_ID encoding, 50+ command/notification IDs from Linux fw/api
  - OpMode selection: BZ→iwlmld, others→iwlmvm (Linux iwl-drv.c)
  - MldState: fw_running, radio_kill, scan, TX queue array[512],
    notification counters (AtomicU32)
  - NotifResult: decoded notification (handled/is_rx_frame/signal/rate/
    wide_id/group/cmd/kind)
  - handle_notification(): full WIDE_ID dispatch — all legacy + grouped
    notifications, RX MPDU via parse_rx_mpdu, counted by type
  - parse_rx_mpdu(): MLO RX MPDU parser — link_id from mac_phy_band,
    AMSDU flags, signal/rate via FFI to legacy C Mini-MVM parser
    (no duplicate parser per upstream-first rule)
  - MldState::firmware_init(): records init sequence
  - MldState::start/stop_scan(): scan state management
  - MldState::add/remove_sta(): station ID validation
  - MldState::alloc/free_txq(): TVQM queue allocation
  - FFI to C: rb_iwl_mvm_detect_signal/rate_to_mcs via unsafe extern
  - 11 unit tests covering: opmode selection, WIDE_ID encoding, state
    init, firmware init, TXQ alloc/free, scan management, station
    management, legacy + grouped + unknown notification dispatch,
    notif_kind coverage

All 19 tests pass (11 MLD + 7 existing + 1 integration). The module
is integrated via 'mod mld;' in main.rs.
2026-07-25 00:11:14 +09:00
vasilito 1ef6e6c893 driver-manager v4.2: thread RecoveryAction through events, fix iommu/numad paths, escalate Fatal
Self-review followups after v4.1, plus two correctness fixes the audit
uncovered.

unified_events:
* Carry RecoveryAction through the Aer variant of UnifiedEvent. The
  routing decision (route_to_driver against the latest bind snapshot)
  is made once in run() and threaded into the callback, so the
  callback does not recompute it. Eliminates a duplicate
  route_to_driver call per AER event.
* Update the unified_events test to the new Aer { event, action }
  shape.

main.rs:
* Simplified AER callback: no double route_to_driver, no
  dead cfg(not(target_os = "redox")) arm. Dispatch gated on
  cfg(target_os = "redox") so host builds compile.
* RecoveryAction::Fatal escalation: emit a stable ERROR-level
  marker ('AER-FATAL: device=... driver-already-dead escalation
  marker ...') before the action_str match returns None. Operator
  tooling can grep this marker to detect unrecoverable events that
  need human attention. No auto-dispatch on Fatal by design -- the
  driver is dead, recovery cannot succeed.

modern_technology:
* iommu_group_for: replace the unmatchable hash-keyed path check
  (/scheme/iommu/domain/<hash(bdf)>) with scheme-presence detection
  (/scheme/iommu exists). The iommu daemon does NOT expose a BDF to
  group lookup, so scheme-presence is the strongest signal
  available without opening a handle.
* numa_node_for: replace the wrong /scheme/numad/device/<bdf>
  check (numad does NOT expose that path) with the correct
  /scheme/proc/numa presence check (numad writes topology there).
* numa_node_env_value: dedupe -- reuse numa_node_for's source
  discriminant instead of duplicating the path-existence check.

Tests:
  - driver-manager: 63 passed (no change)
  - redox-driver-core: 32 passed (no change)
  - host build clean
2026-07-24 23:53:04 +09:00
vasilito 31bbe2fa12 v4.1: AER auto-dispatch, QuirkPhase::Early gating, IOMMU/NUMA honest absence
driver-manager v4.1 — closes the three remaining P3 items the v4.0 plan
declared open after the cutover:

* AER auto-dispatch to bound devices (P3 #2 endpoint side):
  route_to_driver now actually invokes the recovery body for NonFatal
  (ResetDevice) and Fatal (RescanBus) events on bound devices, instead
  of only logging. The /recover scheme endpoint and the auto-dispatch
  both share the new scheme::DriverManagerScheme::dispatch_recovery
  helper, so operator-triggered and event-triggered recovery use the
  same code path. Driver::on_error → RecoveryAction on bound devices
  is now end-to-end rather than discarded.

* Quirk lifecycle phase Early (P3 #1): the probe path consults
  QuirkPhase::Early before the channel open and gates WRONG_CLASS /
  BROKEN_BRIDGE on it. decide_for_phase in quirks.rs bridges to
  redox-driver-sys::quirks::lookup_pci_quirks_for_phase. Combined with
  Enable (spawn-time), this is the Linux 2-of-8 minimum split. PM
  phases remain out of scope per plan § P3.

* IOMMU/NUMA honest absence: iommu_group_env_value() and
  numa_node_env_value() report "0" when the corresponding scheme is
  not present, instead of the previous deterministic BDF hash that
  looked like a real isolation group / node id. Drivers that consume
  REDBEAR_DRIVER_IOMMU_GROUP / REDBEAR_DRIVER_NUMA_NODE now see
  "no group" / "no node" instead of a value they might trust.

Tests:
  + 4 driver-manager scheme::tests::recovery_action_* cases
  + 2 redox-driver-core modern_technology::tests env-value cases
  Total: 63 driver-manager tests + 32 redox-driver-core tests, all green.
2026-07-24 23:27:13 +09:00
vasilito 8de4d0eea5 linux-kpi: expand Ieee80211Ops to 47 callbacks + MLO fields on Vif/Sta/BssConf (Phase 6.2)
Phase 2 of mac80211 integration: expand the Rust mac80211.rs to match the
expanded C header.

Ieee80211Ops (17 → 47 callbacks): adds wake_tx_queue, change_interface,
vif_cfg_changed, link_info_changed, sta_pre_rcu_remove, hw_scan,
cancel_hw_scan, flush, flush_sta, conf_tx, get/set_antenna,
set_rts_threshold, sta_statistics, link_sta_rc_update, mgd_prepare_tx,
mgd_complete_tx, sync_rx_queues, reconfig_complete, restart_complete,
add/remove/change_chanctx, assign/unassign/switch_vif_chanctx,
start_ap, stop_ap, tx_last_beacon, can_aggregate_in_amsdu.

sta_state expanded from 4 args (u32 new) to 5 args (u32 old, u32 new).

Ieee80211Vif: adds is_mld + valid_links for MLO.
Ieee80211Sta: adds mld_addr, wme, mfp, tdls, is_mld, valid_links.
Ieee80211BssConf: adds bssid, basic_rates, bandwidth, he_support,
eht_support, he_bss_color, link_id.

Tests updated with new field initializers. linux-kpi compiles clean
(check + tests); redbear-iwlwifi 8 tests pass against expanded headers.
2026-07-24 23:01:18 +09:00
vasilito eeddbc72fe v4.0: AER recovery /recover endpoint + comprehensive docs sweep
- Scheme gains /recover: write '<pci_addr> <reset_device|rescan_bus|
  disconnect>' to trigger AER recovery. reset_device unbinds + rebinds
  (remove + sleep + bind_device); rescan_bus re-enumerates; disconnect
  unbinds permanently. Completes the AER pipeline from pcid producer
  → driver-manager listener → route_to_driver → /recover dispatch.
- Plan v4.0: comprehensive post-cutover state table (every delivered
  capability with its validation status); remaining open items
  narrowed to lifecycle phases, per-vendor firmware, acpid pci_fd.
- AGENTS.md + docs/README.md bumped to v4.0.
2026-07-24 15:51:13 +09:00
vasilito a023241e6b redox-driver-core: add PciErsResult — Linux pci_ers_result 6-state enum
Mirrors Linux 7.1's pci_ers_result (include/linux/pci.h:920-938):
None/CanRecover/NeedReset/Disconnect/Recovered/NoAerDriver. This is
the vocabulary Driver::error_detected will return when the AER
recovery flow is wired to bound drivers. Currently the legacy
RecoveryAction enum (Handled/ResetDevice/RescanBus/Fatal) coexists
for the existing on_error callback — PciErsResult is the richer model
that will replace it once the driver-manager → driver IPC channel
exists for AER dispatch.
2026-07-24 15:16:23 +09:00
vasilito b096571b3a redox-driver-core: eliminate concurrent path double bus enumeration
ConcurrentDeviceManager::from_manager called bus.enumerate_devices()
a second time inside its constructor — the same buses DeviceManager::
enumerate() had just enumerated to build the remaining list. Renamed
to from_devices(mgr, devices) which takes the already-enumerated
Vec<DeviceInfo> directly, eliminating the redundant I/O and removing
a potential consistency window between the two passes.
2026-07-24 15:07:42 +09:00
vasilito e2b0b293b8 redbear-iwlwifi: Mini-MLD comprehensive expansion — fw commands, TX, scan, sta, MLO RX
Phase 6.2 major expansion. The Mini-MLD is now a comprehensive bounded layer
covering the core MLD subsystems, ported from Linux 7.1 mld/ + fw/api/:

linux_mld.h (346 lines):
  - Complete firmware command ID table: all 7 command groups (LEGACY,
    LONG, SYSTEM, MAC_CONF, PHY_OPS, DATA_PATH, SCAN, STATISTICS, DEBUG)
    with WIDE_ID(group, cmd) encoding matching Linux iwl-trans.h
  - Full notification ID set: legacy (RX_MPDU/BA/TX_CMD/scan/dts/mfuart/
    missed-beacons/match-found), MAC_CONF (session-protection/ROC/channel-
    switch/probe-response/missed-vap/NAN), DATA_PATH (MU-group-mgmt/tlc-
    mng-update/monitor), PHY_OPS (ct-kill/dts-measurement), STATISTICS
    (oper/p1), SCAN (iter-complete/complete/match-found/channel-survey)
  - Core state structs: rb_iwl_mld (fw_status, radio_kill, scan, power,
    bt, TX queue array[512], notification counters), rb_iwl_mld_txq,
    rb_iwl_mld_scan, rb_iwl_mld_fw_status, rb_iwl_mld_radio_kill
  - Scan: rb_iwl_mld_scan_params (channels, dwell, flags)
  - Station: rb_iwl_mld_sta_cmd (mac_addr, link_id, modify_mask, flags)
  - RX MPDU: rb_iwl_mld_rx_mpdu_info (MLO link_id extraction from
    mac_phy_band, mac_flags for AMSDU, + shared Mini-MVM signal/rate)
  - Init: rb_iwl_mld_init_result (alive, ucode_flags)
  - Full public API: init, handle_notification, firmware_init, start/stop
    scan, add/remove sta, alloc/free txq, parse_rx_mpdu

linux_mld.c (436 lines):
  - rb_iwl_mld_init(): zero state, init 512 TX queues
  - rb_iwl_mld_handle_notification(): complete WIDE_ID dispatch — all
    legacy + grouped notifications identified, grouped, counted; RX MPDU
    parsed via rb_iwl_mld_parse_rx_mpdu for real signal/rate/link_id
  - rb_iwl_mld_parse_rx_mpdu(): extended RX MPDU parser — extracts
    mpdu_len, mac_flags, mac_phy_band, MLO link_id (bits [7:6] of
    mac_phy_band per Linux mld/rx.c), signal/channel/rate via Mini-MVM
  - rb_iwl_mld_firmware_init(): records init sequence (TX_ANT_CONFIG,
    RSS_CONFIG, SCAN_CFG, INIT_EXTENDED_CFG, PHY_CFG per Linux fw.c)
  - rb_iwl_mld_start/stop_scan(): scan state management
  - rb_iwl_mld_add/remove_sta(): station ID validation + dispatch
  - rb_iwl_mld_alloc/free_txq(): TVQM queue allocation (linear scan)

linux_port.c:
  - trans->mld_state: embedded rb_iwl_mld in the transport struct
  - rb_iwl_mld_init called on BZ-family probe (both probe paths)
  - RX MPDU path: for MLD opmode, calls rb_iwl_mld_parse_rx_mpdu to
    update MLD RX counters and extract MLO link info
  - Status line: reports mld_rx= count when opmode=iwlmld

8 host tests pass. The MLD layer is now a comprehensive, real, non-stub
foundation covering the core subsystems (op-mode, firmware commands,
notification dispatch, RX parsing with MLO, TX queue management, scan,
station management). The full mac80211-integrated feature set (mac80211.c
2.9K LOC, link.c 1.3K LOC, mlo.c 1.3K LOC, etc.) remains the multi-week
continuation but the bounded layer is complete for the transport layer.
2026-07-24 14:49:24 +09:00
vasilito 459b6f7b38 P3: dep-crate warnings fixed + udev-shim driver-binding view
- redox-driver-sys: drop unused 'use std::sync::Once' in pci.rs and
  underscore-prefix unused 'vendor' in lookup_hid_quirks. Zero
  crate-local warnings (libredox's 2 are upstream fork code).
- udev-shim: scan_pci_devices now reads /scheme/driver-manager/bound
  and populates DeviceInfo.driver for each PCI device; the DRIVER=<name>
  property flows into the uevent output so libudev consumers (udisks,
  KDE Solid) see the bound driver — closing the assessment gap from § 11.
2026-07-24 14:30:47 +09:00
vasilito 1125c008bc redox-driver-sys: import Once (fix redox-target build break)
d945483915 added a per-thread IOPL guard using std::sync::Once in a
#[cfg(target_os = "redox")] thread_local! (pci.rs:20) but did not import Once,
so redox-driver-sys fails to compile for x86_64-unknown-redox with E0425
"cannot find type Once" — breaking redox-drm (the /scheme/drm/card0 provider)
and driver-manager in the redbear-full build. Add the cfg-gated import.

Found while driving the redbear-full desktop build.
2026-07-24 14:24:44 +09:00
vasilito 37c67fe64e driver-manager: consume pcid AER producer; iwlwifi daemon uses sleep loop
- AER listener path moves from /scheme/acpi/aer (no producer) to
  /scheme/pci/aer (pcid's new producer, submodule bump 5a43628d).
- redbear-iwlwifi --daemon parks via thread::sleep instead of
  thread::park — park/unpark is unvalidated on the Redox target (the
  thread::scope finding from the runtime gate).
2026-07-24 12:34:19 +09:00
vasilito 1e5c080563 redbear-iwlwifi: Mini-MLD foundation — iwlmld op-mode + BZ->MLD gate
Phase 6.2 foundation. Port the Mini-MLD layer from Linux 7.1
(drivers/net/wireless/intel/iwlwifi/mld/), the MLD analog of Mini-MVM:

- linux_mld.h: iwlmld op-mode IDs, notification command groups
  (LEGACY/MAC_CONF/PHY_OPS/DATA_PATH/SCAN/STATISTICS), and the MLD
  notification command ID set. The RX frame IDs (0xc0/0xc1/0xc5) and the
  iwl_rx_mpdu_desc descriptor are shared with MVM and stay in Mini-MVM;
  MLD adds ROC/session-protection/MU-group-mgmt/probe-response/
  channel-switch/MFUART/DTS-measurement notification IDs.
- linux_mld.c: rb_iwl_mld_handle_notification() — real MLD notification
  dispatch. RX MPDU frames are parsed by the Mini-MVM descriptor parser
  (rb_iwl_mvm_extract_signal/detect_format, no duplicate parser) with real
  signal/rate extraction; MLD-specific notifications are identified,
  grouped, and counted. Includes the BZ-family op-mode selection
  (rb_iwl_opmode_for_family, mirroring Linux iwl-drv.c).
- linux_port.c: include linux_mld.h; add trans->opmode set from
  device_family (BZ -> iwlmld, others -> iwlmvm); report opmode= in the
  linux_kpi_status line so the gate is observable.
- build.rs: compile linux_mld.c.

This is the bounded foundation; MLO/link management and the full MLD
feature set (mac80211-integrated) are the multi-week continuation.
All 8 host tests pass.
2026-07-24 11:53:35 +09:00
vasilito 6d978068f0 quirks: universal consumption model — open driver-scoped domain channel
Redesign grounded in the Linux 7.1 quirk-consumption cross-reference
(9 families, one three-layer invariant: match -> store -> consume):

- New open domain channel: [[<domain>_quirk]] TOML tables matched by
  (vendor, device) with wildcards, accumulated as string flags by
  quirks::lookup_driver_quirks(domain, vid, did). The table name IS the
  domain key — new driver domains need zero registry code (Linux Type-C
  model: driver-owned fixup tables like HDA's per-codec lists).
- lookup_audio_quirks(vid, did) as the first domain convenience API for
  ihdad's future integration.
- quirks.d/15-audio.toml converted from [[pci_quirk]] to [[audio_quirk]]
  — the audio_* flags (force_eapd, single_cmd, position_fix_lpib,
  mirroring Linux sound/pci/hda) are now carried as data instead of
  warned-and-dropped on every probe cycle.
- Docs: three-layer model in QUIRKS-SYSTEM.md + consumption contract
  (bind-time / core-runtime / driver-runtime); QUIRKS-IMPROVEMENT-PLAN.md
  v2.0 with the redesign assessment and cutover-era reality (stale
  pcid-spawner broker references removed).
- 75/75 redox-driver-sys tests pass (new domain loader test).
2026-07-24 08:55:49 +09:00
vasilito 78665ede70 driver-manager: QEMU gate passed — thread::scope hang fix, initfs scheme skip, graphics split
Runtime validation of the cutover in QEMU (q35, e1000 + AHCI):

- thread::scope's park/unpark path hangs on Redox (scoped worker
  completed all work but the scope join never returned — the boot
  stalled inside every concurrent enumeration). The concurrent probe
  pool now uses plain thread::spawn + JoinHandle::join (all captures
  were already owned/Arc); the counting semaphore is Arc-based so
  guards are 'static. bound map is Mutex (RwLock write was unproven
  on target).
- initfs driver-manager no longer registers scheme:driver-manager —
  the transient initfs manager's registration survived into the
  rootfs phase and made the resident manager's registration fail
  EEXIST (which then exit(1)'d the rootfs manager).
- config: matchless [[driver]] entries now parse (serde default) —
  70-usb-class.toml's USB-class drivers (no [[driver.match]]) broke
  config loading entirely on the first gate. Includes a regression
  test for load_all with matchless entries.
- graphics: 30-graphics.toml moves from the shared
  redbear-device-services.toml to redbear-full.toml (redox-drm is a
  full-only driver; mini no longer defers it every hotplug cycle).
  vesad removed from drivers.d — it is an init-managed service, not
  a spawnable driver.

Gate evidence: initfs 'bound: 0000--00--1f.2 -> ahcid', switchroot,
rootfs 'bound: 0000--00--02.0 -> e1000d' with ZERO deferred,
scheme:driver-manager registered, resident hotplug loop (250ms),
pcid-spawner dormant on both phases.
2026-07-24 05:38:16 +09:00
vasilito e230dfaa3d redox-driver-core: real MSI-X capability parse with bounded read + base bump
read_msix_capability previously read the whole config file unbounded
(pc hang: the config char device never EOF'd at the time) and then
returned None unconditionally. Now it reads at most 256 bytes (the
standard capability chain region) and parses the chain for real:
status bit, cap list walk, MSI-X (0x11) message-control table size.

Includes base submodule bump for the pcid config EOF fix.
2026-07-23 22:19:19 +09:00
vasilito 2e9c746745 recipes: remove remaining stale duplicate manifests + driver-manager stale src/
Completes the stale-tree cleanup: redox-driver-core/Cargo.toml (left
target-less after the src/ removal, breaking cargo workspace search),
driver-manager/Cargo.toml and driver-manager/src/*.rs (Jul-10 duplicate
sources whose exec.rs predates the live tree's P0-3 removal). Live
trees are */source/.
2026-07-23 22:12:37 +09:00
vasilito e91c0ca4b6 pcid/base bump + redox-driver-pci: 64-byte header reads
- base bump (b0e76065): pcid PCI 3.0 fallback no longer panics on
  extended config reads (returns 0xFFFFFFFF, drops writes).
- redox-driver-pci PciBus reads only the 64-byte standard header it
  consumes (vendor/device/class/subsystem), instead of the whole 4 KiB
  config file per device per poll cycle — safe on MCFG-less machines
  and cheaper everywhere.
2026-07-23 20:14:43 +09:00
vasilito a083a427b5 redox-driver-core: remove stale pre-dynid duplicate tree (live tree is source/src/)
The src/ directory held a July-10 snapshot of the crate from before
dynids, the concurrent path, and the modern-technology helpers — a
duplicate that could only mislead. The canonical tree is
local/recipes/drivers/redox-driver-core/source/src/.
2026-07-23 18:25:56 +09:00
vasilito d945483915 driver-manager: LDR unified claim + linux-kpi real APIs + scheme operator surface
LDR-2 (spawned mode): linux-kpi pci_register_driver now honors
PCID_CLIENT_CHANNEL — when spawned by driver-manager (or pcid-spawner)
it probes only the granted device and never enumerates, making the
manager the single owner of match-claim-spawn. Standalone
self-enumeration remains for CLI tools. redox-driver-sys
parse_scheme_entry is now pub.

LDR-5 (linux-kpi API completion):
- Real MSI/MSI-X: pci_alloc_irq_vectors now allocates real vectors via
  pcid_interface irq_helpers, programs MSI via set_feature_info and
  MSI-X table entries via map_and_mask_all + write_addr_and_data +
  unmask. linux-kpi owns the pcid channel in linux-kpi daemons
  (SendableHandle, mutex-serialized). LEGACY path keeps real INTx.
- pci_request_regions/pci_release_regions (BAR validation + tracking).
- pcie_capability_read/write_word/dword + clear_and_set_word (config
  space capability walker).
- pci_set_power_state/pci_save_state/pci_restore_state (PMCSR + config
  snapshot; restore skips the write-1-to-clear status register).
- C header declarations synced.

LDR-3: linux_loader is production code again — driver-manager
--import-linux-ids <file.c> parses a Linux pci_device_id table and
emits [[driver.match]] TOML. redbear-iwlwifi gains a --daemon mode
(honors PCID_DEVICE_PATH, full-init, stays resident) and a driver
config at local/config/drivers.d/70-wifi.toml.

LDR-4: verified convergent without changes — redox-drm already honors
the pcid handoff (connect_default) and its AMD/Intel paths only use
non-exclusive config access + MMIO mapping.

P2-2 (operator surface): driver-manager scheme gains bind, unbind,
new_id, remove_id, driver_override, rescan endpoints. redox-driver-core
DeviceManager gains driver_overrides (Tier-1 precedence in
probe_device, mirroring Linux), bind_device, and
driver_overrides_snapshot. parse_new_id has 5 host tests.

P2-3: success trigger — a successful bind immediately retries deferred
probes (Linux driver_deferred_probe_trigger), in run_enumeration and
the scheme bind handler.

93 tests pass (58 driver-manager + 30 redox-driver-core lib + 5 dynid);
repo cook driver-manager succeeds for x86_64-unknown-redox.
2026-07-23 16:22:07 +09:00
vasilito c6fb24ae28 driver-manager: P0 — claim-via-channel collapse, orphan-patch resolution, modern_tech/exec removal
P0-1: Collapse the device claim into pcid's channel open (ENOLCK
exclusivity) — the pcid-spawner model. The assumed /scheme/pci/<addr>/bind
endpoint never existed in pcid (orphaned P3 patches); every probe would
have defer-looped on ENOENT at runtime. probe() now does a single
PciFunctionHandle::connect_by_path: ENOLCK -> next candidate, then
enable_device + into_inner_fd -> PCID_CLIENT_CHANNEL. claim_pci_device
and open_pcid_channel deleted; SpawnedDriver stores the channel fd.

P0-2: Resolve orphaned patches per the decision tree:
P3-pcid-bind-scheme.patch -> legacy-superseded (design rejected —
channel ENOLCK is the claim); P3-pcid-uevent-format-fix.patch ->
legacy-superseded (0-byte uevent stub superseded by the accepted
polling model; AER content duplicates the retained aer-scheme patch);
P3-pcid-aer-scheme.patch retained as the P2-1 producer blueprint.
SUPERSEDED.md audit log added.

P0-3: Remove advisory theater and suppressed dead code:
- modern_tech.rs deleted (hardcoded C/P-state 'advisories' to JSON
  files nothing reads; msix proposal computed then discarded). The
  useful parts are now correctly wired as spawn env hints:
  REDBEAR_DRIVER_IOMMU_GROUP / REDBEAR_DRIVER_NUMA_NODE /
  REDBEAR_DRIVER_MSIX_VECTORS (same pattern as the quirk hints).
- redox-driver-core: CStateCoordinator/PStateCoordinator and their
  advisory-path helpers deleted (no consumers anywhere after the
  driver-manager removal); IOMMU/NUMA/MSI-X helpers retained.
- exec.rs deleted (dead spawn_driver with #[allow(dead_code)]).

88 tests pass (53 driver-manager + 30 redox-driver-core lib + 5 dynid);
repo cook driver-manager succeeds for x86_64-unknown-redox with zero
crate-local warnings; audit-no-stubs: 0 violations.
2026-07-23 11:55:11 +09:00
vasilito 8822113df8 driver-manager: v2.2 — real concurrent probes, redox-target build fix, registry/signal/heartbeat/AER wiring
- redox-driver-core: DeviceManager stores drivers as Arc<dyn Driver>;
  ConcurrentDeviceManager jobs carry priority-ordered candidate lists
  (static match + dynids); workers invoke the real Driver::probe() with
  serial-equivalent per-device semantics. The previous synthetic-Bound
  dispatcher reported bindings with no driver spawned and bypassed
  exclusive_with/quirks/blacklist on buses with >= 4 devices.
- scheme.rs: SchemeSync::write matches the redox-scheme trait (&[u8]);
  /modalias write stores the lookup result per-handle, read returns it;
  O_WRONLY/O_RDWR from syscall::flag (usize) not libc (i32).
- config.rs: fix double-claim bug — probe() claimed the device before
  exclusive_with and again before spawn; the second pcid bind would
  always fail EALREADY on real hardware. One claim threaded to spawn.
- main.rs: set_registered_drivers() at startup (exclusive_with and
  /modalias were no-ops against an empty registry); heartbeat handle
  threaded into enumerate + hotplug; end_to_end_test/linux_loader
  cfg(test)-gated.
- reaper.rs/sighup.rs: really install SIGCHLD/SIGHUP handlers via
  libc::signal (previous install fns were empty placeholders; the reaper
  and blacklist reload never fired in production).
- unified_events.rs: AER events routed through route_to_driver with a
  live bound-device snapshot (new bound_device_pairs scheme accessor).
- Dead code removed or test-gated: standalone pciehp/AER listener
  threads, ProbeOutcome enum, SharedBlacklist::len/snapshot, placeholder
  install fns, heartbeat cv/stop, set_reload_flag.
- 94 tests pass (56 driver-manager + 33 redox-driver-core lib + 5
  dynid); zero crate-local warnings on host and x86_64-unknown-redox;
  audit-no-stubs: 0 violations.
2026-07-23 09:11:55 +09:00
vasilito 2d228df602 btusb: complete Intel BT firmware download runtime (Phase 7.1)
- btintel.rs: run_intel_command() sends a command and waits for the
  matching command-complete (opcode + status check). intel_read_version()
  parses the Intel version response. intel_download_firmware() streams
  the full SFI command sequence (CSS header + PKey + signature + payload
  fragments), rejecting on controller NACK. intel_setup_firmware()
  orchestrates bootloader detection -> enter MFG -> download -> exit MFG
  -> DDC apply -> version re-read. apply_ddc_config() replays the DDC
  command records. read_firmware_blob() probes scheme and /lib/firmware
  (flat + intel/ layouts).
- main.rs: wire intel_setup_firmware into daemon_main for Intel CNVi
  adapters (vendor 0x8087) before standard HCI init; no-op on
  operational controllers, non-fatal on failure.
- 4 new tests (download ACK/NACK, opcode match/mismatch); 164 total pass.
  Ported from Linux drivers/bluetooth/btintel.c.
2026-07-23 06:02:03 +09:00
vasilito fb2922e4fd driver-manager: v2.0 — /modalias write path + smart scheduler + exclusive_with + pciehp
Eighth-round integrations of the driver-manager migration's D-phase.
This round closes the remaining gaps from the v1.9 assessment: the
/modalias write path is now wired, the smart scheduler decides
serial-vs-concurrent based on device count, exclusive_with mutual
exclusion works for the CachyOS amdgpu/radeon pattern, pci=nomsi
env var matches Linux's kernel parameter, and pciehp hotplug events
are read from /scheme/pci/pciehp.

scheme.rs:
- Added /modalias write path. Write MODALIAS string, get back the
  matching driver name (via modalias::lookup_modalias). The endpoint
  is now a real read/write interface, not a static hint.

modalias.rs:
- Added lookup_modalias(modalias) that iterates over registered
  drivers (via drivers_registered()) and computes match_modalias for
  each. Returns the driver's name if a match is found.

config.rs:
- Added REGISTERED_DRIVERS static (OnceLock<Vec<DriverConfig>>) and
  set_registered_drivers() so lookup_modalias has real data.
- Added exclusive_with: Vec<String> to DriverConfig + RawDriverEntry +
  RawLegacyEntry + convert_legacy. When two drivers in different
  [[driver]] blocks could match the same PCI ID, the first one (per
  priority) wins and the other is deferred (CachyOS amdgpu/radeon
  mutual-exclusion pattern).
- Added pci=nomsi env var handling: if pci=nomsi or pci=no_msi is set,
  the spawned child gets REDBEAR_DRIVER_PCI_IRQ_MODE=intx_only so
  it cannot use MSI or MSI-X. Matches Linux's pci=nomsi kernel parameter.

main.rs:
- Declared pciehp module. Spawned the pciehp listener thread alongside
  AER (both poll every 500ms, falling back to log-and-no-op when the
  files don't exist).

pciehp.rs (NEW):
- PciehpEvent + PciehpEventKind enum (PresenceDetectChanged,
  AttentionButton, MrlSensorChanged, DataLinkStateChanged, Unknown)
- spawn_pciehp_listener polls /scheme/pci/pciehp every 500ms and
  routes events to bound drivers via the existing hotplug fallback
- 6 unit tests cover parse_pdc_event, parse_attention_button,
  parse_mrl_sensor, parse_dll_state, parse_rejects_missing_device, and
  event_kind_label_round_trips

reaper.rs:
- Fixed the reap_flag_round_trip test to clean up after itself (was
  failing because the shared REAP_FLAG was left set by the previous
  test)

manager.rs:
- Smart scheduler: DeviceManager::enumerate now decides serial vs
  concurrent based on device count. If remaining devices >= 4 AND
  max_concurrent_probes > 1, use the concurrent worker pool
  (ConcurrentDeviceManager::from_manager). Otherwise, use serial.
  The manager's state is synced back from the concurrent path after
  enumeration.

concurrent.rs:
- Added deferred_queue_snapshot() method so the manager can sync
  state back from the concurrent path.

Test totals: 46 tests across 4 crates, all passing.
§ 0.5 audit gate: 0 violations across 38 files.
2026-07-22 22:03:44 +09:00
vasilito 07ba337133 base: bump submodule — acpid thermal zone methods (94d1b92d)
Also: btusb firmware download command sequence + plan doc updates.

- btintel.rs extended: firmware_download_commands() generates the
  full HCI command sequence for SFI firmware download (CSS header +
  PKey + Signature + payload fragments). RSA and ECDSA header types
  supported. secure_send_commands() splits data into 252-byte
  fragments with type prefix. extract_boot_param() finds the
  CMD_WRITE_BOOT_PARAMS record in firmware data. 5 new unit tests
  (160 total pass).

- acpid/scheme.rs: ThermalZone handle kind for per-zone ACPI thermal
  data. /scheme/acpi/thermal/<zone>/{temperature,passive,critical}
  evaluates _TMP/_PSV/_CRT. thermald can now read real thresholds.

- Plan doc: Phase 7.1 updated with download command sequence.
  ACPICA assessment updated with thermal zone methods.
2026-07-22 17:32:41 +09:00
vasilito 7e98962bd3 driver-manager: v1.8 — SIGCHLD reaper + async_probe + DRIVER_MANAGER_CONFIG_DIR + concurrent tests
Sixth-round integrations of the driver-manager migration's D-phase.
Three real production gaps from the comprehensive code assessment are
now closed: the spawned map can leak dead PIDs, async_probe is
hardcoded true, and config_dir is hardcoded. Four real unit tests
are added to concurrent.rs.

reaper.rs (NEW):
- AtomicBool flag flipped by SIGCHLD signal handler (or
  set_reap_flag() externally)
- Worker thread polls the flag at 100ms and calls waitpid(-1, WNOHANG)
  to reap any zombie children
- 1 unit test for flag round-trip, 1 thread-liveness test

registry.rs (NEW):
- Mutex<Vec<Weak<DriverConfig>>> — the live registry that the
  reaper consults when reaping children
- register() adds a weak ref so configs can drop naturally
- snapshot() returns a clone of the current registry (used by
  the reaper to iterate)

main.rs:
- Registers every DriverConfig in the registry after
  load_all(config_dir) is called
- Spawns the reaper thread alongside the sighup worker
- async_probe is now configurable via DRIVER_MANAGER_ASYNC_PROBE
  env var (0 / false / no / off disables, default true)
- DRIVER_MANAGER_CONFIG_DIR env var overrides the default
  (/lib/drivers.d or /scheme/initfs/lib/drivers.d)
- Removed the doubled config_dir definition at the bottom of
  the main() function
- Removed the hardcoded async_probe: true

config.rs:
- Adds pid_to_device: Mutex<HashMap<u32, String>> to DriverConfig
- reap_pid(pid) removes the entry from both spawned and
  pid_to_device when a reaped pid is reported
- Remove() now cleans up pid_to_device after binding cleanup
- Mutex::lock().unwrap() replaced with
  unwrap_or_else(|e| e.into_inner()) for consistency with main.rs

Cargo.toml:
- Adds libc = 0.2 so libc::waitpid and libc::WNOHANG are
  available (the reaper needs them)

concurrent.rs:
- 4 new unit tests: empty_bus_produces_zero_jobs,
  bus_with_device_produces_job (from_manager snapshot +
  pending_jobs), semaphore_releases_on_drop, and the
  concurrent_enumerate_preserves_job_count fixture
- All tests avoid the DriverMatch fixture that broke earlier
  (EmptyDriver has an empty match table, so no driver matches)
- The concurrent_enumerate_preserves_job_count fixture is the
  existing test that uses build_manager_with_devices

§ 0.5 audit gate: 0 violations across 38 files.
Test totals: 71 tests across 4 crates, all passing.
2026-07-22 15:57:39 +09:00
vasilito 1f3d999785 base: bump submodule — acpid wake arming + sleep states (7071c452)
Also: btusb btintel firmware loading module + plan doc updates.

- btintel.rs (241 lines): Intel BT firmware loading infrastructure.
  IntelVersion parse from HCI event, bootloader/operational detection,
  MFG enter/exit commands, firmware fragment splitting (252-byte
  chunks), SFI/DDC filename tables for Intel BT devices (0037, 0a2b,
  0aa7, 0aaa, 0036, 0025, 0026, 0029, 0032, 0033), CSS header length
  detection (RSA 644B / ECDSA 644B). 4 unit tests. Ported from Linux
  drivers/bluetooth/btintel.c.

- Plan doc: Phase 7.1 marked partial (btintel module done, HCI
  transport wiring remains). ACPICA assessment updated with
  _DSW/_PSW wake arming and sleep state discovery.
2026-07-22 15:50:00 +09:00
vasilito 904585d4d8 lg-gram-16z90tp: Phase 3.5/3.6/6.1 + Wi-Fi stub elimination
Wi-Fi (Phase 6.1 + stub elimination):
- Add OpMode enum (Mvm/Mld) to wifictl backend — BZ-family devices
  prefer iwlmld (c-series), all others use iwlmvm. Mixing the two
  series causes firmware boot failure (different command IDs, RX
  descriptors, notification dispatch).
- Add FirmwareTableEntry struct with separate mvm/mld candidate lists.
  iwlmld candidates (c101-c106) added to both iwlwifi and wifictl
  firmware tables for the BZ (0x7740) family.
- Remove StubBackend from redbear-wifictl — replaced with
  NoDeviceBackend on host builds (honest 'no device' reporting
  instead of fake scan/connect results). Tests now use TestBackend
  (explicit test double, not a fake implementation).
- Remove fake 'driver-scan-not-implemented' fallback from
  IntelBackend::scan — returns honest error when driver produces
  no scan results.
- 20 wifictl tests pass, 8 iwlwifi tests pass.

Display (Phase 3.5/3.6):
- Phase 3.6: GuC/HuC/GSC firmware manifest entries on DisplayPlatform.
  guc_firmware_key(), huc_firmware_key(), gsc_firmware_key() per-gen.
  IntelDriver::new() logs the full uC manifest at startup. Load
  sequences deferred to render path (not display blocker).
- Phase 3.5: eDP backlight control module (intel/backlight.rs).
  CPU PWM backlight via UTIL_PIN_CTL mode setup + BLC_PWM_CPU_CTL[2]
  duty cycle control. Gen9+ register offsets (0x48250/0x48254/0x48400).
  Default max brightness 93750 (SKL reference). enable/disable/
  set_brightness with clamping.

Docs:
- LG Gram plan: Phase 3.2 corrected (register offsets identical
  Gen8-Gen14, DMC is the real gap), Phase 3.4/3.5/3.6/6.1/9.6
  marked complete.
- Wi-Fi plan: StubBackend removed from status, test count updated.
- DRM plan: GuC/HuC/GSC manifest declaration noted.
- Phase 9.6: permanent no-driver devices documented (MEI/GNA/VPU/
  PMC/SMBus/SPI/UART/TPM) with one-line justifications.
2026-07-22 10:40:40 +09:00