fix: add try_map_bar, try_pci_allocate_interrupt_vector, fix try_mem return type

- try_mem now returns Result (matching caller expectations)
- try_map_bar: non-panicking BAR mapping on PciFunctionHandle
- try_pci_allocate_interrupt_vector: non-panicking IRQ allocation
- virtio-core: reverted .ok_or() back to .map_err() for Result type
This commit is contained in:
Red Bear OS
2026-07-12 02:48:16 +03:00
parent 4932cb4d62
commit 3fe7b12434
4 changed files with 57 additions and 5 deletions
+5 -4
View File
@@ -53,16 +53,17 @@ impl PciBar {
}
}
pub fn try_mem(&self) -> Option<(usize, usize)> {
pub fn try_mem(&self) -> Result<(usize, usize), &'static str> {
match *self {
PciBar::Memory32 { addr, size } => Some((addr as usize, size as usize)),
PciBar::Memory64 { addr, size } => Some((
PciBar::Memory32 { addr, size } => Ok((addr as usize, size as usize)),
PciBar::Memory64 { addr, size } => Ok((
addr.try_into()
.expect("conversion from 64bit BAR to usize failed"),
size.try_into()
.expect("conversion from 64bit BAR size to usize failed"),
)),
_ => None,
PciBar::Port(_) => Err("expected memory BAR, found port BAR"),
PciBar::None => Err("expected BAR to exist"),
}
}
@@ -332,3 +332,27 @@ pub fn pci_allocate_interrupt_vector(
panic!("{driver}: no interrupts supported at all")
}
}
pub fn try_pci_allocate_interrupt_vector(
pcid_handle: &mut crate::driver_interface::PciFunctionHandle,
driver: &str,
) -> io::Result<InterruptVector> {
let features = pcid_handle.fetch_all_features();
let has_msi = features.iter().any(|feature| feature.is_msi());
let has_msix = features.iter().any(|feature| feature.is_msix());
if has_msix || has_msi {
Ok(pci_allocate_interrupt_vector(pcid_handle, driver))
} else if let Some(irq) = pcid_handle.config().func.legacy_interrupt_line {
Ok(InterruptVector {
irq_handle: irq.try_irq_handle(driver)?,
vector: 0,
kind: InterruptVectorKind::Legacy,
})
} else {
Err(io::Error::new(
io::ErrorKind::NotFound,
format!("{driver}: no interrupts supported at all"),
))
}
}
+27
View File
@@ -508,6 +508,33 @@ impl PciFunctionHandle {
})
}
}
pub unsafe fn try_map_bar(&mut self, bir: u8) -> Result<&MappedBar, String> {
let mapped_bar = &mut self.mapped_bars[bir as usize];
if mapped_bar.is_none() {
let (bar, bar_size) = self.config.func.bars[bir as usize]
.try_mem()
.map_err(|e| e.to_string())?;
let ptr = unsafe {
common::physmap(
bar,
bar_size,
common::Prot::RW,
common::MemoryType::Uncacheable,
)
}
.map_err(|e| format!("physmap failed: {e}"))?;
let ptr = NonNull::new(ptr.cast::<u8>())
.ok_or_else(|| "physmap returned null".to_string())?;
mapped_bar.insert(MappedBar {
ptr,
bar_size,
});
}
Ok(mapped_bar.as_ref().expect("BAR was just mapped"))
}
}
pub fn pci_daemon<F: FnOnce(Daemon, PciFunctionHandle) -> !>(f: F) -> ! {
+1 -1
View File
@@ -57,7 +57,7 @@ pub fn probe_device(pcid_handle: &mut PciFunctionHandle) -> Result<Device, Error
let (addr, _) = pci_config.func.bars[capability.bar as usize]
.try_mem()
.ok_or(Error::Probe("BAR is not memory-mapped"))?;
.map_err(|_| Error::Probe("BAR is not memory-mapped"))?;
let address = unsafe {
let addr = addr + capability.offset as usize;