• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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