@@ -4,16 +4,17 @@ use alloc::sync::Arc;
4
4
use hashbrown:: HashMap ;
5
5
6
6
use crate :: {
7
+ arch:: { PciArch , TraitPciArch } ,
7
8
libs:: spinlock:: { SpinLock , SpinLockGuard } ,
8
9
mm:: {
9
10
mmio_buddy:: { mmio_pool, MMIOSpaceGuard } ,
10
11
page:: PAGE_2M_SIZE ,
11
- PhysAddr ,
12
12
} ,
13
13
} ;
14
14
15
- use super :: pci:: {
16
- BusDeviceFunction , ExternalCapabilityIterator , PciCam , PciError , SegmentGroupNumber ,
15
+ use super :: {
16
+ ecam:: EcamRootInfo ,
17
+ pci:: { BusDeviceFunction , ExternalCapabilityIterator , PciCam , PciError , SegmentGroupNumber } ,
17
18
} ;
18
19
19
20
lazy_static ! {
@@ -28,13 +29,14 @@ pub fn pci_root_manager() -> &'static PciRootManager {
28
29
/// 代表一个PCI segement greoup.
29
30
#[ derive( Clone , Debug ) ]
30
31
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 > > , //映射后的虚拟地址,为方便访问数据这里转化成指针
36
34
/// 配置空间访问机制
37
35
pub cam : PciCam ,
36
+ /// bus起始位置
37
+ pub bus_begin : u8 ,
38
+ /// bus结束位置
39
+ pub bus_end : u8 ,
38
40
}
39
41
40
42
///线程间共享需要,该结构体只需要在初始化时写入数据,无需读写锁保证线程安全
@@ -43,11 +45,15 @@ unsafe impl Sync for PciRoot {}
43
45
///实现PciRoot的Display trait,自定义输出
44
46
impl core:: fmt:: Display for PciRoot {
45
47
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
+ }
51
57
}
52
58
}
53
59
@@ -69,27 +75,28 @@ impl PciRoot {
69
75
///
70
76
/// - 成功执行后,结构体的内部状态将被初始化为包含映射后的虚拟地址。
71
77
pub fn new (
72
- segment_group_number : SegmentGroupNumber ,
78
+ ecam_root_info : Option < EcamRootInfo > ,
73
79
cam : PciCam ,
74
- phys_base : PhysAddr ,
75
80
bus_begin : u8 ,
76
81
bus_end : u8 ,
77
82
) -> Result < Arc < Self > , PciError > {
78
- assert_eq ! ( cam, PciCam :: Ecam ) ;
79
83
let mut pci_root = Self {
80
- physical_address_base : phys_base ,
84
+ ecam_root_info ,
81
85
mmio_guard : None ,
82
- segment_group_number ,
86
+ cam ,
83
87
bus_begin,
84
88
bus_end,
85
- cam,
86
89
} ;
87
- pci_root. map ( ) ?;
90
+
91
+ if ecam_root_info. is_some ( ) {
92
+ pci_root. map ( ) ?;
93
+ }
88
94
89
95
Ok ( Arc :: new ( pci_root) )
90
96
}
91
- /// @brief 完成物理地址到虚拟地址的映射,并将虚拟地址加入mmio_base变量
92
- /// @return 返回错误或Ok(0)
97
+
98
+ /// # 完成物理地址到虚拟地址的映射,并将虚拟地址加入mmio_base变量
99
+ /// ## return 返回错误或Ok(0)
93
100
fn map ( & mut self ) -> Result < u8 , PciError > {
94
101
//debug!("bus_begin={},bus_end={}", self.bus_begin,self.bus_end);
95
102
let bus_number = ( self . bus_end - self . bus_begin ) as u32 + 1 ;
@@ -104,7 +111,7 @@ impl PciRoot {
104
111
self . mmio_guard = Some ( space_guard. clone ( ) ) ;
105
112
106
113
assert ! ( space_guard
107
- . map_phys( self . physical_address_base, size)
114
+ . map_phys( self . ecam_root_info . unwrap ( ) . physical_address_base, size)
108
115
. is_ok( ) ) ;
109
116
}
110
117
return Ok ( 0 ) ;
@@ -129,18 +136,20 @@ impl PciRoot {
129
136
/// - 此函数计算出的地址需要是字对齐的(即地址与0x3对齐)。如果不是,将panic。
130
137
fn cam_offset ( & self , bus_device_function : BusDeviceFunction , register_offset : u16 ) -> u32 {
131
138
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
133
140
| ( bus_device_function. device as u32 ) << 3
134
141
| bus_device_function. function as u32 ;
135
142
let address =
136
143
bdf << match self . cam {
144
+ PciCam :: Portiocam => 4 ,
137
145
PciCam :: MmioCam => 8 ,
138
146
PciCam :: Ecam => 12 ,
139
147
} | register_offset as u32 ;
140
148
// Ensure that address is word-aligned.
141
149
assert ! ( address & 0x3 == 0 ) ;
142
150
address
143
151
}
152
+
144
153
/// # read_config - 通过bus_device_function和offset读取相应位置寄存器的值(32位)
145
154
///
146
155
/// 此函数用于通过指定的bus_device_function和register_offset读取PCI设备中相应位置的寄存器值。
@@ -154,12 +163,16 @@ impl PciRoot {
154
163
///
155
164
/// - `u32`: 寄存器读值结果
156
165
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 )
163
176
}
164
177
}
165
178
@@ -178,16 +191,21 @@ impl PciRoot {
178
191
register_offset : u16 ,
179
192
data : u32 ,
180
193
) {
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) ;
189
206
}
190
207
}
208
+
191
209
/// 返回迭代器,遍历pcie设备的external_capabilities
192
210
#[ allow( dead_code) ]
193
211
pub fn external_capabilities (
@@ -233,9 +251,14 @@ impl PciRootManager {
233
251
/// - `pci_root`: Arc<PciRoot>,要添加的PciRoot的Arc指针
234
252
pub fn add_pci_root ( & self , pci_root : Arc < PciRoot > ) {
235
253
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
+ }
239
262
}
240
263
241
264
/// # 检查是否存在PciRoot - 检查PciRootManager中是否存在指定segment_group_number的PciRoot
0 commit comments