1 use core::fmt::Formatter;
2
3 use alloc::sync::Arc;
4 use hashbrown::HashMap;
5
6 use crate::{
7 arch::{PciArch, TraitPciArch},
8 libs::spinlock::{SpinLock, SpinLockGuard},
9 mm::{
10 mmio_buddy::{mmio_pool, MMIOSpaceGuard},
11 page::PAGE_2M_SIZE,
12 },
13 };
14
15 use super::{
16 ecam::EcamRootInfo,
17 pci::{BusDeviceFunction, ExternalCapabilityIterator, PciCam, PciError, SegmentGroupNumber},
18 };
19
20 lazy_static! {
21 static ref PCI_ROOT_MANAGER: PciRootManager = PciRootManager::new();
22 }
23
24 #[inline(always)]
pci_root_manager() -> &'static PciRootManager25 pub fn pci_root_manager() -> &'static PciRootManager {
26 &PCI_ROOT_MANAGER
27 }
28
29 /// 代表一个PCI segement greoup.
30 #[derive(Clone, Debug)]
31 pub struct PciRoot {
32 pub ecam_root_info: Option<EcamRootInfo>,
33 pub mmio_guard: Option<Arc<MMIOSpaceGuard>>, //映射后的虚拟地址,为方便访问数据这里转化成指针
34 /// 配置空间访问机制
35 pub cam: PciCam,
36 /// bus起始位置
37 pub bus_begin: u8,
38 /// bus结束位置
39 pub bus_end: u8,
40 }
41
42 ///线程间共享需要,该结构体只需要在初始化时写入数据,无需读写锁保证线程安全
43 unsafe impl Send for PciRoot {}
44 unsafe impl Sync for PciRoot {}
45 ///实现PciRoot的Display trait,自定义输出
46 impl core::fmt::Display for PciRoot {
fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result47 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
48 if let Some(ecam_root_info) = &self.ecam_root_info {
49 write!(
50 f,
51 "PCI Eacm Root with segment:{}, bus begin at {}, bus end at {}, physical address at {:?},mapped at {:?}",
52 ecam_root_info.segment_group_number, ecam_root_info.bus_begin, ecam_root_info.bus_end, ecam_root_info.physical_address_base, self.mmio_guard
53 )
54 } else {
55 write!(f, "PCI Root cam is {:?}", self.cam,)
56 }
57 }
58 }
59
60 impl PciRoot {
61 /// 此函数用于初始化一个PciRoot结构体实例,
62 /// 该结构体基于ECAM根的物理地址,将其映射到虚拟地址
63 ///
64 /// ## 参数
65 ///
66 /// - segment_group_number: ECAM根的段组号。
67 /// - cam: PCI配置空间访问机制
68 ///
69 /// ## 返回值
70 ///
71 /// - Ok(Self): 初始化成功,返回一个新的结构体实例。
72 /// - Err(PciError): 初始化过程中发生错误,返回错误信息。
73 ///
74 /// ## 副作用
75 ///
76 /// - 成功执行后,结构体的内部状态将被初始化为包含映射后的虚拟地址。
new( ecam_root_info: Option<EcamRootInfo>, cam: PciCam, bus_begin: u8, bus_end: u8, ) -> Result<Arc<Self>, PciError>77 pub fn new(
78 ecam_root_info: Option<EcamRootInfo>,
79 cam: PciCam,
80 bus_begin: u8,
81 bus_end: u8,
82 ) -> Result<Arc<Self>, PciError> {
83 let mut pci_root = Self {
84 ecam_root_info,
85 mmio_guard: None,
86 cam,
87 bus_begin,
88 bus_end,
89 };
90
91 if ecam_root_info.is_some() {
92 pci_root.map()?;
93 }
94
95 Ok(Arc::new(pci_root))
96 }
97
98 /// # 完成物理地址到虚拟地址的映射,并将虚拟地址加入mmio_base变量
99 /// ## return 返回错误或Ok(0)
map(&mut self) -> Result<u8, PciError>100 fn map(&mut self) -> Result<u8, PciError> {
101 //debug!("bus_begin={},bus_end={}", self.bus_begin,self.bus_end);
102 let bus_number = (self.bus_end - self.bus_begin) as u32 + 1;
103 let bus_number_double = (bus_number - 1) / 2 + 1; //一个bus占据1MB空间,计算全部bus占据空间相对于2MB空间的个数
104
105 let size = (bus_number_double as usize) * PAGE_2M_SIZE;
106 unsafe {
107 let space_guard = mmio_pool()
108 .create_mmio(size)
109 .map_err(|_| PciError::CreateMmioError)?;
110 let space_guard = Arc::new(space_guard);
111 self.mmio_guard = Some(space_guard.clone());
112
113 assert!(space_guard
114 .map_phys(self.ecam_root_info.unwrap().physical_address_base, size)
115 .is_ok());
116 }
117 return Ok(0);
118 }
119
120 /// # cam_offset - 获得要操作的寄存器相对于mmio_offset的偏移量
121 ///
122 /// 此函数用于计算一个PCI设备中特定寄存器相对于该设备的MMIO基地址的偏移量。
123 ///
124 /// ## 参数
125 ///
126 /// - `bus_device_function`: BusDeviceFunction,用于标识在同一组中的PCI设备。
127 /// - `register_offset`: u16,寄存器在设备中的偏移量。
128 ///
129 /// ## 返回值
130 ///
131 /// - `u32`: 成功时,返回要操作的寄存器相对于mmio_offset的偏移量。
132 ///
133 /// ## Panic
134 ///
135 /// - 此函数在参数有效性方面进行了断言,如果传入的`bus_device_function`无效,将panic。
136 /// - 此函数计算出的地址需要是字对齐的(即地址与0x3对齐)。如果不是,将panic。
cam_offset(&self, bus_device_function: BusDeviceFunction, register_offset: u16) -> u32137 fn cam_offset(&self, bus_device_function: BusDeviceFunction, register_offset: u16) -> u32 {
138 assert!(bus_device_function.valid());
139 let bdf = ((bus_device_function.bus - self.ecam_root_info.unwrap().bus_begin) as u32) << 8
140 | (bus_device_function.device as u32) << 3
141 | bus_device_function.function as u32;
142 let address =
143 bdf << match self.cam {
144 PciCam::Portiocam => 4,
145 PciCam::MmioCam => 8,
146 PciCam::Ecam => 12,
147 } | register_offset as u32;
148 // Ensure that address is word-aligned.
149 assert!(address & 0x3 == 0);
150 address
151 }
152
153 /// # read_config - 通过bus_device_function和offset读取相应位置寄存器的值(32位)
154 ///
155 /// 此函数用于通过指定的bus_device_function和register_offset读取PCI设备中相应位置的寄存器值。
156 ///
157 /// ## 参数
158 ///
159 /// - `bus_device_function`: 在同一个group中pci设备的唯一标识符
160 /// - `register_offset`: 寄存器在设备中的offset
161 ///
162 /// ## 返回值
163 ///
164 /// - `u32`: 寄存器读值结果
read_config(&self, bus_device_function: BusDeviceFunction, register_offset: u16) -> u32165 pub fn read_config(&self, bus_device_function: BusDeviceFunction, register_offset: u16) -> u32 {
166 if self.ecam_root_info.is_some() {
167 let address = self.cam_offset(bus_device_function, register_offset);
168 unsafe {
169 // Right shift to convert from byte offset to word offset.
170 ((self.mmio_guard.as_ref().unwrap().vaddr().data() as *mut u32)
171 .add((address >> 2) as usize))
172 .read_volatile()
173 }
174 } else {
175 PciArch::read_config(&bus_device_function, register_offset as u8)
176 }
177 }
178
179 /// # write_config - 通过bus_device_function和offset写入相应位置寄存器值(32位)
180 ///
181 /// 此函数用于通过指定的bus_device_function和register_offset,向PCI设备写入一个32位的寄存器值。
182 ///
183 /// ## 参数
184 ///
185 /// - `bus_device_function`: 在同一个group中pci设备的唯一标识符
186 /// - `register_offset`: 寄存器在设备中的offset
187 /// - `data`: 要写入的数据
write_config( &self, bus_device_function: BusDeviceFunction, register_offset: u16, data: u32, )188 pub fn write_config(
189 &self,
190 bus_device_function: BusDeviceFunction,
191 register_offset: u16,
192 data: u32,
193 ) {
194 if self.ecam_root_info.is_some() {
195 let address = self.cam_offset(bus_device_function, register_offset);
196 // Safe because both the `mmio_base` and the address offset are properly aligned, and the
197 // resulting pointer is within the MMIO range of the CAM.
198 unsafe {
199 // Right shift to convert from byte offset to word offset.
200 ((self.mmio_guard.as_ref().unwrap().vaddr().data() as *mut u32)
201 .add((address >> 2) as usize))
202 .write_volatile(data)
203 }
204 } else {
205 PciArch::write_config(&bus_device_function, register_offset as u8, data);
206 }
207 }
208
209 /// 返回迭代器,遍历pcie设备的external_capabilities
210 #[allow(dead_code)]
external_capabilities( &self, bus_device_function: BusDeviceFunction, ) -> ExternalCapabilityIterator211 pub fn external_capabilities(
212 &self,
213 bus_device_function: BusDeviceFunction,
214 ) -> ExternalCapabilityIterator {
215 ExternalCapabilityIterator {
216 root: self,
217 bus_device_function,
218 next_capability_offset: Some(0x100),
219 }
220 }
221 }
222
223 #[inline(always)]
pci_root_0() -> Arc<PciRoot>224 pub fn pci_root_0() -> Arc<PciRoot> {
225 pci_root_manager().get_pci_root(0).unwrap()
226 }
227
228 pub struct PciRootManager {
229 inner: SpinLock<InnerPciRootManager>,
230 }
231
232 struct InnerPciRootManager {
233 pci_root: HashMap<SegmentGroupNumber, Arc<PciRoot>>,
234 }
235
236 impl PciRootManager {
new() -> Self237 pub fn new() -> Self {
238 Self {
239 inner: SpinLock::new(InnerPciRootManager {
240 pci_root: HashMap::new(),
241 }),
242 }
243 }
244
245 /// # 添加PciRoot - 向PciRootManager中添加一个PciRoot
246 ///
247 /// 向PciRootManager中添加一个新的PciRoot,通过其segment_group_number进行标识。
248 ///
249 /// ## 参数
250 ///
251 /// - `pci_root`: Arc<PciRoot>,要添加的PciRoot的Arc指针
add_pci_root(&self, pci_root: Arc<PciRoot>)252 pub fn add_pci_root(&self, pci_root: Arc<PciRoot>) {
253 let mut inner = self.inner.lock();
254
255 if let Some(ecam_root_info) = pci_root.ecam_root_info {
256 inner
257 .pci_root
258 .insert(ecam_root_info.segment_group_number, pci_root);
259 } else {
260 inner.pci_root.insert(pci_root.bus_begin as u16, pci_root);
261 }
262 }
263
264 /// # 检查是否存在PciRoot - 检查PciRootManager中是否存在指定segment_group_number的PciRoot
265 ///
266 /// 检查PciRootManager中是否存在segment_group_number对应的PciRoot。
267 ///
268 /// ## 参数
269 ///
270 /// - `segement_group_number`: SegmentGroupNumber,要检查的segment_group_number。
271 ///
272 /// ## 返回值
273 ///
274 /// - `true`: 如果存在对应的PciRoot。
275 /// - `false`: 如果不存在对应的PciRoot。
has_root(&self, segement_group_number: SegmentGroupNumber) -> bool276 pub fn has_root(&self, segement_group_number: SegmentGroupNumber) -> bool {
277 self.inner
278 .lock()
279 .pci_root
280 .contains_key(&segement_group_number)
281 }
282
283 /// # 获取PciRoot - 从PciRootManager中获取指定segment_group_number的PciRoot
284 ///
285 /// 从PciRootManager中获取segment_group_number对应的PciRoot。
286 ///
287 /// ## 参数
288 ///
289 /// - `segement_group_number`: SegmentGroupNumber,要获取的PciRoot的segment_group_number。
290 ///
291 /// ## 返回值
292 ///
293 /// - `Some(Arc<PciRoot>)`: 如果找到对应的PciRoot,返回其引用。
294 /// - `None`: 如果没有找到对应的PciRoot。
get_pci_root(&self, segement_group_number: SegmentGroupNumber) -> Option<Arc<PciRoot>>295 pub fn get_pci_root(&self, segement_group_number: SegmentGroupNumber) -> Option<Arc<PciRoot>> {
296 self.inner
297 .lock()
298 .pci_root
299 .get(&segement_group_number)
300 .cloned()
301 }
302
303 /// # PciRoot迭代器 - 创建一个新的PciRoot迭代器
304 ///
305 /// 创建一个新的迭代器,用于遍历PciRootManager中的所有PciRoot。
306 #[allow(dead_code)]
iter(&self) -> PciRootIterator<'_>307 pub fn iter(&self) -> PciRootIterator<'_> {
308 PciRootIterator {
309 inner: self.inner.lock(),
310 index: 0,
311 }
312 }
313 }
314
315 pub struct PciRootIterator<'a> {
316 inner: SpinLockGuard<'a, InnerPciRootManager>,
317 index: usize,
318 }
319
320 impl Iterator for PciRootIterator<'_> {
321 type Item = Arc<PciRoot>;
322
next(&mut self) -> Option<Self::Item>323 fn next(&mut self) -> Option<Self::Item> {
324 self.inner.pci_root.values().nth(self.index).cloned()
325 }
326 }
327