1 use fdt::{node::FdtNode, Fdt}; 2 use system_error::SystemError; 3 4 use crate::{ 5 driver::{ 6 open_firmware::fdt::open_firmware_fdt_driver, 7 pci::ecam::{pci_ecam_root_info_manager, EcamRootInfo}, 8 }, 9 kdebug, 10 mm::PhysAddr, 11 }; 12 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 kdebug!( 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 kdebug!( 65 "pci_host_ecam_driver_init(): check {} error: {:?}", 66 node.name, 67 err 68 ); 69 } 70 } 71 72 return Ok(()); 73 } 74