pcid: Move capability offset into the Capability enum
This makes it easier to move to using pci_types for parsing PCI capabilities.
This commit is contained in:
+24
-26
@@ -14,7 +14,7 @@ use crate::State;
|
||||
|
||||
pub struct DriverHandler {
|
||||
addr: PciAddress,
|
||||
capabilities: Vec<(u8, PciCapability)>,
|
||||
capabilities: Vec<PciCapability>,
|
||||
|
||||
state: Arc<State>,
|
||||
}
|
||||
@@ -23,7 +23,7 @@ impl DriverHandler {
|
||||
pub fn spawn(
|
||||
state: Arc<State>,
|
||||
func: driver_interface::PciFunction,
|
||||
capabilities: Vec<(u8, PciCapability)>,
|
||||
capabilities: Vec<PciCapability>,
|
||||
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::<Vec<_>>(),
|
||||
),
|
||||
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)
|
||||
|
||||
+8
-2
@@ -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<Self::Item> {
|
||||
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)),
|
||||
|
||||
+34
-22
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user