xref: /DragonOS/kernel/src/driver/pci/pci.rs (revision 73c607aaddf6e4634cad179a81d3f1bc589f7220) !
1 use crate::include::bindings::bindings::{
2     initial_mm, mm_map, mm_struct, pci_read_config, pci_write_config, VM_DONTCOPY, VM_IO,
3 };
4 use crate::mm::mmio_buddy::MMIO_POOL;
5 use crate::{kdebug, kerror, kwarn};
6 use bitflags::bitflags;
7 use core::{
8     convert::TryFrom,
9     fmt::{self, Display, Formatter},
10 };
11 //Bar0寄存器的offset
12 const BAR0_OFFSET: u8 = 0x10;
13 //Status、Command寄存器的offset
14 const STATUS_COMMAND_OFFSET: u8 = 0x04;
15 /// ID for vendor-specific PCI capabilities.(Virtio Capabilities)
16 pub const PCI_CAP_ID_VNDR: u8 = 0x09;
17 
18 bitflags! {
19     /// The status register in PCI configuration space.
20     pub struct Status: u16 {
21         // Bits 0-2 are reserved.
22         /// The state of the device's INTx# signal.
23         const INTERRUPT_STATUS = 1 << 3;
24         /// The device has a linked list of capabilities.
25         const CAPABILITIES_LIST = 1 << 4;
26         /// The device is capabile of running at 66 MHz rather than 33 MHz.
27         const MHZ_66_CAPABLE = 1 << 5;
28         // Bit 6 is reserved.
29         /// The device can accept fast back-to-back transactions not from the same agent.
30         const FAST_BACK_TO_BACK_CAPABLE = 1 << 7;
31         /// The bus agent observed a parity error (if parity error handling is enabled).
32         const MASTER_DATA_PARITY_ERROR = 1 << 8;
33         // Bits 9-10 are DEVSEL timing.
34         /// A target device terminated a transaction with target-abort.
35         const SIGNALED_TARGET_ABORT = 1 << 11;
36         /// A master device transaction was terminated with target-abort.
37         const RECEIVED_TARGET_ABORT = 1 << 12;
38         /// A master device transaction was terminated with master-abort.
39         const RECEIVED_MASTER_ABORT = 1 << 13;
40         /// A device asserts SERR#.
41         const SIGNALED_SYSTEM_ERROR = 1 << 14;
42         /// The device detects a parity error, even if parity error handling is disabled.
43         const DETECTED_PARITY_ERROR = 1 << 15;
44     }
45 }
46 
47 bitflags! {
48     /// The command register in PCI configuration space.
49     pub struct CommandRegister: u16 {
50         /// The device can respond to I/O Space accesses.
51         const IO_SPACE = 1 << 0;
52         /// The device can respond to Memory Space accesses.
53         const MEMORY_SPACE = 1 << 1;
54         /// The device can behave as a bus master.
55         const BUS_MASTER = 1 << 2;
56         /// The device can monitor Special Cycle operations.
57         const SPECIAL_CYCLES = 1 << 3;
58         /// The device can generate the Memory Write and Invalidate command.
59         const MEMORY_WRITE_AND_INVALIDATE_ENABLE = 1 << 4;
60         /// The device will snoop palette register data.
61         const VGA_PALETTE_SNOOP = 1 << 5;
62         /// The device should take its normal action when a parity error is detected.
63         const PARITY_ERROR_RESPONSE = 1 << 6;
64         // Bit 7 is reserved.
65         /// The SERR# driver is enabled.
66         const SERR_ENABLE = 1 << 8;
67         /// The device is allowed to generate fast back-to-back transactions.
68         const FAST_BACK_TO_BACK_ENABLE = 1 << 9;
69         /// Assertion of the device's INTx# signal is disabled.
70         const INTERRUPT_DISABLE = 1 << 10;
71     }
72 }
73 
74 /// Gets the capabilities 'pointer' for the device function, if any.
75 ///@brief 获取第一个capability 的offset
76 ///@param device_function PCI设备的唯一标识
77 ///@return Option<u8> offset
78 pub fn capabilities_offset(device_function: DeviceFunction) -> Option<u8> {
79     let status: Status = unsafe {
80         let temp = pci_read_config(
81             device_function.bus,
82             device_function.device,
83             device_function.function,
84             STATUS_COMMAND_OFFSET,
85         );
86         Status::from_bits_truncate((temp >> 16) as u16)
87     };
88     if status.contains(Status::CAPABILITIES_LIST) {
89         let cap_pointer = unsafe {
90             let temp = pci_read_config(
91                 device_function.bus,
92                 device_function.device,
93                 device_function.function,
94                 0x34,
95             );
96             temp as u8 & 0xFC
97         };
98         Some(cap_pointer)
99     } else {
100         None
101     }
102 }
103 /// An identifier for a PCI bus, device and function.
104 /// PCI设备的唯一标识
105 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
106 pub struct DeviceFunction {
107     /// The PCI bus number, between 0 and 255.
108     pub bus: u8,
109     /// The device number on the bus, between 0 and 31.
110     pub device: u8,
111     /// The function number of the device, between 0 and 7.
112     pub function: u8,
113 }
114 ///PCI的Error
115 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
116 pub enum PciError {
117     /// The device reported an invalid BAR type.
118     InvalidBarType,
119     CreateMmioError,
120 }
121 ///实现PciError的Display trait,使其可以直接输出
122 impl Display for PciError {
123     fn fmt(&self, f: &mut Formatter) -> fmt::Result {
124         match self {
125             Self::InvalidBarType => write!(f, "Invalid PCI BAR type."),
126             Self::CreateMmioError => write!(f, "Error occurred while creating mmio"),
127         }
128     }
129 }
130 
131 impl DeviceFunction {
132     /// Returns whether the device and function numbers are valid, i.e. the device is between 0 and
133     /// 31, and the function is between 0 and 7.
134     /// @brief 检测DeviceFunction实例是否有效
135     /// @param self
136     /// @return bool 是否有效
137     #[allow(dead_code)]
138     pub fn valid(&self) -> bool {
139         self.device < 32 && self.function < 8
140     }
141 }
142 ///实现DeviceFunction的Display trait,使其可以直接输出
143 impl Display for DeviceFunction {
144     fn fmt(&self, f: &mut Formatter) -> fmt::Result {
145         write!(f, "{:02x}:{:02x}.{}", self.bus, self.device, self.function)
146     }
147 }
148 /// The location allowed for a memory BAR.
149 /// memory BAR的三种情况
150 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
151 pub enum MemoryBarType {
152     /// The BAR has a 32-bit address and can be mapped anywhere in 32-bit address space.
153     Width32,
154     /// The BAR must be mapped below 1MiB.
155     Below1MiB,
156     /// The BAR has a 64-bit address and can be mapped anywhere in 64-bit address space.
157     Width64,
158 }
159 ///实现MemoryBarType与u8的类型转换
160 impl From<MemoryBarType> for u8 {
161     fn from(bar_type: MemoryBarType) -> Self {
162         match bar_type {
163             MemoryBarType::Width32 => 0,
164             MemoryBarType::Below1MiB => 1,
165             MemoryBarType::Width64 => 2,
166         }
167     }
168 }
169 ///实现MemoryBarType与u8的类型转换
170 impl TryFrom<u8> for MemoryBarType {
171     type Error = PciError;
172     fn try_from(value: u8) -> Result<Self, Self::Error> {
173         match value {
174             0 => Ok(Self::Width32),
175             1 => Ok(Self::Below1MiB),
176             2 => Ok(Self::Width64),
177             _ => Err(PciError::InvalidBarType),
178         }
179     }
180 }
181 
182 /// Information about a PCI Base Address Register.
183 /// BAR的三种类型 Memory/IO/Unused
184 #[derive(Clone, Debug, Eq, PartialEq)]
185 pub enum BarInfo {
186     /// The BAR is for a memory region.
187     Memory {
188         /// The size of the BAR address and where it can be located.
189         address_type: MemoryBarType,
190         /// If true, then reading from the region doesn't have side effects. The CPU may cache reads
191         /// and merge repeated stores.
192         prefetchable: bool,
193         /// The memory address, always 16-byte aligned.
194         address: u64,
195         /// The size of the BAR in bytes.
196         size: u32,
197         /// The virtaddress for a memory bar(mapped).
198         virtaddress: u64,
199     },
200     /// The BAR is for an I/O region.
201     IO {
202         /// The I/O address, always 4-byte aligned.
203         address: u32,
204         /// The size of the BAR in bytes.
205         size: u32,
206     },
207     Unused,
208 }
209 
210 impl BarInfo {
211     /// Returns the address and size of this BAR if it is a memory bar, or `None` if it is an IO
212     /// BAR.
213     ///@brief 得到某个bar的memory_address与size(前提是他的类型为Memory Bar)
214     ///@param self
215     ///@return Option<(u64, u32) 是Memory Bar返回内存地址与大小,不是则返回None
216     pub fn memory_address_size(&self) -> Option<(u64, u32)> {
217         if let Self::Memory { address, size, .. } = self {
218             Some((*address, *size))
219         } else {
220             None
221         }
222     }
223     ///@brief 得到某个bar的virtaddress(前提是他的类型为Memory Bar)
224     ///@param self
225     ///@return Option<(u64) 是Memory Bar返回映射的虚拟地址,不是则返回None
226     pub fn virtual_address(&self) -> Option<u64> {
227         if let Self::Memory { virtaddress, .. } = self {
228             Some(*virtaddress)
229         } else {
230             None
231         }
232     }
233 }
234 ///实现BarInfo的Display trait,使其可以直接输出
235 impl Display for BarInfo {
236     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
237         match self {
238             Self::Memory {
239                 address_type,
240                 prefetchable,
241                 address,
242                 size,
243                 virtaddress,
244             } => write!(
245                 f,
246                 "Memory space at {:#010x}, size {}, type {:?}, prefetchable {},mapped at {:#x}",
247                 address, size, address_type, prefetchable, virtaddress
248             ),
249             Self::IO { address, size } => {
250                 write!(f, "I/O space at {:#010x}, size {}", address, size)
251             }
252             Self::Unused => {
253                 write!(f, "Unused bar")
254             }
255         }
256     }
257 }
258 ///一个PCI设备有6个BAR寄存器,PciDeviceBar存储其全部信息
259 #[derive(Clone, Debug, Eq, PartialEq)]
260 pub struct PciDeviceBar {
261     bar0: BarInfo,
262     bar1: BarInfo,
263     bar2: BarInfo,
264     bar3: BarInfo,
265     bar4: BarInfo,
266     bar5: BarInfo,
267 }
268 
269 impl PciDeviceBar {
270     ///@brief 得到某个bar的barinfo
271     ///@param self ,bar_index(0-5)
272     ///@return Result<&BarInfo, PciError> bar_index在0-5则返回对应的bar_info结构体,超出范围则返回错误
273     pub fn get_bar(&self, bar_index: u8) -> Result<&BarInfo, PciError> {
274         match bar_index {
275             0 => Ok(&self.bar0),
276             1 => Ok(&self.bar1),
277             2 => Ok(&self.bar2),
278             3 => Ok(&self.bar3),
279             4 => Ok(&self.bar4),
280             _ => Err(PciError::InvalidBarType),
281         }
282     }
283 }
284 ///实现PciDeviceBar的Display trait,使其可以直接输出
285 impl Display for PciDeviceBar {
286     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
287         write!(
288             f,
289             "\r\nBar0:{}\r\n Bar1:{}\r\n Bar2:{}\r\n Bar3:{}\r\nBar4:{}\r\nBar5:{}",
290             self.bar0, self.bar1, self.bar2, self.bar3, self.bar4, self.bar5
291         )
292     }
293 }
294 ///实现PciDeviceBar的Default trait,使其可以简单初始化
295 impl Default for PciDeviceBar {
296     fn default() -> Self {
297         PciDeviceBar {
298             bar0: BarInfo::Unused,
299             bar1: BarInfo::Unused,
300             bar2: BarInfo::Unused,
301             bar3: BarInfo::Unused,
302             bar4: BarInfo::Unused,
303             bar5: BarInfo::Unused,
304         }
305     }
306 }
307 
308 ///@brief 将某个pci设备的bar全部初始化,memory
309 ///@param self ,device_function PCI设备的唯一标识符
310 ///@return Result<PciDeviceBar, PciError> 成功则返回对应的PciDeviceBar结构体,失败则返回错误类型
311 pub fn pci_bar_init(device_function: DeviceFunction) -> Result<PciDeviceBar, PciError> {
312     let mut device_bar: PciDeviceBar = PciDeviceBar::default();
313     let mut bar_index_ignore: u8 = 255;
314     for bar_index in 0..6 {
315         if bar_index == bar_index_ignore {
316             continue;
317         }
318         let bar_info;
319         let mut virtaddress: u64 = 0;
320         let bar_orig = unsafe {
321             let bar_temp = pci_read_config(
322                 device_function.bus,
323                 device_function.device,
324                 device_function.function,
325                 BAR0_OFFSET + 4 * bar_index,
326             );
327             bar_temp
328         };
329         unsafe {
330             pci_write_config(
331                 device_function.bus,
332                 device_function.device,
333                 device_function.function,
334                 BAR0_OFFSET + 4 * bar_index,
335                 0xffffffff,
336             );
337         }
338         let size_mask = unsafe {
339             let bar_temp = pci_read_config(
340                 device_function.bus,
341                 device_function.device,
342                 device_function.function,
343                 BAR0_OFFSET + 4 * bar_index,
344             );
345             bar_temp
346         };
347         // A wrapping add is necessary to correctly handle the case of unused BARs, which read back
348         // as 0, and should be treated as size 0.
349         let size = (!(size_mask & 0xfffffff0)).wrapping_add(1);
350         //kdebug!("bar_orig:{:#x},size: {:#x}", bar_orig,size);
351         // Restore the original value.
352         unsafe {
353             pci_write_config(
354                 device_function.bus,
355                 device_function.device,
356                 device_function.function,
357                 BAR0_OFFSET + 4 * bar_index,
358                 bar_orig,
359             );
360         }
361         if size == 0 {
362             continue;
363         }
364         if bar_orig & 0x00000001 == 0x00000001 {
365             // I/O space
366             let address = bar_orig & 0xfffffffc;
367             bar_info = BarInfo::IO { address, size };
368         } else {
369             // Memory space
370             let mut address = u64::from(bar_orig & 0xfffffff0);
371             let prefetchable = bar_orig & 0x00000008 != 0;
372             let address_type = MemoryBarType::try_from(((bar_orig & 0x00000006) >> 1) as u8)?;
373             if address_type == MemoryBarType::Width64 {
374                 if bar_index >= 5 {
375                     return Err(PciError::InvalidBarType);
376                 }
377                 let address_top = unsafe {
378                     let bar_temp = pci_read_config(
379                         device_function.bus,
380                         device_function.device,
381                         device_function.function,
382                         BAR0_OFFSET + 4 * (bar_index + 1),
383                     );
384                     bar_temp
385                 };
386                 address |= u64::from(address_top) << 32;
387                 bar_index_ignore = bar_index + 1; //下个bar跳过,因为64位的memory bar覆盖了两个bar
388             }
389             //kdebug!("address={:#x},size={:#x}",address,size);
390             unsafe {
391                 let vaddr_ptr = &mut virtaddress as *mut u64;
392                 let mut virtsize: u64 = 0;
393                 let virtsize_ptr = &mut virtsize as *mut u64;
394                 let initial_mm_ptr = &mut initial_mm as *mut mm_struct;
395                 //kdebug!("size want={:#x}", size);
396                 if let Err(_) = MMIO_POOL.create_mmio(
397                     size,
398                     (VM_IO | VM_DONTCOPY) as u64,
399                     vaddr_ptr,
400                     virtsize_ptr,
401                 ) {
402                     kerror!("Create mmio failed when initing pci bar");
403                     return Err(PciError::CreateMmioError);
404                 };
405                 //kdebug!("virtaddress={:#x},virtsize={:#x}",virtaddress,virtsize);
406                 mm_map(initial_mm_ptr, virtaddress, size as u64, address);
407             }
408             bar_info = BarInfo::Memory {
409                 address_type,
410                 prefetchable,
411                 address,
412                 size,
413                 virtaddress,
414             };
415         }
416         match bar_index {
417             0 => {
418                 device_bar.bar0 = bar_info;
419             }
420             1 => {
421                 device_bar.bar1 = bar_info;
422             }
423             2 => {
424                 device_bar.bar2 = bar_info;
425             }
426             3 => {
427                 device_bar.bar3 = bar_info;
428             }
429             4 => {
430                 device_bar.bar4 = bar_info;
431             }
432             5 => {
433                 device_bar.bar5 = bar_info;
434             }
435             _ => {}
436         }
437     }
438     kdebug!("pci_device_bar:{}", device_bar);
439     return Ok(device_bar);
440 }
441 
442 /// Information about a PCI device capability.
443 /// PCI设备的capability的信息
444 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
445 pub struct CapabilityInfo {
446     /// The offset of the capability in the PCI configuration space of the device function.
447     pub offset: u8,
448     /// The ID of the capability.
449     pub id: u8,
450     /// The third and fourth bytes of the capability, to save reading them again.
451     pub private_header: u16,
452 }
453 
454 /// Iterator over capabilities for a device.
455 /// 创建迭代器以遍历PCI设备的capability
456 #[derive(Debug)]
457 pub struct CapabilityIterator {
458     pub device_function: DeviceFunction,
459     pub next_capability_offset: Option<u8>,
460 }
461 
462 impl Iterator for CapabilityIterator {
463     type Item = CapabilityInfo;
464     fn next(&mut self) -> Option<Self::Item> {
465         let offset = self.next_capability_offset?;
466 
467         // Read the first 4 bytes of the capability.
468         let capability_header = unsafe {
469             let temp = pci_read_config(
470                 self.device_function.bus,
471                 self.device_function.device,
472                 self.device_function.function,
473                 offset,
474             );
475             temp
476         };
477         let id = capability_header as u8;
478         let next_offset = (capability_header >> 8) as u8;
479         let private_header = (capability_header >> 16) as u16;
480 
481         self.next_capability_offset = if next_offset == 0 {
482             None
483         } else if next_offset < 64 || next_offset & 0x3 != 0 {
484             kwarn!("Invalid next capability offset {:#04x}", next_offset);
485             None
486         } else {
487             Some(next_offset)
488         };
489 
490         Some(CapabilityInfo {
491             offset,
492             id,
493             private_header,
494         })
495     }
496 }
497 
498 /// @brief 设置PCI Config Space里面的Command Register
499 ///
500 /// @param device_function 设备
501 /// @param value command register要被设置成的值
502 pub fn set_command_register(device_function: &DeviceFunction, value: CommandRegister) {
503     unsafe {
504         pci_write_config(
505             device_function.bus,
506             device_function.device,
507             device_function.function,
508             STATUS_COMMAND_OFFSET,
509             value.bits().into(),
510         );
511     }
512 }
513 /// @brief 使能对PCI Memory/IO空间的写入,使能PCI设备作为主设备(主动进行Memory的写入等,msix中断使用到)
514 ///
515 /// @param device_function 设备
516 pub fn pci_enable_master(device_function: DeviceFunction) {
517     set_command_register(
518         &device_function,
519         CommandRegister::IO_SPACE | CommandRegister::MEMORY_SPACE | CommandRegister::BUS_MASTER,
520     );
521 }
522