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:
Daniel Verkamp 2018-08-30 12:47:40 -07:00 committed by chrome-bot
parent 8a4a13d48d
commit ed2b3e0349

View file

@ -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
}
}