xref: /DragonOS/kernel/src/arch/x86_64/pci/pci.rs (revision 2eab6dd743e94a86a685f1f3c01e599adf86610a)
1 use crate::arch::TraitPciArch;
2 use crate::driver::acpi::acpi_manager;
3 use crate::driver::pci::ecam::{pci_ecam_root_info_manager, EcamRootInfo};
4 use crate::driver::pci::pci::{
5     pci_init, BusDeviceFunction, PciAddr, PciError, PORT_PCI_CONFIG_ADDRESS, PORT_PCI_CONFIG_DATA,
6 };
7 use crate::include::bindings::bindings::{io_in32, io_out32};
8 use crate::init::initcall::INITCALL_SUBSYS;
9 
10 use crate::mm::PhysAddr;
11 
12 use acpi::mcfg::Mcfg;
13 use log::error;
14 use system_error::SystemError;
15 use unified_init::macros::unified_init;
16 
17 pub struct X86_64PciArch;
18 impl TraitPciArch for X86_64PciArch {
19     fn read_config(bus_device_function: &BusDeviceFunction, offset: u8) -> u32 {
20         // 构造pci配置空间地址
21         let address = ((bus_device_function.bus as u32) << 16)
22             | ((bus_device_function.device as u32) << 11)
23             | ((bus_device_function.function as u32 & 7) << 8)
24             | (offset & 0xfc) as u32
25             | (0x80000000);
26         let ret = unsafe {
27             io_out32(PORT_PCI_CONFIG_ADDRESS, address);
28             let temp = io_in32(PORT_PCI_CONFIG_DATA);
29             temp
30         };
31         return ret;
32     }
33 
34     fn write_config(bus_device_function: &BusDeviceFunction, offset: u8, data: u32) {
35         let address = ((bus_device_function.bus as u32) << 16)
36             | ((bus_device_function.device as u32) << 11)
37             | ((bus_device_function.function as u32 & 7) << 8)
38             | (offset & 0xfc) as u32
39             | (0x80000000);
40         unsafe {
41             io_out32(PORT_PCI_CONFIG_ADDRESS, address);
42             // 写入数据
43             io_out32(PORT_PCI_CONFIG_DATA, data);
44         }
45     }
46 
47     fn address_pci_to_physical(pci_address: PciAddr) -> PhysAddr {
48         return PhysAddr::new(pci_address.data());
49     }
50 }
51 
52 #[unified_init(INITCALL_SUBSYS)]
53 fn x86_64_pci_init() -> Result<(), SystemError> {
54     if let Err(e) = discover_ecam_root() {
55         error!("x86_64_pci_init(): discover_ecam_root error: {:?}", e);
56     }
57     pci_init();
58 
59     return Ok(());
60 }
61 
62 /// # discover_ecam_root - 发现使用ECAM的PCI root device
63 ///
64 /// 该函数用于从ACPI管理器获取MCFG表,并从中发现使用ECAM的PCI root device。
65 /// 然后,本函数将这些信息添加到pci_ecam_root_info_manager
66 ///
67 /// ## 返回值
68 ///
69 /// - Ok(()): 成功发现并添加了所有ECAM根信息
70 /// - Err(PciError): 在获取ACPI管理器表或发现MCFG表时发生错误
71 fn discover_ecam_root() -> Result<(), PciError> {
72     let mcfg = acpi_manager()
73         .tables()
74         .expect("get acpi_manager table error")
75         .find_table::<Mcfg>()
76         .map_err(|_| PciError::McfgTableNotFound)?;
77     for mcfg_entry in mcfg.entries() {
78         pci_ecam_root_info_manager().add_ecam_root_info(EcamRootInfo::new(
79             mcfg_entry.pci_segment_group,
80             mcfg_entry.bus_number_start,
81             mcfg_entry.bus_number_end,
82             PhysAddr::new(mcfg_entry.base_address as usize),
83         ));
84     }
85 
86     Ok(())
87 }
88