Move PCI bus in OSTD into PCI component

This commit is contained in:
Yuke Peng 2025-07-25 15:35:39 +08:00 committed by Tate, Hongliang Tian
parent f2d1cbdf57
commit 1a86bd2471
23 changed files with 177 additions and 168 deletions

3
Cargo.lock generated
View File

@ -255,6 +255,8 @@ dependencies = [
name = "aster-pci"
version = "0.1.0"
dependencies = [
"bitflags 1.3.2",
"cfg-if",
"component",
"log",
"ostd",
@ -334,6 +336,7 @@ dependencies = [
"aster-console",
"aster-input",
"aster-network",
"aster-pci",
"aster-rights",
"aster-softirq",
"aster-systree",

View File

@ -10,6 +10,8 @@ ostd = { path = "../../../ostd" }
component = { path = "../../libs/comp-sys/component" }
log = "0.4"
spin = "0.9.4"
cfg-if = "1.0"
bitflags = "1.3"
[lints]
workspace = true

View File

@ -0,0 +1,51 @@
// SPDX-License-Identifier: MPL-2.0
//! PCI device Information
use ostd::bus::pci::PciDeviceLocation;
use super::cfg_space::PciDeviceCommonCfgOffset;
/// PCI device ID
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct PciDeviceId {
/// Vendor ID
pub vendor_id: u16,
/// Device ID
pub device_id: u16,
/// Revision ID
pub revision_id: u8,
/// Programming Interface Byte
pub prog_if: u8,
/// Specifies the specific function the device performs.
pub subclass: u8,
/// Specifies the type of function the device performs.
pub class: u8,
/// Subsystem Vendor ID
pub subsystem_vendor_id: u16,
/// Subsystem ID
pub subsystem_id: u16,
}
impl PciDeviceId {
pub(super) fn new(location: PciDeviceLocation) -> Self {
let vendor_id = location.read16(PciDeviceCommonCfgOffset::VendorId as u16);
let device_id = location.read16(PciDeviceCommonCfgOffset::DeviceId as u16);
let revision_id = location.read8(PciDeviceCommonCfgOffset::RevisionId as u16);
let prog_if = location.read8(PciDeviceCommonCfgOffset::ClassCode as u16);
let subclass = location.read8(PciDeviceCommonCfgOffset::ClassCode as u16 + 1);
let class = location.read8(PciDeviceCommonCfgOffset::ClassCode as u16 + 2);
let subsystem_vendor_id =
location.read16(PciDeviceCommonCfgOffset::SubsystemVendorId as u16);
let subsystem_id = location.read16(PciDeviceCommonCfgOffset::SubsystemId as u16);
Self {
vendor_id,
device_id,
revision_id,
prog_if,
subclass,
class,
subsystem_vendor_id,
subsystem_id,
}
}
}

View File

@ -1,13 +1,96 @@
// SPDX-License-Identifier: MPL-2.0
//! PCI bus in Asterinas
//! The PCI bus of Asterinas.
//!
//! Users can implement the bus under the `PciDriver` to register devices to
//! the PCI bus. When the physical device and the driver match successfully, it
//! will be provided through the driver's `construct` function to construct a
//! structure that implements the `PciDevice` trait. And in the end, the PCI
//! bus will store a reference to the structure and finally call the driver's
//! probe function to remind the driver of a new device access.
//!
//! Use case:
//!
//! ```rust no_run
//! #[derive(Debug)]
//! pub struct PciDeviceA {
//! common_device: PciCommonDevice,
//! }
//!
//! impl PciDevice for PciDeviceA {
//! fn device_id(&self) -> PciDeviceId {
//! self.common_device.device_id().clone()
//! }
//! }
//!
//! #[derive(Debug)]
//! pub struct PciDriverA {
//! devices: Mutex<Vec<Arc<PciDeviceA>>>,
//! }
//!
//! impl PciDriver for PciDriverA {
//! fn probe(
//! &self,
//! device: PciCommonDevice,
//! ) -> Result<Arc<dyn PciDevice>, (PciDriverProbeError, PciCommonDevice)> {
//! if device.device_id().vendor_id != 0x1234 {
//! return Err((PciDriverProbeError::DeviceNotMatch, device));
//! }
//! let device = Arc::new(PciDeviceA {
//! common_device: device,
//! });
//! self.devices.lock().push(device.clone());
//! Ok(device)
//! }
//! }
//!
//! pub fn driver_a_init() {
//! let driver_a = Arc::new(PciDriverA {
//! devices: Mutex::new(Vec::new()),
//! });
//! PCI_BUS.lock().register_driver(driver_a);
//! }
//! ```
#![no_std]
#![deny(unsafe_code)]
pub mod bus;
pub mod capability;
pub mod cfg_space;
pub mod common_device;
mod device_info;
extern crate alloc;
use component::{init_component, ComponentInitError};
pub use device_info::PciDeviceId;
use ostd::{
bus::pci::{has_pci_bus, PciDeviceLocation},
sync::Mutex,
};
use self::{bus::PciBus, common_device::PciCommonDevice};
#[init_component]
fn pci_init() -> Result<(), ComponentInitError> {
init();
Ok(())
}
/// PCI bus instance
pub static PCI_BUS: Mutex<PciBus> = Mutex::new(PciBus::new());
fn init() {
if !has_pci_bus() {
return;
}
let mut lock = PCI_BUS.lock();
for location in PciDeviceLocation::all() {
let Some(device) = PciCommonDevice::new(location) else {
continue;
};
lock.register_common_device(device);
}
}

View File

@ -15,6 +15,7 @@ aster-console = { path = "../console" }
aster-util = { path = "../../libs/aster-util" }
aster-rights = { path = "../../libs/aster-rights" }
aster-bigtcp = { path = "../../libs/aster-bigtcp" }
aster-pci = { path = "../pci" }
aster-softirq = { path = "../softirq"}
aster-systree = { path = "../systree" }
id-alloc = { path = "../../../ostd/libs/id-alloc" }

View File

@ -7,7 +7,6 @@ use aster_rights::{ReadOp, WriteOp};
use aster_util::{field_ptr, safe_ptr::SafePtr};
use log::warn;
use ostd::{
bus::pci::cfg_space::Bar,
io::IoMem,
irq::IrqCallbackFunction,
mm::{DmaCoherent, HasDaddr, PAGE_SIZE},
@ -206,7 +205,7 @@ impl VirtioTransport for VirtioMmioTransport {
Some(self.common_device.io_mem().slice(0x100..0x200))
}
fn device_config_bar(&self) -> Option<(Bar, usize)> {
fn device_config_bar(&self) -> Option<(aster_pci::cfg_space::Bar, usize)> {
None
}

View File

@ -3,10 +3,10 @@
use alloc::{boxed::Box, sync::Arc};
use core::fmt::Debug;
use aster_pci::cfg_space::Bar;
use aster_util::safe_ptr::SafePtr;
use ostd::{
arch::device::io_port::{PortRead, PortWrite},
bus::pci::cfg_space::Bar,
io::IoMem,
irq::IrqCallbackFunction,
mm::{DmaCoherent, PodOnce},

View File

@ -2,12 +2,12 @@
use alloc::sync::Arc;
use log::warn;
use ostd::bus::pci::{
use aster_pci::{
capability::vendor::CapabilityVndrData,
cfg_space::{Bar, MemoryBar},
common_device::BarManager,
};
use log::warn;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[repr(u8)]

View File

@ -3,16 +3,14 @@
use alloc::{boxed::Box, sync::Arc};
use core::fmt::Debug;
use aster_pci::{
bus::PciDevice, capability::CapabilityData, cfg_space::Bar, common_device::PciCommonDevice,
PciDeviceId,
};
use aster_util::{field_ptr, safe_ptr::SafePtr};
use log::{info, warn};
use ostd::{
bus::{
pci::{
bus::PciDevice, capability::CapabilityData, cfg_space::Bar,
common_device::PciCommonDevice, PciDeviceId,
},
BusProbeError,
},
bus::BusProbeError,
io::IoMem,
irq::IrqCallbackFunction,
mm::{DmaCoherent, HasDaddr},

View File

@ -2,17 +2,12 @@
use alloc::{boxed::Box, sync::Arc, vec::Vec};
use ostd::{
bus::{
pci::{
bus::{PciDevice, PciDriver},
capability::CapabilityData,
common_device::PciCommonDevice,
},
BusProbeError,
},
sync::SpinLock,
use aster_pci::{
bus::{PciDevice, PciDriver},
capability::CapabilityData,
common_device::PciCommonDevice,
};
use ostd::{bus::BusProbeError, sync::SpinLock};
use super::device::VirtioPciModernTransport;
use crate::transport::{

View File

@ -3,13 +3,11 @@
use alloc::{boxed::Box, sync::Arc};
use core::fmt::Debug;
use aster_pci::{capability::CapabilityData, cfg_space::Bar, common_device::PciCommonDevice};
use aster_util::safe_ptr::SafePtr;
use log::{info, warn};
use ostd::{
bus::{
pci::{capability::CapabilityData, cfg_space::Bar, common_device::PciCommonDevice},
BusProbeError,
},
bus::BusProbeError,
io::IoMem,
irq::IrqCallbackFunction,
mm::{DmaCoherent, HasDaddr, PAGE_SIZE},

View File

@ -9,7 +9,7 @@ pub(super) mod msix;
use alloc::sync::Arc;
use ostd::bus::pci::PCI_BUS;
use aster_pci::PCI_BUS;
use spin::Once;
use self::driver::VirtioPciDriver;

View File

@ -2,7 +2,8 @@
use alloc::vec::Vec;
use ostd::{bus::pci::capability::msix::CapabilityMsixData, irq::IrqLine};
use aster_pci::capability::msix::CapabilityMsixData;
use ostd::irq::IrqLine;
pub struct VirtioMsixManager {
config_msix_vector: u16,

View File

@ -12,8 +12,3 @@ pub enum BusProbeError {
/// An error in accessing the configuration space of the device.
ConfigurationSpaceError,
}
/// Initializes the bus
pub(crate) fn init() {
pci::init();
}

View File

@ -1,54 +1,12 @@
// SPDX-License-Identifier: MPL-2.0
//! PCI device Information
//! Helper functions or structures for PCI devices.
use core::iter;
use super::cfg_space::PciDeviceCommonCfgOffset;
/// PCI device ID
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct PciDeviceId {
/// Vendor ID
pub vendor_id: u16,
/// Device ID
pub device_id: u16,
/// Revision ID
pub revision_id: u8,
/// Programming Interface Byte
pub prog_if: u8,
/// Specifies the specific function the device performs.
pub subclass: u8,
/// Specifies the type of function the device performs.
pub class: u8,
/// Subsystem Vendor ID
pub subsystem_vendor_id: u16,
/// Subsystem ID
pub subsystem_id: u16,
}
impl PciDeviceId {
pub(super) fn new(location: PciDeviceLocation) -> Self {
let vendor_id = location.read16(PciDeviceCommonCfgOffset::VendorId as u16);
let device_id = location.read16(PciDeviceCommonCfgOffset::DeviceId as u16);
let revision_id = location.read8(PciDeviceCommonCfgOffset::RevisionId as u16);
let prog_if = location.read8(PciDeviceCommonCfgOffset::ClassCode as u16);
let subclass = location.read8(PciDeviceCommonCfgOffset::ClassCode as u16 + 1);
let class = location.read8(PciDeviceCommonCfgOffset::ClassCode as u16 + 2);
let subsystem_vendor_id =
location.read16(PciDeviceCommonCfgOffset::SubsystemVendorId as u16);
let subsystem_id = location.read16(PciDeviceCommonCfgOffset::SubsystemId as u16);
Self {
vendor_id,
device_id,
revision_id,
prog_if,
subclass,
class,
subsystem_vendor_id,
subsystem_id,
}
}
/// Checks if the system has a PCI bus.
pub fn has_pci_bus() -> bool {
crate::arch::pci::has_pci_bus()
}
/// PCI device Location
@ -111,19 +69,22 @@ impl PciDeviceLocation {
}
impl PciDeviceLocation {
pub(super) const BIT32_ALIGN_MASK: u16 = 0xFFFC;
const BIT32_ALIGN_MASK: u16 = 0xFFFC;
pub(super) fn read8(&self, offset: u16) -> u8 {
/// Reads a 8-bit value from the PCI configuration space at the specified offset.
pub fn read8(&self, offset: u16) -> u8 {
let val = self.read32(offset & Self::BIT32_ALIGN_MASK);
((val >> ((offset as usize & 0b11) << 3)) & 0xFF) as u8
}
pub(super) fn read16(&self, offset: u16) -> u16 {
/// Reads a 16-bit value from the PCI configuration space at the specified offset.
pub fn read16(&self, offset: u16) -> u16 {
let val = self.read32(offset & Self::BIT32_ALIGN_MASK);
((val >> ((offset as usize & 0b10) << 3)) & 0xFFFF) as u16
}
pub(super) fn read32(&self, offset: u16) -> u32 {
/// Reads a 32-bit value from the PCI configuration space at the specified offset.
pub fn read32(&self, offset: u16) -> u32 {
debug_assert!(
(offset & 0b11) == 0,
"misaligned PCI configuration dword u32 read"
@ -131,7 +92,8 @@ impl PciDeviceLocation {
crate::arch::pci::read32(self, offset as u32).unwrap()
}
pub(super) fn write8(&self, offset: u16, val: u8) {
/// Writes an 8-bit value to the PCI configuration space at the specified offset.
pub fn write8(&self, offset: u16, val: u8) {
let old = self.read32(offset & Self::BIT32_ALIGN_MASK);
let dest = (offset as usize & 0b11) << 3;
let mask = (0xFF << dest) as u32;
@ -141,7 +103,8 @@ impl PciDeviceLocation {
);
}
pub(super) fn write16(&self, offset: u16, val: u16) {
/// Writes an 16-bit value to the PCI configuration space at the specified offset.
pub fn write16(&self, offset: u16, val: u16) {
let old = self.read32(offset & Self::BIT32_ALIGN_MASK);
let dest = (offset as usize & 0b10) << 3;
let mask = (0xFFFF << dest) as u32;
@ -151,7 +114,8 @@ impl PciDeviceLocation {
);
}
pub(super) fn write32(&self, offset: u16, val: u32) {
/// Writes an 32-bit value to the PCI configuration space at the specified offset.
pub fn write32(&self, offset: u16, val: u32) {
debug_assert!(
(offset & 0b11) == 0,
"misaligned PCI configuration dword u32 write"

View File

@ -1,79 +0,0 @@
// SPDX-License-Identifier: MPL-2.0
//! PCI bus
//!
//! Users can implement the bus under the `PciDriver` to the PCI bus to register devices,
//! when the physical device and the driver match successfully, it will be provided through the driver `construct` function
//! to construct a structure that implements the `PciDevice` trait. And in the end,
//! PCI bus will store a reference to the structure and finally call the driver's probe function to remind the driver of a new device access.
//!
//! Use case:
//!
//! ```rust no_run
//! #[derive(Debug)]
//! pub struct PciDeviceA {
//! common_device: PciCommonDevice,
//! }
//!
//! impl PciDevice for PciDeviceA {
//! fn device_id(&self) -> PciDeviceId {
//! self.common_device.device_id().clone()
//! }
//! }
//!
//! #[derive(Debug)]
//! pub struct PciDriverA {
//! devices: Mutex<Vec<Arc<PciDeviceA>>>,
//! }
//!
//! impl PciDriver for PciDriverA {
//! fn probe(
//! &self,
//! device: PciCommonDevice,
//! ) -> Result<Arc<dyn PciDevice>, (PciDriverProbeError, PciCommonDevice)> {
//! if device.device_id().vendor_id != 0x1234 {
//! return Err((PciDriverProbeError::DeviceNotMatch, device));
//! }
//! let device = Arc::new(PciDeviceA {
//! common_device: device,
//! });
//! self.devices.lock().push(device.clone());
//! Ok(device)
//! }
//! }
//!
//! pub fn driver_a_init() {
//! let driver_a = Arc::new(PciDriverA {
//! devices: Mutex::new(Vec::new()),
//! });
//! PCI_BUS.lock().register_driver(driver_a);
//! }
//! ```
pub mod bus;
pub mod capability;
pub mod cfg_space;
pub mod common_device;
mod device_info;
pub use device_info::{PciDeviceId, PciDeviceLocation};
use self::{bus::PciBus, common_device::PciCommonDevice};
use crate::{arch::pci::has_pci_bus, sync::Mutex};
/// PCI bus instance
pub static PCI_BUS: Mutex<PciBus> = Mutex::new(PciBus::new());
pub(crate) fn init() {
if !has_pci_bus() {
return;
}
let mut lock = PCI_BUS.lock();
for location in PciDeviceLocation::all() {
let Some(device) = PciCommonDevice::new(location) else {
continue;
};
lock.register_common_device(device);
}
}

View File

@ -132,8 +132,6 @@ unsafe fn init() {
mm::kspace::activate_kernel_page_table();
}
bus::init();
arch::irq::enable_local();
invoke_ffi_init_funcs();