1 use fdt::{node::FdtNode, Fdt};
2 use log::debug;
3 use system_error::SystemError;
4
5 use crate::{
6 driver::{
7 open_firmware::fdt::open_firmware_fdt_driver,
8 pci::ecam::{pci_ecam_root_info_manager, EcamRootInfo},
9 },
10 mm::PhysAddr,
11 };
12
pci_host_ecam_driver_init(fdt: &Fdt<'_>) -> Result<(), SystemError>13 pub(super) fn pci_host_ecam_driver_init(fdt: &Fdt<'_>) -> Result<(), SystemError> {
14 let do_check = |node: FdtNode| -> Result<(), SystemError> {
15 let reg = node
16 .reg()
17 .ok_or(SystemError::EINVAL)?
18 .next()
19 .ok_or(SystemError::EINVAL)?;
20 let paddr = reg.starting_address as usize;
21 let size = reg.size.unwrap_or(0);
22 let bus_range: &[u8] = node.property("bus-range").ok_or(SystemError::EINVAL)?.value;
23
24 let (bus_begin, bus_end) = match bus_range.len() {
25 8 => (
26 u32::from_be_bytes(bus_range[0..4].try_into().unwrap()),
27 u32::from_be_bytes(bus_range[4..8].try_into().unwrap()),
28 ),
29 _ => panic!("Unexpected bus-range length"),
30 };
31
32 let segement_group_number: &[u8] = node
33 .property("linux,pci-domain")
34 .ok_or(SystemError::EINVAL)?
35 .value;
36
37 let segement_group_number = match segement_group_number.len() {
38 4 => u32::from_be_bytes(segement_group_number[0..4].try_into().unwrap()),
39 _ => panic!("Unexpected linux,pci-domain length"),
40 };
41
42 debug!(
43 "pci_host_ecam_driver_init(): {} paddr: {:#x} size: {:#x} bus-range: {}-{} segement_group_number: {}",
44 node.name,
45 paddr,
46 size,
47 bus_begin,
48 bus_end,
49 segement_group_number
50 );
51
52 pci_ecam_root_info_manager().add_ecam_root_info(EcamRootInfo::new(
53 segement_group_number.try_into().unwrap(),
54 bus_begin as u8,
55 bus_end as u8,
56 PhysAddr::new(paddr),
57 ));
58
59 Ok(())
60 };
61
62 for node in open_firmware_fdt_driver().find_node_by_compatible(&fdt, "pci-host-ecam-generic") {
63 if let Err(err) = do_check(node) {
64 debug!(
65 "pci_host_ecam_driver_init(): check {} error: {:?}",
66 node.name, err
67 );
68 }
69 }
70
71 return Ok(());
72 }
73