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