Commit Graph

3347 Commits

Author SHA1 Message Date
Red Bear OS e30f24997c init: ConditionPathExists service gate (systemd-style, with ! negation)
init's Service parser used deny_unknown_fields, so the C0
driver-manager service files (which use ConditionPathExists) were
rejected wholesale — driver-manager stayed dormant by parser accident
instead of by design.

- service.rs: new optional ConditionPathExists field + condition_met()
  gate. A leading '!' negates: the service starts only when the path
  does NOT exist.
- scheduler.rs: skip services whose condition is not met (status_skip,
  same pattern as skip_cmd).
- 00_driver-manager.service: fix inverted polarity — the intent is
  'run unless /etc/driver-manager.d/disabled exists', i.e.
  ConditionPathExists = "!/etc/driver-manager.d/disabled".
- Drop two pre-existing unused imports (Write in service.rs,
  status_fail in main.rs).
2026-07-23 16:55:42 +09:00
Red Bear OS c836fffb66 ihdad: graceful failure on DSP/cAVS platforms (Phase 8.1)
On cAVS/SOF platforms (e.g. LG Gram 8086:7728), STATESTS reads 0
because the codec sits behind the audio DSP; the legacy HDA codec-wake
mechanism cannot reach it. enumerate() previously hardcoded codec 0 and
would hang reading a non-existent codec via CORB/RIRB. Now, if no
codecs respond after reset_controller(), log the DSP-platform diagnosis
and fail honestly with ENODEV instead of hanging. A SOF/cAVS driver
(Phase 8.2) is required for these platforms.
2026-07-23 06:34:35 +09:00
Red Bear OS b5f84b44df acpid/acpi-rs: _REG opregion connect + LPIT parse fix + thermal active + PM timer + HW-reduced + GPE dispatch
acpi-rs (vendored fork):
- _REG opregion connect (ACPICA evrgnini.c): run \_SB._REG(space, 1)
  per installed handler after \_INI — firmware gates EC access behind
  this. Device-level _REG for each device holding an OpRegion of an
  installed space. Fills the last big TODO in initialize_namespace.
- RegionSpace: add From<RegionSpace> for u8 (region-space ID for _REG).

acpid:
- LPIT parser BUG FIX: GAS (Generic Address Structure) is 12 bytes
  (4-byte header + 8-byte address); the parser previously read
  entry_trigger/residency/latency/counter_frequency 4 bytes early and
  required length>=48 instead of 56. Fixed offsets, added
  entry_trigger_space_id, and mwait_hint()/best_mwait_hint() for the
  FFH MWAIT hint. Tests rewritten with correct 56-byte layout.
- Thermal active cooling: /scheme/acpi/thermal/<zone>/active evaluates
  _AC0.._AC9 and returns defined trip points (tenths of K).
- ACPI PM timer: pm_timer_read() from FADT pm_timer_block;
  /scheme/acpi/pmtimer endpoint (3.579545 MHz).
- HW-reduced ACPI: Fadt::is_hardware_reduced() (FADT bit 20); skip
  PM1/GPE setup on such platforms.
- General GPE dispatch: enabled_active_gpes() + \_GPE._Lxx/_Exx method
  evaluation (evgpe.c acpi_ev_gpe_detect).
2026-07-22 22:08:23 +09:00
Red Bear OS 0485ae662a acpid: general GPE _Lxx/_Exx dispatch + ACPI PM timer (ACPICA port)
- GpeBlocks::enabled_active_gpes(): scans all GPE block status+enable
  register pairs, returns every GPE with both bits set (evgpe detect
  semantics — a GPE only fires the SCI when enabled AND active).

- handle_sci general GPE dispatch (acpi_ev_gpe_detect): every
  enabled+active GPE that is not the EC GPE gets its \_GPE._L{gpe:02X}
  (level, tried first) or \_GPE._E{gpe:02X} (edge) control method
  evaluated; status cleared after. This is the ACPICA core GPE model
  that drives lid, device wake, and all non-EC GPE events — previously
  only the EC GPE and PM1 fixed events were dispatched.

- pm_timer_read(): reads the FADT pm_timer_block free-running counter
  (3.579545 MHz, PM_TIMER_FREQUENCY_HZ). Exposed at
  /scheme/acpi/pmtimer for precise sleep-path timing.
2026-07-22 19:09:42 +09:00
Red Bear OS 94d1b92d91 acpid: thermal zone method evaluation (_TMP/_PSV/_CRT)
Add ThermalZone handle kind to the scheme: per-zone ACPI thermal
data at /scheme/acpi/thermal/<zone>/{temperature,passive,critical}.
Each path evaluates the corresponding AML method (_TMP, _PSV, _CRT)
and returns the raw integer value. ThermalFileKind enum dispatches
to the correct method. thermald can now read real thermal zone
temperatures and thresholds instead of relying on hardcoded values.
Ported from Linux drivers/acpi/thermal.c thermal_zone_device_ops.
2026-07-22 17:30:05 +09:00
Red Bear OS 7071c4529e acpid: _DSW/_PSW wake arming + sleep state discovery + GPE wake re-arm
- WakeRegistry::arm_wake_devices(): evaluates _DSW(1,0,Sx) per wake
  device (falls back to _PSW(1)), enables wake GPEs in the GPE block.
  Wired into enter_s2idle() — wake devices are now armed before
  the kernel MWAIT loop. Ported from Linux acpi_enable_wakeup_devices.

- WakeRegistry::disarm_wake_devices(): evaluates _DSW(0,0,0) per
  wake device (falls back to _PSW(0)), clears wake GPE status bits.
  Wired into exit_s2idle() — wake devices are disarmed on resume.
  Ported from Linux acpi_disable_wakeup_devices.

- SleepStates::discover(): enumerates _S0 through _S5 to find
  available sleep states. s3_supported() and s2idle_only() helpers
  identify the platform's sleep capability profile.

- AcpiContext.wake_registry: new field storing the populated
  WakeRegistry for use by enter_s2idle/exit_s2idle.
2026-07-22 15:41:51 +09:00
Red Bear OS 9c571e2942 pcid: guard config access against out-of-range offsets (fixes boot panic)
An extended-capability walk (pci_types capabilities()) that follows a
chain running to/past the end of config space read at offset 4096,
which tripped the dword-offset assert in bus_addr_offset_in_dwords
("pcie offset larger than 4095") and aborted pcid with an Invalid
opcode fault / UNHANDLED EXCEPTION on boot — after switchroot to /usr,
so it blocked reaching login.

PCIe config space is exactly 4096 bytes (offsets 0..=4095). Fix at two
levels:

- ConfigRegionAccess::read/write (cfg_access/mod.rs): guard the single
  access choke point — an out-of-range read returns the PCI "no
  response" pattern (0xFFFFFFFF, which also terminates a capability
  walk cleanly) and an out-of-range write is a no-op. This catches any
  caller (capability walk, scheme reads, driver access).

