os/device/bus/
pcie.rs

1//! PCIe 模块
2
3use crate::{
4    config::{VirtDevice, mmio_of},
5    device::device_tree::FDT,
6    mm::address::{ConvertablePaddr, Paddr, UsizeConvert},
7    pr_info,
8};
9use core::ptr::{read_volatile, write_volatile};
10
11/// PCIe 设备结构体
12pub struct PciDevice {}
13
14/// PCIe 驱动结构体
15pub struct PciDriver {}
16
17/// PCIe Host 控制器结构体
18#[derive(Clone, Copy)]
19pub struct PcieHost {
20    /// ECAM 物理地址
21    ecam_paddr: usize,
22    /// ECAM 虚拟地址
23    ecam_vaddr: usize,
24    /// ECAM 大小
25    ecam_size: usize,
26    /// MMIO 基地址
27    mmio_base: usize,
28    /// MMIO 大小
29    mmio_size: usize,
30    /// 总线起始号
31    bus_start: u8,
32    /// 总线结束号
33    bus_end: u8,
34}
35
36impl PcieHost {
37    /// 从设备树解析
38    pub fn from_fdt() -> Option<Self> {
39        let fdt = &*FDT;
40
41        // 找到兼容 pci-host-ecam-generic 的节点
42        let mut target = None;
43        for node in fdt.all_nodes() {
44            if let Some(prop) = node.property("compatible") {
45                let bytes = prop.value;
46                let mut start = 0;
47                while start < bytes.len() {
48                    let mut end = start;
49                    while end < bytes.len() && bytes[end] != 0 {
50                        end += 1;
51                    }
52                    if end > start && &bytes[start..end] == b"pci-host-ecam-generic" {
53                        target = Some(node);
54                        break;
55                    }
56                    start = end + 1;
57                }
58                if target.is_some() {
59                    break;
60                }
61            }
62        }
63        let node = target?;
64
65        // 父节点(通常是 /soc 或根)决定 reg/ranges 中 parent addr/size cells
66        let parent = node.interrupt_parent()?;
67
68        let child_addr_cells = node
69            .property("#address-cells")
70            .and_then(|p| {
71                if p.value.len() >= 4 {
72                    Some(u32::from_be_bytes(p.value[0..4].try_into().unwrap()) as usize)
73                } else {
74                    None
75                }
76            })
77            .unwrap_or(3); // PCI 默认 3
78
79        let child_size_cells = node
80            .property("#size-cells")
81            .and_then(|p| {
82                if p.value.len() >= 4 {
83                    Some(u32::from_be_bytes(p.value[0..4].try_into().unwrap()) as usize)
84                } else {
85                    None
86                }
87            })
88            .unwrap_or(2);
89
90        let parent_addr_cells = parent
91            .property("#address-cells")
92            .and_then(|p| {
93                if p.value.len() >= 4 {
94                    Some(u32::from_be_bytes(p.value[0..4].try_into().unwrap()) as usize)
95                } else {
96                    None
97                }
98            })
99            .unwrap_or(2);
100
101        let parent_size_cells = parent
102            .property("#size-cells")
103            .and_then(|p| {
104                if p.value.len() >= 4 {
105                    Some(u32::from_be_bytes(p.value[0..4].try_into().unwrap()) as usize)
106                } else {
107                    None
108                }
109            })
110            .unwrap_or(2);
111
112        // bus-range(两个 32-bit)
113        let (bus_start, bus_end) = if let Some(prop) = node.property("bus-range") {
114            if prop.value.len() >= 8 {
115                let b0 = u32::from_be_bytes(prop.value[0..4].try_into().unwrap());
116                let b1 = u32::from_be_bytes(prop.value[4..8].try_into().unwrap());
117                (b0 as u8, b1 as u8)
118            } else {
119                (0, 255)
120            }
121        } else {
122            (0, 255)
123        };
124
125        // reg: 假设 parent_addr_cells=2 parent_size_cells=2 => 4 cells = 16 字节
126        let (ecam_base, ecam_size) = if let Some(prop) = node.property("reg") {
127            let cells = parent_addr_cells + parent_size_cells;
128            let need = cells * 4;
129            if prop.value.len() < need {
130                return None;
131            }
132            let mut idx = 0;
133            let mut addr = 0usize;
134            for _ in 0..parent_addr_cells {
135                addr = (addr << 32)
136                    | u32::from_be_bytes(prop.value[idx..idx + 4].try_into().unwrap()) as usize;
137                idx += 4;
138            }
139            let mut size = 0usize;
140            for _ in 0..parent_size_cells {
141                size = (size << 32)
142                    | u32::from_be_bytes(prop.value[idx..idx + 4].try_into().unwrap()) as usize;
143                idx += 4;
144            }
145            (addr, size)
146        } else {
147            return None;
148        };
149
150        // 解析 ranges:迭代条目,选取第一个 memory 资源作为 mmio window
151        let (mmio_base, mmio_size) = if let Some(prop) = node.property("ranges") {
152            let entry_cells = child_addr_cells + parent_addr_cells + parent_size_cells;
153            let entry_bytes = entry_cells * 4;
154            let mut mmio: Option<(usize, usize)> = None;
155            let mut off = 0;
156            while off + entry_bytes <= prop.value.len() {
157                let mut idx = off;
158
159                // child 地址(第一 cell 为 flags)
160                let mut child_cells_vals: [u32; 8] = [0; 8];
161                for c in 0..child_addr_cells {
162                    child_cells_vals[c] =
163                        u32::from_be_bytes(prop.value[idx..idx + 4].try_into().unwrap());
164                    idx += 4;
165                }
166                let flags = child_cells_vals[0];
167
168                // 仅处理 memory 空间 (flags & 0x0300_0000 == 0x0100_0000 或 0x0200_0000)
169                let space_code = flags & 0x0300_0000;
170                let is_mem = space_code == 0x0100_0000 || space_code == 0x0200_0000;
171                // 组合 child 基址(后两个 cells)
172                let mut child_addr = 0usize;
173                for c in 1..child_addr_cells {
174                    child_addr = (child_addr << 32) | child_cells_vals[c] as usize;
175                }
176
177                // parent 地址
178                let mut parent_addr = 0usize;
179                for _ in 0..parent_addr_cells {
180                    parent_addr = (parent_addr << 32)
181                        | u32::from_be_bytes(prop.value[idx..idx + 4].try_into().unwrap()) as usize;
182                    idx += 4;
183                }
184
185                // size
186                let mut size = 0usize;
187                for _ in 0..parent_size_cells {
188                    size = (size << 32)
189                        | u32::from_be_bytes(prop.value[idx..idx + 4].try_into().unwrap()) as usize;
190                    idx += 4;
191                }
192
193                if is_mem && size != 0 && mmio.is_none() {
194                    mmio = Some((parent_addr, size));
195                }
196
197                off += entry_bytes;
198            }
199
200            mmio.unwrap_or_else(|| mmio_of(VirtDevice::VirtPcieMmio).unwrap())
201        } else {
202            mmio_of(VirtDevice::VirtPcieMmio)?
203        };
204
205        let ecam_vaddr = Paddr::to_vaddr(&Paddr::from_usize(ecam_base)).as_usize();
206
207        Some(Self {
208            ecam_paddr: ecam_base,
209            ecam_vaddr,
210            ecam_size,
211            mmio_base,
212            mmio_size,
213            bus_start,
214            bus_end,
215        })
216    }
217
218    /// 从平台默认配置解析
219    pub fn from_platform_defaults() -> Option<Self> {
220        let (ecam_base, ecam_size) = mmio_of(VirtDevice::VirtPcieEcam)?;
221        let (mmio_base, mmio_size) = mmio_of(VirtDevice::VirtPcieMmio)?;
222        let ecam_vaddr = Paddr::to_vaddr(&Paddr::from_usize(ecam_base)).as_usize();
223
224        Some(Self {
225            ecam_paddr: ecam_base,
226            ecam_vaddr,
227            ecam_size,
228            mmio_base,
229            mmio_size,
230            bus_start: 0,
231            bus_end: 255, // 后续可由 FDT 的 bus-range 收缩
232        })
233    }
234
235    /// 计算配置空间地址
236    #[inline]
237    fn cfg_addr(&self, bus: u8, dev: u8, func: u8, offset: u16) -> *mut u32 {
238        // ECAM: base + (bus<<20) + (dev<<15) + (func<<12) + offset
239        let off = ((bus as usize) << 20)
240            | ((dev as usize) << 15)
241            | ((func as usize) << 12)
242            | ((offset as usize) & 0xfff);
243        (self.ecam_vaddr + off) as *mut u32
244    }
245
246    /// 读取 PCIe 配置空间
247    pub unsafe fn cfg_read32(&self, bus: u8, dev: u8, func: u8, offset: u16) -> u32 {
248        unsafe { read_volatile(self.cfg_addr(bus, dev, func, offset)) }
249    }
250
251    /// 写入 PCIe 配置空间
252    pub unsafe fn cfg_write32(&self, bus: u8, dev: u8, func: u8, offset: u16, val: u32) {
253        unsafe {
254            write_volatile(self.cfg_addr(bus, dev, func, offset), val);
255        }
256    }
257
258    /// 枚举 PCIe 设备并打印信息
259    pub fn enumerate(&self) {
260        pr_info!(
261            "[PCIe] ECAM @ {:#x} (size {:#x}), MMIO @ {:#x} (size {:#x})",
262            self.ecam_paddr,
263            self.ecam_size,
264            self.mmio_base,
265            self.mmio_size
266        );
267
268        for bus in self.bus_start..=self.bus_end {
269            for dev in 0u8..32 {
270                // 先探测 function 0 是否存在(Vendor ID 全 1 表示不存在)
271                let vend = unsafe { self.cfg_read32(bus, dev, 0, 0x00) } as u16;
272                if vend == 0xffff {
273                    continue;
274                }
275                // 读取 func0 的设备信息
276                let did = (unsafe { self.cfg_read32(bus, dev, 0, 0x00) } >> 16) as u16;
277                let hdr = (unsafe { self.cfg_read32(bus, dev, 0, 0x0C) } >> 16) as u8; // header type
278                let multi_func = (hdr & 0x80) != 0;
279
280                pr_info!(
281                    "[PCIe] bus {:02x} dev {:02x} fn 00: vendor={:04x} device={:04x} hdr={:02x}",
282                    bus,
283                    dev,
284                    vend,
285                    did,
286                    hdr & 0x7f
287                );
288
289                // 如为多功能设备,继续探测 fn1..7
290                if multi_func {
291                    for func in 1u8..8 {
292                        let vend = unsafe { self.cfg_read32(bus, dev, func, 0x00) } as u16;
293                        if vend == 0xffff {
294                            continue;
295                        }
296                        let did = (unsafe { self.cfg_read32(bus, dev, func, 0x00) } >> 16) as u16;
297                        let hdr = (unsafe { self.cfg_read32(bus, dev, func, 0x0C) } >> 16) as u8;
298                        pr_info!(
299                            "[PCIe] bus {:02x} dev {:02x} fn {:02x}: vendor={:04x} device={:04x} hdr={:02x}",
300                            bus,
301                            dev,
302                            func,
303                            vend,
304                            did,
305                            hdr & 0x7f
306                        );
307                    }
308                }
309            }
310        }
311    }
312}
313
314/// 初始化并枚举 PCIe 设备
315pub fn init_and_enumerate() {
316    if let Some(host) = PcieHost::from_fdt().or_else(|| PcieHost::from_platform_defaults()) {
317        host.enumerate();
318    } else {
319        pr_info!("[PCIe] no host found from platform defaults");
320    }
321}