1 // Copyright 2021 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 use std::sync::Arc; 5 use sync::Mutex; 6 7 use crate::pci::pci_configuration::PciCapabilityID; 8 use crate::pci::pcie::pci_bridge::PciBridgeBusRange; 9 use crate::pci::pcie::*; 10 use crate::pci::{MsixConfig, PciAddress, PciCapability, PciDeviceError}; 11 use data_model::DataInit; 12 use resources::SystemAllocator; 13 14 pub trait PcieDevice: Send { get_device_id(&self) -> u1615 fn get_device_id(&self) -> u16; debug_label(&self) -> String16 fn debug_label(&self) -> String; allocate_address( &mut self, resources: &mut SystemAllocator, ) -> std::result::Result<PciAddress, PciDeviceError>17 fn allocate_address( 18 &mut self, 19 resources: &mut SystemAllocator, 20 ) -> std::result::Result<PciAddress, PciDeviceError>; read_config(&self, reg_idx: usize, data: &mut u32)21 fn read_config(&self, reg_idx: usize, data: &mut u32); write_config(&mut self, reg_idx: usize, offset: u64, data: &[u8])22 fn write_config(&mut self, reg_idx: usize, offset: u64, data: &[u8]); clone_interrupt(&mut self, msix_config: Arc<Mutex<MsixConfig>>)23 fn clone_interrupt(&mut self, msix_config: Arc<Mutex<MsixConfig>>); get_caps(&self) -> Vec<Box<dyn PciCapability>>24 fn get_caps(&self) -> Vec<Box<dyn PciCapability>>; set_capability_reg_idx(&mut self, id: PciCapabilityID, reg_idx: usize)25 fn set_capability_reg_idx(&mut self, id: PciCapabilityID, reg_idx: usize); get_bus_range(&self) -> Option<PciBridgeBusRange>26 fn get_bus_range(&self) -> Option<PciBridgeBusRange> { 27 None 28 } get_removed_devices(&self) -> Vec<PciAddress>29 fn get_removed_devices(&self) -> Vec<PciAddress>; 30 31 /// Hotplug capability is implemented on this bridge or not. 32 /// Return true, the children pci devices could be connected through hotplug 33 /// Return false, the children pci devices should be connected statically hotplug_implemented(&self) -> bool34 fn hotplug_implemented(&self) -> bool; 35 36 /// Get bridge window size to cover children's mmio size 37 /// (u64, u64) -> (non_prefetchable window size, prefetchable_window_size) get_bridge_window_size(&self) -> (u64, u64)38 fn get_bridge_window_size(&self) -> (u64, u64); 39 } 40 41 #[repr(C)] 42 #[derive(Clone, Copy)] 43 pub struct PcieCap { 44 _cap_vndr: u8, 45 _cap_next: u8, 46 pcie_cap: u16, 47 dev_cap: u32, 48 dev_control: u16, 49 dev_status: u16, 50 link_cap: u32, 51 link_control: u16, 52 link_status: u16, 53 slot_cap: u32, 54 slot_control: u16, 55 slot_status: u16, 56 root_control: u16, 57 root_cap: u16, 58 root_status: u32, 59 dev_cap_2: u32, 60 dev_control_2: u16, 61 dev_status_2: u16, 62 link_cap_2: u32, 63 link_control_2: u16, 64 link_status_2: u16, 65 slot_cap_2: u32, 66 slot_control_2: u16, 67 slot_status_2: u16, 68 } 69 // It is safe to implement DataInit; all members are simple numbers and any value is valid. 70 unsafe impl DataInit for PcieCap {} 71 72 impl PciCapability for PcieCap { bytes(&self) -> &[u8]73 fn bytes(&self) -> &[u8] { 74 self.as_slice() 75 } 76 id(&self) -> PciCapabilityID77 fn id(&self) -> PciCapabilityID { 78 PciCapabilityID::PciExpress 79 } 80 writable_bits(&self) -> Vec<u32>81 fn writable_bits(&self) -> Vec<u32> { 82 vec![ 83 0u32, 84 0, 85 0xf_ffff, 86 0, 87 0x3000_0fff, 88 0, 89 0x11f_1fff, 90 0x1f, 91 0, 92 0, 93 0, 94 0, 95 0, 96 0, 97 0, 98 ] 99 } 100 } 101 102 impl PcieCap { new(device_type: PcieDevicePortType, slot: bool, irq_num: u16) -> Self103 pub fn new(device_type: PcieDevicePortType, slot: bool, irq_num: u16) -> Self { 104 let mut pcie_cap = PCIE_CAP_VERSION; 105 pcie_cap |= (device_type as u16) << PCIE_TYPE_SHIFT; 106 if slot { 107 pcie_cap |= 1 << PCIE_CAP_SLOT_SHIFT; 108 } 109 pcie_cap |= irq_num << PCIE_CAP_IRQ_NUM_SHIFT; 110 111 let dev_cap = PCIE_DEVCAP_RBER; 112 let link_cap = (PCIE_LINK_X1 | PCIE_LINK_2_5GT) as u32; 113 let link_status = PCIE_LINK_X1 | PCIE_LINK_2_5GT; 114 115 let mut slot_cap: u32 = 0; 116 let mut slot_control: u16 = 0; 117 if slot { 118 slot_cap = PCIE_SLTCAP_ABP 119 | PCIE_SLTCAP_AIP 120 | PCIE_SLTCAP_PIP 121 | PCIE_SLTCAP_HPS 122 | PCIE_SLTCAP_HPC; 123 slot_control = PCIE_SLTCTL_PIC_OFF | PCIE_SLTCTL_AIC_OFF; 124 } 125 126 PcieCap { 127 _cap_vndr: 0, 128 _cap_next: 0, 129 pcie_cap, 130 dev_cap, 131 dev_control: 0, 132 dev_status: 0, 133 link_cap, 134 link_control: 0, 135 link_status, 136 slot_cap, 137 slot_control, 138 slot_status: 0, 139 root_control: 0, 140 root_cap: 0, 141 root_status: 0, 142 dev_cap_2: 0, 143 dev_control_2: 0, 144 dev_status_2: 0, 145 link_cap_2: 0, 146 link_control_2: 0, 147 link_status_2: 0, 148 slot_cap_2: 0, 149 slot_control_2: 0, 150 slot_status_2: 0, 151 } 152 } 153 } 154 155 #[repr(C)] 156 #[derive(Clone, Copy)] 157 pub struct PciPmcCap { 158 _cap_vndr: u8, 159 _cap_next: u8, 160 pmc_cap: u16, 161 pmc_control_status: u16, 162 padding: u16, 163 } 164 165 // It is safe to implement DataInit; all members are simple numbers and any value is valid. 166 unsafe impl DataInit for PciPmcCap {} 167 168 impl PciCapability for PciPmcCap { bytes(&self) -> &[u8]169 fn bytes(&self) -> &[u8] { 170 self.as_slice() 171 } 172 id(&self) -> PciCapabilityID173 fn id(&self) -> PciCapabilityID { 174 PciCapabilityID::PowerManagement 175 } 176 writable_bits(&self) -> Vec<u32>177 fn writable_bits(&self) -> Vec<u32> { 178 vec![0u32, 0x8103] 179 } 180 } 181 182 impl PciPmcCap { new() -> Self183 pub fn new() -> Self { 184 let pmc_cap: u16 = PMC_CAP_PME_SUPPORT_D0 185 | PMC_CAP_PME_SUPPORT_D3_HOT 186 | PMC_CAP_PME_SUPPORT_D3_COLD 187 | PMC_CAP_VERSION; 188 PciPmcCap { 189 _cap_vndr: 0, 190 _cap_next: 0, 191 pmc_cap, 192 pmc_control_status: 0, 193 padding: 0, 194 } 195 } 196 } 197 198 pub struct PmcConfig { 199 power_control_status: u16, 200 } 201 202 impl PmcConfig { new() -> Self203 pub fn new() -> Self { 204 PmcConfig { 205 power_control_status: 0, 206 } 207 } 208 read(&self, data: &mut u32)209 pub fn read(&self, data: &mut u32) { 210 *data = self.power_control_status as u32; 211 } 212 write(&mut self, offset: u64, data: &[u8])213 pub fn write(&mut self, offset: u64, data: &[u8]) { 214 if offset > 1 { 215 return; 216 } 217 218 if offset == 0 { 219 self.power_control_status &= !PMC_POWER_STATE_MASK; 220 self.power_control_status |= data[0] as u16 & PMC_POWER_STATE_MASK; 221 } 222 223 let write_data = if offset == 0 && (data.len() == 2 || data.len() == 4) { 224 Some((data[1] as u16) << 8) 225 } else if offset == 1 && data.len() == 1 { 226 Some((data[0] as u16) << 8) 227 } else { 228 None 229 }; 230 231 if let Some(write_data) = write_data { 232 if write_data & PMC_PME_STATUS != 0 { 233 // clear PME_STATUS 234 self.power_control_status &= !PMC_PME_STATUS; 235 } 236 237 if write_data & PMC_PME_ENABLE != 0 { 238 self.power_control_status |= PMC_PME_ENABLE; 239 } else { 240 self.power_control_status &= !PMC_PME_ENABLE; 241 } 242 } 243 } 244 245 /// If device is in D3 and PME is enabled, set PME status, then device could 246 /// inject a pme interrupt into guest should_trigger_pme(&mut self) -> bool247 pub fn should_trigger_pme(&mut self) -> bool { 248 if self.power_control_status & PMC_POWER_STATE_MASK == PMC_POWER_STATE_D3 249 && self.power_control_status & PMC_PME_ENABLE != 0 250 { 251 self.power_control_status |= PMC_PME_STATUS; 252 253 return true; 254 } 255 256 false 257 } 258 259 /// Get device power status get_power_status(&self) -> PciDevicePower260 pub fn get_power_status(&self) -> PciDevicePower { 261 match self.power_control_status & PMC_POWER_STATE_MASK { 262 PMC_POWER_STATE_D0 => PciDevicePower::D0, 263 PMC_POWER_STATE_D3 => PciDevicePower::D3, 264 _ => PciDevicePower::Unsupported, 265 } 266 } 267 } 268