- scheme.rs config read/write loop: clamp the loop bound with
  saturating_add(...).min(4096) so a consumer requesting offset+len
  past the boundary reads only the valid part instead of looping to
  offset 4096.

Verified: boot no longer panics in pcid (progresses past the previous
crash point through switchroot and the /usr driver set).
2026-07-22 14:20:57 +09:00
Red Bear OS a12fb9fc7c acpid: LPIT parser + _PRW wake enumeration + FADT S0-idle detection (ACPICA port)
Port useful ACPICA components into the existing Rust ACPI stack:

- LPIT (Low Power Idle Table) parser in new acpid/wake.rs.
  Parses native C-state LPI entries (entry trigger, residency,
  latency, residency counter, counter frequency). Computes total
  residency and deepest LPI state. 4 unit tests cover parsing,
  empty input, short input, and deepest-entry selection.
  Reference: Linux include/acpi/actbl2.h struct acpi_lpit_native.

- _PRW wake device enumeration in acpid/wake.rs.
  WakeRegistry::enumerate() evaluates _PRW on known wake-capable
  device paths (LID, PWRB, SLPB, XHCI, HDAS, CNVW, I2C0/1, THC0/1).
  Extracts GPE number and sleep state from the _PRW package.
  Reference: Linux drivers/acpi/scan.c acpi_bus_get_wakeup_device_flags.

- FADT S0-idle detection: Fadt::supports_s0_idle() checks bit 21
  (ACPI_FADT_LOW_POWER_S0) to detect platforms that support s2idle.
  Reference: Linux include/acpi/actbl.h.

- acpid/main.rs: LPIT parse + wake enumeration + S0-idle detection
  wired into init after AcpiContext::init() and before power events.

ACPICA assessment: do NOT port ACPICA as a C library. Port its
useful data structures and algorithms into the existing Rust stack
(acpi-rs vendored fork + acpid daemon). The AML interpreter already
has comprehensive opcode coverage (only DefLoad/DefLoadTable remain
unimplemented, both optional). The GPE/EC/fixed-event infrastructure
is already in acpid. LPIT + _PRW + S0-idle detection fill the
remaining gaps for Phase 9.1 s2idle completion.
2026-07-22 12:22:36 +09:00
Red Bear OS cf2abc64b0 ided: implement PCI native mode for primary and secondary IDE channels
The PCI IDE Programming Interface byte (PCI spec §3.1.1) encodes
per-channel mode: bit 0 = primary native, bit 2 = secondary native.
The previous code panicked on native-mode channels and also had a
bug checking bit 0 for both channels (secondary should check bit 2).

Native mode now reads I/O and control bases from PCI BARs (BAR0/1 for
primary, BAR2/3 for secondary) instead of hardcoded legacy ports.
Interrupt line comes from legacy_interrupt_line when available.
2026-07-22 05:25:59 +09:00
Red Bear OS 6571df7802 acpi-rs: eliminate all AML stubs (resource descriptors, ConnectionField, Match, Index ref)
resource.rs — implement all ~20 stubbed resource descriptor parsers:
  - QWord/DWord/Word AddressSpace, IRQ, DMA, I/O, FixedI/O, FixedDMA
  - StartDependentFunctions, VendorDefined (small+large)
  - GPIOConnection, GenericSerialBus (I2C/SPI/UART subtypes)
  - PinFunction, PinConfiguration, PinGroup, PinGroupFunction, PinGroupConfiguration
  - ExtendedAddressSpace, GenericRegister
  - Both large/small dispatch tables now call real parsers
  - ACPI 6.5 §6.4 coverage complete, cross-referenced with ACPICA amlresrc.h

mod.rs — eliminate 3 remaining stubs:
  - ConnectionField in parse_field_list: namestring + inline buffer forms
  - Opcode::Match: full opcode handler with ResolveBehaviour::ByteData intercept,
    10-arg OpInFlight, do_match executor with 7 match operators
  - ReferenceKind::Index in do_copy_object: merged with Named/Local path

virtio-core: replace arch stubs (aarch64, riscv64) with real Error::Probe returns

usbscsid/uas: full UAS transport implementation (1006 lines) replacing
stub-heavy version — IUs, pipe detection, stream/non-stream modes,
task tag management, cross-referenced with Linux 7.1 uas.c

initnsmgr: Rc<RefCell<>> -> Arc<Mutex<>> for namespace concurrency safety

xhcid/quirks: fix comment (3 hci_version-dependent entries, not 2)

cargo check -p acpi: clean (3 pre-existing warnings only)
cargo test -p acpi --lib: 5/5 pass
2026-07-22 05:00:29 +09:00
Red Bear OS f315a9be3b acpid + i2c-hidd: Phase 5 (GPE/EC/lid/buttons/fan) + Phase 4.4 (HID descriptor parser)
Phase 5 — Laptop ACPI events (LG Gram 16Z90TP compatibility plan):
- Vendor acpi-rs crate (rev 90cbe88) into base fork with a real
  Opcode::Notify executor; upstream panicked on every Notify opcode,
  which is the backbone of ACPI event flow on real laptop firmware.
  Handler::handle_notify hook added; acpid + amlserde pointed at the
  path dep so every consumer sees the same fork.
- gpe.rs: FADT-driven GPE block register map (status half + enable
  half), write-1-to-clear status bits, read-modify-write enable
  preserving every other GPE's firmware state. PM1 fixed-event bits
  (PWRBTN/SLPBTN/RTC) per ACPI 6.4 §4.8.3.1.
- power_events.rs: init builds the GPE map, discovers the EC via ECDT
  (ACPI 6.4 §5.2.16) with a _HID=PNP0C09 probe fallback over conven-
  tional paths, enables the EC GPE + PM1 fixed events, discovers lid
  and ACPI 4.0 fan devices. handle_sci dispatches PM1 → EC query loop
  (bounded at 32) → AML notification drain, following Linux 7.1
  evgpe.c / ec.c / button.c.
- notifications.rs: shared AmlNotifications queue (parking_lot::Mutex)
  populated by the vendored acpi-rs handle_notify hook, drained by the
  SCI handler and redbear-upower.
- ec.rs: sci_evt_set() and query() exposed on Ec for the SCI handler.
- scheme.rs: new handle kinds Lid, LidState, ButtonDir, Button,
  Notifications, Fan, FanState, FanSpeed with proper dir/file
  separation. Fan _FST on read, _FSL on write (percent clamped 0-100).
- main.rs: subscribes /scheme/irq/{sci_irq} (default 9) on the event
  queue, dispatches SCI events through handle_sci. PowerButton incre-
  ments edge counter and triggers the shutdown path; SleepButton incre-
  ments counter and calls enter_s2idle.
- acpi.rs: AcpiContext gained gpe, ec_device, lid_device, lid_state,
  power_button_events, sleep_button_events, fan_devices fields (all
  RwLock-guarded). evaluate_acpi_method and enter_s2idle changed from
  &mut self to &self (AML mutation goes through RwLock inner state).
- aml_physmem.rs: handle_notify impl pushes onto the shared queue.

