diff --git a/framework/aster-frame/src/bus/pci/cfg_space.rs b/framework/aster-frame/src/bus/pci/cfg_space.rs index 7e5051936..c6bf735d6 100644 --- a/framework/aster-frame/src/bus/pci/cfg_space.rs +++ b/framework/aster-frame/src/bus/pci/cfg_space.rs @@ -1,11 +1,16 @@ // SPDX-License-Identifier: MPL-2.0 use alloc::sync::Arc; +use core::mem::size_of; use bitflags::bitflags; use super::PciDeviceLocation; -use crate::{io_mem::IoMem, Error, Result}; +use crate::{ + arch::device::io_port::{PortRead, PortWrite}, + io_mem::IoMem, + Error, Result, +}; #[repr(u16)] pub enum PciDeviceCommonCfgOffset { @@ -189,6 +194,35 @@ impl IoBar { self.size } + pub fn read(&self, offset: u32) -> Result { + // Check alignment + if (self.base + offset) % size_of::() as u32 != 0 { + return Err(Error::InvalidArgs); + } + // Check overflow + if self.size < size_of::() as u32 || offset > self.size - size_of::() as u32 { + return Err(Error::InvalidArgs); + } + // Safety: The range of ports accessed is within the scope managed by the IoBar and + // an out-of-bounds check is performed. + unsafe { Ok(T::read_from_port((self.base + offset) as u16)) } + } + + pub fn write(&self, offset: u32, value: T) -> Result<()> { + // Check alignment + if (self.base + offset) % size_of::() as u32 != 0 { + return Err(Error::InvalidArgs); + } + // Check overflow + if size_of::() as u32 > self.size || offset > self.size - size_of::() as u32 { + return Err(Error::InvalidArgs); + } + // Safety: The range of ports accessed is within the scope managed by the IoBar and + // an out-of-bounds check is performed. + unsafe { T::write_to_port((self.base + offset) as u16, value) } + Ok(()) + } + fn new(location: &PciDeviceLocation, index: u8) -> Result { let offset = index as u16 * 4 + PciDeviceCommonCfgOffset::Bar0 as u16; let raw = location.read32(offset);