fdt_parser/
pci.rs

1use core::{fmt::Debug, ops::Range};
2
3use crate::{
4    define::Phandle,
5    error::FdtResult,
6    node::Node,
7    read::{FdtReader, U32Array},
8    FdtError, FdtRangeIter, InterruptController,
9};
10
11pub struct Pci<'a> {
12    pub node: Node<'a>,
13}
14
15impl<'a> Pci<'a> {
16    pub fn bus_range(&self) -> Option<Range<usize>> {
17        let prop = self.node.find_property("bus-range")?;
18        let mut reader = FdtReader::new(prop.raw_value());
19        let start = reader.take_u32()?;
20        let end = reader.take_u32()?;
21
22        Some(start as usize..end as usize)
23    }
24
25    pub fn ranges(&self) -> FdtResult<impl Iterator<Item = PciRange> + 'a> {
26        let ranges = self
27            .node
28            .node_ranges()
29            .ok_or(FdtError::NotFound("ranges"))?;
30
31        let iter = ranges.iter();
32
33        Ok(PciRangeIter { iter })
34    }
35
36    pub fn child_interrupts(
37        &self,
38        bus: u8,
39        device: u8,
40        func: u8,
41        irq_pin: u32,
42    ) -> FdtResult<PciChildIrq<'a>> {
43        let mask = self.interrupt_map_mask()?;
44
45        let want0 = (bus as u32) << 16 | (device as u32) << 11 | (func as u32) << 8;
46
47        let mut want = [0; 4];
48
49        want[0] = want0 & mask[0];
50        want[3] = irq_pin & mask[3];
51
52        let mut prop = self
53            .node
54            .find_property("interrupt-map")
55            .ok_or(FdtError::NotFound("interrupt-map"))?;
56
57        while let Some(hi) = prop.data.take_u32() {
58            let _mid = prop.data.take_u32().ok_or(FdtError::Eof)?;
59            let _lo = prop.data.take_u32().ok_or(FdtError::Eof)?;
60            let irq_line = prop.data.take_u32().ok_or(FdtError::Eof)?;
61
62            let parent = Phandle::from(prop.data.take_u32().ok_or(FdtError::Eof)?);
63
64            let parent_node = self
65                .node
66                .fdt
67                .get_node_by_phandle(parent)
68                .ok_or(FdtError::NotFound("parent interrupt"))?;
69
70            let address_cell = parent_node
71                .find_property("#address-cells")
72                .map(|p| p.u32())
73                .unwrap_or_default();
74
75            for _i in 0..address_cell {
76                prop.data.take_u32().ok_or(FdtError::Eof)?;
77            }
78
79            let parent_node = InterruptController { node: parent_node };
80
81            let cell_size = parent_node.interrupt_cells();
82
83            let data = prop
84                .data
85                .take(cell_size * size_of::<u32>())
86                .ok_or(FdtError::Eof)?;
87
88            if hi & mask[0] != want[0] || irq_line != want[3] {
89                continue;
90            }
91
92            return Ok(PciChildIrq {
93                parent,
94                irqs: U32Array::new(data),
95            });
96        }
97
98        Err(FdtError::NotFound("pci child"))
99    }
100
101    fn interrupt_map_mask(&self) -> FdtResult<[u32; 4]> {
102        let prop = self
103            .node
104            .find_property("interrupt-map-mask")
105            .ok_or(FdtError::NotFound("interrupt-map-mask"))?;
106
107        let mut mask = [0u32; 4];
108        let mut data = prop.data.clone();
109
110        for one in mask.iter_mut() {
111            *one = data.take_u32().ok_or(FdtError::Eof)?;
112        }
113
114        Ok(mask)
115    }
116}
117
118pub struct PciChildIrq<'a> {
119    pub parent: Phandle,
120    pub irqs: U32Array<'a>,
121}
122
123pub struct PciRangeIter<'a> {
124    iter: FdtRangeIter<'a>,
125}
126
127impl Iterator for PciRangeIter<'_> {
128    type Item = PciRange;
129
130    fn next(&mut self) -> Option<Self::Item> {
131        let one = self.iter.next()?;
132        let mut child = one.child_bus_address();
133        let cpu_address = one.parent_bus_address().as_u64();
134        let size = one.size;
135
136        let hi = child.next().unwrap();
137        let mid = child.next().unwrap();
138        let low = child.next().unwrap();
139
140        let ss = (hi >> 24) & 0b11;
141        let prefetchable = (hi & 1 << 30) > 0;
142
143        let space = match ss {
144            0b00 => PciSpace::Configuration,
145            0b01 => PciSpace::IO,
146            0b10 => PciSpace::Memory32,
147            0b11 => PciSpace::Memory64,
148            _ => panic!(),
149        };
150
151        let child_bus_address = (mid as u64) << 32 | low as u64;
152
153        Some(PciRange {
154            space,
155            bus_address: child_bus_address,
156            cpu_address,
157            size,
158            prefetchable,
159        })
160    }
161}
162
163#[derive(Debug, Clone, Copy, PartialEq, Eq)]
164pub enum PciSpace {
165    Configuration,
166    IO,
167    Memory32,
168    Memory64,
169}
170
171#[derive(Clone, PartialEq, Eq)]
172pub struct PciRange {
173    pub space: PciSpace,
174    pub bus_address: u64,
175    pub cpu_address: u64,
176    pub size: u64,
177    pub prefetchable: bool,
178}
179
180// #[derive(Debug, Clone, Copy)]
181// pub struct PciPhys {
182//     pub bus_address: u64,
183//     pub bus_num: u8,
184//     pub device_num: u8,
185//     pub function_num: u8,
186//     pub register_num: u8,
187//     pub space: PciSpace,
188//     pub prefetchable: bool,
189//     pub relocatable: bool,
190// }
191
192// impl From<[u32; 3]> for PciPhys {
193//     fn from(value: [u32; 3]) -> Self {
194//         // [hi, mid, low]
195
196//         let hi = value[0];
197//         let mid = value[1];
198//         let low = value[2];
199
200//         let ss = (hi >> 24) & 0b11;
201//         let prefetchable = (hi & 1 << 30) > 0;
202//         let relocatable = (hi & 1 << 31) > 0;
203
204//         let bus_num = ((hi >> 16) & 0xFF) as u8;
205
206//         let device_num = ((hi >> 11) & 0b11111) as u8;
207//         let function_num = (hi >> 8 & 0b111) as u8;
208//         let register_num = (hi & 0xFF) as u8;
209
210//         let space = match ss {
211//             0b00 => PciSpace::Configuration,
212//             0b01 => PciSpace::IO,
213//             0b10 => PciSpace::Memory32,
214//             0b11 => PciSpace::Memory64,
215//             _ => panic!(),
216//         };
217
218//         let child_bus_address = (mid as u64) << 32 | low as u64;
219
220//         PciPhys {
221//             space,
222//             bus_address: child_bus_address,
223//             prefetchable,
224//             relocatable,
225//             bus_num,
226//             device_num,
227//             function_num,
228//             register_num,
229//         }
230//     }
231// }
232
233impl Debug for PciRange {
234    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
235        write!(f, "PciRange {{ space: {:?}, child_bus_address: {:#x}, parent_bus_address: {:#x}, size: {:#x}, prefetchable: {}}}", 
236        self.space, self.bus_address, self.cpu_address, self.size, self.prefetchable)
237    }
238}