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