Skip to content

Commit ffa026b

Browse files
1037827920BrahmaMantra
authored andcommitted
feat(driver/pci): 完善pci root结构体,增加portio的pci配置空间访问 (DragonOS-Community#818)
* feat(driver/pci): 完善pci root结构体,增加portio的pci配置空间访问
1 parent ccff9e8 commit ffa026b

File tree

4 files changed

+118
-57
lines changed

4 files changed

+118
-57
lines changed

kernel/src/arch/x86_64/pci/pci.rs

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,40 @@ use crate::arch::TraitPciArch;
22
use crate::driver::acpi::acpi_manager;
33
use crate::driver::pci::ecam::{pci_ecam_root_info_manager, EcamRootInfo};
44
use crate::driver::pci::pci::{
5-
pci_init, BusDeviceFunction, PciAddr, PciError, PORT_PCI_CONFIG_ADDRESS, PORT_PCI_CONFIG_DATA,
5+
pci_init, BusDeviceFunction, PciAddr, PciCam, PciError, PORT_PCI_CONFIG_ADDRESS,
6+
PORT_PCI_CONFIG_DATA,
67
};
7-
use crate::include::bindings::bindings::{io_in32, io_out32};
8+
use crate::driver::pci::root::{pci_root_manager, PciRoot};
9+
use crate::include::bindings::bindings::{io_in32, io_in8, io_out32};
810
use crate::init::initcall::INITCALL_SUBSYS;
9-
1011
use crate::mm::PhysAddr;
1112

1213
use acpi::mcfg::Mcfg;
13-
use log::error;
14+
use log::{error, warn};
1415
use system_error::SystemError;
1516
use unified_init::macros::unified_init;
1617

1718
pub struct X86_64PciArch;
19+
20+
impl X86_64PciArch {
21+
/// # 在早期引导阶段直接访问PCI配置空间的函数
22+
/// 参考:https://code.dragonos.org.cn/xref/linux-6.6.21/arch/x86/pci/early.c?fi=read_pci_config_byte#19
23+
fn read_config_early(bus: u8, slot: u8, func: u8, offset: u8) -> u8 {
24+
unsafe {
25+
io_out32(
26+
PORT_PCI_CONFIG_ADDRESS,
27+
0x80000000
28+
| ((bus as u32) << 16)
29+
| ((slot as u32) << 11)
30+
| ((func as u32) << 8)
31+
| offset as u32,
32+
);
33+
}
34+
let value = unsafe { io_in8(PORT_PCI_CONFIG_DATA + (offset & 3) as u16) };
35+
return value;
36+
}
37+
}
38+
1839
impl TraitPciArch for X86_64PciArch {
1940
fn read_config(bus_device_function: &BusDeviceFunction, offset: u8) -> u32 {
2041
// 构造pci配置空间地址
@@ -51,8 +72,18 @@ impl TraitPciArch for X86_64PciArch {
5172

5273
#[unified_init(INITCALL_SUBSYS)]
5374
fn x86_64_pci_init() -> Result<(), SystemError> {
54-
if let Err(e) = discover_ecam_root() {
55-
error!("x86_64_pci_init(): discover_ecam_root error: {:?}", e);
75+
if discover_ecam_root().is_err() {
76+
// ecam初始化失败,使用portio访问pci配置空间
77+
// 参考:https://code.dragonos.org.cn/xref/linux-6.6.21/arch/x86/pci/broadcom_bus.c#27
78+
let bus_begin = X86_64PciArch::read_config_early(0, 0, 0, 0x44);
79+
let bus_end = X86_64PciArch::read_config_early(0, 0, 0, 0x45);
80+
81+
if !pci_root_manager().has_root(bus_begin as u16) {
82+
let root = PciRoot::new(None, PciCam::Portiocam, bus_begin, bus_end);
83+
pci_root_manager().add_pci_root(root.unwrap());
84+
} else {
85+
warn!("x86_64_pci_init(): pci_root_manager {}", bus_begin);
86+
}
5687
}
5788
pci_init();
5889

kernel/src/driver/pci/ecam.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,32 @@ pub fn pci_ecam_root_info_manager() -> &'static EcamRootInfoManager {
1313
}
1414

1515
/// Ecam pci root info
16-
#[derive(Clone, Copy)]
16+
#[derive(Clone, Debug, Copy)]
1717
pub struct EcamRootInfo {
18-
pub segement_group_number: SegmentGroupNumber,
18+
/// 段组号
19+
pub segment_group_number: SegmentGroupNumber,
20+
/// 该分组中的最小bus
1921
pub bus_begin: u8,
22+
/// 该分组中的最大bus
2023
pub bus_end: u8,
24+
/// 物理基地址
2125
pub physical_address_base: PhysAddr,
2226
}
2327

2428
impl EcamRootInfo {
2529
pub fn new(
26-
segement_group_number: SegmentGroupNumber,
30+
segment_group_number: SegmentGroupNumber,
2731
bus_begin: u8,
2832
bus_end: u8,
2933
physical_address_base: PhysAddr,
3034
) -> Self {
31-
Self {
32-
segement_group_number,
35+
let ecam_root_info = Self {
36+
segment_group_number,
3337
bus_begin,
3438
bus_end,
3539
physical_address_base,
36-
}
40+
};
41+
return ecam_root_info;
3742
}
3843
}
3944

@@ -48,11 +53,10 @@ impl EcamRootInfoManager {
4853
///
4954
/// - `ecam_root_info`: EcamRootInfo - 要添加的EcamRootInfo实例
5055
pub fn add_ecam_root_info(&self, ecam_root_info: EcamRootInfo) {
51-
if !pci_root_manager().has_root(ecam_root_info.segement_group_number) {
56+
if !pci_root_manager().has_root(ecam_root_info.segment_group_number) {
5257
let root = PciRoot::new(
53-
ecam_root_info.segement_group_number,
58+
Some(ecam_root_info),
5459
PciCam::Ecam,
55-
ecam_root_info.physical_address_base,
5660
ecam_root_info.bus_begin,
5761
ecam_root_info.bus_end,
5862
);
@@ -66,7 +70,7 @@ impl EcamRootInfoManager {
6670
} else {
6771
warn!(
6872
"add_ecam_root_info(): root {} already exists",
69-
ecam_root_info.segement_group_number
73+
ecam_root_info.segment_group_number
7074
);
7175
}
7276
}

kernel/src/driver/pci/pci.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,8 @@ impl PciDeviceStructure for PciDeviceStructurePciToCardbusBridge {
639639
/// 用于访问PCI设备的功能配置空间的一组机制。
640640
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
641641
pub enum PciCam {
642+
/// PortIO配置访问机制
643+
Portiocam,
642644
/// PCI内存映射配置访问机制
643645
///
644646
/// 为每个设备功能提供256字节的配置空间访问。
@@ -653,6 +655,7 @@ impl PciCam {
653655
/// Returns the total size in bytes of the memory-mapped region.
654656
pub const fn size(self) -> u32 {
655657
match self {
658+
Self::Portiocam => 0x100000,
656659
Self::MmioCam => 0x1000000,
657660
Self::Ecam => 0x10000000,
658661
}

kernel/src/driver/pci/root.rs

Lines changed: 64 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,17 @@ use alloc::sync::Arc;
44
use hashbrown::HashMap;
55

66
use crate::{
7+
arch::{PciArch, TraitPciArch},
78
libs::spinlock::{SpinLock, SpinLockGuard},
89
mm::{
910
mmio_buddy::{mmio_pool, MMIOSpaceGuard},
1011
page::PAGE_2M_SIZE,
11-
PhysAddr,
1212
},
1313
};
1414

15-
use super::pci::{
16-
BusDeviceFunction, ExternalCapabilityIterator, PciCam, PciError, SegmentGroupNumber,
15+
use super::{
16+
ecam::EcamRootInfo,
17+
pci::{BusDeviceFunction, ExternalCapabilityIterator, PciCam, PciError, SegmentGroupNumber},
1718
};
1819

1920
lazy_static! {
@@ -28,13 +29,14 @@ pub fn pci_root_manager() -> &'static PciRootManager {
2829
/// 代表一个PCI segement greoup.
2930
#[derive(Clone, Debug)]
3031
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
32+
pub ecam_root_info: Option<EcamRootInfo>,
33+
pub mmio_guard: Option<Arc<MMIOSpaceGuard>>, //映射后的虚拟地址,为方便访问数据这里转化成指针
3634
/// 配置空间访问机制
3735
pub cam: PciCam,
36+
/// bus起始位置
37+
pub bus_begin: u8,
38+
/// bus结束位置
39+
pub bus_end: u8,
3840
}
3941

4042
///线程间共享需要,该结构体只需要在初始化时写入数据,无需读写锁保证线程安全
@@ -43,11 +45,15 @@ unsafe impl Sync for PciRoot {}
4345
///实现PciRoot的Display trait,自定义输出
4446
impl core::fmt::Display for PciRoot {
4547
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-
)
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+
}
5157
}
5258
}
5359

@@ -69,27 +75,28 @@ impl PciRoot {
6975
///
7076
/// - 成功执行后,结构体的内部状态将被初始化为包含映射后的虚拟地址。
7177
pub fn new(
72-
segment_group_number: SegmentGroupNumber,
78+
ecam_root_info: Option<EcamRootInfo>,
7379
cam: PciCam,
74-
phys_base: PhysAddr,
7580
bus_begin: u8,
7681
bus_end: u8,
7782
) -> Result<Arc<Self>, PciError> {
78-
assert_eq!(cam, PciCam::Ecam);
7983
let mut pci_root = Self {
80-
physical_address_base: phys_base,
84+
ecam_root_info,
8185
mmio_guard: None,
82-
segment_group_number,
86+
cam,
8387
bus_begin,
8488
bus_end,
85-
cam,
8689
};
87-
pci_root.map()?;
90+
91+
if ecam_root_info.is_some() {
92+
pci_root.map()?;
93+
}
8894

8995
Ok(Arc::new(pci_root))
9096
}
91-
/// @brief 完成物理地址到虚拟地址的映射,并将虚拟地址加入mmio_base变量
92-
/// @return 返回错误或Ok(0)
97+
98+
/// # 完成物理地址到虚拟地址的映射,并将虚拟地址加入mmio_base变量
99+
/// ## return 返回错误或Ok(0)
93100
fn map(&mut self) -> Result<u8, PciError> {
94101
//debug!("bus_begin={},bus_end={}", self.bus_begin,self.bus_end);
95102
let bus_number = (self.bus_end - self.bus_begin) as u32 + 1;
@@ -104,7 +111,7 @@ impl PciRoot {
104111
self.mmio_guard = Some(space_guard.clone());
105112

106113
assert!(space_guard
107-
.map_phys(self.physical_address_base, size)
114+
.map_phys(self.ecam_root_info.unwrap().physical_address_base, size)
108115
.is_ok());
109116
}
110117
return Ok(0);
@@ -129,18 +136,20 @@ impl PciRoot {
129136
/// - 此函数计算出的地址需要是字对齐的(即地址与0x3对齐)。如果不是,将panic。
130137
fn cam_offset(&self, bus_device_function: BusDeviceFunction, register_offset: u16) -> u32 {
131138
assert!(bus_device_function.valid());
132-
let bdf = ((bus_device_function.bus - self.bus_begin) as u32) << 8
139+
let bdf = ((bus_device_function.bus - self.ecam_root_info.unwrap().bus_begin) as u32) << 8
133140
| (bus_device_function.device as u32) << 3
134141
| bus_device_function.function as u32;
135142
let address =
136143
bdf << match self.cam {
144+
PciCam::Portiocam => 4,
137145
PciCam::MmioCam => 8,
138146
PciCam::Ecam => 12,
139147
} | register_offset as u32;
140148
// Ensure that address is word-aligned.
141149
assert!(address & 0x3 == 0);
142150
address
143151
}
152+
144153
/// # read_config - 通过bus_device_function和offset读取相应位置寄存器的值(32位)
145154
///
146155
/// 此函数用于通过指定的bus_device_function和register_offset读取PCI设备中相应位置的寄存器值。
@@ -154,12 +163,16 @@ impl PciRoot {
154163
///
155164
/// - `u32`: 寄存器读值结果
156165
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()
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)
163176
}
164177
}
165178

@@ -178,16 +191,21 @@ impl PciRoot {
178191
register_offset: u16,
179192
data: u32,
180193
) {
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)
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);
189206
}
190207
}
208+
191209
/// 返回迭代器,遍历pcie设备的external_capabilities
192210
#[allow(dead_code)]
193211
pub fn external_capabilities(
@@ -233,9 +251,14 @@ impl PciRootManager {
233251
/// - `pci_root`: Arc<PciRoot>,要添加的PciRoot的Arc指针
234252
pub fn add_pci_root(&self, pci_root: Arc<PciRoot>) {
235253
let mut inner = self.inner.lock();
236-
inner
237-
.pci_root
238-
.insert(pci_root.segment_group_number, pci_root);
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+
}
239262
}
240263

241264
/// # 检查是否存在PciRoot - 检查PciRootManager中是否存在指定segment_group_number的PciRoot

0 commit comments

Comments
 (0)