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