xref: /aosp_15_r20/external/crosvm/devices/src/pci/pcie/pcie_device.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1 // Copyright 2021 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::sync::Arc;
6 
7 use resources::SystemAllocator;
8 use sync::Mutex;
9 use zerocopy::AsBytes;
10 
11 use crate::pci::pci_configuration::PciCapConfig;
12 use crate::pci::pci_configuration::PciCapConfigWriteResult;
13 use crate::pci::pci_configuration::PciCapabilityID;
14 use crate::pci::pcie::pci_bridge::PciBridgeBusRange;
15 use crate::pci::pcie::*;
16 use crate::pci::MsiConfig;
17 use crate::pci::PciAddress;
18 use crate::pci::PciCapability;
19 use crate::pci::PciDeviceError;
20 
21 pub trait PcieDevice: Send {
get_device_id(&self) -> u1622     fn get_device_id(&self) -> u16;
debug_label(&self) -> String23     fn debug_label(&self) -> String;
preferred_address(&self) -> Option<PciAddress>24     fn preferred_address(&self) -> Option<PciAddress> {
25         None
26     }
allocate_address( &mut self, resources: &mut SystemAllocator, ) -> std::result::Result<PciAddress, PciDeviceError>27     fn allocate_address(
28         &mut self,
29         resources: &mut SystemAllocator,
30     ) -> std::result::Result<PciAddress, PciDeviceError>;
read_config(&self, reg_idx: usize, data: &mut u32)31     fn read_config(&self, reg_idx: usize, data: &mut u32);
write_config(&mut self, reg_idx: usize, offset: u64, data: &[u8])32     fn write_config(&mut self, reg_idx: usize, offset: u64, data: &[u8]);
handle_cap_write_result(&mut self, res: Box<dyn PciCapConfigWriteResult>)33     fn handle_cap_write_result(&mut self, res: Box<dyn PciCapConfigWriteResult>);
clone_interrupt(&mut self, msi_config: Arc<Mutex<MsiConfig>>)34     fn clone_interrupt(&mut self, msi_config: Arc<Mutex<MsiConfig>>);
get_caps(&self) -> Vec<(Box<dyn PciCapability>, Option<Box<dyn PciCapConfig>>)>35     fn get_caps(&self) -> Vec<(Box<dyn PciCapability>, Option<Box<dyn PciCapConfig>>)>;
get_bus_range(&self) -> Option<PciBridgeBusRange>36     fn get_bus_range(&self) -> Option<PciBridgeBusRange> {
37         None
38     }
get_removed_devices(&self) -> Vec<PciAddress>39     fn get_removed_devices(&self) -> Vec<PciAddress>;
40 
41     /// Hotplug capability is implemented on this bridge or not.
42     /// Return true, the children pci devices could be connected through hotplug
43     /// Return false, the children pci devices should be connected statically
hotplug_implemented(&self) -> bool44     fn hotplug_implemented(&self) -> bool;
45 
46     /// This function returns true if this pcie device is hotplugged into the system
hotplugged(&self) -> bool47     fn hotplugged(&self) -> bool;
48 
49     /// Get bridge window size to cover children's mmio size
50     /// (u64, u64) -> (non_prefetchable window size, prefetchable_window_size)
get_bridge_window_size(&self) -> (u64, u64)51     fn get_bridge_window_size(&self) -> (u64, u64);
52 }
53 
54 #[repr(C)]
55 #[derive(Clone, Copy, AsBytes)]
56 pub struct PcieCap {
57     _cap_vndr: u8,
58     _cap_next: u8,
59     pcie_cap: u16,
60     dev_cap: u32,
61     dev_control: u16,
62     dev_status: u16,
63     link_cap: u32,
64     link_control: u16,
65     link_status: u16,
66     slot_cap: u32,
67     slot_control: u16,
68     slot_status: u16,
69     root_control: u16,
70     root_cap: u16,
71     root_status: u32,
72     dev_cap_2: u32,
73     dev_control_2: u16,
74     dev_status_2: u16,
75     link_cap_2: u32,
76     link_control_2: u16,
77     link_status_2: u16,
78     slot_cap_2: u32,
79     slot_control_2: u16,
80     slot_status_2: u16,
81 }
82 
83 impl PciCapability for PcieCap {
bytes(&self) -> &[u8]84     fn bytes(&self) -> &[u8] {
85         self.as_bytes()
86     }
87 
id(&self) -> PciCapabilityID88     fn id(&self) -> PciCapabilityID {
89         PciCapabilityID::PciExpress
90     }
91 
writable_bits(&self) -> Vec<u32>92     fn writable_bits(&self) -> Vec<u32> {
93         vec![
94             0u32,
95             0,
96             0xf_ffff,
97             0,
98             0x3000_0fff,
99             0,
100             0x11f_1fff,
101             0x1f,
102             0,
103             0,
104             0,
105             0,
106             0,
107             0,
108             0,
109         ]
110     }
111 }
112 
113 impl PcieCap {
new(device_type: PcieDevicePortType, slot: bool, irq_num: u16) -> Self114     pub fn new(device_type: PcieDevicePortType, slot: bool, irq_num: u16) -> Self {
115         let mut pcie_cap = PCIE_CAP_VERSION;
116         pcie_cap |= (device_type as u16) << PCIE_TYPE_SHIFT;
117         if slot {
118             pcie_cap |= 1 << PCIE_CAP_SLOT_SHIFT;
119         }
120         pcie_cap |= irq_num << PCIE_CAP_IRQ_NUM_SHIFT;
121 
122         let dev_cap = PCIE_DEVCAP_RBER;
123         let link_cap = (PCIE_LINK_X1 | PCIE_LINK_2_5GT) as u32;
124         let link_status = PCIE_LINK_X1 | PCIE_LINK_2_5GT;
125 
126         let mut slot_cap: u32 = 0;
127         let mut slot_control: u16 = 0;
128         if slot {
129             slot_cap = PCIE_SLTCAP_ABP
130                 | PCIE_SLTCAP_AIP
131                 | PCIE_SLTCAP_PIP
132                 | PCIE_SLTCAP_HPS
133                 | PCIE_SLTCAP_HPC;
134             slot_control = PCIE_SLTCTL_PIC_OFF | PCIE_SLTCTL_AIC_OFF;
135         }
136 
137         PcieCap {
138             _cap_vndr: 0,
139             _cap_next: 0,
140             pcie_cap,
141             dev_cap,
142             dev_control: 0,
143             dev_status: 0,
144             link_cap,
145             link_control: 0,
146             link_status,
147             slot_cap,
148             slot_control,
149             slot_status: 0,
150             root_control: 0,
151             root_cap: 0,
152             root_status: 0,
153             dev_cap_2: 0,
154             dev_control_2: 0,
155             dev_status_2: 0,
156             link_cap_2: 0,
157             link_control_2: 0,
158             link_status_2: 0,
159             slot_cap_2: 0,
160             slot_control_2: 0,
161             slot_status_2: 0,
162         }
163     }
164 }
165