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