mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-22 11:13:22 +00:00
pci: 添加pci root manager来管理pci root,并使得riscv能够正常扫描pci设备. (#745)
* pci: 添加pci root manager来管理pci root. pci: 使得riscv能够正常扫描pci设备. * doc: 添加注释
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
driver::pci::pci::{BusDeviceFunction, PciAddr, PciError, PciRoot, SegmentGroupNumber},
|
||||
driver::pci::pci::{BusDeviceFunction, PciAddr},
|
||||
mm::PhysAddr,
|
||||
};
|
||||
|
||||
@ -31,8 +31,4 @@ pub trait TraitPciArch {
|
||||
/// @param address PCI域地址
|
||||
/// @return usize 转换结果
|
||||
fn address_pci_to_physical(pci_address: PciAddr) -> PhysAddr;
|
||||
/// @brief 获取Segement的root地址,x86_64架构为acpi mcfg表中读取
|
||||
/// @param segement 组id
|
||||
/// @return Result<PciRoot, PciError> 转换结果或出错原因
|
||||
fn ecam_root(segement: SegmentGroupNumber) -> Result<PciRoot, PciError>;
|
||||
}
|
||||
|
@ -1,8 +1,21 @@
|
||||
use system_error::SystemError;
|
||||
use unified_init::macros::unified_init;
|
||||
|
||||
use crate::{
|
||||
arch::TraitPciArch,
|
||||
driver::pci::pci::{BusDeviceFunction, PciAddr, PciError, PciRoot, SegmentGroupNumber},
|
||||
driver::{
|
||||
open_firmware::fdt::open_firmware_fdt_driver,
|
||||
pci::pci::{pci_init, BusDeviceFunction, PciAddr, PciError, SegmentGroupNumber},
|
||||
},
|
||||
init::{boot_params, initcall::INITCALL_SUBSYS},
|
||||
kwarn,
|
||||
mm::PhysAddr,
|
||||
};
|
||||
|
||||
use self::pci_host_ecam::pci_host_ecam_driver_init;
|
||||
|
||||
mod pci_host_ecam;
|
||||
|
||||
pub struct RiscV64PciArch;
|
||||
impl TraitPciArch for RiscV64PciArch {
|
||||
fn read_config(bus_device_function: &BusDeviceFunction, offset: u8) -> u32 {
|
||||
@ -14,10 +27,16 @@ impl TraitPciArch for RiscV64PciArch {
|
||||
}
|
||||
|
||||
fn address_pci_to_physical(pci_address: PciAddr) -> crate::mm::PhysAddr {
|
||||
unimplemented!("RiscV64PciArch::address_pci_to_physical")
|
||||
}
|
||||
|
||||
fn ecam_root(segement: SegmentGroupNumber) -> Result<PciRoot, PciError> {
|
||||
unimplemented!("RiscV64PciArch::ecam_root")
|
||||
return PhysAddr::new(pci_address.data());
|
||||
}
|
||||
}
|
||||
|
||||
#[unified_init(INITCALL_SUBSYS)]
|
||||
fn riscv_pci_init() -> Result<(), SystemError> {
|
||||
let fdt = open_firmware_fdt_driver().fdt_ref()?;
|
||||
|
||||
pci_host_ecam_driver_init(&fdt)?;
|
||||
pci_init();
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
73
kernel/src/arch/riscv64/pci/pci_host_ecam.rs
Normal file
73
kernel/src/arch/riscv64/pci/pci_host_ecam.rs
Normal file
@ -0,0 +1,73 @@
|
||||
use fdt::{node::FdtNode, Fdt};
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
driver::{
|
||||
open_firmware::fdt::open_firmware_fdt_driver,
|
||||
pci::ecam::{pci_ecam_root_info_manager, EcamRootInfo},
|
||||
},
|
||||
kdebug,
|
||||
mm::PhysAddr,
|
||||
};
|
||||
|
||||
pub(super) fn pci_host_ecam_driver_init(fdt: &Fdt<'_>) -> Result<(), SystemError> {
|
||||
let do_check = |node: FdtNode| -> Result<(), SystemError> {
|
||||
let reg = node
|
||||
.reg()
|
||||
.ok_or(SystemError::EINVAL)?
|
||||
.next()
|
||||
.ok_or(SystemError::EINVAL)?;
|
||||
let paddr = reg.starting_address as usize;
|
||||
let size = reg.size.unwrap_or(0);
|
||||
let bus_range: &[u8] = node.property("bus-range").ok_or(SystemError::EINVAL)?.value;
|
||||
|
||||
let (bus_begin, bus_end) = match bus_range.len() {
|
||||
8 => (
|
||||
u32::from_be_bytes(bus_range[0..4].try_into().unwrap()),
|
||||
u32::from_be_bytes(bus_range[4..8].try_into().unwrap()),
|
||||
),
|
||||
_ => panic!("Unexpected bus-range length"),
|
||||
};
|
||||
|
||||
let segement_group_number: &[u8] = node
|
||||
.property("linux,pci-domain")
|
||||
.ok_or(SystemError::EINVAL)?
|
||||
.value;
|
||||
|
||||
let segement_group_number = match segement_group_number.len() {
|
||||
4 => u32::from_be_bytes(segement_group_number[0..4].try_into().unwrap()),
|
||||
_ => panic!("Unexpected linux,pci-domain length"),
|
||||
};
|
||||
|
||||
kdebug!(
|
||||
"pci_host_ecam_driver_init(): {} paddr: {:#x} size: {:#x} bus-range: {}-{} segement_group_number: {}",
|
||||
node.name,
|
||||
paddr,
|
||||
size,
|
||||
bus_begin,
|
||||
bus_end,
|
||||
segement_group_number
|
||||
);
|
||||
|
||||
pci_ecam_root_info_manager().add_ecam_root_info(EcamRootInfo::new(
|
||||
segement_group_number.try_into().unwrap(),
|
||||
bus_begin as u8,
|
||||
bus_end as u8,
|
||||
PhysAddr::new(paddr),
|
||||
));
|
||||
|
||||
Ok(())
|
||||
};
|
||||
|
||||
for node in open_firmware_fdt_driver().find_node_by_compatible(&fdt, "pci-host-ecam-generic") {
|
||||
if let Err(err) = do_check(node) {
|
||||
kdebug!(
|
||||
"pci_host_ecam_driver_init(): check {} error: {:?}",
|
||||
node.name,
|
||||
err
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
@ -5,7 +5,6 @@ use x86::dtables::DescriptorTablePointer;
|
||||
|
||||
use crate::{
|
||||
arch::{interrupt::trap::arch_trap_init, process::table::TSSManager},
|
||||
driver::pci::pci::pci_init,
|
||||
init::init::start_kernel,
|
||||
kdebug,
|
||||
mm::{MemoryManagementArch, PhysAddr},
|
||||
@ -88,8 +87,6 @@ pub fn early_setup_arch() -> Result<(), SystemError> {
|
||||
/// 架构相关的初始化
|
||||
#[inline(never)]
|
||||
pub fn setup_arch() -> Result<(), SystemError> {
|
||||
// todo: 将来pci接入设备驱动模型之后,删掉这里。
|
||||
pci_init();
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,17 @@
|
||||
use crate::arch::TraitPciArch;
|
||||
use crate::driver::acpi::acpi_manager;
|
||||
use crate::driver::pci::ecam::{pci_ecam_root_info_manager, EcamRootInfo};
|
||||
use crate::driver::pci::pci::{
|
||||
BusDeviceFunction, PciAddr, PciCam, PciError, PciRoot, SegmentGroupNumber,
|
||||
PORT_PCI_CONFIG_ADDRESS, PORT_PCI_CONFIG_DATA,
|
||||
pci_init, BusDeviceFunction, PciAddr, PciError, PORT_PCI_CONFIG_ADDRESS, PORT_PCI_CONFIG_DATA,
|
||||
};
|
||||
use crate::include::bindings::bindings::{io_in32, io_out32};
|
||||
use crate::init::initcall::INITCALL_SUBSYS;
|
||||
use crate::kerror;
|
||||
use crate::mm::PhysAddr;
|
||||
|
||||
use acpi::mcfg::Mcfg;
|
||||
use system_error::SystemError;
|
||||
use unified_init::macros::unified_init;
|
||||
|
||||
pub struct X86_64PciArch;
|
||||
impl TraitPciArch for X86_64PciArch {
|
||||
@ -42,25 +46,41 @@ impl TraitPciArch for X86_64PciArch {
|
||||
fn address_pci_to_physical(pci_address: PciAddr) -> PhysAddr {
|
||||
return PhysAddr::new(pci_address.data());
|
||||
}
|
||||
|
||||
fn ecam_root(segement: SegmentGroupNumber) -> Result<PciRoot, PciError> {
|
||||
let mcfg = acpi_manager()
|
||||
.tables()
|
||||
.expect("get acpi_manager table error")
|
||||
.find_table::<Mcfg>()
|
||||
.map_err(|_| PciError::McfgTableNotFound)?;
|
||||
for mcfg_entry in mcfg.entries() {
|
||||
if mcfg_entry.pci_segment_group == segement {
|
||||
return Ok(PciRoot {
|
||||
physical_address_base: PhysAddr::new(mcfg_entry.base_address as usize),
|
||||
mmio_guard: None,
|
||||
segement_group_number: segement,
|
||||
bus_begin: mcfg_entry.bus_number_start,
|
||||
bus_end: mcfg_entry.bus_number_end,
|
||||
cam: PciCam::Ecam,
|
||||
});
|
||||
}
|
||||
}
|
||||
return Err(PciError::SegmentNotFound);
|
||||
}
|
||||
}
|
||||
|
||||
#[unified_init(INITCALL_SUBSYS)]
|
||||
fn x86_64_pci_init() -> Result<(), SystemError> {
|
||||
if let Err(e) = discover_ecam_root() {
|
||||
kerror!("x86_64_pci_init(): discover_ecam_root error: {:?}", e);
|
||||
}
|
||||
pci_init();
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// # discover_ecam_root - 发现使用ECAM的PCI root device
|
||||
///
|
||||
/// 该函数用于从ACPI管理器获取MCFG表,并从中发现使用ECAM的PCI root device。
|
||||
/// 然后,本函数将这些信息添加到pci_ecam_root_info_manager
|
||||
///
|
||||
/// ## 返回值
|
||||
///
|
||||
/// - Ok(()): 成功发现并添加了所有ECAM根信息
|
||||
/// - Err(PciError): 在获取ACPI管理器表或发现MCFG表时发生错误
|
||||
fn discover_ecam_root() -> Result<(), PciError> {
|
||||
let mcfg = acpi_manager()
|
||||
.tables()
|
||||
.expect("get acpi_manager table error")
|
||||
.find_table::<Mcfg>()
|
||||
.map_err(|_| PciError::McfgTableNotFound)?;
|
||||
for mcfg_entry in mcfg.entries() {
|
||||
pci_ecam_root_info_manager().add_ecam_root_info(EcamRootInfo::new(
|
||||
mcfg_entry.pci_segment_group,
|
||||
mcfg_entry.bus_number_start,
|
||||
mcfg_entry.bus_number_end,
|
||||
PhysAddr::new(mcfg_entry.base_address as usize),
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
Reference in New Issue
Block a user