xref: /DragonOS/kernel/src/arch/x86_64/pci/pci.rs (revision 196b75dc17b5cc2ed84301bce776e496ddfe1ed1)
1 use crate::arch::TraitPciArch;
2 use crate::driver::acpi::acpi_manager;
3 use crate::driver::pci::pci::{
4     BusDeviceFunction, PciAddr, PciError, PciRoot, SegmentGroupNumber, PORT_PCI_CONFIG_ADDRESS,
5     PORT_PCI_CONFIG_DATA,
6 };
7 use crate::include::bindings::bindings::{io_in32, io_out32};
8 use crate::mm::PhysAddr;
9 
10 use acpi::mcfg::Mcfg;
11 
12 pub struct X86_64PciArch;
13 impl TraitPciArch for X86_64PciArch {
14     fn read_config(bus_device_function: &BusDeviceFunction, offset: u8) -> u32 {
15         // 构造pci配置空间地址
16         let address = ((bus_device_function.bus as u32) << 16)
17             | ((bus_device_function.device as u32) << 11)
18             | ((bus_device_function.function as u32 & 7) << 8)
19             | (offset & 0xfc) as u32
20             | (0x80000000);
21         let ret = unsafe {
22             io_out32(PORT_PCI_CONFIG_ADDRESS, address);
23             let temp = io_in32(PORT_PCI_CONFIG_DATA);
24             temp
25         };
26         return ret;
27     }
28 
29     fn write_config(bus_device_function: &BusDeviceFunction, offset: u8, data: u32) {
30         let address = ((bus_device_function.bus as u32) << 16)
31             | ((bus_device_function.device as u32) << 11)
32             | ((bus_device_function.function as u32 & 7) << 8)
33             | (offset & 0xfc) as u32
34             | (0x80000000);
35         unsafe {
36             io_out32(PORT_PCI_CONFIG_ADDRESS, address);
37             // 写入数据
38             io_out32(PORT_PCI_CONFIG_DATA, data);
39         }
40     }
41 
42     fn address_pci_to_physical(pci_address: PciAddr) -> PhysAddr {
43         return PhysAddr::new(pci_address.data());
44     }
45 
46     fn ecam_root(segement: SegmentGroupNumber) -> Result<PciRoot, PciError> {
47         let mcfg = acpi_manager()
48             .tables()
49             .expect("get acpi_manager table error")
50             .find_table::<Mcfg>()
51             .map_err(|_| PciError::McfgTableNotFound)?;
52         for mcfg_entry in mcfg.entries() {
53             if mcfg_entry.pci_segment_group == segement {
54                 return Ok(PciRoot {
55                     physical_address_base: PhysAddr::new(mcfg_entry.base_address as usize),
56                     mmio_guard: None,
57                     segement_group_number: segement,
58                     bus_begin: mcfg_entry.bus_number_start,
59                     bus_end: mcfg_entry.bus_number_end,
60                 });
61             }
62         }
63         return Err(PciError::SegmentNotFound);
64     }
65 }
66