Phase 4.4 — HID report descriptor parser (i2c-hidd):
- report_desc.rs: HID 1.11 §6.2.2 descriptor parser + decoder. Global-
  state stack (Push/Pop), usage-min/max expansion, sign-extended
  fields, contact reconstruction (id, tip, x, y). 3 unit tests.
- input.rs: forward_layout_report dispatches descriptor-driven reports
  through forward_decoded: first touching contact → absolute
  MouseEvent; two simultaneous contacts → vertical ScrollEvent (two-
  finger scroll); buttons → ButtonEvent; keyboard-page reports fall
  back to the existing boot-protocol path.
- hid.rs: stream_input_reports parses the descriptor once and uses
  forward_layout_report when layouts are non-empty, otherwise keeps the
  boot-protocol summary path.

Reference: Linux 7.1 drivers/acpi/{evgpeblk.c,evgpe.c,ec.c,button.c}
and drivers/hid/hid-core.c.

All affected crates compile for x86_64-unknown-redox; i2c-hidd 3/3
unit tests pass on host; acpid host-side tests still can't link
(pre-existing libredox limitation — must run via redoxer).
2026-07-21 21:36:07 +09:00
Red Bear OS ddcd08709f pcid: read REDBEAR_DRIVER_PCI_IRQ_MODE / DISABLE_ACCEL env vars
The pcid_interface crate now reads the two env vars emitted by
driver-manager's SpawnDecision committee:
- REDBEAR_DRIVER_PCI_IRQ_MODE: lets the spawned child know
  whether to fall back to MSI / INTx instead of MSI-X
- REDBEAR_DRIVER_DISABLE_ACCEL: lets the spawned child suppress
  hardware acceleration (matches PciQuirkFlags::DISABLE_ACCEL)

Both values are stored on PciFunctionHandle and exposed via
accessors (irq_mode_hint / disable_accel_hint) so the driver
daemons can read them at startup. 6 new unit tests cover the
env-var parsing.

Refs: local/docs/DRIVER-MANAGER-MIGRATION-PLAN.md § 5.2 D2.7.
2026-07-21 12:07:49 +09:00
Red Bear OS 6db0f48170 i2c: review-fix round — hardware-correct DesignWare engine + LPSS bring-up
Post-implementation review returned FAIL with two verified-CRITICAL
findings; all legitimate findings fixed in this round:

CRITICAL — engine wrote IC_CON/IC_TAR while enabled (DesignWare
databook forbids; Linux i2c_dw_xfer_init disables first). Engine
restructured: wait-idle -> disable -> program -> enable with
IC_ENABLE_STATUS polling on every transfer.

CRITICAL — Intel LPSS PCI bring-up skipped parent-device init.
intel-lpss-i2cd now claims functions via pcid_interface
(connect_by_path + enable_device), validates the real BAR size, and
performs intel_lpss_init_dev's sequence (reset-deassert + 64-bit
remap address at BAR0+0x200), ported from Linux drivers/mfd/intel-lpss.c.

MAJOR fixes:
- wait_for checks TX_ABRT before success predicates — a NACKed write
  no longer reports success via post-abort idle state
- SCL timing corrected to Linux's formulas: HCNT uses sda_fall_ns,
  round-to-nearest division (FS 100/200, SS 552/652 for bxt 133 MHz)
- stop=false rejected honestly instead of hanging on the idle wait
- recover(): ABORT-bit cycle + disable + state flush after any failed
  transfer
- validate_request: segment/byte/address/10-bit limits before any MMIO
- i2cd + endpoint: exact-first adapter resolution; last-component
  matching accepted only when unambiguous
- i2cd registration validates provider_scheme as a single safe
  scheme-name component
- I2cTransferResponse gains typed status (I2cTransferStatus,
  serde-defaulted, wire-compatible)
- endpoint::serve takes a Result-returning on_ready callback;
  setrens failure is fatal (fail-closed namespace reduction)
- unexpected i2cd registration responses are fatal for that controller

Tests: dw-i2c 5 (timing vectors, validation, resolution),
intel-lpss-i2cd 1 (PCI ID table coverage), full workspace cargo check
clean, base cooks for x86_64-unknown-redox.

Refs: local/docs/LG-GRAM-16Z90TP-COMPATIBILITY-PLAN.md review-fix round
2026-07-21 12:03:00 +09:00
Red Bear OS 8dd8fb3b20 acpid: harden AML handler — bounded stall, mutex owner-check, static cache, panic-free path, observability
Five daemon-local hardening items on top of the AML-mutex fix. acpid is
single-threaded and serves the `acpi` scheme on the same thread that
evaluates AML, so any way it can stall or die stalls or kills every
consumer. These reduce or bound each such way (verified against
local/reference/linux-7.1 ACPICA):

- stall(): refuse >255us and warn >100us instead of an unbounded CPU
  busy-spin on the serving thread (ACPICA exsystem.c:129-147). The spec
  caps Stall at 100us; a long busy-spin here would delay scheme requests.

- AML mutex release(): a release of a not-currently-held mutex, or by a
  non-owning thread, is now logged (ACPICA AE_NOT_ACQUIRED / owner
  mismatch, exmutex.c:287,376) rather than silently decrementing depth.

- Static processor-method cache: _PSS/_PSD/_CST/_CPC are fixed after boot
  but cpufreqd polls them; cache the first evaluation so later reads never
  re-run the AML interpreter under the global lock. Removes acpid's
  dominant recurring head-of-line source. Dynamic methods are not cached.

- Panic-free scheme path: every release_global_lock().expect(...) on the
  AML-evaluation path is now log-and-continue, and a result.ok()?.unwrap()
  that panicked on Ok(None) (absent method) is now `?`. A scheme-daemon
  panic kills the `acpi` scheme and wedges every consumer.

- Observability: log AML evaluations >=50ms and mutex-acquire timeouts —
  the early-warning signal before a stall becomes a wedge.

Context: the residual under-load boot wedge is NOT in acpid (a mutex-only
baseline wedges identically under load); it is head-of-line blocking in
the single-threaded initnsmgr. See
local/docs/INIT-NAMESPACE-MANAGER-SCALABILITY-PLAN.md and
local/docs/INITNSMGR-CONCURRENCY-DESIGN.md.
2026-07-21 08:33:26 +09:00
Red Bear OS 0407d9ccbb init: add dormant driver-manager service files (C0)
Adds the two dormant service files for the driver-manager
post-switchroot + initfs spawner paths. Both files are dormant by
default — they require /etc/driver-manager.d/{disabled,initfs-active}
to be absent before they activate. The cutover (C1-C4) is
operator-ratified; this commit only adds the file presence so
the C0 wiring exists.

Refs: local/docs/DRIVER-MANAGER-MIGRATION-PLAN.md § 5.2 C0.
2026-07-21 06:58:10 +09:00
Red Bear OS 452452e453 i2c: real DesignWare transfer chain — engine, PCI discovery, provider routing
The I2C transfer chain was stubbed end-to-end:

