xref: /aosp_15_r20/external/crosvm/devices/src/pci/pci_configuration.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2018 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeMap;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::convert::TryFrom;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::convert::TryInto;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
9*bb4ee6a4SAndroid Build Coastguard Worker 
10*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::bail;
11*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Context;
12*bb4ee6a4SAndroid Build Coastguard Worker use base::custom_serde::deserialize_seq_to_arr;
13*bb4ee6a4SAndroid Build Coastguard Worker use base::custom_serde::serialize_arr;
14*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
15*bb4ee6a4SAndroid Build Coastguard Worker use base::warn;
16*bb4ee6a4SAndroid Build Coastguard Worker use base::MemoryMapping;
17*bb4ee6a4SAndroid Build Coastguard Worker use base::MemoryMappingBuilder;
18*bb4ee6a4SAndroid Build Coastguard Worker use base::SharedMemory;
19*bb4ee6a4SAndroid Build Coastguard Worker use downcast_rs::impl_downcast;
20*bb4ee6a4SAndroid Build Coastguard Worker use downcast_rs::Downcast;
21*bb4ee6a4SAndroid Build Coastguard Worker use remain::sorted;
22*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
23*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize;
24*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex;
25*bb4ee6a4SAndroid Build Coastguard Worker use thiserror::Error;
26*bb4ee6a4SAndroid Build Coastguard Worker 
27*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciInterruptPin;
28*bb4ee6a4SAndroid Build Coastguard Worker 
29*bb4ee6a4SAndroid Build Coastguard Worker // The number of 32bit registers in the config space, 256 bytes.
30*bb4ee6a4SAndroid Build Coastguard Worker const NUM_CONFIGURATION_REGISTERS: usize = 64;
31*bb4ee6a4SAndroid Build Coastguard Worker 
32*bb4ee6a4SAndroid Build Coastguard Worker pub const PCI_ID_REG: usize = 0;
33*bb4ee6a4SAndroid Build Coastguard Worker pub const COMMAND_REG: usize = 1;
34*bb4ee6a4SAndroid Build Coastguard Worker pub const COMMAND_REG_IO_SPACE_MASK: u32 = 0x0000_0001;
35*bb4ee6a4SAndroid Build Coastguard Worker pub const COMMAND_REG_MEMORY_SPACE_MASK: u32 = 0x0000_0002;
36*bb4ee6a4SAndroid Build Coastguard Worker const STATUS_REG: usize = 1;
37*bb4ee6a4SAndroid Build Coastguard Worker pub const STATUS_REG_CAPABILITIES_USED_MASK: u32 = 0x0010_0000;
38*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
39*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
40*bb4ee6a4SAndroid Build Coastguard Worker pub const CLASS_REG: usize = 2;
41*bb4ee6a4SAndroid Build Coastguard Worker pub const HEADER_TYPE_REG: usize = 3;
42*bb4ee6a4SAndroid Build Coastguard Worker pub const HEADER_TYPE_REG_OFFSET: usize = 2;
43*bb4ee6a4SAndroid Build Coastguard Worker pub const HEADER_TYPE_MULTIFUNCTION_MASK: u8 = 0x80;
44*bb4ee6a4SAndroid Build Coastguard Worker pub const BAR0_REG: usize = 4;
45*bb4ee6a4SAndroid Build Coastguard Worker const BAR_IO_ADDR_MASK: u32 = 0xffff_fffc;
46*bb4ee6a4SAndroid Build Coastguard Worker const BAR_IO_MIN_SIZE: u64 = 4;
47*bb4ee6a4SAndroid Build Coastguard Worker const BAR_MEM_ADDR_MASK: u32 = 0xffff_fff0;
48*bb4ee6a4SAndroid Build Coastguard Worker const BAR_MEM_MIN_SIZE: u64 = 16;
49*bb4ee6a4SAndroid Build Coastguard Worker const BAR_ROM_MIN_SIZE: u64 = 2048;
50*bb4ee6a4SAndroid Build Coastguard Worker pub const NUM_BAR_REGS: usize = 7; // 6 normal BARs + expansion ROM BAR.
51*bb4ee6a4SAndroid Build Coastguard Worker pub const ROM_BAR_IDX: PciBarIndex = 6;
52*bb4ee6a4SAndroid Build Coastguard Worker pub const ROM_BAR_REG: usize = 12;
53*bb4ee6a4SAndroid Build Coastguard Worker pub const CAPABILITY_LIST_HEAD_OFFSET: usize = 0x34;
54*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
55*bb4ee6a4SAndroid Build Coastguard Worker pub const PCI_CAP_NEXT_POINTER: usize = 0x1;
56*bb4ee6a4SAndroid Build Coastguard Worker const FIRST_CAPABILITY_OFFSET: usize = 0x40;
57*bb4ee6a4SAndroid Build Coastguard Worker pub const CAPABILITY_MAX_OFFSET: usize = 255;
58*bb4ee6a4SAndroid Build Coastguard Worker 
59*bb4ee6a4SAndroid Build Coastguard Worker const INTERRUPT_LINE_PIN_REG: usize = 15;
60*bb4ee6a4SAndroid Build Coastguard Worker 
61*bb4ee6a4SAndroid Build Coastguard Worker /// Represents the types of PCI headers allowed in the configuration registers.
62*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
63*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone)]
64*bb4ee6a4SAndroid Build Coastguard Worker pub enum PciHeaderType {
65*bb4ee6a4SAndroid Build Coastguard Worker     Device,
66*bb4ee6a4SAndroid Build Coastguard Worker     Bridge,
67*bb4ee6a4SAndroid Build Coastguard Worker }
68*bb4ee6a4SAndroid Build Coastguard Worker 
69*bb4ee6a4SAndroid Build Coastguard Worker /// Classes of PCI nodes.
70*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
71*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Debug, enumn::N, Serialize, Deserialize, PartialEq, Eq)]
72*bb4ee6a4SAndroid Build Coastguard Worker pub enum PciClassCode {
73*bb4ee6a4SAndroid Build Coastguard Worker     TooOld,
74*bb4ee6a4SAndroid Build Coastguard Worker     MassStorage,
75*bb4ee6a4SAndroid Build Coastguard Worker     NetworkController,
76*bb4ee6a4SAndroid Build Coastguard Worker     DisplayController,
77*bb4ee6a4SAndroid Build Coastguard Worker     MultimediaController,
78*bb4ee6a4SAndroid Build Coastguard Worker     MemoryController,
79*bb4ee6a4SAndroid Build Coastguard Worker     BridgeDevice,
80*bb4ee6a4SAndroid Build Coastguard Worker     SimpleCommunicationController,
81*bb4ee6a4SAndroid Build Coastguard Worker     BaseSystemPeripheral,
82*bb4ee6a4SAndroid Build Coastguard Worker     InputDevice,
83*bb4ee6a4SAndroid Build Coastguard Worker     DockingStation,
84*bb4ee6a4SAndroid Build Coastguard Worker     Processor,
85*bb4ee6a4SAndroid Build Coastguard Worker     SerialBusController,
86*bb4ee6a4SAndroid Build Coastguard Worker     WirelessController,
87*bb4ee6a4SAndroid Build Coastguard Worker     IntelligentIoController,
88*bb4ee6a4SAndroid Build Coastguard Worker     SatelliteCommunicationController,
89*bb4ee6a4SAndroid Build Coastguard Worker     EncryptionController,
90*bb4ee6a4SAndroid Build Coastguard Worker     DataAcquisitionSignalProcessing,
91*bb4ee6a4SAndroid Build Coastguard Worker     ProcessingAccelerator,
92*bb4ee6a4SAndroid Build Coastguard Worker     NonEssentialInstrumentation,
93*bb4ee6a4SAndroid Build Coastguard Worker     Other = 0xff,
94*bb4ee6a4SAndroid Build Coastguard Worker }
95*bb4ee6a4SAndroid Build Coastguard Worker 
96*bb4ee6a4SAndroid Build Coastguard Worker impl PciClassCode {
get_register_value(&self) -> u897*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_register_value(&self) -> u8 {
98*bb4ee6a4SAndroid Build Coastguard Worker         *self as u8
99*bb4ee6a4SAndroid Build Coastguard Worker     }
100*bb4ee6a4SAndroid Build Coastguard Worker }
101*bb4ee6a4SAndroid Build Coastguard Worker 
102*bb4ee6a4SAndroid Build Coastguard Worker #[sorted]
103*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Error, Debug)]
104*bb4ee6a4SAndroid Build Coastguard Worker pub enum PciClassCodeParseError {
105*bb4ee6a4SAndroid Build Coastguard Worker     #[error("Unknown class code")]
106*bb4ee6a4SAndroid Build Coastguard Worker     Unknown,
107*bb4ee6a4SAndroid Build Coastguard Worker }
108*bb4ee6a4SAndroid Build Coastguard Worker 
109*bb4ee6a4SAndroid Build Coastguard Worker impl TryFrom<u8> for PciClassCode {
110*bb4ee6a4SAndroid Build Coastguard Worker     type Error = PciClassCodeParseError;
try_from(v: u8) -> std::result::Result<PciClassCode, PciClassCodeParseError>111*bb4ee6a4SAndroid Build Coastguard Worker     fn try_from(v: u8) -> std::result::Result<PciClassCode, PciClassCodeParseError> {
112*bb4ee6a4SAndroid Build Coastguard Worker         match PciClassCode::n(v) {
113*bb4ee6a4SAndroid Build Coastguard Worker             Some(class) => Ok(class),
114*bb4ee6a4SAndroid Build Coastguard Worker             None => Err(PciClassCodeParseError::Unknown),
115*bb4ee6a4SAndroid Build Coastguard Worker         }
116*bb4ee6a4SAndroid Build Coastguard Worker     }
117*bb4ee6a4SAndroid Build Coastguard Worker }
118*bb4ee6a4SAndroid Build Coastguard Worker 
119*bb4ee6a4SAndroid Build Coastguard Worker /// A PCI sublcass. Each class in `PciClassCode` can specify a unique set of subclasses. This trait
120*bb4ee6a4SAndroid Build Coastguard Worker /// is implemented by each subclass. It allows use of a trait object to generate configurations.
121*bb4ee6a4SAndroid Build Coastguard Worker pub trait PciSubclass {
122*bb4ee6a4SAndroid Build Coastguard Worker     /// Convert this subclass to the value used in the PCI specification.
get_register_value(&self) -> u8123*bb4ee6a4SAndroid Build Coastguard Worker     fn get_register_value(&self) -> u8;
124*bb4ee6a4SAndroid Build Coastguard Worker }
125*bb4ee6a4SAndroid Build Coastguard Worker 
126*bb4ee6a4SAndroid Build Coastguard Worker /// Subclasses of the MassStorage class.
127*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
128*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone)]
129*bb4ee6a4SAndroid Build Coastguard Worker pub enum PciMassStorageSubclass {
130*bb4ee6a4SAndroid Build Coastguard Worker     Scsi = 0x00,
131*bb4ee6a4SAndroid Build Coastguard Worker     NonVolatileMemory = 0x08,
132*bb4ee6a4SAndroid Build Coastguard Worker     Other = 0x80,
133*bb4ee6a4SAndroid Build Coastguard Worker }
134*bb4ee6a4SAndroid Build Coastguard Worker 
135*bb4ee6a4SAndroid Build Coastguard Worker impl PciSubclass for PciMassStorageSubclass {
get_register_value(&self) -> u8136*bb4ee6a4SAndroid Build Coastguard Worker     fn get_register_value(&self) -> u8 {
137*bb4ee6a4SAndroid Build Coastguard Worker         *self as u8
138*bb4ee6a4SAndroid Build Coastguard Worker     }
139*bb4ee6a4SAndroid Build Coastguard Worker }
140*bb4ee6a4SAndroid Build Coastguard Worker 
141*bb4ee6a4SAndroid Build Coastguard Worker /// Subclasses of the NetworkController class.
142*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
143*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone)]
144*bb4ee6a4SAndroid Build Coastguard Worker pub enum PciNetworkControllerSubclass {
145*bb4ee6a4SAndroid Build Coastguard Worker     Other = 0x80,
146*bb4ee6a4SAndroid Build Coastguard Worker }
147*bb4ee6a4SAndroid Build Coastguard Worker 
148*bb4ee6a4SAndroid Build Coastguard Worker impl PciSubclass for PciNetworkControllerSubclass {
get_register_value(&self) -> u8149*bb4ee6a4SAndroid Build Coastguard Worker     fn get_register_value(&self) -> u8 {
150*bb4ee6a4SAndroid Build Coastguard Worker         *self as u8
151*bb4ee6a4SAndroid Build Coastguard Worker     }
152*bb4ee6a4SAndroid Build Coastguard Worker }
153*bb4ee6a4SAndroid Build Coastguard Worker 
154*bb4ee6a4SAndroid Build Coastguard Worker /// Subclasses of the DisplayController class.
155*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
156*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone)]
157*bb4ee6a4SAndroid Build Coastguard Worker pub enum PciDisplaySubclass {
158*bb4ee6a4SAndroid Build Coastguard Worker     VgaCompatibleController = 0x00,
159*bb4ee6a4SAndroid Build Coastguard Worker     XgaCompatibleController = 0x01,
160*bb4ee6a4SAndroid Build Coastguard Worker     ThreeDController = 0x02,
161*bb4ee6a4SAndroid Build Coastguard Worker     Other = 0x80,
162*bb4ee6a4SAndroid Build Coastguard Worker }
163*bb4ee6a4SAndroid Build Coastguard Worker 
164*bb4ee6a4SAndroid Build Coastguard Worker impl PciSubclass for PciDisplaySubclass {
get_register_value(&self) -> u8165*bb4ee6a4SAndroid Build Coastguard Worker     fn get_register_value(&self) -> u8 {
166*bb4ee6a4SAndroid Build Coastguard Worker         *self as u8
167*bb4ee6a4SAndroid Build Coastguard Worker     }
168*bb4ee6a4SAndroid Build Coastguard Worker }
169*bb4ee6a4SAndroid Build Coastguard Worker 
170*bb4ee6a4SAndroid Build Coastguard Worker /// Subclasses of the MultimediaController class.
171*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
172*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone)]
173*bb4ee6a4SAndroid Build Coastguard Worker pub enum PciMultimediaSubclass {
174*bb4ee6a4SAndroid Build Coastguard Worker     VideoController = 0x00,
175*bb4ee6a4SAndroid Build Coastguard Worker     AudioController = 0x01,
176*bb4ee6a4SAndroid Build Coastguard Worker     TelephonyDevice = 0x02,
177*bb4ee6a4SAndroid Build Coastguard Worker     AudioDevice = 0x03,
178*bb4ee6a4SAndroid Build Coastguard Worker     Other = 0x80,
179*bb4ee6a4SAndroid Build Coastguard Worker }
180*bb4ee6a4SAndroid Build Coastguard Worker 
181*bb4ee6a4SAndroid Build Coastguard Worker impl PciSubclass for PciMultimediaSubclass {
get_register_value(&self) -> u8182*bb4ee6a4SAndroid Build Coastguard Worker     fn get_register_value(&self) -> u8 {
183*bb4ee6a4SAndroid Build Coastguard Worker         *self as u8
184*bb4ee6a4SAndroid Build Coastguard Worker     }
185*bb4ee6a4SAndroid Build Coastguard Worker }
186*bb4ee6a4SAndroid Build Coastguard Worker 
187*bb4ee6a4SAndroid Build Coastguard Worker /// Subclasses of the BridgeDevice
188*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
189*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone)]
190*bb4ee6a4SAndroid Build Coastguard Worker pub enum PciBridgeSubclass {
191*bb4ee6a4SAndroid Build Coastguard Worker     HostBridge = 0x00,
192*bb4ee6a4SAndroid Build Coastguard Worker     IsaBridge = 0x01,
193*bb4ee6a4SAndroid Build Coastguard Worker     EisaBridge = 0x02,
194*bb4ee6a4SAndroid Build Coastguard Worker     McaBridge = 0x03,
195*bb4ee6a4SAndroid Build Coastguard Worker     PciToPciBridge = 0x04,
196*bb4ee6a4SAndroid Build Coastguard Worker     PcmciaBridge = 0x05,
197*bb4ee6a4SAndroid Build Coastguard Worker     NuBusBridge = 0x06,
198*bb4ee6a4SAndroid Build Coastguard Worker     CardBusBridge = 0x07,
199*bb4ee6a4SAndroid Build Coastguard Worker     RaceWayBridge = 0x08,
200*bb4ee6a4SAndroid Build Coastguard Worker     PciToPciSemiTransparentBridge = 0x09,
201*bb4ee6a4SAndroid Build Coastguard Worker     InfiniBrandToPciHostBridge = 0x0a,
202*bb4ee6a4SAndroid Build Coastguard Worker     OtherBridgeDevice = 0x80,
203*bb4ee6a4SAndroid Build Coastguard Worker }
204*bb4ee6a4SAndroid Build Coastguard Worker 
205*bb4ee6a4SAndroid Build Coastguard Worker impl PciSubclass for PciBridgeSubclass {
get_register_value(&self) -> u8206*bb4ee6a4SAndroid Build Coastguard Worker     fn get_register_value(&self) -> u8 {
207*bb4ee6a4SAndroid Build Coastguard Worker         *self as u8
208*bb4ee6a4SAndroid Build Coastguard Worker     }
209*bb4ee6a4SAndroid Build Coastguard Worker }
210*bb4ee6a4SAndroid Build Coastguard Worker 
211*bb4ee6a4SAndroid Build Coastguard Worker /// Subclasses of the SimpleCommunicationController class.
212*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
213*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone)]
214*bb4ee6a4SAndroid Build Coastguard Worker pub enum PciSimpleCommunicationControllerSubclass {
215*bb4ee6a4SAndroid Build Coastguard Worker     Other = 0x80,
216*bb4ee6a4SAndroid Build Coastguard Worker }
217*bb4ee6a4SAndroid Build Coastguard Worker 
218*bb4ee6a4SAndroid Build Coastguard Worker impl PciSubclass for PciSimpleCommunicationControllerSubclass {
get_register_value(&self) -> u8219*bb4ee6a4SAndroid Build Coastguard Worker     fn get_register_value(&self) -> u8 {
220*bb4ee6a4SAndroid Build Coastguard Worker         *self as u8
221*bb4ee6a4SAndroid Build Coastguard Worker     }
222*bb4ee6a4SAndroid Build Coastguard Worker }
223*bb4ee6a4SAndroid Build Coastguard Worker 
224*bb4ee6a4SAndroid Build Coastguard Worker /// Subclasses of the BaseSystemPeripheral class.
225*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
226*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone)]
227*bb4ee6a4SAndroid Build Coastguard Worker pub enum PciBaseSystemPeripheralSubclass {
228*bb4ee6a4SAndroid Build Coastguard Worker     Iommu = 0x06,
229*bb4ee6a4SAndroid Build Coastguard Worker     Other = 0x80,
230*bb4ee6a4SAndroid Build Coastguard Worker }
231*bb4ee6a4SAndroid Build Coastguard Worker 
232*bb4ee6a4SAndroid Build Coastguard Worker impl PciSubclass for PciBaseSystemPeripheralSubclass {
get_register_value(&self) -> u8233*bb4ee6a4SAndroid Build Coastguard Worker     fn get_register_value(&self) -> u8 {
234*bb4ee6a4SAndroid Build Coastguard Worker         *self as u8
235*bb4ee6a4SAndroid Build Coastguard Worker     }
236*bb4ee6a4SAndroid Build Coastguard Worker }
237*bb4ee6a4SAndroid Build Coastguard Worker 
238*bb4ee6a4SAndroid Build Coastguard Worker /// Subclasses of the InputDevice class.
239*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
240*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone)]
241*bb4ee6a4SAndroid Build Coastguard Worker pub enum PciInputDeviceSubclass {
242*bb4ee6a4SAndroid Build Coastguard Worker     Other = 0x80,
243*bb4ee6a4SAndroid Build Coastguard Worker }
244*bb4ee6a4SAndroid Build Coastguard Worker 
245*bb4ee6a4SAndroid Build Coastguard Worker impl PciSubclass for PciInputDeviceSubclass {
get_register_value(&self) -> u8246*bb4ee6a4SAndroid Build Coastguard Worker     fn get_register_value(&self) -> u8 {
247*bb4ee6a4SAndroid Build Coastguard Worker         *self as u8
248*bb4ee6a4SAndroid Build Coastguard Worker     }
249*bb4ee6a4SAndroid Build Coastguard Worker }
250*bb4ee6a4SAndroid Build Coastguard Worker 
251*bb4ee6a4SAndroid Build Coastguard Worker /// Subclass of the SerialBus
252*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
253*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone)]
254*bb4ee6a4SAndroid Build Coastguard Worker pub enum PciSerialBusSubClass {
255*bb4ee6a4SAndroid Build Coastguard Worker     Firewire = 0x00,
256*bb4ee6a4SAndroid Build Coastguard Worker     AccessBus = 0x01,
257*bb4ee6a4SAndroid Build Coastguard Worker     Ssa = 0x02,
258*bb4ee6a4SAndroid Build Coastguard Worker     Usb = 0x03,
259*bb4ee6a4SAndroid Build Coastguard Worker }
260*bb4ee6a4SAndroid Build Coastguard Worker 
261*bb4ee6a4SAndroid Build Coastguard Worker impl PciSubclass for PciSerialBusSubClass {
get_register_value(&self) -> u8262*bb4ee6a4SAndroid Build Coastguard Worker     fn get_register_value(&self) -> u8 {
263*bb4ee6a4SAndroid Build Coastguard Worker         *self as u8
264*bb4ee6a4SAndroid Build Coastguard Worker     }
265*bb4ee6a4SAndroid Build Coastguard Worker }
266*bb4ee6a4SAndroid Build Coastguard Worker 
267*bb4ee6a4SAndroid Build Coastguard Worker /// Subclasses of the WirelessController class.
268*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
269*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone)]
270*bb4ee6a4SAndroid Build Coastguard Worker pub enum PciWirelessControllerSubclass {
271*bb4ee6a4SAndroid Build Coastguard Worker     Other = 0x80,
272*bb4ee6a4SAndroid Build Coastguard Worker }
273*bb4ee6a4SAndroid Build Coastguard Worker 
274*bb4ee6a4SAndroid Build Coastguard Worker impl PciSubclass for PciWirelessControllerSubclass {
get_register_value(&self) -> u8275*bb4ee6a4SAndroid Build Coastguard Worker     fn get_register_value(&self) -> u8 {
276*bb4ee6a4SAndroid Build Coastguard Worker         *self as u8
277*bb4ee6a4SAndroid Build Coastguard Worker     }
278*bb4ee6a4SAndroid Build Coastguard Worker }
279*bb4ee6a4SAndroid Build Coastguard Worker 
280*bb4ee6a4SAndroid Build Coastguard Worker /// Subclasses for PciClassCode Other.
281*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
282*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone)]
283*bb4ee6a4SAndroid Build Coastguard Worker #[repr(u8)]
284*bb4ee6a4SAndroid Build Coastguard Worker pub enum PciOtherSubclass {
285*bb4ee6a4SAndroid Build Coastguard Worker     Other = 0xff,
286*bb4ee6a4SAndroid Build Coastguard Worker }
287*bb4ee6a4SAndroid Build Coastguard Worker 
288*bb4ee6a4SAndroid Build Coastguard Worker impl PciSubclass for PciOtherSubclass {
get_register_value(&self) -> u8289*bb4ee6a4SAndroid Build Coastguard Worker     fn get_register_value(&self) -> u8 {
290*bb4ee6a4SAndroid Build Coastguard Worker         *self as u8
291*bb4ee6a4SAndroid Build Coastguard Worker     }
292*bb4ee6a4SAndroid Build Coastguard Worker }
293*bb4ee6a4SAndroid Build Coastguard Worker 
294*bb4ee6a4SAndroid Build Coastguard Worker /// A PCI class programming interface. Each combination of `PciClassCode` and
295*bb4ee6a4SAndroid Build Coastguard Worker /// `PciSubclass` can specify a set of register-level programming interfaces.
296*bb4ee6a4SAndroid Build Coastguard Worker /// This trait is implemented by each programming interface.
297*bb4ee6a4SAndroid Build Coastguard Worker /// It allows use of a trait object to generate configurations.
298*bb4ee6a4SAndroid Build Coastguard Worker pub trait PciProgrammingInterface {
299*bb4ee6a4SAndroid Build Coastguard Worker     /// Convert this programming interface to the value used in the PCI specification.
get_register_value(&self) -> u8300*bb4ee6a4SAndroid Build Coastguard Worker     fn get_register_value(&self) -> u8;
301*bb4ee6a4SAndroid Build Coastguard Worker }
302*bb4ee6a4SAndroid Build Coastguard Worker 
303*bb4ee6a4SAndroid Build Coastguard Worker /// Types of PCI capabilities.
304*bb4ee6a4SAndroid Build Coastguard Worker pub enum PciCapabilityID {
305*bb4ee6a4SAndroid Build Coastguard Worker     ListID = 0,
306*bb4ee6a4SAndroid Build Coastguard Worker     PowerManagement = 0x01,
307*bb4ee6a4SAndroid Build Coastguard Worker     AcceleratedGraphicsPort = 0x02,
308*bb4ee6a4SAndroid Build Coastguard Worker     VitalProductData = 0x03,
309*bb4ee6a4SAndroid Build Coastguard Worker     SlotIdentification = 0x04,
310*bb4ee6a4SAndroid Build Coastguard Worker     MessageSignalledInterrupts = 0x05,
311*bb4ee6a4SAndroid Build Coastguard Worker     CompactPciHotSwap = 0x06,
312*bb4ee6a4SAndroid Build Coastguard Worker     Pcix = 0x07,
313*bb4ee6a4SAndroid Build Coastguard Worker     HyperTransport = 0x08,
314*bb4ee6a4SAndroid Build Coastguard Worker     VendorSpecific = 0x09,
315*bb4ee6a4SAndroid Build Coastguard Worker     Debugport = 0x0A,
316*bb4ee6a4SAndroid Build Coastguard Worker     CompactPciCentralResourceControl = 0x0B,
317*bb4ee6a4SAndroid Build Coastguard Worker     PciStandardHotPlugController = 0x0C,
318*bb4ee6a4SAndroid Build Coastguard Worker     BridgeSubsystemVendorDeviceID = 0x0D,
319*bb4ee6a4SAndroid Build Coastguard Worker     AgpTargetPciPciBridge = 0x0E,
320*bb4ee6a4SAndroid Build Coastguard Worker     SecureDevice = 0x0F,
321*bb4ee6a4SAndroid Build Coastguard Worker     PciExpress = 0x10,
322*bb4ee6a4SAndroid Build Coastguard Worker     Msix = 0x11,
323*bb4ee6a4SAndroid Build Coastguard Worker     SataDataIndexConf = 0x12,
324*bb4ee6a4SAndroid Build Coastguard Worker     PciAdvancedFeatures = 0x13,
325*bb4ee6a4SAndroid Build Coastguard Worker     PciEnhancedAllocation = 0x14,
326*bb4ee6a4SAndroid Build Coastguard Worker }
327*bb4ee6a4SAndroid Build Coastguard Worker 
328*bb4ee6a4SAndroid Build Coastguard Worker /// A PCI capability list. Devices can optionally specify capabilities in their configuration space.
329*bb4ee6a4SAndroid Build Coastguard Worker pub trait PciCapability {
bytes(&self) -> &[u8]330*bb4ee6a4SAndroid Build Coastguard Worker     fn bytes(&self) -> &[u8];
id(&self) -> PciCapabilityID331*bb4ee6a4SAndroid Build Coastguard Worker     fn id(&self) -> PciCapabilityID;
writable_bits(&self) -> Vec<u32>332*bb4ee6a4SAndroid Build Coastguard Worker     fn writable_bits(&self) -> Vec<u32>;
333*bb4ee6a4SAndroid Build Coastguard Worker }
334*bb4ee6a4SAndroid Build Coastguard Worker 
335*bb4ee6a4SAndroid Build Coastguard Worker pub trait PciCapConfigWriteResult: Downcast {}
336*bb4ee6a4SAndroid Build Coastguard Worker impl_downcast!(PciCapConfigWriteResult);
337*bb4ee6a4SAndroid Build Coastguard Worker 
338*bb4ee6a4SAndroid Build Coastguard Worker /// A trait for implementing complex PCI capabilities.
339*bb4ee6a4SAndroid Build Coastguard Worker pub trait PciCapConfig: Send {
340*bb4ee6a4SAndroid Build Coastguard Worker     /// Reads a 32bit register from the capability. Only the bits set in the
341*bb4ee6a4SAndroid Build Coastguard Worker     /// read mask will be used, while the rest of the bits will be taken from
342*bb4ee6a4SAndroid Build Coastguard Worker     /// the `PciConfiguration`'s register data.
343*bb4ee6a4SAndroid Build Coastguard Worker     /// `reg_idx` - index into the capability
read_reg(&self, reg_idx: usize) -> u32344*bb4ee6a4SAndroid Build Coastguard Worker     fn read_reg(&self, reg_idx: usize) -> u32;
345*bb4ee6a4SAndroid Build Coastguard Worker 
346*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns the read mask used by `read_reg`.
read_mask(&self) -> &'static [u32]347*bb4ee6a4SAndroid Build Coastguard Worker     fn read_mask(&self) -> &'static [u32];
348*bb4ee6a4SAndroid Build Coastguard Worker 
349*bb4ee6a4SAndroid Build Coastguard Worker     /// Writes data to the capability.
350*bb4ee6a4SAndroid Build Coastguard Worker     /// `reg_idx` - index into PciConfiguration.registers.
351*bb4ee6a4SAndroid Build Coastguard Worker     /// `offset`  - PciConfiguration.registers is in unit of DWord, offset define byte
352*bb4ee6a4SAndroid Build Coastguard Worker     ///             offset in the DWord.
353*bb4ee6a4SAndroid Build Coastguard Worker     /// `data`    - The data to write.
write_reg( &mut self, reg_idx: usize, offset: u64, data: &[u8], ) -> Option<Box<dyn PciCapConfigWriteResult>>354*bb4ee6a4SAndroid Build Coastguard Worker     fn write_reg(
355*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
356*bb4ee6a4SAndroid Build Coastguard Worker         reg_idx: usize,
357*bb4ee6a4SAndroid Build Coastguard Worker         offset: u64,
358*bb4ee6a4SAndroid Build Coastguard Worker         data: &[u8],
359*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Option<Box<dyn PciCapConfigWriteResult>>;
360*bb4ee6a4SAndroid Build Coastguard Worker 
361*bb4ee6a4SAndroid Build Coastguard Worker     /// Used to pass the mmio region for the capability to the implementation.
362*bb4ee6a4SAndroid Build Coastguard Worker     /// If any external events update the capability's registers, then
363*bb4ee6a4SAndroid Build Coastguard Worker     /// `PciCapMapping.set_reg` must be called to make the changes visible
364*bb4ee6a4SAndroid Build Coastguard Worker     /// to the guest.
set_cap_mapping(&mut self, _mapping: PciCapMapping)365*bb4ee6a4SAndroid Build Coastguard Worker     fn set_cap_mapping(&mut self, _mapping: PciCapMapping) {}
366*bb4ee6a4SAndroid Build Coastguard Worker 
num_regs(&self) -> usize367*bb4ee6a4SAndroid Build Coastguard Worker     fn num_regs(&self) -> usize {
368*bb4ee6a4SAndroid Build Coastguard Worker         self.read_mask().len()
369*bb4ee6a4SAndroid Build Coastguard Worker     }
370*bb4ee6a4SAndroid Build Coastguard Worker }
371*bb4ee6a4SAndroid Build Coastguard Worker 
372*bb4ee6a4SAndroid Build Coastguard Worker /// Contains the configuration space of a PCI node.
373*bb4ee6a4SAndroid Build Coastguard Worker /// See the [specification](https://en.wikipedia.org/wiki/PCI_configuration_space).
374*bb4ee6a4SAndroid Build Coastguard Worker /// The configuration space is accessed with DWORD reads and writes from the guest.
375*bb4ee6a4SAndroid Build Coastguard Worker pub struct PciConfiguration {
376*bb4ee6a4SAndroid Build Coastguard Worker     registers: [u32; NUM_CONFIGURATION_REGISTERS],
377*bb4ee6a4SAndroid Build Coastguard Worker     writable_bits: [u32; NUM_CONFIGURATION_REGISTERS], // writable bits for each register.
378*bb4ee6a4SAndroid Build Coastguard Worker     bar_used: [bool; NUM_BAR_REGS],
379*bb4ee6a4SAndroid Build Coastguard Worker     bar_configs: [Option<PciBarConfiguration>; NUM_BAR_REGS],
380*bb4ee6a4SAndroid Build Coastguard Worker     // Contains the byte offset and size of the last capability.
381*bb4ee6a4SAndroid Build Coastguard Worker     last_capability: Option<(usize, usize)>,
382*bb4ee6a4SAndroid Build Coastguard Worker     capability_configs: BTreeMap<usize, Box<dyn PciCapConfig>>,
383*bb4ee6a4SAndroid Build Coastguard Worker     mmio_mapping: Option<(Arc<Mutex<MemoryMapping>>, usize)>,
384*bb4ee6a4SAndroid Build Coastguard Worker }
385*bb4ee6a4SAndroid Build Coastguard Worker 
386*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize)]
387*bb4ee6a4SAndroid Build Coastguard Worker pub struct PciConfigurationSerialized {
388*bb4ee6a4SAndroid Build Coastguard Worker     #[serde(
389*bb4ee6a4SAndroid Build Coastguard Worker         serialize_with = "serialize_arr",
390*bb4ee6a4SAndroid Build Coastguard Worker         deserialize_with = "deserialize_seq_to_arr"
391*bb4ee6a4SAndroid Build Coastguard Worker     )]
392*bb4ee6a4SAndroid Build Coastguard Worker     registers: [u32; NUM_CONFIGURATION_REGISTERS],
393*bb4ee6a4SAndroid Build Coastguard Worker     #[serde(
394*bb4ee6a4SAndroid Build Coastguard Worker         serialize_with = "serialize_arr",
395*bb4ee6a4SAndroid Build Coastguard Worker         deserialize_with = "deserialize_seq_to_arr"
396*bb4ee6a4SAndroid Build Coastguard Worker     )]
397*bb4ee6a4SAndroid Build Coastguard Worker     writable_bits: [u32; NUM_CONFIGURATION_REGISTERS],
398*bb4ee6a4SAndroid Build Coastguard Worker     bar_used: [bool; NUM_BAR_REGS],
399*bb4ee6a4SAndroid Build Coastguard Worker     bar_configs: [Option<PciBarConfiguration>; NUM_BAR_REGS],
400*bb4ee6a4SAndroid Build Coastguard Worker     last_capability: Option<(usize, usize)>,
401*bb4ee6a4SAndroid Build Coastguard Worker }
402*bb4ee6a4SAndroid Build Coastguard Worker 
403*bb4ee6a4SAndroid Build Coastguard Worker /// See pci_regs.h in kernel
404*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
405*bb4ee6a4SAndroid Build Coastguard Worker pub enum PciBarRegionType {
406*bb4ee6a4SAndroid Build Coastguard Worker     Memory32BitRegion = 0,
407*bb4ee6a4SAndroid Build Coastguard Worker     IoRegion = 0x01,
408*bb4ee6a4SAndroid Build Coastguard Worker     Memory64BitRegion = 0x04,
409*bb4ee6a4SAndroid Build Coastguard Worker }
410*bb4ee6a4SAndroid Build Coastguard Worker 
411*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
412*bb4ee6a4SAndroid Build Coastguard Worker pub enum PciBarPrefetchable {
413*bb4ee6a4SAndroid Build Coastguard Worker     NotPrefetchable = 0,
414*bb4ee6a4SAndroid Build Coastguard Worker     Prefetchable = 0x08,
415*bb4ee6a4SAndroid Build Coastguard Worker }
416*bb4ee6a4SAndroid Build Coastguard Worker 
417*bb4ee6a4SAndroid Build Coastguard Worker pub type PciBarIndex = usize;
418*bb4ee6a4SAndroid Build Coastguard Worker 
419*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
420*bb4ee6a4SAndroid Build Coastguard Worker pub struct PciBarConfiguration {
421*bb4ee6a4SAndroid Build Coastguard Worker     addr: u64,
422*bb4ee6a4SAndroid Build Coastguard Worker     size: u64,
423*bb4ee6a4SAndroid Build Coastguard Worker     bar_idx: PciBarIndex,
424*bb4ee6a4SAndroid Build Coastguard Worker     region_type: PciBarRegionType,
425*bb4ee6a4SAndroid Build Coastguard Worker     prefetchable: PciBarPrefetchable,
426*bb4ee6a4SAndroid Build Coastguard Worker }
427*bb4ee6a4SAndroid Build Coastguard Worker 
428*bb4ee6a4SAndroid Build Coastguard Worker pub struct PciBarIter<'a> {
429*bb4ee6a4SAndroid Build Coastguard Worker     config: &'a PciConfiguration,
430*bb4ee6a4SAndroid Build Coastguard Worker     bar_num: PciBarIndex,
431*bb4ee6a4SAndroid Build Coastguard Worker }
432*bb4ee6a4SAndroid Build Coastguard Worker 
433*bb4ee6a4SAndroid Build Coastguard Worker impl<'a> Iterator for PciBarIter<'a> {
434*bb4ee6a4SAndroid Build Coastguard Worker     type Item = PciBarConfiguration;
435*bb4ee6a4SAndroid Build Coastguard Worker 
next(&mut self) -> Option<Self::Item>436*bb4ee6a4SAndroid Build Coastguard Worker     fn next(&mut self) -> Option<Self::Item> {
437*bb4ee6a4SAndroid Build Coastguard Worker         while self.bar_num < NUM_BAR_REGS {
438*bb4ee6a4SAndroid Build Coastguard Worker             let bar_config = self.config.get_bar_configuration(self.bar_num);
439*bb4ee6a4SAndroid Build Coastguard Worker             self.bar_num += 1;
440*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(bar_config) = bar_config {
441*bb4ee6a4SAndroid Build Coastguard Worker                 return Some(bar_config);
442*bb4ee6a4SAndroid Build Coastguard Worker             }
443*bb4ee6a4SAndroid Build Coastguard Worker         }
444*bb4ee6a4SAndroid Build Coastguard Worker 
445*bb4ee6a4SAndroid Build Coastguard Worker         None
446*bb4ee6a4SAndroid Build Coastguard Worker     }
447*bb4ee6a4SAndroid Build Coastguard Worker }
448*bb4ee6a4SAndroid Build Coastguard Worker 
449*bb4ee6a4SAndroid Build Coastguard Worker #[sorted]
450*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Error, Debug, PartialEq, Eq)]
451*bb4ee6a4SAndroid Build Coastguard Worker pub enum Error {
452*bb4ee6a4SAndroid Build Coastguard Worker     #[error("address {0} size {1} too big")]
453*bb4ee6a4SAndroid Build Coastguard Worker     BarAddressInvalid(u64, u64),
454*bb4ee6a4SAndroid Build Coastguard Worker     #[error("address {0} is not aligned to size {1}")]
455*bb4ee6a4SAndroid Build Coastguard Worker     BarAlignmentInvalid(u64, u64),
456*bb4ee6a4SAndroid Build Coastguard Worker     #[error("bar {0} already used")]
457*bb4ee6a4SAndroid Build Coastguard Worker     BarInUse(PciBarIndex),
458*bb4ee6a4SAndroid Build Coastguard Worker     #[error("64bit bar {0} already used (requires two regs)")]
459*bb4ee6a4SAndroid Build Coastguard Worker     BarInUse64(PciBarIndex),
460*bb4ee6a4SAndroid Build Coastguard Worker     #[error("bar {0} invalid, max {}", NUM_BAR_REGS - 1)]
461*bb4ee6a4SAndroid Build Coastguard Worker     BarInvalid(PciBarIndex),
462*bb4ee6a4SAndroid Build Coastguard Worker     #[error("64bitbar {0} invalid, requires two regs, max {}", ROM_BAR_IDX - 1)]
463*bb4ee6a4SAndroid Build Coastguard Worker     BarInvalid64(PciBarIndex),
464*bb4ee6a4SAndroid Build Coastguard Worker     #[error("expansion rom bar must be a memory region")]
465*bb4ee6a4SAndroid Build Coastguard Worker     BarInvalidRomType,
466*bb4ee6a4SAndroid Build Coastguard Worker     #[error("bar address {0} not a power of two")]
467*bb4ee6a4SAndroid Build Coastguard Worker     BarSizeInvalid(u64),
468*bb4ee6a4SAndroid Build Coastguard Worker     #[error("empty capabilities are invalid")]
469*bb4ee6a4SAndroid Build Coastguard Worker     CapabilityEmpty,
470*bb4ee6a4SAndroid Build Coastguard Worker     #[error("Invalid capability length {0}")]
471*bb4ee6a4SAndroid Build Coastguard Worker     CapabilityLengthInvalid(usize),
472*bb4ee6a4SAndroid Build Coastguard Worker     #[error("capability of size {0} doesn't fit")]
473*bb4ee6a4SAndroid Build Coastguard Worker     CapabilitySpaceFull(usize),
474*bb4ee6a4SAndroid Build Coastguard Worker }
475*bb4ee6a4SAndroid Build Coastguard Worker 
476*bb4ee6a4SAndroid Build Coastguard Worker pub type Result<T> = std::result::Result<T, Error>;
477*bb4ee6a4SAndroid Build Coastguard Worker 
478*bb4ee6a4SAndroid Build Coastguard Worker impl PciConfiguration {
new( vendor_id: u16, device_id: u16, class_code: PciClassCode, subclass: &dyn PciSubclass, programming_interface: Option<&dyn PciProgrammingInterface>, header_type: PciHeaderType, subsystem_vendor_id: u16, subsystem_id: u16, revision_id: u8, ) -> Self479*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(
480*bb4ee6a4SAndroid Build Coastguard Worker         vendor_id: u16,
481*bb4ee6a4SAndroid Build Coastguard Worker         device_id: u16,
482*bb4ee6a4SAndroid Build Coastguard Worker         class_code: PciClassCode,
483*bb4ee6a4SAndroid Build Coastguard Worker         subclass: &dyn PciSubclass,
484*bb4ee6a4SAndroid Build Coastguard Worker         programming_interface: Option<&dyn PciProgrammingInterface>,
485*bb4ee6a4SAndroid Build Coastguard Worker         header_type: PciHeaderType,
486*bb4ee6a4SAndroid Build Coastguard Worker         subsystem_vendor_id: u16,
487*bb4ee6a4SAndroid Build Coastguard Worker         subsystem_id: u16,
488*bb4ee6a4SAndroid Build Coastguard Worker         revision_id: u8,
489*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Self {
490*bb4ee6a4SAndroid Build Coastguard Worker         let mut registers = [0u32; NUM_CONFIGURATION_REGISTERS];
491*bb4ee6a4SAndroid Build Coastguard Worker         let mut writable_bits = [0u32; NUM_CONFIGURATION_REGISTERS];
492*bb4ee6a4SAndroid Build Coastguard Worker         registers[0] = u32::from(device_id) << 16 | u32::from(vendor_id);
493*bb4ee6a4SAndroid Build Coastguard Worker         // TODO(dverkamp): Status should be write-1-to-clear
494*bb4ee6a4SAndroid Build Coastguard Worker         writable_bits[1] = 0x0000_ffff; // Status (r/o), command (r/w)
495*bb4ee6a4SAndroid Build Coastguard Worker         let pi = if let Some(pi) = programming_interface {
496*bb4ee6a4SAndroid Build Coastguard Worker             pi.get_register_value()
497*bb4ee6a4SAndroid Build Coastguard Worker         } else {
498*bb4ee6a4SAndroid Build Coastguard Worker             0
499*bb4ee6a4SAndroid Build Coastguard Worker         };
500*bb4ee6a4SAndroid Build Coastguard Worker         registers[2] = u32::from(class_code.get_register_value()) << 24
501*bb4ee6a4SAndroid Build Coastguard Worker             | u32::from(subclass.get_register_value()) << 16
502*bb4ee6a4SAndroid Build Coastguard Worker             | u32::from(pi) << 8
503*bb4ee6a4SAndroid Build Coastguard Worker             | u32::from(revision_id);
504*bb4ee6a4SAndroid Build Coastguard Worker         writable_bits[3] = 0x0000_00ff; // Cacheline size (r/w)
505*bb4ee6a4SAndroid Build Coastguard Worker         match header_type {
506*bb4ee6a4SAndroid Build Coastguard Worker             PciHeaderType::Device => {
507*bb4ee6a4SAndroid Build Coastguard Worker                 registers[3] = 0x0000_0000; // Header type 0 (device)
508*bb4ee6a4SAndroid Build Coastguard Worker                 writable_bits[15] = 0x0000_00ff; // Interrupt line (r/w)
509*bb4ee6a4SAndroid Build Coastguard Worker                 registers[11] = u32::from(subsystem_id) << 16 | u32::from(subsystem_vendor_id);
510*bb4ee6a4SAndroid Build Coastguard Worker             }
511*bb4ee6a4SAndroid Build Coastguard Worker             PciHeaderType::Bridge => {
512*bb4ee6a4SAndroid Build Coastguard Worker                 registers[3] = 0x0001_0000; // Header type 1 (bridge)
513*bb4ee6a4SAndroid Build Coastguard Worker                 writable_bits[6] = 0x00ff_ffff; // Primary/secondary/subordinate bus number,
514*bb4ee6a4SAndroid Build Coastguard Worker                                                 // secondary latency timer
515*bb4ee6a4SAndroid Build Coastguard Worker                 registers[7] = 0x0000_00f0; // IO base > IO Limit, no IO address on secondary side at initialize
516*bb4ee6a4SAndroid Build Coastguard Worker                 writable_bits[7] = 0xf900_0000; // IO base and limit, secondary status,
517*bb4ee6a4SAndroid Build Coastguard Worker                 registers[8] = 0x0000_fff0; // mem base > mem Limit, no MMIO address on secondary side at initialize
518*bb4ee6a4SAndroid Build Coastguard Worker                 writable_bits[8] = 0xfff0_fff0; // Memory base and limit
519*bb4ee6a4SAndroid Build Coastguard Worker                 registers[9] = 0x0001_fff1; // pmem base > pmem Limit, no prefetch MMIO address on secondary side at initialize
520*bb4ee6a4SAndroid Build Coastguard Worker                 writable_bits[9] = 0xfff0_fff0; // Prefetchable base and limit
521*bb4ee6a4SAndroid Build Coastguard Worker                 writable_bits[10] = 0xffff_ffff; // Prefetchable base upper 32 bits
522*bb4ee6a4SAndroid Build Coastguard Worker                 writable_bits[11] = 0xffff_ffff; // Prefetchable limit upper 32 bits
523*bb4ee6a4SAndroid Build Coastguard Worker                 writable_bits[15] = 0xffff_00ff; // Bridge control (r/w), interrupt line (r/w)
524*bb4ee6a4SAndroid Build Coastguard Worker             }
525*bb4ee6a4SAndroid Build Coastguard Worker         };
526*bb4ee6a4SAndroid Build Coastguard Worker 
527*bb4ee6a4SAndroid Build Coastguard Worker         PciConfiguration {
528*bb4ee6a4SAndroid Build Coastguard Worker             registers,
529*bb4ee6a4SAndroid Build Coastguard Worker             writable_bits,
530*bb4ee6a4SAndroid Build Coastguard Worker             bar_used: [false; NUM_BAR_REGS],
531*bb4ee6a4SAndroid Build Coastguard Worker             bar_configs: [None; NUM_BAR_REGS],
532*bb4ee6a4SAndroid Build Coastguard Worker             last_capability: None,
533*bb4ee6a4SAndroid Build Coastguard Worker             capability_configs: BTreeMap::new(),
534*bb4ee6a4SAndroid Build Coastguard Worker             mmio_mapping: None,
535*bb4ee6a4SAndroid Build Coastguard Worker         }
536*bb4ee6a4SAndroid Build Coastguard Worker     }
537*bb4ee6a4SAndroid Build Coastguard Worker 
538*bb4ee6a4SAndroid Build Coastguard Worker     /// Reads a 32bit register from `reg_idx` in the register map.
read_reg(&self, reg_idx: usize) -> u32539*bb4ee6a4SAndroid Build Coastguard Worker     pub fn read_reg(&self, reg_idx: usize) -> u32 {
540*bb4ee6a4SAndroid Build Coastguard Worker         let mut data = *(self.registers.get(reg_idx).unwrap_or(&0xffff_ffff));
541*bb4ee6a4SAndroid Build Coastguard Worker         if let Some((idx, cfg)) = self.capability_configs.range(..=reg_idx).last() {
542*bb4ee6a4SAndroid Build Coastguard Worker             if reg_idx < idx + cfg.num_regs() {
543*bb4ee6a4SAndroid Build Coastguard Worker                 let cap_idx = reg_idx - idx;
544*bb4ee6a4SAndroid Build Coastguard Worker                 let mask = cfg.read_mask()[cap_idx];
545*bb4ee6a4SAndroid Build Coastguard Worker                 data = (data & !mask) | (cfg.read_reg(cap_idx) & mask);
546*bb4ee6a4SAndroid Build Coastguard Worker             }
547*bb4ee6a4SAndroid Build Coastguard Worker         }
548*bb4ee6a4SAndroid Build Coastguard Worker         data
549*bb4ee6a4SAndroid Build Coastguard Worker     }
550*bb4ee6a4SAndroid Build Coastguard Worker 
551*bb4ee6a4SAndroid Build Coastguard Worker     /// Writes data to PciConfiguration.registers.
552*bb4ee6a4SAndroid Build Coastguard Worker     /// `reg_idx` - index into PciConfiguration.registers.
553*bb4ee6a4SAndroid Build Coastguard Worker     /// `offset`  - PciConfiguration.registers is in unit of DWord, offset define byte
554*bb4ee6a4SAndroid Build Coastguard Worker     ///             offset in the DWord.
555*bb4ee6a4SAndroid Build Coastguard Worker     /// `data`    - The data to write.
write_reg( &mut self, reg_idx: usize, offset: u64, data: &[u8], ) -> Option<Box<dyn PciCapConfigWriteResult>>556*bb4ee6a4SAndroid Build Coastguard Worker     pub fn write_reg(
557*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
558*bb4ee6a4SAndroid Build Coastguard Worker         reg_idx: usize,
559*bb4ee6a4SAndroid Build Coastguard Worker         offset: u64,
560*bb4ee6a4SAndroid Build Coastguard Worker         data: &[u8],
561*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Option<Box<dyn PciCapConfigWriteResult>> {
562*bb4ee6a4SAndroid Build Coastguard Worker         let reg_offset = reg_idx * 4 + offset as usize;
563*bb4ee6a4SAndroid Build Coastguard Worker         match data.len() {
564*bb4ee6a4SAndroid Build Coastguard Worker             1 => self.write_byte(reg_offset, data[0]),
565*bb4ee6a4SAndroid Build Coastguard Worker             2 => self.write_word(reg_offset, u16::from_le_bytes(data.try_into().unwrap())),
566*bb4ee6a4SAndroid Build Coastguard Worker             4 => self.write_dword(reg_offset, u32::from_le_bytes(data.try_into().unwrap())),
567*bb4ee6a4SAndroid Build Coastguard Worker             _ => (),
568*bb4ee6a4SAndroid Build Coastguard Worker         }
569*bb4ee6a4SAndroid Build Coastguard Worker         if let Some((idx, cfg)) = self.capability_configs.range_mut(..=reg_idx).last() {
570*bb4ee6a4SAndroid Build Coastguard Worker             if reg_idx < idx + cfg.num_regs() {
571*bb4ee6a4SAndroid Build Coastguard Worker                 let cap_idx = reg_idx - idx;
572*bb4ee6a4SAndroid Build Coastguard Worker                 let ret = cfg.write_reg(cap_idx, offset, data);
573*bb4ee6a4SAndroid Build Coastguard Worker                 let new_val = cfg.read_reg(cap_idx);
574*bb4ee6a4SAndroid Build Coastguard Worker                 let mask = cfg.read_mask()[cap_idx];
575*bb4ee6a4SAndroid Build Coastguard Worker                 self.set_reg(reg_idx, new_val, mask);
576*bb4ee6a4SAndroid Build Coastguard Worker                 return ret;
577*bb4ee6a4SAndroid Build Coastguard Worker             }
578*bb4ee6a4SAndroid Build Coastguard Worker         }
579*bb4ee6a4SAndroid Build Coastguard Worker         None
580*bb4ee6a4SAndroid Build Coastguard Worker     }
581*bb4ee6a4SAndroid Build Coastguard Worker 
582*bb4ee6a4SAndroid Build Coastguard Worker     /// Writes a 32bit dword to `offset`. `offset` must be 32bit aligned.
write_dword(&mut self, offset: usize, value: u32)583*bb4ee6a4SAndroid Build Coastguard Worker     fn write_dword(&mut self, offset: usize, value: u32) {
584*bb4ee6a4SAndroid Build Coastguard Worker         if offset % 4 != 0 {
585*bb4ee6a4SAndroid Build Coastguard Worker             warn!("bad PCI config dword write offset {}", offset);
586*bb4ee6a4SAndroid Build Coastguard Worker             return;
587*bb4ee6a4SAndroid Build Coastguard Worker         }
588*bb4ee6a4SAndroid Build Coastguard Worker         let reg_idx = offset / 4;
589*bb4ee6a4SAndroid Build Coastguard Worker         if reg_idx < NUM_CONFIGURATION_REGISTERS {
590*bb4ee6a4SAndroid Build Coastguard Worker             let old_value = self.registers[reg_idx];
591*bb4ee6a4SAndroid Build Coastguard Worker             let new_value =
592*bb4ee6a4SAndroid Build Coastguard Worker                 (old_value & !self.writable_bits[reg_idx]) | (value & self.writable_bits[reg_idx]);
593*bb4ee6a4SAndroid Build Coastguard Worker             self.do_write(reg_idx, new_value)
594*bb4ee6a4SAndroid Build Coastguard Worker         } else {
595*bb4ee6a4SAndroid Build Coastguard Worker             warn!("bad PCI dword write {}", offset);
596*bb4ee6a4SAndroid Build Coastguard Worker         }
597*bb4ee6a4SAndroid Build Coastguard Worker     }
598*bb4ee6a4SAndroid Build Coastguard Worker 
599*bb4ee6a4SAndroid Build Coastguard Worker     /// Writes a 16bit word to `offset`. `offset` must be 16bit aligned.
write_word(&mut self, offset: usize, value: u16)600*bb4ee6a4SAndroid Build Coastguard Worker     fn write_word(&mut self, offset: usize, value: u16) {
601*bb4ee6a4SAndroid Build Coastguard Worker         let shift = match offset % 4 {
602*bb4ee6a4SAndroid Build Coastguard Worker             0 => 0,
603*bb4ee6a4SAndroid Build Coastguard Worker             2 => 16,
604*bb4ee6a4SAndroid Build Coastguard Worker             _ => {
605*bb4ee6a4SAndroid Build Coastguard Worker                 warn!("bad PCI config word write offset {}", offset);
606*bb4ee6a4SAndroid Build Coastguard Worker                 return;
607*bb4ee6a4SAndroid Build Coastguard Worker             }
608*bb4ee6a4SAndroid Build Coastguard Worker         };
609*bb4ee6a4SAndroid Build Coastguard Worker         let reg_idx = offset / 4;
610*bb4ee6a4SAndroid Build Coastguard Worker 
611*bb4ee6a4SAndroid Build Coastguard Worker         if reg_idx < NUM_CONFIGURATION_REGISTERS {
612*bb4ee6a4SAndroid Build Coastguard Worker             let old_value = self.registers[reg_idx];
613*bb4ee6a4SAndroid Build Coastguard Worker             let writable_mask = self.writable_bits[reg_idx];
614*bb4ee6a4SAndroid Build Coastguard Worker             let mask = (0xffffu32 << shift) & writable_mask;
615*bb4ee6a4SAndroid Build Coastguard Worker             let shifted_value = (u32::from(value) << shift) & writable_mask;
616*bb4ee6a4SAndroid Build Coastguard Worker             let new_value = old_value & !mask | shifted_value;
617*bb4ee6a4SAndroid Build Coastguard Worker             self.do_write(reg_idx, new_value)
618*bb4ee6a4SAndroid Build Coastguard Worker         } else {
619*bb4ee6a4SAndroid Build Coastguard Worker             warn!("bad PCI config word write offset {}", offset);
620*bb4ee6a4SAndroid Build Coastguard Worker         }
621*bb4ee6a4SAndroid Build Coastguard Worker     }
622*bb4ee6a4SAndroid Build Coastguard Worker 
623*bb4ee6a4SAndroid Build Coastguard Worker     /// Writes a byte to `offset`.
write_byte(&mut self, offset: usize, value: u8)624*bb4ee6a4SAndroid Build Coastguard Worker     fn write_byte(&mut self, offset: usize, value: u8) {
625*bb4ee6a4SAndroid Build Coastguard Worker         self.write_byte_internal(offset, value, true);
626*bb4ee6a4SAndroid Build Coastguard Worker     }
627*bb4ee6a4SAndroid Build Coastguard Worker 
628*bb4ee6a4SAndroid Build Coastguard Worker     /// Writes a byte to `offset`, optionally enforcing read-only bits.
write_byte_internal(&mut self, offset: usize, value: u8, apply_writable_mask: bool)629*bb4ee6a4SAndroid Build Coastguard Worker     fn write_byte_internal(&mut self, offset: usize, value: u8, apply_writable_mask: bool) {
630*bb4ee6a4SAndroid Build Coastguard Worker         let shift = (offset % 4) * 8;
631*bb4ee6a4SAndroid Build Coastguard Worker         let reg_idx = offset / 4;
632*bb4ee6a4SAndroid Build Coastguard Worker 
633*bb4ee6a4SAndroid Build Coastguard Worker         if reg_idx < NUM_CONFIGURATION_REGISTERS {
634*bb4ee6a4SAndroid Build Coastguard Worker             let writable_mask = if apply_writable_mask {
635*bb4ee6a4SAndroid Build Coastguard Worker                 self.writable_bits[reg_idx]
636*bb4ee6a4SAndroid Build Coastguard Worker             } else {
637*bb4ee6a4SAndroid Build Coastguard Worker                 0xffff_ffff
638*bb4ee6a4SAndroid Build Coastguard Worker             };
639*bb4ee6a4SAndroid Build Coastguard Worker             let old_value = self.registers[reg_idx];
640*bb4ee6a4SAndroid Build Coastguard Worker             let mask = (0xffu32 << shift) & writable_mask;
641*bb4ee6a4SAndroid Build Coastguard Worker             let shifted_value = (u32::from(value) << shift) & writable_mask;
642*bb4ee6a4SAndroid Build Coastguard Worker             let new_value = old_value & !mask | shifted_value;
643*bb4ee6a4SAndroid Build Coastguard Worker             self.do_write(reg_idx, new_value)
644*bb4ee6a4SAndroid Build Coastguard Worker         } else {
645*bb4ee6a4SAndroid Build Coastguard Worker             warn!("bad PCI config byte write offset {}", offset);
646*bb4ee6a4SAndroid Build Coastguard Worker         }
647*bb4ee6a4SAndroid Build Coastguard Worker     }
648*bb4ee6a4SAndroid Build Coastguard Worker 
649*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets the value of a PciConfiguration register. This should be used when
650*bb4ee6a4SAndroid Build Coastguard Worker     /// device-internal events require changing the configuration space - as such,
651*bb4ee6a4SAndroid Build Coastguard Worker     /// the writable bits masks do not apply.
652*bb4ee6a4SAndroid Build Coastguard Worker     /// `reg_idx` - index into PciConfiguration.registers.
653*bb4ee6a4SAndroid Build Coastguard Worker     /// `data`    - The data to write.
654*bb4ee6a4SAndroid Build Coastguard Worker     /// `mask`    - The mask of which bits to modify.
set_reg(&mut self, reg_idx: usize, data: u32, mask: u32)655*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_reg(&mut self, reg_idx: usize, data: u32, mask: u32) {
656*bb4ee6a4SAndroid Build Coastguard Worker         if reg_idx >= NUM_CONFIGURATION_REGISTERS {
657*bb4ee6a4SAndroid Build Coastguard Worker             return;
658*bb4ee6a4SAndroid Build Coastguard Worker         }
659*bb4ee6a4SAndroid Build Coastguard Worker         let new_val = (self.registers[reg_idx] & !mask) | (data & mask);
660*bb4ee6a4SAndroid Build Coastguard Worker         self.do_write(reg_idx, new_val);
661*bb4ee6a4SAndroid Build Coastguard Worker     }
662*bb4ee6a4SAndroid Build Coastguard Worker 
663*bb4ee6a4SAndroid Build Coastguard Worker     /// Adds a region specified by `config`.  Configures the specified BAR(s) to
664*bb4ee6a4SAndroid Build Coastguard Worker     /// report this region and size to the guest kernel.  Enforces a few constraints
665*bb4ee6a4SAndroid Build Coastguard Worker     /// (i.e, region size must be power of two, register not already used). Returns 'None' on
666*bb4ee6a4SAndroid Build Coastguard Worker     /// failure all, `Some(BarIndex)` on success.
add_pci_bar(&mut self, config: PciBarConfiguration) -> Result<PciBarIndex>667*bb4ee6a4SAndroid Build Coastguard Worker     pub fn add_pci_bar(&mut self, config: PciBarConfiguration) -> Result<PciBarIndex> {
668*bb4ee6a4SAndroid Build Coastguard Worker         if config.bar_idx >= NUM_BAR_REGS {
669*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::BarInvalid(config.bar_idx));
670*bb4ee6a4SAndroid Build Coastguard Worker         }
671*bb4ee6a4SAndroid Build Coastguard Worker 
672*bb4ee6a4SAndroid Build Coastguard Worker         if self.bar_used[config.bar_idx] {
673*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::BarInUse(config.bar_idx));
674*bb4ee6a4SAndroid Build Coastguard Worker         }
675*bb4ee6a4SAndroid Build Coastguard Worker 
676*bb4ee6a4SAndroid Build Coastguard Worker         if config.size.count_ones() != 1 {
677*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::BarSizeInvalid(config.size));
678*bb4ee6a4SAndroid Build Coastguard Worker         }
679*bb4ee6a4SAndroid Build Coastguard Worker 
680*bb4ee6a4SAndroid Build Coastguard Worker         if config.is_expansion_rom() && config.region_type != PciBarRegionType::Memory32BitRegion {
681*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::BarInvalidRomType);
682*bb4ee6a4SAndroid Build Coastguard Worker         }
683*bb4ee6a4SAndroid Build Coastguard Worker 
684*bb4ee6a4SAndroid Build Coastguard Worker         let min_size = if config.is_expansion_rom() {
685*bb4ee6a4SAndroid Build Coastguard Worker             BAR_ROM_MIN_SIZE
686*bb4ee6a4SAndroid Build Coastguard Worker         } else if config.region_type == PciBarRegionType::IoRegion {
687*bb4ee6a4SAndroid Build Coastguard Worker             BAR_IO_MIN_SIZE
688*bb4ee6a4SAndroid Build Coastguard Worker         } else {
689*bb4ee6a4SAndroid Build Coastguard Worker             BAR_MEM_MIN_SIZE
690*bb4ee6a4SAndroid Build Coastguard Worker         };
691*bb4ee6a4SAndroid Build Coastguard Worker 
692*bb4ee6a4SAndroid Build Coastguard Worker         if config.size < min_size {
693*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::BarSizeInvalid(config.size));
694*bb4ee6a4SAndroid Build Coastguard Worker         }
695*bb4ee6a4SAndroid Build Coastguard Worker 
696*bb4ee6a4SAndroid Build Coastguard Worker         if config.addr % config.size != 0 {
697*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::BarAlignmentInvalid(config.addr, config.size));
698*bb4ee6a4SAndroid Build Coastguard Worker         }
699*bb4ee6a4SAndroid Build Coastguard Worker 
700*bb4ee6a4SAndroid Build Coastguard Worker         let reg_idx = config.reg_index();
701*bb4ee6a4SAndroid Build Coastguard Worker         let end_addr = config
702*bb4ee6a4SAndroid Build Coastguard Worker             .addr
703*bb4ee6a4SAndroid Build Coastguard Worker             .checked_add(config.size)
704*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::BarAddressInvalid(config.addr, config.size))?;
705*bb4ee6a4SAndroid Build Coastguard Worker         match config.region_type {
706*bb4ee6a4SAndroid Build Coastguard Worker             PciBarRegionType::Memory32BitRegion | PciBarRegionType::IoRegion => {
707*bb4ee6a4SAndroid Build Coastguard Worker                 if end_addr > u64::from(u32::MAX) {
708*bb4ee6a4SAndroid Build Coastguard Worker                     return Err(Error::BarAddressInvalid(config.addr, config.size));
709*bb4ee6a4SAndroid Build Coastguard Worker                 }
710*bb4ee6a4SAndroid Build Coastguard Worker             }
711*bb4ee6a4SAndroid Build Coastguard Worker             PciBarRegionType::Memory64BitRegion => {
712*bb4ee6a4SAndroid Build Coastguard Worker                 // The expansion ROM BAR cannot be used for part of a 64-bit BAR.
713*bb4ee6a4SAndroid Build Coastguard Worker                 if config.bar_idx + 1 >= ROM_BAR_IDX {
714*bb4ee6a4SAndroid Build Coastguard Worker                     return Err(Error::BarInvalid64(config.bar_idx));
715*bb4ee6a4SAndroid Build Coastguard Worker                 }
716*bb4ee6a4SAndroid Build Coastguard Worker 
717*bb4ee6a4SAndroid Build Coastguard Worker                 if self.bar_used[config.bar_idx + 1] {
718*bb4ee6a4SAndroid Build Coastguard Worker                     return Err(Error::BarInUse64(config.bar_idx));
719*bb4ee6a4SAndroid Build Coastguard Worker                 }
720*bb4ee6a4SAndroid Build Coastguard Worker 
721*bb4ee6a4SAndroid Build Coastguard Worker                 self.do_write(reg_idx + 1, (config.addr >> 32) as u32);
722*bb4ee6a4SAndroid Build Coastguard Worker                 self.writable_bits[reg_idx + 1] = !((config.size - 1) >> 32) as u32;
723*bb4ee6a4SAndroid Build Coastguard Worker                 self.bar_used[config.bar_idx + 1] = true;
724*bb4ee6a4SAndroid Build Coastguard Worker             }
725*bb4ee6a4SAndroid Build Coastguard Worker         }
726*bb4ee6a4SAndroid Build Coastguard Worker 
727*bb4ee6a4SAndroid Build Coastguard Worker         let (mask, lower_bits) = match config.region_type {
728*bb4ee6a4SAndroid Build Coastguard Worker             PciBarRegionType::Memory32BitRegion | PciBarRegionType::Memory64BitRegion => {
729*bb4ee6a4SAndroid Build Coastguard Worker                 self.registers[COMMAND_REG] |= COMMAND_REG_MEMORY_SPACE_MASK;
730*bb4ee6a4SAndroid Build Coastguard Worker                 (
731*bb4ee6a4SAndroid Build Coastguard Worker                     BAR_MEM_ADDR_MASK,
732*bb4ee6a4SAndroid Build Coastguard Worker                     config.prefetchable as u32 | config.region_type as u32,
733*bb4ee6a4SAndroid Build Coastguard Worker                 )
734*bb4ee6a4SAndroid Build Coastguard Worker             }
735*bb4ee6a4SAndroid Build Coastguard Worker             PciBarRegionType::IoRegion => {
736*bb4ee6a4SAndroid Build Coastguard Worker                 self.registers[COMMAND_REG] |= COMMAND_REG_IO_SPACE_MASK;
737*bb4ee6a4SAndroid Build Coastguard Worker                 (BAR_IO_ADDR_MASK, config.region_type as u32)
738*bb4ee6a4SAndroid Build Coastguard Worker             }
739*bb4ee6a4SAndroid Build Coastguard Worker         };
740*bb4ee6a4SAndroid Build Coastguard Worker 
741*bb4ee6a4SAndroid Build Coastguard Worker         self.do_write(reg_idx, ((config.addr as u32) & mask) | lower_bits);
742*bb4ee6a4SAndroid Build Coastguard Worker         self.writable_bits[reg_idx] = !(config.size - 1) as u32;
743*bb4ee6a4SAndroid Build Coastguard Worker         if config.is_expansion_rom() {
744*bb4ee6a4SAndroid Build Coastguard Worker             self.writable_bits[reg_idx] |= 1; // Expansion ROM enable bit.
745*bb4ee6a4SAndroid Build Coastguard Worker         }
746*bb4ee6a4SAndroid Build Coastguard Worker         self.bar_used[config.bar_idx] = true;
747*bb4ee6a4SAndroid Build Coastguard Worker         self.bar_configs[config.bar_idx] = Some(config);
748*bb4ee6a4SAndroid Build Coastguard Worker         Ok(config.bar_idx)
749*bb4ee6a4SAndroid Build Coastguard Worker     }
750*bb4ee6a4SAndroid Build Coastguard Worker 
751*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns an iterator of the currently configured base address registers.
752*bb4ee6a4SAndroid Build Coastguard Worker     #[allow(dead_code)] // TODO(dverkamp): remove this once used
get_bars(&self) -> PciBarIter753*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_bars(&self) -> PciBarIter {
754*bb4ee6a4SAndroid Build Coastguard Worker         PciBarIter {
755*bb4ee6a4SAndroid Build Coastguard Worker             config: self,
756*bb4ee6a4SAndroid Build Coastguard Worker             bar_num: 0,
757*bb4ee6a4SAndroid Build Coastguard Worker         }
758*bb4ee6a4SAndroid Build Coastguard Worker     }
759*bb4ee6a4SAndroid Build Coastguard Worker 
760*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns the configuration of a base address register, if present.
get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration>761*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration> {
762*bb4ee6a4SAndroid Build Coastguard Worker         let config = self.bar_configs.get(bar_num)?;
763*bb4ee6a4SAndroid Build Coastguard Worker 
764*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(mut config) = config {
765*bb4ee6a4SAndroid Build Coastguard Worker             let command = self.read_reg(COMMAND_REG);
766*bb4ee6a4SAndroid Build Coastguard Worker             if (config.is_memory() && (command & COMMAND_REG_MEMORY_SPACE_MASK == 0))
767*bb4ee6a4SAndroid Build Coastguard Worker                 || (config.is_io() && (command & COMMAND_REG_IO_SPACE_MASK == 0))
768*bb4ee6a4SAndroid Build Coastguard Worker             {
769*bb4ee6a4SAndroid Build Coastguard Worker                 return None;
770*bb4ee6a4SAndroid Build Coastguard Worker             }
771*bb4ee6a4SAndroid Build Coastguard Worker 
772*bb4ee6a4SAndroid Build Coastguard Worker             // The address may have been modified by the guest, so the value in bar_configs
773*bb4ee6a4SAndroid Build Coastguard Worker             // may be outdated. Replace it with the current value.
774*bb4ee6a4SAndroid Build Coastguard Worker             config.addr = self.get_bar_addr(bar_num);
775*bb4ee6a4SAndroid Build Coastguard Worker             Some(config)
776*bb4ee6a4SAndroid Build Coastguard Worker         } else {
777*bb4ee6a4SAndroid Build Coastguard Worker             None
778*bb4ee6a4SAndroid Build Coastguard Worker         }
779*bb4ee6a4SAndroid Build Coastguard Worker     }
780*bb4ee6a4SAndroid Build Coastguard Worker 
781*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns the type of the given BAR region.
get_bar_type(&self, bar_num: PciBarIndex) -> Option<PciBarRegionType>782*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_bar_type(&self, bar_num: PciBarIndex) -> Option<PciBarRegionType> {
783*bb4ee6a4SAndroid Build Coastguard Worker         self.bar_configs.get(bar_num)?.map(|c| c.region_type)
784*bb4ee6a4SAndroid Build Coastguard Worker     }
785*bb4ee6a4SAndroid Build Coastguard Worker 
786*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns the address of the given BAR region.
get_bar_addr(&self, bar_num: PciBarIndex) -> u64787*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_bar_addr(&self, bar_num: PciBarIndex) -> u64 {
788*bb4ee6a4SAndroid Build Coastguard Worker         let bar_idx = if bar_num == ROM_BAR_IDX {
789*bb4ee6a4SAndroid Build Coastguard Worker             ROM_BAR_REG
790*bb4ee6a4SAndroid Build Coastguard Worker         } else {
791*bb4ee6a4SAndroid Build Coastguard Worker             BAR0_REG + bar_num
792*bb4ee6a4SAndroid Build Coastguard Worker         };
793*bb4ee6a4SAndroid Build Coastguard Worker 
794*bb4ee6a4SAndroid Build Coastguard Worker         let bar_type = match self.get_bar_type(bar_num) {
795*bb4ee6a4SAndroid Build Coastguard Worker             Some(t) => t,
796*bb4ee6a4SAndroid Build Coastguard Worker             None => return 0,
797*bb4ee6a4SAndroid Build Coastguard Worker         };
798*bb4ee6a4SAndroid Build Coastguard Worker 
799*bb4ee6a4SAndroid Build Coastguard Worker         match bar_type {
800*bb4ee6a4SAndroid Build Coastguard Worker             PciBarRegionType::IoRegion => u64::from(self.registers[bar_idx] & BAR_IO_ADDR_MASK),
801*bb4ee6a4SAndroid Build Coastguard Worker             PciBarRegionType::Memory32BitRegion => {
802*bb4ee6a4SAndroid Build Coastguard Worker                 u64::from(self.registers[bar_idx] & BAR_MEM_ADDR_MASK)
803*bb4ee6a4SAndroid Build Coastguard Worker             }
804*bb4ee6a4SAndroid Build Coastguard Worker             PciBarRegionType::Memory64BitRegion => {
805*bb4ee6a4SAndroid Build Coastguard Worker                 u64::from(self.registers[bar_idx] & BAR_MEM_ADDR_MASK)
806*bb4ee6a4SAndroid Build Coastguard Worker                     | u64::from(self.registers[bar_idx + 1]) << 32
807*bb4ee6a4SAndroid Build Coastguard Worker             }
808*bb4ee6a4SAndroid Build Coastguard Worker         }
809*bb4ee6a4SAndroid Build Coastguard Worker     }
810*bb4ee6a4SAndroid Build Coastguard Worker 
811*bb4ee6a4SAndroid Build Coastguard Worker     /// Configures the IRQ line and pin used by this device.
set_irq(&mut self, line: u8, pin: PciInterruptPin)812*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_irq(&mut self, line: u8, pin: PciInterruptPin) {
813*bb4ee6a4SAndroid Build Coastguard Worker         // `pin` is 1-based in the pci config space.
814*bb4ee6a4SAndroid Build Coastguard Worker         let pin_idx = (pin as u32) + 1;
815*bb4ee6a4SAndroid Build Coastguard Worker         let new_val = (self.registers[INTERRUPT_LINE_PIN_REG] & 0xffff_0000)
816*bb4ee6a4SAndroid Build Coastguard Worker             | (pin_idx << 8)
817*bb4ee6a4SAndroid Build Coastguard Worker             | u32::from(line);
818*bb4ee6a4SAndroid Build Coastguard Worker         self.do_write(INTERRUPT_LINE_PIN_REG, new_val)
819*bb4ee6a4SAndroid Build Coastguard Worker     }
820*bb4ee6a4SAndroid Build Coastguard Worker 
821*bb4ee6a4SAndroid Build Coastguard Worker     /// Adds the capability `cap_data` to the list of capabilities.
822*bb4ee6a4SAndroid Build Coastguard Worker     /// `cap_data` should include the two-byte PCI capability header (type, next),
823*bb4ee6a4SAndroid Build Coastguard Worker     /// but not populate it. Correct values will be generated automatically based
824*bb4ee6a4SAndroid Build Coastguard Worker     /// on `cap_data.id()`.
add_capability( &mut self, cap_data: &dyn PciCapability, cap_config: Option<Box<dyn PciCapConfig>>, ) -> Result<()>825*bb4ee6a4SAndroid Build Coastguard Worker     pub fn add_capability(
826*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
827*bb4ee6a4SAndroid Build Coastguard Worker         cap_data: &dyn PciCapability,
828*bb4ee6a4SAndroid Build Coastguard Worker         cap_config: Option<Box<dyn PciCapConfig>>,
829*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<()> {
830*bb4ee6a4SAndroid Build Coastguard Worker         let total_len = cap_data.bytes().len();
831*bb4ee6a4SAndroid Build Coastguard Worker         // Check that the length is valid.
832*bb4ee6a4SAndroid Build Coastguard Worker         if cap_data.bytes().is_empty() {
833*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::CapabilityEmpty);
834*bb4ee6a4SAndroid Build Coastguard Worker         }
835*bb4ee6a4SAndroid Build Coastguard Worker         let (cap_offset, tail_offset) = match self.last_capability {
836*bb4ee6a4SAndroid Build Coastguard Worker             Some((offset, len)) => (Self::next_dword(offset, len), offset + 1),
837*bb4ee6a4SAndroid Build Coastguard Worker             None => (FIRST_CAPABILITY_OFFSET, CAPABILITY_LIST_HEAD_OFFSET),
838*bb4ee6a4SAndroid Build Coastguard Worker         };
839*bb4ee6a4SAndroid Build Coastguard Worker         let end_offset = cap_offset
840*bb4ee6a4SAndroid Build Coastguard Worker             .checked_add(total_len)
841*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::CapabilitySpaceFull(total_len))?;
842*bb4ee6a4SAndroid Build Coastguard Worker         if end_offset > CAPABILITY_MAX_OFFSET {
843*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::CapabilitySpaceFull(total_len));
844*bb4ee6a4SAndroid Build Coastguard Worker         }
845*bb4ee6a4SAndroid Build Coastguard Worker         self.do_write(
846*bb4ee6a4SAndroid Build Coastguard Worker             STATUS_REG,
847*bb4ee6a4SAndroid Build Coastguard Worker             self.registers[STATUS_REG] | STATUS_REG_CAPABILITIES_USED_MASK,
848*bb4ee6a4SAndroid Build Coastguard Worker         );
849*bb4ee6a4SAndroid Build Coastguard Worker         self.write_byte_internal(tail_offset, cap_offset as u8, false);
850*bb4ee6a4SAndroid Build Coastguard Worker         self.write_byte_internal(cap_offset, cap_data.id() as u8, false);
851*bb4ee6a4SAndroid Build Coastguard Worker         self.write_byte_internal(cap_offset + 1, 0, false); // Next pointer.
852*bb4ee6a4SAndroid Build Coastguard Worker         for (i, byte) in cap_data.bytes().iter().enumerate().skip(2) {
853*bb4ee6a4SAndroid Build Coastguard Worker             self.write_byte_internal(cap_offset + i, *byte, false);
854*bb4ee6a4SAndroid Build Coastguard Worker         }
855*bb4ee6a4SAndroid Build Coastguard Worker         let reg_idx = cap_offset / 4;
856*bb4ee6a4SAndroid Build Coastguard Worker         for (i, dword) in cap_data.writable_bits().iter().enumerate() {
857*bb4ee6a4SAndroid Build Coastguard Worker             self.writable_bits[reg_idx + i] = *dword;
858*bb4ee6a4SAndroid Build Coastguard Worker         }
859*bb4ee6a4SAndroid Build Coastguard Worker         self.last_capability = Some((cap_offset, total_len));
860*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(mut cap_config) = cap_config {
861*bb4ee6a4SAndroid Build Coastguard Worker             if let Some((mapping, offset)) = &self.mmio_mapping {
862*bb4ee6a4SAndroid Build Coastguard Worker                 cap_config.set_cap_mapping(PciCapMapping {
863*bb4ee6a4SAndroid Build Coastguard Worker                     mapping: mapping.clone(),
864*bb4ee6a4SAndroid Build Coastguard Worker                     offset: reg_idx * 4 + offset,
865*bb4ee6a4SAndroid Build Coastguard Worker                     num_regs: total_len / 4,
866*bb4ee6a4SAndroid Build Coastguard Worker                 });
867*bb4ee6a4SAndroid Build Coastguard Worker             }
868*bb4ee6a4SAndroid Build Coastguard Worker             self.capability_configs.insert(cap_offset / 4, cap_config);
869*bb4ee6a4SAndroid Build Coastguard Worker         }
870*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
871*bb4ee6a4SAndroid Build Coastguard Worker     }
872*bb4ee6a4SAndroid Build Coastguard Worker 
873*bb4ee6a4SAndroid Build Coastguard Worker     // Find the next aligned offset after the one given.
next_dword(offset: usize, len: usize) -> usize874*bb4ee6a4SAndroid Build Coastguard Worker     fn next_dword(offset: usize, len: usize) -> usize {
875*bb4ee6a4SAndroid Build Coastguard Worker         let next = offset + len;
876*bb4ee6a4SAndroid Build Coastguard Worker         (next + 3) & !3
877*bb4ee6a4SAndroid Build Coastguard Worker     }
878*bb4ee6a4SAndroid Build Coastguard Worker 
do_write(&mut self, reg_idx: usize, value: u32)879*bb4ee6a4SAndroid Build Coastguard Worker     fn do_write(&mut self, reg_idx: usize, value: u32) {
880*bb4ee6a4SAndroid Build Coastguard Worker         self.registers[reg_idx] = value;
881*bb4ee6a4SAndroid Build Coastguard Worker         if let Some((mmio_mapping, offset)) = self.mmio_mapping.as_ref() {
882*bb4ee6a4SAndroid Build Coastguard Worker             let mmio_mapping = mmio_mapping.lock();
883*bb4ee6a4SAndroid Build Coastguard Worker             let reg_offset = offset + reg_idx * 4;
884*bb4ee6a4SAndroid Build Coastguard Worker             if reg_idx == HEADER_TYPE_REG {
885*bb4ee6a4SAndroid Build Coastguard Worker                 // Skip writing the header type byte (reg_idx=2/offset=3) as
886*bb4ee6a4SAndroid Build Coastguard Worker                 // per the requirements of PciDevice.setup_pci_config_mapping.
887*bb4ee6a4SAndroid Build Coastguard Worker                 mmio_mapping
888*bb4ee6a4SAndroid Build Coastguard Worker                     .write_obj_volatile((value & 0xffff) as u16, reg_offset)
889*bb4ee6a4SAndroid Build Coastguard Worker                     .expect("bad register offset");
890*bb4ee6a4SAndroid Build Coastguard Worker                 // Skip HEADER_TYPE_REG_OFFSET (i.e. header+mfd byte)
891*bb4ee6a4SAndroid Build Coastguard Worker                 mmio_mapping
892*bb4ee6a4SAndroid Build Coastguard Worker                     .write_obj_volatile(((value >> 24) & 0xff) as u8, reg_offset + 3)
893*bb4ee6a4SAndroid Build Coastguard Worker                     .expect("bad register offset");
894*bb4ee6a4SAndroid Build Coastguard Worker             } else {
895*bb4ee6a4SAndroid Build Coastguard Worker                 mmio_mapping
896*bb4ee6a4SAndroid Build Coastguard Worker                     .write_obj_volatile(value, reg_offset)
897*bb4ee6a4SAndroid Build Coastguard Worker                     .expect("bad register offset");
898*bb4ee6a4SAndroid Build Coastguard Worker             }
899*bb4ee6a4SAndroid Build Coastguard Worker             if let Err(err) = mmio_mapping.flush_region(reg_offset, 4) {
900*bb4ee6a4SAndroid Build Coastguard Worker                 error!(
901*bb4ee6a4SAndroid Build Coastguard Worker                     "failed to flush write to pci mmio register ({}): {}",
902*bb4ee6a4SAndroid Build Coastguard Worker                     reg_idx, err
903*bb4ee6a4SAndroid Build Coastguard Worker                 );
904*bb4ee6a4SAndroid Build Coastguard Worker             }
905*bb4ee6a4SAndroid Build Coastguard Worker         }
906*bb4ee6a4SAndroid Build Coastguard Worker     }
907*bb4ee6a4SAndroid Build Coastguard Worker 
snapshot(&mut self) -> anyhow::Result<serde_json::Value>908*bb4ee6a4SAndroid Build Coastguard Worker     pub fn snapshot(&mut self) -> anyhow::Result<serde_json::Value> {
909*bb4ee6a4SAndroid Build Coastguard Worker         serde_json::to_value(PciConfigurationSerialized {
910*bb4ee6a4SAndroid Build Coastguard Worker             registers: self.registers,
911*bb4ee6a4SAndroid Build Coastguard Worker             writable_bits: self.writable_bits,
912*bb4ee6a4SAndroid Build Coastguard Worker             bar_used: self.bar_used,
913*bb4ee6a4SAndroid Build Coastguard Worker             bar_configs: self.bar_configs,
914*bb4ee6a4SAndroid Build Coastguard Worker             last_capability: self.last_capability,
915*bb4ee6a4SAndroid Build Coastguard Worker         })
916*bb4ee6a4SAndroid Build Coastguard Worker         .context("failed to serialize PciConfiguration")
917*bb4ee6a4SAndroid Build Coastguard Worker     }
918*bb4ee6a4SAndroid Build Coastguard Worker 
restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>919*bb4ee6a4SAndroid Build Coastguard Worker     pub fn restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
920*bb4ee6a4SAndroid Build Coastguard Worker         let deser: PciConfigurationSerialized =
921*bb4ee6a4SAndroid Build Coastguard Worker             serde_json::from_value(data).context("failed to deserialize PciConfiguration")?;
922*bb4ee6a4SAndroid Build Coastguard Worker         self.registers = deser.registers;
923*bb4ee6a4SAndroid Build Coastguard Worker         self.writable_bits = deser.writable_bits;
924*bb4ee6a4SAndroid Build Coastguard Worker         self.bar_used = deser.bar_used;
925*bb4ee6a4SAndroid Build Coastguard Worker         self.bar_configs = deser.bar_configs;
926*bb4ee6a4SAndroid Build Coastguard Worker         self.last_capability = deser.last_capability;
927*bb4ee6a4SAndroid Build Coastguard Worker         // Restore everything via do_write to avoid writing to the header type register
928*bb4ee6a4SAndroid Build Coastguard Worker         // and clobbering the multi-function device bit, as that bit is managed by the
929*bb4ee6a4SAndroid Build Coastguard Worker         // PciRoot. Since restore doesn't change the types or layout of PCI devices, the
930*bb4ee6a4SAndroid Build Coastguard Worker         // header type bits in the register are already correct anyway.
931*bb4ee6a4SAndroid Build Coastguard Worker         for i in 0..NUM_CONFIGURATION_REGISTERS {
932*bb4ee6a4SAndroid Build Coastguard Worker             self.do_write(i, self.registers[i]);
933*bb4ee6a4SAndroid Build Coastguard Worker         }
934*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
935*bb4ee6a4SAndroid Build Coastguard Worker     }
936*bb4ee6a4SAndroid Build Coastguard Worker 
setup_mapping( &mut self, shmem: &SharedMemory, base: usize, len: usize, ) -> anyhow::Result<()>937*bb4ee6a4SAndroid Build Coastguard Worker     pub fn setup_mapping(
938*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
939*bb4ee6a4SAndroid Build Coastguard Worker         shmem: &SharedMemory,
940*bb4ee6a4SAndroid Build Coastguard Worker         base: usize,
941*bb4ee6a4SAndroid Build Coastguard Worker         len: usize,
942*bb4ee6a4SAndroid Build Coastguard Worker     ) -> anyhow::Result<()> {
943*bb4ee6a4SAndroid Build Coastguard Worker         if self.mmio_mapping.is_some() {
944*bb4ee6a4SAndroid Build Coastguard Worker             bail!("PCIe config mmio mapping already initialized");
945*bb4ee6a4SAndroid Build Coastguard Worker         }
946*bb4ee6a4SAndroid Build Coastguard Worker         let mapping = MemoryMappingBuilder::new(base::pagesize())
947*bb4ee6a4SAndroid Build Coastguard Worker             .from_shared_memory(shmem)
948*bb4ee6a4SAndroid Build Coastguard Worker             .build()
949*bb4ee6a4SAndroid Build Coastguard Worker             .context("Failed to create mapping")?;
950*bb4ee6a4SAndroid Build Coastguard Worker         for i in 0..(len / 4) {
951*bb4ee6a4SAndroid Build Coastguard Worker             let val = self.registers.get(i).unwrap_or(&0xffff_ffff);
952*bb4ee6a4SAndroid Build Coastguard Worker             mapping
953*bb4ee6a4SAndroid Build Coastguard Worker                 .write_obj_volatile(*val, base + i * 4)
954*bb4ee6a4SAndroid Build Coastguard Worker                 .expect("memcpy failed");
955*bb4ee6a4SAndroid Build Coastguard Worker         }
956*bb4ee6a4SAndroid Build Coastguard Worker         let mapping = Arc::new(Mutex::new(mapping));
957*bb4ee6a4SAndroid Build Coastguard Worker         for (idx, cap) in self.capability_configs.iter_mut() {
958*bb4ee6a4SAndroid Build Coastguard Worker             let mut cap_mapping = PciCapMapping {
959*bb4ee6a4SAndroid Build Coastguard Worker                 mapping: mapping.clone(),
960*bb4ee6a4SAndroid Build Coastguard Worker                 offset: idx * 4 + base,
961*bb4ee6a4SAndroid Build Coastguard Worker                 num_regs: cap.num_regs(),
962*bb4ee6a4SAndroid Build Coastguard Worker             };
963*bb4ee6a4SAndroid Build Coastguard Worker             for i in 0..cap.num_regs() {
964*bb4ee6a4SAndroid Build Coastguard Worker                 let val = cap.read_reg(i);
965*bb4ee6a4SAndroid Build Coastguard Worker                 let mask = cap.read_mask()[i];
966*bb4ee6a4SAndroid Build Coastguard Worker                 cap_mapping.set_reg(i, val, mask);
967*bb4ee6a4SAndroid Build Coastguard Worker             }
968*bb4ee6a4SAndroid Build Coastguard Worker             cap.set_cap_mapping(cap_mapping);
969*bb4ee6a4SAndroid Build Coastguard Worker         }
970*bb4ee6a4SAndroid Build Coastguard Worker         self.mmio_mapping = Some((mapping, base));
971*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
972*bb4ee6a4SAndroid Build Coastguard Worker     }
973*bb4ee6a4SAndroid Build Coastguard Worker }
974*bb4ee6a4SAndroid Build Coastguard Worker 
975*bb4ee6a4SAndroid Build Coastguard Worker impl PciBarConfiguration {
new( bar_idx: PciBarIndex, size: u64, region_type: PciBarRegionType, prefetchable: PciBarPrefetchable, ) -> Self976*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(
977*bb4ee6a4SAndroid Build Coastguard Worker         bar_idx: PciBarIndex,
978*bb4ee6a4SAndroid Build Coastguard Worker         size: u64,
979*bb4ee6a4SAndroid Build Coastguard Worker         region_type: PciBarRegionType,
980*bb4ee6a4SAndroid Build Coastguard Worker         prefetchable: PciBarPrefetchable,
981*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Self {
982*bb4ee6a4SAndroid Build Coastguard Worker         PciBarConfiguration {
983*bb4ee6a4SAndroid Build Coastguard Worker             bar_idx,
984*bb4ee6a4SAndroid Build Coastguard Worker             addr: 0,
985*bb4ee6a4SAndroid Build Coastguard Worker             size,
986*bb4ee6a4SAndroid Build Coastguard Worker             region_type,
987*bb4ee6a4SAndroid Build Coastguard Worker             prefetchable,
988*bb4ee6a4SAndroid Build Coastguard Worker         }
989*bb4ee6a4SAndroid Build Coastguard Worker     }
990*bb4ee6a4SAndroid Build Coastguard Worker 
bar_index(&self) -> PciBarIndex991*bb4ee6a4SAndroid Build Coastguard Worker     pub fn bar_index(&self) -> PciBarIndex {
992*bb4ee6a4SAndroid Build Coastguard Worker         self.bar_idx
993*bb4ee6a4SAndroid Build Coastguard Worker     }
994*bb4ee6a4SAndroid Build Coastguard Worker 
reg_index(&self) -> usize995*bb4ee6a4SAndroid Build Coastguard Worker     pub fn reg_index(&self) -> usize {
996*bb4ee6a4SAndroid Build Coastguard Worker         if self.bar_idx == ROM_BAR_IDX {
997*bb4ee6a4SAndroid Build Coastguard Worker             ROM_BAR_REG
998*bb4ee6a4SAndroid Build Coastguard Worker         } else {
999*bb4ee6a4SAndroid Build Coastguard Worker             BAR0_REG + self.bar_idx
1000*bb4ee6a4SAndroid Build Coastguard Worker         }
1001*bb4ee6a4SAndroid Build Coastguard Worker     }
1002*bb4ee6a4SAndroid Build Coastguard Worker 
address(&self) -> u641003*bb4ee6a4SAndroid Build Coastguard Worker     pub fn address(&self) -> u64 {
1004*bb4ee6a4SAndroid Build Coastguard Worker         self.addr
1005*bb4ee6a4SAndroid Build Coastguard Worker     }
1006*bb4ee6a4SAndroid Build Coastguard Worker 
address_range(&self) -> std::ops::Range<u64>1007*bb4ee6a4SAndroid Build Coastguard Worker     pub fn address_range(&self) -> std::ops::Range<u64> {
1008*bb4ee6a4SAndroid Build Coastguard Worker         self.addr..self.addr + self.size
1009*bb4ee6a4SAndroid Build Coastguard Worker     }
1010*bb4ee6a4SAndroid Build Coastguard Worker 
set_address(mut self, addr: u64) -> Self1011*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_address(mut self, addr: u64) -> Self {
1012*bb4ee6a4SAndroid Build Coastguard Worker         self.addr = addr;
1013*bb4ee6a4SAndroid Build Coastguard Worker         self
1014*bb4ee6a4SAndroid Build Coastguard Worker     }
1015*bb4ee6a4SAndroid Build Coastguard Worker 
size(&self) -> u641016*bb4ee6a4SAndroid Build Coastguard Worker     pub fn size(&self) -> u64 {
1017*bb4ee6a4SAndroid Build Coastguard Worker         self.size
1018*bb4ee6a4SAndroid Build Coastguard Worker     }
1019*bb4ee6a4SAndroid Build Coastguard Worker 
is_expansion_rom(&self) -> bool1020*bb4ee6a4SAndroid Build Coastguard Worker     pub fn is_expansion_rom(&self) -> bool {
1021*bb4ee6a4SAndroid Build Coastguard Worker         self.bar_idx == ROM_BAR_IDX
1022*bb4ee6a4SAndroid Build Coastguard Worker     }
1023*bb4ee6a4SAndroid Build Coastguard Worker 
is_memory(&self) -> bool1024*bb4ee6a4SAndroid Build Coastguard Worker     pub fn is_memory(&self) -> bool {
1025*bb4ee6a4SAndroid Build Coastguard Worker         matches!(
1026*bb4ee6a4SAndroid Build Coastguard Worker             self.region_type,
1027*bb4ee6a4SAndroid Build Coastguard Worker             PciBarRegionType::Memory32BitRegion | PciBarRegionType::Memory64BitRegion
1028*bb4ee6a4SAndroid Build Coastguard Worker         )
1029*bb4ee6a4SAndroid Build Coastguard Worker     }
1030*bb4ee6a4SAndroid Build Coastguard Worker 
is_64bit_memory(&self) -> bool1031*bb4ee6a4SAndroid Build Coastguard Worker     pub fn is_64bit_memory(&self) -> bool {
1032*bb4ee6a4SAndroid Build Coastguard Worker         self.region_type == PciBarRegionType::Memory64BitRegion
1033*bb4ee6a4SAndroid Build Coastguard Worker     }
1034*bb4ee6a4SAndroid Build Coastguard Worker 
is_io(&self) -> bool1035*bb4ee6a4SAndroid Build Coastguard Worker     pub fn is_io(&self) -> bool {
1036*bb4ee6a4SAndroid Build Coastguard Worker         self.region_type == PciBarRegionType::IoRegion
1037*bb4ee6a4SAndroid Build Coastguard Worker     }
1038*bb4ee6a4SAndroid Build Coastguard Worker 
is_prefetchable(&self) -> bool1039*bb4ee6a4SAndroid Build Coastguard Worker     pub fn is_prefetchable(&self) -> bool {
1040*bb4ee6a4SAndroid Build Coastguard Worker         self.is_memory() && self.prefetchable == PciBarPrefetchable::Prefetchable
1041*bb4ee6a4SAndroid Build Coastguard Worker     }
1042*bb4ee6a4SAndroid Build Coastguard Worker }
1043*bb4ee6a4SAndroid Build Coastguard Worker 
1044*bb4ee6a4SAndroid Build Coastguard Worker impl<T: PciCapConfig + ?Sized> PciCapConfig for Arc<Mutex<T>> {
read_mask(&self) -> &'static [u32]1045*bb4ee6a4SAndroid Build Coastguard Worker     fn read_mask(&self) -> &'static [u32] {
1046*bb4ee6a4SAndroid Build Coastguard Worker         self.lock().read_mask()
1047*bb4ee6a4SAndroid Build Coastguard Worker     }
read_reg(&self, reg_idx: usize) -> u321048*bb4ee6a4SAndroid Build Coastguard Worker     fn read_reg(&self, reg_idx: usize) -> u32 {
1049*bb4ee6a4SAndroid Build Coastguard Worker         self.lock().read_reg(reg_idx)
1050*bb4ee6a4SAndroid Build Coastguard Worker     }
write_reg( &mut self, reg_idx: usize, offset: u64, data: &[u8], ) -> Option<Box<dyn PciCapConfigWriteResult>>1051*bb4ee6a4SAndroid Build Coastguard Worker     fn write_reg(
1052*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
1053*bb4ee6a4SAndroid Build Coastguard Worker         reg_idx: usize,
1054*bb4ee6a4SAndroid Build Coastguard Worker         offset: u64,
1055*bb4ee6a4SAndroid Build Coastguard Worker         data: &[u8],
1056*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Option<Box<dyn PciCapConfigWriteResult>> {
1057*bb4ee6a4SAndroid Build Coastguard Worker         self.lock().write_reg(reg_idx, offset, data)
1058*bb4ee6a4SAndroid Build Coastguard Worker     }
set_cap_mapping(&mut self, mapping: PciCapMapping)1059*bb4ee6a4SAndroid Build Coastguard Worker     fn set_cap_mapping(&mut self, mapping: PciCapMapping) {
1060*bb4ee6a4SAndroid Build Coastguard Worker         self.lock().set_cap_mapping(mapping)
1061*bb4ee6a4SAndroid Build Coastguard Worker     }
1062*bb4ee6a4SAndroid Build Coastguard Worker }
1063*bb4ee6a4SAndroid Build Coastguard Worker 
1064*bb4ee6a4SAndroid Build Coastguard Worker /// Struct for updating a capabilitiy's mmio mapping.
1065*bb4ee6a4SAndroid Build Coastguard Worker pub struct PciCapMapping {
1066*bb4ee6a4SAndroid Build Coastguard Worker     mapping: Arc<Mutex<MemoryMapping>>,
1067*bb4ee6a4SAndroid Build Coastguard Worker     offset: usize,
1068*bb4ee6a4SAndroid Build Coastguard Worker     num_regs: usize,
1069*bb4ee6a4SAndroid Build Coastguard Worker }
1070*bb4ee6a4SAndroid Build Coastguard Worker 
1071*bb4ee6a4SAndroid Build Coastguard Worker impl PciCapMapping {
1072*bb4ee6a4SAndroid Build Coastguard Worker     /// Set the bits of register `reg_idx` specified by `mask` to `data`.
set_reg(&mut self, reg_idx: usize, data: u32, mask: u32)1073*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_reg(&mut self, reg_idx: usize, data: u32, mask: u32) {
1074*bb4ee6a4SAndroid Build Coastguard Worker         if reg_idx >= self.num_regs {
1075*bb4ee6a4SAndroid Build Coastguard Worker             error!(
1076*bb4ee6a4SAndroid Build Coastguard Worker                 "out of bounds register write {} vs {}",
1077*bb4ee6a4SAndroid Build Coastguard Worker                 self.num_regs, reg_idx
1078*bb4ee6a4SAndroid Build Coastguard Worker             );
1079*bb4ee6a4SAndroid Build Coastguard Worker             return;
1080*bb4ee6a4SAndroid Build Coastguard Worker         }
1081*bb4ee6a4SAndroid Build Coastguard Worker         let mapping = self.mapping.lock();
1082*bb4ee6a4SAndroid Build Coastguard Worker         let offset = self.offset + reg_idx * 4;
1083*bb4ee6a4SAndroid Build Coastguard Worker         let cur_value = mapping.read_obj::<u32>(offset).expect("memcpy failed");
1084*bb4ee6a4SAndroid Build Coastguard Worker         let new_val = (cur_value & !mask) | (data & mask);
1085*bb4ee6a4SAndroid Build Coastguard Worker         mapping
1086*bb4ee6a4SAndroid Build Coastguard Worker             .write_obj_volatile(new_val, offset)
1087*bb4ee6a4SAndroid Build Coastguard Worker             .expect("memcpy failed");
1088*bb4ee6a4SAndroid Build Coastguard Worker         if let Err(err) = mapping.flush_region(offset, 4) {
1089*bb4ee6a4SAndroid Build Coastguard Worker             error!(
1090*bb4ee6a4SAndroid Build Coastguard Worker                 "failed to flush write to pci cap in mmio register ({}): {}",
1091*bb4ee6a4SAndroid Build Coastguard Worker                 reg_idx, err
1092*bb4ee6a4SAndroid Build Coastguard Worker             );
1093*bb4ee6a4SAndroid Build Coastguard Worker         }
1094*bb4ee6a4SAndroid Build Coastguard Worker     }
1095*bb4ee6a4SAndroid Build Coastguard Worker }
1096*bb4ee6a4SAndroid Build Coastguard Worker 
1097*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
1098*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
1099*bb4ee6a4SAndroid Build Coastguard Worker     use zerocopy::AsBytes;
1100*bb4ee6a4SAndroid Build Coastguard Worker 
1101*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
1102*bb4ee6a4SAndroid Build Coastguard Worker 
1103*bb4ee6a4SAndroid Build Coastguard Worker     #[repr(C, packed)]
1104*bb4ee6a4SAndroid Build Coastguard Worker     #[derive(Clone, Copy, AsBytes)]
1105*bb4ee6a4SAndroid Build Coastguard Worker     #[allow(dead_code)]
1106*bb4ee6a4SAndroid Build Coastguard Worker     struct TestCap {
1107*bb4ee6a4SAndroid Build Coastguard Worker         _vndr: u8,
1108*bb4ee6a4SAndroid Build Coastguard Worker         _next: u8,
1109*bb4ee6a4SAndroid Build Coastguard Worker         len: u8,
1110*bb4ee6a4SAndroid Build Coastguard Worker         foo: u8,
1111*bb4ee6a4SAndroid Build Coastguard Worker     }
1112*bb4ee6a4SAndroid Build Coastguard Worker 
1113*bb4ee6a4SAndroid Build Coastguard Worker     impl PciCapability for TestCap {
bytes(&self) -> &[u8]1114*bb4ee6a4SAndroid Build Coastguard Worker         fn bytes(&self) -> &[u8] {
1115*bb4ee6a4SAndroid Build Coastguard Worker             self.as_bytes()
1116*bb4ee6a4SAndroid Build Coastguard Worker         }
1117*bb4ee6a4SAndroid Build Coastguard Worker 
id(&self) -> PciCapabilityID1118*bb4ee6a4SAndroid Build Coastguard Worker         fn id(&self) -> PciCapabilityID {
1119*bb4ee6a4SAndroid Build Coastguard Worker             PciCapabilityID::VendorSpecific
1120*bb4ee6a4SAndroid Build Coastguard Worker         }
1121*bb4ee6a4SAndroid Build Coastguard Worker 
writable_bits(&self) -> Vec<u32>1122*bb4ee6a4SAndroid Build Coastguard Worker         fn writable_bits(&self) -> Vec<u32> {
1123*bb4ee6a4SAndroid Build Coastguard Worker             vec![0u32; 1]
1124*bb4ee6a4SAndroid Build Coastguard Worker         }
1125*bb4ee6a4SAndroid Build Coastguard Worker     }
1126*bb4ee6a4SAndroid Build Coastguard Worker 
1127*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
add_capability()1128*bb4ee6a4SAndroid Build Coastguard Worker     fn add_capability() {
1129*bb4ee6a4SAndroid Build Coastguard Worker         let mut cfg = PciConfiguration::new(
1130*bb4ee6a4SAndroid Build Coastguard Worker             0x1234,
1131*bb4ee6a4SAndroid Build Coastguard Worker             0x5678,
1132*bb4ee6a4SAndroid Build Coastguard Worker             PciClassCode::MultimediaController,
1133*bb4ee6a4SAndroid Build Coastguard Worker             &PciMultimediaSubclass::AudioController,
1134*bb4ee6a4SAndroid Build Coastguard Worker             None,
1135*bb4ee6a4SAndroid Build Coastguard Worker             PciHeaderType::Device,
1136*bb4ee6a4SAndroid Build Coastguard Worker             0xABCD,
1137*bb4ee6a4SAndroid Build Coastguard Worker             0x2468,
1138*bb4ee6a4SAndroid Build Coastguard Worker             0,
1139*bb4ee6a4SAndroid Build Coastguard Worker         );
1140*bb4ee6a4SAndroid Build Coastguard Worker 
1141*bb4ee6a4SAndroid Build Coastguard Worker         // Add two capabilities with different contents.
1142*bb4ee6a4SAndroid Build Coastguard Worker         let cap1 = TestCap {
1143*bb4ee6a4SAndroid Build Coastguard Worker             _vndr: 0,
1144*bb4ee6a4SAndroid Build Coastguard Worker             _next: 0,
1145*bb4ee6a4SAndroid Build Coastguard Worker             len: 4,
1146*bb4ee6a4SAndroid Build Coastguard Worker             foo: 0xAA,
1147*bb4ee6a4SAndroid Build Coastguard Worker         };
1148*bb4ee6a4SAndroid Build Coastguard Worker         let cap1_offset = 64;
1149*bb4ee6a4SAndroid Build Coastguard Worker         cfg.add_capability(&cap1, None).unwrap();
1150*bb4ee6a4SAndroid Build Coastguard Worker 
1151*bb4ee6a4SAndroid Build Coastguard Worker         let cap2 = TestCap {
1152*bb4ee6a4SAndroid Build Coastguard Worker             _vndr: 0,
1153*bb4ee6a4SAndroid Build Coastguard Worker             _next: 0,
1154*bb4ee6a4SAndroid Build Coastguard Worker             len: 0x04,
1155*bb4ee6a4SAndroid Build Coastguard Worker             foo: 0x55,
1156*bb4ee6a4SAndroid Build Coastguard Worker         };
1157*bb4ee6a4SAndroid Build Coastguard Worker         let cap2_offset = 68;
1158*bb4ee6a4SAndroid Build Coastguard Worker         cfg.add_capability(&cap2, None).unwrap();
1159*bb4ee6a4SAndroid Build Coastguard Worker 
1160*bb4ee6a4SAndroid Build Coastguard Worker         // The capability list head should be pointing to cap1.
1161*bb4ee6a4SAndroid Build Coastguard Worker         let cap_ptr = cfg.read_reg(CAPABILITY_LIST_HEAD_OFFSET / 4) & 0xFF;
1162*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(cap1_offset, cap_ptr as usize);
1163*bb4ee6a4SAndroid Build Coastguard Worker 
1164*bb4ee6a4SAndroid Build Coastguard Worker         // Verify the contents of the capabilities.
1165*bb4ee6a4SAndroid Build Coastguard Worker         let cap1_data = cfg.read_reg(cap1_offset / 4);
1166*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(cap1_data & 0xFF, 0x09); // capability ID
1167*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!((cap1_data >> 8) & 0xFF, cap2_offset as u32); // next capability pointer
1168*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!((cap1_data >> 16) & 0xFF, 0x04); // cap1.len
1169*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!((cap1_data >> 24) & 0xFF, 0xAA); // cap1.foo
1170*bb4ee6a4SAndroid Build Coastguard Worker 
1171*bb4ee6a4SAndroid Build Coastguard Worker         let cap2_data = cfg.read_reg(cap2_offset / 4);
1172*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(cap2_data & 0xFF, 0x09); // capability ID
1173*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!((cap2_data >> 8) & 0xFF, 0x00); // next capability pointer
1174*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!((cap2_data >> 16) & 0xFF, 0x04); // cap2.len
1175*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!((cap2_data >> 24) & 0xFF, 0x55); // cap2.foo
1176*bb4ee6a4SAndroid Build Coastguard Worker     }
1177*bb4ee6a4SAndroid Build Coastguard Worker 
1178*bb4ee6a4SAndroid Build Coastguard Worker     #[derive(Copy, Clone)]
1179*bb4ee6a4SAndroid Build Coastguard Worker     enum TestPI {
1180*bb4ee6a4SAndroid Build Coastguard Worker         Test = 0x5a,
1181*bb4ee6a4SAndroid Build Coastguard Worker     }
1182*bb4ee6a4SAndroid Build Coastguard Worker 
1183*bb4ee6a4SAndroid Build Coastguard Worker     impl PciProgrammingInterface for TestPI {
get_register_value(&self) -> u81184*bb4ee6a4SAndroid Build Coastguard Worker         fn get_register_value(&self) -> u8 {
1185*bb4ee6a4SAndroid Build Coastguard Worker             *self as u8
1186*bb4ee6a4SAndroid Build Coastguard Worker         }
1187*bb4ee6a4SAndroid Build Coastguard Worker     }
1188*bb4ee6a4SAndroid Build Coastguard Worker 
1189*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
class_code()1190*bb4ee6a4SAndroid Build Coastguard Worker     fn class_code() {
1191*bb4ee6a4SAndroid Build Coastguard Worker         let cfg = PciConfiguration::new(
1192*bb4ee6a4SAndroid Build Coastguard Worker             0x1234,
1193*bb4ee6a4SAndroid Build Coastguard Worker             0x5678,
1194*bb4ee6a4SAndroid Build Coastguard Worker             PciClassCode::MultimediaController,
1195*bb4ee6a4SAndroid Build Coastguard Worker             &PciMultimediaSubclass::AudioController,
1196*bb4ee6a4SAndroid Build Coastguard Worker             Some(&TestPI::Test),
1197*bb4ee6a4SAndroid Build Coastguard Worker             PciHeaderType::Device,
1198*bb4ee6a4SAndroid Build Coastguard Worker             0xABCD,
1199*bb4ee6a4SAndroid Build Coastguard Worker             0x2468,
1200*bb4ee6a4SAndroid Build Coastguard Worker             0,
1201*bb4ee6a4SAndroid Build Coastguard Worker         );
1202*bb4ee6a4SAndroid Build Coastguard Worker 
1203*bb4ee6a4SAndroid Build Coastguard Worker         let class_reg = cfg.read_reg(2);
1204*bb4ee6a4SAndroid Build Coastguard Worker         let class_code = (class_reg >> 24) & 0xFF;
1205*bb4ee6a4SAndroid Build Coastguard Worker         let subclass = (class_reg >> 16) & 0xFF;
1206*bb4ee6a4SAndroid Build Coastguard Worker         let prog_if = (class_reg >> 8) & 0xFF;
1207*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(class_code, 0x04);
1208*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(subclass, 0x01);
1209*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(prog_if, 0x5a);
1210*bb4ee6a4SAndroid Build Coastguard Worker     }
1211*bb4ee6a4SAndroid Build Coastguard Worker 
1212*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
read_only_bits()1213*bb4ee6a4SAndroid Build Coastguard Worker     fn read_only_bits() {
1214*bb4ee6a4SAndroid Build Coastguard Worker         let mut cfg = PciConfiguration::new(
1215*bb4ee6a4SAndroid Build Coastguard Worker             0x1234,
1216*bb4ee6a4SAndroid Build Coastguard Worker             0x5678,
1217*bb4ee6a4SAndroid Build Coastguard Worker             PciClassCode::MultimediaController,
1218*bb4ee6a4SAndroid Build Coastguard Worker             &PciMultimediaSubclass::AudioController,
1219*bb4ee6a4SAndroid Build Coastguard Worker             Some(&TestPI::Test),
1220*bb4ee6a4SAndroid Build Coastguard Worker             PciHeaderType::Device,
1221*bb4ee6a4SAndroid Build Coastguard Worker             0xABCD,
1222*bb4ee6a4SAndroid Build Coastguard Worker             0x2468,
1223*bb4ee6a4SAndroid Build Coastguard Worker             0,
1224*bb4ee6a4SAndroid Build Coastguard Worker         );
1225*bb4ee6a4SAndroid Build Coastguard Worker 
1226*bb4ee6a4SAndroid Build Coastguard Worker         // Attempt to overwrite vendor ID and device ID, which are read-only
1227*bb4ee6a4SAndroid Build Coastguard Worker         cfg.write_reg(0, 0, &[0xBA, 0xAD, 0xF0, 0x0D]);
1228*bb4ee6a4SAndroid Build Coastguard Worker         // The original vendor and device ID should remain.
1229*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(cfg.read_reg(0), 0x56781234);
1230*bb4ee6a4SAndroid Build Coastguard Worker     }
1231*bb4ee6a4SAndroid Build Coastguard Worker 
1232*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
query_unused_bar()1233*bb4ee6a4SAndroid Build Coastguard Worker     fn query_unused_bar() {
1234*bb4ee6a4SAndroid Build Coastguard Worker         let cfg = PciConfiguration::new(
1235*bb4ee6a4SAndroid Build Coastguard Worker             0x1234,
1236*bb4ee6a4SAndroid Build Coastguard Worker             0x5678,
1237*bb4ee6a4SAndroid Build Coastguard Worker             PciClassCode::MultimediaController,
1238*bb4ee6a4SAndroid Build Coastguard Worker             &PciMultimediaSubclass::AudioController,
1239*bb4ee6a4SAndroid Build Coastguard Worker             Some(&TestPI::Test),
1240*bb4ee6a4SAndroid Build Coastguard Worker             PciHeaderType::Device,
1241*bb4ee6a4SAndroid Build Coastguard Worker             0xABCD,
1242*bb4ee6a4SAndroid Build Coastguard Worker             0x2468,
1243*bb4ee6a4SAndroid Build Coastguard Worker             0,
1244*bb4ee6a4SAndroid Build Coastguard Worker         );
1245*bb4ee6a4SAndroid Build Coastguard Worker 
1246*bb4ee6a4SAndroid Build Coastguard Worker         // No BAR 0 has been configured, so these should return None or 0 as appropriate.
1247*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(cfg.get_bar_type(0), None);
1248*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(cfg.get_bar_addr(0), 0);
1249*bb4ee6a4SAndroid Build Coastguard Worker 
1250*bb4ee6a4SAndroid Build Coastguard Worker         let mut bar_iter = cfg.get_bars();
1251*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(bar_iter.next(), None);
1252*bb4ee6a4SAndroid Build Coastguard Worker     }
1253*bb4ee6a4SAndroid Build Coastguard Worker 
1254*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
add_pci_bar_mem_64bit()1255*bb4ee6a4SAndroid Build Coastguard Worker     fn add_pci_bar_mem_64bit() {
1256*bb4ee6a4SAndroid Build Coastguard Worker         let mut cfg = PciConfiguration::new(
1257*bb4ee6a4SAndroid Build Coastguard Worker             0x1234,
1258*bb4ee6a4SAndroid Build Coastguard Worker             0x5678,
1259*bb4ee6a4SAndroid Build Coastguard Worker             PciClassCode::MultimediaController,
1260*bb4ee6a4SAndroid Build Coastguard Worker             &PciMultimediaSubclass::AudioController,
1261*bb4ee6a4SAndroid Build Coastguard Worker             Some(&TestPI::Test),
1262*bb4ee6a4SAndroid Build Coastguard Worker             PciHeaderType::Device,
1263*bb4ee6a4SAndroid Build Coastguard Worker             0xABCD,
1264*bb4ee6a4SAndroid Build Coastguard Worker             0x2468,
1265*bb4ee6a4SAndroid Build Coastguard Worker             0,
1266*bb4ee6a4SAndroid Build Coastguard Worker         );
1267*bb4ee6a4SAndroid Build Coastguard Worker 
1268*bb4ee6a4SAndroid Build Coastguard Worker         cfg.add_pci_bar(
1269*bb4ee6a4SAndroid Build Coastguard Worker             PciBarConfiguration::new(
1270*bb4ee6a4SAndroid Build Coastguard Worker                 0,
1271*bb4ee6a4SAndroid Build Coastguard Worker                 0x10,
1272*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarRegionType::Memory64BitRegion,
1273*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarPrefetchable::NotPrefetchable,
1274*bb4ee6a4SAndroid Build Coastguard Worker             )
1275*bb4ee6a4SAndroid Build Coastguard Worker             .set_address(0x0123_4567_89AB_CDE0),
1276*bb4ee6a4SAndroid Build Coastguard Worker         )
1277*bb4ee6a4SAndroid Build Coastguard Worker         .expect("add_pci_bar failed");
1278*bb4ee6a4SAndroid Build Coastguard Worker 
1279*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1280*bb4ee6a4SAndroid Build Coastguard Worker             cfg.get_bar_type(0),
1281*bb4ee6a4SAndroid Build Coastguard Worker             Some(PciBarRegionType::Memory64BitRegion)
1282*bb4ee6a4SAndroid Build Coastguard Worker         );
1283*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(cfg.get_bar_addr(0), 0x0123_4567_89AB_CDE0);
1284*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(cfg.writable_bits[BAR0_REG + 1], 0xFFFFFFFF);
1285*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(cfg.writable_bits[BAR0_REG + 0], 0xFFFFFFF0);
1286*bb4ee6a4SAndroid Build Coastguard Worker 
1287*bb4ee6a4SAndroid Build Coastguard Worker         let mut bar_iter = cfg.get_bars();
1288*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1289*bb4ee6a4SAndroid Build Coastguard Worker             bar_iter.next(),
1290*bb4ee6a4SAndroid Build Coastguard Worker             Some(PciBarConfiguration {
1291*bb4ee6a4SAndroid Build Coastguard Worker                 addr: 0x0123_4567_89AB_CDE0,
1292*bb4ee6a4SAndroid Build Coastguard Worker                 size: 0x10,
1293*bb4ee6a4SAndroid Build Coastguard Worker                 bar_idx: 0,
1294*bb4ee6a4SAndroid Build Coastguard Worker                 region_type: PciBarRegionType::Memory64BitRegion,
1295*bb4ee6a4SAndroid Build Coastguard Worker                 prefetchable: PciBarPrefetchable::NotPrefetchable
1296*bb4ee6a4SAndroid Build Coastguard Worker             })
1297*bb4ee6a4SAndroid Build Coastguard Worker         );
1298*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(bar_iter.next(), None);
1299*bb4ee6a4SAndroid Build Coastguard Worker     }
1300*bb4ee6a4SAndroid Build Coastguard Worker 
1301*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
add_pci_bar_mem_32bit()1302*bb4ee6a4SAndroid Build Coastguard Worker     fn add_pci_bar_mem_32bit() {
1303*bb4ee6a4SAndroid Build Coastguard Worker         let mut cfg = PciConfiguration::new(
1304*bb4ee6a4SAndroid Build Coastguard Worker             0x1234,
1305*bb4ee6a4SAndroid Build Coastguard Worker             0x5678,
1306*bb4ee6a4SAndroid Build Coastguard Worker             PciClassCode::MultimediaController,
1307*bb4ee6a4SAndroid Build Coastguard Worker             &PciMultimediaSubclass::AudioController,
1308*bb4ee6a4SAndroid Build Coastguard Worker             Some(&TestPI::Test),
1309*bb4ee6a4SAndroid Build Coastguard Worker             PciHeaderType::Device,
1310*bb4ee6a4SAndroid Build Coastguard Worker             0xABCD,
1311*bb4ee6a4SAndroid Build Coastguard Worker             0x2468,
1312*bb4ee6a4SAndroid Build Coastguard Worker             0,
1313*bb4ee6a4SAndroid Build Coastguard Worker         );
1314*bb4ee6a4SAndroid Build Coastguard Worker 
1315*bb4ee6a4SAndroid Build Coastguard Worker         cfg.add_pci_bar(
1316*bb4ee6a4SAndroid Build Coastguard Worker             PciBarConfiguration::new(
1317*bb4ee6a4SAndroid Build Coastguard Worker                 0,
1318*bb4ee6a4SAndroid Build Coastguard Worker                 0x10,
1319*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarRegionType::Memory32BitRegion,
1320*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarPrefetchable::NotPrefetchable,
1321*bb4ee6a4SAndroid Build Coastguard Worker             )
1322*bb4ee6a4SAndroid Build Coastguard Worker             .set_address(0x12345670),
1323*bb4ee6a4SAndroid Build Coastguard Worker         )
1324*bb4ee6a4SAndroid Build Coastguard Worker         .expect("add_pci_bar failed");
1325*bb4ee6a4SAndroid Build Coastguard Worker 
1326*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1327*bb4ee6a4SAndroid Build Coastguard Worker             cfg.get_bar_type(0),
1328*bb4ee6a4SAndroid Build Coastguard Worker             Some(PciBarRegionType::Memory32BitRegion)
1329*bb4ee6a4SAndroid Build Coastguard Worker         );
1330*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(cfg.get_bar_addr(0), 0x12345670);
1331*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(cfg.writable_bits[BAR0_REG], 0xFFFFFFF0);
1332*bb4ee6a4SAndroid Build Coastguard Worker 
1333*bb4ee6a4SAndroid Build Coastguard Worker         let mut bar_iter = cfg.get_bars();
1334*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1335*bb4ee6a4SAndroid Build Coastguard Worker             bar_iter.next(),
1336*bb4ee6a4SAndroid Build Coastguard Worker             Some(PciBarConfiguration {
1337*bb4ee6a4SAndroid Build Coastguard Worker                 addr: 0x12345670,
1338*bb4ee6a4SAndroid Build Coastguard Worker                 size: 0x10,
1339*bb4ee6a4SAndroid Build Coastguard Worker                 bar_idx: 0,
1340*bb4ee6a4SAndroid Build Coastguard Worker                 region_type: PciBarRegionType::Memory32BitRegion,
1341*bb4ee6a4SAndroid Build Coastguard Worker                 prefetchable: PciBarPrefetchable::NotPrefetchable
1342*bb4ee6a4SAndroid Build Coastguard Worker             })
1343*bb4ee6a4SAndroid Build Coastguard Worker         );
1344*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(bar_iter.next(), None);
1345*bb4ee6a4SAndroid Build Coastguard Worker     }
1346*bb4ee6a4SAndroid Build Coastguard Worker 
1347*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
add_pci_bar_io()1348*bb4ee6a4SAndroid Build Coastguard Worker     fn add_pci_bar_io() {
1349*bb4ee6a4SAndroid Build Coastguard Worker         let mut cfg = PciConfiguration::new(
1350*bb4ee6a4SAndroid Build Coastguard Worker             0x1234,
1351*bb4ee6a4SAndroid Build Coastguard Worker             0x5678,
1352*bb4ee6a4SAndroid Build Coastguard Worker             PciClassCode::MultimediaController,
1353*bb4ee6a4SAndroid Build Coastguard Worker             &PciMultimediaSubclass::AudioController,
1354*bb4ee6a4SAndroid Build Coastguard Worker             Some(&TestPI::Test),
1355*bb4ee6a4SAndroid Build Coastguard Worker             PciHeaderType::Device,
1356*bb4ee6a4SAndroid Build Coastguard Worker             0xABCD,
1357*bb4ee6a4SAndroid Build Coastguard Worker             0x2468,
1358*bb4ee6a4SAndroid Build Coastguard Worker             0,
1359*bb4ee6a4SAndroid Build Coastguard Worker         );
1360*bb4ee6a4SAndroid Build Coastguard Worker 
1361*bb4ee6a4SAndroid Build Coastguard Worker         cfg.add_pci_bar(
1362*bb4ee6a4SAndroid Build Coastguard Worker             PciBarConfiguration::new(
1363*bb4ee6a4SAndroid Build Coastguard Worker                 0,
1364*bb4ee6a4SAndroid Build Coastguard Worker                 0x4,
1365*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarRegionType::IoRegion,
1366*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarPrefetchable::NotPrefetchable,
1367*bb4ee6a4SAndroid Build Coastguard Worker             )
1368*bb4ee6a4SAndroid Build Coastguard Worker             .set_address(0x1230),
1369*bb4ee6a4SAndroid Build Coastguard Worker         )
1370*bb4ee6a4SAndroid Build Coastguard Worker         .expect("add_pci_bar failed");
1371*bb4ee6a4SAndroid Build Coastguard Worker 
1372*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(cfg.get_bar_type(0), Some(PciBarRegionType::IoRegion));
1373*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(cfg.get_bar_addr(0), 0x1230);
1374*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(cfg.writable_bits[BAR0_REG], 0xFFFFFFFC);
1375*bb4ee6a4SAndroid Build Coastguard Worker 
1376*bb4ee6a4SAndroid Build Coastguard Worker         let mut bar_iter = cfg.get_bars();
1377*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1378*bb4ee6a4SAndroid Build Coastguard Worker             bar_iter.next(),
1379*bb4ee6a4SAndroid Build Coastguard Worker             Some(PciBarConfiguration {
1380*bb4ee6a4SAndroid Build Coastguard Worker                 addr: 0x1230,
1381*bb4ee6a4SAndroid Build Coastguard Worker                 size: 0x4,
1382*bb4ee6a4SAndroid Build Coastguard Worker                 bar_idx: 0,
1383*bb4ee6a4SAndroid Build Coastguard Worker                 region_type: PciBarRegionType::IoRegion,
1384*bb4ee6a4SAndroid Build Coastguard Worker                 prefetchable: PciBarPrefetchable::NotPrefetchable
1385*bb4ee6a4SAndroid Build Coastguard Worker             })
1386*bb4ee6a4SAndroid Build Coastguard Worker         );
1387*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(bar_iter.next(), None);
1388*bb4ee6a4SAndroid Build Coastguard Worker     }
1389*bb4ee6a4SAndroid Build Coastguard Worker 
1390*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
add_pci_bar_multiple()1391*bb4ee6a4SAndroid Build Coastguard Worker     fn add_pci_bar_multiple() {
1392*bb4ee6a4SAndroid Build Coastguard Worker         let mut cfg = PciConfiguration::new(
1393*bb4ee6a4SAndroid Build Coastguard Worker             0x1234,
1394*bb4ee6a4SAndroid Build Coastguard Worker             0x5678,
1395*bb4ee6a4SAndroid Build Coastguard Worker             PciClassCode::MultimediaController,
1396*bb4ee6a4SAndroid Build Coastguard Worker             &PciMultimediaSubclass::AudioController,
1397*bb4ee6a4SAndroid Build Coastguard Worker             Some(&TestPI::Test),
1398*bb4ee6a4SAndroid Build Coastguard Worker             PciHeaderType::Device,
1399*bb4ee6a4SAndroid Build Coastguard Worker             0xABCD,
1400*bb4ee6a4SAndroid Build Coastguard Worker             0x2468,
1401*bb4ee6a4SAndroid Build Coastguard Worker             0,
1402*bb4ee6a4SAndroid Build Coastguard Worker         );
1403*bb4ee6a4SAndroid Build Coastguard Worker 
1404*bb4ee6a4SAndroid Build Coastguard Worker         // bar_num 0-1: 64-bit memory
1405*bb4ee6a4SAndroid Build Coastguard Worker         cfg.add_pci_bar(
1406*bb4ee6a4SAndroid Build Coastguard Worker             PciBarConfiguration::new(
1407*bb4ee6a4SAndroid Build Coastguard Worker                 0,
1408*bb4ee6a4SAndroid Build Coastguard Worker                 0x10,
1409*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarRegionType::Memory64BitRegion,
1410*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarPrefetchable::NotPrefetchable,
1411*bb4ee6a4SAndroid Build Coastguard Worker             )
1412*bb4ee6a4SAndroid Build Coastguard Worker             .set_address(0x0123_4567_89AB_CDE0),
1413*bb4ee6a4SAndroid Build Coastguard Worker         )
1414*bb4ee6a4SAndroid Build Coastguard Worker         .expect("add_pci_bar failed");
1415*bb4ee6a4SAndroid Build Coastguard Worker 
1416*bb4ee6a4SAndroid Build Coastguard Worker         // bar 2: 32-bit memory
1417*bb4ee6a4SAndroid Build Coastguard Worker         cfg.add_pci_bar(
1418*bb4ee6a4SAndroid Build Coastguard Worker             PciBarConfiguration::new(
1419*bb4ee6a4SAndroid Build Coastguard Worker                 2,
1420*bb4ee6a4SAndroid Build Coastguard Worker                 0x10,
1421*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarRegionType::Memory32BitRegion,
1422*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarPrefetchable::NotPrefetchable,
1423*bb4ee6a4SAndroid Build Coastguard Worker             )
1424*bb4ee6a4SAndroid Build Coastguard Worker             .set_address(0x12345670),
1425*bb4ee6a4SAndroid Build Coastguard Worker         )
1426*bb4ee6a4SAndroid Build Coastguard Worker         .expect("add_pci_bar failed");
1427*bb4ee6a4SAndroid Build Coastguard Worker 
1428*bb4ee6a4SAndroid Build Coastguard Worker         // bar 3: I/O
1429*bb4ee6a4SAndroid Build Coastguard Worker         cfg.add_pci_bar(
1430*bb4ee6a4SAndroid Build Coastguard Worker             PciBarConfiguration::new(
1431*bb4ee6a4SAndroid Build Coastguard Worker                 3,
1432*bb4ee6a4SAndroid Build Coastguard Worker                 0x4,
1433*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarRegionType::IoRegion,
1434*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarPrefetchable::NotPrefetchable,
1435*bb4ee6a4SAndroid Build Coastguard Worker             )
1436*bb4ee6a4SAndroid Build Coastguard Worker             .set_address(0x1230),
1437*bb4ee6a4SAndroid Build Coastguard Worker         )
1438*bb4ee6a4SAndroid Build Coastguard Worker         .expect("add_pci_bar failed");
1439*bb4ee6a4SAndroid Build Coastguard Worker 
1440*bb4ee6a4SAndroid Build Coastguard Worker         // Confirm default memory and I/O region configurations.
1441*bb4ee6a4SAndroid Build Coastguard Worker         let mut bar_iter = cfg.get_bars();
1442*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1443*bb4ee6a4SAndroid Build Coastguard Worker             bar_iter.next(),
1444*bb4ee6a4SAndroid Build Coastguard Worker             Some(PciBarConfiguration {
1445*bb4ee6a4SAndroid Build Coastguard Worker                 addr: 0x0123_4567_89AB_CDE0,
1446*bb4ee6a4SAndroid Build Coastguard Worker                 size: 0x10,
1447*bb4ee6a4SAndroid Build Coastguard Worker                 bar_idx: 0,
1448*bb4ee6a4SAndroid Build Coastguard Worker                 region_type: PciBarRegionType::Memory64BitRegion,
1449*bb4ee6a4SAndroid Build Coastguard Worker                 prefetchable: PciBarPrefetchable::NotPrefetchable
1450*bb4ee6a4SAndroid Build Coastguard Worker             })
1451*bb4ee6a4SAndroid Build Coastguard Worker         );
1452*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1453*bb4ee6a4SAndroid Build Coastguard Worker             bar_iter.next(),
1454*bb4ee6a4SAndroid Build Coastguard Worker             Some(PciBarConfiguration {
1455*bb4ee6a4SAndroid Build Coastguard Worker                 addr: 0x12345670,
1456*bb4ee6a4SAndroid Build Coastguard Worker                 size: 0x10,
1457*bb4ee6a4SAndroid Build Coastguard Worker                 bar_idx: 2,
1458*bb4ee6a4SAndroid Build Coastguard Worker                 region_type: PciBarRegionType::Memory32BitRegion,
1459*bb4ee6a4SAndroid Build Coastguard Worker                 prefetchable: PciBarPrefetchable::NotPrefetchable
1460*bb4ee6a4SAndroid Build Coastguard Worker             })
1461*bb4ee6a4SAndroid Build Coastguard Worker         );
1462*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1463*bb4ee6a4SAndroid Build Coastguard Worker             bar_iter.next(),
1464*bb4ee6a4SAndroid Build Coastguard Worker             Some(PciBarConfiguration {
1465*bb4ee6a4SAndroid Build Coastguard Worker                 addr: 0x1230,
1466*bb4ee6a4SAndroid Build Coastguard Worker                 size: 0x4,
1467*bb4ee6a4SAndroid Build Coastguard Worker                 bar_idx: 3,
1468*bb4ee6a4SAndroid Build Coastguard Worker                 region_type: PciBarRegionType::IoRegion,
1469*bb4ee6a4SAndroid Build Coastguard Worker                 prefetchable: PciBarPrefetchable::NotPrefetchable
1470*bb4ee6a4SAndroid Build Coastguard Worker             })
1471*bb4ee6a4SAndroid Build Coastguard Worker         );
1472*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(bar_iter.next(), None);
1473*bb4ee6a4SAndroid Build Coastguard Worker 
1474*bb4ee6a4SAndroid Build Coastguard Worker         // Reassign the address for BAR 0 and verify that get_memory_regions() matches.
1475*bb4ee6a4SAndroid Build Coastguard Worker         cfg.write_reg(4 + 0, 0, &0xBBAA9980u32.to_le_bytes());
1476*bb4ee6a4SAndroid Build Coastguard Worker         cfg.write_reg(4 + 1, 0, &0xFFEEDDCCu32.to_le_bytes());
1477*bb4ee6a4SAndroid Build Coastguard Worker 
1478*bb4ee6a4SAndroid Build Coastguard Worker         let mut bar_iter = cfg.get_bars();
1479*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1480*bb4ee6a4SAndroid Build Coastguard Worker             bar_iter.next(),
1481*bb4ee6a4SAndroid Build Coastguard Worker             Some(PciBarConfiguration {
1482*bb4ee6a4SAndroid Build Coastguard Worker                 addr: 0xFFEE_DDCC_BBAA_9980,
1483*bb4ee6a4SAndroid Build Coastguard Worker                 size: 0x10,
1484*bb4ee6a4SAndroid Build Coastguard Worker                 bar_idx: 0,
1485*bb4ee6a4SAndroid Build Coastguard Worker                 region_type: PciBarRegionType::Memory64BitRegion,
1486*bb4ee6a4SAndroid Build Coastguard Worker                 prefetchable: PciBarPrefetchable::NotPrefetchable
1487*bb4ee6a4SAndroid Build Coastguard Worker             })
1488*bb4ee6a4SAndroid Build Coastguard Worker         );
1489*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1490*bb4ee6a4SAndroid Build Coastguard Worker             bar_iter.next(),
1491*bb4ee6a4SAndroid Build Coastguard Worker             Some(PciBarConfiguration {
1492*bb4ee6a4SAndroid Build Coastguard Worker                 addr: 0x12345670,
1493*bb4ee6a4SAndroid Build Coastguard Worker                 size: 0x10,
1494*bb4ee6a4SAndroid Build Coastguard Worker                 bar_idx: 2,
1495*bb4ee6a4SAndroid Build Coastguard Worker                 region_type: PciBarRegionType::Memory32BitRegion,
1496*bb4ee6a4SAndroid Build Coastguard Worker                 prefetchable: PciBarPrefetchable::NotPrefetchable
1497*bb4ee6a4SAndroid Build Coastguard Worker             })
1498*bb4ee6a4SAndroid Build Coastguard Worker         );
1499*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1500*bb4ee6a4SAndroid Build Coastguard Worker             bar_iter.next(),
1501*bb4ee6a4SAndroid Build Coastguard Worker             Some(PciBarConfiguration {
1502*bb4ee6a4SAndroid Build Coastguard Worker                 addr: 0x1230,
1503*bb4ee6a4SAndroid Build Coastguard Worker                 size: 0x4,
1504*bb4ee6a4SAndroid Build Coastguard Worker                 bar_idx: 3,
1505*bb4ee6a4SAndroid Build Coastguard Worker                 region_type: PciBarRegionType::IoRegion,
1506*bb4ee6a4SAndroid Build Coastguard Worker                 prefetchable: PciBarPrefetchable::NotPrefetchable
1507*bb4ee6a4SAndroid Build Coastguard Worker             })
1508*bb4ee6a4SAndroid Build Coastguard Worker         );
1509*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(bar_iter.next(), None);
1510*bb4ee6a4SAndroid Build Coastguard Worker     }
1511*bb4ee6a4SAndroid Build Coastguard Worker 
1512*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
add_pci_bar_invalid_size()1513*bb4ee6a4SAndroid Build Coastguard Worker     fn add_pci_bar_invalid_size() {
1514*bb4ee6a4SAndroid Build Coastguard Worker         let mut cfg = PciConfiguration::new(
1515*bb4ee6a4SAndroid Build Coastguard Worker             0x1234,
1516*bb4ee6a4SAndroid Build Coastguard Worker             0x5678,
1517*bb4ee6a4SAndroid Build Coastguard Worker             PciClassCode::MultimediaController,
1518*bb4ee6a4SAndroid Build Coastguard Worker             &PciMultimediaSubclass::AudioController,
1519*bb4ee6a4SAndroid Build Coastguard Worker             Some(&TestPI::Test),
1520*bb4ee6a4SAndroid Build Coastguard Worker             PciHeaderType::Device,
1521*bb4ee6a4SAndroid Build Coastguard Worker             0xABCD,
1522*bb4ee6a4SAndroid Build Coastguard Worker             0x2468,
1523*bb4ee6a4SAndroid Build Coastguard Worker             0,
1524*bb4ee6a4SAndroid Build Coastguard Worker         );
1525*bb4ee6a4SAndroid Build Coastguard Worker 
1526*bb4ee6a4SAndroid Build Coastguard Worker         // I/O BAR with size 2 (too small)
1527*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1528*bb4ee6a4SAndroid Build Coastguard Worker             cfg.add_pci_bar(
1529*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarConfiguration::new(
1530*bb4ee6a4SAndroid Build Coastguard Worker                     0,
1531*bb4ee6a4SAndroid Build Coastguard Worker                     0x2,
1532*bb4ee6a4SAndroid Build Coastguard Worker                     PciBarRegionType::IoRegion,
1533*bb4ee6a4SAndroid Build Coastguard Worker                     PciBarPrefetchable::NotPrefetchable,
1534*bb4ee6a4SAndroid Build Coastguard Worker                 )
1535*bb4ee6a4SAndroid Build Coastguard Worker                 .set_address(0x1230),
1536*bb4ee6a4SAndroid Build Coastguard Worker             ),
1537*bb4ee6a4SAndroid Build Coastguard Worker             Err(Error::BarSizeInvalid(0x2))
1538*bb4ee6a4SAndroid Build Coastguard Worker         );
1539*bb4ee6a4SAndroid Build Coastguard Worker 
1540*bb4ee6a4SAndroid Build Coastguard Worker         // I/O BAR with size 3 (not a power of 2)
1541*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1542*bb4ee6a4SAndroid Build Coastguard Worker             cfg.add_pci_bar(
1543*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarConfiguration::new(
1544*bb4ee6a4SAndroid Build Coastguard Worker                     0,
1545*bb4ee6a4SAndroid Build Coastguard Worker                     0x3,
1546*bb4ee6a4SAndroid Build Coastguard Worker                     PciBarRegionType::IoRegion,
1547*bb4ee6a4SAndroid Build Coastguard Worker                     PciBarPrefetchable::NotPrefetchable,
1548*bb4ee6a4SAndroid Build Coastguard Worker                 )
1549*bb4ee6a4SAndroid Build Coastguard Worker                 .set_address(0x1230),
1550*bb4ee6a4SAndroid Build Coastguard Worker             ),
1551*bb4ee6a4SAndroid Build Coastguard Worker             Err(Error::BarSizeInvalid(0x3))
1552*bb4ee6a4SAndroid Build Coastguard Worker         );
1553*bb4ee6a4SAndroid Build Coastguard Worker 
1554*bb4ee6a4SAndroid Build Coastguard Worker         // Memory BAR with size 8 (too small)
1555*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1556*bb4ee6a4SAndroid Build Coastguard Worker             cfg.add_pci_bar(
1557*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarConfiguration::new(
1558*bb4ee6a4SAndroid Build Coastguard Worker                     0,
1559*bb4ee6a4SAndroid Build Coastguard Worker                     0x8,
1560*bb4ee6a4SAndroid Build Coastguard Worker                     PciBarRegionType::Memory32BitRegion,
1561*bb4ee6a4SAndroid Build Coastguard Worker                     PciBarPrefetchable::NotPrefetchable,
1562*bb4ee6a4SAndroid Build Coastguard Worker                 )
1563*bb4ee6a4SAndroid Build Coastguard Worker                 .set_address(0x12345670),
1564*bb4ee6a4SAndroid Build Coastguard Worker             ),
1565*bb4ee6a4SAndroid Build Coastguard Worker             Err(Error::BarSizeInvalid(0x8))
1566*bb4ee6a4SAndroid Build Coastguard Worker         );
1567*bb4ee6a4SAndroid Build Coastguard Worker     }
1568*bb4ee6a4SAndroid Build Coastguard Worker 
1569*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
add_rom_bar()1570*bb4ee6a4SAndroid Build Coastguard Worker     fn add_rom_bar() {
1571*bb4ee6a4SAndroid Build Coastguard Worker         let mut cfg = PciConfiguration::new(
1572*bb4ee6a4SAndroid Build Coastguard Worker             0x1234,
1573*bb4ee6a4SAndroid Build Coastguard Worker             0x5678,
1574*bb4ee6a4SAndroid Build Coastguard Worker             PciClassCode::MultimediaController,
1575*bb4ee6a4SAndroid Build Coastguard Worker             &PciMultimediaSubclass::AudioController,
1576*bb4ee6a4SAndroid Build Coastguard Worker             Some(&TestPI::Test),
1577*bb4ee6a4SAndroid Build Coastguard Worker             PciHeaderType::Device,
1578*bb4ee6a4SAndroid Build Coastguard Worker             0xABCD,
1579*bb4ee6a4SAndroid Build Coastguard Worker             0x2468,
1580*bb4ee6a4SAndroid Build Coastguard Worker             0,
1581*bb4ee6a4SAndroid Build Coastguard Worker         );
1582*bb4ee6a4SAndroid Build Coastguard Worker 
1583*bb4ee6a4SAndroid Build Coastguard Worker         // Attempt to add a 64-bit memory BAR as the expansion ROM (invalid).
1584*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1585*bb4ee6a4SAndroid Build Coastguard Worker             cfg.add_pci_bar(PciBarConfiguration::new(
1586*bb4ee6a4SAndroid Build Coastguard Worker                 ROM_BAR_IDX,
1587*bb4ee6a4SAndroid Build Coastguard Worker                 0x1000,
1588*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarRegionType::Memory64BitRegion,
1589*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarPrefetchable::NotPrefetchable,
1590*bb4ee6a4SAndroid Build Coastguard Worker             ),),
1591*bb4ee6a4SAndroid Build Coastguard Worker             Err(Error::BarInvalidRomType)
1592*bb4ee6a4SAndroid Build Coastguard Worker         );
1593*bb4ee6a4SAndroid Build Coastguard Worker 
1594*bb4ee6a4SAndroid Build Coastguard Worker         // Attempt to add an I/O BAR as the expansion ROM (invalid).
1595*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1596*bb4ee6a4SAndroid Build Coastguard Worker             cfg.add_pci_bar(PciBarConfiguration::new(
1597*bb4ee6a4SAndroid Build Coastguard Worker                 ROM_BAR_IDX,
1598*bb4ee6a4SAndroid Build Coastguard Worker                 0x1000,
1599*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarRegionType::IoRegion,
1600*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarPrefetchable::NotPrefetchable,
1601*bb4ee6a4SAndroid Build Coastguard Worker             ),),
1602*bb4ee6a4SAndroid Build Coastguard Worker             Err(Error::BarInvalidRomType)
1603*bb4ee6a4SAndroid Build Coastguard Worker         );
1604*bb4ee6a4SAndroid Build Coastguard Worker 
1605*bb4ee6a4SAndroid Build Coastguard Worker         // Attempt to add a 1KB memory region as the expansion ROM (too small).
1606*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1607*bb4ee6a4SAndroid Build Coastguard Worker             cfg.add_pci_bar(PciBarConfiguration::new(
1608*bb4ee6a4SAndroid Build Coastguard Worker                 ROM_BAR_IDX,
1609*bb4ee6a4SAndroid Build Coastguard Worker                 1024,
1610*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarRegionType::Memory32BitRegion,
1611*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarPrefetchable::NotPrefetchable,
1612*bb4ee6a4SAndroid Build Coastguard Worker             ),),
1613*bb4ee6a4SAndroid Build Coastguard Worker             Err(Error::BarSizeInvalid(1024))
1614*bb4ee6a4SAndroid Build Coastguard Worker         );
1615*bb4ee6a4SAndroid Build Coastguard Worker 
1616*bb4ee6a4SAndroid Build Coastguard Worker         // Add a 32-bit memory BAR as the expansion ROM (valid).
1617*bb4ee6a4SAndroid Build Coastguard Worker         cfg.add_pci_bar(
1618*bb4ee6a4SAndroid Build Coastguard Worker             PciBarConfiguration::new(
1619*bb4ee6a4SAndroid Build Coastguard Worker                 ROM_BAR_IDX,
1620*bb4ee6a4SAndroid Build Coastguard Worker                 0x800,
1621*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarRegionType::Memory32BitRegion,
1622*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarPrefetchable::NotPrefetchable,
1623*bb4ee6a4SAndroid Build Coastguard Worker             )
1624*bb4ee6a4SAndroid Build Coastguard Worker             .set_address(0x12345000),
1625*bb4ee6a4SAndroid Build Coastguard Worker         )
1626*bb4ee6a4SAndroid Build Coastguard Worker         .expect("add_pci_bar failed");
1627*bb4ee6a4SAndroid Build Coastguard Worker 
1628*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1629*bb4ee6a4SAndroid Build Coastguard Worker             cfg.get_bar_type(ROM_BAR_IDX),
1630*bb4ee6a4SAndroid Build Coastguard Worker             Some(PciBarRegionType::Memory32BitRegion)
1631*bb4ee6a4SAndroid Build Coastguard Worker         );
1632*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(cfg.get_bar_addr(ROM_BAR_IDX), 0x12345000);
1633*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(cfg.read_reg(ROM_BAR_REG), 0x12345000);
1634*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(cfg.writable_bits[ROM_BAR_REG], 0xFFFFF801);
1635*bb4ee6a4SAndroid Build Coastguard Worker     }
1636*bb4ee6a4SAndroid Build Coastguard Worker 
1637*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
pci_configuration_capability_snapshot_restore() -> anyhow::Result<()>1638*bb4ee6a4SAndroid Build Coastguard Worker     fn pci_configuration_capability_snapshot_restore() -> anyhow::Result<()> {
1639*bb4ee6a4SAndroid Build Coastguard Worker         let mut cfg = PciConfiguration::new(
1640*bb4ee6a4SAndroid Build Coastguard Worker             0x1234,
1641*bb4ee6a4SAndroid Build Coastguard Worker             0x5678,
1642*bb4ee6a4SAndroid Build Coastguard Worker             PciClassCode::MultimediaController,
1643*bb4ee6a4SAndroid Build Coastguard Worker             &PciMultimediaSubclass::AudioController,
1644*bb4ee6a4SAndroid Build Coastguard Worker             Some(&TestPI::Test),
1645*bb4ee6a4SAndroid Build Coastguard Worker             PciHeaderType::Device,
1646*bb4ee6a4SAndroid Build Coastguard Worker             0xABCD,
1647*bb4ee6a4SAndroid Build Coastguard Worker             0x2468,
1648*bb4ee6a4SAndroid Build Coastguard Worker             0,
1649*bb4ee6a4SAndroid Build Coastguard Worker         );
1650*bb4ee6a4SAndroid Build Coastguard Worker 
1651*bb4ee6a4SAndroid Build Coastguard Worker         let snap_init = cfg.snapshot().context("failed to snapshot")?;
1652*bb4ee6a4SAndroid Build Coastguard Worker 
1653*bb4ee6a4SAndroid Build Coastguard Worker         // Add a capability.
1654*bb4ee6a4SAndroid Build Coastguard Worker         let cap1 = TestCap {
1655*bb4ee6a4SAndroid Build Coastguard Worker             _vndr: 0,
1656*bb4ee6a4SAndroid Build Coastguard Worker             _next: 0,
1657*bb4ee6a4SAndroid Build Coastguard Worker             len: 4,
1658*bb4ee6a4SAndroid Build Coastguard Worker             foo: 0xAA,
1659*bb4ee6a4SAndroid Build Coastguard Worker         };
1660*bb4ee6a4SAndroid Build Coastguard Worker         cfg.add_capability(&cap1, None).unwrap();
1661*bb4ee6a4SAndroid Build Coastguard Worker 
1662*bb4ee6a4SAndroid Build Coastguard Worker         let snap_mod = cfg.snapshot().context("failed to snapshot mod")?;
1663*bb4ee6a4SAndroid Build Coastguard Worker         cfg.restore(snap_init.clone())
1664*bb4ee6a4SAndroid Build Coastguard Worker             .context("failed to restore snap_init")?;
1665*bb4ee6a4SAndroid Build Coastguard Worker         let snap_restore_init = cfg.snapshot().context("failed to snapshot restored_init")?;
1666*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(snap_init, snap_restore_init);
1667*bb4ee6a4SAndroid Build Coastguard Worker         assert_ne!(snap_init, snap_mod);
1668*bb4ee6a4SAndroid Build Coastguard Worker         cfg.restore(snap_mod.clone())
1669*bb4ee6a4SAndroid Build Coastguard Worker             .context("failed to restore snap_init")?;
1670*bb4ee6a4SAndroid Build Coastguard Worker         let snap_restore_mod = cfg.snapshot().context("failed to snapshot restored_mod")?;
1671*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(snap_mod, snap_restore_mod);
1672*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
1673*bb4ee6a4SAndroid Build Coastguard Worker     }
1674*bb4ee6a4SAndroid Build Coastguard Worker 
1675*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
pci_configuration_pci_bar_snapshot_restore() -> anyhow::Result<()>1676*bb4ee6a4SAndroid Build Coastguard Worker     fn pci_configuration_pci_bar_snapshot_restore() -> anyhow::Result<()> {
1677*bb4ee6a4SAndroid Build Coastguard Worker         let mut cfg = PciConfiguration::new(
1678*bb4ee6a4SAndroid Build Coastguard Worker             0x1234,
1679*bb4ee6a4SAndroid Build Coastguard Worker             0x5678,
1680*bb4ee6a4SAndroid Build Coastguard Worker             PciClassCode::MultimediaController,
1681*bb4ee6a4SAndroid Build Coastguard Worker             &PciMultimediaSubclass::AudioController,
1682*bb4ee6a4SAndroid Build Coastguard Worker             Some(&TestPI::Test),
1683*bb4ee6a4SAndroid Build Coastguard Worker             PciHeaderType::Device,
1684*bb4ee6a4SAndroid Build Coastguard Worker             0xABCD,
1685*bb4ee6a4SAndroid Build Coastguard Worker             0x2468,
1686*bb4ee6a4SAndroid Build Coastguard Worker             0,
1687*bb4ee6a4SAndroid Build Coastguard Worker         );
1688*bb4ee6a4SAndroid Build Coastguard Worker 
1689*bb4ee6a4SAndroid Build Coastguard Worker         let snap_init = cfg.snapshot().context("failed to snapshot")?;
1690*bb4ee6a4SAndroid Build Coastguard Worker 
1691*bb4ee6a4SAndroid Build Coastguard Worker         // bar_num 0-1: 64-bit memory
1692*bb4ee6a4SAndroid Build Coastguard Worker         cfg.add_pci_bar(
1693*bb4ee6a4SAndroid Build Coastguard Worker             PciBarConfiguration::new(
1694*bb4ee6a4SAndroid Build Coastguard Worker                 0,
1695*bb4ee6a4SAndroid Build Coastguard Worker                 0x10,
1696*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarRegionType::Memory64BitRegion,
1697*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarPrefetchable::NotPrefetchable,
1698*bb4ee6a4SAndroid Build Coastguard Worker             )
1699*bb4ee6a4SAndroid Build Coastguard Worker             .set_address(0x0123_4567_89AB_CDE0),
1700*bb4ee6a4SAndroid Build Coastguard Worker         )
1701*bb4ee6a4SAndroid Build Coastguard Worker         .expect("add_pci_bar failed");
1702*bb4ee6a4SAndroid Build Coastguard Worker 
1703*bb4ee6a4SAndroid Build Coastguard Worker         let snap_mod = cfg.snapshot().context("failed to snapshot mod")?;
1704*bb4ee6a4SAndroid Build Coastguard Worker         cfg.restore(snap_init.clone())
1705*bb4ee6a4SAndroid Build Coastguard Worker             .context("failed to restore snap_init")?;
1706*bb4ee6a4SAndroid Build Coastguard Worker         let snap_restore_init = cfg.snapshot().context("failed to snapshot restored_init")?;
1707*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(snap_init, snap_restore_init);
1708*bb4ee6a4SAndroid Build Coastguard Worker         assert_ne!(snap_init, snap_mod);
1709*bb4ee6a4SAndroid Build Coastguard Worker         cfg.restore(snap_mod.clone())
1710*bb4ee6a4SAndroid Build Coastguard Worker             .context("failed to restore snap_init")?;
1711*bb4ee6a4SAndroid Build Coastguard Worker         let snap_restore_mod = cfg.snapshot().context("failed to snapshot restored_mod")?;
1712*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(snap_mod, snap_restore_mod);
1713*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
1714*bb4ee6a4SAndroid Build Coastguard Worker     }
1715*bb4ee6a4SAndroid Build Coastguard Worker 
1716*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
pci_configuration_capability_pci_bar_snapshot_restore() -> anyhow::Result<()>1717*bb4ee6a4SAndroid Build Coastguard Worker     fn pci_configuration_capability_pci_bar_snapshot_restore() -> anyhow::Result<()> {
1718*bb4ee6a4SAndroid Build Coastguard Worker         let mut cfg = PciConfiguration::new(
1719*bb4ee6a4SAndroid Build Coastguard Worker             0x1234,
1720*bb4ee6a4SAndroid Build Coastguard Worker             0x5678,
1721*bb4ee6a4SAndroid Build Coastguard Worker             PciClassCode::MultimediaController,
1722*bb4ee6a4SAndroid Build Coastguard Worker             &PciMultimediaSubclass::AudioController,
1723*bb4ee6a4SAndroid Build Coastguard Worker             Some(&TestPI::Test),
1724*bb4ee6a4SAndroid Build Coastguard Worker             PciHeaderType::Device,
1725*bb4ee6a4SAndroid Build Coastguard Worker             0xABCD,
1726*bb4ee6a4SAndroid Build Coastguard Worker             0x2468,
1727*bb4ee6a4SAndroid Build Coastguard Worker             0,
1728*bb4ee6a4SAndroid Build Coastguard Worker         );
1729*bb4ee6a4SAndroid Build Coastguard Worker 
1730*bb4ee6a4SAndroid Build Coastguard Worker         let snap_init = cfg.snapshot().context("failed to snapshot")?;
1731*bb4ee6a4SAndroid Build Coastguard Worker 
1732*bb4ee6a4SAndroid Build Coastguard Worker         // Add a capability.
1733*bb4ee6a4SAndroid Build Coastguard Worker         let cap1 = TestCap {
1734*bb4ee6a4SAndroid Build Coastguard Worker             _vndr: 0,
1735*bb4ee6a4SAndroid Build Coastguard Worker             _next: 0,
1736*bb4ee6a4SAndroid Build Coastguard Worker             len: 4,
1737*bb4ee6a4SAndroid Build Coastguard Worker             foo: 0xAA,
1738*bb4ee6a4SAndroid Build Coastguard Worker         };
1739*bb4ee6a4SAndroid Build Coastguard Worker         cfg.add_capability(&cap1, None).unwrap();
1740*bb4ee6a4SAndroid Build Coastguard Worker 
1741*bb4ee6a4SAndroid Build Coastguard Worker         // bar_num 0-1: 64-bit memory
1742*bb4ee6a4SAndroid Build Coastguard Worker         cfg.add_pci_bar(
1743*bb4ee6a4SAndroid Build Coastguard Worker             PciBarConfiguration::new(
1744*bb4ee6a4SAndroid Build Coastguard Worker                 0,
1745*bb4ee6a4SAndroid Build Coastguard Worker                 0x10,
1746*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarRegionType::Memory64BitRegion,
1747*bb4ee6a4SAndroid Build Coastguard Worker                 PciBarPrefetchable::NotPrefetchable,
1748*bb4ee6a4SAndroid Build Coastguard Worker             )
1749*bb4ee6a4SAndroid Build Coastguard Worker             .set_address(0x0123_4567_89AB_CDE0),
1750*bb4ee6a4SAndroid Build Coastguard Worker         )
1751*bb4ee6a4SAndroid Build Coastguard Worker         .expect("add_pci_bar failed");
1752*bb4ee6a4SAndroid Build Coastguard Worker 
1753*bb4ee6a4SAndroid Build Coastguard Worker         let snap_mod = cfg.snapshot().context("failed to snapshot mod")?;
1754*bb4ee6a4SAndroid Build Coastguard Worker         cfg.restore(snap_init.clone())
1755*bb4ee6a4SAndroid Build Coastguard Worker             .context("failed to restore snap_init")?;
1756*bb4ee6a4SAndroid Build Coastguard Worker         let snap_restore_init = cfg.snapshot().context("failed to snapshot restored_init")?;
1757*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(snap_init, snap_restore_init);
1758*bb4ee6a4SAndroid Build Coastguard Worker         assert_ne!(snap_init, snap_mod);
1759*bb4ee6a4SAndroid Build Coastguard Worker         cfg.restore(snap_mod.clone())
1760*bb4ee6a4SAndroid Build Coastguard Worker             .context("failed to restore snap_init")?;
1761*bb4ee6a4SAndroid Build Coastguard Worker         let snap_restore_mod = cfg.snapshot().context("failed to snapshot restored_mod")?;
1762*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(snap_mod, snap_restore_mod);
1763*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
1764*bb4ee6a4SAndroid Build Coastguard Worker     }
1765*bb4ee6a4SAndroid Build Coastguard Worker }
1766