diff --git a/pcid/src/main.rs b/pcid/src/main.rs index 18a64f2060..f5d146632f 100644 --- a/pcid/src/main.rs +++ b/pcid/src/main.rs @@ -15,7 +15,6 @@ use crate::config::Config; use crate::driver_interface::LegacyInterruptLine; use crate::pci::PciFunc; use crate::pci::cap::Capability as PciCapability; -use crate::pci::func::{ConfigReader, ConfigWriter}; use crate::pci_header::{PciEndpointHeader, PciHeader, PciHeaderError}; mod cfg_access; diff --git a/pcid/src/pci/cap.rs b/pcid/src/pci/cap.rs index 41e480a71c..729845ef84 100644 --- a/pcid/src/pci/cap.rs +++ b/pcid/src/pci/cap.rs @@ -1,22 +1,20 @@ -use super::func::ConfigReader; +use super::func::PciFunc; + use serde::{Serialize, Deserialize}; -pub struct CapabilitiesIter<'a, R> { +pub struct CapabilitiesIter<'a> { offset: u8, - reader: &'a R, + func: &'a PciFunc<'a>, } -impl<'a, R> CapabilitiesIter<'a, R> { - pub fn new(offset: u8, reader: &'a R) -> Self { +impl<'a> CapabilitiesIter<'a> { + pub fn new(offset: u8, func: &'a PciFunc) -> Self { Self { offset, - reader, + func, } } } -impl<'a, R> Iterator for CapabilitiesIter<'a, R> -where - R: ConfigReader -{ +impl<'a> Iterator for CapabilitiesIter<'a> { type Item = (u8, Capability); fn next(&mut self) -> Option { @@ -26,7 +24,7 @@ where if self.offset == 0 { return None }; - let first_dword = self.reader.read_u32(u16::from(self.offset)); + let first_dword = self.func.read_u32(u16::from(self.offset)); let next = ((first_dword >> 8) & 0xFF) as u8; let offset = self.offset; @@ -36,7 +34,7 @@ where }; let cap = unsafe { - Capability::parse(self.reader, offset) + Capability::parse(self.func, offset) }; Some((offset, cap)) @@ -159,28 +157,28 @@ impl Capability { _ => None, } } - unsafe fn parse_msi(reader: &R, offset: u8) -> Self { - Self::Msi(MsiCapability::parse(reader, offset)) + unsafe fn parse_msi(func: &PciFunc, offset: u8) -> Self { + Self::Msi(MsiCapability::parse(func, offset)) } - unsafe fn parse_msix(reader: &R, offset: u8) -> Self { + unsafe fn parse_msix(func: &PciFunc, offset: u8) -> Self { Self::MsiX(MsixCapability { - a: reader.read_u32(u16::from(offset)), - b: reader.read_u32(u16::from(offset + 4)), - c: reader.read_u32(u16::from(offset + 8)), + a: func.read_u32(u16::from(offset)), + b: func.read_u32(u16::from(offset + 4)), + c: func.read_u32(u16::from(offset + 8)), }) } - unsafe fn parse_pwr(reader: &R, offset: u8) -> Self { + unsafe fn parse_pwr(func: &PciFunc, offset: u8) -> Self { Self::PwrMgmt(PwrMgmtCapability { - a: reader.read_u32(u16::from(offset)), - b: reader.read_u32(u16::from(offset + 4)), + a: func.read_u32(u16::from(offset)), + b: func.read_u32(u16::from(offset + 4)), }) } - unsafe fn parse_vendor(reader: &R, offset: u8) -> Self { - let next = reader.read_u8(u16::from(offset+1)); - let length = reader.read_u8(u16::from(offset+2)); + unsafe fn parse_vendor(func: &PciFunc, offset: u8) -> Self { + let next = func.read_u8(u16::from(offset+1)); + let length = func.read_u8(u16::from(offset+2)); log::info!("Vendor specific offset: {offset:#02x} next: {next:#02x} cap len: {length:#02x}"); let data = if length > 0 { - let mut raw_data = reader.read_range(offset.into(), length.into()); + let mut raw_data = func.read_range(offset.into(), length.into()); raw_data.drain(3..).collect() } else { log::warn!("Vendor specific capability is invalid"); @@ -190,45 +188,45 @@ impl Capability { data }) } - unsafe fn parse_pcie(reader: &R, offset: u8) -> Self { + unsafe fn parse_pcie(func: &PciFunc, offset: u8) -> Self { let offset = u16::from(offset); Self::Pcie(PcieCapability { - pcie_caps: reader.read_u32(offset), - dev_caps: reader.read_u32(offset + 0x04), - dev_sts_ctl: reader.read_u32(offset + 0x08), - link_caps: reader.read_u32(offset + 0x0C), - link_sts_ctl: reader.read_u32(offset + 0x10), - slot_caps: reader.read_u32(offset + 0x14), - slot_sts_ctl: reader.read_u32(offset + 0x18), - root_cap_ctl: reader.read_u32(offset + 0x1C), - root_sts: reader.read_u32(offset + 0x20), - dev_caps2: reader.read_u32(offset + 0x24), - dev_sts_ctl2: reader.read_u32(offset + 0x28), - link_caps2: reader.read_u32(offset + 0x2C), - link_sts_ctl2: reader.read_u32(offset + 0x30), - slot_caps2: reader.read_u32(offset + 0x34), - slot_sts_ctl2: reader.read_u32(offset + 0x38), + pcie_caps: func.read_u32(offset), + dev_caps: func.read_u32(offset + 0x04), + dev_sts_ctl: func.read_u32(offset + 0x08), + link_caps: func.read_u32(offset + 0x0C), + link_sts_ctl: func.read_u32(offset + 0x10), + slot_caps: func.read_u32(offset + 0x14), + slot_sts_ctl: func.read_u32(offset + 0x18), + root_cap_ctl: func.read_u32(offset + 0x1C), + root_sts: func.read_u32(offset + 0x20), + dev_caps2: func.read_u32(offset + 0x24), + dev_sts_ctl2: func.read_u32(offset + 0x28), + link_caps2: func.read_u32(offset + 0x2C), + link_sts_ctl2: func.read_u32(offset + 0x30), + slot_caps2: func.read_u32(offset + 0x34), + slot_sts_ctl2: func.read_u32(offset + 0x38), }) } - unsafe fn parse(reader: &R, offset: u8) -> Self { + unsafe fn parse(func: &PciFunc, offset: u8) -> Self { assert_eq!(offset & 0xFC, offset, "capability must be dword aligned"); - let dword = reader.read_u32(u16::from(offset)); + let dword = func.read_u32(u16::from(offset)); let capability_id = (dword & 0xFF) as u8; if capability_id == CapabilityId::Msi as u8 { - Self::parse_msi(reader, offset) + Self::parse_msi(func, offset) } else if capability_id == CapabilityId::MsiX as u8 { - Self::parse_msix(reader, offset) + Self::parse_msix(func, offset) } else if capability_id == CapabilityId::Pcie as u8 { - Self::parse_pcie(reader, offset) + Self::parse_pcie(func, offset) } else if capability_id == CapabilityId::PwrMgmt as u8{ - Self::parse_pwr(reader, offset) + Self::parse_pwr(func, offset) } else if capability_id == CapabilityId::Vendor as u8 { - Self::parse_vendor(reader, offset) + Self::parse_vendor(func, offset) } else if capability_id == CapabilityId::Sata as u8 { - Self::FunctionSpecific(capability_id, reader.read_range(offset.into(), 8)) + Self::FunctionSpecific(capability_id, func.read_range(offset.into(), 8)) } else { log::warn!("unimplemented or malformed capability id: {}", capability_id); Self::Other(capability_id) diff --git a/pcid/src/pci/func.rs b/pcid/src/pci/func.rs index 7bdabff43d..e94e40818d 100644 --- a/pcid/src/pci/func.rs +++ b/pcid/src/pci/func.rs @@ -1,8 +1,13 @@ use byteorder::{ByteOrder, LittleEndian}; use pci_types::{ConfigRegionAccess, PciAddress}; -pub trait ConfigReader { - unsafe fn read_range(&self, offset: u16, len: u16) -> Vec { +pub struct PciFunc<'pci> { + pub pci: &'pci dyn ConfigRegionAccess, + pub addr: PciAddress, +} + +impl<'pci> PciFunc<'pci> { + pub unsafe fn read_range(&self, offset: u16, len: u16) -> Vec { assert!(len > 3 && len % 4 == 0, "invalid range length: {}", len); let mut ret = Vec::with_capacity(len as usize); let results = (offset..offset + len) @@ -17,32 +22,20 @@ pub trait ConfigReader { ret } - unsafe fn read_u32(&self, offset: u16) -> u32; - - unsafe fn read_u8(&self, offset: u16) -> u8 { + pub unsafe fn read_u8(&self, offset: u16) -> u8 { let dword_offset = (offset / 4) * 4; let dword = self.read_u32(dword_offset); let shift = (offset % 4) * 8; ((dword >> shift) & 0xFF) as u8 } -} -pub trait ConfigWriter { - unsafe fn write_u32(&self, offset: u16, value: u32); -} -pub struct PciFunc<'pci> { - pub pci: &'pci dyn ConfigRegionAccess, - pub addr: PciAddress, -} - -impl<'pci> ConfigReader for PciFunc<'pci> { - unsafe fn read_u32(&self, offset: u16) -> u32 { + pub unsafe fn read_u32(&self, offset: u16) -> u32 { self.pci.read(self.addr, offset) } } -impl<'pci> ConfigWriter for PciFunc<'pci> { - unsafe fn write_u32(&self, offset: u16, value: u32) { +impl<'pci> PciFunc<'pci> { + pub unsafe fn write_u32(&self, offset: u16, value: u32) { self.pci.write(self.addr, offset, value); } } diff --git a/pcid/src/pci/msi.rs b/pcid/src/pci/msi.rs index ce176a1846..8d6e8f4f83 100644 --- a/pcid/src/pci/msi.rs +++ b/pcid/src/pci/msi.rs @@ -2,7 +2,7 @@ use std::fmt; use super::bar::PciBar; pub use super::cap::{MsiCapability, MsixCapability}; -use super::func::{ConfigReader, ConfigWriter}; +use super::func::PciFunc; use serde::{Deserialize, Serialize}; use syscall::{Io, Mmio}; @@ -35,8 +35,8 @@ impl MsiCapability { pub const MC_MSI_ENABLED_BIT: u16 = 1; - pub unsafe fn parse(reader: &R, offset: u8) -> Self { - let dword = reader.read_u32(u16::from(offset)); + pub unsafe fn parse(func: &PciFunc, offset: u8) -> Self { + let dword = func.read_u32(u16::from(offset)); let message_control = (dword >> 16) as u16; @@ -44,34 +44,34 @@ impl MsiCapability { if message_control & Self::MC_64_BIT_ADDR_BIT != 0 { Self::_64BitAddressWithPvm { message_control: dword, - message_address_lo: reader.read_u32(u16::from(offset + 4)), - message_address_hi: reader.read_u32(u16::from(offset + 8)), - message_data: reader.read_u32(u16::from(offset + 12)), - mask_bits: reader.read_u32(u16::from(offset + 16)), - pending_bits: reader.read_u32(u16::from(offset + 20)), + message_address_lo: func.read_u32(u16::from(offset + 4)), + message_address_hi: func.read_u32(u16::from(offset + 8)), + message_data: func.read_u32(u16::from(offset + 12)), + mask_bits: func.read_u32(u16::from(offset + 16)), + pending_bits: func.read_u32(u16::from(offset + 20)), } } else { Self::_32BitAddressWithPvm { message_control: dword, - message_address: reader.read_u32(u16::from(offset + 4)), - message_data: reader.read_u32(u16::from(offset + 8)), - mask_bits: reader.read_u32(u16::from(offset + 12)), - pending_bits: reader.read_u32(u16::from(offset + 16)), + message_address: func.read_u32(u16::from(offset + 4)), + message_data: func.read_u32(u16::from(offset + 8)), + mask_bits: func.read_u32(u16::from(offset + 12)), + pending_bits: func.read_u32(u16::from(offset + 16)), } } } else { if message_control & Self::MC_64_BIT_ADDR_BIT != 0 { Self::_64BitAddress { message_control: dword, - message_address_lo: reader.read_u32(u16::from(offset + 4)), - message_address_hi: reader.read_u32(u16::from(offset + 8)), - message_data: reader.read_u32(u16::from(offset + 12)) as u16, + message_address_lo: func.read_u32(u16::from(offset + 4)), + message_address_hi: func.read_u32(u16::from(offset + 8)), + message_data: func.read_u32(u16::from(offset + 12)) as u16, } } else { Self::_32BitAddress { message_control: dword, - message_address: reader.read_u32(u16::from(offset + 4)), - message_data: reader.read_u32(u16::from(offset + 8)) as u16, + message_address: func.read_u32(u16::from(offset + 4)), + message_data: func.read_u32(u16::from(offset + 8)) as u16, } } } @@ -97,8 +97,8 @@ impl MsiCapability { | Self::_64BitAddressWithPvm { ref mut message_control, .. } => *message_control = new_message_control, } } - pub unsafe fn write_message_control(&self, writer: &W, offset: u8) { - writer.write_u32(u16::from(offset), self.message_control_raw()); + pub unsafe fn write_message_control(&self, func: &PciFunc, offset: u8) { + func.write_u32(u16::from(offset), self.message_control_raw()); } pub fn is_pvt_capable(&self) -> bool { self.message_control() & Self::MC_PVT_CAPABLE_BIT != 0 @@ -186,36 +186,36 @@ impl MsiCapability { } Some(()) } - pub unsafe fn write_message_address(&self, writer: &W, offset: u8) { - writer.write_u32(u16::from(offset) + 4, self.message_address()) + 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_upper_address(&self, writer: &W, offset: u8) -> Option<()> { + pub unsafe fn write_message_upper_address(&self, func: &PciFunc, offset: u8) -> Option<()> { let value = self.message_upper_address()?; - writer.write_u32(u16::from(offset + 8), value); + func.write_u32(u16::from(offset + 8), value); Some(()) } - pub unsafe fn write_message_data(&self, writer: &W, offset: u8) { + pub unsafe fn write_message_data(&self, func: &PciFunc, offset: u8) { match self { - &Self::_32BitAddress { message_data, .. } => writer.write_u32(u16::from(offset + 8), message_data.into()), - &Self::_32BitAddressWithPvm { message_data, .. } => writer.write_u32(u16::from(offset + 8), message_data), - &Self::_64BitAddress { message_data, .. } => writer.write_u32(u16::from(offset + 12), message_data.into()), - &Self::_64BitAddressWithPvm { message_data, .. } => writer.write_u32(u16::from(offset + 12), message_data), + &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), } } - pub unsafe fn write_mask_bits(&self, writer: &W, offset: u8) -> Option<()> { + pub unsafe fn write_mask_bits(&self, func: &PciFunc, offset: u8) -> Option<()> { match self { - &Self::_32BitAddressWithPvm { mask_bits, .. } => writer.write_u32(u16::from(offset + 12), mask_bits), - &Self::_64BitAddressWithPvm { mask_bits, .. } => writer.write_u32(u16::from(offset + 16), mask_bits), + &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::_32BitAddress { .. } | &Self::_64BitAddress { .. } => return None, } Some(()) } - pub unsafe fn write_all(&self, writer: &W, offset: u8) { - self.write_message_control(writer, offset); - self.write_message_address(writer, offset); - self.write_message_upper_address(writer, offset); - self.write_message_data(writer, offset); - self.write_mask_bits(writer, offset); + 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); } } @@ -329,8 +329,8 @@ impl MsixCapability { /// Write the first DWORD into configuration space (containing the partially modifiable Message /// Control field). - pub unsafe fn write_a(&self, writer: &W, offset: u8) { - writer.write_u32(u16::from(offset), self.a) + pub unsafe fn write_a(&self, func: &PciFunc, offset: u8) { + func.write_u32(u16::from(offset), self.a) } }