Merge branch 'pci_interrupts_rework' into 'master'

Couple of interrupt handling cleanups and some other changes

See merge request redox-os/drivers!137
This commit is contained in:
Jeremy Soller
2024-01-24 13:21:24 +00:00
20 changed files with 184 additions and 247 deletions
+3 -3
View File
@@ -76,9 +76,9 @@ fn main() {
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;
let irq = pci_config.func.legacy_interrupt_line.expect("ac97d: no legacy interrupts supported");
print!("{}", format!(" + ac97 {} on: {:X}, {:X}, IRQ {}\n", name, bar0, bar1, irq));
println!(" + ac97 {}", pci_config.func.display());
// Daemonize
redox_daemon::Daemon::new(move |daemon| {
@@ -86,7 +86,7 @@ fn main() {
unsafe { syscall::iopl(3) }.expect("ac97d: failed to set I/O privilege level to Ring 3");
let mut irq_file = File::open(format!("irq:{}", irq)).expect("ac97d: failed to open IRQ file");
let mut irq_file = irq.irq_handle("ac97d");
let device = Arc::new(RefCell::new(unsafe { device::Ac97::new(bar0, bar1).expect("ac97d: failed to allocate device") }));
let socket_fd = syscall::open(":audiohw", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK).expect("ac97d: failed to create hda scheme");
+7 -16
View File
@@ -6,6 +6,7 @@ extern crate byteorder;
use std::fs::File;
use std::io::{ErrorKind, Read, Write};
use std::os::fd::AsRawFd;
use std::os::unix::io::{FromRawFd, RawFd};
use std::usize;
@@ -81,22 +82,15 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
let mut name = pci_config.func.name();
name.push_str("_ahci");
let (bar, bar_size) = pci_config.func.bars[5].expect_mem();
let bar = &pci_config.func.bars[5];
let irq = pci_config.func.legacy_interrupt_line;
let irq = pci_config.func.legacy_interrupt_line.expect("ahcid: no legacy interrupts supported");
let _logger_ref = setup_logging(&name);
info!(" + AHCI {} on: {} size: {} IRQ: {}", name, bar, bar_size, irq);
info!(" + AHCI {}", pci_config.func.display());
let address = unsafe {
common::physmap(
bar,
bar_size,
common::Prot { read: true, write: true },
common::MemoryType::Uncacheable,
).expect("ahcid: failed to map address")
};
let address = unsafe { bar.physmap_mem("ahcid") };
{
let scheme_name = format!("disk.{}", name);
let socket_fd = syscall::open(
@@ -105,11 +99,8 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
).expect("ahcid: failed to create disk scheme");
let mut socket = unsafe { File::from_raw_fd(socket_fd as RawFd) };
let irq_fd = syscall::open(
&format!("irq:{}", irq),
syscall::O_RDWR | syscall::O_NONBLOCK
).expect("ahcid: failed to open irq file");
let mut irq_file = unsafe { File::from_raw_fd(irq_fd as RawFd) };
let mut irq_file = irq.irq_handle("ahcid");
let irq_fd = irq_file.as_raw_fd() as usize;
let mut event_file = File::open("event:").expect("ahcid: failed to open event file");
+1 -1
View File
@@ -1705,7 +1705,7 @@ impl Alx {
}
let mac = self.get_perm_macaddr();
print!("{}", format!(" - MAC: {:>02X}:{:>02X}:{:>02X}:{:>02X}:{:>02X}:{:>02X}\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]));
println!(" - MAC: {:>02X}:{:>02X}:{:>02X}:{:>02X}:{:>02X}:{:>02X}\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
let _ = setcfg("mac", &format!("{:>02X}-{:>02X}-{:>02X}-{:>02X}-{:>02X}-{:>02X}\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]));
if ! self.get_phy_info() {
+1 -1
View File
@@ -32,7 +32,7 @@ fn main() {
let irq_str = args.next().expect("alxd: no irq provided");
let irq = irq_str.parse::<u8>().expect("alxd: failed to parse irq");
print!("{}", format!(" + ALX {} on: {:X}, IRQ: {}\n", name, bar, irq));
println!(" + ALX {} on: {:X}, IRQ: {}\n", name, bar, irq);
// Daemonize
redox_daemon::Daemon::new(move |daemon| {
+1 -1
View File
@@ -25,7 +25,7 @@ fn main() {
let mut name = pci_config.func.name();
name.push_str("_bga");
println!(" + BGA {}", name);
println!(" + BGA {}", pci_config.func.display());
redox_daemon::Daemon::new(move |daemon| {
unsafe { iopl(3).unwrap() };
+5 -12
View File
@@ -68,11 +68,11 @@ fn main() {
let mut name = pci_config.func.name();
name.push_str("_e1000");
let (bar, bar_size) = pci_config.func.bars[0].expect_mem();
let bar = &pci_config.func.bars[0];
let irq = pci_config.func.legacy_interrupt_line;
let irq = pci_config.func.legacy_interrupt_line.expect("e1000d: no legacy interrupts supported");
eprintln!(" + E1000 {} on: {:X} size: {} IRQ: {}", name, bar, bar_size, irq);
eprintln!(" + E1000 {}", pci_config.func.display());
redox_daemon::Daemon::new(move |daemon| {
let socket_fd = syscall::open(
@@ -84,16 +84,9 @@ fn main() {
File::from_raw_fd(socket_fd as RawFd)
}));
let irq_fd = syscall::open(
format!("irq:{}", irq),
syscall::O_RDWR | syscall::O_NONBLOCK
).expect("e1000d: failed to open IRQ file");
let mut irq_file = unsafe { File::from_raw_fd(irq_fd as RawFd) };
let mut irq_file = irq.irq_handle("e1000d");
let address = unsafe {
common::physmap(bar, bar_size, common::Prot::RW, common::MemoryType::Uncacheable)
.expect("e1000d: failed to map address")
} as usize;
let address = unsafe { bar.physmap_mem("e1000d") } as usize;
{
let device = Arc::new(RefCell::new(unsafe {
device::Intel8254x::new(address).expect("e1000d: failed to allocate device")
+13 -21
View File
@@ -74,11 +74,9 @@ fn setup_logging() -> Option<&'static RedoxLogger> {
}
#[cfg(target_arch = "x86_64")]
fn get_int_method(pcid_handle: &mut PcidServerHandle) -> Option<File> {
fn get_int_method(pcid_handle: &mut PcidServerHandle) -> File {
let pci_config = pcid_handle.fetch_config().expect("ihdad: failed to fetch config");
let irq = pci_config.func.legacy_interrupt_line;
let all_pci_features = pcid_handle.fetch_all_features().expect("ihdad: failed to fetch pci features");
log::debug!("PCI FEATURES: {:?}", all_pci_features);
@@ -123,30 +121,27 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle) -> Option<File> {
pcid_handle.enable_feature(PciFeature::Msi).expect("ihdad: failed to enable MSI");
log::debug!("Enabled MSI");
Some(interrupt_handle)
} else if pci_config.func.legacy_interrupt_pin.is_some() {
interrupt_handle
} else if let Some(irq) = pci_config.func.legacy_interrupt_line {
log::debug!("Legacy IRQ {}", irq);
// legacy INTx# interrupt pins.
Some(File::open(format!("irq:{}", irq)).expect("ihdad: failed to open legacy IRQ file"))
File::open(format!("irq:{}", irq)).expect("ihdad: failed to open legacy IRQ file")
} else {
// no interrupts at all
None
panic!("ihdad: no interrupts supported at all")
}
}
//TODO: MSI on non-x86_64?
#[cfg(not(target_arch = "x86_64"))]
fn get_int_method(pcid_handle: &mut PcidServerHandle) -> Option<File> {
fn get_int_method(pcid_handle: &mut PcidServerHandle) -> File {
let pci_config = pcid_handle.fetch_config().expect("ihdad: failed to fetch config");
let irq = pci_config.func.legacy_interrupt_line;
if pci_config.func.legacy_interrupt_pin.is_some() {
if let Some(irq) = pci_config.func.legacy_interrupt_line {
// legacy INTx# interrupt pins.
Some(File::open(format!("irq:{}", irq)).expect("ihdad: failed to open legacy IRQ file"))
File::open(format!("irq:{}", irq)).expect("ihdad: failed to open legacy IRQ file")
} else {
// no interrupts at all
None
panic!("ihdad: no interrupts supported at all")
}
}
@@ -160,17 +155,14 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
let mut name = pci_config.func.name();
name.push_str("_ihda");
let (bar_ptr, bar_size) = pci_config.func.bars[0].expect_mem();
let bar = &pci_config.func.bars[0];
log::info!(" + IHDA {} on: {:#X} size: {}", name, bar_ptr, bar_size);
log::info!(" + IHDA {}", pci_config.func.display());
let address = unsafe {
common::physmap(bar_ptr, bar_size, common::Prot::RW, common::MemoryType::Uncacheable)
.expect("ihdad: failed to map address") as usize
};
let address = unsafe { bar.physmap_mem("ihdad") } as usize;
//TODO: MSI-X
let mut irq_file = get_int_method(&mut pcid_handle).expect("ihdad: no interrupt file");
let mut irq_file = get_int_method(&mut pcid_handle);
{
let vend_prod: u32 = ((pci_config.func.full_device_id.vendor_id as u32) << 16)
+3 -4
View File
@@ -78,9 +78,9 @@ fn main() {
let (bar, _) = pci_config.func.bars[0].expect_mem();
let irq = pci_config.func.legacy_interrupt_line;
let irq = pci_config.func.legacy_interrupt_line.expect("ixgbed: no legacy interrupts supported");
println!(" + IXGBE {} on: {:X} IRQ: {}", name, bar, irq);
println!(" + IXGBE {}", pci_config.func.display());
redox_daemon::Daemon::new(move |daemon| {
let socket_fd = syscall::open(
@@ -94,8 +94,7 @@ fn main() {
daemon.ready().expect("ixgbed: failed to signal readiness");
let mut irq_file =
File::open(format!("irq:{}", irq)).expect("ixgbed: failed to open IRQ file");
let mut irq_file = irq.irq_handle("ixgbed");
let address = unsafe {
common::physmap(bar, IXGBE_MMIO_SIZE, common::Prot::RW, common::MemoryType::Uncacheable)
+17 -24
View File
@@ -48,7 +48,12 @@ impl Bar {
impl Drop for Bar {
fn drop(&mut self) {
let _ = unsafe { syscall::funmap(self.physical, self.bar_size.next_multiple_of(PAGE_SIZE)) };
let _ = unsafe {
syscall::funmap(
self.ptr.as_ptr() as usize,
self.bar_size.next_multiple_of(PAGE_SIZE),
)
};
}
}
@@ -205,14 +210,12 @@ fn get_int_method(
pcid_handle.enable_feature(PciFeature::Msi).unwrap();
Ok((interrupt_method, interrupt_sources))
} else if function.legacy_interrupt_pin.is_some() {
} else if let Some(irq) = function.legacy_interrupt_line {
// INTx# pin based interrupts.
let irq_handle = File::open(format!("irq:{}", function.legacy_interrupt_line))
.expect("nvmed: failed to open INTx# interrupt line");
let irq_handle = irq.irq_handle("nvmed");
Ok((InterruptMethod::Intx, InterruptSources::Intx(irq_handle)))
} else {
// No interrupts at all
todo!("handling of no interrupts")
panic!("nvmed: no interrupts supported at all")
}
}
@@ -223,14 +226,12 @@ fn get_int_method(
function: &PciFunction,
allocated_bars: &AllocatedBars,
) -> Result<(InterruptMethod, InterruptSources)> {
if function.legacy_interrupt_pin.is_some() {
if let Some(irq) = function.legacy_interrupt_line {
// INTx# pin based interrupts.
let irq_handle = File::open(format!("irq:{}", function.legacy_interrupt_line))
.expect("nvmed: failed to open INTx# interrupt line");
let irq_handle = irq.irq_handle("nvmed");
Ok((InterruptMethod::Intx, InterruptSources::Intx(irq_handle)))
} else {
// No interrupts at all
todo!("handling of no interrupts")
panic!("nvmed: no interrupts supported at all")
}
}
@@ -288,28 +289,20 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
.fetch_config()
.expect("nvmed: failed to fetch config");
let scheme_name = format!("disk.pci-{}-nvme", pci_config.func.addr);
let scheme_name = format!("disk.{}-nvme", pci_config.func.name());
let _logger_ref = setup_logging(&scheme_name);
let (bar, bar_size) = pci_config.func.bars[0].expect_mem();
let irq = pci_config.func.legacy_interrupt_line;
let bar = &pci_config.func.bars[0];
let (bar_ptr, bar_size) = bar.expect_mem();
log::debug!("NVME PCI CONFIG: {:?}", pci_config);
let allocated_bars = AllocatedBars::default();
let address = unsafe {
common::physmap(
bar,
bar_size,
common::Prot { read: true, write: true },
common::MemoryType::Uncacheable,
)
.expect("nvmed: failed to map address")
} as usize;
let address = unsafe { bar.physmap_mem("nvmed") } as usize;
*allocated_bars.0[0].lock().unwrap() = Some(Bar {
physical: bar,
physical: bar_ptr,
bar_size,
ptr: NonNull::new(address as *mut u8).expect("Physmapping BAR gave nullptr"),
});
+1 -1
View File
@@ -1,7 +1,7 @@
[package]
name = "pcid"
version = "0.1.0"
edition = "2018"
edition = "2021"
[[bin]]
name = "pcid"
+35 -14
View File
@@ -1,3 +1,4 @@
use std::fmt;
use std::fs::File;
use std::io::prelude::*;
use std::{env, io};
@@ -14,16 +15,20 @@ pub use crate::pci::{FullDeviceId, PciAddress, PciBar};
pub mod irq_helpers;
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
#[repr(u8)]
pub enum LegacyInterruptPin {
/// INTa#
IntA = 1,
/// INTb#
IntB = 2,
/// INTc#
IntC = 3,
/// INTd#
IntD = 4,
pub struct LegacyInterruptLine(pub(crate) u8);
impl LegacyInterruptLine {
/// Get an IRQ handle for this interrupt line.
pub fn irq_handle(self, driver: &str) -> File {
File::open(format!("irq:{}", self.0))
.unwrap_or_else(|err| panic!("{driver}: failed to open IRQ file: {err}"))
}
}
impl fmt::Display for LegacyInterruptLine {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Serialize, Deserialize)]
@@ -57,10 +62,8 @@ pub struct PciFunction {
/// 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.
pub legacy_interrupt_line: u8,
/// Legacy interrupt pin (INTx#), none if INTx# interrupts aren't supported at all.
pub legacy_interrupt_pin: Option<LegacyInterruptPin>,
/// If INTx# interrupts aren't supported at all this is `None`.
pub legacy_interrupt_line: Option<LegacyInterruptLine>,
/// All identifying information of the PCI function.
pub full_device_id: FullDeviceId,
@@ -70,6 +73,24 @@ impl PciFunction {
// FIXME stop replacing : with - once it is a valid character in scheme names
format!("pci-{}", self.addr).replace(':', "-")
}
pub fn display(&self) -> String {
let mut string = self.name();
let mut first = true;
for (i, bar) in self.bars.iter().enumerate() {
if !bar.is_none() {
if first {
first = false;
string.push_str(" on:");
}
string.push_str(&format!(" {i}={}", bar.display()));
}
}
if let Some(irq) = self.legacy_interrupt_line {
string.push_str(&format!(" IRQ: {irq}"));
}
string
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
+18 -22
View File
@@ -13,6 +13,7 @@ use redox_log::{OutputBuilder, RedoxLogger};
use crate::cfg_access::Pcie;
use crate::config::Config;
use crate::driver_interface::LegacyInterruptLine;
use crate::pci::{PciBar, PciFunc};
use crate::pci::cap::Capability as PciCapability;
use crate::pci::func::{ConfigReader, ConfigWriter};
@@ -244,11 +245,8 @@ fn handle_parsed_header(state: Arc<State>, config: &Config, addr: PciAddress, he
let mut string = String::new();
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::Port(port) => string.push_str(&format!(" {i}=P{port:04X}")),
if !bar.is_none() {
string.push_str(&format!(" {i}={}", bar.display()));
}
}
@@ -280,6 +278,16 @@ fn handle_parsed_header(state: Arc<State>, config: &Config, addr: PciAddress, he
state.pcie.write(addr, 0x3C, data);
};
let legacy_interrupt_enabled = match interrupt_pin {
0 => false,
1 | 2 | 3 | 4 => true,
other => {
warn!("pcid: invalid interrupt pin: {}", other);
false
}
};
let capabilities = if endpoint_header.status(&state.pcie).has_capability_list() {
let func = PciFunc {
pci: &state.pcie,
@@ -291,26 +299,14 @@ fn handle_parsed_header(state: Arc<State>, config: &Config, addr: PciAddress, he
};
debug!("PCI DEVICE CAPABILITIES for {}: {:?}", args.iter().map(|string| string.as_ref()).nth(0).unwrap_or("[unknown]"), capabilities);
use driver_interface::LegacyInterruptPin;
let legacy_interrupt_pin = match interrupt_pin {
0 => None,
1 => Some(LegacyInterruptPin::IntA),
2 => Some(LegacyInterruptPin::IntB),
3 => Some(LegacyInterruptPin::IntC),
4 => Some(LegacyInterruptPin::IntD),
other => {
warn!("pcid: invalid interrupt pin: {}", other);
None
}
};
let func = driver_interface::PciFunction {
bars,
addr,
legacy_interrupt_line: irq,
legacy_interrupt_pin,
legacy_interrupt_line: if legacy_interrupt_enabled {
Some(LegacyInterruptLine(irq))
} else {
None
},
full_device_id: header.full_device_id().clone(),
};
+23
View File
@@ -11,6 +11,15 @@ pub enum PciBar {
}
impl PciBar {
pub fn display(&self) -> String {
match self {
PciBar::None => format!("<none>"),
PciBar::Memory32 { addr, .. } => format!("{addr:08X}"),
PciBar::Memory64 { addr, .. } => format!("{addr:016X}"),
PciBar::Port(port) => format!("P{port:04X}"),
}
}
pub fn is_none(&self) -> bool {
match self {
&PciBar::None => true,
@@ -41,4 +50,18 @@ impl PciBar {
PciBar::None => panic!("expected BAR to exist"),
}
}
pub unsafe fn physmap_mem(&self, driver: &str) -> *mut () {
let (bar, bar_size) = self.expect_mem();
unsafe {
common::physmap(
bar,
bar_size,
common::Prot::RW,
// FIXME once the kernel supports this use write-through for prefetchable BAR
common::MemoryType::Uncacheable,
)
}
.unwrap_or_else(|err| panic!("{driver}: failed to map BAR at {bar:016X}: {err}"))
}
}
+9 -51
View File
@@ -203,11 +203,11 @@ impl MsiCapability {
}
impl MsixCapability {
pub const MC_MSIX_ENABLED_BIT: u16 = 1 << 15;
pub const MC_MSIX_ENABLED_SHIFT: u8 = 15;
pub const MC_FUNCTION_MASK_BIT: u16 = 1 << 14;
pub const MC_FUNCTION_MASK_SHIFT: u8 = 14;
pub const MC_TABLE_SIZE_MASK: u16 = 0x03FF;
const MC_MSIX_ENABLED_BIT: u16 = 1 << 15;
const MC_MSIX_ENABLED_SHIFT: u8 = 15;
const MC_FUNCTION_MASK_BIT: u16 = 1 << 14;
const MC_FUNCTION_MASK_SHIFT: u8 = 14;
const MC_TABLE_SIZE_MASK: u16 = 0x03FF;
/// The Message Control field, containing the enabled and function mask bits, as well as the
/// table size.
@@ -246,8 +246,8 @@ impl MsixCapability {
new_message_control |= u16::from(function_mask) << Self::MC_FUNCTION_MASK_SHIFT;
self.set_message_control(new_message_control);
}
pub const TABLE_OFFSET_MASK: u32 = 0xFFFF_FFF8;
pub const TABLE_BIR_MASK: u32 = 0x0000_0007;
const TABLE_OFFSET_MASK: u32 = 0xFFFF_FFF8;
const TABLE_BIR_MASK: u32 = 0x0000_0007;
/// The table offset is guaranteed to be QWORD aligned (8 bytes).
pub const fn table_offset(&self) -> u32 {
@@ -258,13 +258,8 @@ impl MsixCapability {
(self.b & Self::TABLE_BIR_MASK) as u8
}
pub fn set_table_offset(&mut self, offset: u32) {
assert_eq!(offset & Self::TABLE_OFFSET_MASK, offset, "MSI-X table offset has to be QWORD aligned");
self.b &= !Self::TABLE_OFFSET_MASK;
self.b |= offset;
}
pub const PBA_OFFSET_MASK: u32 = 0xFFFF_FFF8;
pub const PBA_BIR_MASK: u32 = 0x0000_0007;
const PBA_OFFSET_MASK: u32 = 0xFFFF_FFF8;
const PBA_BIR_MASK: u32 = 0x0000_0007;
/// The Pending Bit Array offset is guaranteed to be QWORD aligned (8 bytes).
pub const fn pba_offset(&self) -> u32 {
@@ -275,11 +270,6 @@ impl MsixCapability {
(self.c & Self::PBA_BIR_MASK) as u8
}
pub fn set_pba_offset(&mut self, offset: u32) {
assert_eq!(offset & Self::PBA_OFFSET_MASK, offset, "MSI-X Pending Bit Array offset has to be QWORD aligned");
self.c &= !Self::PBA_OFFSET_MASK;
self.c |= offset;
}
pub fn table_base_pointer(&self, bars: [PciBar; 6]) -> usize {
if self.table_bir() > 5 {
@@ -287,9 +277,6 @@ impl MsixCapability {
}
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
}
pub fn pba_base_pointer(&self, bars: [PciBar; 6]) -> usize {
if self.pba_bir() > 5 {
@@ -297,41 +284,12 @@ impl MsixCapability {
}
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
}
pub const fn pba_bit_dword(&self, k: u16) -> u8 {
(k % 32) as u8
}
pub fn pba_pointer_qword(&self, bars: [PciBar; 6], k: u16) -> usize {
self.pba_base_pointer(bars) + (k as usize / 64) * 8
}
pub const fn pba_bit_qword(&self, k: u16) -> u8 {
(k % 64) as u8
}
/// Write the first DWORD into configuration space (containing the partially modifiable Message
/// Control field).
pub unsafe fn write_a<W: ConfigWriter>(&self, writer: &W, offset: u8) {
writer.write_u32(u16::from(offset), self.a)
}
/// Write the second DWORD into configuration space (containing the modifiable table
/// offset and the readonly table BIR).
pub unsafe fn write_b<W: ConfigWriter>(&self, writer: &W, offset: u8) {
writer.write_u32(u16::from(offset + 4), self.a)
}
/// Write the third DWORD into configuration space (containing the modifiable pending bit array
/// offset, and the readonly PBA BIR).
pub unsafe fn write_c<W: ConfigWriter>(&self, writer: &W, offset: u8) {
writer.write_u32(u16::from(offset + 8), self.a)
}
/// Write this capability structure back to configuration space.
pub unsafe fn write_all<W: ConfigWriter>(&self, writer: &W, offset: u8) {
self.write_a(writer, offset);
self.write_b(writer, offset);
self.write_c(writer, offset);
}
}
#[repr(packed)]
+15 -22
View File
@@ -108,11 +108,9 @@ impl MsixInfo {
}
#[cfg(target_arch = "x86_64")]
fn get_int_method(pcid_handle: &mut PcidServerHandle) -> Option<File> {
fn get_int_method(pcid_handle: &mut PcidServerHandle) -> File {
let pci_config = pcid_handle.fetch_config().expect("rtl8139d: failed to fetch config");
let irq = pci_config.func.legacy_interrupt_line;
let all_pci_features = pcid_handle.fetch_all_features().expect("rtl8139d: failed to fetch pci features");
log::info!("PCI FEATURES: {:?}", all_pci_features);
@@ -157,7 +155,7 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle) -> Option<File> {
pcid_handle.enable_feature(PciFeature::Msi).expect("rtl8139d: failed to enable MSI");
log::info!("Enabled MSI");
Some(interrupt_handle)
interrupt_handle
} else if msix_enabled {
let capability = match pcid_handle.feature_info(PciFeature::MsiX).expect("rtl8139d: failed to retrieve the MSI-X capability structure from pcid") {
PciFeatureInfo::Msi(_) => panic!(),
@@ -171,12 +169,10 @@ 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_ptr, bar_size) = pci_config.func.bars[bir].expect_mem();
let bar = &pci_config.func.bars[bir];
let (bar_ptr, bar_size) = bar.expect_mem();
let address = unsafe {
common::physmap(bar_ptr, bar_size, common::Prot::RW, common::MemoryType::Uncacheable)
.expect("rtl8139d: failed to map address") as usize
};
let address = unsafe { bar.physmap_mem("rtl8139d") } as usize;
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);
@@ -220,34 +216,31 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle) -> Option<File> {
table_entry_pointer.msg_data.write(msg_data);
table_entry_pointer.vec_ctl.writef(MsixTableEntry::VEC_CTL_MASK_BIT, false);
Some(interrupt_handle)
interrupt_handle
};
pcid_handle.enable_feature(PciFeature::MsiX).expect("rtl8139d: failed to enable MSI-X");
log::info!("Enabled MSI-X");
method
} else if pci_config.func.legacy_interrupt_pin.is_some() {
} else if let Some(irq) = pci_config.func.legacy_interrupt_line {
// legacy INTx# interrupt pins.
Some(File::open(format!("irq:{}", irq)).expect("rtl8139d: failed to open legacy IRQ file"))
irq.irq_handle("rtl8139d")
} else {
// no interrupts at all
None
panic!("rtl8139d: no interrupts supported at all")
}
}
//TODO: MSI on non-x86_64?
#[cfg(not(target_arch = "x86_64"))]
fn get_int_method(pcid_handle: &mut PcidServerHandle) -> Option<File> {
fn get_int_method(pcid_handle: &mut PcidServerHandle) -> File {
let pci_config = pcid_handle.fetch_config().expect("rtl8139d: failed to fetch config");
let irq = pci_config.func.legacy_interrupt_line;
if pci_config.func.legacy_interrupt_pin.is_some() {
if let Some(irq) = pci_config.func.legacy_interrupt_line {
// legacy INTx# interrupt pins.
Some(File::open(format!("irq:{}", irq)).expect("rtl8139d: failed to open legacy IRQ file"))
irq.irq_handle("rtl8139d")
} else {
// no interrupts at all
None
panic!("rtl8139d: no interrupts supported at all")
}
}
@@ -323,7 +316,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
name.push_str("_rtl8139");
let (bar_ptr, bar_size) = find_bar(&pci_config).expect("rtl8139d: failed to find BAR");
log::info!(" + RTL8139 {} on: {:#X} size: {}", name, bar_ptr, bar_size);
log::info!(" + RTL8139 {}", pci_config.func.display());
let address = unsafe {
common::physmap(bar_ptr, bar_size, common::Prot::RW, common::MemoryType::Uncacheable)
@@ -340,7 +333,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
}));
//TODO: MSI-X
let mut irq_file = get_int_method(&mut pcid_handle).expect("rtl8139d: no interrupt file");
let mut irq_file = get_int_method(&mut pcid_handle);
{
let device = Arc::new(RefCell::new(unsafe {
+15 -22
View File
@@ -106,11 +106,9 @@ impl MsixInfo {
}
#[cfg(target_arch = "x86_64")]
fn get_int_method(pcid_handle: &mut PcidServerHandle) -> Option<File> {
fn get_int_method(pcid_handle: &mut PcidServerHandle) -> File {
let pci_config = pcid_handle.fetch_config().expect("rtl8168d: failed to fetch config");
let irq = pci_config.func.legacy_interrupt_line;
let all_pci_features = pcid_handle.fetch_all_features().expect("rtl8168d: failed to fetch pci features");
log::info!("PCI FEATURES: {:?}", all_pci_features);
@@ -155,7 +153,7 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle) -> Option<File> {
pcid_handle.enable_feature(PciFeature::Msi).expect("rtl8168d: failed to enable MSI");
log::info!("Enabled MSI");
Some(interrupt_handle)
interrupt_handle
} else if msix_enabled {
let capability = match pcid_handle.feature_info(PciFeature::MsiX).expect("rtl8168d: failed to retrieve the MSI-X capability structure from pcid") {
PciFeatureInfo::Msi(_) => panic!(),
@@ -169,12 +167,10 @@ 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_ptr, bar_size) = pci_config.func.bars[bir].expect_mem();
let bar = &pci_config.func.bars[bir];
let (bar_ptr, bar_size) = bar.expect_mem();
let address = unsafe {
common::physmap(bar_ptr, bar_size, common::Prot::RW, common::MemoryType::Uncacheable)
.expect("rtl8168d: failed to map address") as usize
};
let address = unsafe { bar.physmap_mem("rtl8168d") } as usize;
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);
@@ -218,34 +214,31 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle) -> Option<File> {
table_entry_pointer.msg_data.write(msg_data);
table_entry_pointer.vec_ctl.writef(MsixTableEntry::VEC_CTL_MASK_BIT, false);
Some(interrupt_handle)
interrupt_handle
};
pcid_handle.enable_feature(PciFeature::MsiX).expect("rtl8168d: failed to enable MSI-X");
log::info!("Enabled MSI-X");
method
} else if pci_config.func.legacy_interrupt_pin.is_some() {
} else if let Some(irq) = pci_config.func.legacy_interrupt_line {
// legacy INTx# interrupt pins.
Some(File::open(format!("irq:{}", irq)).expect("rtl8168d: failed to open legacy IRQ file"))
irq.irq_handle("rtl8168d")
} else {
// no interrupts at all
None
panic!("rtl8168d: no interrupts supported at all")
}
}
//TODO: MSI on non-x86_64?
#[cfg(not(target_arch = "x86_64"))]
fn get_int_method(pcid_handle: &mut PcidServerHandle) -> Option<File> {
fn get_int_method(pcid_handle: &mut PcidServerHandle) -> File {
let pci_config = pcid_handle.fetch_config().expect("rtl8168d: failed to fetch config");
let irq = pci_config.func.legacy_interrupt_line;
if pci_config.func.legacy_interrupt_pin.is_some() {
if let Some(irq) = pci_config.func.legacy_interrupt_line {
// legacy INTx# interrupt pins.
Some(File::open(format!("irq:{}", irq)).expect("rtl8168d: failed to open legacy IRQ file"))
irq.irq_handle("rtl8168d")
} else {
// no interrupts at all
None
panic!("rtl8168d: no interrupts supported at all")
}
}
@@ -321,7 +314,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
name.push_str("_rtl8168");
let (bar_ptr, bar_size) = find_bar(&pci_config).expect("rtl8168d: failed to find BAR");
log::info!(" + RTL8168 {} on: {:#X} size: {}", name, bar_ptr, bar_size);
log::info!(" + RTL8168 {}", pci_config.func.display());
let address = unsafe {
common::physmap(bar_ptr, bar_size, common::Prot::RW, common::MemoryType::Uncacheable)
@@ -338,7 +331,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
}));
//TODO: MSI-X
let mut irq_file = get_int_method(&mut pcid_handle).expect("rtl8168d: no interrupt file");
let mut irq_file = get_int_method(&mut pcid_handle);
{
let device = Arc::new(RefCell::new(unsafe {
+1 -1
View File
@@ -68,7 +68,7 @@ fn main() {
let addr_str = args.next().unwrap_or("220".to_string());
let addr = u16::from_str_radix(&addr_str, 16).expect("sb16: failed to parse address");
print!("{}", format!(" + sb16 at 0x{:X}\n", addr));
println!(" + sb16 at 0x{:X}\n", addr);
// Daemonize
redox_daemon::Daemon::new(move |daemon| {
+5 -5
View File
@@ -196,11 +196,11 @@ fn main() {
let bar0 = pci_config.func.bars[0].expect_port();
let (bar1, _) = pci_config.func.bars[1].expect_mem();
let bar1 = &pci_config.func.bars[1];
let irq = pci_config.func.legacy_interrupt_line;
let irq = pci_config.func.legacy_interrupt_line.expect("vboxd: no legacy interrupts supported");
print!("{}", format!(" + VirtualBox {} on: {:X}, {:X}, IRQ {}\n", name, bar0, bar1, irq));
println!(" + VirtualBox {}", pci_config.func.display());
// Daemonize
redox_daemon::Daemon::new(move |daemon| {
@@ -221,10 +221,10 @@ fn main() {
}
}
let mut irq_file = File::open(format!("irq:{}", irq)).expect("vboxd: failed to open IRQ file");
let mut irq_file = irq.irq_handle("vboxd");
let mut port = Pio::<u32>::new(bar0 as u16);
let address = unsafe { common::physmap(bar1, 4096, common::Prot::RW, common::MemoryType::Uncacheable).expect("vboxd: failed to map address") };
let address = unsafe { bar1.physmap_mem("vboxd") };
{
let vmmdev = unsafe { &mut *(address as *mut VboxVmmDev) };
+3 -9
View File
@@ -27,16 +27,10 @@ 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_ptr, bar_size) = pci_config.func.bars[bir].expect_mem();
let bar = &pci_config.func.bars[bir];
let (bar_ptr, bar_size) = bar.expect_mem();
let address = unsafe {
common::physmap(
bar_ptr,
bar_size,
common::Prot::RW,
common::MemoryType::Uncacheable,
)? as usize
};
let address = unsafe { bar.physmap_mem("virtio-core") } as usize;
// Ensure that the table and PBA are be within the BAR.
{
+8 -17
View File
@@ -86,7 +86,6 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle, address: usize) -> (Option
let pci_config = pcid_handle.fetch_config().expect("xhcid: failed to fetch config");
let (bar_ptr, bar_size) = pci_config.func.bars[0].expect_mem();
let irq = pci_config.func.legacy_interrupt_line;
let all_pci_features = pcid_handle.fetch_all_features().expect("xhcid: failed to fetch pci features");
log::debug!("XHCI PCI FEATURES: {:?}", all_pci_features);
@@ -194,11 +193,11 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle, address: usize) -> (Option
log::debug!("Enabled MSI-X");
method
} else if pci_config.func.legacy_interrupt_pin.is_some() {
} else if let Some(irq) = pci_config.func.legacy_interrupt_line {
log::debug!("Legacy IRQ {}", irq);
// legacy INTx# interrupt pins.
(Some(File::open(format!("irq:{}", irq)).expect("xhcid: failed to open legacy IRQ file")), InterruptMethod::Intx)
(Some(irq.irq_handle("xhcid")), InterruptMethod::Intx)
} else {
// no interrupts at all
(None, InterruptMethod::Polling)
@@ -209,11 +208,10 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle, address: usize) -> (Option
#[cfg(not(target_arch = "x86_64"))]
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 irq = pci_config.func.legacy_interrupt_line;
if pci_config.func.legacy_interrupt_pin.is_some() {
if let Some(irq) = pci_config.func.legacy_interrupt_line {
// legacy INTx# interrupt pins.
(Some(File::open(format!("irq:{}", irq)).expect("xhcid: failed to open legacy IRQ file")), InterruptMethod::Intx)
(Some(irq.irq_handle("xhcid")), InterruptMethod::Intx)
} else {
// no interrupts at all
(None, InterruptMethod::Polling)
@@ -234,20 +232,13 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
let _logger_ref = setup_logging(&name);
log::debug!("XHCI PCI CONFIG: {:?}", pci_config);
let (bar_ptr, bar_size) = pci_config.func.bars[0].expect_mem();
let irq = pci_config.func.legacy_interrupt_line;
let bar = &pci_config.func.bars[0];
let address = unsafe {
common::physmap(bar_ptr, bar_size, common::Prot::RW, common::MemoryType::Uncacheable)
.expect("xhcid: failed to map address") as usize
};
let address = unsafe { bar.physmap_mem("xhcid") } as usize;
let (mut irq_file, interrupt_method) = get_int_method(&mut pcid_handle, address);
let (irq_file, interrupt_method) = get_int_method(&mut pcid_handle, address);
print!(
"{}",
format!(" + XHCI {} on: {:016X} IRQ: {}\n", name, bar_ptr, irq)
);
println!(" + XHCI {}", pci_config.func.display());
let scheme_name = format!("usb.{}", name);
let socket_fd = syscall::open(