Skip to content

Commit

Permalink
pci: 添加pci root manager来管理pci root.
Browse files Browse the repository at this point in the history
pci: 使得riscv能够正常扫描pci设备.
  • Loading branch information
fslongjin committed Apr 20, 2024
1 parent 2709e01 commit 3ae815c
Show file tree
Hide file tree
Showing 16 changed files with 490 additions and 214 deletions.
6 changes: 1 addition & 5 deletions kernel/src/arch/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
driver::pci::pci::{BusDeviceFunction, PciAddr, PciError, PciRoot, SegmentGroupNumber},
driver::pci::pci::{BusDeviceFunction, PciAddr},
mm::PhysAddr,
};

Expand Down Expand Up @@ -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>;
}
29 changes: 24 additions & 5 deletions kernel/src/arch/riscv64/pci/mod.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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")
return PhysAddr::new(pci_address.data());
}
}

fn ecam_root(segement: SegmentGroupNumber) -> Result<PciRoot, PciError> {
unimplemented!("RiscV64PciArch::ecam_root")
}
#[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(());
}
75 changes: 75 additions & 0 deletions kernel/src/arch/riscv64/pci/pci_host_ecam.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
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,
};

// static PCI_ECAM_HOST

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(());
}
3 changes: 0 additions & 3 deletions kernel/src/arch/x86_64/init/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -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(());
}

Expand Down
53 changes: 32 additions & 21 deletions kernel/src/arch/x86_64/pci/pci.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down Expand Up @@ -42,25 +46,32 @@ 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(());
}

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(())
}
5 changes: 0 additions & 5 deletions kernel/src/driver/net/e1000e/e1000e.rs
Original file line number Diff line number Diff line change
Expand Up @@ -587,11 +587,6 @@ impl Drop for E1000EDevice {
}
}

#[no_mangle]
pub extern "C" fn rs_e1000e_init() {
e1000e_init();
}

pub fn e1000e_init() {
match e1000e_probe() {
Ok(_code) => {
Expand Down
14 changes: 14 additions & 0 deletions kernel/src/driver/open_firmware/fdt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,20 @@ impl OpenFirmwareFdtDriver {

return mem_block_manager().reserve_block(base, size);
}

pub fn find_node_by_compatible<'b>(
&self,
fdt: &'b Fdt<'b>,
compatible: &'b str,
) -> impl Iterator<Item = fdt::node::FdtNode<'b, 'b>> + 'b {
// compatible = compatible.trim();
let r = fdt.all_nodes().filter(move |x| {
x.compatible()
.is_some_and(|x| x.all().any(|x| x == compatible))
});

return r;
}
}

#[allow(dead_code)]
Expand Down
71 changes: 71 additions & 0 deletions kernel/src/driver/pci/ecam.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use crate::mm::PhysAddr;

use super::{
pci::{PciCam, SegmentGroupNumber},
root::{pci_root_manager, PciRoot},
};

#[inline(always)]
pub fn pci_ecam_root_info_manager() -> &'static EcamRootInfoManager {
&EcamRootInfoManager
}

/// Ecam pci root info
#[derive(Clone, Copy)]
pub struct EcamRootInfo {
pub segement_group_number: SegmentGroupNumber,
pub bus_begin: u8,
pub bus_end: u8,
pub physical_address_base: PhysAddr,
}

impl EcamRootInfo {
pub fn new(
segement_group_number: SegmentGroupNumber,
bus_begin: u8,
bus_end: u8,
physical_address_base: PhysAddr,
) -> Self {
Self {
segement_group_number,
bus_begin,
bus_end,
physical_address_base,
}
}
}

pub struct EcamRootInfoManager;

impl EcamRootInfoManager {
/// # add_ecam_root_info - 向EcamRootInfoManager添加EcamRootInfo
///
/// 将一个新的EcamRootInfo添加到EcamRootInfoManager中。
///
/// ## 参数
///
/// - `ecam_root_info`: EcamRootInfo - 要添加的EcamRootInfo实例
pub fn add_ecam_root_info(&self, ecam_root_info: EcamRootInfo) {
if !pci_root_manager().has_root(ecam_root_info.segement_group_number) {
let root = PciRoot::new(
ecam_root_info.segement_group_number,
PciCam::Ecam,
ecam_root_info.physical_address_base,
ecam_root_info.bus_begin,
ecam_root_info.bus_end,
);

if let Err(err) = root {
kerror!("add_ecam_root_info(): failed to create PciRoot: {:?}", err);
return;
}

pci_root_manager().add_pci_root(root.unwrap());
} else {
kwarn!(
"add_ecam_root_info(): root {} already exists",
ecam_root_info.segement_group_number
);
}
}
}
2 changes: 2 additions & 0 deletions kernel/src/driver/pci/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
pub mod ecam;
#[allow(clippy::module_inception)]
pub mod pci;
pub mod pci_irq;
pub mod root;
Loading

0 comments on commit 3ae815c

Please sign in to comment.