mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-06 02:25:23 +00:00
devices: pci: add Programming Interface to device
PCI class codes are made up of three fields: class, subclass, and programming interface. Some class/subclass combinations do not define any programming interfaces, so add an optional parameter to specify the value and use 0 if it is not provided. Change-Id: Ib4000eafe2d7d003ed5753d7b0ea05e16fd06130 Signed-off-by: Daniel Verkamp <dverkamp@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1237358 Reviewed-by: Dylan Reid <dgreid@chromium.org>
This commit is contained in:
parent
0f579cb09c
commit
4f228cb203
3 changed files with 53 additions and 2 deletions
|
@ -8,7 +8,7 @@ mod pci_configuration;
|
|||
mod pci_device;
|
||||
mod pci_root;
|
||||
|
||||
pub use self::pci_configuration::{PciCapability, PciCapabilityID, PciClassCode, PciConfiguration, PciHeaderType, PciSubclass};
|
||||
pub use self::pci_configuration::{PciCapability, PciCapabilityID, PciClassCode, PciConfiguration, PciHeaderType, PciProgrammingInterface, PciSubclass};
|
||||
pub use self::pci_device::Error as PciDeviceError;
|
||||
pub use self::pci_device::PciDevice;
|
||||
pub use self::pci_root::PciRoot;
|
||||
|
|
|
@ -121,6 +121,15 @@ impl PciSubclass for PciSerialBusSubClass {
|
|||
}
|
||||
}
|
||||
|
||||
/// A PCI class programming interface. Each combination of `PciClassCode` and
|
||||
/// `PciSubclass` can specify a set of register-level programming interfaces.
|
||||
/// This trait is implemented by each programming interface.
|
||||
/// It allows use of a trait object to generate configurations.
|
||||
pub trait PciProgrammingInterface {
|
||||
/// Convert this programming interface to the value used in the PCI specification.
|
||||
fn get_register_value(&self) -> u8;
|
||||
}
|
||||
|
||||
/// Types of PCI capabilities.
|
||||
pub enum PciCapabilityID {
|
||||
ListID = 0,
|
||||
|
@ -169,14 +178,21 @@ impl PciConfiguration {
|
|||
device_id: u16,
|
||||
class_code: PciClassCode,
|
||||
subclass: &PciSubclass,
|
||||
programming_interface: Option<&PciProgrammingInterface>,
|
||||
header_type: PciHeaderType,
|
||||
subsystem_vendor_id: u16,
|
||||
subsystem_id: u16,
|
||||
) -> Self {
|
||||
let mut registers = [0u32; NUM_CONFIGURATION_REGISTERS];
|
||||
registers[0] = u32::from(device_id) << 16 | u32::from(vendor_id);
|
||||
let pi = if let Some(pi) = programming_interface {
|
||||
pi.get_register_value()
|
||||
} else {
|
||||
0
|
||||
};
|
||||
registers[2] = u32::from(class_code.get_register_value()) << 24
|
||||
| u32::from(subclass.get_register_value()) << 16;
|
||||
| u32::from(subclass.get_register_value()) << 16
|
||||
| u32::from(pi) << 8;
|
||||
match header_type {
|
||||
PciHeaderType::Device => (),
|
||||
PciHeaderType::Bridge => registers[3] = 0x0001_0000,
|
||||
|
@ -364,6 +380,7 @@ mod tests {
|
|||
0x5678,
|
||||
PciClassCode::MultimediaController,
|
||||
&PciMultimediaSubclass::AudioController,
|
||||
None,
|
||||
PciHeaderType::Device,
|
||||
0xABCD,
|
||||
0x2468,
|
||||
|
@ -395,4 +412,37 @@ mod tests {
|
|||
assert_eq!((cap2_data >> 16) & 0xFF, 0x04); // cap2.len
|
||||
assert_eq!((cap2_data >> 24) & 0xFF, 0x55); // cap2.foo
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum TestPI {
|
||||
Test = 0x5a,
|
||||
}
|
||||
|
||||
impl PciProgrammingInterface for TestPI {
|
||||
fn get_register_value(&self) -> u8 {
|
||||
*self as u8
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn class_code() {
|
||||
let cfg = PciConfiguration::new(
|
||||
0x1234,
|
||||
0x5678,
|
||||
PciClassCode::MultimediaController,
|
||||
&PciMultimediaSubclass::AudioController,
|
||||
Some(&TestPI::Test),
|
||||
PciHeaderType::Device,
|
||||
0xABCD,
|
||||
0x2468,
|
||||
);
|
||||
|
||||
let class_reg = cfg.read_reg(2);
|
||||
let class_code = (class_reg >> 24) & 0xFF;
|
||||
let subclass = (class_reg >> 16) & 0xFF;
|
||||
let prog_if = (class_reg >> 8) & 0xFF;
|
||||
assert_eq!(class_code, 0x04);
|
||||
assert_eq!(subclass, 0x01);
|
||||
assert_eq!(prog_if, 0x5a);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@ impl PciRoot {
|
|||
0,
|
||||
PciClassCode::BridgeDevice,
|
||||
&PciBridgeSubclass::HostBridge,
|
||||
None,
|
||||
PciHeaderType::Bridge,
|
||||
0,
|
||||
0,
|
||||
|
|
Loading…
Reference in a new issue