1 // Copyright 2022 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 use std::str::FromStr;
6 use std::sync::mpsc;
7 use std::sync::Arc;
8
9 use base::warn;
10 use resources::Alloc;
11 use resources::SystemAllocator;
12 use sync::Mutex;
13 use zerocopy::FromBytes;
14
15 use crate::pci::pci_configuration::PciCapConfig;
16 use crate::pci::pci_configuration::PciCapConfigWriteResult;
17 use crate::pci::pci_configuration::PciCapMapping;
18 use crate::pci::pci_configuration::PciCapability;
19 use crate::pci::pcie::pci_bridge::PciBridgeBusRange;
20 use crate::pci::pcie::pcie_device::PcieCap;
21 use crate::pci::pcie::pcie_device::PcieDevice;
22 use crate::pci::pcie::pcie_host::PcieHostPort;
23 use crate::pci::pcie::*;
24 use crate::pci::pm::PciDevicePower;
25 use crate::pci::pm::PciPmCap;
26 use crate::pci::pm::PmConfig;
27 use crate::pci::pm::PmStatusChange;
28 use crate::pci::MsiConfig;
29 use crate::pci::PciAddress;
30 use crate::pci::PciDeviceError;
31
32 // reserve 8MB memory window
33 const PCIE_BR_MEM_SIZE: u64 = 0x80_0000;
34 // reserve 64MB prefetch window
35 const PCIE_BR_PREF_MEM_SIZE: u64 = 0x400_0000;
36
trigger_interrupt(msi: &Option<Arc<Mutex<MsiConfig>>>)37 fn trigger_interrupt(msi: &Option<Arc<Mutex<MsiConfig>>>) {
38 if let Some(msi_config) = msi {
39 let msi_config = msi_config.lock();
40 if msi_config.is_msi_enabled() {
41 msi_config.trigger()
42 }
43 }
44 }
45
46 struct PcieRootCap {
47 secondary_bus_num: u8,
48 subordinate_bus_num: u8,
49
50 control: u16,
51 status: u32,
52 pme_pending_requester_id: Option<u16>,
53
54 msi_config: Option<Arc<Mutex<MsiConfig>>>,
55 }
56
57 impl PcieRootCap {
new(secondary_bus_num: u8, subordinate_bus_num: u8) -> Self58 fn new(secondary_bus_num: u8, subordinate_bus_num: u8) -> Self {
59 PcieRootCap {
60 secondary_bus_num,
61 subordinate_bus_num,
62 control: 0,
63 status: 0,
64 pme_pending_requester_id: None,
65 msi_config: None,
66 }
67 }
68
clone_interrupt(&mut self, msi_config: Arc<Mutex<MsiConfig>>)69 fn clone_interrupt(&mut self, msi_config: Arc<Mutex<MsiConfig>>) {
70 self.msi_config = Some(msi_config);
71 }
72
trigger_pme_interrupt(&self)73 fn trigger_pme_interrupt(&self) {
74 if (self.control & PCIE_ROOTCTL_PME_ENABLE) != 0
75 && (self.status & PCIE_ROOTSTA_PME_STATUS) != 0
76 {
77 trigger_interrupt(&self.msi_config)
78 }
79 }
80 }
81
82 static PCIE_ROOTS_CAP: Mutex<Vec<Arc<Mutex<PcieRootCap>>>> = Mutex::new(Vec::new());
83
push_pcie_root_cap(root_cap: Arc<Mutex<PcieRootCap>>)84 fn push_pcie_root_cap(root_cap: Arc<Mutex<PcieRootCap>>) {
85 PCIE_ROOTS_CAP.lock().push(root_cap);
86 }
87
get_pcie_root_cap(bus_num: u8) -> Option<Arc<Mutex<PcieRootCap>>>88 fn get_pcie_root_cap(bus_num: u8) -> Option<Arc<Mutex<PcieRootCap>>> {
89 for root_cap in PCIE_ROOTS_CAP.lock().iter() {
90 let root_cap_lock = root_cap.lock();
91 if root_cap_lock.secondary_bus_num <= bus_num
92 && root_cap_lock.subordinate_bus_num >= bus_num
93 {
94 return Some(root_cap.clone());
95 }
96 }
97
98 None
99 }
100
101 pub struct PciePort {
102 device_id: u16,
103 debug_label: String,
104 preferred_address: Option<PciAddress>,
105 pci_address: Option<PciAddress>,
106 bus_range: PciBridgeBusRange,
107 pcie_host: Option<PcieHostPort>,
108 pcie_config: Arc<Mutex<PcieConfig>>,
109 pm_config: Arc<Mutex<PmConfig>>,
110
111 msi_config: Option<Arc<Mutex<MsiConfig>>>,
112
113 // For PcieRootPort, root_cap point to itself
114 // For PcieDownstreamPort or PciDownstreamPort, root_cap point to PcieRootPort its behind.
115 root_cap: Arc<Mutex<PcieRootCap>>,
116 port_type: PcieDevicePortType,
117
118 prepare_hotplug: bool,
119 }
120
121 impl PciePort {
122 /// Constructs a new PCIE port
new( device_id: u16, debug_label: String, primary_bus_num: u8, secondary_bus_num: u8, slot_implemented: bool, port_type: PcieDevicePortType, ) -> Self123 pub fn new(
124 device_id: u16,
125 debug_label: String,
126 primary_bus_num: u8,
127 secondary_bus_num: u8,
128 slot_implemented: bool,
129 port_type: PcieDevicePortType,
130 ) -> Self {
131 let bus_range = PciBridgeBusRange {
132 primary: primary_bus_num,
133 secondary: secondary_bus_num,
134 subordinate: secondary_bus_num,
135 };
136
137 let root_cap = if port_type == PcieDevicePortType::RootPort {
138 let cap = Arc::new(Mutex::new(PcieRootCap::new(
139 secondary_bus_num,
140 secondary_bus_num,
141 )));
142 push_pcie_root_cap(cap.clone());
143 cap
144 } else {
145 get_pcie_root_cap(primary_bus_num).expect("Pcie root port should be created at first")
146 };
147
148 PciePort {
149 device_id,
150 debug_label,
151 preferred_address: None,
152 pci_address: None,
153 bus_range,
154 pcie_host: None,
155 msi_config: None,
156 pcie_config: Arc::new(Mutex::new(PcieConfig::new(
157 root_cap.clone(),
158 slot_implemented,
159 port_type,
160 ))),
161 pm_config: Arc::new(Mutex::new(PmConfig::new(false))),
162
163 root_cap,
164 port_type,
165
166 prepare_hotplug: false,
167 }
168 }
169
new_from_host( pcie_host: PcieHostPort, slot_implemented: bool, port_type: PcieDevicePortType, ) -> std::result::Result<Self, PciDeviceError>170 pub fn new_from_host(
171 pcie_host: PcieHostPort,
172 slot_implemented: bool,
173 port_type: PcieDevicePortType,
174 ) -> std::result::Result<Self, PciDeviceError> {
175 let bus_range = pcie_host.get_bus_range();
176 let host_address = PciAddress::from_str(&pcie_host.host_name())
177 .map_err(|e| PciDeviceError::PciAddressParseFailure(pcie_host.host_name(), e))?;
178 let root_cap = if port_type == PcieDevicePortType::RootPort {
179 let cap = Arc::new(Mutex::new(PcieRootCap::new(
180 bus_range.secondary,
181 bus_range.subordinate,
182 )));
183 push_pcie_root_cap(cap.clone());
184 cap
185 } else {
186 get_pcie_root_cap(bus_range.primary).expect("Pcie root port should be created at first")
187 };
188
189 Ok(PciePort {
190 device_id: pcie_host.read_device_id(),
191 debug_label: pcie_host.host_name(),
192 preferred_address: Some(host_address),
193 pci_address: None,
194 bus_range,
195 pcie_host: Some(pcie_host),
196 msi_config: None,
197 pcie_config: Arc::new(Mutex::new(PcieConfig::new(
198 root_cap.clone(),
199 slot_implemented,
200 port_type,
201 ))),
202 pm_config: Arc::new(Mutex::new(PmConfig::new(false))),
203
204 root_cap,
205 port_type,
206
207 prepare_hotplug: false,
208 })
209 }
210
get_device_id(&self) -> u16211 pub fn get_device_id(&self) -> u16 {
212 self.device_id
213 }
214
get_address(&self) -> Option<PciAddress>215 pub fn get_address(&self) -> Option<PciAddress> {
216 self.pci_address
217 }
218
debug_label(&self) -> String219 pub fn debug_label(&self) -> String {
220 self.debug_label.clone()
221 }
222
preferred_address(&self) -> Option<PciAddress>223 pub fn preferred_address(&self) -> Option<PciAddress> {
224 self.preferred_address
225 }
226
allocate_address( &mut self, resources: &mut SystemAllocator, ) -> std::result::Result<PciAddress, PciDeviceError>227 pub fn allocate_address(
228 &mut self,
229 resources: &mut SystemAllocator,
230 ) -> std::result::Result<PciAddress, PciDeviceError> {
231 if self.pci_address.is_none() {
232 if let Some(address) = self.preferred_address {
233 if resources.reserve_pci(
234 Alloc::PciBar {
235 bus: address.bus,
236 dev: address.dev,
237 func: address.func,
238 bar: 0,
239 },
240 self.debug_label(),
241 ) {
242 self.pci_address = Some(address);
243 } else {
244 self.pci_address = None;
245 }
246 } else {
247 match resources.allocate_pci(self.bus_range.primary, self.debug_label()) {
248 Some(Alloc::PciBar {
249 bus,
250 dev,
251 func,
252 bar: _,
253 }) => self.pci_address = Some(PciAddress { bus, dev, func }),
254 _ => self.pci_address = None,
255 }
256 }
257 }
258 self.pci_address.ok_or(PciDeviceError::PciAllocationFailed)
259 }
260
read_config(&self, reg_idx: usize, data: &mut u32)261 pub fn read_config(&self, reg_idx: usize, data: &mut u32) {
262 if let Some(host) = &self.pcie_host {
263 host.read_config(reg_idx, data);
264 }
265 }
266
write_config(&mut self, reg_idx: usize, offset: u64, data: &[u8])267 pub fn write_config(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
268 if let Some(host) = self.pcie_host.as_mut() {
269 host.write_config(reg_idx, offset, data);
270 }
271 }
272
handle_cap_write_result(&mut self, res: Box<dyn PciCapConfigWriteResult>)273 pub fn handle_cap_write_result(&mut self, res: Box<dyn PciCapConfigWriteResult>) {
274 if let Some(status) = res.downcast_ref::<PmStatusChange>() {
275 if status.from == PciDevicePower::D3
276 && status.to == PciDevicePower::D0
277 && self.prepare_hotplug
278 {
279 if let Some(host) = self.pcie_host.as_mut() {
280 host.hotplug_probe();
281 self.prepare_hotplug = false;
282 }
283 }
284 }
285 }
286
get_caps(&self) -> Vec<(Box<dyn PciCapability>, Option<Box<dyn PciCapConfig>>)>287 pub fn get_caps(&self) -> Vec<(Box<dyn PciCapability>, Option<Box<dyn PciCapConfig>>)> {
288 vec![
289 (
290 Box::new(PcieCap::new(self.port_type, self.hotplug_implemented(), 0)),
291 Some(Box::new(self.pcie_config.clone())),
292 ),
293 (
294 Box::new(PciPmCap::new()),
295 Some(Box::new(self.pm_config.clone())),
296 ),
297 ]
298 }
299
get_bus_range(&self) -> Option<PciBridgeBusRange>300 pub fn get_bus_range(&self) -> Option<PciBridgeBusRange> {
301 Some(self.bus_range)
302 }
303
get_bridge_window_size(&self) -> (u64, u64)304 pub fn get_bridge_window_size(&self) -> (u64, u64) {
305 if let Some(host) = &self.pcie_host {
306 host.get_bridge_window_size()
307 } else {
308 (PCIE_BR_MEM_SIZE, PCIE_BR_PREF_MEM_SIZE)
309 }
310 }
311
clone_interrupt(&mut self, msi_config: Arc<Mutex<MsiConfig>>)312 pub fn clone_interrupt(&mut self, msi_config: Arc<Mutex<MsiConfig>>) {
313 if self.port_type == PcieDevicePortType::RootPort {
314 self.root_cap.lock().clone_interrupt(msi_config.clone());
315 }
316 self.pcie_config.lock().msi_config = Some(msi_config.clone());
317 self.msi_config = Some(msi_config);
318 }
319
hotplug_implemented(&self) -> bool320 pub fn hotplug_implemented(&self) -> bool {
321 self.pcie_config.lock().slot_control.is_some()
322 }
323
inject_pme(&mut self, requester_id: u16)324 pub fn inject_pme(&mut self, requester_id: u16) {
325 let mut r = self.root_cap.lock();
326 if (r.status & PCIE_ROOTSTA_PME_STATUS) != 0 {
327 r.status |= PCIE_ROOTSTA_PME_PENDING;
328 r.pme_pending_requester_id = Some(requester_id);
329 } else {
330 r.status &= !PCIE_ROOTSTA_PME_REQ_ID_MASK;
331 r.status |= requester_id as u32;
332 r.pme_pending_requester_id = None;
333 r.status |= PCIE_ROOTSTA_PME_STATUS;
334 r.trigger_pme_interrupt();
335 }
336 }
337
338 /// Has command completion pending.
is_cc_pending(&self) -> bool339 pub fn is_cc_pending(&self) -> bool {
340 self.pcie_config.lock().cc_sender.is_some()
341 }
342
343 /// Sets a sender for notifying guest report command complete. Returns sender replaced.
set_cc_sender(&mut self, cc_sender: mpsc::Sender<()>) -> Option<mpsc::Sender<()>>344 pub fn set_cc_sender(&mut self, cc_sender: mpsc::Sender<()>) -> Option<mpsc::Sender<()>> {
345 self.pcie_config.lock().cc_sender.replace(cc_sender)
346 }
347
trigger_hp_or_pme_interrupt(&mut self)348 pub fn trigger_hp_or_pme_interrupt(&mut self) {
349 if self.pm_config.lock().should_trigger_pme() {
350 self.pcie_config.lock().hp_interrupt_pending = true;
351 self.inject_pme(self.pci_address.unwrap().pme_requester_id());
352 } else {
353 self.pcie_config.lock().trigger_hp_interrupt();
354 }
355 }
356
is_host(&self) -> bool357 pub fn is_host(&self) -> bool {
358 self.pcie_host.is_some()
359 }
360
hot_unplug(&mut self)361 pub fn hot_unplug(&mut self) {
362 if let Some(host) = self.pcie_host.as_mut() {
363 host.hot_unplug()
364 }
365 }
366
is_match(&self, host_addr: PciAddress) -> Option<u8>367 pub fn is_match(&self, host_addr: PciAddress) -> Option<u8> {
368 if host_addr.bus == self.bus_range.secondary || self.pcie_host.is_none() {
369 Some(self.bus_range.secondary)
370 } else {
371 None
372 }
373 }
374
removed_downstream_valid(&self) -> bool375 pub fn removed_downstream_valid(&self) -> bool {
376 self.pcie_config.lock().removed_downstream_valid
377 }
378
set_slot_status(&mut self, flag: u16)379 pub fn set_slot_status(&mut self, flag: u16) {
380 self.pcie_config.lock().set_slot_status(flag);
381 }
382
should_trigger_pme(&mut self) -> bool383 pub fn should_trigger_pme(&mut self) -> bool {
384 self.pm_config.lock().should_trigger_pme()
385 }
386
prepare_hotplug(&mut self)387 pub fn prepare_hotplug(&mut self) {
388 self.prepare_hotplug = true;
389 }
390 }
391
392 pub struct PcieConfig {
393 msi_config: Option<Arc<Mutex<MsiConfig>>>,
394
395 slot_control: Option<u16>,
396 slot_status: u16,
397
398 // For PcieRootPort, root_cap point to itself
399 // For PcieDownstreamPort or PciDownstreamPort, root_cap point to PcieRootPort its behind.
400 root_cap: Arc<Mutex<PcieRootCap>>,
401 port_type: PcieDevicePortType,
402
403 cc_sender: Option<mpsc::Sender<()>>,
404 hp_interrupt_pending: bool,
405 removed_downstream_valid: bool,
406
407 cap_mapping: Option<PciCapMapping>,
408 }
409
410 impl PcieConfig {
new( root_cap: Arc<Mutex<PcieRootCap>>, slot_implemented: bool, port_type: PcieDevicePortType, ) -> Self411 fn new(
412 root_cap: Arc<Mutex<PcieRootCap>>,
413 slot_implemented: bool,
414 port_type: PcieDevicePortType,
415 ) -> Self {
416 PcieConfig {
417 msi_config: None,
418
419 slot_control: if slot_implemented {
420 Some(PCIE_SLTCTL_PIC_OFF | PCIE_SLTCTL_AIC_OFF)
421 } else {
422 None
423 },
424 slot_status: 0,
425
426 root_cap,
427 port_type,
428
429 cc_sender: None,
430 hp_interrupt_pending: false,
431 removed_downstream_valid: false,
432
433 cap_mapping: None,
434 }
435 }
436
read_pcie_cap(&self, offset: usize, data: &mut u32)437 fn read_pcie_cap(&self, offset: usize, data: &mut u32) {
438 if offset == PCIE_SLTCTL_OFFSET {
439 *data = ((self.slot_status as u32) << 16) | (self.get_slot_control() as u32);
440 } else if offset == PCIE_ROOTCTL_OFFSET {
441 *data = match self.port_type {
442 PcieDevicePortType::RootPort => self.root_cap.lock().control as u32,
443 _ => 0,
444 };
445 } else if offset == PCIE_ROOTSTA_OFFSET {
446 *data = match self.port_type {
447 PcieDevicePortType::RootPort => self.root_cap.lock().status,
448 _ => 0,
449 };
450 }
451 }
452
write_pcie_cap(&mut self, offset: usize, data: &[u8])453 fn write_pcie_cap(&mut self, offset: usize, data: &[u8]) {
454 self.removed_downstream_valid = false;
455 match offset {
456 PCIE_SLTCTL_OFFSET => {
457 let value = match u16::read_from(data) {
458 Some(v) => v,
459 None => {
460 warn!("write SLTCTL isn't word, len: {}", data.len());
461 return;
462 }
463 };
464
465 // if slot is populated, power indicator is off,
466 // it will detach devices
467 let old_control = self.get_slot_control();
468 match self.slot_control.as_mut() {
469 Some(v) => *v = value,
470 None => return,
471 }
472 if (self.slot_status & PCIE_SLTSTA_PDS != 0)
473 && (value & PCIE_SLTCTL_PIC_OFF == PCIE_SLTCTL_PIC_OFF)
474 && (old_control & PCIE_SLTCTL_PIC_OFF != PCIE_SLTCTL_PIC_OFF)
475 {
476 self.removed_downstream_valid = true;
477 self.slot_status &= !PCIE_SLTSTA_PDS;
478 self.trigger_hp_interrupt();
479 }
480
481 // Guest enable hotplug interrupt and has hotplug interrupt
482 // pending, inject it right row.
483 if (old_control & PCIE_SLTCTL_HPIE == 0)
484 && (value & PCIE_SLTCTL_HPIE == PCIE_SLTCTL_HPIE)
485 && self.hp_interrupt_pending
486 {
487 self.hp_interrupt_pending = false;
488 self.trigger_hp_interrupt();
489 }
490
491 if old_control != value {
492 // send Command completed events
493 if let Some(sender) = self.cc_sender.take() {
494 if let Err(e) = sender.send(()) {
495 warn!("Failed to notify command complete for slot event: {:#}", &e);
496 }
497 }
498 self.slot_status |= PCIE_SLTSTA_CC;
499 self.trigger_cc_interrupt();
500 }
501 }
502 PCIE_SLTSTA_OFFSET => {
503 if self.slot_control.is_none() {
504 return;
505 }
506 let value = match u16::read_from(data) {
507 Some(v) => v,
508 None => {
509 warn!("write SLTSTA isn't word, len: {}", data.len());
510 return;
511 }
512 };
513 if value & PCIE_SLTSTA_ABP != 0 {
514 self.slot_status &= !PCIE_SLTSTA_ABP;
515 }
516 if value & PCIE_SLTSTA_PFD != 0 {
517 self.slot_status &= !PCIE_SLTSTA_PFD;
518 }
519 if value & PCIE_SLTSTA_PDC != 0 {
520 self.slot_status &= !PCIE_SLTSTA_PDC;
521 }
522 if value & PCIE_SLTSTA_CC != 0 {
523 self.slot_status &= !PCIE_SLTSTA_CC;
524 }
525 if value & PCIE_SLTSTA_DLLSC != 0 {
526 self.slot_status &= !PCIE_SLTSTA_DLLSC;
527 }
528 }
529 PCIE_ROOTCTL_OFFSET => match u16::read_from(data) {
530 Some(v) => {
531 if self.port_type == PcieDevicePortType::RootPort {
532 self.root_cap.lock().control = v;
533 } else {
534 warn!("write root control register while device isn't root port");
535 }
536 }
537 None => warn!("write root control isn't word, len: {}", data.len()),
538 },
539 PCIE_ROOTSTA_OFFSET => match u32::read_from(data) {
540 Some(v) => {
541 if self.port_type == PcieDevicePortType::RootPort {
542 if v & PCIE_ROOTSTA_PME_STATUS != 0 {
543 let mut r = self.root_cap.lock();
544 if let Some(requester_id) = r.pme_pending_requester_id {
545 r.status &= !PCIE_ROOTSTA_PME_PENDING;
546 r.status &= !PCIE_ROOTSTA_PME_REQ_ID_MASK;
547 r.status |= requester_id as u32;
548 r.status |= PCIE_ROOTSTA_PME_STATUS;
549 r.pme_pending_requester_id = None;
550 r.trigger_pme_interrupt();
551 } else {
552 r.status &= !PCIE_ROOTSTA_PME_STATUS;
553 }
554 }
555 } else {
556 warn!("write root status register while device isn't root port");
557 }
558 }
559 None => warn!("write root status isn't dword, len: {}", data.len()),
560 },
561 _ => (),
562 }
563 }
564
get_slot_control(&self) -> u16565 fn get_slot_control(&self) -> u16 {
566 if let Some(slot_control) = self.slot_control {
567 return slot_control;
568 }
569 0
570 }
571
trigger_cc_interrupt(&self)572 fn trigger_cc_interrupt(&self) {
573 if (self.get_slot_control() & PCIE_SLTCTL_CCIE) != 0
574 && (self.slot_status & PCIE_SLTSTA_CC) != 0
575 {
576 trigger_interrupt(&self.msi_config)
577 }
578 }
579
trigger_hp_interrupt(&mut self)580 fn trigger_hp_interrupt(&mut self) {
581 let slot_control = self.get_slot_control();
582 if (slot_control & PCIE_SLTCTL_HPIE) != 0 {
583 self.set_slot_status(PCIE_SLTSTA_PDC);
584 if (self.slot_status & slot_control & (PCIE_SLTCTL_ABPE | PCIE_SLTCTL_PDCE)) != 0 {
585 trigger_interrupt(&self.msi_config)
586 }
587 }
588 }
589
set_slot_status(&mut self, flag: u16)590 fn set_slot_status(&mut self, flag: u16) {
591 self.slot_status |= flag;
592 if let Some(mapping) = self.cap_mapping.as_mut() {
593 mapping.set_reg(
594 PCIE_SLTCTL_OFFSET / 4,
595 (self.slot_status as u32) << 16,
596 0xffff0000,
597 );
598 }
599 }
600 }
601
602 const PCIE_CONFIG_READ_MASK: [u32; PCIE_CAP_LEN / 4] = {
603 let mut arr: [u32; PCIE_CAP_LEN / 4] = [0; PCIE_CAP_LEN / 4];
604 arr[PCIE_SLTCTL_OFFSET / 4] = 0xffffffff;
605 arr[PCIE_ROOTCTL_OFFSET / 4] = 0xffffffff;
606 arr[PCIE_ROOTSTA_OFFSET / 4] = 0xffffffff;
607 arr
608 };
609
610 impl PciCapConfig for PcieConfig {
read_mask(&self) -> &'static [u32]611 fn read_mask(&self) -> &'static [u32] {
612 &PCIE_CONFIG_READ_MASK
613 }
614
read_reg(&self, reg_idx: usize) -> u32615 fn read_reg(&self, reg_idx: usize) -> u32 {
616 let mut data = 0;
617 self.read_pcie_cap(reg_idx * 4, &mut data);
618 data
619 }
620
write_reg( &mut self, reg_idx: usize, offset: u64, data: &[u8], ) -> Option<Box<dyn PciCapConfigWriteResult>>621 fn write_reg(
622 &mut self,
623 reg_idx: usize,
624 offset: u64,
625 data: &[u8],
626 ) -> Option<Box<dyn PciCapConfigWriteResult>> {
627 self.write_pcie_cap(reg_idx * 4 + offset as usize, data);
628 None
629 }
630
set_cap_mapping(&mut self, mapping: PciCapMapping)631 fn set_cap_mapping(&mut self, mapping: PciCapMapping) {
632 self.cap_mapping = Some(mapping);
633 }
634 }
635
636 /// Helper trait for implementing PcieDevice where most functions
637 /// are proxied directly to a PciePort instance.
638 pub trait PciePortVariant: Send {
get_pcie_port(&self) -> &PciePort639 fn get_pcie_port(&self) -> &PciePort;
get_pcie_port_mut(&mut self) -> &mut PciePort640 fn get_pcie_port_mut(&mut self) -> &mut PciePort;
641
642 /// Called via PcieDevice.get_removed_devices
get_removed_devices_impl(&self) -> Vec<PciAddress>643 fn get_removed_devices_impl(&self) -> Vec<PciAddress>;
644
645 /// Called via PcieDevice.hotplug_implemented
hotplug_implemented_impl(&self) -> bool646 fn hotplug_implemented_impl(&self) -> bool;
647
648 /// Called via PcieDevice.hotplug
hotplugged_impl(&self) -> bool649 fn hotplugged_impl(&self) -> bool;
650 }
651
652 impl<T: PciePortVariant> PcieDevice for T {
get_device_id(&self) -> u16653 fn get_device_id(&self) -> u16 {
654 self.get_pcie_port().get_device_id()
655 }
656
debug_label(&self) -> String657 fn debug_label(&self) -> String {
658 self.get_pcie_port().debug_label()
659 }
660
preferred_address(&self) -> Option<PciAddress>661 fn preferred_address(&self) -> Option<PciAddress> {
662 self.get_pcie_port().preferred_address()
663 }
664
allocate_address( &mut self, resources: &mut SystemAllocator, ) -> std::result::Result<PciAddress, PciDeviceError>665 fn allocate_address(
666 &mut self,
667 resources: &mut SystemAllocator,
668 ) -> std::result::Result<PciAddress, PciDeviceError> {
669 self.get_pcie_port_mut().allocate_address(resources)
670 }
671
clone_interrupt(&mut self, msi_config: Arc<Mutex<MsiConfig>>)672 fn clone_interrupt(&mut self, msi_config: Arc<Mutex<MsiConfig>>) {
673 self.get_pcie_port_mut().clone_interrupt(msi_config);
674 }
675
read_config(&self, reg_idx: usize, data: &mut u32)676 fn read_config(&self, reg_idx: usize, data: &mut u32) {
677 self.get_pcie_port().read_config(reg_idx, data);
678 }
679
write_config(&mut self, reg_idx: usize, offset: u64, data: &[u8])680 fn write_config(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
681 self.get_pcie_port_mut().write_config(reg_idx, offset, data);
682 }
683
get_caps(&self) -> Vec<(Box<dyn PciCapability>, Option<Box<dyn PciCapConfig>>)>684 fn get_caps(&self) -> Vec<(Box<dyn PciCapability>, Option<Box<dyn PciCapConfig>>)> {
685 self.get_pcie_port().get_caps()
686 }
687
handle_cap_write_result(&mut self, res: Box<dyn PciCapConfigWriteResult>)688 fn handle_cap_write_result(&mut self, res: Box<dyn PciCapConfigWriteResult>) {
689 self.get_pcie_port_mut().handle_cap_write_result(res)
690 }
691
get_bus_range(&self) -> Option<PciBridgeBusRange>692 fn get_bus_range(&self) -> Option<PciBridgeBusRange> {
693 self.get_pcie_port().get_bus_range()
694 }
695
get_removed_devices(&self) -> Vec<PciAddress>696 fn get_removed_devices(&self) -> Vec<PciAddress> {
697 self.get_removed_devices_impl()
698 }
699
hotplug_implemented(&self) -> bool700 fn hotplug_implemented(&self) -> bool {
701 self.hotplug_implemented_impl()
702 }
703
hotplugged(&self) -> bool704 fn hotplugged(&self) -> bool {
705 self.hotplugged_impl()
706 }
707
get_bridge_window_size(&self) -> (u64, u64)708 fn get_bridge_window_size(&self) -> (u64, u64) {
709 self.get_pcie_port().get_bridge_window_size()
710 }
711 }
712