fdt_edit/node/view/
pci.rs1use core::ops::{Deref, Range};
4
5use alloc::vec::Vec;
6use fdt_raw::{FdtError, Phandle};
7
8use super::NodeView;
9use crate::{NodeGeneric, NodeGenericMut, Property, ViewMutOp, ViewOp};
10
11#[derive(Clone, Debug, PartialEq)]
17pub enum PciSpace {
18 IO,
20 Memory32,
22 Memory64,
24}
25
26#[derive(Clone, Debug, PartialEq)]
30pub struct PciRange {
31 pub space: PciSpace,
33 pub bus_address: u64,
35 pub cpu_address: u64,
37 pub size: u64,
39 pub prefetchable: bool,
41}
42
43#[derive(Clone, Debug)]
47pub struct PciInterruptMap {
48 pub child_address: Vec<u32>,
50 pub child_irq: Vec<u32>,
52 pub interrupt_parent: Phandle,
54 pub parent_irq: Vec<u32>,
56}
57
58#[derive(Clone, Debug, PartialEq)]
62pub struct PciInterruptInfo {
63 pub irqs: Vec<u32>,
65}
66
67#[derive(Clone, Copy)]
73pub struct PciNodeView<'a> {
74 pub(super) inner: NodeGeneric<'a>,
75}
76
77impl<'a> Deref for PciNodeView<'a> {
78 type Target = NodeGeneric<'a>;
79
80 fn deref(&self) -> &Self::Target {
81 &self.inner
82 }
83}
84
85impl<'a> ViewOp<'a> for PciNodeView<'a> {
86 fn as_view(&self) -> NodeView<'a> {
87 self.inner.as_view()
88 }
89}
90
91impl<'a> PciNodeView<'a> {
92 pub(crate) fn try_from_view(view: NodeView<'a>) -> Option<Self> {
93 if view.as_node().is_pci() {
94 Some(Self {
95 inner: NodeGeneric { inner: view },
96 })
97 } else {
98 None
99 }
100 }
101
102 pub fn interrupt_cells(&self) -> u32 {
106 self.as_view()
107 .as_node()
108 .get_property("#interrupt-cells")
109 .and_then(|prop| prop.get_u32())
110 .unwrap_or(1)
111 }
112
113 pub fn interrupt_map_mask(&self) -> Option<Vec<u32>> {
115 self.as_view()
116 .as_node()
117 .get_property("interrupt-map-mask")
118 .map(|prop| prop.get_u32_iter().collect())
119 }
120
121 pub fn bus_range(&self) -> Option<Range<u32>> {
123 self.as_view()
124 .as_node()
125 .get_property("bus-range")
126 .and_then(|prop| {
127 let mut iter = prop.get_u32_iter();
128 let start = iter.next()?;
129 let end = iter.next()?;
130 Some(start..end)
131 })
132 }
133
134 fn decode_pci_address_space(&self, pci_hi: u32) -> (PciSpace, bool) {
140 let space_code = (pci_hi >> 24) & 0x03;
141 let prefetchable = (pci_hi >> 30) & 0x01 == 1;
142
143 let space = match space_code {
144 1 => PciSpace::IO,
145 2 => PciSpace::Memory32,
146 3 => PciSpace::Memory64,
147 _ => PciSpace::Memory32,
148 };
149
150 (space, prefetchable)
151 }
152
153 pub fn ranges(&self) -> Option<Vec<PciRange>> {
155 let prop = self.as_view().as_node().get_property("ranges")?;
156 let mut data = prop.as_reader();
157 let mut ranges = Vec::new();
158
159 let parent_addr_cells = if let Some(parent) = self.as_view().parent() {
166 parent.as_view().address_cells().unwrap_or(2) as usize
167 } else {
168 2_usize
169 };
170
171 let size_cells = self.as_view().size_cells().unwrap_or(2) as usize;
172
173 while let Some(pci_hi) = data.read_u32() {
174 let pci_mid = data.read_u32()?;
177 let pci_lo = data.read_u32()?;
178 let bus_address = ((pci_mid as u64) << 32) | (pci_lo as u64);
179
180 let mut parent_addr = 0u64;
182 for _ in 0..parent_addr_cells {
183 let cell = data.read_u32()? as u64;
184 parent_addr = (parent_addr << 32) | cell;
185 }
186
187 let mut size = 0u64;
189 for _ in 0..size_cells {
190 let cell = data.read_u32()? as u64;
191 size = (size << 32) | cell;
192 }
193
194 let (space, prefetchable) = self.decode_pci_address_space(pci_hi);
196
197 ranges.push(PciRange {
198 space,
199 bus_address,
200 cpu_address: parent_addr,
201 size,
202 prefetchable,
203 });
204 }
205
206 Some(ranges)
207 }
208
209 pub fn interrupt_map(&self) -> Result<Vec<PciInterruptMap>, FdtError> {
211 let prop = self
212 .as_view()
213 .as_node()
214 .get_property("interrupt-map")
215 .ok_or(FdtError::NotFound)?;
216
217 let mask: Vec<u32> = self
219 .interrupt_map_mask()
220 .ok_or(FdtError::NotFound)?
221 .into_iter()
222 .collect();
223
224 let mut data = prop.as_reader();
225 let mut mappings = Vec::new();
226
227 let child_addr_cells = self.as_view().address_cells().unwrap_or(3) as usize;
230 let child_irq_cells = self.interrupt_cells() as usize;
231
232 loop {
233 let mut child_address = Vec::with_capacity(child_addr_cells);
235 for _ in 0..child_addr_cells {
236 match data.read_u32() {
237 Some(v) => child_address.push(v),
238 None => return Ok(mappings), }
240 }
241
242 let mut child_irq = Vec::with_capacity(child_irq_cells);
244 for _ in 0..child_irq_cells {
245 match data.read_u32() {
246 Some(v) => child_irq.push(v),
247 None => return Ok(mappings),
248 }
249 }
250
251 let interrupt_parent_raw = match data.read_u32() {
253 Some(v) => v,
254 None => return Ok(mappings),
255 };
256 let interrupt_parent = Phandle::from(interrupt_parent_raw);
257
258 let (parent_addr_cells, parent_irq_cells) =
261 if let Some(irq_parent) = self.as_view().fdt().get_by_phandle(interrupt_parent) {
262 let addr_cells = irq_parent.as_view().address_cells().unwrap_or(0) as usize;
264
265 let irq_cells = irq_parent
266 .as_view()
267 .as_node()
268 .get_property("#interrupt-cells")
269 .and_then(|p| p.get_u32())
270 .unwrap_or(3) as usize;
271 (addr_cells, irq_cells)
272 } else {
273 (0, 3)
275 };
276
277 for _ in 0..parent_addr_cells {
279 if data.read_u32().is_none() {
280 return Ok(mappings);
281 }
282 }
283
284 let mut parent_irq = Vec::with_capacity(parent_irq_cells);
286 for _ in 0..parent_irq_cells {
287 match data.read_u32() {
288 Some(v) => parent_irq.push(v),
289 None => return Ok(mappings),
290 }
291 }
292
293 let masked_address: Vec<u32> = child_address
295 .iter()
296 .enumerate()
297 .map(|(i, value)| {
298 let mask_value = mask.get(i).copied().unwrap_or(0xffff_ffff);
299 value & mask_value
300 })
301 .collect();
302 let masked_irq: Vec<u32> = child_irq
303 .iter()
304 .enumerate()
305 .map(|(i, value)| {
306 let mask_value = mask
307 .get(child_addr_cells + i)
308 .copied()
309 .unwrap_or(0xffff_ffff);
310 value & mask_value
311 })
312 .collect();
313
314 mappings.push(PciInterruptMap {
315 child_address: masked_address,
316 child_irq: masked_irq,
317 interrupt_parent,
318 parent_irq,
319 });
320 }
321 }
322
323 pub fn child_interrupts(
326 &self,
327 bus: u8,
328 device: u8,
329 function: u8,
330 interrupt_pin: u8,
331 ) -> Result<PciInterruptInfo, FdtError> {
332 let interrupt_map = self.interrupt_map()?;
334
335 let mask: Vec<u32> = self
337 .interrupt_map_mask()
338 .ok_or(FdtError::NotFound)?
339 .into_iter()
340 .collect();
341
342 let child_addr_high = ((bus as u32 & 0xff) << 16)
345 | ((device as u32 & 0x1f) << 11)
346 | ((function as u32 & 0x07) << 8);
347 let child_addr_mid = 0u32;
348 let child_addr_low = 0u32;
349
350 let child_addr_cells = self.as_view().address_cells().unwrap_or(3) as usize;
351 let child_irq_cells = self.interrupt_cells() as usize;
352
353 let encoded_address = [child_addr_high, child_addr_mid, child_addr_low];
354 let mut masked_child_address = Vec::with_capacity(child_addr_cells);
355
356 for (idx, value) in encoded_address.iter().take(child_addr_cells).enumerate() {
358 let mask_value = mask.get(idx).copied().unwrap_or(0xffff_ffff);
359 masked_child_address.push(value & mask_value);
360 }
361
362 let remaining = child_addr_cells.saturating_sub(encoded_address.len());
364 masked_child_address.extend(core::iter::repeat_n(0, remaining));
365
366 let encoded_irq = [interrupt_pin as u32];
367 let mut masked_child_irq = Vec::with_capacity(child_irq_cells);
368
369 for (idx, value) in encoded_irq.iter().take(child_irq_cells).enumerate() {
371 let mask_value = mask
372 .get(child_addr_cells + idx)
373 .copied()
374 .unwrap_or(0xffff_ffff);
375 masked_child_irq.push(value & mask_value);
376 }
377
378 let remaining_irq = child_irq_cells.saturating_sub(encoded_irq.len());
380 masked_child_irq.extend(core::iter::repeat_n(0, remaining_irq));
381
382 for mapping in &interrupt_map {
384 if mapping.child_address == masked_child_address
385 && mapping.child_irq == masked_child_irq
386 {
387 return Ok(PciInterruptInfo {
388 irqs: mapping.parent_irq.clone(),
389 });
390 }
391 }
392
393 let simple_irq = (device as u32 * 4 + interrupt_pin as u32) % 32;
395 Ok(PciInterruptInfo {
396 irqs: vec![simple_irq],
397 })
398 }
399}
400
401pub struct PciNodeViewMut<'a> {
407 pub(super) inner: NodeGenericMut<'a>,
408}
409
410impl<'a> Deref for PciNodeViewMut<'a> {
411 type Target = NodeGenericMut<'a>;
412
413 fn deref(&self) -> &Self::Target {
414 &self.inner
415 }
416}
417
418impl<'a> ViewOp<'a> for PciNodeViewMut<'a> {
419 fn as_view(&self) -> NodeView<'a> {
420 self.inner.as_view()
421 }
422}
423
424impl<'a> ViewMutOp<'a> for PciNodeViewMut<'a> {
425 fn new(node: NodeGenericMut<'a>) -> Self {
426 let mut s = Self { inner: node };
427 let n = s.inner.inner.as_node_mut();
428 n.set_property(Property::new("device_type", b"pci\0".to_vec()));
430 n.set_property(Property::new(
432 "#address-cells",
433 (3u32).to_be_bytes().to_vec(),
434 ));
435 n.set_property(Property::new("#size-cells", (2u32).to_be_bytes().to_vec()));
436 n.set_property(Property::new(
437 "#interrupt-cells",
438 (1u32).to_be_bytes().to_vec(),
439 ));
440 s
441 }
442}
443
444impl<'a> PciNodeViewMut<'a> {
445 pub(crate) fn try_from_view(view: NodeView<'a>) -> Option<Self> {
446 if view.as_node().is_pci() {
447 Some(Self {
448 inner: NodeGenericMut { inner: view },
449 })
450 } else {
451 None
452 }
453 }
454}