- i2cd's transfer path returned 'not implemented yet' for every
  transfer, and its wire format didn't match the only in-tree consumer
  (i2c-hidd sends a bare I2cTransferRequest, i2cd expected
  I2cControlRequest::Transfer).
- intel-lpss-i2cd / dw-acpi-i2cd / amd-mp2-i2cd registered an adapter
  name and parked forever without initializing the controller or
  executing a transfer.
- intel-lpss-i2cd matched only legacy ACPI HIDs, which do not exist on
  Meteor Lake / Arrow Lake platforms (LPSS I2C binds by PCI ID there,
  per Linux drivers/mfd/intel-lpss-pci.c).

Replace with real implementations:

- New shared crate drivers/i2c/designware (dw-i2c): DesignWare I2C
  master engine ported from Linux 7.1 i2c-designware-master.c and
  i2c-designware-common.c — IC_CON + SCL timing computed from ic_clk
  with Linux's exact hcnt/lcnt formulas (bxt_i2c_info 133 MHz for
  LPSS, 100 MHz for ACPI-designated blocks), SDA hold with RX-hold
  workaround, polling transfer engine with RESTART/STOP sequencing,
  TX_ABRT decode (Nack/arbitration-lost/abort/timeout), 7/10-bit
  addressing, bounded timeouts. Also provides the shared
  /scheme/<name> transfer endpoint with register-then-ready ordering.
- intel-lpss-i2cd: PCI discovery for ARL-H (0x7750/0x7751,
  0x7778-0x777b) and MTL-P (0x7e50/0x7e51, 0x7e78-0x7e7b) with 32/64-bit
  BAR0 decode, ACPI alias resolution via FixedMemory32 == BAR0 across
  /scheme/acpi/resources, legacy ACPI-HID path kept, i2cd registration
  with bounded retry, serves /scheme/i2c-lpss.
- dw-acpi-i2cd: converted from register-and-park to the shared engine,
  serves /scheme/dw-acpi-i2c.
- i2cd: real transfer routing — adapter resolution by name/alias
  (exact, normalized, last-component) and forwarding to the provider
  daemon's /scheme/<provider>/transfer endpoint.
- i2c-interface: I2cAdapterInfo gains provider_scheme + aliases
  (serde-default, wire-compatible).

Tests: dw-i2c 3, intel-lpss-i2cd 3; full workspace cargo check clean;
base cooks for x86_64-unknown-redox.

Refs: local/docs/LG-GRAM-16Z90TP-COMPATIBILITY-PLAN.md Phase 4
2026-07-21 06:02:31 +09:00
Red Bear OS d78fd44a07 acpid: fix AML mutex acquire — recursion, ownership, and timeout units
The AML mutex `acquire` handler had two defects that let a routine
`_ACQ` on ACPI processor P-state objects (`processor/CPUn/pss`, opened
by cpufreqd) deadlock acpid permanently:

1. Timeout units. ACPI `_ACQ` timeouts are milliseconds and 0xFFFF is
   the spec's "wait forever" (ACPICA ACPI_WAIT_FOREVER,
   actypes.h:459). The code multiplied the value by 1000, treating it
   as seconds, so 0xFFFF became ~18 hours.

2. No ownership. ACPI mutexes are recursive: the owning thread may
   re-acquire, each Acquire paired with a Release (ACPICA
   acpi_ex_acquire_mutex_object, exmutex.c:140). The old code tracked
   only a "held" set with no owner, so a nested acquire by the single
   AML thread waited for a release only it could perform — a
   self-deadlock.

Because acpid is single-threaded and the same thread serves the
`acpi` scheme socket, a stuck acquire stops acpid answering scheme
requests. The init namespace manager then blocks in the openat it was
proxying, and — since every restricted-namespace path resolution goes
through that single manager — the whole system's open path wedges
(observed: mini never reaches a usable brush login).

Fix: track (owner ThreadId, recursion depth) per mutex, treat a
nested acquire by the owner as a depth bump, interpret the timeout as
milliseconds, and bound any wait to MAX_MUTEX_WAIT (5s) so a
misbehaving AML method can never freeze the scheme-serving thread.
2026-07-21 04:47:00 +09:00
Red Bear OS 94a99f02ed usbhidd: reset global endpoint counter per candidate configuration
usbhidd already accumulated prior interfaces' endpoint counts (global
enumeration index, matching xhcid's PortState::get_endp_desc), but the
counter was never reset between candidate configurations — a HID device
whose usable config is not the first would get endpoint numbers offset
by the first config's endpoints. xhcid indexes within the selected
configuration only, so reset per config.
2026-07-20 21:09:05 +09:00
Red Bear OS 2a3b0d4e0a xhcid: per-device USB 2.0 hardware LPM (L1) enablement at attach (P7-A)
Implement the Linux 7.1 xhci.c:4650 xhci_set_usb2_hardware_lpm() enable
path, closing the P7-A gap on top of the P2-B substrate:

- usb/bos.rs: BosUsb2ExtDesc bmAttributes accessors (LPM support, BESL
  support/validity, baseline/deep BESL fields) + 3 unit tests
- xhci/mod.rs:
  - change_max_exit_latency(): MEL update via Evaluate Context (slot
    output context copied, SLOT add flag, DWORD1 low 16 bits = MEL) —
    Linux xhci.c:4520
  - calculate_hird_besl(): HCS_PARAMS3 U2 latency + device BESL
    attributes — Linux xhci.c:4594
  - enable_usb2_hw_lpm(): BESL vs HIRD parameter selection, MEL
    Evaluate Context, PORTHLPMC/PORTPMSC programming via the existing
    Port::enable_lpm — Linux xhci.c:4686-4722
  - BESL_ENCODING_US table, XHCI_L1_TIMEOUT_US=512, XHCI_DEFAULT_BESL=4
- xhci/scheme.rs (get_desc): attach-time gate chain — hw_lpm_support &&
  per-port HLC (USB 2.0 protocol only) && device USB_LPM_SUPPORT in BOS
  && non-hub class && root-hub-direct (get_desc only runs for root-port
  devices). LPM enable failure logs a warning and continues — LPM is
  opportunistic; the device works in U0 regardless.

Verified: cargo check -Z build-std --target x86_64-unknown-redox -p
xhcid clean (no new warnings). Unit tests compile-verified; execution
requires redoxer like the crate's existing test suite. Runtime L1
entry validation requires LPM-capable hardware (QEMU's xHCI does not
advertise HLC) — recorded as hardware-validation debt in the USB plan.
2026-07-20 19:21:01 +09:00
Red Bear OS 28afc1fefd drivers: complete shared-IRQ re-arm sweep (audio, net, graphics)
Continuation of 92924224 — the same conditional-ack bug class found in
six more drivers: a foreign interrupt on a shared INTx line skipped the
write-back ack, leaving the kernel-masked IRQ line dead forever.

