Merge branch 'pcid_cleanup' into 'master'
More pcid cleanups See merge request redox-os/drivers!158
This commit is contained in:
+17
-59
@@ -5,8 +5,7 @@ use std::process::Command;
|
||||
use std::thread;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use pci_types::device_type::DeviceType;
|
||||
use pci_types::{CommandRegister, ConfigRegionAccess, PciAddress};
|
||||
use pci_types::{CommandRegister, PciAddress};
|
||||
use structopt::StructOpt;
|
||||
use log::{debug, error, info, warn, trace};
|
||||
use redox_log::{OutputBuilder, RedoxLogger};
|
||||
@@ -16,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;
|
||||
@@ -43,18 +41,17 @@ pub struct DriverHandler {
|
||||
|
||||
state: Arc<State>,
|
||||
}
|
||||
fn with_pci_func_raw<T, F: FnOnce(&PciFunc) -> T>(pci: &dyn ConfigRegionAccess, addr: PciAddress, function: F) -> T {
|
||||
let func = PciFunc {
|
||||
pci,
|
||||
addr,
|
||||
};
|
||||
function(&func)
|
||||
}
|
||||
|
||||
impl DriverHandler {
|
||||
fn respond(&mut self, request: driver_interface::PcidClientRequest, args: &driver_interface::SubdriverArguments) -> driver_interface::PcidClientResponse {
|
||||
use driver_interface::*;
|
||||
use crate::pci::cap::{MsiCapability, MsixCapability};
|
||||
|
||||
let func = PciFunc {
|
||||
pci: &self.state.pcie,
|
||||
addr: self.addr,
|
||||
};
|
||||
|
||||
match request {
|
||||
PcidClientRequest::RequestCapabilities => {
|
||||
PcidClientResponse::Capabilities(self.capabilities.iter().map(|(_, capability)| capability.clone()).collect::<Vec<_>>())
|
||||
@@ -76,10 +73,8 @@ impl DriverHandler {
|
||||
None => return PcidClientResponse::Error(PcidServerResponseError::NonexistentFeature(feature)),
|
||||
};
|
||||
unsafe {
|
||||
with_pci_func_raw(&self.state.pcie, self.addr, |func| {
|
||||
capability.set_enabled(true);
|
||||
capability.write_message_control(func, offset);
|
||||
});
|
||||
capability.set_enabled(true);
|
||||
capability.write_message_control(&func, offset);
|
||||
}
|
||||
PcidClientResponse::FeatureEnabled(feature)
|
||||
}
|
||||
@@ -89,10 +84,8 @@ impl DriverHandler {
|
||||
None => return PcidClientResponse::Error(PcidServerResponseError::NonexistentFeature(feature)),
|
||||
};
|
||||
unsafe {
|
||||
with_pci_func_raw(&self.state.pcie, self.addr, |func| {
|
||||
capability.set_msix_enabled(true);
|
||||
capability.write_a(func, offset);
|
||||
});
|
||||
capability.set_msix_enabled(true);
|
||||
capability.write_a(&func, offset);
|
||||
}
|
||||
PcidClientResponse::FeatureEnabled(feature)
|
||||
}
|
||||
@@ -151,9 +144,7 @@ impl DriverHandler {
|
||||
info.set_mask_bits(mask_bits);
|
||||
}
|
||||
unsafe {
|
||||
with_pci_func_raw(&self.state.pcie, self.addr, |func| {
|
||||
info.write_all(func, offset);
|
||||
});
|
||||
info.write_all(&func, offset);
|
||||
}
|
||||
PcidClientResponse::SetFeatureInfo(PciFeature::Msi)
|
||||
} else {
|
||||
@@ -163,9 +154,7 @@ impl DriverHandler {
|
||||
if let Some(mask) = function_mask {
|
||||
info.set_function_mask(mask);
|
||||
unsafe {
|
||||
with_pci_func_raw(&self.state.pcie, self.addr, |func| {
|
||||
info.write_a(func, offset);
|
||||
});
|
||||
info.write_a(&func, offset);
|
||||
}
|
||||
}
|
||||
PcidClientResponse::SetFeatureInfo(PciFeature::MsiX)
|
||||
@@ -174,18 +163,12 @@ impl DriverHandler {
|
||||
}
|
||||
}
|
||||
PcidClientRequest::ReadConfig(offset) => {
|
||||
let value = unsafe {
|
||||
with_pci_func_raw(&self.state.pcie, self.addr, |func| {
|
||||
func.read_u32(offset)
|
||||
})
|
||||
};
|
||||
let value = unsafe { func.read_u32(offset) };
|
||||
return PcidClientResponse::ReadConfig(value);
|
||||
},
|
||||
PcidClientRequest::WriteConfig(offset, value) => {
|
||||
unsafe {
|
||||
with_pci_func_raw(&self.state.pcie, self.addr, |func| {
|
||||
func.write_u32(offset, value);
|
||||
});
|
||||
func.write_u32(offset, value);
|
||||
}
|
||||
return PcidClientResponse::WriteConfig;
|
||||
}
|
||||
@@ -209,31 +192,6 @@ pub struct State {
|
||||
pcie: Pcie,
|
||||
}
|
||||
|
||||
fn print_pci_function(header: &PciHeader) {
|
||||
let mut string = format!("PCI {} {:>04X}:{:>04X} {:>02X}.{:>02X}.{:>02X}.{:>02X} {:?}",
|
||||
header.address(), header.vendor_id(), header.device_id(), header.class(),
|
||||
header.subclass(), header.interface(), header.revision(), header.class());
|
||||
let device_type = DeviceType::from((header.class(), header.subclass()));
|
||||
match device_type {
|
||||
DeviceType::LegacyVgaCompatible => string.push_str(" VGA CTL"),
|
||||
DeviceType::IdeController => string.push_str(" IDE"),
|
||||
DeviceType::SataController => match header.interface() {
|
||||
0 => string.push_str(" SATA VND"),
|
||||
1 => string.push_str(" SATA AHCI"),
|
||||
_ => (),
|
||||
},
|
||||
DeviceType::UsbController => match header.interface() {
|
||||
0x00 => string.push_str(" UHCI"),
|
||||
0x10 => string.push_str(" OHCI"),
|
||||
0x20 => string.push_str(" EHCI"),
|
||||
0x30 => string.push_str(" XHCI"),
|
||||
_ => (),
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
info!("{}", string);
|
||||
}
|
||||
|
||||
fn handle_parsed_header(state: Arc<State>, config: &Config, header: PciEndpointHeader) {
|
||||
for driver in config.drivers.iter() {
|
||||
if !driver.match_function(header.full_device_id()) {
|
||||
@@ -293,7 +251,7 @@ fn handle_parsed_header(state: Arc<State>, config: &Config, header: PciEndpointH
|
||||
pci: &state.pcie,
|
||||
addr: header.address(),
|
||||
};
|
||||
crate::pci::cap::CapabilitiesIter { inner: crate::pci::cap::CapabilityOffsetsIter::new(header.cap_pointer(), &func) }.collect::<Vec<_>>()
|
||||
crate::pci::cap::CapabilitiesIter::new(header.cap_pointer(), &func).collect::<Vec<_>>()
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
@@ -470,7 +428,7 @@ fn main(args: Args) {
|
||||
let func_addr = PciAddress::new(0, bus_num, dev_num, func_num);
|
||||
match PciHeader::from_reader(&state.pcie, func_addr) {
|
||||
Ok(header) => {
|
||||
print_pci_function(&header);
|
||||
info!("{}", header.display());
|
||||
match header {
|
||||
PciHeader::General(endpoint_header) => {
|
||||
handle_parsed_header(Arc::clone(&state), &config, endpoint_header);
|
||||
|
||||
@@ -2,6 +2,8 @@ use std::convert::TryInto;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
// This type is used instead of [pci_types::Bar] in the driver interface as the
|
||||
// latter can't be serialized and is missing the convenience functions of [PciBar].
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum PciBar {
|
||||
None,
|
||||
|
||||
+56
-68
@@ -1,39 +1,43 @@
|
||||
use super::func::ConfigReader;
|
||||
use super::func::PciFunc;
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
pub struct CapabilityOffsetsIter<'a, R> {
|
||||
pub struct CapabilitiesIter<'a> {
|
||||
offset: u8,
|
||||
reader: &'a R,
|
||||
func: &'a PciFunc<'a>,
|
||||
}
|
||||
impl<'a, R> CapabilityOffsetsIter<'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 CapabilityOffsetsIter<'a, R>
|
||||
where
|
||||
R: ConfigReader
|
||||
{
|
||||
type Item = u8;
|
||||
impl<'a> Iterator for CapabilitiesIter<'a> {
|
||||
type Item = (u8, Capability);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
unsafe {
|
||||
let offset = unsafe {
|
||||
// mask RsvdP bits
|
||||
self.offset = self.offset & 0xFC;
|
||||
|
||||
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;
|
||||
self.offset = next;
|
||||
|
||||
Some(offset)
|
||||
}
|
||||
offset
|
||||
};
|
||||
|
||||
let cap = unsafe {
|
||||
Capability::parse(self.func, offset)
|
||||
};
|
||||
|
||||
Some((offset, cap))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,28 +157,28 @@ impl Capability {
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
unsafe fn parse_msi<R: ConfigReader>(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<R: ConfigReader>(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<R: ConfigReader>(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<R: ConfigReader>(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");
|
||||
@@ -184,64 +188,48 @@ impl Capability {
|
||||
data
|
||||
})
|
||||
}
|
||||
unsafe fn parse_pcie<R: ConfigReader>(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<R: ConfigReader>(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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CapabilitiesIter<'a, R> {
|
||||
pub inner: CapabilityOffsetsIter<'a, R>,
|
||||
}
|
||||
|
||||
impl<'a, R> Iterator for CapabilitiesIter<'a, R>
|
||||
where
|
||||
R: ConfigReader
|
||||
{
|
||||
type Item = (u8, Capability);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let offset = self.inner.next()?;
|
||||
Some((offset, unsafe { Capability::parse(self.inner.reader, offset) }))
|
||||
}
|
||||
}
|
||||
|
||||
+11
-18
@@ -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<u8> {
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
+39
-39
@@ -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<R: ConfigReader>(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<W: ConfigWriter>(&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<W: ConfigWriter>(&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<W: ConfigWriter>(&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<W: ConfigWriter>(&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<W: ConfigWriter>(&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<W: ConfigWriter>(&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<W: ConfigWriter>(&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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+43
-10
@@ -1,5 +1,4 @@
|
||||
use std::convert::TryInto;
|
||||
|
||||
use pci_types::device_type::DeviceType;
|
||||
use pci_types::{
|
||||
Bar as TyBar, ConfigRegionAccess, EndpointHeader, HeaderType, PciAddress,
|
||||
PciHeader as TyPciHeader, PciPciBridgeHeader,
|
||||
@@ -33,7 +32,6 @@ pub enum PciHeader {
|
||||
PciToPci {
|
||||
shared: SharedPciHeader,
|
||||
secondary_bus_num: u8,
|
||||
cap_pointer: u8,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -44,12 +42,13 @@ impl PciHeader {
|
||||
access: &impl ConfigRegionAccess,
|
||||
addr: PciAddress,
|
||||
) -> Result<PciHeader, PciHeaderError> {
|
||||
if unsafe { access.read(addr, 0) } == 0xffffffff {
|
||||
let header = TyPciHeader::new(addr);
|
||||
let (vendor_id, device_id) = header.id(access);
|
||||
|
||||
if vendor_id == 0xffff && device_id == 0xffff {
|
||||
return Err(PciHeaderError::NoDevice);
|
||||
}
|
||||
|
||||
let header = TyPciHeader::new(addr);
|
||||
let (vendor_id, device_id) = header.id(access);
|
||||
let (revision, class, subclass, interface) = header.revision_and_class(access);
|
||||
let header_type = header.header_type(access);
|
||||
let shared = SharedPciHeader {
|
||||
@@ -68,7 +67,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 = (unsafe { access.read(addr, 0x34) } & 0xff) as u8;
|
||||
let cap_pointer = endpoint_header
|
||||
.capability_pointer(access)
|
||||
.try_into()
|
||||
.unwrap();
|
||||
Ok(PciHeader::General(PciEndpointHeader {
|
||||
shared,
|
||||
subsystem_vendor_id,
|
||||
@@ -79,11 +81,9 @@ impl PciHeader {
|
||||
HeaderType::PciPciBridge => {
|
||||
let bridge_header = PciPciBridgeHeader::from_header(header, access).unwrap();
|
||||
let secondary_bus_num = bridge_header.secondary_bus_number(access);
|
||||
let cap_pointer = (unsafe { access.read(addr, 0x34) } & 0xff) as u8;
|
||||
Ok(PciHeader::PciToPci {
|
||||
shared,
|
||||
secondary_bus_num,
|
||||
cap_pointer,
|
||||
})
|
||||
}
|
||||
ty => Err(PciHeaderError::UnknownHeaderType(ty)),
|
||||
@@ -149,6 +149,40 @@ impl PciHeader {
|
||||
pub fn class(&self) -> u8 {
|
||||
self.full_device_id().class
|
||||
}
|
||||
|
||||
/// Format a human readable string indicating the address and type of PCI device.
|
||||
pub fn display(&self) -> String {
|
||||
let mut string = format!(
|
||||
"PCI {} {:>04X}:{:>04X} {:>02X}.{:>02X}.{:>02X}.{:>02X} {:?}",
|
||||
self.address(),
|
||||
self.vendor_id(),
|
||||
self.device_id(),
|
||||
self.class(),
|
||||
self.subclass(),
|
||||
self.interface(),
|
||||
self.revision(),
|
||||
self.class()
|
||||
);
|
||||
let device_type = DeviceType::from((self.class(), self.subclass()));
|
||||
match device_type {
|
||||
DeviceType::LegacyVgaCompatible => string.push_str(" VGA CTL"),
|
||||
DeviceType::IdeController => string.push_str(" IDE"),
|
||||
DeviceType::SataController => match self.interface() {
|
||||
0 => string.push_str(" SATA VND"),
|
||||
1 => string.push_str(" SATA AHCI"),
|
||||
_ => (),
|
||||
},
|
||||
DeviceType::UsbController => match self.interface() {
|
||||
0x00 => string.push_str(" UHCI"),
|
||||
0x10 => string.push_str(" OHCI"),
|
||||
0x20 => string.push_str(" EHCI"),
|
||||
0x30 => string.push_str(" XHCI"),
|
||||
_ => (),
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
string
|
||||
}
|
||||
}
|
||||
|
||||
impl PciEndpointHeader {
|
||||
@@ -165,7 +199,6 @@ impl PciEndpointHeader {
|
||||
}
|
||||
|
||||
/// Return the Headers BARs.
|
||||
// FIXME use pci_types::Bar instead
|
||||
pub fn bars(&self, access: &impl ConfigRegionAccess) -> [PciBar; 6] {
|
||||
let endpoint_header = self.endpoint_header(access);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user