From 4bd978da7a18fbd0f3765f612c3f84e82debcea6 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 10 Jun 2024 17:37:32 +0200 Subject: [PATCH] pcid: Use pci_types for parsing capabilties --- pcid/src/driver_handler.rs | 216 +++++++++++++++++-------------- pcid/src/main.rs | 12 +- pcid/src/pci/cap.rs | 170 +----------------------- pcid/src/pci/msi.rs | 256 ------------------------------------- pcid/src/pci_header.rs | 10 -- 5 files changed, 125 insertions(+), 539 deletions(-) diff --git a/pcid/src/driver_handler.rs b/pcid/src/driver_handler.rs index c1b08d0937..4374df9387 100644 --- a/pcid/src/driver_handler.rs +++ b/pcid/src/driver_handler.rs @@ -5,10 +5,10 @@ use std::sync::Arc; use std::thread; use log::{error, info}; +use pci_types::capability::{MultipleMessageSupport, PciCapability}; use pci_types::{ConfigRegionAccess, PciAddress}; use crate::driver_interface; -use crate::pci::cap::Capability as PciCapability; use crate::State; pub struct DriverHandler { @@ -97,7 +97,6 @@ impl DriverHandler { request: driver_interface::PcidClientRequest, args: &driver_interface::SubdriverArguments, ) -> driver_interface::PcidClientResponse { - use crate::pci::cap::{MsiCapability, MsixCapability}; use driver_interface::*; match request { @@ -105,7 +104,9 @@ impl DriverHandler { self.capabilities .iter() .filter_map(|capability| match capability { - PciCapability::Vendor(capability) => Some(capability.clone()), + PciCapability::Vendor(addr) => unsafe { + Some(VendorSpecificCapability::parse(*addr, &self.state.pcie)) + }, _ => None, }) .collect::>(), @@ -121,85 +122,87 @@ impl DriverHandler { }) .collect(), ), - PcidClientRequest::EnableFeature(feature) => match feature { - PciFeature::Msi => { - if let Some(msix_capability) = self - .capabilities - .iter_mut() - .find_map(|capability| capability.as_msix_mut()) - { - // If MSI-X is supported disable it before enabling MSI as they can't be - // active at the same time. - unsafe { - msix_capability.set_msix_enabled(false); - msix_capability.write_a(self.addr, &self.state.pcie); + PcidClientRequest::EnableFeature(feature) => { + match feature { + PciFeature::Msi => { + if let Some(msix_capability) = + self.capabilities + .iter_mut() + .find_map(|capability| match capability { + PciCapability::MsiX(cap) => Some(cap), + _ => None, + }) + { + // If MSI-X is supported disable it before enabling MSI as they can't be + // active at the same time. + msix_capability.set_enabled(false, &self.state.pcie); } - } - let capability: &mut MsiCapability = match self - .capabilities - .iter_mut() - .find_map(|capability| capability.as_msi_mut()) - { - Some(capability) => capability, - None => { - return PcidClientResponse::Error( - PcidServerResponseError::NonexistentFeature(feature), - ) - } - }; - unsafe { - capability.set_enabled(true); - capability.write_message_control(self.addr, &self.state.pcie); + let capability = match self.capabilities.iter_mut().find_map(|capability| { + match capability { + PciCapability::Msi(cap) => Some(cap), + _ => None, + } + }) { + Some(capability) => capability, + None => { + return PcidClientResponse::Error( + PcidServerResponseError::NonexistentFeature(feature), + ) + } + }; + capability.set_enabled(true, &self.state.pcie); + PcidClientResponse::FeatureEnabled(feature) } - PcidClientResponse::FeatureEnabled(feature) - } - PciFeature::MsiX => { - if let Some(msi_capability) = self - .capabilities - .iter_mut() - .find_map(|capability| capability.as_msi_mut()) - { - // If MSI is supported disable it before enabling MSI-X as they can't be - // active at the same time. - unsafe { - msi_capability.set_enabled(false); - msi_capability.write_message_control(self.addr, &self.state.pcie); + PciFeature::MsiX => { + if let Some(msi_capability) = + self.capabilities + .iter_mut() + .find_map(|capability| match capability { + PciCapability::Msi(cap) => Some(cap), + _ => None, + }) + { + // If MSI is supported disable it before enabling MSI-X as they can't be + // active at the same time. + msi_capability.set_enabled(false, &self.state.pcie); } - } - let capability: &mut MsixCapability = match self - .capabilities - .iter_mut() - .find_map(|capability| capability.as_msix_mut()) - { - Some(capability) => capability, - None => { - return PcidClientResponse::Error( - PcidServerResponseError::NonexistentFeature(feature), - ) - } - }; - unsafe { - capability.set_msix_enabled(true); - capability.write_a(self.addr, &self.state.pcie); + let capability = match self.capabilities.iter_mut().find_map(|capability| { + match capability { + PciCapability::MsiX(cap) => Some(cap), + _ => None, + } + }) { + Some(capability) => capability, + None => { + return PcidClientResponse::Error( + PcidServerResponseError::NonexistentFeature(feature), + ) + } + }; + capability.set_enabled(true, &self.state.pcie); + PcidClientResponse::FeatureEnabled(feature) } - PcidClientResponse::FeatureEnabled(feature) } - }, + } PcidClientRequest::FeatureInfo(feature) => PcidClientResponse::FeatureInfo( feature, match feature { PciFeature::Msi => { - if let Some(info) = self - .capabilities - .iter() - .find_map(|capability| capability.as_msi()) + if let Some(info) = + self.capabilities + .iter() + .find_map(|capability| match capability { + PciCapability::Msi(cap) => Some(cap), + _ => None, + }) { PciFeatureInfo::Msi(msi::MsiInfo { - log2_multiple_message_capable: info.multi_message_capable(), - is_64bit: info.has_64_bit_addr(), - has_per_vector_masking: info.is_pvt_capable(), + log2_multiple_message_capable: info.multiple_message_capable() + as u8, + is_64bit: info.is_64bit(), + has_per_vector_masking: info.has_per_vector_masking(), }) } else { return PcidClientResponse::Error( @@ -208,16 +211,19 @@ impl DriverHandler { } } PciFeature::MsiX => { - if let Some(info) = self - .capabilities - .iter() - .find_map(|capability| capability.as_msix()) + if let Some(info) = + self.capabilities + .iter() + .find_map(|capability| match capability { + PciCapability::MsiX(cap) => Some(cap), + _ => None, + }) { PciFeatureInfo::MsiX(msi::MsixInfo { - table_bar: info.table_bir(), + table_bar: info.table_bar(), table_offset: info.table_offset(), table_size: info.table_size(), - pba_bar: info.pba_bir(), + pba_bar: info.pba_bar(), pba_offset: info.pba_offset(), }) } else { @@ -230,18 +236,36 @@ impl DriverHandler { ), PcidClientRequest::SetFeatureInfo(info_to_set) => match info_to_set { SetFeatureInfo::Msi(info_to_set) => { - if let Some(info) = self - .capabilities - .iter_mut() - .find_map(|capability| capability.as_msi_mut()) + if let Some(info) = + self.capabilities + .iter_mut() + .find_map(|capability| match capability { + PciCapability::Msi(cap) => Some(cap), + _ => None, + }) { if let Some(mme) = info_to_set.multi_message_enable { - if info.multi_message_capable() < mme || mme > 0b101 { + if (info.multiple_message_capable() as u8) < mme { return PcidClientResponse::Error( PcidServerResponseError::InvalidBitPattern, ); } - info.set_multi_message_enable(mme); + info.set_multiple_message_enable( + match mme { + 0 => MultipleMessageSupport::Int1, + 1 => MultipleMessageSupport::Int2, + 2 => MultipleMessageSupport::Int4, + 3 => MultipleMessageSupport::Int8, + 4 => MultipleMessageSupport::Int16, + 5 => MultipleMessageSupport::Int32, + _ => { + return PcidClientResponse::Error( + PcidServerResponseError::InvalidBitPattern, + ) + } + }, + &self.state.pcie, + ); } if let Some(message_addr_and_data) = info_to_set.message_address_and_data { let message_addr = message_addr_and_data.addr; @@ -250,27 +274,25 @@ impl DriverHandler { PcidServerResponseError::InvalidBitPattern, ); } - info.set_message_address(message_addr as u32); - info.set_message_upper_address((message_addr >> 32) as u32); - if message_addr_and_data.data & ((1 << info.multi_message_enable()) - 1) + if message_addr_and_data.data + & ((1 << info.multiple_message_enable(&self.state.pcie) as u8) - 1) != 0 { return PcidClientResponse::Error( PcidServerResponseError::InvalidBitPattern, ); } - info.set_message_data( + info.set_message_info( + message_addr, message_addr_and_data .data .try_into() .expect("pcid: MSI message data too big"), + &self.state.pcie, ); } if let Some(mask_bits) = info_to_set.mask_bits { - info.set_mask_bits(mask_bits); - } - unsafe { - info.write_all(self.addr, &self.state.pcie); + info.set_message_mask(mask_bits, &self.state.pcie); } PcidClientResponse::SetFeatureInfo(PciFeature::Msi) } else { @@ -280,16 +302,16 @@ impl DriverHandler { } } SetFeatureInfo::MsiX { function_mask } => { - if let Some(info) = self - .capabilities - .iter_mut() - .find_map(|capability| capability.as_msix_mut()) + if let Some(info) = + self.capabilities + .iter_mut() + .find_map(|capability| match capability { + PciCapability::MsiX(cap) => Some(cap), + _ => None, + }) { if let Some(mask) = function_mask { - info.set_function_mask(mask); - unsafe { - info.write_a(self.addr, &self.state.pcie); - } + info.set_function_mask(mask, &self.state.pcie); } PcidClientResponse::SetFeatureInfo(PciFeature::MsiX) } else { diff --git a/pcid/src/main.rs b/pcid/src/main.rs index 039e0fd2ea..3f126f7e3d 100644 --- a/pcid/src/main.rs +++ b/pcid/src/main.rs @@ -4,7 +4,6 @@ use std::sync::{Arc, Mutex}; use std::thread; use log::{debug, info, trace, warn}; -use pci_types::capability::PciCapabilityAddress; use pci_types::{CommandRegister, PciAddress}; use redox_log::{OutputBuilder, RedoxLogger}; use structopt::StructOpt; @@ -98,14 +97,9 @@ fn handle_parsed_header(state: Arc, config: &Config, header: PciEndpointH }; let capabilities = if endpoint_header.status(&state.pcie).has_capability_list() { - crate::pci::cap::CapabilitiesIter::new( - PciCapabilityAddress { - address: header.address(), - offset: header.cap_pointer(), - }, - &state.pcie, - ) - .collect::>() + endpoint_header + .capabilities(&state.pcie) + .collect::>() } else { Vec::new() }; diff --git a/pcid/src/pci/cap.rs b/pcid/src/pci/cap.rs index 47dc68fc55..7655be1c14 100644 --- a/pcid/src/pci/cap.rs +++ b/pcid/src/pci/cap.rs @@ -2,148 +2,13 @@ use pci_types::capability::PciCapabilityAddress; use pci_types::ConfigRegionAccess; use serde::{Serialize, Deserialize}; -pub struct CapabilitiesIter<'a> { - addr: PciCapabilityAddress, - access: &'a dyn ConfigRegionAccess, -} -impl<'a> CapabilitiesIter<'a> { - pub fn new(addr: PciCapabilityAddress, access: &'a dyn ConfigRegionAccess) -> Self { - Self { addr, access } - } -} -impl<'a> Iterator for CapabilitiesIter<'a> { - type Item = Capability; - - fn next(&mut self) -> Option { - let addr = unsafe { - // mask RsvdP bits - self.addr.offset = self.addr.offset & 0xFC; - - if self.addr.offset == 0 { - return None; - }; - - let first_dword = self.access.read(self.addr.address, self.addr.offset); - let next = ((first_dword >> 8) & 0xFF) as u16; - - let addr = self.addr; - self.addr.offset = next; - - addr - }; - - let cap = unsafe { - Capability::parse(addr, self.access) - }; - - Some(cap) - } -} - -#[repr(u8)] -pub enum CapabilityId { - PwrMgmt = 0x01, - Msi = 0x05, - MsiX = 0x11, - Pcie = 0x10, - Vendor = 0x09, - - // function specific - Sata = 0x12, // only on AHCI functions -} - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -pub enum MsiCapability { - _32BitAddress { - cap_offset: u16, - message_control: u32, - message_address: u32, - message_data: u16, - }, - _64BitAddress { - cap_offset: u16, - message_control: u32, - message_address_lo: u32, - message_address_hi: u32, - message_data: u16, - }, - _32BitAddressWithPvm { - cap_offset: u16, - message_control: u32, - message_address: u32, - message_data: u32, - mask_bits: u32, - pending_bits: u32, - }, - _64BitAddressWithPvm { - cap_offset: u16, - message_control: u32, - message_address_lo: u32, - message_address_hi: u32, - message_data: u32, - mask_bits: u32, - pending_bits: u32, - }, -} - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -pub struct MsixCapability { - pub cap_offset: u16, - pub a: u32, - pub b: u32, - pub c: u32, -} - #[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] pub struct VendorSpecificCapability { pub data: Vec, } -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -pub enum Capability { - Msi(MsiCapability), - MsiX(MsixCapability), - Vendor(VendorSpecificCapability), - Other(u8), -} - -impl Capability { - pub fn as_msi(&self) -> Option<&MsiCapability> { - match self { - &Self::Msi(ref msi) => Some(msi), - _ => None, - } - } - pub fn as_msix(&self) -> Option<&MsixCapability> { - match self { - &Self::MsiX(ref msix) => Some(msix), - _ => None, - } - } - pub fn as_msi_mut(&mut self) -> Option<&mut MsiCapability> { - match self { - &mut Self::Msi(ref mut msi) => Some(msi), - _ => None, - } - } - pub fn as_msix_mut(&mut self) -> Option<&mut MsixCapability> { - match self { - &mut Self::MsiX(ref mut msix) => Some(msix), - _ => None, - } - } - unsafe fn parse_msi(addr: PciCapabilityAddress, access: &dyn ConfigRegionAccess) -> Self { - Self::Msi(MsiCapability::parse(addr, access)) - } - unsafe fn parse_msix(addr: PciCapabilityAddress, access: &dyn ConfigRegionAccess) -> Self { - Self::MsiX(MsixCapability { - cap_offset: addr.offset, - a: access.read(addr.address, addr.offset), - b: access.read(addr.address, addr.offset + 4), - c: access.read(addr.address, addr.offset + 8), - }) - } - unsafe fn parse_vendor(addr: PciCapabilityAddress, access: &dyn ConfigRegionAccess) -> Self { +impl VendorSpecificCapability { + pub(crate) unsafe fn parse(addr: PciCapabilityAddress, access: &dyn ConfigRegionAccess) -> Self { let dword = access.read(addr.address, addr.offset); let next = (dword >> 8) & 0xFF; let length = ((dword >> 16) & 0xFF) as u16; @@ -168,37 +33,8 @@ impl Capability { log::warn!("Vendor specific capability is invalid"); Vec::new() }; - Self::Vendor(VendorSpecificCapability { + VendorSpecificCapability { data - }) - } - unsafe fn parse(addr: PciCapabilityAddress, access: &dyn ConfigRegionAccess) -> Self { - assert_eq!( - addr.offset & 0xFC, - addr.offset, - "capability must be dword aligned" - ); - - let dword = access.read(addr.address, addr.offset); - let capability_id = (dword & 0xFF) as u8; - - if capability_id == CapabilityId::Msi as u8 { - Self::parse_msi(addr, access) - } else if capability_id == CapabilityId::MsiX as u8 { - Self::parse_msix(addr, access) - } else if capability_id == CapabilityId::Vendor as u8 { - Self::parse_vendor(addr, access) - } else { - if capability_id != CapabilityId::Pcie as u8 - && capability_id != CapabilityId::PwrMgmt as u8 - && capability_id != CapabilityId::Sata as u8 - { - log::warn!( - "unimplemented or malformed capability id: {}", - capability_id - ); - } - Self::Other(capability_id) } } } diff --git a/pcid/src/pci/msi.rs b/pcid/src/pci/msi.rs index 727d36695f..1332f19ce4 100644 --- a/pcid/src/pci/msi.rs +++ b/pcid/src/pci/msi.rs @@ -1,10 +1,7 @@ use std::fmt; use super::bar::PciBar; -pub use super::cap::{MsiCapability, MsixCapability}; -use pci_types::capability::PciCapabilityAddress; -use pci_types::{ConfigRegionAccess, PciAddress}; use serde::{Deserialize, Serialize}; use syscall::{Io, Mmio}; @@ -31,193 +28,6 @@ pub struct MsiInfo { pub has_per_vector_masking: bool, } -impl MsiCapability { - const MC_PVT_CAPABLE_BIT: u16 = 1 << 8; - const MC_64_BIT_ADDR_BIT: u16 = 1 << 7; - - const MC_MULTI_MESSAGE_MASK: u16 = 0x000E; - const MC_MULTI_MESSAGE_SHIFT: u8 = 1; - - const MC_MULTI_MESSAGE_ENABLE_MASK: u16 = 0x0070; - const MC_MULTI_MESSAGE_ENABLE_SHIFT: u8 = 4; - - const MC_MSI_ENABLED_BIT: u16 = 1; - - pub(crate) unsafe fn parse(addr: PciCapabilityAddress, access: &dyn ConfigRegionAccess) -> Self { - let dword = access.read(addr.address, addr.offset); - - let message_control = (dword >> 16) as u16; - - if message_control & Self::MC_PVT_CAPABLE_BIT != 0 { - if message_control & Self::MC_64_BIT_ADDR_BIT != 0 { - Self::_64BitAddressWithPvm { - cap_offset: addr.offset, - message_control: dword, - message_address_lo: access.read(addr.address, addr.offset + 4), - message_address_hi: access.read(addr.address, addr.offset + 8), - message_data: access.read(addr.address, addr.offset + 12), - mask_bits: access.read(addr.address, addr.offset + 16), - pending_bits: access.read(addr.address, addr.offset + 20), - } - } else { - Self::_32BitAddressWithPvm { - cap_offset: addr.offset, - message_control: dword, - message_address: access.read(addr.address, addr.offset + 4), - message_data: access.read(addr.address, addr.offset + 8), - mask_bits: access.read(addr.address, addr.offset + 12), - pending_bits: access.read(addr.address, addr.offset + 16), - } - } - } else { - if message_control & Self::MC_64_BIT_ADDR_BIT != 0 { - Self::_64BitAddress { - cap_offset: addr.offset, - message_control: dword, - message_address_lo: access.read(addr.address, addr.offset + 4), - message_address_hi: access.read(addr.address, addr.offset + 8), - message_data: access.read(addr.address, addr.offset + 12) as u16, - } - } else { - Self::_32BitAddress { - cap_offset: addr.offset, - message_control: dword, - message_address: access.read(addr.address, addr.offset + 4), - message_data: access.read(addr.address, addr.offset + 8) as u16, - } - } - } - } - fn cap_offset(&self) -> u16 { - match *self { - MsiCapability::_32BitAddress { cap_offset, .. } - | MsiCapability::_64BitAddress { cap_offset, .. } - | MsiCapability::_32BitAddressWithPvm { cap_offset, .. } - | MsiCapability::_64BitAddressWithPvm { cap_offset, .. } => u16::from(cap_offset), - } - } - - fn message_control_raw(&self) -> u32 { - match self { - Self::_32BitAddress { message_control, .. } | Self::_64BitAddress { message_control, .. } | Self::_32BitAddressWithPvm { message_control, .. } | Self::_64BitAddressWithPvm { message_control, .. } => *message_control, - } - } - fn message_control(&self) -> u16 { - (self.message_control_raw() >> 16) as u16 - } - pub(crate) fn set_message_control(&mut self, value: u16) { - let mut new_message_control = self.message_control_raw(); - new_message_control &= 0x0000_FFFF; - new_message_control |= u32::from(value) << 16; - - match self { - Self::_32BitAddress { ref mut message_control, .. } - | Self::_64BitAddress { ref mut message_control, .. } - | Self::_32BitAddressWithPvm { ref mut message_control, .. } - | Self::_64BitAddressWithPvm { ref mut message_control, .. } => *message_control = new_message_control, - } - } - pub(crate) unsafe fn write_message_control(&self, addr: PciAddress, access: &dyn ConfigRegionAccess) { - access.write(addr, self.cap_offset(), self.message_control_raw()); - } - pub(crate) fn is_pvt_capable(&self) -> bool { - self.message_control() & Self::MC_PVT_CAPABLE_BIT != 0 - } - pub(crate) fn has_64_bit_addr(&self) -> bool { - self.message_control() & Self::MC_64_BIT_ADDR_BIT != 0 - } - pub(crate) fn set_enabled(&mut self, enabled: bool) { - let mut new_message_control = self.message_control() & (!Self::MC_MSI_ENABLED_BIT); - new_message_control |= u16::from(enabled); - self.set_message_control(new_message_control); - } - pub(crate) fn multi_message_capable(&self) -> u8 { - ((self.message_control() & Self::MC_MULTI_MESSAGE_MASK) >> Self::MC_MULTI_MESSAGE_SHIFT) as u8 - } - pub(crate) fn multi_message_enable(&self) -> u8 { - ((self.message_control() & Self::MC_MULTI_MESSAGE_ENABLE_MASK) >> Self::MC_MULTI_MESSAGE_ENABLE_SHIFT) as u8 - } - pub(crate) fn set_multi_message_enable(&mut self, log_mme: u8) { - let mut new_message_control = self.message_control() & (!Self::MC_MULTI_MESSAGE_ENABLE_MASK); - new_message_control |= u16::from(log_mme) << Self::MC_MULTI_MESSAGE_ENABLE_SHIFT; - self.set_message_control(new_message_control); - } - - fn message_address(&self) -> u32 { - match self { - &Self::_32BitAddress { message_address, .. } | &Self::_32BitAddressWithPvm { message_address, .. } => message_address, - &Self::_64BitAddress { message_address_lo, .. } | &Self::_64BitAddressWithPvm { message_address_lo, .. } => message_address_lo, - } - } - fn message_upper_address(&self) -> Option { - match self { - &Self::_64BitAddress { message_address_hi, .. } | &Self::_64BitAddressWithPvm { message_address_hi, .. } => Some(message_address_hi), - &Self::_32BitAddress { .. } | &Self::_32BitAddressWithPvm { .. } => None, - } - } - pub(crate) fn set_message_address(&mut self, message_address: u32) { - assert_eq!(message_address & 0xFFFF_FFFC, message_address, "unaligned message address (this should already be validated)"); - match self { - &mut Self::_32BitAddress { message_address: ref mut addr, .. } | &mut Self::_32BitAddressWithPvm { message_address: ref mut addr, .. } => *addr = message_address, - &mut Self::_64BitAddress { message_address_lo: ref mut addr, .. } | &mut Self::_64BitAddressWithPvm { message_address_lo: ref mut addr, .. } => *addr = message_address, - } - } - pub(crate) fn set_message_upper_address(&mut self, message_upper_address: u32) -> Option<()> { - match self { - &mut Self::_64BitAddress { ref mut message_address_hi, .. } | &mut Self::_64BitAddressWithPvm { ref mut message_address_hi, .. } => *message_address_hi = message_upper_address, - &mut Self::_32BitAddress { .. } | &mut Self::_32BitAddressWithPvm { .. } => return None, - } - Some(()) - } - pub(crate) fn set_message_data(&mut self, value: u16) { - match self { - &mut Self::_32BitAddress { ref mut message_data, .. } | &mut Self::_64BitAddress { ref mut message_data, .. } => *message_data = value, - &mut Self::_32BitAddressWithPvm { ref mut message_data, .. } | &mut Self::_64BitAddressWithPvm { ref mut message_data, .. } => { - *message_data &= 0xFFFF_0000; - *message_data |= u32::from(value); - } - } - } - pub(crate) fn set_mask_bits(&mut self, mask_bits: u32) -> Option<()> { - match self { - &mut Self::_32BitAddressWithPvm { mask_bits: ref mut bits, .. } | &mut Self::_64BitAddressWithPvm { mask_bits: ref mut bits, .. } => *bits = mask_bits, - &mut Self::_32BitAddress { .. } | &mut Self::_64BitAddress { .. } => return None, - } - Some(()) - } - unsafe fn write_message_address(&self, addr: PciAddress, access: &dyn ConfigRegionAccess) { - access.write(addr, self.cap_offset() + 4, self.message_address()) - } - unsafe fn write_message_upper_address(&self, addr: PciAddress, access: &dyn ConfigRegionAccess) -> Option<()> { - let value = self.message_upper_address()?; - access.write(addr, self.cap_offset() + 8, value); - Some(()) - } - unsafe fn write_message_data(&self, addr: PciAddress, access: &dyn ConfigRegionAccess) { - match self { - &Self::_32BitAddress { cap_offset, message_data, .. } => access.write(addr, u16::from(cap_offset + 8), message_data.into()), - &Self::_32BitAddressWithPvm { cap_offset, message_data, .. } => access.write(addr, u16::from(cap_offset + 8), message_data), - &Self::_64BitAddress { cap_offset, message_data, .. } => access.write(addr, u16::from(cap_offset + 12), message_data.into()), - &Self::_64BitAddressWithPvm { cap_offset, message_data, .. } => access.write(addr, u16::from(cap_offset + 12), message_data), - } - } - unsafe fn write_mask_bits(&self, addr: PciAddress, access: &dyn ConfigRegionAccess) -> Option<()> { - match self { - &Self::_32BitAddressWithPvm { cap_offset, mask_bits, .. } => access.write(addr, u16::from(cap_offset + 12), mask_bits), - &Self::_64BitAddressWithPvm { cap_offset, mask_bits, .. } => access.write(addr, u16::from(cap_offset + 16), mask_bits), - &Self::_32BitAddress { .. } | &Self::_64BitAddress { .. } => return None, - } - Some(()) - } - pub(crate) unsafe fn write_all(&self, addr: PciAddress, access: &dyn ConfigRegionAccess) { - self.write_message_control(addr, access); - self.write_message_address(addr, access); - self.write_message_upper_address(addr, access); - self.write_message_data(addr, access); - self.write_mask_bits(addr, access); - } -} - #[derive(Debug, Serialize, Deserialize)] pub struct MsixInfo { pub table_bar: u8, @@ -268,72 +78,6 @@ impl MsixInfo { } } -impl MsixCapability { - const MC_MSIX_ENABLED_BIT: u16 = 1 << 15; - const MC_MSIX_ENABLED_SHIFT: u8 = 15; - const MC_FUNCTION_MASK_BIT: u16 = 1 << 14; - const MC_FUNCTION_MASK_SHIFT: u8 = 14; - const MC_TABLE_SIZE_MASK: u16 = 0x03FF; - - /// The Message Control field, containing the enabled and function mask bits, as well as the - /// table size. - const fn message_control(&self) -> u16 { - (self.a >> 16) as u16 - } - - pub(crate) fn set_message_control(&mut self, message_control: u16) { - self.a &= 0x0000_FFFF; - self.a |= u32::from(message_control) << 16; - } - /// Returns the MSI-X table size. - pub(crate) const fn table_size(&self) -> u16 { - (self.message_control() & Self::MC_TABLE_SIZE_MASK) + 1 - } - pub(crate) fn set_msix_enabled(&mut self, enabled: bool) { - let mut new_message_control = self.message_control(); - new_message_control &= !(Self::MC_MSIX_ENABLED_BIT); - new_message_control |= u16::from(enabled) << Self::MC_MSIX_ENABLED_SHIFT; - self.set_message_control(new_message_control); - } - - pub(crate) fn set_function_mask(&mut self, function_mask: bool) { - let mut new_message_control = self.message_control(); - new_message_control &= !(Self::MC_FUNCTION_MASK_BIT); - new_message_control |= u16::from(function_mask) << Self::MC_FUNCTION_MASK_SHIFT; - self.set_message_control(new_message_control); - } - const TABLE_OFFSET_MASK: u32 = 0xFFFF_FFF8; - const TABLE_BIR_MASK: u32 = 0x0000_0007; - - /// The table offset is guaranteed to be QWORD aligned (8 bytes). - pub(crate) const fn table_offset(&self) -> u32 { - self.b & Self::TABLE_OFFSET_MASK - } - /// The table BIR, which is used to map the offset to a memory location. - pub(crate) const fn table_bir(&self) -> u8 { - (self.b & Self::TABLE_BIR_MASK) as u8 - } - - const PBA_OFFSET_MASK: u32 = 0xFFFF_FFF8; - const PBA_BIR_MASK: u32 = 0x0000_0007; - - /// The Pending Bit Array offset is guaranteed to be QWORD aligned (8 bytes). - pub(crate) const fn pba_offset(&self) -> u32 { - self.c & Self::PBA_OFFSET_MASK - } - /// The Pending Bit Array BIR, which is used to map the offset to a memory location. - pub(crate) const fn pba_bir(&self) -> u8 { - (self.c & Self::PBA_BIR_MASK) as u8 - } - - - /// Write the first DWORD into configuration space (containing the partially modifiable Message - /// Control field). - pub(crate) unsafe fn write_a(&self, addr: PciAddress, access: &dyn ConfigRegionAccess) { - access.write(addr, u16::from(self.cap_offset), self.a) - } -} - #[repr(packed)] pub struct MsixTableEntry { pub addr_lo: Mmio, diff --git a/pcid/src/pci_header.rs b/pcid/src/pci_header.rs index 52ea3a512e..8bde8369c8 100644 --- a/pcid/src/pci_header.rs +++ b/pcid/src/pci_header.rs @@ -23,7 +23,6 @@ pub struct PciEndpointHeader { shared: SharedPciHeader, subsystem_vendor_id: u16, subsystem_id: u16, - cap_pointer: u16, } #[derive(Clone, Copy, Debug, PartialEq)] @@ -67,15 +66,10 @@ impl PciHeader { HeaderType::Endpoint => { let endpoint_header = EndpointHeader::from_header(header, access).unwrap(); let (subsystem_id, subsystem_vendor_id) = endpoint_header.subsystem(access); - let cap_pointer = endpoint_header - .capability_pointer(access) - .try_into() - .unwrap(); Ok(PciHeader::General(PciEndpointHeader { shared, subsystem_vendor_id, subsystem_id, - cap_pointer, })) } HeaderType::PciPciBridge => { @@ -239,10 +233,6 @@ impl PciEndpointHeader { } bars } - - pub fn cap_pointer(&self) -> u16 { - self.cap_pointer - } } #[cfg(test)]