Merge branch 'pcid_cleanup5' into 'master'

Remove PciFunc

See merge request redox-os/drivers!163
This commit is contained in:
Jeremy Soller
2024-06-13 22:40:43 +00:00
7 changed files with 122 additions and 142 deletions
+9 -15
View File
@@ -5,11 +5,10 @@ use std::sync::Arc;
use std::thread;
use log::{error, info};
use pci_types::PciAddress;
use pci_types::{ConfigRegionAccess, PciAddress};
use crate::driver_interface;
use crate::pci::cap::Capability as PciCapability;
use crate::pci::PciFunc;
use crate::State;
pub struct DriverHandler {
@@ -101,11 +100,6 @@ impl DriverHandler {
use crate::pci::cap::{MsiCapability, MsixCapability};
use driver_interface::*;
let func = PciFunc {
pci: &self.state.pcie,
addr: self.addr,
};
match request {
PcidClientRequest::RequestCapabilities => PcidClientResponse::Capabilities(
self.capabilities
@@ -135,7 +129,7 @@ impl DriverHandler {
// active at the same time.
unsafe {
msix_capability.set_msix_enabled(false);
msix_capability.write_a(&func);
msix_capability.write_a(self.addr, &self.state.pcie);
}
}
@@ -153,7 +147,7 @@ impl DriverHandler {
};
unsafe {
capability.set_enabled(true);
capability.write_message_control(&func);
capability.write_message_control(self.addr, &self.state.pcie);
}
PcidClientResponse::FeatureEnabled(feature)
}
@@ -167,7 +161,7 @@ impl DriverHandler {
// active at the same time.
unsafe {
msi_capability.set_enabled(false);
msi_capability.write_message_control(&func);
msi_capability.write_message_control(self.addr, &self.state.pcie);
}
}
@@ -185,7 +179,7 @@ impl DriverHandler {
};
unsafe {
capability.set_msix_enabled(true);
capability.write_a(&func);
capability.write_a(self.addr, &self.state.pcie);
}
PcidClientResponse::FeatureEnabled(feature)
}
@@ -273,7 +267,7 @@ impl DriverHandler {
info.set_mask_bits(mask_bits);
}
unsafe {
info.write_all(&func);
info.write_all(self.addr, &self.state.pcie);
}
PcidClientResponse::SetFeatureInfo(PciFeature::Msi)
} else {
@@ -291,7 +285,7 @@ impl DriverHandler {
if let Some(mask) = function_mask {
info.set_function_mask(mask);
unsafe {
info.write_a(&func);
info.write_a(self.addr, &self.state.pcie);
}
}
PcidClientResponse::SetFeatureInfo(PciFeature::MsiX)
@@ -303,12 +297,12 @@ impl DriverHandler {
}
},
PcidClientRequest::ReadConfig(offset) => {
let value = unsafe { func.read_u32(offset) };
let value = unsafe { self.state.pcie.read(self.addr, offset) };
return PcidClientResponse::ReadConfig(value);
}
PcidClientRequest::WriteConfig(offset, value) => {
unsafe {
func.write_u32(offset, value);
self.state.pcie.write(self.addr, offset, value);
}
return PcidClientResponse::WriteConfig;
}
+9 -6
View File
@@ -4,6 +4,7 @@ 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;
@@ -11,7 +12,6 @@ use structopt::StructOpt;
use crate::cfg_access::Pcie;
use crate::config::Config;
use crate::driver_interface::LegacyInterruptLine;
use crate::pci::PciFunc;
use crate::pci_header::{PciEndpointHeader, PciHeader, PciHeaderError};
mod cfg_access;
@@ -98,11 +98,14 @@ fn handle_parsed_header(state: Arc<State>, config: &Config, header: PciEndpointH
};
let capabilities = if endpoint_header.status(&state.pcie).has_capability_list() {
let func = PciFunc {
pci: &state.pcie,
addr: header.address(),
};
crate::pci::cap::CapabilitiesIter::new(header.cap_pointer(), &func).collect::<Vec<_>>()
crate::pci::cap::CapabilitiesIter::new(
PciCapabilityAddress {
address: header.address(),
offset: header.cap_pointer(),
},
&state.pcie,
)
.collect::<Vec<_>>()
} else {
Vec::new()
};
+58 -41
View File
@@ -1,40 +1,39 @@
use super::func::PciFunc;
use pci_types::capability::PciCapabilityAddress;
use pci_types::ConfigRegionAccess;
use serde::{Serialize, Deserialize};
pub struct CapabilitiesIter<'a> {
offset: u8,
func: &'a PciFunc<'a>,
addr: PciCapabilityAddress,
access: &'a dyn ConfigRegionAccess,
}
impl<'a> CapabilitiesIter<'a> {
pub fn new(offset: u8, func: &'a PciFunc) -> Self {
Self {
offset,
func,
}
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<Self::Item> {
let offset = unsafe {
let addr = unsafe {
// mask RsvdP bits
self.offset = self.offset & 0xFC;
self.addr.offset = self.addr.offset & 0xFC;
if self.offset == 0 { return None };
if self.addr.offset == 0 {
return None;
};
let first_dword = self.func.read_u32(u16::from(self.offset));
let next = ((first_dword >> 8) & 0xFF) as u8;
let first_dword = self.access.read(self.addr.address, self.addr.offset);
let next = ((first_dword >> 8) & 0xFF) as u16;
let offset = self.offset;
self.offset = next;
let addr = self.addr;
self.addr.offset = next;
offset
addr
};
let cap = unsafe {
Capability::parse(self.func, offset)
Capability::parse(addr, self.access)
};
Some(cap)
@@ -56,20 +55,20 @@ pub enum CapabilityId {
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub enum MsiCapability {
_32BitAddress {
cap_offset: u8,
cap_offset: u16,
message_control: u32,
message_address: u32,
message_data: u16,
},
_64BitAddress {
cap_offset: u8,
cap_offset: u16,
message_control: u32,
message_address_lo: u32,
message_address_hi: u32,
message_data: u16,
},
_32BitAddressWithPvm {
cap_offset: u8,
cap_offset: u16,
message_control: u32,
message_address: u32,
message_data: u32,
@@ -77,7 +76,7 @@ pub enum MsiCapability {
pending_bits: u32,
},
_64BitAddressWithPvm {
cap_offset: u8,
cap_offset: u16,
message_control: u32,
message_address_lo: u32,
message_address_hi: u32,
@@ -89,7 +88,7 @@ pub enum MsiCapability {
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub struct MsixCapability {
pub cap_offset: u8,
pub cap_offset: u16,
pub a: u32,
pub b: u32,
pub c: u32,
@@ -133,23 +132,37 @@ impl Capability {
_ => None,
}
}
unsafe fn parse_msi(func: &PciFunc, offset: u8) -> Self {
Self::Msi(MsiCapability::parse(func, offset))
unsafe fn parse_msi(addr: PciCapabilityAddress, access: &dyn ConfigRegionAccess) -> Self {
Self::Msi(MsiCapability::parse(addr, access))
}
unsafe fn parse_msix(func: &PciFunc, offset: u8) -> Self {
unsafe fn parse_msix(addr: PciCapabilityAddress, access: &dyn ConfigRegionAccess) -> 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)),
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(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}");
unsafe fn parse_vendor(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;
log::info!(
"Vendor specific offset: {:#02x} next: {next:#02x} cap len: {length:#02x}",
addr.offset
);
let data = if length > 0 {
let mut raw_data = func.read_range(offset.into(), length.into());
assert!(
length > 3 && length % 4 == 0,
"invalid range length: {}",
length
);
let mut raw_data = {
(addr.offset..addr.offset + length)
.step_by(4)
.flat_map(|offset| access.read(addr.address, offset).to_le_bytes())
.collect::<Vec<u8>>()
};
raw_data.drain(3..).collect()
} else {
log::warn!("Vendor specific capability is invalid");
@@ -159,18 +172,22 @@ impl Capability {
data
})
}
unsafe fn parse(func: &PciFunc, offset: u8) -> Self {
assert_eq!(offset & 0xFC, offset, "capability must be dword aligned");
unsafe fn parse(addr: PciCapabilityAddress, access: &dyn ConfigRegionAccess) -> Self {
assert_eq!(
addr.offset & 0xFC,
addr.offset,
"capability must be dword aligned"
);
let dword = func.read_u32(u16::from(offset));
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(func, offset)
Self::parse_msi(addr, access)
} else if capability_id == CapabilityId::MsiX as u8 {
Self::parse_msix(func, offset)
Self::parse_msix(addr, access)
} else if capability_id == CapabilityId::Vendor as u8 {
Self::parse_vendor(func, offset)
Self::parse_vendor(addr, access)
} else {
if capability_id != CapabilityId::Pcie as u8
&& capability_id != CapabilityId::PwrMgmt as u8
-33
View File
@@ -1,33 +0,0 @@
use pci_types::{ConfigRegionAccess, PciAddress};
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<u8> {
assert!(len > 3 && len % 4 == 0, "invalid range length: {}", len);
(offset..offset + len)
.step_by(4)
.flat_map(|offset| self.read_u32(offset).to_le_bytes())
.collect::<Vec<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 unsafe fn read_u32(&self, offset: u16) -> u32 {
self.pci.read(self.addr, offset)
}
}
impl<'pci> PciFunc<'pci> {
pub unsafe fn write_u32(&self, offset: u16, value: u32) {
self.pci.write(self.addr, offset, value);
}
}
-2
View File
@@ -1,10 +1,8 @@
pub use self::bar::PciBar;
pub use self::func::PciFunc;
pub use self::id::FullDeviceId;
pub use pci_types::PciAddress;
mod bar;
pub mod cap;
pub mod func;
mod id;
pub mod msi;
+44 -43
View File
@@ -2,8 +2,9 @@ use std::fmt;
use super::bar::PciBar;
pub use super::cap::{MsiCapability, MsixCapability};
use super::func::PciFunc;
use pci_types::capability::PciCapabilityAddress;
use pci_types::{ConfigRegionAccess, PciAddress};
use serde::{Deserialize, Serialize};
use syscall::{Io, Mmio};
@@ -42,47 +43,47 @@ impl MsiCapability {
const MC_MSI_ENABLED_BIT: u16 = 1;
pub(crate) unsafe fn parse(func: &PciFunc, offset: u8) -> Self {
let dword = func.read_u32(u16::from(offset));
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: offset,
cap_offset: addr.offset,
message_control: dword,
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)),
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: offset,
cap_offset: addr.offset,
message_control: dword,
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)),
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: offset,
cap_offset: addr.offset,
message_control: dword,
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,
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: offset,
cap_offset: addr.offset,
message_control: dword,
message_address: func.read_u32(u16::from(offset + 4)),
message_data: func.read_u32(u16::from(offset + 8)) as u16,
message_address: access.read(addr.address, addr.offset + 4),
message_data: access.read(addr.address, addr.offset + 8) as u16,
}
}
}
@@ -116,8 +117,8 @@ impl MsiCapability {
| Self::_64BitAddressWithPvm { ref mut message_control, .. } => *message_control = new_message_control,
}
}
pub(crate) unsafe fn write_message_control(&self, func: &PciFunc) {
func.write_u32(self.cap_offset(), self.message_control_raw());
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
@@ -184,36 +185,36 @@ impl MsiCapability {
}
Some(())
}
unsafe fn write_message_address(&self, func: &PciFunc) {
func.write_u32(self.cap_offset() + 4, self.message_address())
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, func: &PciFunc) -> Option<()> {
unsafe fn write_message_upper_address(&self, addr: PciAddress, access: &dyn ConfigRegionAccess) -> Option<()> {
let value = self.message_upper_address()?;
func.write_u32(self.cap_offset() + 8, value);
access.write(addr, self.cap_offset() + 8, value);
Some(())
}
unsafe fn write_message_data(&self, func: &PciFunc) {
unsafe fn write_message_data(&self, addr: PciAddress, access: &dyn ConfigRegionAccess) {
match self {
&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),
&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, func: &PciFunc) -> Option<()> {
unsafe fn write_mask_bits(&self, addr: PciAddress, access: &dyn ConfigRegionAccess) -> Option<()> {
match self {
&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::_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, 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);
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);
}
}
@@ -328,8 +329,8 @@ impl MsixCapability {
/// Write the first DWORD into configuration space (containing the partially modifiable Message
/// Control field).
pub(crate) unsafe fn write_a(&self, func: &PciFunc) {
func.write_u32(u16::from(self.cap_offset), self.a)
pub(crate) unsafe fn write_a(&self, addr: PciAddress, access: &dyn ConfigRegionAccess) {
access.write(addr, u16::from(self.cap_offset), self.a)
}
}
+2 -2
View File
@@ -23,7 +23,7 @@ pub struct PciEndpointHeader {
shared: SharedPciHeader,
subsystem_vendor_id: u16,
subsystem_id: u16,
cap_pointer: u8,
cap_pointer: u16,
}
#[derive(Clone, Copy, Debug, PartialEq)]
@@ -240,7 +240,7 @@ impl PciEndpointHeader {
bars
}
pub fn cap_pointer(&self) -> u8 {
pub fn cap_pointer(&self) -> u16 {
self.cap_pointer
}
}