- sb16d, ac97d: ack before the not-ours continue
- rtl8139d, rtl8168d, ixgbed: ack unconditionally, tick only when ours
  (the stale 'TODO: spurious interrupts' comments removed — the
  spurious-interrupt confusion was this bug)
- ihdgd: ack unconditionally, handle_events/tick only when ours

Verified: cargo check -Z build-std --target x86_64-unknown-redox for
sb16d, ac97d, rtl8139d, rtl8168d, ixgbed, ihdgd — clean, no new
warnings. nvmed audited: not affected (per-queue MSI pattern, no
conditional ack).
2026-07-20 18:48:30 +09:00
Red Bear OS 9292422458 drivers: always re-arm shared IRQ lines after interrupt delivery
Same bug class as the ahcid fix (ad40fffd): the kernel masks the IRQ
line when it delivers an interrupt and only re-arms it on the userspace
write-back (irq scheme write -> acknowledge() -> pic/ioapic_unmask).
When a driver acks only if the interrupt was its own, one foreign
interrupt on a shared INTx line leaves the line masked forever and all
later interrupts for the device are lost.

- e1000d: ack unconditionally; ICR is read-to-clear, so the ownership
  check doubles as the device-level status clear
- ihdad: ack before the not-ours continue
- vboxd: ack unconditionally; device-side ack and event handling stay
  conditional on host_events
- xhcid: ack unconditionally in the IRQ reactor; for INTx the ownership
  check already clears IMAN.IP (RW1C) and device interrupts are masked
  before re-arming, so no storm. MSI/MSI-X vectors are never shared, so
  behavior there is unchanged (every delivery is ours by construction)

Verified: cargo check -Z build-std --target x86_64-unknown-redox for
e1000d, ihdad, vboxd, xhcid — clean, no new warnings.
2026-07-20 18:44:53 +09:00
Red Bear OS 54e89a337a fbcond: perform the display handoff open off the console loop
fbcond blocked indefinitely in open_display_v2() while handing the console
over to the real graphics driver: boot stopped at "fbcond: Performing
handoff" and never reached the "Opened new display" that follows a
successful open.

fbcond is single-threaded and owns the console, so while it waited there it
stopped draining console writers. getty, login and the login shell all
blocked on their writes, which made the failure look like a slow or hung
shell -- the stall point just tracked whichever process next wrote to the
console. If the graphics driver was itself waiting on the console, the two
deadlocked outright and the console never came back.

The wait comes from the scheme-open handshake: inputd signals the handoff as
soon as the driver registers its path, but the driver may not be serving its
scheme yet, and O_NONBLOCK does not bound the open (it governs later reads).

Split the two halves in inputd's ConsumerHandle: display_path_v2() only does
an fpath on our own handle and returns promptly, while open_display_path_v2()
carries the blocking open. fbcond now resolves the path inline and hands the
open to a worker thread, then picks the result up from the event loop via
poll_pending_handoff(). Console output produced meanwhile is buffered in
pending_writes (already the behaviour while the display is unmapped) and
flushed once the new display is mapped.
2026-07-20 18:10:59 +09:00
Red Bear OS ad40fffd80 ahcid: always re-arm the IRQ line, even for foreign interrupts
The kernel masks an IRQ line when it delivers the interrupt to userspace
(trigger() -> pic_mask()/ioapic_mask()) and only re-enables it when the
driver writes the count back (kwrite -> acknowledge() -> pic_unmask()/
ioapic_unmask()). That write-back is therefore mandatory, not optional.

ahcid only performed it inside the `is > 0` branch. IRQ lines are shared
(on q35 the AHCI controller sits on IRQ 10 with other devices), so an
interrupt raised by a different device reaches the handler with the HBA
interrupt status register reading 0. In that case ahcid returned without
writing back, leaving the line masked permanently: every subsequent AHCI
completion was lost and all disk I/O blocked forever.

Move the write-back out of the branch so the line is re-armed whether or
not the interrupt turned out to be ours, and keep scheme.tick() gated on
`is > 0` since there is no completion to service otherwise. Device-level
status is still cleared before unmasking, so this cannot cause a storm.
2026-07-20 14:09:40 +09:00
Red Bear OS fb421083e0 fbcond: retry handoff while display driver is not ready
The handoff is one-shot: inputd signals it the moment the real display
driver registers its path, but the driver's scheme may not serve the v2
open / capability query for a few more milliseconds. Without a retry, a
transient not-ready driver leaves the framebuffer permanently blank —
the login prompt is drawn to the framebuffer VT, so the console appears
dead even though boot continues on the serial mirror (observed as the
2026-07-20 '-vga std' boot freeze at 'Performing handoff').

Retry the reopen for up to 250 x 10ms; the driver becomes ready well
within this bound in practice. On success after retries, log the retry
count at info level. If the driver is still not ready after the bound,
emit a single explicit warning instead of per-attempt warn spam (the
per-attempt message in display.rs is demoted to debug). Serial mirror
remains unaffected in the failure case.
2026-07-20 08:59:26 +09:00
Red Bear OS e4d4dfffec xhcid: promote IRQ reactor startup lines to info level
'Running IRQ reactor with IRQ file and event queue' and 'in polling
mode' were debug! since the file was created, so test-xhci-irq-qemu.sh
(which greps for the interrupt-driven line) could never see them at the
default info log level — the IRQ-driven path had zero runtime evidence.
They are one-time startup lines; promote to info so the interrupt
delivery mode is observable and the proof can detect it.
2026-07-20 00:44:11 +09:00
Red Bear OS 6694b5af9e fbcond/graphics-ipc: treat not-ready graphics driver as transient at handoff
V2GraphicsHandle::from_file() unwrapped/asserted the DumbBuffer
capability, but the display fd is O_NONBLOCK and the graphics driver
often has not finished coming up at handoff time — so from_file failed
with EAGAIN and the assert panicked fbcond. Since fbcond owns the
console and serial mirror, its death froze the whole boot right after
'Performing handoff' with no login prompt.

Return an error from graphics-ipc when the driver does not yet report
DumbBuffer, and have fbcond log-and-return so the handoff is retried
when the driver publishes its surface, instead of panicking.

