diff --git a/ac97d/src/main.rs b/ac97d/src/main.rs index 04a5f3f7be..2a26dc193b 100644 --- a/ac97d/src/main.rs +++ b/ac97d/src/main.rs @@ -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"); diff --git a/ahcid/src/main.rs b/ahcid/src/main.rs index 3d661c321f..60dd30ab12 100644 --- a/ahcid/src/main.rs +++ b/ahcid/src/main.rs @@ -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"); diff --git a/alxd/src/device/mod.rs b/alxd/src/device/mod.rs index 04da35d59e..e3d8ff4996 100644 --- a/alxd/src/device/mod.rs +++ b/alxd/src/device/mod.rs @@ -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() { diff --git a/alxd/src/main.rs b/alxd/src/main.rs index d52371f94a..9bd0d6edb3 100644 --- a/alxd/src/main.rs +++ b/alxd/src/main.rs @@ -32,7 +32,7 @@ fn main() { let irq_str = args.next().expect("alxd: no irq provided"); let irq = irq_str.parse::().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| { diff --git a/bgad/src/main.rs b/bgad/src/main.rs index e9b7bb7600..18ac70df34 100644 --- a/bgad/src/main.rs +++ b/bgad/src/main.rs @@ -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() }; diff --git a/e1000d/src/main.rs b/e1000d/src/main.rs index dffeb43f4d..1746883701 100644 --- a/e1000d/src/main.rs +++ b/e1000d/src/main.rs @@ -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") diff --git a/ihdad/src/main.rs b/ihdad/src/main.rs index 860446ad5c..7f87807b40 100755 --- a/ihdad/src/main.rs +++ b/ihdad/src/main.rs @@ -74,11 +74,9 @@ fn setup_logging() -> Option<&'static RedoxLogger> { } #[cfg(target_arch = "x86_64")] -fn get_int_method(pcid_handle: &mut PcidServerHandle) -> Option { +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 { 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 { +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) diff --git a/ixgbed/src/main.rs b/ixgbed/src/main.rs index 4666b98142..a5ec7bfa7f 100644 --- a/ixgbed/src/main.rs +++ b/ixgbed/src/main.rs @@ -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) diff --git a/nvmed/src/main.rs b/nvmed/src/main.rs index 09ced15aff..8e57eb4db0 100644 --- a/nvmed/src/main.rs +++ b/nvmed/src/main.rs @@ -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"), }); diff --git a/pcid/Cargo.toml b/pcid/Cargo.toml index 794002fb18..b883b4e8ce 100644 --- a/pcid/Cargo.toml +++ b/pcid/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "pcid" version = "0.1.0" -edition = "2018" +edition = "2021" [[bin]] name = "pcid" diff --git a/pcid/src/driver_interface/mod.rs b/pcid/src/driver_interface/mod.rs index 36c002a15f..88b7068915 100644 --- a/pcid/src/driver_interface/mod.rs +++ b/pcid/src/driver_interface/mod.rs @@ -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, + /// If INTx# interrupts aren't supported at all this is `None`. + pub legacy_interrupt_line: Option, /// 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)] diff --git a/pcid/src/main.rs b/pcid/src/main.rs index 2858433a43..bbc46d0794 100644 --- a/pcid/src/main.rs +++ b/pcid/src/main.rs @@ -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, 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, 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, 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(), }; diff --git a/pcid/src/pci/bar.rs b/pcid/src/pci/bar.rs index 4ee887d91f..b9e8008f51 100644 --- a/pcid/src/pci/bar.rs +++ b/pcid/src/pci/bar.rs @@ -11,6 +11,15 @@ pub enum PciBar { } impl PciBar { + pub fn display(&self) -> String { + match self { + PciBar::None => format!(""), + 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}")) + } } diff --git a/pcid/src/pci/msi.rs b/pcid/src/pci/msi.rs index ba37e30127..fe09768a91 100644 --- a/pcid/src/pci/msi.rs +++ b/pcid/src/pci/msi.rs @@ -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(&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(&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(&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(&self, writer: &W, offset: u8) { - self.write_a(writer, offset); - self.write_b(writer, offset); - self.write_c(writer, offset); - } } #[repr(packed)] diff --git a/rtl8139d/src/main.rs b/rtl8139d/src/main.rs index dc3616a08a..e0bfbf2648 100644 --- a/rtl8139d/src/main.rs +++ b/rtl8139d/src/main.rs @@ -108,11 +108,9 @@ impl MsixInfo { } #[cfg(target_arch = "x86_64")] -fn get_int_method(pcid_handle: &mut PcidServerHandle) -> Option { +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 { 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 { 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 { 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 { +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 { diff --git a/rtl8168d/src/main.rs b/rtl8168d/src/main.rs index 2592100b2c..d157ab8706 100644 --- a/rtl8168d/src/main.rs +++ b/rtl8168d/src/main.rs @@ -106,11 +106,9 @@ impl MsixInfo { } #[cfg(target_arch = "x86_64")] -fn get_int_method(pcid_handle: &mut PcidServerHandle) -> Option { +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 { 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 { 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 { 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 { +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 { diff --git a/sb16d/src/main.rs b/sb16d/src/main.rs index 5415e2fcb6..6671ac9b39 100644 --- a/sb16d/src/main.rs +++ b/sb16d/src/main.rs @@ -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| { diff --git a/vboxd/src/main.rs b/vboxd/src/main.rs index 77f43eb10d..7555482450 100644 --- a/vboxd/src/main.rs +++ b/vboxd/src/main.rs @@ -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::::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) }; diff --git a/virtio-core/src/arch/x86_64.rs b/virtio-core/src/arch/x86_64.rs index 5bccd00c2a..a160f508cd 100644 --- a/virtio-core/src/arch/x86_64.rs +++ b/virtio-core/src/arch/x86_64.rs @@ -27,16 +27,10 @@ pub fn enable_msix(pcid_handle: &mut PcidServerHandle) -> Result { 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. { diff --git a/xhcid/src/main.rs b/xhcid/src/main.rs index 9c8dbf542e..c6dd1565a5 100644 --- a/xhcid/src/main.rs +++ b/xhcid/src/main.rs @@ -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, 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(