Merge branch 'centralize_error_handling' into 'master'

Make all pcid_interface methods abort the process on errors

See merge request redox-os/drivers!242
This commit is contained in:
Jeremy Soller
2025-03-02 18:45:17 +00:00
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.