(Change found as uncommitted work in the fork; committing to preserve
it and unblock the clean-fork build gate.)
2026-07-20 00:28:02 +09:00
Red Bear OS 3c9dda3253 virtio-netd: log MSI-X interrupt delivery at info level
The driver requires MSI-X (virtio-core probe errors out without it) and
binds both virtqueues to MSIX_PRIMARY_VECTOR, but only noted the
transport in a debug log — leaving zero runtime evidence of the MSI-X
path at the default level, which is why test-msix-qemu.sh found no live
MSI-X evidence. Log the delivery method at info where it is set up.
2026-07-20 00:24:54 +09:00
Red Bear OS a8e1ddc913 usb: demote diagnostic ATTACH/HUBFLOW traces to debug!
The diagnostic milestones used to root-cause the intermittent boot
'freeze' (attach_device milestones, usbhubd HUBFLOW decision points,
reactor/enumerator startup) moved from info to debug! so production
logs stay clean. One-line-per-boot startup confirmations (scheme
registered, daemon ready, reactor started, enumerator started, reactor
dispatch mode, enumerator running) remain at info as genuinely useful
low-volume startup evidence.
2026-07-19 23:01:48 +09:00
Red Bear OS 5a709b0f43 xhcid: fix build — InterruptMethod does not implement Debug
The reactor-start trace used {:?} on InterruptMethod, which has no
Debug impl. Dropped the format arg.
2026-07-19 21:48:41 +09:00
Red Bear OS a1df36a0b9 xhcid: info-level startup milestones for reactor-race diagnosis
Traces at scheme registration, daemon.ready, reactor/enumerator start,
reactor dispatch + IRQ subscribe, and enumerator run entry, to pinpoint
where xhcid stops in boots that lose the intermittent IRQ-reactor
startup race. Diagnostic; level to be revisited after root cause.
2026-07-19 21:46:50 +09:00
Red Bear OS 0e948dd2a7 usbhubd: gate port-indicator SetPortFeature on hub capability
SetPortFeature(PORT_INDICATOR) was issued unconditionally for every
connected+enabled port. QEMU's usb-hub does not advertise indicator
support and NAKs the request indefinitely; with no control-transfer
timeout the daemon hung before the post-enable debounce, so devices
behind the hub never attached. Gate on wHubCharacteristics bit 7
(HUB_CHAR_PORTIND, USB 2.0 Table 11-13), matching Linux hub_configure's
has_indicators check.
2026-07-19 19:11:36 +09:00
Red Bear OS ef34223201 usbhubd: trace SetPortReset result + wait_for_reset boundaries (diagnostic)
Log SetPortFeature(PORT_RESET) result, wait_for_reset's first fetch,
and its completion/timeout outcomes at info level to pinpoint where
hub port-reset polling stalls in QEMU.
2026-07-19 18:38:03 +09:00
Red Bear OS 5164417f56 ps2d: don't panic on transient event-queue read errors in the input loop 2026-07-19 18:02:15 +09:00
Red Bear OS bcf8ea25a7 inputd: fix misaligned-load UB on producer event writes
The producer's write buffer arrives byte-aligned from an arbitrary
scheme write; constructing a &[Event] slice directly over it is
undefined behaviour (misaligned loads, hardware faults on strict-
alignment targets). Copy the events into a properly aligned Vec<Event>
via copy_nonoverlapping and drop the trailing partial event.

(Change found as uncommitted work in the fork; committing to preserve
it and unblock the clean-fork build gate.)
2026-07-19 12:27:50 +09:00
Red Bear OS 0683c020a5 ptyd: harden against transient scan/event-queue errors
Replace two panics (initial scan_requests expect, event-queue read
expect) and a socket-event break with error logging + continuation. A
transient error reading the event queue or scanning requests must not
kill ptyd and take the whole pty subsystem down with it.

(Change found as uncommitted work in the fork; committing to preserve
it and unblock the clean-fork build gate.)
2026-07-19 12:25:21 +09:00
Red Bear OS 5f78ad843a usbhubd: info-level HUBFLOW traces at attach decision points (diagnostic)
Post-debounce state, pre-attach state, and attach() result logged at
info level to pinpoint where hub-child enumeration stalls in QEMU.
Diagnostic; level to be revisited.
2026-07-19 12:00:45 +09:00
Red Bear OS 5803f4c6f2 xhcid: info-level attach_device milestone traces (diagnostic)
Temporary info-level ATTACH milestones in attach_device (begin, slot,
addressed, desc8, desc-full, drivers spawned) to trace hub-child
enumeration in QEMU — the kbd behind a hub reaches port-enable but
produces no visible outcome at the default log level. Level to be
revisited after the hub-child attach path is diagnosed.
2026-07-19 11:39:44 +09:00
Red Bear OS b16e6ca399 usbhubd: judge debounce stability on connection state, not change bit
The debounce's inner clear of C_PORT_CONNECTION could hang or be
ignored by the hub, and our control transfers have no timeout — so a
literal port of Linux's clear-inside-the-loop design deadlocked hub
enumeration: the debounce never converged and the reset/attach path was
never reached (observed on QEMU as usbhubd logging the port's first
status with connection_changed=true and then going silent forever).

Judge the 100ms stable window on the connection STATE alone (the same
stability property hub_port_debounce_be_connected protects): a stuck or
hung change bit can no longer deadlock enumeration — it only
re-triggers a poll, and is cleared once, best-effort, after a
successful attach (matching Linux port_event's C_PORT_CONNECTION
clear). New regression test debounce_stuck_change_bit_still_converges
locks the deadlock scenario; 15/15 tests pass.
2026-07-19 10:59:35 +09:00
Red Bear OS 217935ec95 ipcd: fix RefCell double-borrow panic on getsockopt(SO_PEERCRED)
UdsStreamScheme::getsockopt held an outer socket_rc.borrow() across the
whole option match. The SO_PEERCRED branch calls get_connected_peer(id),
which itself does borrow_mut() on the same socket — a RefCell
double-borrow that panicked ipcd and took the UDS scheme down (observed
in QEMU boot logs as ipcd crash at uds/stream.rs plus tokio
UnixStream::pair / 'failed to create UnixStream' failures from clients
calling getsockopt(SO_PEERCRED)).

Borrow only inside the branches that read socket fields (SNDBUF/RCVBUF);
the SO_PEERCRED branch now runs without an outer borrow held.

(Change found as uncommitted work in the fork; committing to unblock the
clean-fork build gate and to preserve the fix.)
2026-07-19 10:17:23 +09:00
Red Bear OS 8cd2f71ddd usbhubd: bound EP1 wait via worker thread + recv_timeout poll fallback
Root cause of hub-child enumeration stalling: after a synchronous
action (power-on, reset) the port's state changes WITHOUT a new
interrupt ever being generated, and the loop's next step was a blocking
EP1 transfer_read with no timeout — the daemon never woke to observe
the state it had just caused, so devices behind a hub sat
enabled-but-never-attached forever.

Move the blocking transfer_read onto a worker thread that forwards each
interrupt bitmap as a u64 mask over an mpsc channel. The main loop
waits with recv_timeout(POLL_FALLBACK_MS): a real bitmap processes only
the changed ports (interrupt fast path), while timeout/disconnect/error
falls back to an all-ports poll (progress guarantee). Matches the Linux
model where hub_irq is the accelerator but port status reads are always
authoritative.
2026-07-19 10:11:38 +09:00
Red Bear OS 9317d4874b usbhubd: fix status-bitmap off-by-one + add initial full port scan
Two latent bugs exposed by test-usb-hub-qemu.sh against a real hub
topology (QEMU usb-hub with usb-kbd behind it):

1. Status-change bitmap was indexed off by one: the loop checked
   bit (port - 1), but USB 2.0 spec 11.12.4 defines bit 0 = hub status
   change and bit N = port N status change (Linux hub_irq uses bit i
   for port i). Every change was processed on the wrong port — a device
   on port N was never enumerated (its bit was read as port N+1).

