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