Merge branch 'pci_use_pci_types' into 'master'

Start using the pci_types crate

See merge request redox-os/drivers!135
This commit is contained in:
Jeremy Soller
2024-01-22 16:12:54 +00:00
27 changed files with 538 additions and 951 deletions
Generated
+17 -6
View File
@@ -196,9 +196,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.4.0"
version = "2.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
[[package]]
name = "bitvec"
@@ -527,7 +527,7 @@ version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8283e7331b8c93b9756e0cfdbcfb90312852f953c6faf9bf741e684cc3b6ad69"
dependencies = [
"bitflags 2.4.0",
"bitflags 2.4.2",
"crc",
"log",
"uuid",
@@ -698,7 +698,7 @@ version = "0.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8"
dependencies = [
"bitflags 2.4.0",
"bitflags 2.4.2",
"libc",
"redox_syscall 0.4.1",
]
@@ -956,6 +956,16 @@ dependencies = [
"winapi",
]
[[package]]
name = "pci_types"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "831e5bebf010674bc2e8070b892948120d4c453c71f37387e1ffea5636620dbe"
dependencies = [
"bit_field",
"bitflags 2.4.2",
]
[[package]]
name = "pcid"
version = "0.1.0"
@@ -968,6 +978,7 @@ dependencies = [
"libc",
"log",
"paw",
"pci_types",
"plain",
"redox-log",
"redox_syscall 0.4.1",
@@ -1151,7 +1162,7 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "475e252d7add4825405d2248d530d33e22364ac5477eab816b56efbeec1e2712"
dependencies = [
"bitflags 2.4.0",
"bitflags 2.4.2",
"libredox",
"redox_syscall 0.4.1",
]
@@ -1727,7 +1738,7 @@ dependencies = [
name = "virtio-core"
version = "0.1.0"
dependencies = [
"bitflags 2.4.0",
"bitflags 2.4.2",
"common",
"crossbeam-queue",
"futures",
+2 -9
View File
@@ -73,15 +73,8 @@ fn main() {
let mut name = pci_config.func.name();
name.push_str("_ac97");
let bar0 = match pci_config.func.bars[0] {
PciBar::Port(port) => port,
_ => unreachable!(),
};
let bar1 = match pci_config.func.bars[1] {
PciBar::Port(port) => port,
_ => unreachable!(),
};
let bar0 = pci_config.func.bars[0].expect_port();
let bar1 = pci_config.func.bars[1].expect_port();
let irq = pci_config.func.legacy_interrupt_line;
+3 -8
View File
@@ -9,7 +9,7 @@ use std::io::{ErrorKind, Read, Write};
use std::os::unix::io::{FromRawFd, RawFd};
use std::usize;
use pcid_interface::{PciBar, PcidServerHandle};
use pcid_interface::PcidServerHandle;
use syscall::error::{Error, ENODEV};
use syscall::data::{Event, Packet};
use syscall::flag::EVENT_READ;
@@ -81,12 +81,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
let mut name = pci_config.func.name();
name.push_str("_ahci");
let bar = match pci_config.func.bars[5] {
PciBar::Memory32(addr) => addr as usize,
PciBar::Memory64(addr) => addr as usize,
PciBar::None | PciBar::Port(_) => unreachable!(),
};
let bar_size = pci_config.func.bar_sizes[5];
let (bar, bar_size) = pci_config.func.bars[5].expect_mem();
let irq = pci_config.func.legacy_interrupt_line;
@@ -97,7 +92,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
let address = unsafe {
common::physmap(
bar,
bar_size as usize,
bar_size,
common::Prot { read: true, write: true },
common::MemoryType::Uncacheable,
).expect("ahcid: failed to map address")
+2 -7
View File
@@ -10,7 +10,7 @@ use std::process;
use std::sync::Arc;
use event::EventQueue;
use pcid_interface::{PciBar, PcidServerHandle};
use pcid_interface::PcidServerHandle;
use syscall::{EventFlags, Packet, SchemeBlockMut};
pub mod device;
@@ -68,12 +68,7 @@ fn main() {
let mut name = pci_config.func.name();
name.push_str("_e1000");
let bar = match pci_config.func.bars[0] {
PciBar::Memory32(addr) => addr as usize,
PciBar::Memory64(addr) => addr as usize,
PciBar::None | PciBar::Port(_) => unreachable!(),
};
let bar_size = pci_config.func.bar_sizes[0] as usize;
let (bar, bar_size) = pci_config.func.bars[0].expect_mem();
let irq = pci_config.func.legacy_interrupt_line;
+1 -4
View File
@@ -86,10 +86,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
info!("IDE PCI CONFIG: {:?}", pci_config);
let busmaster_base = match pci_config.func.bars[4] {
PciBar::Port(port) => port,
other => panic!("TODO: IDE busmaster BAR {:#x?}", other),
};
let busmaster_base = pci_config.func.bars[4].expect_port();
let (primary, primary_irq) = if pci_config.func.full_device_id.interface & 1 != 0 {
panic!("TODO: IDE primary channel is PCI native");
} else {
+2 -14
View File
@@ -160,24 +160,12 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
let mut name = pci_config.func.name();
name.push_str("_ihda");
let bar = pci_config.func.bars[0];
let bar_size = pci_config.func.bar_sizes[0];
let bar_ptr = match bar {
pcid_interface::PciBar::Memory32(ptr) => match ptr {
0 => panic!("BAR 0 is mapped to address 0"),
_ => ptr as u64,
},
pcid_interface::PciBar::Memory64(ptr) => match ptr {
0 => panic!("BAR 0 is mapped to address 0"),
_ => ptr,
},
other => panic!("Expected memory bar, found {:?}", other),
};
let (bar_ptr, bar_size) = pci_config.func.bars[0].expect_mem();
log::info!(" + IHDA {} on: {:#X} size: {}", name, bar_ptr, bar_size);
let address = unsafe {
common::physmap(bar_ptr as usize, bar_size as usize, common::Prot::RW, common::MemoryType::Uncacheable)
common::physmap(bar_ptr, bar_size, common::Prot::RW, common::MemoryType::Uncacheable)
.expect("ihdad: failed to map address") as usize
};
+2 -6
View File
@@ -13,7 +13,7 @@ use std::sync::Arc;
use std::thread;
use event::EventQueue;
use pcid_interface::{PciBar, PcidServerHandle};
use pcid_interface::PcidServerHandle;
use std::time::Duration;
use syscall::{EventFlags, Packet, SchemeBlockMut};
@@ -76,11 +76,7 @@ fn main() {
let mut name = pci_config.func.name();
name.push_str("_ixgbe");
let bar = match pci_config.func.bars[0] {
PciBar::Memory32(addr) => addr as usize,
PciBar::Memory64(addr) => addr as usize,
PciBar::None | PciBar::Port(_) => unreachable!(),
};
let (bar, _) = pci_config.func.bars[0].expect_mem();
let irq = pci_config.func.legacy_interrupt_line;
+8 -30
View File
@@ -9,7 +9,7 @@ use std::ptr::NonNull;
use std::sync::{Arc, Mutex};
use std::{slice, usize};
use pcid_interface::{PciBar, PciFeature, PciFeatureInfo, PciFunction, PcidServerHandle};
use pcid_interface::{PciFeature, PciFeatureInfo, PciFunction, PcidServerHandle};
use syscall::{
Event, Mmio, Packet, Result, SchemeBlockMut,
PAGE_SIZE,
@@ -93,20 +93,9 @@ fn get_int_method(
match &mut *bar_guard {
&mut Some(ref bar) => Ok(bar.ptr),
bar_to_set @ &mut None => {
let bar = match function.bars[bir] {
PciBar::Memory32(addr) => match addr {
0 => panic!("BAR {} is mapped to address 0", bir),
_ => addr as u64,
},
PciBar::Memory64(addr) => match addr {
0 => panic!("BAR {} is mapped to address 0", bir),
_ => addr,
},
other => panic!("Expected memory BAR, found {:?}", other),
};
let bar_size = function.bar_sizes[bir];
let (bar, bar_size) = function.bars[bir].expect_mem();
let bar = Bar::allocate(bar as usize, bar_size as usize)?;
let bar = Bar::allocate(bar, bar_size)?;
*bar_to_set = Some(bar);
Ok(bar_to_set.as_ref().unwrap().ptr)
}
@@ -303,18 +292,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
let _logger_ref = setup_logging(&scheme_name);
let bar = match pci_config.func.bars[0] {
PciBar::Memory32(mem) => match mem {
0 => panic!("BAR 0 is mapped to address 0"),
_ => mem as u64,
},
PciBar::Memory64(mem) => match mem {
0 => panic!("BAR 0 is mapped to address 0"),
_ => mem,
},
other => panic!("received a non-memory BAR ({:?})", other),
};
let bar_size = pci_config.func.bar_sizes[0];
let (bar, bar_size) = pci_config.func.bars[0].expect_mem();
let irq = pci_config.func.legacy_interrupt_line;
log::debug!("NVME PCI CONFIG: {:?}", pci_config);
@@ -323,16 +301,16 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
let address = unsafe {
common::physmap(
bar as usize,
bar_size as usize,
bar,
bar_size,
common::Prot { read: true, write: true },
common::MemoryType::Uncacheable,
)
.expect("nvmed: failed to map address")
} as usize;
*allocated_bars.0[0].lock().unwrap() = Some(Bar {
physical: bar as usize,
bar_size: bar_size as usize,
physical: bar,
bar_size,
ptr: NonNull::new(address as *mut u8).expect("Physmapping BAR gave nullptr"),
});
+1
View File
@@ -19,6 +19,7 @@ byteorder = "1.2"
libc = "0.2"
log = "0.4"
paw = "1.0"
pci_types = "0.6.1"
plain = "0.2"
redox-log = "0.1"
redox_syscall = "0.4"
+11 -4
View File
@@ -6,8 +6,7 @@ use std::sync::Mutex;
use syscall::io::{Io as _, Pio};
use log::info;
use crate::pci::{CfgAccess, PciAddress};
use pci_types::{ConfigRegionAccess, PciAddress};
pub(crate) struct Pci {
lock: Mutex<()>,
@@ -58,7 +57,11 @@ impl Pci {
}
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
impl CfgAccess for Pci {
impl ConfigRegionAccess for Pci {
fn function_exists(&self, _address: PciAddress) -> bool {
todo!();
}
unsafe fn read(&self, address: PciAddress, offset: u16) -> u32 {
let _guard = self.lock.lock().unwrap();
@@ -86,7 +89,11 @@ impl CfgAccess for Pci {
}
}
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
impl CfgAccess for Pci {
impl ConfigRegionAccess for Pci {
fn function_exists(&self, _address: PciAddress) -> bool {
todo!();
}
unsafe fn read(&self, addr: PciAddress, offset: u16) -> u32 {
let _guard = self.lock.lock().unwrap();
todo!("Pci::CfgAccess::read on this architecture")
+6 -2
View File
@@ -2,8 +2,8 @@ use std::sync::Mutex;
use std::{fmt, fs, io, mem, ptr, slice};
use log::info;
use pci_types::{ConfigRegionAccess, PciAddress};
use crate::pci::{CfgAccess, PciAddress};
use fallback::Pci;
mod fallback;
@@ -221,7 +221,11 @@ impl Pcie {
}
}
impl CfgAccess for Pcie {
impl ConfigRegionAccess for Pcie {
fn function_exists(&self, _address: PciAddress) -> bool {
todo!();
}
unsafe fn read(&self, address: PciAddress, offset: u16) -> u32 {
let _guard = self.lock.lock().unwrap();
+21 -3
View File
@@ -26,17 +26,34 @@ pub enum LegacyInterruptPin {
IntD = 4,
}
#[derive(Serialize, Deserialize)]
#[serde(remote = "PciAddress")]
struct PciAddressDef {
#[serde(getter = "PciAddress::segment")]
segment: u16,
#[serde(getter = "PciAddress::bus")]
bus: u8,
#[serde(getter = "PciAddress::device")]
device: u8,
#[serde(getter = "PciAddress::function")]
function: u8,
}
impl From<PciAddressDef> for PciAddress {
fn from(value: PciAddressDef) -> Self {
PciAddress::new(value.segment, value.bus, value.device, value.function)
}
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct PciFunction {
/// Address of the PCI function.
#[serde(with = "PciAddressDef")]
pub addr: PciAddress,
/// PCI Base Address Registers
pub bars: [PciBar; 6],
/// BAR sizes
pub bar_sizes: [u32; 6],
/// Legacy IRQ line: It's the responsibility of pcid to make sure that it be mapped in either
/// the I/O APIC or the 8259 PIC, so that the subdriver can map the interrupt vector directly.
/// The vector to map is always this field, plus 32.
@@ -262,6 +279,7 @@ impl PcidServerHandle {
}
}
// FIXME turn into struct with bool fields
pub fn fetch_all_features(&mut self) -> Result<Vec<(PciFeature, FeatureStatus)>> {
self.send(&PcidClientRequest::RequestFeatures)?;
match self.recv()? {
+38 -96
View File
@@ -5,20 +5,24 @@ use std::process::Command;
use std::thread;
use std::sync::{Arc, Mutex};
use pci_types::device_type::DeviceType;
use pci_types::{ConfigRegionAccess, PciAddress};
use structopt::StructOpt;
use log::{debug, error, info, warn, trace};
use redox_log::{OutputBuilder, RedoxLogger};
use crate::cfg_access::Pcie;
use crate::config::Config;
use crate::pci::{CfgAccess, PciAddress, PciBar, PciClass, PciFunc, PciHeader, PciHeaderError, PciHeaderType};
use crate::pci::{PciBar, PciFunc};
use crate::pci::cap::Capability as PciCapability;
use crate::pci::func::{ConfigReader, ConfigWriter};
use crate::pci_header::{PciHeader, PciHeaderError};
mod cfg_access;
mod config;
mod driver_interface;
mod pci;
mod pci_header;
#[derive(StructOpt)]
#[structopt(about)]
@@ -38,7 +42,7 @@ pub struct DriverHandler {
state: Arc<State>,
}
fn with_pci_func_raw<T, F: FnOnce(&PciFunc) -> T>(pci: &dyn CfgAccess, addr: PciAddress, function: F) -> T {
fn with_pci_func_raw<T, F: FnOnce(&PciFunc) -> T>(pci: &dyn ConfigRegionAccess, addr: PciAddress, function: F) -> T {
let func = PciFunc {
pci,
addr,
@@ -71,7 +75,7 @@ impl DriverHandler {
None => return PcidClientResponse::Error(PcidServerResponseError::NonexistentFeature(feature)),
};
unsafe {
with_pci_func_raw(self.state.preferred_cfg_access(), self.addr, |func| {
with_pci_func_raw(&self.state.pcie, self.addr, |func| {
capability.set_enabled(true);
capability.write_message_control(func, offset);
});
@@ -84,7 +88,7 @@ impl DriverHandler {
None => return PcidClientResponse::Error(PcidServerResponseError::NonexistentFeature(feature)),
};
unsafe {
with_pci_func_raw(self.state.preferred_cfg_access(), self.addr, |func| {
with_pci_func_raw(&self.state.pcie, self.addr, |func| {
capability.set_msix_enabled(true);
capability.write_a(func, offset);
});
@@ -144,7 +148,7 @@ impl DriverHandler {
info.set_mask_bits(mask_bits);
}
unsafe {
with_pci_func_raw(self.state.preferred_cfg_access(), self.addr, |func| {
with_pci_func_raw(&self.state.pcie, self.addr, |func| {
info.write_all(func, offset);
});
}
@@ -156,7 +160,7 @@ impl DriverHandler {
if let Some(mask) = function_mask {
info.set_function_mask(mask);
unsafe {
with_pci_func_raw(self.state.preferred_cfg_access(), self.addr, |func| {
with_pci_func_raw(&self.state.pcie, self.addr, |func| {
info.write_a(func, offset);
});
}
@@ -168,7 +172,7 @@ impl DriverHandler {
}
PcidClientRequest::ReadConfig(offset) => {
let value = unsafe {
with_pci_func_raw(self.state.preferred_cfg_access(), self.addr, |func| {
with_pci_func_raw(&self.state.pcie, self.addr, |func| {
func.read_u32(offset)
})
};
@@ -176,7 +180,7 @@ impl DriverHandler {
},
PcidClientRequest::WriteConfig(offset, value) => {
unsafe {
with_pci_func_raw(self.state.preferred_cfg_access(), self.addr, |func| {
with_pci_func_raw(&self.state.pcie, self.addr, |func| {
func.write_u32(offset, value);
});
}
@@ -201,58 +205,37 @@ pub struct State {
threads: Mutex<Vec<thread::JoinHandle<()>>>,
pcie: Pcie,
}
impl State {
fn preferred_cfg_access(&self) -> &dyn CfgAccess {
&self.pcie
}
}
fn handle_parsed_header(state: Arc<State>, config: &Config, addr: PciAddress, header: PciHeader) {
let pci = state.preferred_cfg_access();
let raw_class: u8 = header.class().into();
let mut string = format!("PCI {} {:>04X}:{:>04X} {:>02X}.{:>02X}.{:>02X}.{:>02X} {:?}",
addr, header.vendor_id(), header.device_id(), raw_class,
header.subclass(), header.interface(), header.revision(), header.class());
match header.class() {
PciClass::Legacy if header.subclass() == 1 => string.push_str(" VGA CTL"),
PciClass::Storage => match header.subclass() {
0x01 => {
string.push_str(" IDE");
},
0x06 => if header.interface() == 0 {
string.push_str(" SATA VND");
} else if header.interface() == 1 {
string.push_str(" SATA AHCI");
},
_ => ()
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"),
_ => (),
},
PciClass::SerialBus => match header.subclass() {
0x03 => match header.interface() {
0x00 => {
string.push_str(" UHCI");
},
0x10 => {
string.push_str(" OHCI");
},
0x20 => {
string.push_str(" EHCI");
},
0x30 => {
string.push_str(" XHCI");
},
_ => ()
},
_ => ()
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"),
_ => (),
},
_ => ()
_ => (),
}
for (i, bar) in header.bars().iter().enumerate() {
let bars = header.bars(&state.pcie);
for (i, bar) in bars.iter().enumerate() {
match bar {
PciBar::None => {},
PciBar::Memory32(addr) => string.push_str(&format!(" {i}={addr:08X}")),
PciBar::Memory64(addr) => string.push_str(&format!(" {i}={addr:016X}")),
PciBar::Memory32{addr,..} => string.push_str(&format!(" {i}={addr:08X}")),
PciBar::Memory64{addr,..} => string.push_str(&format!(" {i}={addr:016X}")),
PciBar::Port(port) => string.push_str(&format!(" {i}=P{port:04X}")),
}
}
@@ -270,9 +253,9 @@ fn handle_parsed_header(state: Arc<State>, config: &Config, addr: PciAddress, he
// Enable bus mastering, memory space, and I/O space
unsafe {
let mut data = pci.read(addr, 0x04);
let mut data = state.pcie.read(addr, 0x04);
data |= 7;
pci.write(addr, 0x04, data);
state.pcie.write(addr, 0x04, data);
}
// Set IRQ line to 9 if not set
@@ -280,56 +263,19 @@ fn handle_parsed_header(state: Arc<State>, config: &Config, addr: PciAddress, he
let interrupt_pin;
unsafe {
let mut data = pci.read(addr, 0x3C);
let mut data = state.pcie.read(addr, 0x3C);
irq = (data & 0xFF) as u8;
interrupt_pin = ((data & 0x0000_FF00) >> 8) as u8;
if irq == 0xFF {
irq = 9;
}
data = (data & 0xFFFFFF00) | irq as u32;
pci.write(addr, 0x3C, data);
state.pcie.write(addr, 0x3C, data);
};
// Find BAR sizes
//TODO: support 64-bit BAR sizes?
let mut bars = [PciBar::None; 6];
let mut bar_sizes = [0; 6];
unsafe {
let count = match header.header_type() {
PciHeaderType::GENERAL => 6,
PciHeaderType::PCITOPCI => 2,
_ => 0,
};
for i in 0..count {
bars[i] = header.get_bar(i);
let offset = 0x10 + (i as u8) * 4;
let original = pci.read(addr, offset.into());
pci.write(addr, offset.into(), 0xFFFFFFFF);
let new = pci.read(addr, offset.into());
pci.write(addr, offset.into(), original);
let masked = if new & 1 == 1 {
new & 0xFFFFFFFC
} else {
new & 0xFFFFFFF0
};
let size = (!masked).wrapping_add(1);
bar_sizes[i] = if size <= 1 {
0
} else {
size
};
}
}
let capabilities = if header.status() & (1 << 4) != 0 {
let func = PciFunc {
pci: state.preferred_cfg_access(),
pci: &state.pcie,
addr
};
crate::pci::cap::CapabilitiesIter { inner: crate::pci::cap::CapabilityOffsetsIter::new(header.cap_pointer(), &func) }.collect::<Vec<_>>()
@@ -355,7 +301,6 @@ fn handle_parsed_header(state: Arc<State>, config: &Config, addr: PciAddress, he
let func = driver_interface::PciFunction {
bars,
bar_sizes,
addr,
legacy_interrupt_line: irq,
legacy_interrupt_pin,
@@ -506,8 +451,6 @@ fn main(args: Args) {
threads: Mutex::new(Vec::new()),
});
let pci = state.preferred_cfg_access();
info!("PCI SG-BS:DV.F VEND:DEVI CL.SC.IN.RV");
// FIXME Use full ACPI for enumerating the host bridges. MCFG only describes the first
@@ -522,8 +465,7 @@ fn main(args: Args) {
'dev: for dev_num in 0..32 {
for func_num in 0..8 {
let func_addr = PciAddress::new(0, bus_num, dev_num, func_num);
let func = PciFunc { pci, addr: func_addr };
match PciHeader::from_reader(func) {
match PciHeader::from_reader(&state.pcie, func_addr) {
Ok(header) => {
handle_parsed_header(Arc::clone(&state), &config, func_addr, header);
if let PciHeader::PciToPci { secondary_bus_num, .. } = header {
@@ -537,7 +479,7 @@ fn main(args: Args) {
}
},
Err(PciHeaderError::UnknownHeaderType(id)) => {
warn!("pcid: unknown header type: {}", id);
warn!("pcid: unknown header type: {id:?}");
}
}
}
+26 -23
View File
@@ -1,11 +1,13 @@
use serde::{Serialize, Deserialize};
use std::convert::TryInto;
use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub enum PciBar {
None,
Memory32(u32),
Memory64(u64),
Port(u16)
Memory32 { addr: u32, size: u32 },
Memory64 { addr: u64, size: u64 },
Port(u16),
}
impl PciBar {
@@ -15,27 +17,28 @@ impl PciBar {
_ => false,
}
}
}
impl From<u32> for PciBar {
fn from(bar: u32) -> Self {
if bar & 0xFFFFFFFC == 0 {
PciBar::None
} else if bar & 1 == 0 {
match (bar >> 1) & 3 {
0 => {
PciBar::Memory32(bar & 0xFFFFFFF0)
},
2 => {
PciBar::Memory64((bar & 0xFFFFFFF0) as u64)
},
other => {
log::warn!("unsupported PCI memory type {}", other);
PciBar::None
},
pub fn expect_port(&self) -> u16 {
match *self {
PciBar::Port(port) => port,
PciBar::Memory32 { .. } | PciBar::Memory64 { .. } => {
panic!("expected port BAR, found memory BAR");
}
} else {
PciBar::Port((bar & 0xFFFC) as u16)
PciBar::None => panic!("expected BAR to exist"),
}
}
pub fn expect_mem(&self) -> (usize, usize) {
match *self {
PciBar::Memory32 { addr, size } => (addr as usize, size as usize),
PciBar::Memory64 { addr, size } => (
addr.try_into()
.expect("conversion from 64bit BAR to usize failed"),
size.try_into()
.expect("conversion from 64bit BAR size to usize failed"),
),
PciBar::Port(_) => panic!("expected memory BAR, found port BAR"),
PciBar::None => panic!("expected BAR to exist"),
}
}
}
-79
View File
@@ -1,79 +0,0 @@
use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub enum PciClass {
Legacy,
Storage,
Network,
Display,
Multimedia,
Memory,
Bridge,
SimpleComms,
Peripheral,
Input,
Docking,
Processor,
SerialBus,
Wireless,
IntelligentIo,
SatelliteComms,
Cryptography,
SignalProc,
Reserved(u8),
Unknown
}
impl From<u8> for PciClass {
fn from(class: u8) -> PciClass {
match class {
0x00 => PciClass::Legacy,
0x01 => PciClass::Storage,
0x02 => PciClass::Network,
0x03 => PciClass::Display,
0x04 => PciClass::Multimedia,
0x05 => PciClass::Memory,
0x06 => PciClass::Bridge,
0x07 => PciClass::SimpleComms,
0x08 => PciClass::Peripheral,
0x09 => PciClass::Input,
0x0A => PciClass::Docking,
0x0B => PciClass::Processor,
0x0C => PciClass::SerialBus,
0x0D => PciClass::Wireless,
0x0E => PciClass::IntelligentIo,
0x0F => PciClass::SatelliteComms,
0x10 => PciClass::Cryptography,
0x11 => PciClass::SignalProc,
0xFF => PciClass::Unknown,
reserved => PciClass::Reserved(reserved)
}
}
}
impl Into<u8> for PciClass {
fn into(self) -> u8 {
match self {
PciClass::Legacy => 0x00,
PciClass::Storage => 0x01,
PciClass::Network => 0x02,
PciClass::Display => 0x03,
PciClass::Multimedia => 0x04,
PciClass::Memory => 0x05,
PciClass::Bridge => 0x06,
PciClass::SimpleComms => 0x07,
PciClass::Peripheral => 0x08,
PciClass::Input => 0x09,
PciClass::Docking => 0x0A,
PciClass::Processor => 0x0B,
PciClass::SerialBus => 0x0C,
PciClass::Wireless => 0x0D,
PciClass::IntelligentIo => 0x0E,
PciClass::SatelliteComms => 0x0F,
PciClass::Cryptography => 0x10,
PciClass::SignalProc => 0x11,
PciClass::Unknown => 0xFF,
PciClass::Reserved(reserved) => reserved
}
}
}
+2 -3
View File
@@ -1,6 +1,5 @@
use byteorder::{ByteOrder, LittleEndian};
use super::{CfgAccess, PciAddress};
use pci_types::{ConfigRegionAccess, PciAddress};
pub trait ConfigReader {
unsafe fn read_range(&self, offset: u16, len: u16) -> Vec<u8> {
@@ -33,7 +32,7 @@ pub trait ConfigWriter {
}
pub struct PciFunc<'pci> {
pub pci: &'pci dyn CfgAccess,
pub pci: &'pci dyn ConfigRegionAccess,
pub addr: PciAddress,
}
-379
View File
@@ -1,379 +0,0 @@
use bitflags::bitflags;
use byteorder::{ByteOrder, LittleEndian};
use serde::{Deserialize, Serialize};
use super::bar::PciBar;
use super::class::PciClass;
use super::func::ConfigReader;
use super::id::FullDeviceId;
#[derive(Debug, PartialEq)]
pub enum PciHeaderError {
NoDevice,
UnknownHeaderType(u8),
}
bitflags! {
/// Flags found in the status register of a PCI device
#[derive(Serialize, Deserialize)]
pub struct PciHeaderType: u8 {
/// A general PCI device (Type 0x01).
const GENERAL = 0b00000000;
/// A PCI-to-PCI bridge device (Type 0x01).
const PCITOPCI = 0b00000001;
/// A PCI-to-PCI bridge device (Type 0x02).
const CARDBUSBRIDGE = 0b00000010;
/// A multifunction device.
const MULTIFUNCTION = 0b01000000;
/// Mask used for fetching the header type.
const HEADER_TYPE = 0b00000011;
}
}
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub struct SharedPciHeader {
full_device_id: FullDeviceId,
command: u16,
status: u16,
header_type: PciHeaderType,
}
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub enum PciHeader {
General {
shared: SharedPciHeader,
bars: [PciBar; 6],
subsystem_vendor_id: u16,
subsystem_id: u16,
cap_pointer: u8,
interrupt_line: u8,
interrupt_pin: u8,
},
PciToPci {
shared: SharedPciHeader,
bars: [PciBar; 2],
secondary_bus_num: u8,
cap_pointer: u8,
interrupt_line: u8,
interrupt_pin: u8,
bridge_control: u16,
},
}
impl PciHeader {
fn get_bars(bytes: &[u8], bars: &mut [PciBar]) {
let mut i = 0;
while i < bars.len() {
let offset = i * 4;
let bar_bytes = match bytes.get(offset..offset + 4) {
Some(some) => some,
None => continue,
};
match PciBar::from(LittleEndian::read_u32(bar_bytes)) {
PciBar::Memory64(mut addr) => {
let high_bytes = match bytes.get(offset + 4..offset + 8) {
Some(some) => some,
None => continue,
};
addr |= (LittleEndian::read_u32(high_bytes) as u64) << 32;
bars[i] = PciBar::Memory64(addr);
i += 2;
}
bar => {
bars[i] = bar;
i += 1;
}
}
}
}
/// Parse the bytes found in the Configuration Space of the PCI device into
/// a more usable PciHeader.
pub fn from_reader<T: ConfigReader>(reader: T) -> Result<PciHeader, PciHeaderError> {
if unsafe { reader.read_u32(0) } != 0xffffffff {
// Read the initial 16 bytes and set variables used by all header types.
let bytes = unsafe { reader.read_range(0, 16) };
let vendor_id = LittleEndian::read_u16(&bytes[0..2]);
let device_id = LittleEndian::read_u16(&bytes[2..4]);
let command = LittleEndian::read_u16(&bytes[4..6]);
let status = LittleEndian::read_u16(&bytes[6..8]);
let revision = bytes[8];
let interface = bytes[9];
let subclass = bytes[10];
let class = bytes[11];
let header_type = PciHeaderType::from_bits_truncate(bytes[14]);
let shared = SharedPciHeader {
full_device_id: FullDeviceId {
vendor_id,
device_id,
class,
subclass,
interface,
revision,
},
command,
status,
header_type,
};
match header_type & PciHeaderType::HEADER_TYPE {
PciHeaderType::GENERAL => {
let bytes = unsafe { reader.read_range(16, 48) };
let mut bars = [PciBar::None; 6];
Self::get_bars(&bytes, &mut bars);
let subsystem_vendor_id = LittleEndian::read_u16(&bytes[28..30]);
let subsystem_id = LittleEndian::read_u16(&bytes[30..32]);
let cap_pointer = bytes[36];
let interrupt_line = bytes[44];
let interrupt_pin = bytes[45];
Ok(PciHeader::General {
shared,
bars,
subsystem_vendor_id,
subsystem_id,
cap_pointer,
interrupt_line,
interrupt_pin,
})
}
PciHeaderType::PCITOPCI => {
let bytes = unsafe { reader.read_range(16, 48) };
let mut bars = [PciBar::None; 2];
Self::get_bars(&bytes, &mut bars);
let secondary_bus_num = bytes[9];
let cap_pointer = bytes[36];
let interrupt_line = bytes[44];
let interrupt_pin = bytes[45];
let bridge_control = LittleEndian::read_u16(&bytes[46..48]);
Ok(PciHeader::PciToPci {
shared,
bars,
secondary_bus_num,
cap_pointer,
interrupt_line,
interrupt_pin,
bridge_control,
})
}
id => Err(PciHeaderError::UnknownHeaderType(id.bits())),
}
} else {
Err(PciHeaderError::NoDevice)
}
}
/// Return the Header Type.
pub fn header_type(&self) -> PciHeaderType {
match self {
&PciHeader::General {
shared: SharedPciHeader { header_type, .. },
..
}
| &PciHeader::PciToPci {
shared: SharedPciHeader { header_type, .. },
..
} => header_type,
}
}
/// Return all identifying information of the PCI function.
pub fn full_device_id(&self) -> &FullDeviceId {
match self {
PciHeader::General {
shared:
SharedPciHeader {
full_device_id: device_id,
..
},
..
}
| PciHeader::PciToPci {
shared:
SharedPciHeader {
full_device_id: device_id,
..
},
..
} => device_id,
}
}
/// Return the Vendor ID field.
pub fn vendor_id(&self) -> u16 {
self.full_device_id().vendor_id
}
/// Return the Device ID field.
pub fn device_id(&self) -> u16 {
self.full_device_id().device_id
}
/// Return the Revision field.
pub fn revision(&self) -> u8 {
self.full_device_id().revision
}
/// Return the Interface field.
pub fn interface(&self) -> u8 {
self.full_device_id().interface
}
/// Return the Subclass field.
pub fn subclass(&self) -> u8 {
self.full_device_id().subclass
}
/// Return the Class field.
pub fn class(&self) -> PciClass {
PciClass::from(self.full_device_id().class)
}
/// Return the Headers BARs.
pub fn bars(&self) -> &[PciBar] {
match self {
&PciHeader::General { ref bars, .. } => bars,
&PciHeader::PciToPci { ref bars, .. } => bars,
}
}
/// Return the BAR at the given index.
///
/// # Panics
/// This function panics if the requested BAR index is beyond the length of the header
/// types BAR array.
pub fn get_bar(&self, idx: usize) -> PciBar {
match self {
&PciHeader::General { bars, .. } => {
assert!(idx < 6, "the general PCI device only has 6 BARs");
bars[idx]
}
&PciHeader::PciToPci { bars, .. } => {
assert!(idx < 2, "the general PCI device only has 2 BARs");
bars[idx]
}
}
}
/// Return the Interrupt Line field.
pub fn interrupt_line(&self) -> u8 {
match self {
&PciHeader::General { interrupt_line, .. }
| &PciHeader::PciToPci { interrupt_line, .. } => interrupt_line,
}
}
pub fn status(&self) -> u16 {
match self {
&PciHeader::General {
shared: SharedPciHeader { status, .. },
..
}
| &PciHeader::PciToPci {
shared: SharedPciHeader { status, .. },
..
} => status,
}
}
pub fn cap_pointer(&self) -> u8 {
match self {
&PciHeader::General { cap_pointer, .. } | &PciHeader::PciToPci { cap_pointer, .. } => {
cap_pointer
}
}
}
}
#[cfg(test)]
impl<'a> ConfigReader for &'a [u8] {
unsafe fn read_u32(&self, offset: u16) -> u32 {
let offset = offset as usize;
assert!(offset < self.len());
LittleEndian::read_u32(&self[offset..offset + 4])
}
}
#[cfg(test)]
mod test {
use super::{PciHeaderError, PciHeader, PciHeaderType};
use super::super::func::ConfigReader;
use super::super::class::PciClass;
use super::super::bar::PciBar;
const IGB_DEV_BYTES: [u8; 256] = [
0x86, 0x80, 0x33, 0x15, 0x07, 0x04, 0x10, 0x00, 0x03, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x50, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x01, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x58, 0xf7,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0x15, 0x33, 0x15,
0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x00,
0x01, 0x50, 0x23, 0xc8, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x05, 0x70, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x11, 0xa0, 0x04, 0x80, 0x03, 0x00, 0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0x10, 0x00, 0x02, 0x00, 0xc2, 0x8c, 0x00, 0x10, 0x0f, 0x28, 0x19, 0x00, 0x11, 0x5c, 0x42, 0x00,
0x42, 0x00, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
];
#[test]
fn tset_parse_igb_dev() {
let header = PciHeader::from_reader(&IGB_DEV_BYTES[..]).unwrap();
assert_eq!(header.header_type(), PciHeaderType::GENERAL);
assert_eq!(header.device_id(), 0x1533);
assert_eq!(header.vendor_id(), 0x8086);
assert_eq!(header.revision(), 3);
assert_eq!(header.interface(), 0);
assert_eq!(header.class(), PciClass::Network);
assert_eq!(header.subclass(), 0);
assert_eq!(header.bars().len(), 6);
assert_eq!(header.get_bar(0), PciBar::Memory32(0xf7500000));
assert_eq!(header.get_bar(1), PciBar::None);
assert_eq!(header.get_bar(2), PciBar::Port(0xb000));
assert_eq!(header.get_bar(3), PciBar::Memory32(0xf7580000));
assert_eq!(header.get_bar(4), PciBar::None);
assert_eq!(header.get_bar(5), PciBar::None);
assert_eq!(header.interrupt_line(), 10);
}
#[test]
fn test_parse_nonexistent() {
let bytes = [
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff
];
assert_eq!(PciHeader::from_reader(&bytes[..]), Err(PciHeaderError::NoDevice));
}
#[test]
fn test_read_range() {
let res = unsafe { (&IGB_DEV_BYTES[..]).read_range(0, 4) };
assert_eq!(res, &[0x86, 0x80, 0x33, 0x15][..]);
let res = unsafe { (&IGB_DEV_BYTES[..]).read_range(16, 32) };
let expected = [
0x00, 0x00, 0x50, 0xf7, 0x00, 0x00, 0x00, 0x00,
0x01, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x58, 0xf7,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xd9, 0x15, 0x33, 0x15
];
assert_eq!(res, expected);
}
macro_rules! read_range_should_panic {
($name:ident, $len:expr) => {
#[test]
#[should_panic(expected = "invalid range length")]
fn $name() {
let _ = unsafe { (&IGB_DEV_BYTES[..]).read_range(0, $len) };
}
}
}
read_range_should_panic!(test_short_len, 2);
read_range_should_panic!(test_not_mod_4_len, 7);
}
+1 -75
View File
@@ -1,84 +1,10 @@
use std::fmt;
use bit_field::BitField;
use serde::{Deserialize, Serialize};
pub use self::bar::PciBar;
pub use self::class::PciClass;
pub use self::func::PciFunc;
pub use self::header::{PciHeader, PciHeaderError, PciHeaderType};
pub use self::id::FullDeviceId;
pub use pci_types::PciAddress;
mod bar;
pub mod cap;
mod class;
pub mod func;
pub mod header;
mod id;
pub mod msi;
pub trait CfgAccess {
unsafe fn read(&self, addr: PciAddress, offset: u16) -> u32;
unsafe fn write(&self, addr: PciAddress, offset: u16, value: u32);
}
// Copied from the pci_types crate, version 0.6.1. It has been modified to add serde support.
// FIXME If we start using it in the future use the upstream version instead.
/// The address of a PCIe function.
///
/// PCIe supports 65536 segments, each with 256 buses, each with 32 slots, each with 8 possible functions. We pack this into a `u32`:
///
/// ```ignore
/// 32 16 8 3 0
/// +-------------------------------+---------------+---------+------+
/// | segment | bus | device | func |
/// +-------------------------------+---------------+---------+------+
/// ```
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize)]
pub struct PciAddress(u32);
impl PciAddress {
pub fn new(segment: u16, bus: u8, device: u8, function: u8) -> PciAddress {
let mut result = 0;
result.set_bits(0..3, function as u32);
result.set_bits(3..8, device as u32);
result.set_bits(8..16, bus as u32);
result.set_bits(16..32, segment as u32);
PciAddress(result)
}
pub fn segment(&self) -> u16 {
self.0.get_bits(16..32) as u16
}
pub fn bus(&self) -> u8 {
self.0.get_bits(8..16) as u8
}
pub fn device(&self) -> u8 {
self.0.get_bits(3..8) as u8
}
pub fn function(&self) -> u8 {
self.0.get_bits(0..3) as u8
}
}
impl fmt::Display for PciAddress {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{:02x}-{:02x}:{:02x}.{}",
self.segment(),
self.bus(),
self.device(),
self.function()
)
}
}
impl fmt::Debug for PciAddress {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self)
}
}
+3 -33
View File
@@ -219,13 +219,9 @@ impl MsixCapability {
self.a &= 0x0000_FFFF;
self.a |= u32::from(message_control) << 16;
}
/// Returns the MSI-X table size, subtracted by one.
pub const fn table_size_raw(&self) -> u16 {
self.message_control() & Self::MC_TABLE_SIZE_MASK
}
/// Returns the MSI-X table size.
pub const fn table_size(&self) -> u16 {
self.table_size_raw() + 1
(self.message_control() & Self::MC_TABLE_SIZE_MASK) + 1
}
/// Returns the MSI-X enabled bit, which enables MSI-X if the MSI enable bit is also set in the
/// MSI capability structure.
@@ -289,20 +285,7 @@ impl MsixCapability {
if self.table_bir() > 5 {
panic!("MSI-X Table BIR contained a reserved enum value: {}", self.table_bir());
}
let base = bars[usize::from(self.table_bir())];
//TODO: ensure type conversions are safe
match base {
PciBar::Memory32(ptr) => {
ptr as usize + self.table_offset() as usize
},
PciBar::Memory64(ptr) => {
ptr as usize + self.table_offset() as usize
},
_ => {
panic!("MSI-X Table BIR referenced a non-memory BAR: {:?}", base);
}
}
bars[usize::from(self.table_bir())].expect_mem().0 + self.table_offset() as usize
}
pub fn table_pointer(&self, bars: [PciBar; 6], k: u16) -> usize {
self.table_base_pointer(bars) + k as usize * 16
@@ -312,20 +295,7 @@ impl MsixCapability {
if self.pba_bir() > 5 {
panic!("MSI-X PBA BIR contained a reserved enum value: {}", self.pba_bir());
}
let base = bars[usize::from(self.pba_bir())];
//TODO: ensure type conversions are safe
match base {
PciBar::Memory32(ptr) => {
ptr as usize + self.pba_offset() as usize
},
PciBar::Memory64(ptr) => {
ptr as usize + self.pba_offset() as usize
},
_ => {
panic!("MSI-X PBA BIR referenced a non-memory BAR: {:?}", base);
}
}
bars[usize::from(self.pba_bir())].expect_mem().0 + self.pba_offset() as usize
}
pub fn pba_pointer_dword(&self, bars: [PciBar; 6], k: u16) -> usize {
self.pba_base_pointer(bars) + (k as usize / 32) * 4
+310
View File
@@ -0,0 +1,310 @@
use std::convert::TryInto;
use pci_types::{
Bar as TyBar, ConfigRegionAccess, EndpointHeader, HeaderType, PciAddress,
PciHeader as TyPciHeader, PciPciBridgeHeader,
};
use crate::pci::{FullDeviceId, PciBar};
#[derive(Debug, PartialEq)]
pub enum PciHeaderError {
NoDevice,
UnknownHeaderType(HeaderType),
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct SharedPciHeader {
full_device_id: FullDeviceId,
command: u16,
status: u16,
addr: PciAddress,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum PciHeader {
General {
shared: SharedPciHeader,
subsystem_vendor_id: u16,
subsystem_id: u16,
cap_pointer: u8,
},
PciToPci {
shared: SharedPciHeader,
secondary_bus_num: u8,
cap_pointer: u8,
},
}
impl PciHeader {
/// Parse the bytes found in the Configuration Space of the PCI device into
/// a more usable PciHeader.
pub fn from_reader(
access: &impl ConfigRegionAccess,
addr: PciAddress,
) -> Result<PciHeader, PciHeaderError> {
if unsafe { access.read(addr, 0) } == 0xffffffff {
return Err(PciHeaderError::NoDevice);
}
let header = TyPciHeader::new(addr);
let (vendor_id, device_id) = header.id(access);
let command_and_status = unsafe { access.read(addr, 4) };
let command = (command_and_status & 0xffff) as u16;
let status = (command_and_status >> 16) as u16;
let (revision, class, subclass, interface) = header.revision_and_class(access);
let header_type = header.header_type(access);
let shared = SharedPciHeader {
full_device_id: FullDeviceId {
vendor_id,
device_id,
class,
subclass,
interface,
revision,
},
command,
status,
addr,
};
match header_type {
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;
Ok(PciHeader::General {
shared,
subsystem_vendor_id,
subsystem_id,
cap_pointer,
})
}
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)),
}
}
/// Return all identifying information of the PCI function.
pub fn full_device_id(&self) -> &FullDeviceId {
match self {
PciHeader::General {
shared:
SharedPciHeader {
full_device_id: device_id,
..
},
..
}
| PciHeader::PciToPci {
shared:
SharedPciHeader {
full_device_id: device_id,
..
},
..
} => device_id,
}
}
/// Return the Vendor ID field.
pub fn vendor_id(&self) -> u16 {
self.full_device_id().vendor_id
}
/// Return the Device ID field.
pub fn device_id(&self) -> u16 {
self.full_device_id().device_id
}
/// Return the Revision field.
pub fn revision(&self) -> u8 {
self.full_device_id().revision
}
/// Return the Interface field.
pub fn interface(&self) -> u8 {
self.full_device_id().interface
}
/// Return the Subclass field.
pub fn subclass(&self) -> u8 {
self.full_device_id().subclass
}
/// Return the Class field.
pub fn class(&self) -> u8 {
self.full_device_id().class
}
/// Return the Headers BARs.
// FIXME use pci_types::Bar instead
pub fn bars(&self, access: &impl ConfigRegionAccess) -> [PciBar; 6] {
let endpoint_header = match *self {
PciHeader::General {
shared: SharedPciHeader { addr, .. },
..
} => EndpointHeader::from_header(TyPciHeader::new(addr), access).unwrap(),
PciHeader::PciToPci { .. } => unreachable!(),
};
let mut bars = [PciBar::None; 6];
let mut skip = false;
for i in 0..6 {
if skip {
skip = false;
continue;
}
match endpoint_header.bar(i, access) {
Some(TyBar::Io { port }) => {
bars[i as usize] = PciBar::Port(port.try_into().unwrap())
}
Some(TyBar::Memory32 {
address,
size,
prefetchable: _,
}) => {
bars[i as usize] = PciBar::Memory32 {
addr: address,
size,
}
}
Some(TyBar::Memory64 {
address,
size,
prefetchable: _,
}) => {
bars[i as usize] = PciBar::Memory64 {
addr: address,
size,
};
skip = true; // Each 64bit memory BAR occupies two slots
}
None => bars[i as usize] = PciBar::None,
}
}
bars
}
pub fn status(&self) -> u16 {
match self {
&PciHeader::General {
shared: SharedPciHeader { status, .. },
..
}
| &PciHeader::PciToPci {
shared: SharedPciHeader { status, .. },
..
} => status,
}
}
pub fn cap_pointer(&self) -> u8 {
match self {
&PciHeader::General { cap_pointer, .. } | &PciHeader::PciToPci { cap_pointer, .. } => {
cap_pointer
}
}
}
}
#[cfg(test)]
mod test {
use std::convert::TryInto;
use pci_types::device_type::DeviceType;
use pci_types::{ConfigRegionAccess, PciAddress};
use super::{PciHeader, PciHeaderError};
struct TestCfgAccess<'a> {
addr: PciAddress,
bytes: &'a [u8],
}
impl ConfigRegionAccess for TestCfgAccess<'_> {
fn function_exists(&self, _address: PciAddress) -> bool {
unreachable!();
}
unsafe fn read(&self, addr: PciAddress, offset: u16) -> u32 {
assert_eq!(addr, self.addr);
let offset = offset as usize;
assert!(offset < self.bytes.len());
u32::from_le_bytes(self.bytes[offset..offset + 4].try_into().unwrap())
}
unsafe fn write(&self, _addr: PciAddress, _offset: u16, _value: u32) {
unreachable!("should not write during tests");
}
}
#[rustfmt::skip]
const IGB_DEV_BYTES: [u8; 256] = [
0x86, 0x80, 0x33, 0x15, 0x07, 0x04, 0x10, 0x00, 0x03, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x50, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x01, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x58, 0xf7,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0x15, 0x33, 0x15,
0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x00,
0x01, 0x50, 0x23, 0xc8, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x05, 0x70, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x11, 0xa0, 0x04, 0x80, 0x03, 0x00, 0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0x10, 0x00, 0x02, 0x00, 0xc2, 0x8c, 0x00, 0x10, 0x0f, 0x28, 0x19, 0x00, 0x11, 0x5c, 0x42, 0x00,
0x42, 0x00, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
];
#[test]
fn tset_parse_igb_dev() {
let header = PciHeader::from_reader(
&TestCfgAccess {
addr: PciAddress::new(0, 2, 4, 0),
bytes: &IGB_DEV_BYTES,
},
PciAddress::new(0, 2, 4, 0),
)
.unwrap();
match header {
PciHeader::General { .. } => {}
_ => panic!("wrong header type"),
}
assert_eq!(header.device_id(), 0x1533);
assert_eq!(header.vendor_id(), 0x8086);
assert_eq!(header.revision(), 3);
assert_eq!(header.interface(), 0);
assert_eq!(
DeviceType::from((header.class(), header.subclass())),
DeviceType::EthernetController
);
assert_eq!(header.subclass(), 0);
}
#[test]
fn test_parse_nonexistent() {
let bytes = &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
assert_eq!(
PciHeader::from_reader(
&TestCfgAccess {
addr: PciAddress::new(0, 2, 4, 0),
bytes,
},
PciAddress::new(0, 2, 4, 0),
),
Err(PciHeaderError::NoDevice)
);
}
}
+14 -33
View File
@@ -171,36 +171,23 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle) -> Option<File> {
let pba_base = capability.pba_base_pointer(pci_config.func.bars);
let bir = capability.table_bir() as usize;
let bar = pci_config.func.bars[bir];
let bar_size = pci_config.func.bar_sizes[bir] as u64;
let bar_ptr = match bar {
pcid_interface::PciBar::Memory32(ptr) => match ptr {
0 => panic!("BAR {} is mapped to address 0", bir),
_ => ptr as u64,
},
pcid_interface::PciBar::Memory64(ptr) => match ptr {
0 => panic!("BAR {} is mapped to address 0", bir),
_ => ptr,
},
other => panic!("Expected memory bar, found {:?}", other),
};
let (bar_ptr, bar_size) = pci_config.func.bars[bir].expect_mem();
let address = unsafe {
common::physmap(bar_ptr as usize, bar_size as usize, common::Prot::RW, common::MemoryType::Uncacheable)
common::physmap(bar_ptr, bar_size, common::Prot::RW, common::MemoryType::Uncacheable)
.expect("rtl8139d: failed to map address") as usize
};
if !(bar_ptr..bar_ptr + bar_size).contains(&(table_base as u64 + table_min_length as u64)) {
if !(bar_ptr as u64..bar_ptr as u64 + bar_size as u64).contains(&(table_base as u64 + table_min_length as u64)) {
panic!("Table {:#x}{:#x} outside of BAR {:#x}:{:#x}", table_base, table_base + table_min_length as usize, bar_ptr, bar_ptr + bar_size);
}
if !(bar_ptr..bar_ptr + bar_size).contains(&(pba_base as u64 + pba_min_length as u64)) {
if !(bar_ptr as u64..bar_ptr as u64 + bar_size as u64).contains(&(pba_base as u64 + pba_min_length as u64)) {
panic!("PBA {:#x}{:#x} outside of BAR {:#x}:{:#X}", pba_base, pba_base + pba_min_length as usize, bar_ptr, bar_ptr + bar_size);
}
let virt_table_base = ((table_base - bar_ptr as usize) + address) as *mut MsixTableEntry;
let virt_pba_base = ((pba_base - bar_ptr as usize) + address) as *mut u64;
let virt_table_base = ((table_base - bar_ptr) + address) as *mut MsixTableEntry;
let virt_pba_base = ((pba_base - bar_ptr) + address) as *mut u64;
let mut info = MsixInfo {
virt_table_base: NonNull::new(virt_table_base).unwrap(),
@@ -311,20 +298,14 @@ fn find_bar(pci_config: &SubdriverArguments) -> Option<(usize, usize)> {
// RTL8139 uses BAR2, RTL8169 uses BAR1, search in that order
for &barnum in &[2, 1] {
match pci_config.func.bars[barnum] {
pcid_interface::PciBar::Memory32(ptr) => match ptr {
0 => log::warn!("BAR {} is mapped to address 0", barnum),
_ => return Some((
ptr.try_into().unwrap(),
pci_config.func.bar_sizes[barnum].try_into().unwrap()
)),
},
pcid_interface::PciBar::Memory64(ptr) => match ptr {
0 => log::warn!("BAR {} is mapped to address 0", barnum),
_ => return Some((
ptr.try_into().unwrap(),
pci_config.func.bar_sizes[barnum].try_into().unwrap()
)),
},
pcid_interface::PciBar::Memory32 { addr, size } => return Some((
addr.try_into().unwrap(),
size.try_into().unwrap()
)),
pcid_interface::PciBar::Memory64 { addr, size } => return Some((
addr.try_into().unwrap(),
size.try_into().unwrap()
)),
other => log::warn!("BAR {} is {:?} instead of memory BAR", barnum, other),
}
}
+14 -33
View File
@@ -169,36 +169,23 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle) -> Option<File> {
let pba_base = capability.pba_base_pointer(pci_config.func.bars);
let bir = capability.table_bir() as usize;
let bar = pci_config.func.bars[bir];
let bar_size = pci_config.func.bar_sizes[bir] as u64;
let bar_ptr = match bar {
pcid_interface::PciBar::Memory32(ptr) => match ptr {
0 => panic!("BAR {} is mapped to address 0", bir),
_ => ptr as u64,
},
pcid_interface::PciBar::Memory64(ptr) => match ptr {
0 => panic!("BAR {} is mapped to address 0", bir),
_ => ptr,
},
other => panic!("Expected memory bar, found {:?}", other),
};
let (bar_ptr, bar_size) = pci_config.func.bars[bir].expect_mem();
let address = unsafe {
common::physmap(bar_ptr as usize, bar_size as usize, common::Prot::RW, common::MemoryType::Uncacheable)
common::physmap(bar_ptr, bar_size, common::Prot::RW, common::MemoryType::Uncacheable)
.expect("rtl8168d: failed to map address") as usize
};
if !(bar_ptr..bar_ptr + bar_size).contains(&(table_base as u64 + table_min_length as u64)) {
if !(bar_ptr as u64..bar_ptr as u64 + bar_size as u64).contains(&(table_base as u64 + table_min_length as u64)) {
panic!("Table {:#x}{:#x} outside of BAR {:#x}:{:#x}", table_base, table_base + table_min_length as usize, bar_ptr, bar_ptr + bar_size);
}
if !(bar_ptr..bar_ptr + bar_size).contains(&(pba_base as u64 + pba_min_length as u64)) {
if !(bar_ptr as u64..bar_ptr as u64 + bar_size as u64).contains(&(pba_base as u64 + pba_min_length as u64)) {
panic!("PBA {:#x}{:#x} outside of BAR {:#x}:{:#X}", pba_base, pba_base + pba_min_length as usize, bar_ptr, bar_ptr + bar_size);
}
let virt_table_base = ((table_base - bar_ptr as usize) + address) as *mut MsixTableEntry;
let virt_pba_base = ((pba_base - bar_ptr as usize) + address) as *mut u64;
let virt_table_base = ((table_base - bar_ptr) + address) as *mut MsixTableEntry;
let virt_pba_base = ((pba_base - bar_ptr) + address) as *mut u64;
let mut info = MsixInfo {
virt_table_base: NonNull::new(virt_table_base).unwrap(),
@@ -309,20 +296,14 @@ fn find_bar(pci_config: &SubdriverArguments) -> Option<(usize, usize)> {
// RTL8168 uses BAR2, RTL8169 uses BAR1, search in that order
for &barnum in &[2, 1] {
match pci_config.func.bars[barnum] {
pcid_interface::PciBar::Memory32(ptr) => match ptr {
0 => log::warn!("BAR {} is mapped to address 0", barnum),
_ => return Some((
ptr.try_into().unwrap(),
pci_config.func.bar_sizes[barnum].try_into().unwrap()
)),
},
pcid_interface::PciBar::Memory64(ptr) => match ptr {
0 => log::warn!("BAR {} is mapped to address 0", barnum),
_ => return Some((
ptr.try_into().unwrap(),
pci_config.func.bar_sizes[barnum].try_into().unwrap()
)),
},
pcid_interface::PciBar::Memory32 { addr, size } => return Some((
addr.try_into().unwrap(),
size.try_into().unwrap()
)),
pcid_interface::PciBar::Memory64 { addr, size } => return Some((
addr.try_into().unwrap(),
size.try_into().unwrap()
)),
other => log::warn!("BAR {} is {:?} instead of memory BAR", barnum, other),
}
}
+2 -9
View File
@@ -194,16 +194,9 @@ fn main() {
let mut name = pci_config.func.name();
name.push_str("_vbox");
let bar0 = match pci_config.func.bars[0] {
PciBar::Port(port) => port,
_ => unreachable!(),
};
let bar0 = pci_config.func.bars[0].expect_port();
let bar1 = match pci_config.func.bars[1] {
PciBar::Memory32(addr) => addr as usize,
PciBar::Memory64(addr) => addr as usize,
PciBar::None | PciBar::Port(_) => unreachable!(),
};
let (bar1, _) = pci_config.func.bars[1].expect_mem();
let irq = pci_config.func.legacy_interrupt_line;
+21 -23
View File
@@ -11,33 +11,31 @@ pub fn probe_legacy_port_transport(
pci_header: &PciHeader,
pcid_handle: &mut PcidServerHandle,
) -> Result<Device, Error> {
if let PciBar::Port(port) = pci_header.get_bar(0) {
unsafe { syscall::iopl(3).expect("virtio: failed to set I/O privilege level") };
log::warn!("virtio: using legacy transport");
let port = pci_header.get_bar(0).expect_port();
let transport = LegacyTransport::new(port);
unsafe { syscall::iopl(3).expect("virtio: failed to set I/O privilege level") };
log::warn!("virtio: using legacy transport");
// Setup interrupts.
let all_pci_features = pcid_handle.fetch_all_features()?;
let has_msix = all_pci_features
.iter()
.any(|(feature, _)| feature.is_msix());
let transport = LegacyTransport::new(port);
// According to the virtio specification, the device REQUIRED to support MSI-X.
assert!(has_msix, "virtio: device does not support MSI-X");
let irq_handle = enable_msix(pcid_handle)?;
// Setup interrupts.
let all_pci_features = pcid_handle.fetch_all_features()?;
let has_msix = all_pci_features
.iter()
.any(|(feature, _)| feature.is_msix());
let device = Device {
transport,
irq_handle,
device_space: core::ptr::null_mut(),
};
// According to the virtio specification, the device REQUIRED to support MSI-X.
assert!(has_msix, "virtio: device does not support MSI-X");
let irq_handle = enable_msix(pcid_handle)?;
device.transport.reset();
reinit(&device)?;
let device = Device {
transport,
irq_handle,
device_space: core::ptr::null_mut(),
};
Ok(device)
} else {
unreachable!("virtio: legacy transport with non-port IO?")
}
device.transport.reset();
reinit(&device)?;
Ok(device)
}
+25 -34
View File
@@ -27,19 +27,12 @@ pub fn enable_msix(pcid_handle: &mut PcidServerHandle) -> Result<File, Error> {
let pba_base = capability.pba_base_pointer(pci_config.func.bars);
let bir = capability.table_bir() as usize;
let bar = pci_config.func.bars[bir];
let bar_size = pci_config.func.bar_sizes[bir] as u64;
let bar_ptr = match bar {
PciBar::Memory32(ptr) => ptr.into(),
PciBar::Memory64(ptr) => ptr,
_ => unreachable!(),
};
let (bar_ptr, bar_size) = pci_config.func.bars[bir].expect_mem();
let address = unsafe {
common::physmap(
bar_ptr as usize,
bar_size as usize,
bar_ptr,
bar_size,
common::Prot::RW,
common::MemoryType::Uncacheable,
)? as usize
@@ -47,7 +40,7 @@ pub fn enable_msix(pcid_handle: &mut PcidServerHandle) -> Result<File, Error> {
// Ensure that the table and PBA are be within the BAR.
{
let bar_range = bar_ptr..bar_ptr + bar_size;
let bar_range = bar_ptr as u64..bar_ptr as u64 + bar_size as u64;
assert!(bar_range.contains(&(table_base as u64 + table_min_length as u64)));
assert!(bar_range.contains(&(pba_base as u64 + pba_min_length as u64)));
}
@@ -99,33 +92,31 @@ pub fn probe_legacy_port_transport(
pci_config: &SubdriverArguments,
pcid_handle: &mut PcidServerHandle,
) -> Result<Device, Error> {
if let PciBar::Port(port) = pci_config.func.bars[0] {
unsafe { syscall::iopl(3).expect("virtio: failed to set I/O privilege level") };
log::warn!("virtio: using legacy transport");
let port = pci_config.func.bars[0].expect_port();
let transport = LegacyTransport::new(port);
unsafe { syscall::iopl(3).expect("virtio: failed to set I/O privilege level") };
log::warn!("virtio: using legacy transport");
// Setup interrupts.
let all_pci_features = pcid_handle.fetch_all_features()?;
let has_msix = all_pci_features
.iter()
.any(|(feature, _)| feature.is_msix());
let transport = LegacyTransport::new(port);
// According to the virtio specification, the device REQUIRED to support MSI-X.
assert!(has_msix, "virtio: device does not support MSI-X");
let irq_handle = enable_msix(pcid_handle)?;
// Setup interrupts.
let all_pci_features = pcid_handle.fetch_all_features()?;
let has_msix = all_pci_features
.iter()
.any(|(feature, _)| feature.is_msix());
let device = Device {
transport,
irq_handle,
device_space: core::ptr::null_mut(),
};
// According to the virtio specification, the device REQUIRED to support MSI-X.
assert!(has_msix, "virtio: device does not support MSI-X");
let irq_handle = enable_msix(pcid_handle)?;
device.transport.reset();
reinit(&device)?;
let device = Device {
transport,
irq_handle,
device_space: core::ptr::null_mut(),
};
Ok(device)
} else {
unreachable!("virtio: legacy transport with non-port IO?")
}
device.transport.reset();
reinit(&device)?;
Ok(device)
}
+1 -7
View File
@@ -90,13 +90,7 @@ pub fn probe_device(pcid_handle: &mut PcidServerHandle) -> Result<Device, Error>
_ => continue,
}
let bar = pci_config.func.bars[capability.bar as usize];
let addr = match bar {
PciBar::Memory32(addr) => addr as usize,
PciBar::Memory64(addr) => addr as usize,
_ => unreachable!("virtio: unsupported bar type: {bar:?}"),
};
let (addr, _) = pci_config.func.bars[capability.bar as usize].expect_mem();
let address = unsafe {
let addr = addr + capability.offset as usize;
+5 -31
View File
@@ -85,22 +85,9 @@ fn setup_logging(name: &str) -> Option<&'static RedoxLogger> {
fn get_int_method(pcid_handle: &mut PcidServerHandle, address: usize) -> (Option<File>, InterruptMethod) {
let pci_config = pcid_handle.fetch_config().expect("xhcid: failed to fetch config");
let bar = pci_config.func.bars[0];
let bar_size = pci_config.func.bar_sizes[0] as u64;
let (bar_ptr, bar_size) = pci_config.func.bars[0].expect_mem();
let irq = pci_config.func.legacy_interrupt_line;
let bar_ptr = match bar {
pcid_interface::PciBar::Memory32(ptr) => match ptr {
0 => panic!("BAR 0 is mapped to address 0"),
_ => ptr as u64,
},
pcid_interface::PciBar::Memory64(ptr) => match ptr {
0 => panic!("BAR 0 is mapped to address 0"),
_ => ptr,
},
other => panic!("Expected memory bar, found {:?}", other),
};
let all_pci_features = pcid_handle.fetch_all_features().expect("xhcid: failed to fetch pci features");
log::debug!("XHCI PCI FEATURES: {:?}", all_pci_features);
@@ -158,11 +145,11 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle, address: usize) -> (Option
let pba_base = capability.pba_base_pointer(pci_config.func.bars);
if !(bar_ptr..bar_ptr + bar_size).contains(&(table_base as u64 + table_min_length as u64)) {
if !(bar_ptr as u64..bar_ptr as u64 + bar_size as u64).contains(&(table_base as u64 + table_min_length as u64)) {
panic!("Table {:#x}{:#x} outside of BAR {:#x}:{:#x}", table_base, table_base + table_min_length as usize, bar_ptr, bar_ptr + bar_size);
}
if !(bar_ptr..bar_ptr + bar_size).contains(&(pba_base as u64 + pba_min_length as u64)) {
if !(bar_ptr as u64..bar_ptr as u64 + bar_size as u64).contains(&(pba_base as u64 + pba_min_length as u64)) {
panic!("PBA {:#x}{:#x} outside of BAR {:#x}:{:#X}", pba_base, pba_base + pba_min_length as usize, bar_ptr, bar_ptr + bar_size);
}
@@ -247,24 +234,11 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
let _logger_ref = setup_logging(&name);
log::debug!("XHCI PCI CONFIG: {:?}", pci_config);
let bar = pci_config.func.bars[0];
let bar_size = pci_config.func.bar_sizes[0];
let (bar_ptr, bar_size) = pci_config.func.bars[0].expect_mem();
let irq = pci_config.func.legacy_interrupt_line;
let bar_ptr = match bar {
pcid_interface::PciBar::Memory32(ptr) => match ptr {
0 => panic!("BAR 0 is mapped to address 0"),
_ => ptr as u64,
},
pcid_interface::PciBar::Memory64(ptr) => match ptr {
0 => panic!("BAR 0 is mapped to address 0"),
_ => ptr,
},
other => panic!("Expected memory bar, found {:?}", other),
};
let address = unsafe {
common::physmap(bar_ptr as usize, bar_size as usize, common::Prot::RW, common::MemoryType::Uncacheable)
common::physmap(bar_ptr, bar_size, common::Prot::RW, common::MemoryType::Uncacheable)
.expect("xhcid: failed to map address") as usize
};