1 #![allow(dead_code)]
2 // 目前仅支持单主桥单Segment
3
4 use super::pci_irq::{IrqType, PciIrqError};
5 use crate::arch::{PciArch, TraitPciArch};
6 use crate::include::bindings::bindings::{PAGE_2M_SIZE, VM_DONTCOPY, VM_IO};
7 use crate::libs::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
8 use crate::mm::kernel_mapper::KernelMapper;
9 use crate::mm::mmio_buddy::mmio_pool;
10 use crate::mm::page::PageFlags;
11 use crate::mm::{PhysAddr, VirtAddr};
12 use crate::{kdebug, kerror, kinfo, kwarn};
13 use alloc::vec::Vec;
14 use alloc::{boxed::Box, collections::LinkedList};
15 use bitflags::bitflags;
16
17 use core::{
18 convert::TryFrom,
19 fmt::{self, Debug, Display, Formatter},
20 };
21 // PCI_DEVICE_LINKEDLIST 添加了读写锁的全局链表,里面存储了检索到的PCI设备结构体
22 // PCI_ROOT_0 Segment为0的全局PciRoot
23 lazy_static! {
24 pub static ref PCI_DEVICE_LINKEDLIST: PciDeviceLinkedList = PciDeviceLinkedList::new();
25 pub static ref PCI_ROOT_0: Option<PciRoot> = {
26 match PciRoot::new(0) {
27 Ok(root) => Some(root),
28 Err(err) => {
29 kerror!("Pci_root init failed because of error: {}", err);
30 None
31 }
32 }
33 };
34 }
35 /// PCI域地址
36 #[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)]
37 #[repr(transparent)]
38 pub struct PciAddr(usize);
39
40 impl PciAddr {
41 #[inline(always)]
new(address: usize) -> Self42 pub const fn new(address: usize) -> Self {
43 Self(address)
44 }
45
46 /// @brief 获取PCI域地址的值
47 #[inline(always)]
data(&self) -> usize48 pub fn data(&self) -> usize {
49 self.0
50 }
51
52 /// @brief 将PCI域地址加上一个偏移量
53 #[inline(always)]
add(self, offset: usize) -> Self54 pub fn add(self, offset: usize) -> Self {
55 Self(self.0 + offset)
56 }
57
58 /// @brief 判断PCI域地址是否按照指定要求对齐
59 #[inline(always)]
check_aligned(&self, align: usize) -> bool60 pub fn check_aligned(&self, align: usize) -> bool {
61 return self.0 & (align - 1) == 0;
62 }
63 }
64 impl Debug for PciAddr {
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result65 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
66 write!(f, "PciAddr({:#x})", self.0)
67 }
68 }
69
70 /// 添加了读写锁的链表,存储PCI设备结构体
71 pub struct PciDeviceLinkedList {
72 list: RwLock<LinkedList<Box<dyn PciDeviceStructure>>>,
73 }
74
75 impl PciDeviceLinkedList {
76 /// @brief 初始化结构体
new() -> Self77 fn new() -> Self {
78 PciDeviceLinkedList {
79 list: RwLock::new(LinkedList::new()),
80 }
81 }
82 /// @brief 获取可读的linkedlist(读锁守卫)
83 /// @return RwLockReadGuard<LinkedList<Box<dyn PciDeviceStructure>>> 读锁守卫
read(&self) -> RwLockReadGuard<LinkedList<Box<dyn PciDeviceStructure>>>84 pub fn read(&self) -> RwLockReadGuard<LinkedList<Box<dyn PciDeviceStructure>>> {
85 self.list.read()
86 }
87 /// @brief 获取可写的linkedlist(写锁守卫)
88 /// @return RwLockWriteGuard<LinkedList<Box<dyn PciDeviceStructure>>> 写锁守卫
write(&self) -> RwLockWriteGuard<LinkedList<Box<dyn PciDeviceStructure>>>89 pub fn write(&self) -> RwLockWriteGuard<LinkedList<Box<dyn PciDeviceStructure>>> {
90 self.list.write()
91 }
92 /// @brief 获取链表中PCI结构体数目
93 /// @return usize 链表中PCI结构体数目
num(&self) -> usize94 pub fn num(&self) -> usize {
95 let list = self.list.read();
96 list.len()
97 }
98 /// @brief 添加Pci设备结构体到链表中
add(&self, device: Box<dyn PciDeviceStructure>)99 pub fn add(&self, device: Box<dyn PciDeviceStructure>) {
100 let mut list = self.list.write();
101 list.push_back(device);
102 }
103 }
104
105 /// @brief 在链表中寻找满足条件的PCI设备结构体并返回其可变引用
106 /// @param list 链表的写锁守卫
107 /// @param class_code 寄存器值
108 /// @param subclass 寄存器值,与class_code一起确定设备类型
109 /// @return Vec<&'a mut Box<(dyn PciDeviceStructure) 包含链表中所有满足条件的PCI结构体的可变引用的容器
get_pci_device_structure_mut<'a>( list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>, class_code: u8, subclass: u8, ) -> Vec<&'a mut Box<(dyn PciDeviceStructure)>>110 pub fn get_pci_device_structure_mut<'a>(
111 list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>,
112 class_code: u8,
113 subclass: u8,
114 ) -> Vec<&'a mut Box<(dyn PciDeviceStructure)>> {
115 let mut result = Vec::new();
116 for box_pci_device_structure in list.iter_mut() {
117 let common_header = (*box_pci_device_structure).common_header();
118 if (common_header.class_code == class_code) && (common_header.subclass == subclass) {
119 result.push(box_pci_device_structure);
120 }
121 }
122 result
123 }
124 /// @brief 在链表中寻找满足条件的PCI设备结构体并返回其不可变引用
125 /// @param list 链表的读锁守卫
126 /// @param class_code 寄存器值
127 /// @param subclass 寄存器值,与class_code一起确定设备类型
128 /// @return Vec<&'a Box<(dyn PciDeviceStructure) 包含链表中所有满足条件的PCI结构体的不可变引用的容器
get_pci_device_structure<'a>( list: &'a mut RwLockReadGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>, class_code: u8, subclass: u8, ) -> Vec<&'a Box<(dyn PciDeviceStructure)>>129 pub fn get_pci_device_structure<'a>(
130 list: &'a mut RwLockReadGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>,
131 class_code: u8,
132 subclass: u8,
133 ) -> Vec<&'a Box<(dyn PciDeviceStructure)>> {
134 let mut result = Vec::new();
135 for box_pci_device_structure in list.iter() {
136 let common_header = (*box_pci_device_structure).common_header();
137 if (common_header.class_code == class_code) && (common_header.subclass == subclass) {
138 result.push(box_pci_device_structure);
139 }
140 }
141 result
142 }
143
144 //Bar0寄存器的offset
145 const BAR0_OFFSET: u8 = 0x10;
146 //Status、Command寄存器的offset
147 const STATUS_COMMAND_OFFSET: u8 = 0x04;
148 /// ID for vendor-specific PCI capabilities.(Virtio Capabilities)
149 pub const PCI_CAP_ID_VNDR: u8 = 0x09;
150 pub const PCI_CAP_ID_MSI: u8 = 0x05;
151 pub const PCI_CAP_ID_MSIX: u8 = 0x11;
152 pub const PORT_PCI_CONFIG_ADDRESS: u16 = 0xcf8;
153 pub const PORT_PCI_CONFIG_DATA: u16 = 0xcfc;
154 // pci设备分组的id
155 pub type SegmentGroupNumber = u16; //理论上最多支持65535个Segment_Group
156
157 bitflags! {
158 /// The status register in PCI configuration space.
159 pub struct Status: u16 {
160 // Bits 0-2 are reserved.
161 /// The state of the device's INTx# signal.
162 const INTERRUPT_STATUS = 1 << 3;
163 /// The device has a linked list of capabilities.
164 const CAPABILITIES_LIST = 1 << 4;
165 /// The device is capabile of running at 66 MHz rather than 33 MHz.
166 const MHZ_66_CAPABLE = 1 << 5;
167 // Bit 6 is reserved.
168 /// The device can accept fast back-to-back transactions not from the same agent.
169 const FAST_BACK_TO_BACK_CAPABLE = 1 << 7;
170 /// The bus agent observed a parity error (if parity error handling is enabled).
171 const MASTER_DATA_PARITY_ERROR = 1 << 8;
172 // Bits 9-10 are DEVSEL timing.
173 /// A target device terminated a transaction with target-abort.
174 const SIGNALED_TARGET_ABORT = 1 << 11;
175 /// A master device transaction was terminated with target-abort.
176 const RECEIVED_TARGET_ABORT = 1 << 12;
177 /// A master device transaction was terminated with master-abort.
178 const RECEIVED_MASTER_ABORT = 1 << 13;
179 /// A device asserts SERR#.
180 const SIGNALED_SYSTEM_ERROR = 1 << 14;
181 /// The device detects a parity error, even if parity error handling is disabled.
182 const DETECTED_PARITY_ERROR = 1 << 15;
183 }
184 }
185
186 bitflags! {
187 /// The command register in PCI configuration space.
188 pub struct Command: u16 {
189 /// The device can respond to I/O Space accesses.
190 const IO_SPACE = 1 << 0;
191 /// The device can respond to Memory Space accesses.
192 const MEMORY_SPACE = 1 << 1;
193 /// The device can behave as a bus master.
194 const BUS_MASTER = 1 << 2;
195 /// The device can monitor Special Cycle operations.
196 const SPECIAL_CYCLES = 1 << 3;
197 /// The device can generate the Memory Write and Invalidate command.
198 const MEMORY_WRITE_AND_INVALIDATE_ENABLE = 1 << 4;
199 /// The device will snoop palette register data.
200 const VGA_PALETTE_SNOOP = 1 << 5;
201 /// The device should take its normal action when a parity error is detected.
202 const PARITY_ERROR_RESPONSE = 1 << 6;
203 // Bit 7 is reserved.
204 /// The SERR# driver is enabled.
205 const SERR_ENABLE = 1 << 8;
206 /// The device is allowed to generate fast back-to-back transactions.
207 const FAST_BACK_TO_BACK_ENABLE = 1 << 9;
208 /// Assertion of the device's INTx# signal is disabled.
209 const INTERRUPT_DISABLE = 1 << 10;
210 }
211 }
212
213 /// The type of a PCI device function header.
214 /// 标头类型/设备类型
215 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
216 pub enum HeaderType {
217 /// A normal PCI device.
218 Standard,
219 /// A PCI to PCI bridge.
220 PciPciBridge,
221 /// A PCI to CardBus bridge.
222 PciCardbusBridge,
223 /// Unrecognised header type.
224 Unrecognised(u8),
225 }
226 /// u8到HeaderType的转换
227 impl From<u8> for HeaderType {
from(value: u8) -> Self228 fn from(value: u8) -> Self {
229 match value {
230 0x00 => Self::Standard,
231 0x01 => Self::PciPciBridge,
232 0x02 => Self::PciCardbusBridge,
233 _ => Self::Unrecognised(value),
234 }
235 }
236 }
237 /// Pci可能触发的各种错误
238 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
239 pub enum PciError {
240 /// The device reported an invalid BAR type.
241 InvalidBarType,
242 CreateMmioError,
243 InvalidBusDeviceFunction,
244 SegmentNotFound,
245 McfgTableNotFound,
246 GetWrongHeader,
247 UnrecognisedHeaderType,
248 PciDeviceStructureTransformError,
249 PciIrqError(PciIrqError),
250 }
251 ///实现PciError的Display trait,使其可以直接输出
252 impl Display for PciError {
fmt(&self, f: &mut Formatter) -> fmt::Result253 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
254 match self {
255 Self::InvalidBarType => write!(f, "Invalid PCI BAR type."),
256 Self::CreateMmioError => write!(f, "Error occurred while creating mmio."),
257 Self::InvalidBusDeviceFunction => write!(f, "Found invalid BusDeviceFunction."),
258 Self::SegmentNotFound => write!(f, "Target segment not found"),
259 Self::McfgTableNotFound => write!(f, "ACPI MCFG Table not found"),
260 Self::GetWrongHeader => write!(f, "GetWrongHeader with vendor id 0xffff"),
261 Self::UnrecognisedHeaderType => write!(f, "Found device with unrecognised header type"),
262 Self::PciDeviceStructureTransformError => {
263 write!(f, "Found None When transform Pci device structure")
264 }
265 Self::PciIrqError(err) => write!(f, "Error occurred while setting irq :{:?}.", err),
266 }
267 }
268 }
269
270 /// trait类型Pci_Device_Structure表示pci设备,动态绑定三种具体设备类型:Pci_Device_Structure_General_Device、Pci_Device_Structure_Pci_to_Pci_Bridge、Pci_Device_Structure_Pci_to_Cardbus_Bridge
271 pub trait PciDeviceStructure: Send + Sync {
272 /// @brief 获取设备类型
273 /// @return HeaderType 设备类型
header_type(&self) -> HeaderType274 fn header_type(&self) -> HeaderType;
275 /// @brief 当其为standard设备时返回&Pci_Device_Structure_General_Device,其余情况返回None
276 #[inline(always)]
as_standard_device(&self) -> Option<&PciDeviceStructureGeneralDevice>277 fn as_standard_device(&self) -> Option<&PciDeviceStructureGeneralDevice> {
278 None
279 }
280 /// @brief 当其为pci to pci bridge设备时返回&Pci_Device_Structure_Pci_to_Pci_Bridge,其余情况返回None
281 #[inline(always)]
as_pci_to_pci_bridge_device(&self) -> Option<&PciDeviceStructurePciToPciBridge>282 fn as_pci_to_pci_bridge_device(&self) -> Option<&PciDeviceStructurePciToPciBridge> {
283 None
284 }
285 /// @brief 当其为pci to cardbus bridge设备时返回&Pci_Device_Structure_Pci_to_Cardbus_Bridge,其余情况返回None
286 #[inline(always)]
as_pci_to_carbus_bridge_device(&self) -> Option<&PciDeviceStructurePciToCardbusBridge>287 fn as_pci_to_carbus_bridge_device(&self) -> Option<&PciDeviceStructurePciToCardbusBridge> {
288 None
289 }
290 /// @brief 获取Pci设备共有的common_header
291 /// @return 返回其不可变引用
common_header(&self) -> &PciDeviceStructureHeader292 fn common_header(&self) -> &PciDeviceStructureHeader;
293 /// @brief 当其为standard设备时返回&mut Pci_Device_Structure_General_Device,其余情况返回None
294 #[inline(always)]
as_standard_device_mut(&mut self) -> Option<&mut PciDeviceStructureGeneralDevice>295 fn as_standard_device_mut(&mut self) -> Option<&mut PciDeviceStructureGeneralDevice> {
296 None
297 }
298 /// @brief 当其为pci to pci bridge设备时返回&mut Pci_Device_Structure_Pci_to_Pci_Bridge,其余情况返回None
299 #[inline(always)]
as_pci_to_pci_bridge_device_mut(&mut self) -> Option<&mut PciDeviceStructurePciToPciBridge>300 fn as_pci_to_pci_bridge_device_mut(&mut self) -> Option<&mut PciDeviceStructurePciToPciBridge> {
301 None
302 }
303 /// @brief 当其为pci to cardbus bridge设备时返回&mut Pci_Device_Structure_Pci_to_Cardbus_Bridge,其余情况返回None
304 #[inline(always)]
as_pci_to_carbus_bridge_device_mut( &mut self, ) -> Option<&mut PciDeviceStructurePciToCardbusBridge>305 fn as_pci_to_carbus_bridge_device_mut(
306 &mut self,
307 ) -> Option<&mut PciDeviceStructurePciToCardbusBridge> {
308 None
309 }
310 /// @brief 返回迭代器,遍历capabilities
capabilities(&self) -> Option<CapabilityIterator>311 fn capabilities(&self) -> Option<CapabilityIterator> {
312 None
313 }
314 /// @brief 获取Status、Command寄存器的值
status_command(&self) -> (Status, Command)315 fn status_command(&self) -> (Status, Command) {
316 let common_header = self.common_header();
317 let status = Status::from_bits_truncate(common_header.status);
318 let command = Command::from_bits_truncate(common_header.command);
319 (status, command)
320 }
321 /// @brief 设置Command寄存器的值
set_command(&mut self, command: Command)322 fn set_command(&mut self, command: Command) {
323 let common_header = self.common_header_mut();
324 let command = command.bits();
325 common_header.command = command;
326 PciArch::write_config(
327 &common_header.bus_device_function,
328 STATUS_COMMAND_OFFSET,
329 command as u32,
330 );
331 }
332 /// @brief 获取Pci设备共有的common_header
333 /// @return 返回其可变引用
common_header_mut(&mut self) -> &mut PciDeviceStructureHeader334 fn common_header_mut(&mut self) -> &mut PciDeviceStructureHeader;
335
336 /// @brief 读取standard设备的bar寄存器,映射后将结果加入结构体的standard_device_bar变量
337 /// @return 只有standard设备才返回成功或者错误,其余返回None
338 #[inline(always)]
bar_ioremap(&mut self) -> Option<Result<u8, PciError>>339 fn bar_ioremap(&mut self) -> Option<Result<u8, PciError>> {
340 None
341 }
342 /// @brief 获取PCI设备的bar寄存器的引用
343 /// @return
344 #[inline(always)]
bar(&mut self) -> Option<&PciStandardDeviceBar>345 fn bar(&mut self) -> Option<&PciStandardDeviceBar> {
346 None
347 }
348 /// @brief 通过设置该pci设备的command
enable_master(&mut self)349 fn enable_master(&mut self) {
350 self.set_command(Command::IO_SPACE | Command::MEMORY_SPACE | Command::BUS_MASTER);
351 }
352 /// @brief 寻找设备的msix空间的offset
msix_capability_offset(&self) -> Option<u8>353 fn msix_capability_offset(&self) -> Option<u8> {
354 for capability in self.capabilities()? {
355 if capability.id == PCI_CAP_ID_MSIX {
356 return Some(capability.offset);
357 }
358 }
359 None
360 }
361 /// @brief 寻找设备的msi空间的offset
msi_capability_offset(&self) -> Option<u8>362 fn msi_capability_offset(&self) -> Option<u8> {
363 for capability in self.capabilities()? {
364 if capability.id == PCI_CAP_ID_MSI {
365 return Some(capability.offset);
366 }
367 }
368 None
369 }
370 /// @brief 返回结构体中的irq_type的可变引用
irq_type_mut(&mut self) -> Option<&mut IrqType>371 fn irq_type_mut(&mut self) -> Option<&mut IrqType>;
372 /// @brief 返回结构体中的irq_vector的可变引用
irq_vector_mut(&mut self) -> Option<&mut Vec<u16>>373 fn irq_vector_mut(&mut self) -> Option<&mut Vec<u16>>;
374 }
375
376 /// Pci_Device_Structure_Header PCI设备结构体共有的头部
377 #[derive(Clone, Debug)]
378 pub struct PciDeviceStructureHeader {
379 // ==== busdevicefunction变量表示该结构体所处的位置
380 pub bus_device_function: BusDeviceFunction,
381 pub vendor_id: u16, // 供应商ID 0xffff是一个无效值,在读取访问不存在的设备的配置空间寄存器时返回
382 pub device_id: u16, // 设备ID,标志特定设备
383 pub command: u16, // 提供对设备生成和响应pci周期的能力的控制 向该寄存器写入0时,设备与pci总线断开除配置空间访问以外的所有连接
384 pub status: u16, // 用于记录pci总线相关时间的状态信息寄存器
385 pub revision_id: u8, // 修订ID,指定特定设备的修订标志符
386 pub prog_if: u8, // 编程接口字节,一个只读寄存器,指定设备具有的寄存器级别的编程接口(如果有的话)
387 pub subclass: u8, // 子类。指定设备执行的特定功能的只读寄存器
388 pub class_code: u8, // 类代码,一个只读寄存器,指定设备执行的功能类型
389 pub cache_line_size: u8, // 缓存线大小:以 32 位为单位指定系统缓存线大小。设备可以限制它可以支持的缓存线大小的数量,如果不支持的值写入该字段,设备将表现得好像写入了 0 值
390 pub latency_timer: u8, // 延迟计时器:以 PCI 总线时钟为单位指定延迟计时器。
391 pub header_type: u8, // 标头类型 a value of 0x0 specifies a general device, a value of 0x1 specifies a PCI-to-PCI bridge, and a value of 0x2 specifies a CardBus bridge. If bit 7 of this register is set, the device has multiple functions; otherwise, it is a single function device.
392 pub bist: u8, // Represents that status and allows control of a devices BIST (built-in self test).
393 // Here is the layout of the BIST register:
394 // | bit7 | bit6 | Bits 5-4 | Bits 3-0 |
395 // | BIST Capable | Start BIST | Reserved | Completion Code |
396 // for more details, please visit https://wiki.osdev.org/PCI
397 }
398
399 /// Pci_Device_Structure_General_Device PCI标准设备结构体
400 #[derive(Clone, Debug)]
401 pub struct PciDeviceStructureGeneralDevice {
402 pub common_header: PciDeviceStructureHeader,
403 // 中断结构体,包括legacy,msi,msix三种情况
404 pub irq_type: IrqType,
405 // 使用的中断号的vec集合
406 pub irq_vector: Vec<u16>,
407 pub standard_device_bar: PciStandardDeviceBar,
408 pub cardbus_cis_pointer: u32, // 指向卡信息结构,供在 CardBus 和 PCI 之间共享芯片的设备使用。
409 pub subsystem_vendor_id: u16,
410 pub subsystem_id: u16,
411 pub expansion_rom_base_address: u32,
412 pub capabilities_pointer: u8,
413 pub reserved0: u8,
414 pub reserved1: u16,
415 pub reserved2: u32,
416 pub interrupt_line: u8, // 指定设备的中断引脚连接到系统中断控制器的哪个输入,并由任何使用中断引脚的设备实现。对于 x86 架构,此寄存器对应于 PIC IRQ 编号 0-15(而不是 I/O APIC IRQ 编号),并且值0xFF定义为无连接。
417 pub interrupt_pin: u8, // 指定设备使用的中断引脚。其中值为0x1INTA#、0x2INTB#、0x3INTC#、0x4INTD#,0x0表示设备不使用中断引脚。
418 pub min_grant: u8, // 一个只读寄存器,用于指定设备所需的突发周期长度(以 1/4 微秒为单位)(假设时钟速率为 33 MHz)
419 pub max_latency: u8, // 一个只读寄存器,指定设备需要多长时间访问一次 PCI 总线(以 1/4 微秒为单位)。
420 }
421 impl PciDeviceStructure for PciDeviceStructureGeneralDevice {
422 #[inline(always)]
header_type(&self) -> HeaderType423 fn header_type(&self) -> HeaderType {
424 HeaderType::Standard
425 }
426 #[inline(always)]
as_standard_device(&self) -> Option<&PciDeviceStructureGeneralDevice>427 fn as_standard_device(&self) -> Option<&PciDeviceStructureGeneralDevice> {
428 Some(self)
429 }
430 #[inline(always)]
as_standard_device_mut(&mut self) -> Option<&mut PciDeviceStructureGeneralDevice>431 fn as_standard_device_mut(&mut self) -> Option<&mut PciDeviceStructureGeneralDevice> {
432 Some(self)
433 }
434 #[inline(always)]
common_header(&self) -> &PciDeviceStructureHeader435 fn common_header(&self) -> &PciDeviceStructureHeader {
436 &self.common_header
437 }
438 #[inline(always)]
common_header_mut(&mut self) -> &mut PciDeviceStructureHeader439 fn common_header_mut(&mut self) -> &mut PciDeviceStructureHeader {
440 &mut self.common_header
441 }
capabilities(&self) -> Option<CapabilityIterator>442 fn capabilities(&self) -> Option<CapabilityIterator> {
443 Some(CapabilityIterator {
444 bus_device_function: self.common_header.bus_device_function,
445 next_capability_offset: Some(self.capabilities_pointer),
446 })
447 }
bar_ioremap(&mut self) -> Option<Result<u8, PciError>>448 fn bar_ioremap(&mut self) -> Option<Result<u8, PciError>> {
449 let common_header = &self.common_header;
450 match pci_bar_init(common_header.bus_device_function) {
451 Ok(bar) => {
452 self.standard_device_bar = bar;
453 Some(Ok(0))
454 }
455 Err(e) => Some(Err(e)),
456 }
457 }
bar(&mut self) -> Option<&PciStandardDeviceBar>458 fn bar(&mut self) -> Option<&PciStandardDeviceBar> {
459 Some(&self.standard_device_bar)
460 }
461 #[inline(always)]
irq_type_mut(&mut self) -> Option<&mut IrqType>462 fn irq_type_mut(&mut self) -> Option<&mut IrqType> {
463 Some(&mut self.irq_type)
464 }
465 #[inline(always)]
irq_vector_mut(&mut self) -> Option<&mut Vec<u16>>466 fn irq_vector_mut(&mut self) -> Option<&mut Vec<u16>> {
467 Some(&mut self.irq_vector)
468 }
469 }
470
471 /// Pci_Device_Structure_Pci_to_Pci_Bridge pci-to-pci桥设备结构体
472 #[derive(Clone, Debug)]
473 pub struct PciDeviceStructurePciToPciBridge {
474 pub common_header: PciDeviceStructureHeader,
475 // 中断结构体,包括legacy,msi,msix三种情况
476 pub irq_type: IrqType,
477 // 使用的中断号的vec集合
478 pub irq_vector: Vec<u16>,
479 pub bar0: u32,
480 pub bar1: u32,
481 pub primary_bus_number: u8,
482 pub secondary_bus_number: u8,
483 pub subordinate_bus_number: u8,
484 pub secondary_latency_timer: u8,
485 pub io_base: u8,
486 pub io_limit: u8,
487 pub secondary_status: u16,
488 pub memory_base: u16,
489 pub memory_limit: u16,
490 pub prefetchable_memory_base: u16,
491 pub prefetchable_memory_limit: u16,
492 pub prefetchable_base_upper_32_bits: u32,
493 pub prefetchable_limit_upper_32_bits: u32,
494 pub io_base_upper_16_bits: u16,
495 pub io_limit_upper_16_bits: u16,
496 pub capability_pointer: u8,
497 pub reserved0: u8,
498 pub reserved1: u16,
499 pub expansion_rom_base_address: u32,
500 pub interrupt_line: u8,
501 pub interrupt_pin: u8,
502 pub bridge_control: u16,
503 }
504 impl PciDeviceStructure for PciDeviceStructurePciToPciBridge {
505 #[inline(always)]
header_type(&self) -> HeaderType506 fn header_type(&self) -> HeaderType {
507 HeaderType::PciPciBridge
508 }
509 #[inline(always)]
as_pci_to_pci_bridge_device(&self) -> Option<&PciDeviceStructurePciToPciBridge>510 fn as_pci_to_pci_bridge_device(&self) -> Option<&PciDeviceStructurePciToPciBridge> {
511 Some(self)
512 }
513 #[inline(always)]
as_pci_to_pci_bridge_device_mut(&mut self) -> Option<&mut PciDeviceStructurePciToPciBridge>514 fn as_pci_to_pci_bridge_device_mut(&mut self) -> Option<&mut PciDeviceStructurePciToPciBridge> {
515 Some(self)
516 }
517 #[inline(always)]
common_header(&self) -> &PciDeviceStructureHeader518 fn common_header(&self) -> &PciDeviceStructureHeader {
519 &self.common_header
520 }
521 #[inline(always)]
common_header_mut(&mut self) -> &mut PciDeviceStructureHeader522 fn common_header_mut(&mut self) -> &mut PciDeviceStructureHeader {
523 &mut self.common_header
524 }
525 #[inline(always)]
irq_type_mut(&mut self) -> Option<&mut IrqType>526 fn irq_type_mut(&mut self) -> Option<&mut IrqType> {
527 Some(&mut self.irq_type)
528 }
529 #[inline(always)]
irq_vector_mut(&mut self) -> Option<&mut Vec<u16>>530 fn irq_vector_mut(&mut self) -> Option<&mut Vec<u16>> {
531 Some(&mut self.irq_vector)
532 }
533 }
534 /// Pci_Device_Structure_Pci_to_Cardbus_Bridge Pci_to_Cardbus桥设备结构体
535 #[derive(Clone, Debug)]
536 pub struct PciDeviceStructurePciToCardbusBridge {
537 pub common_header: PciDeviceStructureHeader,
538 pub cardbus_socket_ex_ca_base_address: u32,
539 pub offset_of_capabilities_list: u8,
540 pub reserved: u8,
541 pub secondary_status: u16,
542 pub pci_bus_number: u8,
543 pub card_bus_bus_number: u8,
544 pub subordinate_bus_number: u8,
545 pub card_bus_latency_timer: u8,
546 pub memory_base_address0: u32,
547 pub memory_limit0: u32,
548 pub memory_base_address1: u32,
549 pub memory_limit1: u32,
550 pub io_base_address0: u32,
551 pub io_limit0: u32,
552 pub io_base_address1: u32,
553 pub io_limit1: u32,
554 pub interrupt_line: u8,
555 pub interrupt_pin: u8,
556 pub bridge_control: u16,
557 pub subsystem_device_id: u16,
558 pub subsystem_vendor_id: u16,
559 pub pc_card_legacy_mode_base_address_16_bit: u32,
560 }
561 impl PciDeviceStructure for PciDeviceStructurePciToCardbusBridge {
562 #[inline(always)]
header_type(&self) -> HeaderType563 fn header_type(&self) -> HeaderType {
564 HeaderType::PciCardbusBridge
565 }
566 #[inline(always)]
as_pci_to_carbus_bridge_device(&self) -> Option<&PciDeviceStructurePciToCardbusBridge>567 fn as_pci_to_carbus_bridge_device(&self) -> Option<&PciDeviceStructurePciToCardbusBridge> {
568 Some(&self)
569 }
570 #[inline(always)]
as_pci_to_carbus_bridge_device_mut( &mut self, ) -> Option<&mut PciDeviceStructurePciToCardbusBridge>571 fn as_pci_to_carbus_bridge_device_mut(
572 &mut self,
573 ) -> Option<&mut PciDeviceStructurePciToCardbusBridge> {
574 Some(self)
575 }
576 #[inline(always)]
common_header(&self) -> &PciDeviceStructureHeader577 fn common_header(&self) -> &PciDeviceStructureHeader {
578 &self.common_header
579 }
580 #[inline(always)]
common_header_mut(&mut self) -> &mut PciDeviceStructureHeader581 fn common_header_mut(&mut self) -> &mut PciDeviceStructureHeader {
582 &mut self.common_header
583 }
584 #[inline(always)]
irq_type_mut(&mut self) -> Option<&mut IrqType>585 fn irq_type_mut(&mut self) -> Option<&mut IrqType> {
586 None
587 }
588 #[inline(always)]
irq_vector_mut(&mut self) -> Option<&mut Vec<u16>>589 fn irq_vector_mut(&mut self) -> Option<&mut Vec<u16>> {
590 None
591 }
592 }
593
594 /// 代表一个PCI segement greoup.
595 #[derive(Copy, Clone, Debug, PartialEq)]
596 pub struct PciRoot {
597 pub physical_address_base: u64, //物理地址,acpi获取
598 pub mmio_base: Option<*mut u32>, //映射后的虚拟地址,为方便访问数据这里转化成指针
599 pub segement_group_number: SegmentGroupNumber, //segement greoup的id
600 pub bus_begin: u8, //该分组中的最小bus
601 pub bus_end: u8, //该分组中的最大bus
602 }
603 ///线程间共享需要,该结构体只需要在初始化时写入数据,无需读写锁保证线程安全
604 unsafe impl Send for PciRoot {}
605 unsafe impl Sync for PciRoot {}
606 ///实现PciRoot的Display trait,自定义输出
607 impl Display for PciRoot {
fmt(&self, f: &mut Formatter<'_>) -> fmt::Result608 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
609 write!(
610 f,
611 "PCI Root with segement:{}, bus begin at {}, bus end at {}, physical address at {:#x},mapped at {:#x}",
612 self.segement_group_number, self.bus_begin, self.bus_end, self.physical_address_base, self.mmio_base.unwrap() as usize
613 )
614 }
615 }
616
617 impl PciRoot {
618 /// @brief 初始化结构体,获取ecam root所在物理地址后map到虚拟地址,再将该虚拟地址加入mmio_base变量
619 /// @return 成功返回结果,错误返回错误类型
new(segment_group_number: SegmentGroupNumber) -> Result<Self, PciError>620 pub fn new(segment_group_number: SegmentGroupNumber) -> Result<Self, PciError> {
621 let mut pci_root = PciArch::ecam_root(segment_group_number)?;
622 pci_root.map()?;
623 Ok(pci_root)
624 }
625 /// @brief 完成物理地址到虚拟地址的映射,并将虚拟地址加入mmio_base变量
626 /// @return 返回错误或Ok(0)
map(&mut self) -> Result<u8, PciError>627 fn map(&mut self) -> Result<u8, PciError> {
628 //kdebug!("bus_begin={},bus_end={}", self.bus_begin,self.bus_end);
629 let bus_number = (self.bus_end - self.bus_begin) as u32 + 1;
630 let bus_number_double = (bus_number - 1) / 2 + 1; //一个bus占据1MB空间,计算全部bus占据空间相对于2MB空间的个数
631 let mut virtaddress: u64 = 0;
632 let vaddr_ptr = &mut virtaddress as *mut u64;
633 let mut virtsize: u64 = 0;
634 let virtsize_ptr = &mut virtsize as *mut u64;
635 let size = bus_number_double * PAGE_2M_SIZE;
636 unsafe {
637 if let Err(_) = mmio_pool().create_mmio(
638 size as usize,
639 (VM_IO | VM_DONTCOPY) as u64,
640 vaddr_ptr,
641 virtsize_ptr,
642 ) {
643 kerror!("Create mmio failed when initing ecam");
644 return Err(PciError::CreateMmioError);
645 };
646
647 //kdebug!("virtaddress={:#x},virtsize={:#x}",virtaddress,virtsize);
648 let vaddr = VirtAddr::new(virtaddress as usize);
649 let paddr = PhysAddr::new(self.physical_address_base as usize);
650 // kdebug!("pci root: map: vaddr={vaddr:?}, paddr={paddr:?}, size={size}");
651 let page_flags = PageFlags::mmio_flags();
652 let mut kernel_mapper = KernelMapper::lock();
653 // todo: 添加错误处理代码。因为内核映射器可能是只读的,所以可能会出错
654 assert!(kernel_mapper
655 .map_phys_with_size(vaddr, paddr, size as usize, page_flags, true)
656 .is_ok());
657 drop(kernel_mapper);
658 }
659 self.mmio_base = Some(virtaddress as *mut u32);
660 Ok(0)
661 }
662 /// @brief 获得要操作的寄存器相对于mmio_offset的偏移量
663 /// @param bus_device_function 在同一个group中pci设备的唯一标识符
664 /// @param register_offset 寄存器在设备中的offset
665 /// @return u32 要操作的寄存器相对于mmio_offset的偏移量
cam_offset(&self, bus_device_function: BusDeviceFunction, register_offset: u16) -> u32666 fn cam_offset(&self, bus_device_function: BusDeviceFunction, register_offset: u16) -> u32 {
667 assert!(bus_device_function.valid());
668 let bdf = ((bus_device_function.bus - self.bus_begin) as u32) << 8
669 | (bus_device_function.device as u32) << 3
670 | bus_device_function.function as u32;
671 let address = bdf << 12 | register_offset as u32;
672 // Ensure that address is word-aligned.
673 assert!(address & 0x3 == 0);
674 address
675 }
676 /// @brief 通过bus_device_function和offset读取相应位置寄存器的值(32位)
677 /// @param bus_device_function 在同一个group中pci设备的唯一标识符
678 /// @param register_offset 寄存器在设备中的offset
679 /// @return u32 寄存器读值结果
read_config(&self, bus_device_function: BusDeviceFunction, register_offset: u16) -> u32680 pub fn read_config(&self, bus_device_function: BusDeviceFunction, register_offset: u16) -> u32 {
681 let address = self.cam_offset(bus_device_function, register_offset);
682 unsafe {
683 // Right shift to convert from byte offset to word offset.
684 (self.mmio_base.unwrap().add((address >> 2) as usize)).read_volatile()
685 }
686 }
687
688 /// @brief 通过bus_device_function和offset写入相应位置寄存器值(32位)
689 /// @param bus_device_function 在同一个group中pci设备的唯一标识符
690 /// @param register_offset 寄存器在设备中的offset
691 /// @param data 要写入的值
write_config( &mut self, bus_device_function: BusDeviceFunction, register_offset: u16, data: u32, )692 pub fn write_config(
693 &mut self,
694 bus_device_function: BusDeviceFunction,
695 register_offset: u16,
696 data: u32,
697 ) {
698 let address = self.cam_offset(bus_device_function, register_offset);
699 // Safe because both the `mmio_base` and the address offset are properly aligned, and the
700 // resulting pointer is within the MMIO range of the CAM.
701 unsafe {
702 // Right shift to convert from byte offset to word offset.
703 (self.mmio_base.unwrap().add((address >> 2) as usize)).write_volatile(data)
704 }
705 }
706 /// @brief 返回迭代器,遍历pcie设备的external_capabilities
external_capabilities( &self, bus_device_function: BusDeviceFunction, ) -> ExternalCapabilityIterator707 pub fn external_capabilities(
708 &self,
709 bus_device_function: BusDeviceFunction,
710 ) -> ExternalCapabilityIterator {
711 ExternalCapabilityIterator {
712 root: self,
713 bus_device_function,
714 next_capability_offset: Some(0x100),
715 }
716 }
717 }
718 /// Gets the capabilities 'pointer' for the device function, if any.
719 /// @brief 获取第一个capability 的offset
720 /// @param bus_device_function PCI设备的唯一标识
721 /// @return Option<u8> offset
capabilities_offset(bus_device_function: BusDeviceFunction) -> Option<u8>722 pub fn capabilities_offset(bus_device_function: BusDeviceFunction) -> Option<u8> {
723 let result = PciArch::read_config(&bus_device_function, STATUS_COMMAND_OFFSET);
724 let status: Status = Status::from_bits_truncate((result >> 16) as u16);
725 if status.contains(Status::CAPABILITIES_LIST) {
726 let cap_pointer = PciArch::read_config(&bus_device_function, 0x34) as u8 & 0xFC;
727 Some(cap_pointer)
728 } else {
729 None
730 }
731 }
732
733 /// @brief 读取pci设备头部
734 /// @param bus_device_function PCI设备的唯一标识
735 /// @param add_to_list 是否添加到链表
736 /// @return 返回的header(trait 类型)
pci_read_header( bus_device_function: BusDeviceFunction, add_to_list: bool, ) -> Result<Box<dyn PciDeviceStructure>, PciError>737 fn pci_read_header(
738 bus_device_function: BusDeviceFunction,
739 add_to_list: bool,
740 ) -> Result<Box<dyn PciDeviceStructure>, PciError> {
741 // 先读取公共header
742 let result = PciArch::read_config(&bus_device_function, 0x00);
743 let vendor_id = result as u16;
744 let device_id = (result >> 16) as u16;
745
746 let result = PciArch::read_config(&bus_device_function, 0x04);
747 let command = result as u16;
748 let status = (result >> 16) as u16;
749
750 let result = PciArch::read_config(&bus_device_function, 0x08);
751 let revision_id = result as u8;
752 let prog_if = (result >> 8) as u8;
753 let subclass = (result >> 16) as u8;
754 let class_code = (result >> 24) as u8;
755
756 let result = PciArch::read_config(&bus_device_function, 0x0c);
757 let cache_line_size = result as u8;
758 let latency_timer = (result >> 8) as u8;
759 let header_type = (result >> 16) as u8;
760 let bist = (result >> 24) as u8;
761 if vendor_id == 0xffff {
762 return Err(PciError::GetWrongHeader);
763 }
764 let header = PciDeviceStructureHeader {
765 bus_device_function,
766 vendor_id,
767 device_id,
768 command,
769 status,
770 revision_id,
771 prog_if,
772 subclass,
773 class_code,
774 cache_line_size,
775 latency_timer,
776 header_type,
777 bist,
778 };
779 match HeaderType::from(header_type & 0x7f) {
780 HeaderType::Standard => {
781 let general_device = pci_read_general_device_header(header, &bus_device_function);
782 let box_general_device = Box::new(general_device);
783 let box_general_device_clone = box_general_device.clone();
784 if add_to_list {
785 PCI_DEVICE_LINKEDLIST.add(box_general_device);
786 }
787 Ok(box_general_device_clone)
788 }
789 HeaderType::PciPciBridge => {
790 let pci_to_pci_bridge = pci_read_pci_to_pci_bridge_header(header, &bus_device_function);
791 let box_pci_to_pci_bridge = Box::new(pci_to_pci_bridge);
792 let box_pci_to_pci_bridge_clone = box_pci_to_pci_bridge.clone();
793 if add_to_list {
794 PCI_DEVICE_LINKEDLIST.add(box_pci_to_pci_bridge);
795 }
796 Ok(box_pci_to_pci_bridge_clone)
797 }
798 HeaderType::PciCardbusBridge => {
799 let pci_cardbus_bridge =
800 pci_read_pci_to_cardbus_bridge_header(header, &bus_device_function);
801 let box_pci_cardbus_bridge = Box::new(pci_cardbus_bridge);
802 let box_pci_cardbus_bridge_clone = box_pci_cardbus_bridge.clone();
803 if add_to_list {
804 PCI_DEVICE_LINKEDLIST.add(box_pci_cardbus_bridge);
805 }
806 Ok(box_pci_cardbus_bridge_clone)
807 }
808 HeaderType::Unrecognised(_) => Err(PciError::UnrecognisedHeaderType),
809 }
810 }
811
812 /// @brief 读取type为0x0的pci设备的header
813 /// 本函数只应被 pci_read_header()调用
814 /// @param common_header 共有头部
815 /// @param bus_device_function PCI设备的唯一标识
816 /// @return Pci_Device_Structure_General_Device 标准设备头部
pci_read_general_device_header( common_header: PciDeviceStructureHeader, bus_device_function: &BusDeviceFunction, ) -> PciDeviceStructureGeneralDevice817 fn pci_read_general_device_header(
818 common_header: PciDeviceStructureHeader,
819 bus_device_function: &BusDeviceFunction,
820 ) -> PciDeviceStructureGeneralDevice {
821 let standard_device_bar = PciStandardDeviceBar::default();
822 let cardbus_cis_pointer = PciArch::read_config(bus_device_function, 0x28);
823
824 let result = PciArch::read_config(bus_device_function, 0x2c);
825 let subsystem_vendor_id = result as u16;
826 let subsystem_id = (result >> 16) as u16;
827
828 let expansion_rom_base_address = PciArch::read_config(bus_device_function, 0x30);
829
830 let result = PciArch::read_config(bus_device_function, 0x34);
831 let capabilities_pointer = result as u8;
832 let reserved0 = (result >> 8) as u8;
833 let reserved1 = (result >> 16) as u16;
834
835 let reserved2 = PciArch::read_config(bus_device_function, 0x38);
836
837 let result = PciArch::read_config(bus_device_function, 0x3c);
838 let interrupt_line = result as u8;
839 let interrupt_pin = (result >> 8) as u8;
840 let min_grant = (result >> 16) as u8;
841 let max_latency = (result >> 24) as u8;
842 PciDeviceStructureGeneralDevice {
843 common_header,
844 irq_type: IrqType::Unused,
845 irq_vector: Vec::new(),
846 standard_device_bar,
847 cardbus_cis_pointer,
848 subsystem_vendor_id,
849 subsystem_id,
850 expansion_rom_base_address,
851 capabilities_pointer,
852 reserved0,
853 reserved1,
854 reserved2,
855 interrupt_line,
856 interrupt_pin,
857 min_grant,
858 max_latency,
859 }
860 }
861
862 /// @brief 读取type为0x1的pci设备的header
863 /// 本函数只应被 pci_read_header()调用
864 /// @param common_header 共有头部
865 /// @param bus_device_function PCI设备的唯一标识
866 /// @return Pci_Device_Structure_Pci_to_Pci_Bridge pci-to-pci 桥设备头部
pci_read_pci_to_pci_bridge_header( common_header: PciDeviceStructureHeader, bus_device_function: &BusDeviceFunction, ) -> PciDeviceStructurePciToPciBridge867 fn pci_read_pci_to_pci_bridge_header(
868 common_header: PciDeviceStructureHeader,
869 bus_device_function: &BusDeviceFunction,
870 ) -> PciDeviceStructurePciToPciBridge {
871 let bar0 = PciArch::read_config(bus_device_function, 0x10);
872 let bar1 = PciArch::read_config(bus_device_function, 0x14);
873
874 let result = PciArch::read_config(bus_device_function, 0x18);
875
876 let primary_bus_number = result as u8;
877 let secondary_bus_number = (result >> 8) as u8;
878 let subordinate_bus_number = (result >> 16) as u8;
879 let secondary_latency_timer = (result >> 24) as u8;
880
881 let result = PciArch::read_config(bus_device_function, 0x1c);
882 let io_base = result as u8;
883 let io_limit = (result >> 8) as u8;
884 let secondary_status = (result >> 16) as u16;
885
886 let result = PciArch::read_config(bus_device_function, 0x20);
887 let memory_base = result as u16;
888 let memory_limit = (result >> 16) as u16;
889
890 let result = PciArch::read_config(bus_device_function, 0x24);
891 let prefetchable_memory_base = result as u16;
892 let prefetchable_memory_limit = (result >> 16) as u16;
893
894 let prefetchable_base_upper_32_bits = PciArch::read_config(bus_device_function, 0x28);
895 let prefetchable_limit_upper_32_bits = PciArch::read_config(bus_device_function, 0x2c);
896
897 let result = PciArch::read_config(bus_device_function, 0x30);
898 let io_base_upper_16_bits = result as u16;
899 let io_limit_upper_16_bits = (result >> 16) as u16;
900
901 let result = PciArch::read_config(bus_device_function, 0x34);
902 let capability_pointer = result as u8;
903 let reserved0 = (result >> 8) as u8;
904 let reserved1 = (result >> 16) as u16;
905
906 let expansion_rom_base_address = PciArch::read_config(bus_device_function, 0x38);
907
908 let result = PciArch::read_config(bus_device_function, 0x3c);
909 let interrupt_line = result as u8;
910 let interrupt_pin = (result >> 8) as u8;
911 let bridge_control = (result >> 16) as u16;
912 PciDeviceStructurePciToPciBridge {
913 common_header,
914 irq_type: IrqType::Unused,
915 irq_vector: Vec::new(),
916 bar0,
917 bar1,
918 primary_bus_number,
919 secondary_bus_number,
920 subordinate_bus_number,
921 secondary_latency_timer,
922 io_base,
923 io_limit,
924 secondary_status,
925 memory_base,
926 memory_limit,
927 prefetchable_memory_base,
928 prefetchable_memory_limit,
929 prefetchable_base_upper_32_bits,
930 prefetchable_limit_upper_32_bits,
931 io_base_upper_16_bits,
932 io_limit_upper_16_bits,
933 capability_pointer,
934 reserved0,
935 reserved1,
936 expansion_rom_base_address,
937 interrupt_line,
938 interrupt_pin,
939 bridge_control,
940 }
941 }
942
943 /// @brief 读取type为0x2的pci设备的header
944 /// 本函数只应被 pci_read_header()调用
945 /// @param common_header 共有头部
946 /// @param bus_device_function PCI设备的唯一标识
947 /// @return Pci_Device_Structure_Pci_to_Cardbus_Bridge pci-to-cardbus 桥设备头部
pci_read_pci_to_cardbus_bridge_header( common_header: PciDeviceStructureHeader, busdevicefunction: &BusDeviceFunction, ) -> PciDeviceStructurePciToCardbusBridge948 fn pci_read_pci_to_cardbus_bridge_header(
949 common_header: PciDeviceStructureHeader,
950 busdevicefunction: &BusDeviceFunction,
951 ) -> PciDeviceStructurePciToCardbusBridge {
952 let cardbus_socket_ex_ca_base_address = PciArch::read_config(busdevicefunction, 0x10);
953
954 let result = PciArch::read_config(busdevicefunction, 0x14);
955 let offset_of_capabilities_list = result as u8;
956 let reserved = (result >> 8) as u8;
957 let secondary_status = (result >> 16) as u16;
958
959 let result = PciArch::read_config(busdevicefunction, 0x18);
960 let pci_bus_number = result as u8;
961 let card_bus_bus_number = (result >> 8) as u8;
962 let subordinate_bus_number = (result >> 16) as u8;
963 let card_bus_latency_timer = (result >> 24) as u8;
964
965 let memory_base_address0 = PciArch::read_config(busdevicefunction, 0x1c);
966 let memory_limit0 = PciArch::read_config(busdevicefunction, 0x20);
967 let memory_base_address1 = PciArch::read_config(busdevicefunction, 0x24);
968 let memory_limit1 = PciArch::read_config(busdevicefunction, 0x28);
969
970 let io_base_address0 = PciArch::read_config(busdevicefunction, 0x2c);
971 let io_limit0 = PciArch::read_config(busdevicefunction, 0x30);
972 let io_base_address1 = PciArch::read_config(busdevicefunction, 0x34);
973 let io_limit1 = PciArch::read_config(busdevicefunction, 0x38);
974 let result = PciArch::read_config(busdevicefunction, 0x3c);
975 let interrupt_line = result as u8;
976 let interrupt_pin = (result >> 8) as u8;
977 let bridge_control = (result >> 16) as u16;
978
979 let result = PciArch::read_config(busdevicefunction, 0x40);
980 let subsystem_device_id = result as u16;
981 let subsystem_vendor_id = (result >> 16) as u16;
982
983 let pc_card_legacy_mode_base_address_16_bit = PciArch::read_config(busdevicefunction, 0x44);
984 PciDeviceStructurePciToCardbusBridge {
985 common_header,
986 cardbus_socket_ex_ca_base_address,
987 offset_of_capabilities_list,
988 reserved,
989 secondary_status,
990 pci_bus_number,
991 card_bus_bus_number,
992 subordinate_bus_number,
993 card_bus_latency_timer,
994 memory_base_address0,
995 memory_limit0,
996 memory_base_address1,
997 memory_limit1,
998 io_base_address0,
999 io_limit0,
1000 io_base_address1,
1001 io_limit1,
1002 interrupt_line,
1003 interrupt_pin,
1004 bridge_control,
1005 subsystem_device_id,
1006 subsystem_vendor_id,
1007 pc_card_legacy_mode_base_address_16_bit,
1008 }
1009 }
1010
1011 /// @brief 检查所有bus上的设备并将其加入链表
1012 /// @return 成功返回ok(),失败返回失败原因
pci_check_all_buses() -> Result<u8, PciError>1013 fn pci_check_all_buses() -> Result<u8, PciError> {
1014 kinfo!("Checking all devices in PCI bus...");
1015 let busdevicefunction = BusDeviceFunction {
1016 bus: 0,
1017 device: 0,
1018 function: 0,
1019 };
1020 let header = pci_read_header(busdevicefunction, false)?;
1021 let common_header = header.common_header();
1022 pci_check_bus(0)?;
1023 if common_header.header_type & 0x80 != 0 {
1024 for function in 1..8 {
1025 pci_check_bus(function)?;
1026 }
1027 }
1028 Ok(0)
1029 }
1030 /// @brief 检查特定设备并将其加入链表
1031 /// @return 成功返回ok(),失败返回失败原因
pci_check_function(busdevicefunction: BusDeviceFunction) -> Result<u8, PciError>1032 fn pci_check_function(busdevicefunction: BusDeviceFunction) -> Result<u8, PciError> {
1033 //kdebug!("PCI check function {}", busdevicefunction.function);
1034 let header = match pci_read_header(busdevicefunction, true) {
1035 Ok(header) => header,
1036 Err(PciError::GetWrongHeader) => {
1037 return Ok(255);
1038 }
1039 Err(e) => {
1040 return Err(e);
1041 }
1042 };
1043 let common_header = header.common_header();
1044 if (common_header.class_code == 0x06)
1045 && (common_header.subclass == 0x04 || common_header.subclass == 0x09)
1046 {
1047 let pci_to_pci_bridge = header
1048 .as_pci_to_pci_bridge_device()
1049 .ok_or(PciError::PciDeviceStructureTransformError)?;
1050 let secondary_bus = pci_to_pci_bridge.secondary_bus_number;
1051 pci_check_bus(secondary_bus)?;
1052 }
1053 Ok(0)
1054 }
1055
1056 /// @brief 检查device上的设备并将其加入链表
1057 /// @return 成功返回ok(),失败返回失败原因
pci_check_device(bus: u8, device: u8) -> Result<u8, PciError>1058 fn pci_check_device(bus: u8, device: u8) -> Result<u8, PciError> {
1059 //kdebug!("PCI check device {}", device);
1060 let busdevicefunction = BusDeviceFunction {
1061 bus,
1062 device,
1063 function: 0,
1064 };
1065 let header = match pci_read_header(busdevicefunction, false) {
1066 Ok(header) => header,
1067 Err(PciError::GetWrongHeader) => {
1068 //设备不存在,直接返回即可,不用终止遍历
1069 return Ok(255);
1070 }
1071 Err(e) => {
1072 return Err(e);
1073 }
1074 };
1075 pci_check_function(busdevicefunction)?;
1076 let common_header = header.common_header();
1077 if common_header.header_type & 0x80 != 0 {
1078 kdebug!(
1079 "Detected multi func device in bus{},device{}",
1080 busdevicefunction.bus,
1081 busdevicefunction.device
1082 );
1083 // 这是一个多function的设备,因此查询剩余的function
1084 for function in 1..8 {
1085 let busdevicefunction = BusDeviceFunction {
1086 bus,
1087 device,
1088 function,
1089 };
1090 pci_check_function(busdevicefunction)?;
1091 }
1092 }
1093 Ok(0)
1094 }
1095 /// @brief 检查该bus上的设备并将其加入链表
1096 /// @return 成功返回ok(),失败返回失败原因
pci_check_bus(bus: u8) -> Result<u8, PciError>1097 fn pci_check_bus(bus: u8) -> Result<u8, PciError> {
1098 //kdebug!("PCI check bus {}", bus);
1099 for device in 0..32 {
1100 pci_check_device(bus, device)?;
1101 }
1102 Ok(0)
1103 }
1104 /// @brief pci初始化函数(for c)
1105 #[no_mangle]
rs_pci_init()1106 pub extern "C" fn rs_pci_init() {
1107 pci_init();
1108 if PCI_ROOT_0.is_some() {
1109 kdebug!("{}", PCI_ROOT_0.unwrap());
1110 //以下为ecam的读取寄存器值测试,经测试可正常读取
1111 // let bus_device_function = BusDeviceFunction {
1112 // bus: 0,
1113 // device: 2,
1114 // function: 0,
1115 // };
1116 // kdebug!(
1117 // "Ecam read virtio-net device status={:#x}",
1118 // (PCI_ROOT_0.unwrap().read_config(bus_device_function, 4)>>16) as u16
1119 // );
1120 }
1121 }
1122 /// @brief pci初始化函数
pci_init()1123 pub fn pci_init() {
1124 kinfo!("Initializing PCI bus...");
1125 if let Err(e) = pci_check_all_buses() {
1126 kerror!("pci init failed when checking bus because of error: {}", e);
1127 return;
1128 }
1129 kinfo!(
1130 "Total pci device and function num = {}",
1131 PCI_DEVICE_LINKEDLIST.num()
1132 );
1133 let list = PCI_DEVICE_LINKEDLIST.read();
1134 for box_pci_device in list.iter() {
1135 let common_header = box_pci_device.common_header();
1136 match box_pci_device.header_type() {
1137 HeaderType::Standard if common_header.status & 0x10 != 0 => {
1138 kinfo!("Found pci standard device with class code ={} subclass={} status={:#x} cap_pointer={:#x} vendor={:#x}, device id={:#x},bdf={}", common_header.class_code, common_header.subclass, common_header.status, box_pci_device.as_standard_device().unwrap().capabilities_pointer,common_header.vendor_id, common_header.device_id,common_header.bus_device_function);
1139 }
1140 HeaderType::Standard => {
1141 kinfo!(
1142 "Found pci standard device with class code ={} subclass={} status={:#x} ",
1143 common_header.class_code,
1144 common_header.subclass,
1145 common_header.status
1146 );
1147 }
1148 HeaderType::PciPciBridge if common_header.status & 0x10 != 0 => {
1149 kinfo!("Found pci-to-pci bridge device with class code ={} subclass={} status={:#x} cap_pointer={:#x}", common_header.class_code, common_header.subclass, common_header.status, box_pci_device.as_standard_device().unwrap().capabilities_pointer);
1150 }
1151 HeaderType::PciPciBridge => {
1152 kinfo!(
1153 "Found pci-to-pci bridge device with class code ={} subclass={} status={:#x} ",
1154 common_header.class_code,
1155 common_header.subclass,
1156 common_header.status
1157 );
1158 }
1159 HeaderType::PciCardbusBridge => {
1160 kinfo!(
1161 "Found pcicardbus bridge device with class code ={} subclass={} status={:#x} ",
1162 common_header.class_code,
1163 common_header.subclass,
1164 common_header.status
1165 );
1166 }
1167 HeaderType::Unrecognised(_) => {}
1168 }
1169 }
1170 kinfo!("PCI bus initialized.");
1171 }
1172
1173 /// An identifier for a PCI bus, device and function.
1174 /// PCI设备的唯一标识
1175 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
1176 pub struct BusDeviceFunction {
1177 /// The PCI bus number, between 0 and 255.
1178 pub bus: u8,
1179 /// The device number on the bus, between 0 and 31.
1180 pub device: u8,
1181 /// The function number of the device, between 0 and 7.
1182 pub function: u8,
1183 }
1184 impl BusDeviceFunction {
1185 /// Returns whether the device and function numbers are valid, i.e. the device is between 0 and
1186 ///@brief 检测BusDeviceFunction实例是否有效
1187 ///@param self
1188 ///@return bool 是否有效
1189 #[allow(dead_code)]
valid(&self) -> bool1190 pub fn valid(&self) -> bool {
1191 self.device < 32 && self.function < 8
1192 }
1193 }
1194 ///实现BusDeviceFunction的Display trait,使其可以直接输出
1195 impl Display for BusDeviceFunction {
fmt(&self, f: &mut Formatter) -> fmt::Result1196 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1197 write!(
1198 f,
1199 "bus {} device {} function{}",
1200 self.bus, self.device, self.function
1201 )
1202 }
1203 }
1204 /// The location allowed for a memory BAR.
1205 /// memory BAR的三种情况
1206 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
1207 pub enum MemoryBarType {
1208 /// The BAR has a 32-bit address and can be mapped anywhere in 32-bit address space.
1209 Width32,
1210 /// The BAR must be mapped below 1MiB.
1211 Below1MiB,
1212 /// The BAR has a 64-bit address and can be mapped anywhere in 64-bit address space.
1213 Width64,
1214 }
1215 ///实现MemoryBarType与u8的类型转换
1216 impl From<MemoryBarType> for u8 {
from(bar_type: MemoryBarType) -> Self1217 fn from(bar_type: MemoryBarType) -> Self {
1218 match bar_type {
1219 MemoryBarType::Width32 => 0,
1220 MemoryBarType::Below1MiB => 1,
1221 MemoryBarType::Width64 => 2,
1222 }
1223 }
1224 }
1225 ///实现MemoryBarType与u8的类型转换
1226 impl TryFrom<u8> for MemoryBarType {
1227 type Error = PciError;
try_from(value: u8) -> Result<Self, Self::Error>1228 fn try_from(value: u8) -> Result<Self, Self::Error> {
1229 match value {
1230 0 => Ok(Self::Width32),
1231 1 => Ok(Self::Below1MiB),
1232 2 => Ok(Self::Width64),
1233 _ => Err(PciError::InvalidBarType),
1234 }
1235 }
1236 }
1237
1238 /// Information about a PCI Base Address Register.
1239 /// BAR的三种类型 Memory/IO/Unused
1240 #[derive(Clone, Debug, Eq, PartialEq)]
1241 pub enum BarInfo {
1242 /// The BAR is for a memory region.
1243 Memory {
1244 /// The size of the BAR address and where it can be located.
1245 address_type: MemoryBarType,
1246 /// If true, then reading from the region doesn't have side effects. The CPU may cache reads
1247 /// and merge repeated stores.
1248 prefetchable: bool,
1249 /// The memory address, always 16-byte aligned.
1250 address: u64,
1251 /// The size of the BAR in bytes.
1252 size: u32,
1253 /// The virtaddress for a memory bar(mapped).
1254 virtaddress: u64,
1255 },
1256 /// The BAR is for an I/O region.
1257 IO {
1258 /// The I/O address, always 4-byte aligned.
1259 address: u32,
1260 /// The size of the BAR in bytes.
1261 size: u32,
1262 },
1263 Unused,
1264 }
1265
1266 impl BarInfo {
1267 /// Returns the address and size of this BAR if it is a memory bar, or `None` if it is an IO
1268 /// BAR.
1269 ///@brief 得到某个bar的memory_address与size(前提是他的类型为Memory Bar)
1270 ///@param self
1271 ///@return Option<(u64, u32) 是Memory Bar返回内存地址与大小,不是则返回None
memory_address_size(&self) -> Option<(u64, u32)>1272 pub fn memory_address_size(&self) -> Option<(u64, u32)> {
1273 if let Self::Memory { address, size, .. } = self {
1274 Some((*address, *size))
1275 } else {
1276 None
1277 }
1278 }
1279 ///@brief 得到某个bar的virtaddress(前提是他的类型为Memory Bar)
1280 ///@param self
1281 ///@return Option<(u64) 是Memory Bar返回映射的虚拟地址,不是则返回None
virtual_address(&self) -> Option<u64>1282 pub fn virtual_address(&self) -> Option<u64> {
1283 if let Self::Memory { virtaddress, .. } = self {
1284 Some(*virtaddress)
1285 } else {
1286 None
1287 }
1288 }
1289 }
1290 ///实现BarInfo的Display trait,自定义输出
1291 impl Display for BarInfo {
fmt(&self, f: &mut Formatter<'_>) -> fmt::Result1292 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1293 match self {
1294 Self::Memory {
1295 address_type,
1296 prefetchable,
1297 address,
1298 size,
1299 virtaddress,
1300 } => write!(
1301 f,
1302 "Memory space at {:#010x}, size {}, type {:?}, prefetchable {},mapped at {:#x}",
1303 address, size, address_type, prefetchable, virtaddress
1304 ),
1305 Self::IO { address, size } => {
1306 write!(f, "I/O space at {:#010x}, size {}", address, size)
1307 }
1308 Self::Unused => {
1309 write!(f, "Unused bar")
1310 }
1311 }
1312 }
1313 }
1314 // todo 增加对桥的bar的支持
1315 pub trait PciDeviceBar {}
1316
1317 ///一个普通PCI设备(非桥)有6个BAR寄存器,PciStandardDeviceBar存储其全部信息
1318 #[derive(Clone, Debug, Eq, PartialEq)]
1319 pub struct PciStandardDeviceBar {
1320 bar0: BarInfo,
1321 bar1: BarInfo,
1322 bar2: BarInfo,
1323 bar3: BarInfo,
1324 bar4: BarInfo,
1325 bar5: BarInfo,
1326 }
1327
1328 impl PciStandardDeviceBar {
1329 ///@brief 得到某个bar的barinfo
1330 ///@param self ,bar_index(0-5)
1331 ///@return Result<&BarInfo, PciError> bar_index在0-5则返回对应的bar_info结构体,超出范围则返回错误
get_bar(&self, bar_index: u8) -> Result<&BarInfo, PciError>1332 pub fn get_bar(&self, bar_index: u8) -> Result<&BarInfo, PciError> {
1333 match bar_index {
1334 0 => Ok(&self.bar0),
1335 1 => Ok(&self.bar1),
1336 2 => Ok(&self.bar2),
1337 3 => Ok(&self.bar3),
1338 4 => Ok(&self.bar4),
1339 5 => Ok(&self.bar5),
1340 _ => Err(PciError::InvalidBarType),
1341 }
1342 }
1343 }
1344 ///实现PciStandardDeviceBar的Display trait,使其可以直接输出
1345 impl Display for PciStandardDeviceBar {
fmt(&self, f: &mut Formatter<'_>) -> fmt::Result1346 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1347 write!(
1348 f,
1349 "\r\nBar0:{}\r\n Bar1:{}\r\n Bar2:{}\r\n Bar3:{}\r\nBar4:{}\r\nBar5:{}",
1350 self.bar0, self.bar1, self.bar2, self.bar3, self.bar4, self.bar5
1351 )
1352 }
1353 }
1354 ///实现PciStandardDeviceBar的Default trait,使其可以简单初始化
1355 impl Default for PciStandardDeviceBar {
default() -> Self1356 fn default() -> Self {
1357 PciStandardDeviceBar {
1358 bar0: BarInfo::Unused,
1359 bar1: BarInfo::Unused,
1360 bar2: BarInfo::Unused,
1361 bar3: BarInfo::Unused,
1362 bar4: BarInfo::Unused,
1363 bar5: BarInfo::Unused,
1364 }
1365 }
1366 }
1367
1368 ///@brief 将某个pci设备的bar寄存器读取值后映射到虚拟地址
1369 ///@param self ,bus_device_function PCI设备的唯一标识符
1370 ///@return Result<PciStandardDeviceBar, PciError> 成功则返回对应的PciStandardDeviceBar结构体,失败则返回错误类型
pci_bar_init( bus_device_function: BusDeviceFunction, ) -> Result<PciStandardDeviceBar, PciError>1371 pub fn pci_bar_init(
1372 bus_device_function: BusDeviceFunction,
1373 ) -> Result<PciStandardDeviceBar, PciError> {
1374 let mut device_bar: PciStandardDeviceBar = PciStandardDeviceBar::default();
1375 let mut bar_index_ignore: u8 = 255;
1376 for bar_index in 0..6 {
1377 if bar_index == bar_index_ignore {
1378 continue;
1379 }
1380 let bar_info;
1381 let mut virtaddress: u64 = 0;
1382 let bar_orig = PciArch::read_config(&bus_device_function, BAR0_OFFSET + 4 * bar_index);
1383 PciArch::write_config(
1384 &bus_device_function,
1385 BAR0_OFFSET + 4 * bar_index,
1386 0xffffffff,
1387 );
1388 let size_mask = PciArch::read_config(&bus_device_function, BAR0_OFFSET + 4 * bar_index);
1389 // A wrapping add is necessary to correctly handle the case of unused BARs, which read back
1390 // as 0, and should be treated as size 0.
1391 let size = (!(size_mask & 0xfffffff0)).wrapping_add(1);
1392 //kdebug!("bar_orig:{:#x},size: {:#x}", bar_orig,size);
1393 // Restore the original value.
1394 PciArch::write_config(&bus_device_function, BAR0_OFFSET + 4 * bar_index, bar_orig);
1395 if size == 0 {
1396 continue;
1397 }
1398 if bar_orig & 0x00000001 == 0x00000001 {
1399 // I/O space
1400 let address = bar_orig & 0xfffffffc;
1401 bar_info = BarInfo::IO { address, size };
1402 } else {
1403 // Memory space
1404 let mut address = u64::from(bar_orig & 0xfffffff0);
1405 let prefetchable = bar_orig & 0x00000008 != 0;
1406 let address_type = MemoryBarType::try_from(((bar_orig & 0x00000006) >> 1) as u8)?;
1407 if address_type == MemoryBarType::Width64 {
1408 if bar_index >= 5 {
1409 return Err(PciError::InvalidBarType);
1410 }
1411 let address_top =
1412 PciArch::read_config(&bus_device_function, BAR0_OFFSET + 4 * (bar_index + 1));
1413 address |= u64::from(address_top) << 32;
1414 bar_index_ignore = bar_index + 1; //下个bar跳过,因为64位的memory bar覆盖了两个bar
1415 }
1416 let pci_address = PciAddr::new(address as usize);
1417 address = PciArch::address_pci_to_physical(pci_address) as u64; //PCI总线域物理地址转换为存储器域物理地址
1418 unsafe {
1419 let vaddr_ptr = &mut virtaddress as *mut u64;
1420 let mut virtsize: u64 = 0;
1421 let virtsize_ptr = &mut virtsize as *mut u64;
1422
1423 let size_want = size as usize;
1424
1425 if let Err(_) = mmio_pool().create_mmio(
1426 size_want,
1427 (VM_IO | VM_DONTCOPY) as u64,
1428 vaddr_ptr,
1429 virtsize_ptr,
1430 ) {
1431 kerror!("Create mmio failed when initing pci bar");
1432 return Err(PciError::CreateMmioError);
1433 };
1434 //kdebug!("virtaddress={:#x},virtsize={:#x}",virtaddress,virtsize);
1435 let vaddr = VirtAddr::new(virtaddress as usize);
1436 let paddr = PhysAddr::new(address as usize);
1437 let page_flags = PageFlags::new()
1438 .set_write(true)
1439 .set_execute(true)
1440 .set_page_cache_disable(true)
1441 .set_page_write_through(true);
1442 kdebug!("Pci bar init: vaddr={vaddr:?}, paddr={paddr:?}, size_want={size_want}, page_flags={page_flags:?}");
1443 let mut kernel_mapper = KernelMapper::lock();
1444 // todo: 添加错误处理代码。因为内核映射器可能是只读的,所以可能会出错
1445 assert!(kernel_mapper
1446 .map_phys_with_size(vaddr, paddr, size_want, page_flags, true)
1447 .is_ok());
1448 drop(kernel_mapper);
1449 }
1450 bar_info = BarInfo::Memory {
1451 address_type,
1452 prefetchable,
1453 address,
1454 size,
1455 virtaddress,
1456 };
1457 }
1458 match bar_index {
1459 0 => {
1460 device_bar.bar0 = bar_info;
1461 }
1462 1 => {
1463 device_bar.bar1 = bar_info;
1464 }
1465 2 => {
1466 device_bar.bar2 = bar_info;
1467 }
1468 3 => {
1469 device_bar.bar3 = bar_info;
1470 }
1471 4 => {
1472 device_bar.bar4 = bar_info;
1473 }
1474 5 => {
1475 device_bar.bar5 = bar_info;
1476 }
1477 _ => {}
1478 }
1479 }
1480 kdebug!("pci_device_bar:{}", device_bar);
1481 return Ok(device_bar);
1482 }
1483
1484 /// Information about a PCI device capability.
1485 /// PCI设备的capability的信息
1486 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
1487 pub struct CapabilityInfo {
1488 /// The offset of the capability in the PCI configuration space of the device function.
1489 pub offset: u8,
1490 /// The ID of the capability.
1491 pub id: u8,
1492 /// The third and fourth bytes of the capability, to save reading them again.
1493 pub private_header: u16,
1494 }
1495
1496 /// Iterator over capabilities for a device.
1497 /// 创建迭代器以遍历PCI设备的capability
1498 #[derive(Debug)]
1499 pub struct CapabilityIterator {
1500 pub bus_device_function: BusDeviceFunction,
1501 pub next_capability_offset: Option<u8>,
1502 }
1503
1504 impl Iterator for CapabilityIterator {
1505 type Item = CapabilityInfo;
next(&mut self) -> Option<Self::Item>1506 fn next(&mut self) -> Option<Self::Item> {
1507 let offset = self.next_capability_offset?;
1508
1509 // Read the first 4 bytes of the capability.
1510 let capability_header = PciArch::read_config(&self.bus_device_function, offset);
1511 let id = capability_header as u8;
1512 let next_offset = (capability_header >> 8) as u8;
1513 let private_header = (capability_header >> 16) as u16;
1514
1515 self.next_capability_offset = if next_offset == 0 {
1516 None
1517 } else if next_offset < 64 || next_offset & 0x3 != 0 {
1518 kwarn!("Invalid next capability offset {:#04x}", next_offset);
1519 None
1520 } else {
1521 Some(next_offset)
1522 };
1523
1524 Some(CapabilityInfo {
1525 offset,
1526 id,
1527 private_header,
1528 })
1529 }
1530 }
1531
1532 /// Information about a PCIe device capability.
1533 /// PCIe设备的external capability的信息
1534 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
1535 pub struct ExternalCapabilityInfo {
1536 /// The offset of the capability in the PCI configuration space of the device function.
1537 pub offset: u16,
1538 /// The ID of the capability.
1539 pub id: u16,
1540 /// The third and fourth bytes of the capability, to save reading them again.
1541 pub capability_version: u8,
1542 }
1543
1544 /// Iterator over capabilities for a device.
1545 /// 创建迭代器以遍历PCIe设备的external capability
1546 #[derive(Debug)]
1547 pub struct ExternalCapabilityIterator<'a> {
1548 pub root: &'a PciRoot,
1549 pub bus_device_function: BusDeviceFunction,
1550 pub next_capability_offset: Option<u16>,
1551 }
1552 impl<'a> Iterator for ExternalCapabilityIterator<'a> {
1553 type Item = ExternalCapabilityInfo;
next(&mut self) -> Option<Self::Item>1554 fn next(&mut self) -> Option<Self::Item> {
1555 let offset = self.next_capability_offset?;
1556
1557 // Read the first 4 bytes of the capability.
1558 let capability_header = self.root.read_config(self.bus_device_function, offset);
1559 let id = capability_header as u16;
1560 let next_offset = (capability_header >> 20) as u16;
1561 let capability_version = ((capability_header >> 16) & 0xf) as u8;
1562
1563 self.next_capability_offset = if next_offset == 0 {
1564 None
1565 } else if next_offset < 0x100 || next_offset & 0x3 != 0 {
1566 kwarn!("Invalid next capability offset {:#04x}", next_offset);
1567 None
1568 } else {
1569 Some(next_offset)
1570 };
1571
1572 Some(ExternalCapabilityInfo {
1573 offset,
1574 id,
1575 capability_version,
1576 })
1577 }
1578 }
1579