2. The event loop's first action was a blocking EP1 interrupt read;
   when the hub delivers no immediate status-change interrupt the
   daemon hung before ever scanning a port. Linux hub_activate()
   performs a full port scan before arming the status-change endpoint;
   the first iteration now forces an all-ports mask with the same
   semantics. Also widened the fallback all-ports mask to bits 1..=ports
   (bit 0 = hub, skipped).
2026-07-19 09:46:05 +09:00
Red Bear OS d7f31916bc xhcid: open hub-child port dirs before enumeration (scheme bootstrap)
open_handle_port required a PortState for every port<N> directory open,
but hub child ports have no PortState until the hub daemon triggers
attach_device via port<N>/attach — an endpoint that itself is
state-free (open_handle_attach_device). This made XhciClientHandle::new
fail with ENOENT for unenumerated hub children, deadlocking the attach
flow: usbhubd could never start enumeration for a device behind a
non-root hub (panic at startup, caught by test-usb-hub-qemu.sh).

Open the directory with the static listing when no PortState exists
yet; state-dependent subpaths (descriptors, state, configure) still
gate on the PortState being present.
2026-07-19 09:15:33 +09:00
Red Bear OS 9bbdc2cafa Merge upstream/main (59cf8189) into submodule/base
Sync the base fork with 13 upstream commits (xhci event-processing
dedup + IRQ race fix, randd permission simplification, nvmed TimeSpec
fix, /dev/ptmx, fpath legacy-path cleanup, dynamically-linked init
fix, and more). Brings process_one_event into the tree, satisfying the
verify-fork-functions gate for base.

Conflicts resolved (3 of 8 overlapping files; 5 auto-merged):

- drivers/usb/xhcid/src/xhci/irq_reactor.rs: took upstream's
  process_one_event/EventProcessResult refactor (b2ed85ea) including
  the a01d3ce6 race fix (process events between NoEvent and
  unmasking), and re-applied the Red Bear SPURIOUS_REBOOT quirk on the
  NoEvent warning (downgrade to debug when quirked).

- randd/src/main.rs: took upstream's permission-handling
  simplification (e26db606); re-applied the RB fcntl improvement
  (F_GETFL/F_GETFD/F_SETFL/F_SETFD handling, Linux random_fops xref)
  and the is_cpu_feature_detected early-return cleanup. Dropped
  test_scheme_perms (deleted by upstream's simplification).

- Makefile: kept upstream's new /dev symlink block (dev/null, ptmx,
  random, urandom, zero, tty, stdin/stdout/stderr).

Verified: cargo check clean; 57/57 tests pass (xhcid 35, usbhubd 14,
xhci trb 8); verify-fork-functions.sh --no-fetch base reports all
upstream functions present.
2026-07-19 05:47:27 +09:00
Red Bear OS bd379e0771 usbhubd: full Linux 7.1 hub enumeration state machine (P3-A)
Port the Linux 7.1 hub.c port state machine into usbhubd, replacing the
minimal connect/reset handling:

New module port_ops.rs (pure logic, side effects injected, 14 unit
tests):
- debounce_until_connected: hub_port_debounce_be_connected() port
  (hub.c:4696-4737) — 25ms polls, connection stable for 100ms, 2s
  budget, connection-change bit cleared in-loop.
- wait_for_reset: hub_port_wait_reset() port (hub.c:2953-3047) — 10ms
  polls until RESET clears with CONNECTION set, escalate to 200ms after
  two short waits, 800ms budget; then 50ms TRSTRCY recovery (hub.c:3159)
  and C_PORT_RESET clear. Replaces the previous bare sleep(10ms).
- wait_for_u0: USB 3.0 polling→U0 wait after port power-on — 36ms steps,
  400ms ceiling (tPollingLFPSTimeout = 360ms; Linux hub.c:1226 debounce
  path).
- accumulate_hub_delay_ns: wHubDelay chain rule (hub.c:1507-1519:
  wHubDelay + parent->hub_delay + 40ns, cap 65535ns).

main.rs wiring:
- Port status normalized to PortStatusSnapshot (decouples the state
  machine from the V2/V3 wire formats; V3 link state extracted from
  bits 8:5).
- Debounce on connection-change before attach; C_PORT_ENABLE cleared
  once handled (Linux port_event semantics).
- Reset path uses wait_for_reset instead of sleep(10ms).
- USB 3 power-on path waits for U0 before proceeding.
- wHubDelay: ancestor-chain walk fetching USB 3 ancestor hub
  descriptors, accumulated per Linux; delivered to newly attached
  SuperSpeed children via SET_ISOCH_DELAY (USB 3.0 9.4.11; Linux
  message.c:1142 — hubs and non-SS skipped, children inherit the hub's
  accumulated delay verbatim per hub.c:5128-5129).
- attach/detach failure logs now identify the port.

hub.rs (xhcid usb module):
- HubDescriptorV3 extended with device_removable: u16 — the SS hub
  descriptor is 12 bytes (spec Table 10-15); the old struct under-read
  by 2 bytes. Stale TODO corrected: SS descriptors have no
  PortPwrCtrlMask (that is USB 2.0-only, still unparsed).

Verified: cargo check clean (0 usbhubd warnings), 14/14 usbhubd tests,
xhcid unaffected (43/43 tests).
2026-07-19 00:27:49 +09:00
Red Bear OS 260003331e xhcid: fix restart_endpoint deadlock, doorbell ordering, NoOp priming (P2-C)
Three bugs in the xHCI endpoint-restart path used by all error recovery
(stall hard reset, transaction-error soft retry, resource retry,
split/babble hard reset):

1. Latent deadlock: restart_endpoint held the port_states write guard
   across set_tr_deque_ptr(), which internally re-acquires a read guard
   on the same key (std RwLock read-while-write on one thread).
   Unobserved because error injection is not yet exercised at runtime
   (P8-C). Fixed by scoping phase-1 ring priming so the guard drops
   before the async command.

2. Doorbell ordering violated xHCI spec 4.6.8/4.6.10: after Reset
   Endpoint the TR Dequeue Pointer is undefined, so Set TR Dequeue
   Pointer must complete BEFORE the doorbell transitions the endpoint
   Stopped->Running. The old order (doorbell first) ran the endpoint
   with an undefined dequeue pointer — undefined xHC behavior on real
   hardware. Linux rings the doorbell from the Set TR Dequeue command
   completion path (xhci_handle_cmd_set_deq, ring.c:1416-1554); xhcid
   now issues Set TR Dequeue, awaits completion, then rings.

3. Priming NoOp never executed: ring.register() was captured after
   ring.next() advanced the enqueue index, so the dequeue pointed past
   the NoOp (dead TRB). Now captured before next(), priming the
   hardware dequeue AT the NoOp so the xHC executes it on restart —
   same semantics as Linux xhci_move_dequeue_past_td pointing at the
   first valid TRB.

