Move PCI bus in OSTD into PCI component
This commit is contained in:
parent
f2d1cbdf57
commit
1a86bd2471
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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" }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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},
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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},
|
||||
|
|
|
|||
|
|
@ -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::{
|
||||
|
|
|
|||
|
|
@ -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},
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -132,8 +132,6 @@ unsafe fn init() {
|
|||
mm::kspace::activate_kernel_page_table();
|
||||
}
|
||||
|
||||
bus::init();
|
||||
|
||||
arch::irq::enable_local();
|
||||
|
||||
invoke_ffi_init_funcs();
|
||||
|
|
|
|||
Loading…
Reference in New Issue