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