Verified: cargo check clean (138 warnings, unchanged), 43/43 tests pass.
2026-07-18 23:14:14 +09:00
Red Bear OS 75229a5789 ptyd: remove temporary line-discipline diagnostics 2026-07-18 23:07:59 +09:00
Red Bear OS d20557f726 xhcid: gate xHCI 1.1+ features on HCCPARAMS2 + protocol-caps bits (P2-B)
Gate xHCI 1.1+ features on their capability bits, cross-referenced with
Linux 7.1 xhci driver behavior:

LEC (HCC2_LEC, scheme.rs):
- lec now uses Linux xhci-mem.c:1350 exact condition:
  hci_version > 0x100 && hcc_params2 & HCC2_LEC (HCCPARAMS2 register
  space is reserved on 1.0 controllers).
- Max ESIT Payload Hi zeroed when LEC=0 (spec Table 6-8 RsvdZ).

U3C (HCC2_U3C, mod.rs suspend_port):
- Refuse SuperSpeed U3 entry with ENOSYS when hci_ver >= 0x110 and
  HCC2_U3C=0 (spec 4.15.1). USB2 suspend unaffected. Linux 7.1 defines
  but never gates this bit; xhcid follows the spec.

CIC (HCC2_CIC): CIE gate pre-existing (set_cie from cic()); added the
hci_ver > 0x100 version guard. HCC2 capability log block similarly
guarded.

HW LPM (extended.rs, mod.rs, port.rs):
- New SupportedProtoCap::{l1_capable,hw_lpm_capable,besl_lpm_capable}
  reading protocol-defined bits (Linux xhci-ext-caps.h:62-66 L1C/HLC/BLC).
- Xhci::hw_lpm_support computed per Linux xhci-mem.c:2137:
  hci_ver >= 0x100 && !HW_LPM_DISABLE && any USB2 protocol cap has HLC.
- attach_device(): defensive LPM clear on USB 2.0 protocol ports
  (rev_major() != 3) when hw_lpm_support is false — Linux xhci.c:4725
  disable path; USB3 excluded because PORTPMSC L1DS aliases U2 timeout.
- Port::enable_lpm/disable_lpm register targets fixed: HLE/HIRD/RWE/
  L1DS belong in PORTPMSC (offset 0x04), not PORTHLPMC (0x0C, bit 16
  RsvdZ) — spec Tables 5-21/5-23, Linux xhci-port.h:135-158. Helpers
  rewritten to Linux xhci.c:4686-4737 two-register sequence.
- Per-device L1 enablement (BESL, MEL Evaluate Context) defers to P3.

Bug fix: removed bogus CapabilityRegs::hlc() + HCC_PARAMS1_HLC_BIT —
they read xECP pointer bits 16-31 of HCCPARAMS1 (spec Table 5-13), not
HLC. HLC lives in the Supported Protocol capability port_info DWORD.

Verification: cargo check clean (138 warnings, -2 vs baseline: the new
disable_lpm call site also revived PORT_HLE/PORT_HIRD_MASK), 43/43
tests pass.
2026-07-18 22:33:38 +09:00
Red Bear OS 9fc1947d53 xhcid: converge xHCI quirks to canonical redox-driver-sys path
Replace xhcid's self-contained 294-line xhci/quirks.rs (7-flag bitflags
type + ~30-entry quirk table) with a thin re-export shim that delegates
to redox-driver-sys::quirks, which now carries all 51 Linux 7.1 quirk
flags and the full ~85-entry canonical controller table.

Changes:
- Cargo.toml: add redox-driver-sys path dependency
- xhci/quirks.rs: replace table with pub use XhciControllerQuirkFlags
  as XhciQuirks + delegating lookup_quirks(vendor, device, revision,
  hci_version)
- main.rs: read real HCIVERSION from MMIO offset 0x04 via
  cap.hci_ver.read() instead of hardcoded 0x100 — matches Linux 7.1
  xhci_gen_setup() at xhci.c:5455. Two table entries depend on the
  value: AMD_0x96_HOST (xhci-pci.c:308) and >= 0x120 spec rule
  (xhci-pci.c:511).
- main.rs: resolve quirks BEFORE get_int_method() so BROKEN_MSI skips
  MSI/MSI-X probing entirely (matching Linux xhci_try_enable_msi at
  xhci-pci.c:143-209). Previously the quirk only overrode the method
  label while irq_file still held the MSI handle — a mismatch causing
  silent interrupt-delivery failures on BROKEN_MSI controllers.
- get_int_method (both cfg variants): accept quirks parameter
2026-07-18 21:52:05 +09:00
Red Bear OS ad4bedd46d xhcid: expand xHCI completion-code error recovery to all 36 codes
maybe_recover_transfer_error previously handled only the first-tier
codes (UsbTransaction, Resource, Stall, BabbleDetected, DataBuffer,
Trb, SplitTransaction) and silently returned Ok(false) for every
other completion code via a catch-all arm.

Cross-referenced Linux 7.1 drivers/usb/host/xhci-ring.c
handle_tx_event() (line 2608+) and handle_transferless_tx_event()
(line 2561+) to add explicit recovery for the remaining ~29 codes:

- Stopped/StoppedLengthInvalid/StoppedShortPacket: restart endpoint
  + retry (up to MAX_SOFT_RETRY), then hard-reset
- InvalidStreamType/InvalidStreamId: soft reset + retry, then
  hard-reset
- IncompatibleDevice: disable slot (device must re-enumerate)
- MissedService/NoPingResponse: log informational, surface to caller
- ContextState/Parameter: hard-reset to resync driver/xHC state
- Bandwidth/BandwidthOverrun/SecondaryBandwidth: log, no transfer
  recovery (config must change)
- IsochBuffer: hard-reset endpoint
- MaxExitLatencyTooLarge: log, surface
- EventLost/Undefined: hard-reset (event ring may be corrupted)
- SlotNotEnabled/EndpointNotEnabled/NoSlotsAvailable: log driver
  state mismatch
- CommandRingStopped/CommandAborted: log xHC state confusion
- Reserved/vendor: default arm logs explicitly

Added completion_code_to_errno() mapping transfer completion codes
to POSIX errnos matching Linux 7.1 semantics:
  Stall -> EPIPE
  BabbleDetected -> EOVERFLOW
  UsbTransaction/SplitTransaction/IncompatibleDevice -> EPROTO
  Trb -> EILSEQ
  DataBuffer -> ENOSR
  SlotNotEnabled/EndpointNotEnabled/NoSlotsAvailable -> ENODEV
  default -> EIO

Rewrote handle_transfer_event_trb() to use the new errno mapping
instead of always returning EIO.

Added 14 unit tests covering all errno mappings and transfer
event handling paths. Full suite (41 tests) passes.
2026-07-18 20:55:41 +09:00
Jacob Lorentzon 59cf818933 Merge branch 'fix_dylink_init' into 'main'
Fix support for dynamically linked init

See merge request redox-os/base!309
2026-07-18 11:05:46 +02:00