mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-01-12 16:45:31 +00:00
pci: add tests for add_capability()
Also fix the misleading add_capability() comment. The standard PCI capability header is just two bytes (capability type and next pointer); the length byte is only part of the vendor-specific capability (09h). More importantly, the current implementation of add_capability() already inserts the two-byte standard header, so the caller should not provide it as part of cap_data. BUG=None TEST=cargo test -p devices Change-Id: Id3517d021bfe29d08ff664d66455b15cf07af1d1 Signed-off-by: Daniel Verkamp <dverkamp@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1197069 Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com> Reviewed-by: Dylan Reid <dgreid@chromium.org>
This commit is contained in:
parent
8a4a13d48d
commit
ed2b3e0349
1 changed files with 66 additions and 1 deletions
|
@ -294,7 +294,8 @@ impl PciConfiguration {
|
|||
}
|
||||
|
||||
/// Adds the capability `cap_data` to the list of capabilities.
|
||||
/// `cap_data` should include the three byte PCI capability header: type, next, length.
|
||||
/// `cap_data` should not include the two-byte PCI capability header (type, next);
|
||||
/// it will be generated automatically based on `cap_data.id()`.
|
||||
pub fn add_capability(&mut self, cap_data: &PciCapability) -> Option<usize> {
|
||||
let total_len = cap_data.bytes().len() + 2;
|
||||
// Check that the length is valid.
|
||||
|
@ -325,3 +326,67 @@ impl PciConfiguration {
|
|||
(next + 3) & !3
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use data_model::{DataInit, Le32};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[repr(packed)]
|
||||
#[derive(Clone, Copy)]
|
||||
struct TestCap {
|
||||
len: u8,
|
||||
foo: u8,
|
||||
}
|
||||
|
||||
// It is safe to implement DataInit; all members are simple numbers and any value is valid.
|
||||
unsafe impl DataInit for TestCap {}
|
||||
|
||||
impl PciCapability for TestCap {
|
||||
fn bytes(&self) -> &[u8] {
|
||||
self.as_slice()
|
||||
}
|
||||
|
||||
fn id(&self) -> PciCapabilityID {
|
||||
PciCapabilityID::VendorSpecific
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_capability() {
|
||||
let mut cfg = PciConfiguration::new(
|
||||
0x1234,
|
||||
0x5678,
|
||||
PciClassCode::MultimediaController,
|
||||
&PciMultimediaSubclass::AudioController,
|
||||
PciHeaderType::Device,
|
||||
);
|
||||
|
||||
// Add two capabilities with different contents.
|
||||
let cap1 = TestCap { len: 4, foo: 0xAA };
|
||||
let cap1_offset = cfg.add_capability(&cap1).unwrap();
|
||||
assert_eq!(cap1_offset % 4, 0);
|
||||
|
||||
let cap2 = TestCap { len: 0x04, foo: 0x55 };
|
||||
let cap2_offset = cfg.add_capability(&cap2).unwrap();
|
||||
assert_eq!(cap2_offset % 4, 0);
|
||||
|
||||
// The capability list head should be pointing to cap1.
|
||||
let cap_ptr = cfg.read_reg(CAPABILITY_LIST_HEAD_OFFSET / 4) & 0xFF;
|
||||
assert_eq!(cap1_offset, cap_ptr as usize);
|
||||
|
||||
// Verify the contents of the capabilities.
|
||||
let cap1_data = cfg.read_reg(cap1_offset / 4);
|
||||
assert_eq!(cap1_data & 0xFF, 0x09); // capability ID
|
||||
assert_eq!((cap1_data >> 8) & 0xFF, cap2_offset as u32); // next capability pointer
|
||||
assert_eq!((cap1_data >> 16) & 0xFF, 0x04); // cap1.len
|
||||
assert_eq!((cap1_data >> 24) & 0xFF, 0xAA); // cap1.foo
|
||||
|
||||
let cap2_data = cfg.read_reg(cap2_offset / 4);
|
||||
assert_eq!(cap2_data & 0xFF, 0x09); // capability ID
|
||||
assert_eq!((cap2_data >> 8) & 0xFF, 0x00); // next capability pointer
|
||||
assert_eq!((cap2_data >> 16) & 0xFF, 0x04); // cap2.len
|
||||
assert_eq!((cap2_data >> 24) & 0xFF, 0x55); // cap2.foo
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue