diff --git a/local/recipes/drivers/redox-driver-core/source/src/modern_technology.rs b/local/recipes/drivers/redox-driver-core/source/src/modern_technology.rs index c76b09b04e..9a9f5abe74 100644 --- a/local/recipes/drivers/redox-driver-core/source/src/modern_technology.rs +++ b/local/recipes/drivers/redox-driver-core/source/src/modern_technology.rs @@ -16,6 +16,7 @@ extern crate alloc; use std::fs; +use std::io::Read; use std::path::Path; /// IOMMU group for a PCI device. Reads `/scheme/iommu/domain/N` files @@ -119,17 +120,32 @@ pub fn propose_msix_vectors(bdf: &str, min: u16, max: u16) -> MsiXProposal { fn read_msix_capability(bdf: &str) -> Option { let path = format!("/scheme/pci/{}/config", bdf); - let data = fs::read(&path).ok()?; - // The MSI-X capability is at offset 0x50 within the config space. - // A real implementation would parse the capability chain. We - // conservatively report None unless the file is large enough to - // contain the capability pointer. - if data.len() < 0x60 { + let file = fs::File::open(&path).ok()?; + let mut data = Vec::new(); + // The standard capability chain lives in the first 256 bytes of + // config space; reading must be bounded because the config file is + // a character device (read_to_end streams until EOF otherwise). + file.take(256).read_to_end(&mut data).ok()?; + if data.len() < 0x40 { return None; } - // Look for the MSI-X capability ID (0x11) in the chained list. - // Without parsing, return None — the caller uses the default. - let _ = bdf; + // Status register (0x06) bit 4: capability list present. + if data[0x06] & 0x10 == 0 { + return None; + } + let mut ptr = (data[0x34] & 0xFC) as usize; + for _ in 0..48 { + if ptr == 0 || ptr + 3 >= data.len() { + return None; + } + if data[ptr] == 0x11 { + // MSI-X: Message Control at cap+2, table size in bits 0..10 + // (encoded as N-1). + let ctrl = u16::from_le_bytes([data[ptr + 2], data[ptr + 3]]); + return Some((ctrl & 0x07FF) + 1); + } + ptr = (data[ptr + 1] & 0xFC) as usize; + } None }