From 144da347c6bf5bb7ada8da513f6b61ab3243326d Mon Sep 17 00:00:00 2001 From: "alesharikReserv@yandex.ru" Date: Sat, 21 May 2022 16:54:50 +0300 Subject: [PATCH 1/4] Add capabilities and status register support --- src/capability/mod.rs | 134 ++++++++++++++++++++++++++++++ src/capability/msi.rs | 185 ++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 79 ++++++++++++++++-- src/register.rs | 128 +++++++++++++++++++++++++++++ 4 files changed, 517 insertions(+), 9 deletions(-) create mode 100644 src/capability/mod.rs create mode 100644 src/capability/msi.rs create mode 100644 src/register.rs diff --git a/src/capability/mod.rs b/src/capability/mod.rs new file mode 100644 index 0000000..3ed2b5d --- /dev/null +++ b/src/capability/mod.rs @@ -0,0 +1,134 @@ +use crate::{ConfigRegionAccess, PciAddress}; +use bit_field::BitField; +use core::fmt::Formatter; + +mod msi; + +pub use msi::{MsiCapability, MultipleMessageSupport, TriggerMode}; + +#[derive(Clone)] +pub struct PciCapabilityAddress { + pub address: PciAddress, + pub offset: u16, +} + +impl core::fmt::Debug for PciCapabilityAddress { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + write!(f, "{}, offset: {:02x}", self.address, self.offset) + } +} + +/// PCI capabilities +#[derive(Clone, Debug)] +pub enum PciCapability { + /// Power management capability, Cap ID = `0x01` + PowerManagement(PciCapabilityAddress), + /// Accelerated graphics port capability, Cap ID = `0x02` + AcceleratedGraphicsPort(PciCapabilityAddress), + /// Vital product data capability, Cap ID = `0x3` + VitalProductData(PciCapabilityAddress), + /// Slot identification capability, Cap ID = `0x04` + SlotIdentification(PciCapabilityAddress), + /// Message signalling interrupts capability, Cap ID = `0x05` + Msi(MsiCapability), + /// CompactPCI HotSwap capability, Cap ID = `0x06` + CompactPCIHotswap(PciCapabilityAddress), + /// PCI-X capability, Cap ID = `0x07` + PciX(PciCapabilityAddress), + /// HyperTransport capability, Cap ID = `0x08` + HyperTransport(PciCapabilityAddress), + /// Vendor-specific capability, Cap ID = `0x09` + Vendor(PciCapabilityAddress), + /// Debug port capability, Cap ID = `0x0A` + DebugPort(PciCapabilityAddress), + /// CompactPCI Central Resource Control capability, Cap ID = `0x0B` + CompactPCICentralResourceControl(PciCapabilityAddress), + /// PCI Standard Hot-Plug Controller capability, Cap ID = `0x0C` + PciHotPlugControl(PciCapabilityAddress), + /// Bridge subsystem vendor/device ID capability, Cap ID = `0x0D` + BridgeSubsystemVendorId(PciCapabilityAddress), + /// AGP Target PCI-PCI bridge capability, Cap ID = `0x0E` + AGP3(PciCapabilityAddress), + /// PCI Express capability, Cap ID = `0x10` + PciExpress(PciCapabilityAddress), + /// MSI-X capability, Cap ID = `0x11` + MsiX(PciCapabilityAddress), + /// Unknown capability + Unknown { + address: PciCapabilityAddress, + id: u8, + }, +} + +impl PciCapability { + fn parse(id: u8, address: PciCapabilityAddress, control: u16) -> Option { + match id { + 0x00 => None, // null capability + 0x01 => Some(PciCapability::PowerManagement(address)), + 0x02 => Some(PciCapability::AcceleratedGraphicsPort(address)), + 0x03 => Some(PciCapability::VitalProductData(address)), + 0x04 => Some(PciCapability::SlotIdentification(address)), + 0x05 => Some(PciCapability::Msi(MsiCapability::new(address, control))), + 0x06 => Some(PciCapability::CompactPCIHotswap(address)), + 0x07 => Some(PciCapability::PciX(address)), + 0x08 => Some(PciCapability::HyperTransport(address)), + 0x09 => Some(PciCapability::Vendor(address)), + 0x0A => Some(PciCapability::DebugPort(address)), + 0x0B => Some(PciCapability::CompactPCICentralResourceControl(address)), + 0x0C => Some(PciCapability::PciHotPlugControl(address)), + 0x0D => Some(PciCapability::BridgeSubsystemVendorId(address)), + 0x0E => Some(PciCapability::AGP3(address)), + 0x10 => Some(PciCapability::PciExpress(address)), + 0x11 => Some(PciCapability::MsiX(address)), + _ => Some(PciCapability::Unknown { address, id }), + } + } +} + +pub struct CapabilityIterator<'a, T: ConfigRegionAccess> { + address: PciAddress, + offset: u16, + access: &'a T, +} + +impl<'a, T: ConfigRegionAccess> CapabilityIterator<'a, T> { + pub(crate) fn new( + address: PciAddress, + offset: u16, + access: &'a T, + ) -> CapabilityIterator<'a, T> { + CapabilityIterator { + address, + offset, + access, + } + } +} + +impl<'a, T: ConfigRegionAccess> Iterator for CapabilityIterator<'a, T> { + type Item = PciCapability; + + fn next(&mut self) -> Option { + loop { + if self.offset == 0 { + return None; + } + let data = unsafe { self.access.read(self.address, self.offset) }; + let next_ptr = data.get_bits(8..16); + let id = data.get_bits(0..8); + let control = data.get_bits(16..32) as u16; + let cap = PciCapability::parse( + id as u8, + PciCapabilityAddress { + address: self.address, + offset: self.offset, + }, + control, + ); + self.offset = next_ptr as u16; + if let Some(cap) = cap { + return Some(cap); + } + } + } +} diff --git a/src/capability/msi.rs b/src/capability/msi.rs new file mode 100644 index 0000000..11779c6 --- /dev/null +++ b/src/capability/msi.rs @@ -0,0 +1,185 @@ +use crate::{capability::PciCapabilityAddress, ConfigRegionAccess}; +use bit_field::BitField; +use core::convert::TryFrom; + +/// Specifies, how much MSI interrupts one device can have. +/// Device will modify lower bits of interrupt vector to send multiple messages, so interrupt block +/// must be aligned accordingly. +#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)] +pub enum MultipleMessageSupport { + /// Device can send 1 interrupt. No interrupt vector modification is happening here + Int1 = 0b000, + /// Device can send 2 interrupts + Int2 = 0b001, + /// Device can send 4 interrupts + Int4 = 0b010, + /// Device can send 8 interrupts + Int8 = 0b011, + /// Device can send 16 interrupts + Int16 = 0b100, + /// Device can send 32 interrupts + Int32 = 0b101, +} + +impl TryFrom for MultipleMessageSupport { + type Error = (); + + fn try_from(value: u8) -> Result { + match value { + 0b000 => Ok(MultipleMessageSupport::Int1), + 0b001 => Ok(MultipleMessageSupport::Int2), + 0b010 => Ok(MultipleMessageSupport::Int4), + 0b011 => Ok(MultipleMessageSupport::Int8), + 0b100 => Ok(MultipleMessageSupport::Int16), + 0b101 => Ok(MultipleMessageSupport::Int32), + _ => Err(()), + } + } +} + +/// When device should trigger the interrupt +#[derive(Debug)] +pub enum TriggerMode { + Edge = 0b00, + LevelAssert = 0b11, + LevelDeassert = 0b10, +} + +#[derive(Debug, Clone)] +pub struct MsiCapability { + address: PciCapabilityAddress, + per_vector_masking: bool, + is_64bit: bool, + multiple_message_capable: MultipleMessageSupport, +} + +impl MsiCapability { + pub(crate) fn new(address: PciCapabilityAddress, control: u16) -> MsiCapability { + MsiCapability { + address, + per_vector_masking: control.get_bit(8), + is_64bit: control.get_bit(7), + multiple_message_capable: + MultipleMessageSupport::try_from(control.get_bits(1..4) as u8) + .unwrap_or(MultipleMessageSupport::Int1), + } + } + + /// Does device supports masking individual vectors? + #[inline] + pub fn has_per_vector_masking(&self) -> bool { + self.per_vector_masking + } + + /// Is device using 64-bit addressing? + #[inline] + pub fn is_64bit(&self) -> bool { + self.is_64bit + } + + /// How much interrupts this device has? + #[inline] + pub fn get_multiple_message_capable(&self) -> MultipleMessageSupport { + self.multiple_message_capable + } + + /// Is MSI capability enabled? + pub fn is_enabled(&self, access: &T) -> bool { + let reg = unsafe { access.read(self.address.address, self.address.offset) }; + reg.get_bit(0) + } + + /// Enable or disable MSI capability + pub fn set_enabled(&self, enabled: bool, access: &T) { + let mut reg = unsafe { access.read(self.address.address, self.address.offset) }; + reg.set_bit(0, enabled); + unsafe { access.write(self.address.address, self.address.offset, reg) }; + } + + /// Set how much interrupts the device will use. If requested count is bigger than supported count, + /// the second will be used. + pub fn set_multiple_message_enable( + &self, + data: MultipleMessageSupport, + access: &T, + ) { + let mut reg = unsafe { access.read(self.address.address, self.address.offset) }; + reg.set_bits(4..7, (data.min(self.multiple_message_capable)) as u32); + unsafe { access.write(self.address.address, self.address.offset, reg) }; + } + + /// Return how much interrupts the device is using + pub fn get_multiple_message_enable( + &self, + access: &T, + ) -> MultipleMessageSupport { + let reg = unsafe { access.read(self.address.address, self.address.offset) }; + MultipleMessageSupport::try_from(reg.get_bits(4..7) as u8) + .unwrap_or(MultipleMessageSupport::Int1) + } + + /// Set where the interrupts will be sent to + /// + /// # Arguments + /// * `address` - Target Local APIC address (if not changed, can be calculated with `0xFEE00000 | (processor << 12)`) + /// * `vector` - Which interrupt vector should be triggered on LAPIC + /// * `trigger_mode` - When interrupt should be triggered + /// * `access` - PCI Configuration Space accessor + pub fn set_message_info( + &self, + address: u32, + vector: u8, + trigger_mode: TriggerMode, + access: &T, + ) { + unsafe { access.write(self.address.address, self.address.offset + 0x4, address) } + let data_offset = if self.is_64bit { 0xC } else { 0x8 }; + let mut data = + unsafe { access.read(self.address.address, self.address.offset + data_offset) }; + data.set_bits(0..8, vector as u32); + data.set_bits(14..16, trigger_mode as u32); + unsafe { + access.write( + self.address.address, + self.address.offset + data_offset, + data, + ) + } + } + + /// Get interrupt mask + /// + /// # Note + /// Only supported on when device supports 64-bit addressing and per-vector masking. Otherwise + /// returns `0` + pub fn get_message_mask(&self, access: &T) -> u32 { + if self.is_64bit && self.per_vector_masking { + unsafe { access.read(self.address.address, self.address.offset + 0x10) } + } else { + 0 + } + } + + /// Set interrupt mask + /// + /// # Note + /// Only supported on when device supports 64-bit addressing and per-vector masking. Otherwise + /// will do nothing + pub fn set_message_mask(&self, access: &T, mask: u32) { + if self.is_64bit && self.per_vector_masking { + unsafe { access.write(self.address.address, self.address.offset + 0x10, mask) } + } + } + + /// Get pending interrupts + /// + /// # Note + /// Only supported on when device supports 64-bit addressing. Otherwise will return `0` + pub fn get_pending(&self, access: &T) -> u32 { + if self.is_64bit { + unsafe { access.read(self.address.address, self.address.offset + 0x14) } + } else { + 0 + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 219ba40..c59a092 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,12 @@ #![no_std] +pub mod capability; pub mod device_type; +mod register; +pub use register::{DevselTiming, StatusRegister}; + +use crate::capability::CapabilityIterator; use bit_field::BitField; use core::fmt; @@ -45,7 +50,14 @@ impl PciAddress { impl fmt::Display for PciAddress { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{:02x}-{:02x}:{:02x}.{}", self.segment(), self.bus(), self.device(), self.function()) + write!( + f, + "{:02x}-{:02x}:{:02x}.{}", + self.segment(), + self.bus(), + self.device(), + self.function() + ) } } @@ -98,7 +110,10 @@ impl PciHeader { pub fn id(&self, access: &impl ConfigRegionAccess) -> (VendorId, DeviceId) { let id = unsafe { access.read(self.0, 0x00) }; - (id.get_bits(0..16) as VendorId, id.get_bits(16..32) as DeviceId) + ( + id.get_bits(0..16) as VendorId, + id.get_bits(16..32) as DeviceId, + ) } pub fn header_type(&self, access: &impl ConfigRegionAccess) -> HeaderType { @@ -128,6 +143,11 @@ impl PciHeader { field.get_bits(8..16) as Interface, ) } + + pub fn status(&self, access: &impl ConfigRegionAccess) -> StatusRegister { + let data = unsafe { access.read(self.0, 0x4).get_bits(16..32) }; + StatusRegister::new(data as u16) + } } /// Endpoints have a Type-0 header, so the remainder of the header is of the form: @@ -179,7 +199,10 @@ impl PciHeader { pub struct EndpointHeader(PciAddress); impl EndpointHeader { - pub fn from_header(header: PciHeader, access: &impl ConfigRegionAccess) -> Option { + pub fn from_header( + header: PciHeader, + access: &impl ConfigRegionAccess, + ) -> Option { match header.header_type(access) { 0x00 => Some(EndpointHeader(header.0)), _ => None, @@ -190,6 +213,24 @@ impl EndpointHeader { PciHeader(self.0) } + pub fn capability_pointer(&self, access: &impl ConfigRegionAccess) -> u16 { + let data = unsafe { access.read(self.0, 0x4).get_bits(16..32) }; + let status = StatusRegister::new(data as u16); + if status.has_capability_list() { + unsafe { access.read(self.0, 0x34).get_bits(0..8) as u16 } + } else { + 0 + } + } + + pub fn capabilities<'a, T: ConfigRegionAccess>( + &self, + access: &'a T, + ) -> CapabilityIterator<'a, T> { + let pointer = self.capability_pointer(access); + CapabilityIterator::new(self.0, pointer, access) + } + /// Get the contents of a BAR in a given slot. Empty bars will return `None`. /// /// ### Note @@ -224,7 +265,11 @@ impl EndpointHeader { }; match bar.get_bits(1..3) { - 0b00 => Some(Bar::Memory32 { address, size, prefetchable }), + 0b00 => Some(Bar::Memory32 { + address, + size, + prefetchable, + }), 0b10 => { let address = { let mut address = address as u64; @@ -232,13 +277,19 @@ impl EndpointHeader { address.set_bits(32..64, unsafe { access.read(self.0, offset + 4) } as u64); address }; - Some(Bar::Memory64 { address, size: size as u64, prefetchable }) + Some(Bar::Memory64 { + address, + size: size as u64, + prefetchable, + }) } // TODO: should we bother to return an error here? _ => panic!("BAR Memory type is reserved!"), } } else { - Some(Bar::Io { port: bar.get_bits(2..32) }) + Some(Bar::Io { + port: bar.get_bits(2..32), + }) } } } @@ -247,7 +298,17 @@ pub const MAX_BARS: usize = 6; #[derive(Clone, Copy, Debug)] pub enum Bar { - Memory32 { address: u32, size: u32, prefetchable: bool }, - Memory64 { address: u64, size: u64, prefetchable: bool }, - Io { port: u32 }, + Memory32 { + address: u32, + size: u32, + prefetchable: bool, + }, + Memory64 { + address: u64, + size: u64, + prefetchable: bool, + }, + Io { + port: u32, + }, } diff --git a/src/register.rs b/src/register.rs new file mode 100644 index 0000000..c7ded09 --- /dev/null +++ b/src/register.rs @@ -0,0 +1,128 @@ +use bit_field::BitField; +use core::convert::TryFrom; +use core::fmt::{Debug, Formatter}; + +/// Slowest time that a device will assert DEVSEL# for any bus command except Configuration Space +/// read and writes +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum DevselTiming { + Fast = 0x0, + Medium = 0x1, + Slow = 0x2, +} + +impl TryFrom for DevselTiming { + type Error = (); + + fn try_from(value: u8) -> Result { + match value { + 0x0 => Ok(DevselTiming::Fast), + 0x1 => Ok(DevselTiming::Medium), + 0x2 => Ok(DevselTiming::Slow), + _ => Err(()), + } + } +} + +#[derive(Clone, Copy, Eq, PartialEq)] +pub struct StatusRegister(u16); + +impl StatusRegister { + pub fn new(value: u16) -> Self { + StatusRegister(value) + } + + /// Will be `true` whenever the device detects a parity error, even if parity error handling is disabled. + pub fn parity_error_detected(&self) -> bool { + self.0.get_bit(15) + } + + /// Will be `true` whenever the device asserts SERR#. + pub fn signalled_system_error(&self) -> bool { + self.0.get_bit(14) + } + + /// Will return `true`, by a master device, whenever its transaction + /// (except for Special Cycle transactions) is terminated with Master-Abort. + pub fn received_master_abort(&self) -> bool { + self.0.get_bit(13) + } + + /// Will return `true`, by a master device, whenever its transaction is terminated with Target-Abort. + pub fn received_target_abort(&self) -> bool { + self.0.get_bit(12) + } + + /// Will return `true` whenever a target device terminates a transaction with Target-Abort. + pub fn signalled_target_abort(&self) -> bool { + self.0.get_bit(11) + } + + /// The slowest time that a device will assert DEVSEL# for any bus command except + /// Configuration Space read and writes. + /// + /// For PCIe always set to `Fast` + pub fn devsel_timing(&self) -> Result { + let bits = self.0.get_bits(9..11); + DevselTiming::try_from(bits as u8) + } + + /// This returns `true` only when the following conditions are met: + /// - The bus agent asserted PERR# on a read or observed an assertion of PERR# on a write + /// - the agent setting the bit acted as the bus master for the operation in which the error occurred + /// - bit 6 of the Command register (Parity Error Response bit) is set to 1. + pub fn master_data_parity_error(&self) -> bool { + self.0.get_bit(8) + } + + /// If returns `true` the device can accept fast back-to-back transactions that are not from + /// the same agent; otherwise, transactions can only be accepted from the same agent. + /// + /// For PCIe always set to `false` + pub fn fast_back_to_back_capable(&self) -> bool { + self.0.get_bit(7) + } + + /// If returns `true` the device is capable of running at 66 MHz; otherwise, the device runs at 33 MHz. + /// + /// For PCIe always set to `false` + pub fn capable_66mhz(&self) -> bool { + self.0.get_bit(5) + } + + /// If returns `true` the device implements the pointer for a New Capabilities Linked list; + /// otherwise, the linked list is not available. + /// + /// For PCIe always set to `true` + pub fn has_capability_list(&self) -> bool { + self.0.get_bit(4) + } + + /// Represents the state of the device's INTx# signal. If returns `true` and bit 10 of the + /// Command register (Interrupt Disable bit) is set to 0 the signal will be asserted; + /// otherwise, the signal will be ignored. + pub fn interrupt_status(&self) -> bool { + self.0.get_bit(3) + } +} + +impl Debug for StatusRegister { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + f.debug_struct("StatusRegister") + .field("parity_error_detected", &self.parity_error_detected()) + .field("signalled_system_error", &self.signalled_system_error()) + .field("received_master_abort", &self.received_master_abort()) + .field("received_target_abort", &self.received_target_abort()) + .field("signalled_target_abort", &self.signalled_target_abort()) + .field("devsel_timing", &self.devsel_timing()) + .field("master_data_parity_error", &self.master_data_parity_error()) + .field( + "fast_back_to_back_capable", + &self.fast_back_to_back_capable(), + ) + .field("capable_66mhz", &self.capable_66mhz()) + .field("has_capability_list", &self.has_capability_list()) + .field("interrupt_status", &self.interrupt_status()) + .finish() + } +} From 8f8138f1af1e0027ca5028ae32e9bfc038cdab75 Mon Sep 17 00:00:00 2001 From: "alesharikReserv@yandex.ru" Date: Sat, 21 May 2022 17:03:02 +0300 Subject: [PATCH 2/4] Add `status` method to `EndpointHeader` --- src/lib.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index c59a092..69d0d8b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -209,13 +209,17 @@ impl EndpointHeader { } } + pub fn status(&self, access: &impl ConfigRegionAccess) -> StatusRegister { + let data = unsafe { access.read(self.0, 0x4).get_bits(16..32) }; + StatusRegister::new(data as u16) + } + pub fn header(&self) -> PciHeader { PciHeader(self.0) } pub fn capability_pointer(&self, access: &impl ConfigRegionAccess) -> u16 { - let data = unsafe { access.read(self.0, 0x4).get_bits(16..32) }; - let status = StatusRegister::new(data as u16); + let status = self.status(access); if status.has_capability_list() { unsafe { access.read(self.0, 0x34).get_bits(0..8) as u16 } } else { From 9b53329a9b2b96ecb2d2097756e925ac17a62a28 Mon Sep 17 00:00:00 2001 From: "alesharikReserv@yandex.ru" Date: Sat, 21 May 2022 17:04:10 +0300 Subject: [PATCH 3/4] Refactor `MsiCapability` --- src/capability/msi.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/capability/msi.rs b/src/capability/msi.rs index 11779c6..fe1cb5d 100644 --- a/src/capability/msi.rs +++ b/src/capability/msi.rs @@ -84,13 +84,13 @@ impl MsiCapability { } /// Is MSI capability enabled? - pub fn is_enabled(&self, access: &T) -> bool { + pub fn is_enabled(&self, access: &impl ConfigRegionAccess) -> bool { let reg = unsafe { access.read(self.address.address, self.address.offset) }; reg.get_bit(0) } /// Enable or disable MSI capability - pub fn set_enabled(&self, enabled: bool, access: &T) { + pub fn set_enabled(&self, enabled: bool, access: &impl ConfigRegionAccess) { let mut reg = unsafe { access.read(self.address.address, self.address.offset) }; reg.set_bit(0, enabled); unsafe { access.write(self.address.address, self.address.offset, reg) }; @@ -98,10 +98,10 @@ impl MsiCapability { /// Set how much interrupts the device will use. If requested count is bigger than supported count, /// the second will be used. - pub fn set_multiple_message_enable( + pub fn set_multiple_message_enable( &self, data: MultipleMessageSupport, - access: &T, + access: &impl ConfigRegionAccess, ) { let mut reg = unsafe { access.read(self.address.address, self.address.offset) }; reg.set_bits(4..7, (data.min(self.multiple_message_capable)) as u32); @@ -109,9 +109,9 @@ impl MsiCapability { } /// Return how much interrupts the device is using - pub fn get_multiple_message_enable( + pub fn get_multiple_message_enable( &self, - access: &T, + access: &impl ConfigRegionAccess, ) -> MultipleMessageSupport { let reg = unsafe { access.read(self.address.address, self.address.offset) }; MultipleMessageSupport::try_from(reg.get_bits(4..7) as u8) @@ -125,12 +125,12 @@ impl MsiCapability { /// * `vector` - Which interrupt vector should be triggered on LAPIC /// * `trigger_mode` - When interrupt should be triggered /// * `access` - PCI Configuration Space accessor - pub fn set_message_info( + pub fn set_message_info( &self, address: u32, vector: u8, trigger_mode: TriggerMode, - access: &T, + access: &impl ConfigRegionAccess, ) { unsafe { access.write(self.address.address, self.address.offset + 0x4, address) } let data_offset = if self.is_64bit { 0xC } else { 0x8 }; @@ -152,7 +152,7 @@ impl MsiCapability { /// # Note /// Only supported on when device supports 64-bit addressing and per-vector masking. Otherwise /// returns `0` - pub fn get_message_mask(&self, access: &T) -> u32 { + pub fn get_message_mask(&self, access: &impl ConfigRegionAccess) -> u32 { if self.is_64bit && self.per_vector_masking { unsafe { access.read(self.address.address, self.address.offset + 0x10) } } else { @@ -165,7 +165,7 @@ impl MsiCapability { /// # Note /// Only supported on when device supports 64-bit addressing and per-vector masking. Otherwise /// will do nothing - pub fn set_message_mask(&self, access: &T, mask: u32) { + pub fn set_message_mask(&self, access: &impl ConfigRegionAccess, mask: u32) { if self.is_64bit && self.per_vector_masking { unsafe { access.write(self.address.address, self.address.offset + 0x10, mask) } } @@ -175,7 +175,7 @@ impl MsiCapability { /// /// # Note /// Only supported on when device supports 64-bit addressing. Otherwise will return `0` - pub fn get_pending(&self, access: &T) -> u32 { + pub fn get_pending(&self, access: &impl ConfigRegionAccess) -> u32 { if self.is_64bit { unsafe { access.read(self.address.address, self.address.offset + 0x14) } } else { From d29b9814d916450eb356249371ccd01020dab31e Mon Sep 17 00:00:00 2001 From: "alesharikReserv@yandex.ru" Date: Tue, 24 May 2022 22:06:46 +0300 Subject: [PATCH 4/4] Refactor and fix typos --- src/capability/mod.rs | 8 ++++---- src/capability/msi.rs | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/capability/mod.rs b/src/capability/mod.rs index 3ed2b5d..5354bf8 100644 --- a/src/capability/mod.rs +++ b/src/capability/mod.rs @@ -61,14 +61,14 @@ pub enum PciCapability { } impl PciCapability { - fn parse(id: u8, address: PciCapabilityAddress, control: u16) -> Option { + fn parse(id: u8, address: PciCapabilityAddress, extension: u16) -> Option { match id { 0x00 => None, // null capability 0x01 => Some(PciCapability::PowerManagement(address)), 0x02 => Some(PciCapability::AcceleratedGraphicsPort(address)), 0x03 => Some(PciCapability::VitalProductData(address)), 0x04 => Some(PciCapability::SlotIdentification(address)), - 0x05 => Some(PciCapability::Msi(MsiCapability::new(address, control))), + 0x05 => Some(PciCapability::Msi(MsiCapability::new(address, extension))), 0x06 => Some(PciCapability::CompactPCIHotswap(address)), 0x07 => Some(PciCapability::PciX(address)), 0x08 => Some(PciCapability::HyperTransport(address)), @@ -116,14 +116,14 @@ impl<'a, T: ConfigRegionAccess> Iterator for CapabilityIterator<'a, T> { let data = unsafe { self.access.read(self.address, self.offset) }; let next_ptr = data.get_bits(8..16); let id = data.get_bits(0..8); - let control = data.get_bits(16..32) as u16; + let extension = data.get_bits(16..32) as u16; let cap = PciCapability::parse( id as u8, PciCapabilityAddress { address: self.address, offset: self.offset, }, - control, + extension, ); self.offset = next_ptr as u16; if let Some(cap) = cap { diff --git a/src/capability/msi.rs b/src/capability/msi.rs index fe1cb5d..7f870f3 100644 --- a/src/capability/msi.rs +++ b/src/capability/msi.rs @@ -2,7 +2,7 @@ use crate::{capability::PciCapabilityAddress, ConfigRegionAccess}; use bit_field::BitField; use core::convert::TryFrom; -/// Specifies, how much MSI interrupts one device can have. +/// Specifies how many MSI interrupts one device can have. /// Device will modify lower bits of interrupt vector to send multiple messages, so interrupt block /// must be aligned accordingly. #[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)] @@ -77,7 +77,7 @@ impl MsiCapability { self.is_64bit } - /// How much interrupts this device has? + /// How many interrupts this device has? #[inline] pub fn get_multiple_message_capable(&self) -> MultipleMessageSupport { self.multiple_message_capable @@ -96,7 +96,7 @@ impl MsiCapability { unsafe { access.write(self.address.address, self.address.offset, reg) }; } - /// Set how much interrupts the device will use. If requested count is bigger than supported count, + /// Set how many interrupts the device will use. If requested count is bigger than supported count, /// the second will be used. pub fn set_multiple_message_enable( &self, @@ -108,7 +108,7 @@ impl MsiCapability { unsafe { access.write(self.address.address, self.address.offset, reg) }; } - /// Return how much interrupts the device is using + /// Return how many interrupts the device is using pub fn get_multiple_message_enable( &self, access: &impl ConfigRegionAccess,