Make all pcid_interface methods abort the process on errors

Effectively the only way to recover from errors in the communication
with pcid is by restarting the driver from scratch possibly after
restarting pcid. As such moving the aborts from individual drivers to
pcid_interface simplifies drivers while at the same time allowing nicer
error messages.
This commit is contained in:
bjorn3
2025-03-02 12:36:35 +01:00
parent e5af02928e
commit e7fe3183b0
23 changed files with 191 additions and 262 deletions
Generated
-1
View File
@@ -971,7 +971,6 @@ dependencies = [
"redox-scheme 0.4.0",
"redox_syscall",
"serde",
"thiserror",
]
[[package]]
+1 -2
View File
@@ -18,8 +18,7 @@ use syscall::{Packet, SchemeBlockMut};
pub mod device;
fn main() {
let pcid_handle =
PciFunctionHandle::connect_default().expect("ac97d: failed to setup channel to pcid");
let pcid_handle = PciFunctionHandle::connect_default();
let pci_config = pcid_handle.config();
let mut name = pci_config.func.name();
+6 -18
View File
@@ -31,19 +31,14 @@ QEMU ICH9 8086:293E
fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> File {
let pci_config = pcid_handle.config();
let all_pci_features = pcid_handle
.fetch_all_features()
.expect("ihdad: failed to fetch pci features");
let all_pci_features = pcid_handle.fetch_all_features();
log::debug!("PCI FEATURES: {:?}", all_pci_features);
let has_msi = all_pci_features.iter().any(|feature| feature.is_msi());
let has_msix = all_pci_features.iter().any(|feature| feature.is_msix());
if has_msi && !has_msix {
let capability = match pcid_handle
.feature_info(PciFeature::Msi)
.expect("ihdad: failed to retrieve the MSI capability structure from pcid")
{
let capability = match pcid_handle.feature_info(PciFeature::Msi) {
PciFeatureInfo::Msi(s) => s,
PciFeatureInfo::MsiX(_) => panic!(),
};
@@ -61,13 +56,9 @@ fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> File {
message_address_and_data: Some(msg_addr_and_data),
mask_bits: None,
};
pcid_handle
.set_feature_info(SetFeatureInfo::Msi(set_feature_info))
.expect("ihdad: failed to set feature info");
pcid_handle.set_feature_info(SetFeatureInfo::Msi(set_feature_info));
pcid_handle
.enable_feature(PciFeature::Msi)
.expect("ihdad: failed to enable MSI");
pcid_handle.enable_feature(PciFeature::Msi);
log::debug!("Enabled MSI");
interrupt_handle
@@ -103,8 +94,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
log::LevelFilter::Info,
);
let mut pcid_handle =
PciFunctionHandle::connect_default().expect("ihdad: failed to setup channel to pcid");
let mut pcid_handle = PciFunctionHandle::connect_default();
let pci_config = pcid_handle.config();
@@ -113,9 +103,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
log::info!(" + IHDA {}", pci_config.func.display());
let address = unsafe { pcid_handle.map_bar(0).expect("ihdad") }
.ptr
.as_ptr() as usize;
let address = unsafe { pcid_handle.map_bar(0) }.ptr.as_ptr() as usize;
//TODO: MSI-X
let mut irq_file = get_int_method(&mut pcid_handle);
+1 -1
View File
@@ -10,5 +10,5 @@ license = "MIT"
[dependencies]
libredox = "0.1.3"
log = "0.4"
redox_syscall = "0.5"
redox_syscall = { version = "0.5", features = ["std"] }
redox-log = "0.1.2"
+1 -2
View File
@@ -17,8 +17,7 @@ mod bga;
mod scheme;
fn main() {
let pcid_handle =
PciFunctionHandle::connect_default().expect("bgad: failed to setup channel to pcid");
let pcid_handle = PciFunctionHandle::connect_default();
let pci_config = pcid_handle.config();
let mut name = pci_config.func.name();
+1 -1
View File
@@ -361,7 +361,7 @@ impl XferToHost2d {
static DEVICE: spin::Once<virtio_core::Device> = spin::Once::new();
fn deamon(deamon: redox_daemon::Daemon) -> anyhow::Result<()> {
let mut pcid_handle = PciFunctionHandle::connect_default()?;
let mut pcid_handle = PciFunctionHandle::connect_default();
// Double check that we have the right device.
//
+2 -6
View File
@@ -8,8 +8,7 @@ use pcid_interface::PciFunctionHandle;
pub mod device;
fn main() {
let mut pcid_handle =
PciFunctionHandle::connect_default().expect("e1000d: failed to setup channel to pcid");
let mut pcid_handle = PciFunctionHandle::connect_default();
let pci_config = pcid_handle.config();
let mut name = pci_config.func.name();
@@ -25,10 +24,7 @@ fn main() {
redox_daemon::Daemon::new(move |daemon| {
let mut irq_file = irq.irq_handle("e1000d");
let address = unsafe { pcid_handle.map_bar(0) }
.expect("e1000d")
.ptr
.as_ptr() as usize;
let address = unsafe { pcid_handle.map_bar(0) }.ptr.as_ptr() as usize;
let device =
unsafe { device::Intel8254x::new(address).expect("e1000d: failed to allocate device") };
+2 -3
View File
@@ -10,8 +10,7 @@ pub mod device;
mod ixgbe;
fn main() {
let mut pcid_handle =
PciFunctionHandle::connect_default().expect("ixgbed: failed to setup channel to pcid");
let mut pcid_handle = PciFunctionHandle::connect_default();
let pci_config = pcid_handle.config();
let mut name = pci_config.func.name();
@@ -27,7 +26,7 @@ fn main() {
redox_daemon::Daemon::new(move |daemon| {
let mut irq_file = irq.irq_handle("ixgbed");
let mapped_bar = unsafe { pcid_handle.map_bar(0) }.expect("ixgbed");
let mapped_bar = unsafe { pcid_handle.map_bar(0) };
let address = mapped_bar.ptr.as_ptr();
let size = mapped_bar.bar_size;
+9 -28
View File
@@ -47,19 +47,14 @@ impl MappedMsixRegs {
fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> File {
let pci_config = pcid_handle.config();
let all_pci_features = pcid_handle
.fetch_all_features()
.expect("rtl8139d: failed to fetch pci features");
let all_pci_features = pcid_handle.fetch_all_features();
log::info!("PCI FEATURES: {:?}", all_pci_features);
let has_msi = all_pci_features.iter().any(|feature| feature.is_msi());
let has_msix = all_pci_features.iter().any(|feature| feature.is_msix());
if has_msi && !has_msix {
let capability = match pcid_handle
.feature_info(PciFeature::Msi)
.expect("rtl8139d: failed to retrieve the MSI capability structure from pcid")
{
let capability = match pcid_handle.feature_info(PciFeature::Msi) {
PciFeatureInfo::Msi(s) => s,
PciFeatureInfo::MsiX(_) => panic!(),
};
@@ -77,27 +72,20 @@ fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> File {
message_address_and_data: Some(msg_addr_and_data),
mask_bits: None,
};
pcid_handle
.set_feature_info(SetFeatureInfo::Msi(set_feature_info))
.expect("rtl8139d: failed to set feature info");
pcid_handle.set_feature_info(SetFeatureInfo::Msi(set_feature_info));
pcid_handle
.enable_feature(PciFeature::Msi)
.expect("rtl8139d: failed to enable MSI");
pcid_handle.enable_feature(PciFeature::Msi);
log::info!("Enabled MSI");
interrupt_handle
} else if has_msix {
let msix_info = match pcid_handle
.feature_info(PciFeature::MsiX)
.expect("rtl8139d: failed to retrieve the MSI-X capability structure from pcid")
{
let msix_info = match pcid_handle.feature_info(PciFeature::MsiX) {
PciFeatureInfo::Msi(_) => panic!(),
PciFeatureInfo::MsiX(s) => s,
};
msix_info.validate(pci_config.func.bars);
let bar_address = unsafe { pcid_handle.map_bar(msix_info.table_bar).expect("rtl8139d") }
let bar_address = unsafe { pcid_handle.map_bar(msix_info.table_bar) }
.ptr
.as_ptr() as usize;
@@ -127,9 +115,7 @@ fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> File {
interrupt_handle
};
pcid_handle
.enable_feature(PciFeature::MsiX)
.expect("rtl8139d: failed to enable MSI-X");
pcid_handle.enable_feature(PciFeature::MsiX);
log::info!("Enabled MSI-X");
method
@@ -161,11 +147,7 @@ fn map_bar(pcid_handle: &mut PciFunctionHandle) -> *mut u8 {
for &barnum in &[2, 1] {
match config.func.bars[usize::from(barnum)] {
pcid_interface::PciBar::Memory32 { .. } | pcid_interface::PciBar::Memory64 { .. } => unsafe {
return pcid_handle
.map_bar(barnum)
.expect("rtl8139d: failed to map address")
.ptr
.as_ptr();
return pcid_handle.map_bar(barnum).ptr.as_ptr();
},
other => log::warn!("BAR {} is {:?} instead of memory BAR", barnum, other),
}
@@ -182,8 +164,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
log::LevelFilter::Info,
);
let mut pcid_handle =
PciFunctionHandle::connect_default().expect("rtl8139d: failed to setup channel to pcid");
let mut pcid_handle = PciFunctionHandle::connect_default();
let pci_config = pcid_handle.config();
+9 -28
View File
@@ -47,19 +47,14 @@ impl MappedMsixRegs {
fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> File {
let pci_config = pcid_handle.config();
let all_pci_features = pcid_handle
.fetch_all_features()
.expect("rtl8168d: failed to fetch pci features");
let all_pci_features = pcid_handle.fetch_all_features();
log::info!("PCI FEATURES: {:?}", all_pci_features);
let has_msi = all_pci_features.iter().any(|feature| feature.is_msi());
let has_msix = all_pci_features.iter().any(|feature| feature.is_msix());
if has_msi && !has_msix {
let capability = match pcid_handle
.feature_info(PciFeature::Msi)
.expect("rtl8168d: failed to retrieve the MSI capability structure from pcid")
{
let capability = match pcid_handle.feature_info(PciFeature::Msi) {
PciFeatureInfo::Msi(s) => s,
PciFeatureInfo::MsiX(_) => panic!(),
};
@@ -77,27 +72,20 @@ fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> File {
message_address_and_data: Some(msg_addr_and_data),
mask_bits: None,
};
pcid_handle
.set_feature_info(SetFeatureInfo::Msi(set_feature_info))
.expect("rtl8168d: failed to set feature info");
pcid_handle.set_feature_info(SetFeatureInfo::Msi(set_feature_info));
pcid_handle
.enable_feature(PciFeature::Msi)
.expect("rtl8168d: failed to enable MSI");
pcid_handle.enable_feature(PciFeature::Msi);
log::info!("Enabled MSI");
interrupt_handle
} else if has_msix {
let msix_info = match pcid_handle
.feature_info(PciFeature::MsiX)
.expect("rtl8168d: failed to retrieve the MSI-X capability structure from pcid")
{
let msix_info = match pcid_handle.feature_info(PciFeature::MsiX) {
PciFeatureInfo::Msi(_) => panic!(),
PciFeatureInfo::MsiX(s) => s,
};
msix_info.validate(pci_config.func.bars);
let bar_address = unsafe { pcid_handle.map_bar(msix_info.table_bar).expect("rtl8168d") }
let bar_address = unsafe { pcid_handle.map_bar(msix_info.table_bar) }
.ptr
.as_ptr() as usize;
@@ -127,9 +115,7 @@ fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> File {
interrupt_handle
};
pcid_handle
.enable_feature(PciFeature::MsiX)
.expect("rtl8168d: failed to enable MSI-X");
pcid_handle.enable_feature(PciFeature::MsiX);
log::info!("Enabled MSI-X");
method
@@ -161,11 +147,7 @@ fn map_bar(pcid_handle: &mut PciFunctionHandle) -> *mut u8 {
for &barnum in &[2, 1] {
match config.func.bars[usize::from(barnum)] {
pcid_interface::PciBar::Memory32 { .. } | pcid_interface::PciBar::Memory64 { .. } => unsafe {
return pcid_handle
.map_bar(barnum)
.expect("rtl8168d: failed to map address")
.ptr
.as_ptr();
return pcid_handle.map_bar(barnum).ptr.as_ptr();
},
other => log::warn!("BAR {} is {:?} instead of memory BAR", barnum, other),
}
@@ -182,8 +164,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
log::LevelFilter::Info,
);
let mut pcid_handle =
PciFunctionHandle::connect_default().expect("rtl8168d: failed to setup channel to pcid");
let mut pcid_handle = PciFunctionHandle::connect_default();
let pci_config = pcid_handle.config();
+1 -1
View File
@@ -28,7 +28,7 @@ static_assertions::const_assert_eq!(core::mem::size_of::<VirtHeader>(), 12);
const MAX_BUFFER_LEN: usize = 65535;
fn deamon(daemon: redox_daemon::Daemon) -> Result<(), Box<dyn std::error::Error>> {
let mut pcid_handle = PciFunctionHandle::connect_default()?;
let mut pcid_handle = PciFunctionHandle::connect_default();
// Double check that we have the right device.
//
+1 -1
View File
@@ -83,7 +83,7 @@ fn main() -> Result<()> {
log::info!("pcid-spawner: spawn {:?}", command);
handle.enable_device()?;
handle.enable_device();
let channel_fd = handle.into_inner_fd();
command.env("PCID_CLIENT_CHANNEL", channel_fd.to_string());
-1
View File
@@ -23,7 +23,6 @@ redox-daemon = "0.1"
redox-scheme = "0.4"
redox_syscall = "0.5.9"
serde = { version = "1", features = ["derive"] }
thiserror = "1"
common = { path = "../common" }
libredox = "0.1.3"
+125 -100
View File
@@ -1,13 +1,12 @@
use std::fmt;
use std::fs::File;
use std::io::prelude::*;
use std::os::fd::{FromRawFd, IntoRawFd, RawFd};
use std::path::Path;
use std::ptr::NonNull;
use std::{env, io};
use std::{fmt, process};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use thiserror::Error;
pub use bar::PciBar;
pub use cap::VendorSpecificCapability;
@@ -186,25 +185,6 @@ pub enum PciFeatureInfo {
MsiX(msi::MsixInfo),
}
#[derive(Debug, Error)]
pub enum PcidClientHandleError {
#[error("i/o error: {0}")]
IoError(#[from] io::Error),
#[error("JSON ser/de error: {0}")]
SerializationError(#[from] bincode::Error),
#[error("environment variable error: {0}")]
EnvError(#[from] env::VarError),
#[error("malformed fd: {0}")]
EnvValidityError(std::num::ParseIntError),
#[error("invalid response: {0:?}")]
InvalidResponse(PcidClientResponse),
}
pub type Result<T, E = PcidClientHandleError> = std::result::Result<T, E>;
// TODO: Remove these "features" and just go strait to the actual thing.
#[derive(Debug, Default, Serialize, Deserialize)]
@@ -286,75 +266,91 @@ pub struct PciFunctionHandle {
mapped_bars: [Option<MappedBar>; 6],
}
#[doc(hidden)]
pub fn send<W: Write, T: Serialize>(w: &mut W, message: &T) -> Result<()> {
fn send<T: Serialize>(w: &mut File, message: &T) {
let mut data = Vec::new();
bincode::serialize_into(&mut data, message)?;
assert_eq!(w.write(&data)?, data.len());
Ok(())
bincode::serialize_into(&mut data, message).expect("couldn't serialize pcid message");
match w.write(&data) {
Ok(len) => assert_eq!(len, data.len()),
Err(err) => {
log::error!("writing pcid request failed: {err}");
process::exit(1);
}
}
}
#[doc(hidden)]
pub fn recv<R: Read, T: DeserializeOwned>(r: &mut R) -> Result<T> {
fn recv<T: DeserializeOwned>(r: &mut File) -> T {
let mut length_bytes = [0u8; 8];
r.read_exact(&mut length_bytes)?;
if let Err(err) = r.read_exact(&mut length_bytes) {
log::error!("reading pcid response length failed: {err}");
process::exit(1);
}
let length = u64::from_le_bytes(length_bytes);
if length > 0x100_000 {
panic!("pcid_interface: buffer too large");
}
let mut data = vec![0u8; length as usize];
r.read_exact(&mut data)?;
if let Err(err) = r.read_exact(&mut data) {
log::error!("reading pcid response failed: {err}");
process::exit(1);
}
Ok(bincode::deserialize_from(&data[..])?)
bincode::deserialize_from(&data[..]).expect("couldn't deserialize pcid message")
}
impl PciFunctionHandle {
pub fn connect_default() -> Result<Self> {
let channel_fd = env::var("PCID_CLIENT_CHANNEL")?
.parse::<RawFd>()
.map_err(PcidClientHandleError::EnvValidityError)?;
pub fn connect_default() -> Self {
let channel_fd = match env::var("PCID_CLIENT_CHANNEL") {
Ok(channel_fd) => channel_fd,
Err(err) => {
log::error!("PCID_CLIENT_CHANNEL invalid: {err}");
process::exit(1);
}
};
let channel_fd = match channel_fd.parse::<RawFd>() {
Ok(channel_fd) => channel_fd,
Err(err) => {
log::error!("PCID_CLIENT_CHANNEL invalid: {err}");
process::exit(1);
}
};
Self::connect_common(channel_fd)
}
pub fn connect_by_path(device_path: &Path) -> Result<Self> {
pub fn connect_by_path(device_path: &Path) -> io::Result<Self> {
let channel_fd = syscall::open(
device_path.join("channel").to_str().unwrap(),
syscall::O_RDWR,
)
.map_err(|err| {
PcidClientHandleError::IoError(io::Error::other(format!(
"failed to open pcid channel: {}",
err
)))
})?;
Self::connect_common(channel_fd as RawFd)
.map_err(|err| io::Error::other(format!("failed to open pcid channel: {}", err)))?;
Ok(Self::connect_common(channel_fd as RawFd))
}
fn connect_common(
channel_fd: i32,
) -> std::result::Result<PciFunctionHandle, PcidClientHandleError> {
fn connect_common(channel_fd: i32) -> PciFunctionHandle {
let mut channel = unsafe { File::from_raw_fd(channel_fd) };
send(&mut channel, &PcidClientRequest::RequestConfig)?;
let config = match recv(&mut channel)? {
send(&mut channel, &PcidClientRequest::RequestConfig);
let config = match recv(&mut channel) {
PcidClientResponse::Config(a) => a,
other => return Err(PcidClientHandleError::InvalidResponse(other)),
other => {
log::error!("received wrong pcid response: {other:?}");
process::exit(1);
}
};
Ok(Self {
Self {
channel,
config,
mapped_bars: [const { None }; 6],
})
}
}
pub fn into_inner_fd(self) -> RawFd {
self.channel.into_raw_fd()
}
fn send(&mut self, req: &PcidClientRequest) -> Result<()> {
fn send(&mut self, req: &PcidClientRequest) {
send(&mut self.channel, req)
}
fn recv(&mut self) -> Result<PcidClientResponse> {
fn recv(&mut self) -> PcidClientResponse {
recv(&mut self.channel)
}
@@ -362,73 +358,97 @@ impl PciFunctionHandle {
self.config.clone()
}
pub fn enable_device(&mut self) -> Result<()> {
self.send(&PcidClientRequest::EnableDevice)?;
match self.recv()? {
PcidClientResponse::EnabledDevice => Ok(()),
other => Err(PcidClientHandleError::InvalidResponse(other)),
pub fn enable_device(&mut self) {
self.send(&PcidClientRequest::EnableDevice);
match self.recv() {
PcidClientResponse::EnabledDevice => {}
other => {
log::error!("received wrong pcid response: {other:?}");
process::exit(1);
}
}
}
pub fn get_vendor_capabilities(&mut self) -> Result<Vec<VendorSpecificCapability>> {
self.send(&PcidClientRequest::RequestVendorCapabilities)?;
match self.recv()? {
PcidClientResponse::VendorCapabilities(a) => Ok(a),
other => Err(PcidClientHandleError::InvalidResponse(other)),
pub fn get_vendor_capabilities(&mut self) -> Vec<VendorSpecificCapability> {
self.send(&PcidClientRequest::RequestVendorCapabilities);
match self.recv() {
PcidClientResponse::VendorCapabilities(a) => a,
other => {
log::error!("received wrong pcid response: {other:?}");
process::exit(1);
}
}
}
// FIXME turn into struct with bool fields
pub fn fetch_all_features(&mut self) -> Result<Vec<PciFeature>> {
self.send(&PcidClientRequest::RequestFeatures)?;
match self.recv()? {
PcidClientResponse::AllFeatures(a) => Ok(a),
other => Err(PcidClientHandleError::InvalidResponse(other)),
pub fn fetch_all_features(&mut self) -> Vec<PciFeature> {
self.send(&PcidClientRequest::RequestFeatures);
match self.recv() {
PcidClientResponse::AllFeatures(a) => a,
other => {
log::error!("received wrong pcid response: {other:?}");
process::exit(1);
}
}
}
pub fn enable_feature(&mut self, feature: PciFeature) -> Result<()> {
self.send(&PcidClientRequest::EnableFeature(feature))?;
match self.recv()? {
PcidClientResponse::FeatureEnabled(feat) if feat == feature => Ok(()),
other => Err(PcidClientHandleError::InvalidResponse(other)),
pub fn enable_feature(&mut self, feature: PciFeature) {
self.send(&PcidClientRequest::EnableFeature(feature));
match self.recv() {
PcidClientResponse::FeatureEnabled(feat) if feat == feature => {}
other => {
log::error!("received wrong pcid response: {other:?}");
process::exit(1);
}
}
}
pub fn feature_info(&mut self, feature: PciFeature) -> Result<PciFeatureInfo> {
self.send(&PcidClientRequest::FeatureInfo(feature))?;
match self.recv()? {
PcidClientResponse::FeatureInfo(feat, info) if feat == feature => Ok(info),
other => Err(PcidClientHandleError::InvalidResponse(other)),
pub fn feature_info(&mut self, feature: PciFeature) -> PciFeatureInfo {
self.send(&PcidClientRequest::FeatureInfo(feature));
match self.recv() {
PcidClientResponse::FeatureInfo(feat, info) if feat == feature => info,
other => {
log::error!("received wrong pcid response: {other:?}");
process::exit(1);
}
}
}
pub fn set_feature_info(&mut self, info: SetFeatureInfo) -> Result<()> {
self.send(&PcidClientRequest::SetFeatureInfo(info))?;
match self.recv()? {
PcidClientResponse::SetFeatureInfo(_) => Ok(()),
other => Err(PcidClientHandleError::InvalidResponse(other)),
pub fn set_feature_info(&mut self, info: SetFeatureInfo) {
self.send(&PcidClientRequest::SetFeatureInfo(info));
match self.recv() {
PcidClientResponse::SetFeatureInfo(_) => {}
other => {
log::error!("received wrong pcid response: {other:?}");
process::exit(1);
}
}
}
pub unsafe fn read_config(&mut self, offset: u16) -> Result<u32> {
self.send(&PcidClientRequest::ReadConfig(offset))?;
match self.recv()? {
PcidClientResponse::ReadConfig(value) => Ok(value),
other => Err(PcidClientHandleError::InvalidResponse(other)),
pub unsafe fn read_config(&mut self, offset: u16) -> u32 {
self.send(&PcidClientRequest::ReadConfig(offset));
match self.recv() {
PcidClientResponse::ReadConfig(value) => value,
other => {
log::error!("received wrong pcid response: {other:?}");
process::exit(1);
}
}
}
pub unsafe fn write_config(&mut self, offset: u16, value: u32) -> Result<()> {
self.send(&PcidClientRequest::WriteConfig(offset, value))?;
match self.recv()? {
PcidClientResponse::WriteConfig => Ok(()),
other => Err(PcidClientHandleError::InvalidResponse(other)),
pub unsafe fn write_config(&mut self, offset: u16, value: u32) {
self.send(&PcidClientRequest::WriteConfig(offset, value));
match self.recv() {
PcidClientResponse::WriteConfig => {}
other => {
log::error!("received wrong pcid response: {other:?}");
process::exit(1);
}
}
}
pub unsafe fn map_bar(&mut self, bir: u8) -> Result<&MappedBar> {
pub unsafe fn map_bar(&mut self, bir: u8) -> &MappedBar {
let mapped_bar = &mut self.mapped_bars[bir as usize];
if let Some(mapped_bar) = mapped_bar {
Ok(mapped_bar)
mapped_bar
} else {
let (bar, bar_size) = self.config.func.bars[bir as usize].expect_mem();
let ptr = unsafe {
let ptr = match unsafe {
common::physmap(
bar,
bar_size,
@@ -436,13 +456,18 @@ impl PciFunctionHandle {
// FIXME once the kernel supports this use write-through for prefetchable BAR
common::MemoryType::Uncacheable,
)
}
.map_err(|err| io::Error::other(format!("failed to map BAR at {bar:016X}: {err}")))?;
} {
Ok(ptr) => ptr,
Err(err) => {
log::error!("failed to map BAR at {bar:016X}: {err}");
process::exit(1);
}
};
Ok(mapped_bar.insert(MappedBar {
mapped_bar.insert(MappedBar {
ptr: NonNull::new(ptr.cast::<u8>()).expect("Mapping a BAR resulted in a nullptr"),
bar_size,
}))
})
}
}
}
+2 -5
View File
@@ -25,8 +25,7 @@ fn main() {
}
fn daemon(daemon: redox_daemon::Daemon) -> ! {
let mut pcid_handle =
PciFunctionHandle::connect_default().expect("ahcid: failed to setup channel to pcid");
let mut pcid_handle = PciFunctionHandle::connect_default();
let pci_config = pcid_handle.config();
let mut name = pci_config.func.name();
@@ -47,9 +46,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
info!(" + AHCI {}", pci_config.func.display());
let address = unsafe { pcid_handle.map_bar(5).expect("ahcid") }
.ptr
.as_ptr() as usize;
let address = unsafe { pcid_handle.map_bar(5) }.ptr.as_ptr() as usize;
{
let scheme_name = format!("disk.{}", name);
let socket = Socket::nonblock(&scheme_name).expect("ahcid: failed to create disk scheme");
+1 -2
View File
@@ -28,8 +28,7 @@ fn main() {
}
fn daemon(daemon: redox_daemon::Daemon) -> ! {
let pcid_handle =
PciFunctionHandle::connect_default().expect("ided: failed to setup channel to pcid");
let pcid_handle = PciFunctionHandle::connect_default();
let pci_config = pcid_handle.config();
+13 -16
View File
@@ -26,7 +26,7 @@ fn get_int_method(
log::trace!("Begin get_int_method");
use pcid_interface::irq_helpers;
let features = pcid_handle.fetch_all_features().unwrap();
let features = pcid_handle.fetch_all_features();
let has_msi = features.iter().any(|feature| feature.is_msi());
let has_msix = features.iter().any(|feature| feature.is_msix());
@@ -37,13 +37,13 @@ fn get_int_method(
use self::nvme::MappedMsixRegs;
use pcid_interface::msi::MsixTableEntry;
let msix_info = match pcid_handle.feature_info(PciFeature::MsiX).unwrap() {
let msix_info = match pcid_handle.feature_info(PciFeature::MsiX) {
PciFeatureInfo::MsiX(msix) => msix,
_ => unreachable!(),
};
msix_info.validate(function.bars);
fn bar_base(pcid_handle: &mut PciFunctionHandle, bir: u8) -> Result<NonNull<u8>> {
Ok(unsafe { pcid_handle.map_bar(bir) }.expect("nvmed").ptr)
Ok(unsafe { pcid_handle.map_bar(bir) }.ptr)
}
let table_bar_base: *mut u8 = bar_base(pcid_handle, msix_info.table_bar)?.as_ptr();
let table_base = unsafe { table_bar_base.offset(msix_info.table_offset as isize) };
@@ -59,7 +59,7 @@ fn get_int_method(
table_entry.mask();
}
pcid_handle.enable_feature(PciFeature::MsiX).unwrap();
pcid_handle.enable_feature(PciFeature::MsiX);
let (msix_vector_number, irq_handle) = {
let entry: &mut MsixTableEntry = &mut table_entries[0];
@@ -84,7 +84,7 @@ fn get_int_method(
Ok((interrupt_method, interrupt_sources))
} else if has_msi {
// Message signaled interrupts.
let msi_info = match pcid_handle.feature_info(PciFeature::Msi).unwrap() {
let msi_info = match pcid_handle.feature_info(PciFeature::Msi) {
PciFeatureInfo::Msi(msi) => msi,
_ => unreachable!(),
};
@@ -97,13 +97,11 @@ fn get_int_method(
let (msg_addr_and_data, irq_handle) =
irq_helpers::allocate_single_interrupt_vector_for_msi(bsp_cpu_id);
pcid_handle
.set_feature_info(SetFeatureInfo::Msi(MsiSetFeatureInfo {
message_address_and_data: Some(msg_addr_and_data),
multi_message_enable: Some(0), // enable 2^0=1 vectors
mask_bits: None,
}))
.unwrap();
pcid_handle.set_feature_info(SetFeatureInfo::Msi(MsiSetFeatureInfo {
message_address_and_data: Some(msg_addr_and_data),
multi_message_enable: Some(0), // enable 2^0=1 vectors
mask_bits: None,
}));
(0, irq_handle)
};
@@ -115,7 +113,7 @@ fn get_int_method(
let interrupt_sources =
InterruptSources::Msi(std::iter::once((msi_vector_number, irq_handle)).collect());
pcid_handle.enable_feature(PciFeature::Msi).unwrap();
pcid_handle.enable_feature(PciFeature::Msi);
Ok((interrupt_method, interrupt_sources))
} else if let Some(irq) = function.legacy_interrupt_line {
@@ -146,8 +144,7 @@ fn main() {
redox_daemon::Daemon::new(daemon).expect("nvmed: failed to daemonize");
}
fn daemon(daemon: redox_daemon::Daemon) -> ! {
let mut pcid_handle =
PciFunctionHandle::connect_default().expect("nvmed: failed to setup channel to pcid");
let mut pcid_handle = PciFunctionHandle::connect_default();
let pci_config = pcid_handle.config();
let scheme_name = format!("disk.{}-nvme", pci_config.func.name());
@@ -162,7 +159,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
log::debug!("NVME PCI CONFIG: {:?}", pci_config);
let address = unsafe { pcid_handle.map_bar(0).expect("nvmed").ptr };
let address = unsafe { pcid_handle.map_bar(0).ptr };
let socket = Socket::create(&scheme_name).expect("nvmed: failed to create disk scheme");
+1 -1
View File
@@ -107,7 +107,7 @@ pub struct BlockVirtRequest {
const_assert_eq!(core::mem::size_of::<BlockVirtRequest>(), 16);
fn deamon(deamon: redox_daemon::Daemon) -> anyhow::Result<()> {
let mut pcid_handle = PciFunctionHandle::connect_default()?;
let mut pcid_handle = PciFunctionHandle::connect_default();
// Double check that we have the right device.
//
+2 -6
View File
@@ -191,8 +191,7 @@ impl VboxGuestInfo {
}
fn main() {
let mut pcid_handle =
PciFunctionHandle::connect_default().expect("vboxd: failed to setup channel to pcid");
let mut pcid_handle = PciFunctionHandle::connect_default();
let pci_config = pcid_handle.config();
let mut name = pci_config.func.name();
@@ -237,10 +236,7 @@ fn main() {
let mut irq_file = irq.irq_handle("vboxd");
let mut port = Pio::<u32>::new(bar0 as u16);
let address = unsafe { pcid_handle.map_bar(1) }
.expect("vboxd")
.ptr
.as_ptr();
let address = unsafe { pcid_handle.map_bar(1) }.ptr.as_ptr();
{
let vmmdev = unsafe { &mut *(address as *mut VboxVmmDev) };
+3 -3
View File
@@ -12,13 +12,13 @@ pub fn enable_msix(pcid_handle: &mut PciFunctionHandle) -> Result<File, Error> {
let pci_config = pcid_handle.config();
// Extended message signaled interrupts.
let msix_info = match pcid_handle.feature_info(PciFeature::MsiX)? {
let msix_info = match pcid_handle.feature_info(PciFeature::MsiX) {
PciFeatureInfo::MsiX(capability) => capability,
_ => unreachable!(),
};
msix_info.validate(pci_config.func.bars);
let bar_address = unsafe { pcid_handle.map_bar(msix_info.table_bar)? }
let bar_address = unsafe { pcid_handle.map_bar(msix_info.table_bar) }
.ptr
.as_ptr() as usize;
let virt_table_base = (bar_address + msix_info.table_offset as usize) as *mut MsixTableEntry;
@@ -43,7 +43,7 @@ pub fn enable_msix(pcid_handle: &mut PciFunctionHandle) -> Result<File, Error> {
interrupt_handle
};
pcid_handle.enable_feature(PciFeature::MsiX)?;
pcid_handle.enable_feature(PciFeature::MsiX);
log::info!("virtio: using MSI-X (interrupt_handle={interrupt_handle:?})");
Ok(interrupt_handle)
+2 -2
View File
@@ -66,7 +66,7 @@ pub fn probe_device(pcid_handle: &mut PciFunctionHandle) -> Result<Device, Error
let mut notify_addr = None;
let mut device_addr = None;
for raw_capability in pcid_handle.get_vendor_capabilities()? {
for raw_capability in pcid_handle.get_vendor_capabilities() {
// SAFETY: We have verified that the length of the data is correct.
let capability = unsafe { &*(raw_capability.data.as_ptr() as *const PciCapability) };
@@ -147,7 +147,7 @@ pub fn probe_device(pcid_handle: &mut PciFunctionHandle) -> Result<Device, Error
);
// Setup interrupts.
let all_pci_features = pcid_handle.fetch_all_features()?;
let all_pci_features = pcid_handle.fetch_all_features();
let has_msix = all_pci_features.iter().any(|feature| feature.is_msix());
// According to the virtio specification, the device REQUIRED to support MSI-X.
-8
View File
@@ -17,18 +17,10 @@ use std::task::{Poll, Waker};
pub enum Error {
#[error("syscall failed")]
SyscallError(#[from] libredox::error::Error),
#[error("pcid client handle error")]
PcidClientHandle(pcid_interface::PcidClientHandleError),
#[error("the device is incapable of {0:?}")]
InCapable(CfgType),
}
impl From<pcid_interface::PcidClientHandleError> for Error {
fn from(value: pcid_interface::PcidClientHandleError) -> Self {
Self::PcidClientHandle(value)
}
}
/// Returns the queue part sizes in bytes.
///
/// ## Reference
+8 -26
View File
@@ -62,19 +62,14 @@ fn get_int_method(
) -> (Option<File>, InterruptMethod) {
let pci_config = pcid_handle.config();
let all_pci_features = pcid_handle
.fetch_all_features()
.expect("xhcid: failed to fetch pci features");
let all_pci_features = pcid_handle.fetch_all_features();
log::debug!("XHCI PCI FEATURES: {:?}", all_pci_features);
let has_msi = all_pci_features.iter().any(|feature| feature.is_msi());
let has_msix = all_pci_features.iter().any(|feature| feature.is_msix());
if has_msi && !has_msix {
let mut capability = match pcid_handle
.feature_info(PciFeature::Msi)
.expect("xhcid: failed to retrieve the MSI capability structure from pcid")
{
let mut capability = match pcid_handle.feature_info(PciFeature::Msi) {
PciFeatureInfo::Msi(s) => s,
PciFeatureInfo::MsiX(_) => panic!(),
};
@@ -92,21 +87,14 @@ fn get_int_method(
message_address_and_data: Some(msg_addr_and_data),
mask_bits: None,
};
pcid_handle
.set_feature_info(SetFeatureInfo::Msi(set_feature_info))
.expect("xhcid: failed to set feature info");
pcid_handle.set_feature_info(SetFeatureInfo::Msi(set_feature_info));
pcid_handle
.enable_feature(PciFeature::Msi)
.expect("xhcid: failed to enable MSI");
pcid_handle.enable_feature(PciFeature::Msi);
log::debug!("Enabled MSI");
(Some(interrupt_handle), InterruptMethod::Msi)
} else if has_msix {
let msix_info = match pcid_handle
.feature_info(PciFeature::MsiX)
.expect("xhcid: failed to retrieve the MSI-X capability structure from pcid")
{
let msix_info = match pcid_handle.feature_info(PciFeature::MsiX) {
PciFeatureInfo::Msi(_) => panic!(),
PciFeatureInfo::MsiX(s) => s,
};
@@ -142,9 +130,7 @@ fn get_int_method(
)
};
pcid_handle
.enable_feature(PciFeature::MsiX)
.expect("xhcid: failed to enable MSI-X");
pcid_handle.enable_feature(PciFeature::MsiX);
log::debug!("Enabled MSI-X");
method
@@ -181,8 +167,7 @@ fn main() {
}
fn daemon(daemon: redox_daemon::Daemon) -> ! {
let mut pcid_handle =
PciFunctionHandle::connect_default().expect("xhcid: failed to setup channel to pcid");
let mut pcid_handle = PciFunctionHandle::connect_default();
let pci_config = pcid_handle.config();
let mut name = pci_config.func.name();
@@ -198,10 +183,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
log::debug!("XHCI PCI CONFIG: {:?}", pci_config);
let address = unsafe { pcid_handle.map_bar(0) }
.expect("xhcid")
.ptr
.as_ptr() as usize;
let address = unsafe { pcid_handle.map_bar(0) }.ptr.as_ptr() as usize;
let (irq_file, interrupt_method) = (None, InterruptMethod::Polling); //get_int_method(&mut pcid_handle, address);
//TODO: Fix interrupts.