From 123eef963572f07d55a19167c2d4ea41dfd15054 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 9 Jun 2024 21:34:48 +0200 Subject: [PATCH] pcid: Move capability offset into the Capability enum This makes it easier to move to using pci_types for parsing PCI capabilities. --- pcid/src/driver_handler.rs | 50 ++++++++++++++++------------------ pcid/src/pci/cap.rs | 10 +++++-- pcid/src/pci/msi.rs | 56 +++++++++++++++++++++++--------------- 3 files changed, 66 insertions(+), 50 deletions(-) diff --git a/pcid/src/driver_handler.rs b/pcid/src/driver_handler.rs index 60c893dd85..4ecb55a4c7 100644 --- a/pcid/src/driver_handler.rs +++ b/pcid/src/driver_handler.rs @@ -14,7 +14,7 @@ use crate::State; pub struct DriverHandler { addr: PciAddress, - capabilities: Vec<(u8, PciCapability)>, + capabilities: Vec, state: Arc, } @@ -23,7 +23,7 @@ impl DriverHandler { pub fn spawn( state: Arc, func: driver_interface::PciFunction, - capabilities: Vec<(u8, PciCapability)>, + capabilities: Vec, args: &[String], ) { let subdriver_args = driver_interface::SubdriverArguments { func }; @@ -110,14 +110,14 @@ impl DriverHandler { PcidClientRequest::RequestCapabilities => PcidClientResponse::Capabilities( self.capabilities .iter() - .map(|(_, capability)| capability.clone()) + .map(|capability| capability.clone()) .collect::>(), ), PcidClientRequest::RequestConfig => PcidClientResponse::Config(args.clone()), PcidClientRequest::RequestFeatures => PcidClientResponse::AllFeatures( self.capabilities .iter() - .filter_map(|(_, capability)| match capability { + .filter_map(|capability| match capability { PciCapability::Msi(msi) => { Some((PciFeature::Msi, FeatureStatus::enabled(msi.enabled()))) } @@ -131,13 +131,12 @@ impl DriverHandler { ), PcidClientRequest::EnableFeature(feature) => match feature { PciFeature::Msi => { - let (offset, capability): (u8, &mut MsiCapability) = match self + let capability: &mut MsiCapability = match self .capabilities .iter_mut() - .find_map(|&mut (offset, ref mut capability)| { - capability.as_msi_mut().map(|cap| (offset, cap)) - }) { - Some(tuple) => tuple, + .find_map(|capability| capability.as_msi_mut()) + { + Some(capability) => capability, None => { return PcidClientResponse::Error( PcidServerResponseError::NonexistentFeature(feature), @@ -146,18 +145,17 @@ impl DriverHandler { }; unsafe { capability.set_enabled(true); - capability.write_message_control(&func, offset); + capability.write_message_control(&func); } PcidClientResponse::FeatureEnabled(feature) } PciFeature::MsiX => { - let (offset, capability): (u8, &mut MsixCapability) = match self + let capability: &mut MsixCapability = match self .capabilities .iter_mut() - .find_map(|&mut (offset, ref mut capability)| { - capability.as_msix_mut().map(|cap| (offset, cap)) - }) { - Some(tuple) => tuple, + .find_map(|capability| capability.as_msix_mut()) + { + Some(capability) => capability, None => { return PcidClientResponse::Error( PcidServerResponseError::NonexistentFeature(feature), @@ -166,7 +164,7 @@ impl DriverHandler { }; unsafe { capability.set_msix_enabled(true); - capability.write_a(&func, offset); + capability.write_a(&func); } PcidClientResponse::FeatureEnabled(feature) } @@ -177,7 +175,7 @@ impl DriverHandler { PciFeature::Msi => self .capabilities .iter() - .find_map(|(_, capability)| { + .find_map(|capability| { if let PciCapability::Msi(msi) = capability { Some(FeatureStatus::enabled(msi.enabled())) } else { @@ -188,7 +186,7 @@ impl DriverHandler { PciFeature::MsiX => self .capabilities .iter() - .find_map(|(_, capability)| { + .find_map(|capability| { if let PciCapability::MsiX(msix) = capability { Some(FeatureStatus::enabled(msix.msix_enabled())) } else { @@ -205,7 +203,7 @@ impl DriverHandler { if let Some(info) = self .capabilities .iter() - .find_map(|(_, capability)| capability.as_msi()) + .find_map(|capability| capability.as_msi()) { PciFeatureInfo::Msi(*info) } else { @@ -218,7 +216,7 @@ impl DriverHandler { if let Some(info) = self .capabilities .iter() - .find_map(|(_, capability)| capability.as_msix()) + .find_map(|capability| capability.as_msix()) { PciFeatureInfo::MsiX(*info) } else { @@ -231,10 +229,10 @@ impl DriverHandler { ), PcidClientRequest::SetFeatureInfo(info_to_set) => match info_to_set { SetFeatureInfo::Msi(info_to_set) => { - if let Some((offset, info)) = self + if let Some(info) = self .capabilities .iter_mut() - .find_map(|(offset, capability)| Some((*offset, capability.as_msi_mut()?))) + .find_map(|capability| capability.as_msi_mut()) { if let Some(mme) = info_to_set.multi_message_enable { if info.multi_message_capable() < mme || mme > 0b101 { @@ -271,7 +269,7 @@ impl DriverHandler { info.set_mask_bits(mask_bits); } unsafe { - info.write_all(&func, offset); + info.write_all(&func); } PcidClientResponse::SetFeatureInfo(PciFeature::Msi) } else { @@ -281,15 +279,15 @@ impl DriverHandler { } } SetFeatureInfo::MsiX { function_mask } => { - if let Some((offset, info)) = self + if let Some(info) = self .capabilities .iter_mut() - .find_map(|(offset, capability)| Some((*offset, capability.as_msix_mut()?))) + .find_map(|capability| capability.as_msix_mut()) { if let Some(mask) = function_mask { info.set_function_mask(mask); unsafe { - info.write_a(&func, offset); + info.write_a(&func); } } PcidClientResponse::SetFeatureInfo(PciFeature::MsiX) diff --git a/pcid/src/pci/cap.rs b/pcid/src/pci/cap.rs index 21ce506f00..06e1436f5f 100644 --- a/pcid/src/pci/cap.rs +++ b/pcid/src/pci/cap.rs @@ -15,7 +15,7 @@ impl<'a> CapabilitiesIter<'a> { } } impl<'a> Iterator for CapabilitiesIter<'a> { - type Item = (u8, Capability); + type Item = Capability; fn next(&mut self) -> Option { let offset = unsafe { @@ -37,7 +37,7 @@ impl<'a> Iterator for CapabilitiesIter<'a> { Capability::parse(self.func, offset) }; - Some((offset, cap)) + Some(cap) } } @@ -56,17 +56,20 @@ pub enum CapabilityId { #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] pub enum MsiCapability { _32BitAddress { + cap_offset: u8, message_control: u32, message_address: u32, message_data: u16, }, _64BitAddress { + cap_offset: u8, message_control: u32, message_address_lo: u32, message_address_hi: u32, message_data: u16, }, _32BitAddressWithPvm { + cap_offset: u8, message_control: u32, message_address: u32, message_data: u32, @@ -74,6 +77,7 @@ pub enum MsiCapability { pending_bits: u32, }, _64BitAddressWithPvm { + cap_offset: u8, message_control: u32, message_address_lo: u32, message_address_hi: u32, @@ -85,6 +89,7 @@ pub enum MsiCapability { #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] pub struct MsixCapability { + pub cap_offset: u8, pub a: u32, pub b: u32, pub c: u32, @@ -133,6 +138,7 @@ impl Capability { } unsafe fn parse_msix(func: &PciFunc, offset: u8) -> Self { Self::MsiX(MsixCapability { + cap_offset: offset, a: func.read_u32(u16::from(offset)), b: func.read_u32(u16::from(offset + 4)), c: func.read_u32(u16::from(offset + 8)), diff --git a/pcid/src/pci/msi.rs b/pcid/src/pci/msi.rs index 8d6e8f4f83..ce9b35cb9e 100644 --- a/pcid/src/pci/msi.rs +++ b/pcid/src/pci/msi.rs @@ -43,6 +43,7 @@ impl MsiCapability { if message_control & Self::MC_PVT_CAPABLE_BIT != 0 { if message_control & Self::MC_64_BIT_ADDR_BIT != 0 { Self::_64BitAddressWithPvm { + cap_offset: offset, message_control: dword, message_address_lo: func.read_u32(u16::from(offset + 4)), message_address_hi: func.read_u32(u16::from(offset + 8)), @@ -52,6 +53,7 @@ impl MsiCapability { } } else { Self::_32BitAddressWithPvm { + cap_offset: offset, message_control: dword, message_address: func.read_u32(u16::from(offset + 4)), message_data: func.read_u32(u16::from(offset + 8)), @@ -62,6 +64,7 @@ impl MsiCapability { } else { if message_control & Self::MC_64_BIT_ADDR_BIT != 0 { Self::_64BitAddress { + cap_offset: offset, message_control: dword, message_address_lo: func.read_u32(u16::from(offset + 4)), message_address_hi: func.read_u32(u16::from(offset + 8)), @@ -69,6 +72,7 @@ impl MsiCapability { } } else { Self::_32BitAddress { + cap_offset: offset, message_control: dword, message_address: func.read_u32(u16::from(offset + 4)), message_data: func.read_u32(u16::from(offset + 8)) as u16, @@ -76,6 +80,14 @@ impl MsiCapability { } } } + 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 { @@ -97,8 +109,8 @@ impl MsiCapability { | Self::_64BitAddressWithPvm { ref mut message_control, .. } => *message_control = new_message_control, } } - pub unsafe fn write_message_control(&self, func: &PciFunc, offset: u8) { - func.write_u32(u16::from(offset), self.message_control_raw()); + pub unsafe fn write_message_control(&self, func: &PciFunc) { + func.write_u32(self.cap_offset(), self.message_control_raw()); } pub fn is_pvt_capable(&self) -> bool { self.message_control() & Self::MC_PVT_CAPABLE_BIT != 0 @@ -186,36 +198,36 @@ impl MsiCapability { } Some(()) } - pub unsafe fn write_message_address(&self, func: &PciFunc, offset: u8) { - func.write_u32(u16::from(offset) + 4, self.message_address()) + pub unsafe fn write_message_address(&self, func: &PciFunc) { + func.write_u32(self.cap_offset() + 4, self.message_address()) } - pub unsafe fn write_message_upper_address(&self, func: &PciFunc, offset: u8) -> Option<()> { + pub unsafe fn write_message_upper_address(&self, func: &PciFunc) -> Option<()> { let value = self.message_upper_address()?; - func.write_u32(u16::from(offset + 8), value); + func.write_u32(self.cap_offset() + 8, value); Some(()) } - pub unsafe fn write_message_data(&self, func: &PciFunc, offset: u8) { + pub unsafe fn write_message_data(&self, func: &PciFunc) { match self { - &Self::_32BitAddress { message_data, .. } => func.write_u32(u16::from(offset + 8), message_data.into()), - &Self::_32BitAddressWithPvm { message_data, .. } => func.write_u32(u16::from(offset + 8), message_data), - &Self::_64BitAddress { message_data, .. } => func.write_u32(u16::from(offset + 12), message_data.into()), - &Self::_64BitAddressWithPvm { message_data, .. } => func.write_u32(u16::from(offset + 12), message_data), + &Self::_32BitAddress { cap_offset, message_data, .. } => func.write_u32(u16::from(cap_offset + 8), message_data.into()), + &Self::_32BitAddressWithPvm { cap_offset, message_data, .. } => func.write_u32(u16::from(cap_offset + 8), message_data), + &Self::_64BitAddress { cap_offset, message_data, .. } => func.write_u32(u16::from(cap_offset + 12), message_data.into()), + &Self::_64BitAddressWithPvm { cap_offset, message_data, .. } => func.write_u32(u16::from(cap_offset + 12), message_data), } } - pub unsafe fn write_mask_bits(&self, func: &PciFunc, offset: u8) -> Option<()> { + pub unsafe fn write_mask_bits(&self, func: &PciFunc) -> Option<()> { match self { - &Self::_32BitAddressWithPvm { mask_bits, .. } => func.write_u32(u16::from(offset + 12), mask_bits), - &Self::_64BitAddressWithPvm { mask_bits, .. } => func.write_u32(u16::from(offset + 16), mask_bits), + &Self::_32BitAddressWithPvm { cap_offset, mask_bits, .. } => func.write_u32(u16::from(cap_offset + 12), mask_bits), + &Self::_64BitAddressWithPvm { cap_offset, mask_bits, .. } => func.write_u32(u16::from(cap_offset + 16), mask_bits), &Self::_32BitAddress { .. } | &Self::_64BitAddress { .. } => return None, } Some(()) } - pub unsafe fn write_all(&self, func: &PciFunc, offset: u8) { - self.write_message_control(func, offset); - self.write_message_address(func, offset); - self.write_message_upper_address(func, offset); - self.write_message_data(func, offset); - self.write_mask_bits(func, offset); + pub unsafe fn write_all(&self, func: &PciFunc) { + self.write_message_control(func); + self.write_message_address(func); + self.write_message_upper_address(func); + self.write_message_data(func); + self.write_mask_bits(func); } } @@ -329,8 +341,8 @@ impl MsixCapability { /// Write the first DWORD into configuration space (containing the partially modifiable Message /// Control field). - pub unsafe fn write_a(&self, func: &PciFunc, offset: u8) { - func.write_u32(u16::from(offset), self.a) + pub unsafe fn write_a(&self, func: &PciFunc) { + func.write_u32(u16::from(self.cap_offset), self.a) } }