fdt_edit/node/
pci.rs

1use core::ops::{Deref, Range};
2
3use alloc::vec::Vec;
4use fdt_raw::{FdtError, Phandle, data::U32Iter};
5use log::debug;
6
7use crate::node::gerneric::NodeRefGen;
8
9#[derive(Clone, Debug, PartialEq)]
10pub enum PciSpace {
11    IO,
12    Memory32,
13    Memory64,
14}
15
16#[derive(Clone, Debug, PartialEq)]
17pub struct PciRange {
18    pub space: PciSpace,
19    pub bus_address: u64,
20    pub cpu_address: u64,
21    pub size: u64,
22    pub prefetchable: bool,
23}
24
25#[derive(Clone, Debug)]
26pub struct PciInterruptMap {
27    pub child_address: Vec<u32>,
28    pub child_irq: Vec<u32>,
29    pub interrupt_parent: Phandle,
30    pub parent_irq: Vec<u32>,
31}
32
33#[derive(Clone, Debug, PartialEq)]
34pub struct PciInterruptInfo {
35    pub irqs: Vec<u32>,
36}
37
38#[derive(Clone, Debug)]
39pub struct NodeRefPci<'a> {
40    pub node: NodeRefGen<'a>,
41}
42
43impl<'a> NodeRefPci<'a> {
44    // 在这里添加 PCI 相关的方法
45    pub fn try_from(node: NodeRefGen<'a>) -> Result<Self, NodeRefGen<'a>> {
46        if node.device_type() == Some("pci") {
47            Ok(Self { node })
48        } else {
49            Err(node)
50        }
51    }
52
53    pub fn interrupt_cells(&self) -> u32 {
54        self.find_property("#interrupt-cells")
55            .and_then(|prop| prop.get_u32())
56            .unwrap_or(1) // Default to 1 interrupt cell for PCI
57    }
58
59    /// Get the interrupt-map-mask property if present
60    pub fn interrupt_map_mask(&self) -> Option<U32Iter<'_>> {
61        self.find_property("interrupt-map-mask")
62            .map(|prop| prop.get_u32_iter())
63    }
64
65    /// Get the bus range property if present
66    pub fn bus_range(&self) -> Option<Range<u32>> {
67        self.find_property("bus-range").and_then(|prop| {
68            let mut data = prop.get_u32_iter();
69            let start = data.next()?;
70            let end = data.next()?;
71
72            Some(start..end)
73        })
74    }
75
76    /// Get the ranges property for address translation
77    pub fn ranges(&self) -> Option<Vec<PciRange>> {
78        let prop = self.find_property("ranges")?;
79
80        let mut data = prop.as_reader();
81
82        let mut ranges = Vec::new();
83
84        // PCI ranges format: <child-bus-address parent-bus-address size>
85        // child-bus-address: 3 cells (pci.hi pci.mid pci.lo) - PCI 地址固定 3 cells
86        // parent-bus-address: 使用父节点的 #address-cells
87        // size: 使用当前节点的 #size-cells
88        let parent_addr_cells = self.ctx.parent_address_cells() as usize;
89        let size_cells = self.size_cells().unwrap_or(2) as usize;
90
91        while let Some(pci_hi) = data.read_u32() {
92            // Parse child bus address (3 cells for PCI: phys.hi, phys.mid, phys.lo)
93            let bus_address = data.read_u64()?;
94
95            // Parse parent bus address (使用父节点的 #address-cells)
96            let parent_addr = data.read_cells(parent_addr_cells)?;
97
98            // Parse size (使用当前节点的 #size-cells)
99            let size = data.read_cells(size_cells)?;
100
101            // Extract PCI address space and prefetchable from child_addr[0]
102            let (space, prefetchable) = self.decode_pci_address_space(pci_hi);
103
104            ranges.push(PciRange {
105                space,
106                bus_address,
107                cpu_address: parent_addr,
108                size,
109                prefetchable,
110            });
111        }
112
113        Some(ranges)
114    }
115
116    /// Decode PCI address space from the high cell of PCI address
117    fn decode_pci_address_space(&self, pci_hi: u32) -> (PciSpace, bool) {
118        // PCI address high cell format:
119        // Bits 31-28: 1 for IO space, 2 for Memory32, 3 for Memory64
120        // Bit 30: Prefetchable for memory spaces
121        let space_code = (pci_hi >> 24) & 0x03;
122        let prefetchable = (pci_hi >> 30) & 0x01 == 1;
123
124        let space = match space_code {
125            1 => PciSpace::IO,
126            2 => PciSpace::Memory32,
127            3 => PciSpace::Memory64,
128            _ => PciSpace::Memory32, // Default fallback
129        };
130
131        (space, prefetchable)
132    }
133
134    /// 获取 PCI 设备的中断信息
135    /// 参数: bus, device, function, pin (1=INTA, 2=INTB, 3=INTC, 4=INTD)
136    pub fn child_interrupts(
137        &self,
138        bus: u8,
139        device: u8,
140        function: u8,
141        interrupt_pin: u8,
142    ) -> Result<PciInterruptInfo, FdtError> {
143        // 获取 interrupt-map 和 mask
144        let interrupt_map = self.interrupt_map()?;
145
146        // 将 mask 转换为 Vec 以便索引访问
147        let mask: Vec<u32> = self
148            .interrupt_map_mask()
149            .ok_or(FdtError::NotFound)?
150            .collect();
151
152        // 构造 PCI 设备的子地址
153        // 格式: [bus_num, device_num, func_num] 在适当的位
154        let child_addr_high = ((bus as u32 & 0xff) << 16)
155            | ((device as u32 & 0x1f) << 11)
156            | ((function as u32 & 0x7) << 8);
157        let child_addr_mid = 0u32;
158        let child_addr_low = 0u32;
159
160        let child_addr_cells = self.address_cells().unwrap_or(3) as usize;
161        let child_irq_cells = self.interrupt_cells() as usize;
162
163        let encoded_address = [child_addr_high, child_addr_mid, child_addr_low];
164        let mut masked_child_address = Vec::with_capacity(child_addr_cells);
165
166        // 应用 mask 到子地址
167        for (idx, value) in encoded_address.iter().take(child_addr_cells).enumerate() {
168            let mask_value = mask.get(idx).copied().unwrap_or(0xffff_ffff);
169            masked_child_address.push(value & mask_value);
170        }
171
172        // 如果 encoded_address 比 child_addr_cells 短,填充 0
173        let remaining = child_addr_cells.saturating_sub(encoded_address.len());
174        masked_child_address.extend(core::iter::repeat_n(0, remaining));
175
176        let encoded_irq = [interrupt_pin as u32];
177        let mut masked_child_irq = Vec::with_capacity(child_irq_cells);
178
179        // 应用 mask 到子 IRQ
180        for (idx, value) in encoded_irq.iter().take(child_irq_cells).enumerate() {
181            let mask_value = mask
182                .get(child_addr_cells + idx)
183                .copied()
184                .unwrap_or(0xffff_ffff);
185            masked_child_irq.push(value & mask_value);
186        }
187
188        // 如果 encoded_irq 比 child_irq_cells 短,填充 0
189        let remaining_irq = child_irq_cells.saturating_sub(encoded_irq.len());
190        masked_child_irq.extend(core::iter::repeat_n(0, remaining_irq));
191
192        // 在 interrupt-map 中查找匹配的条目
193        for mapping in &interrupt_map {
194            if mapping.child_address == masked_child_address
195                && mapping.child_irq == masked_child_irq
196            {
197                return Ok(PciInterruptInfo {
198                    irqs: mapping.parent_irq.clone(),
199                });
200            }
201        }
202
203        // 回退到简单的 IRQ 计算
204        let simple_irq = (device as u32 * 4 + interrupt_pin as u32) % 32;
205        Ok(PciInterruptInfo {
206            irqs: vec![simple_irq],
207        })
208    }
209
210    /// 解析 interrupt-map 属性
211    pub fn interrupt_map(&self) -> Result<Vec<PciInterruptMap>, FdtError> {
212        let prop = self
213            .find_property("interrupt-map")
214            .ok_or(FdtError::NotFound)?;
215
216        // 将 mask 和 data 转换为 Vec 以便索引访问
217        let mask: Vec<u32> = self
218            .interrupt_map_mask()
219            .ok_or(FdtError::NotFound)?
220            .collect();
221
222        let mut data = prop.as_reader();
223        let mut mappings = Vec::new();
224
225        // 计算每个条目的大小
226        // 格式: <child-address child-irq interrupt-parent parent-address parent-irq...>
227        let child_addr_cells = self.address_cells().unwrap_or(3) as usize;
228        let child_irq_cells = self.interrupt_cells() as usize;
229
230        loop {
231            // 解析子地址
232            let mut child_address = Vec::with_capacity(child_addr_cells);
233            for _ in 0..child_addr_cells {
234                match data.read_u32() {
235                    Some(v) => child_address.push(v),
236                    None => return Ok(mappings), // 数据结束
237                }
238            }
239
240            // 解析子 IRQ
241            let mut child_irq = Vec::with_capacity(child_irq_cells);
242            for _ in 0..child_irq_cells {
243                match data.read_u32() {
244                    Some(v) => child_irq.push(v),
245                    None => return Ok(mappings),
246                }
247            }
248
249            // 解析中断父 phandle
250            let interrupt_parent_raw = match data.read_u32() {
251                Some(v) => v,
252                None => return Ok(mappings),
253            };
254            let interrupt_parent = Phandle::from(interrupt_parent_raw);
255
256            debug!(
257                "Looking for interrupt parent phandle: 0x{:x} (raw: {})",
258                interrupt_parent.raw(),
259                interrupt_parent_raw
260            );
261            debug!(
262                "Context phandle_map keys: {:?}",
263                self.ctx
264                    .phandle_map
265                    .keys()
266                    .map(|p| format!("0x{:x}", p.raw()))
267                    .collect::<Vec<_>>()
268            );
269
270            // 通过 phandle 查找中断父节点以获取其 #address-cells 和 #interrupt-cells
271            // 根据 devicetree 规范,interrupt-map 中的 parent unit address 使用中断父节点的 #address-cells
272            let (parent_addr_cells, parent_irq_cells) =
273                if let Some(irq_parent) = self.ctx.find_by_phandle(interrupt_parent) {
274                    debug!("Found interrupt parent: {:?}", irq_parent.name);
275
276                    // 直接使用中断父节点的 #address-cells
277                    let addr_cells = irq_parent.address_cells().unwrap_or(0) as usize;
278
279                    let irq_cells = irq_parent
280                        .get_property("#interrupt-cells")
281                        .and_then(|p| p.get_u32())
282                        .unwrap_or(3) as usize;
283                    debug!(
284                        "irq_parent addr_cells: {}, irq_cells: {}",
285                        addr_cells, irq_cells
286                    );
287                    (addr_cells, irq_cells)
288                } else {
289                    debug!(
290                        "Interrupt parent phandle 0x{:x} NOT FOUND in context!",
291                        interrupt_parent.raw()
292                    );
293                    // 默认值:address_cells=0, interrupt_cells=3 (GIC 格式)
294                    (0, 3)
295                };
296
297            // 跳过父地址 cells
298            for _ in 0..parent_addr_cells {
299                if data.read_u32().is_none() {
300                    return Ok(mappings);
301                }
302            }
303
304            // 解析父 IRQ
305            let mut parent_irq = Vec::with_capacity(parent_irq_cells);
306            for _ in 0..parent_irq_cells {
307                match data.read_u32() {
308                    Some(v) => parent_irq.push(v),
309                    None => return Ok(mappings),
310                }
311            }
312
313            // 应用 mask 到子地址和 IRQ
314            let masked_address: Vec<u32> = child_address
315                .iter()
316                .enumerate()
317                .map(|(i, value)| {
318                    let mask_value = mask.get(i).copied().unwrap_or(0xffff_ffff);
319                    value & mask_value
320                })
321                .collect();
322            let masked_irq: Vec<u32> = child_irq
323                .iter()
324                .enumerate()
325                .map(|(i, value)| {
326                    let mask_value = mask
327                        .get(child_addr_cells + i)
328                        .copied()
329                        .unwrap_or(0xffff_ffff);
330                    value & mask_value
331                })
332                .collect();
333
334            mappings.push(PciInterruptMap {
335                child_address: masked_address,
336                child_irq: masked_irq,
337                interrupt_parent,
338                parent_irq,
339            });
340        }
341    }
342}
343
344impl<'a> Deref for NodeRefPci<'a> {
345    type Target = NodeRefGen<'a>;
346
347    fn deref(&self) -> &Self::Target {
348        &self.node
349    }
350}