Merge branch 'pci_interrupts_rework5' into 'master'
Deduplicate int vector handling between ihdad and rtl network drivers See merge request redox-os/drivers!298
This commit is contained in:
+2
-38
@@ -11,8 +11,7 @@ use std::usize;
|
||||
use syscall::{Packet, SchemeBlockMut};
|
||||
|
||||
use event::{user_data, EventQueue};
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use pcid_interface::irq_helpers::allocate_first_msi_interrupt_on_bsp;
|
||||
use pcid_interface::irq_helpers::pci_allocate_interrupt_vector;
|
||||
use pcid_interface::PciFunctionHandle;
|
||||
|
||||
pub mod hda;
|
||||
@@ -24,40 +23,6 @@ QEMU ICH9 8086:293E
|
||||
82801H ICH8 8086:284B
|
||||
*/
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> File {
|
||||
let pci_config = pcid_handle.config();
|
||||
|
||||
let all_pci_features = pcid_handle.fetch_all_features();
|
||||
log::debug!("PCI FEATURES: {:?}", all_pci_features);
|
||||
|
||||
let has_msi = all_pci_features.iter().any(|feature| feature.is_msi());
|
||||
|
||||
if has_msi {
|
||||
allocate_first_msi_interrupt_on_bsp(pcid_handle)
|
||||
} else if let Some(irq) = pci_config.func.legacy_interrupt_line {
|
||||
log::debug!("Legacy IRQ {}", irq);
|
||||
|
||||
// legacy INTx# interrupt pins.
|
||||
irq.irq_handle("ihdad")
|
||||
} else {
|
||||
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 PciFunctionHandle) -> File {
|
||||
let pci_config = pcid_handle.config();
|
||||
|
||||
if let Some(irq) = pci_config.func.legacy_interrupt_line {
|
||||
// legacy INTx# interrupt pins.
|
||||
irq.irq_handle("ihdad")
|
||||
} else {
|
||||
panic!("ihdad: no interrupts supported at all")
|
||||
}
|
||||
}
|
||||
|
||||
fn daemon(daemon: redox_daemon::Daemon) -> ! {
|
||||
let mut pcid_handle = PciFunctionHandle::connect_default();
|
||||
|
||||
@@ -78,8 +43,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
|
||||
|
||||
let address = unsafe { pcid_handle.map_bar(0) }.ptr.as_ptr() as usize;
|
||||
|
||||
//TODO: MSI-X
|
||||
let mut irq_file = get_int_method(&mut pcid_handle);
|
||||
let mut irq_file = pci_allocate_interrupt_vector(&mut pcid_handle, "ihdad");
|
||||
|
||||
{
|
||||
let vend_prod: u32 = ((pci_config.func.full_device_id.vendor_id as u32) << 16)
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Write};
|
||||
use std::os::unix::io::AsRawFd;
|
||||
|
||||
use driver_network::NetworkScheme;
|
||||
use event::{user_data, EventQueue};
|
||||
use pcid_interface::irq_helpers::read_bsp_apic_id;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use pcid_interface::irq_helpers::{
|
||||
allocate_first_msi_interrupt_on_bsp, allocate_single_interrupt_vector_for_msi,
|
||||
};
|
||||
use pcid_interface::{PciFeature, PciFeatureInfo, PciFunctionHandle};
|
||||
use pcid_interface::irq_helpers::pci_allocate_interrupt_vector;
|
||||
use pcid_interface::PciFunctionHandle;
|
||||
|
||||
pub mod device;
|
||||
|
||||
@@ -25,67 +20,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> File {
|
||||
let pci_config = pcid_handle.config();
|
||||
|
||||
let all_pci_features = pcid_handle.fetch_all_features();
|
||||
log::info!("PCI FEATURES: {:?}", all_pci_features);
|
||||
|
||||
let has_msi = all_pci_features.iter().any(|feature| feature.is_msi());
|
||||
let has_msix = all_pci_features.iter().any(|feature| feature.is_msix());
|
||||
|
||||
if has_msix {
|
||||
let msix_info = match pcid_handle.feature_info(PciFeature::MsiX) {
|
||||
PciFeatureInfo::Msi(_) => panic!(),
|
||||
PciFeatureInfo::MsiX(s) => s,
|
||||
};
|
||||
let mut info = unsafe { msix_info.map_and_mask_all(pcid_handle) };
|
||||
|
||||
// Allocate one msi vector.
|
||||
|
||||
let method = {
|
||||
// primary interrupter
|
||||
let k = 0;
|
||||
|
||||
let table_entry_pointer = info.table_entry_pointer(k);
|
||||
|
||||
let destination_id = read_bsp_apic_id().expect("rtl8139d: failed to read BSP apic id");
|
||||
let (msg_addr_and_data, interrupt_handle) =
|
||||
allocate_single_interrupt_vector_for_msi(destination_id);
|
||||
table_entry_pointer.write_addr_and_data(msg_addr_and_data);
|
||||
table_entry_pointer.unmask();
|
||||
|
||||
interrupt_handle
|
||||
};
|
||||
|
||||
pcid_handle.enable_feature(PciFeature::MsiX);
|
||||
log::debug!("Enabled MSI-X");
|
||||
|
||||
method
|
||||
} else if has_msi {
|
||||
allocate_first_msi_interrupt_on_bsp(pcid_handle)
|
||||
} else if let Some(irq) = pci_config.func.legacy_interrupt_line {
|
||||
// legacy INTx# interrupt pins.
|
||||
irq.irq_handle("rtl8139d")
|
||||
} else {
|
||||
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 PciFunctionHandle) -> File {
|
||||
let pci_config = pcid_handle.config();
|
||||
|
||||
if let Some(irq) = pci_config.func.legacy_interrupt_line {
|
||||
// legacy INTx# interrupt pins.
|
||||
irq.irq_handle("rtl8139d")
|
||||
} else {
|
||||
panic!("rtl8139d: no interrupts supported at all")
|
||||
}
|
||||
}
|
||||
|
||||
fn map_bar(pcid_handle: &mut PciFunctionHandle) -> *mut u8 {
|
||||
let config = pcid_handle.config();
|
||||
|
||||
@@ -121,8 +55,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
|
||||
|
||||
let bar = map_bar(&mut pcid_handle);
|
||||
|
||||
//TODO: MSI-X
|
||||
let mut irq_file = get_int_method(&mut pcid_handle);
|
||||
let mut irq_file = pci_allocate_interrupt_vector(&mut pcid_handle, "rtl8139d");
|
||||
|
||||
let mut scheme = NetworkScheme::new(
|
||||
move || unsafe {
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Write};
|
||||
use std::os::unix::io::AsRawFd;
|
||||
|
||||
use driver_network::NetworkScheme;
|
||||
use event::{user_data, EventQueue};
|
||||
use pcid_interface::irq_helpers::read_bsp_apic_id;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use pcid_interface::irq_helpers::{
|
||||
allocate_first_msi_interrupt_on_bsp, allocate_single_interrupt_vector_for_msi,
|
||||
};
|
||||
use pcid_interface::{PciFeature, PciFeatureInfo, PciFunctionHandle};
|
||||
use pcid_interface::irq_helpers::pci_allocate_interrupt_vector;
|
||||
use pcid_interface::PciFunctionHandle;
|
||||
|
||||
pub mod device;
|
||||
|
||||
@@ -25,67 +20,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> File {
|
||||
let pci_config = pcid_handle.config();
|
||||
|
||||
let all_pci_features = pcid_handle.fetch_all_features();
|
||||
log::info!("PCI FEATURES: {:?}", all_pci_features);
|
||||
|
||||
let has_msi = all_pci_features.iter().any(|feature| feature.is_msi());
|
||||
let has_msix = all_pci_features.iter().any(|feature| feature.is_msix());
|
||||
|
||||
if has_msix {
|
||||
let msix_info = match pcid_handle.feature_info(PciFeature::MsiX) {
|
||||
PciFeatureInfo::Msi(_) => panic!(),
|
||||
PciFeatureInfo::MsiX(s) => s,
|
||||
};
|
||||
let mut info = unsafe { msix_info.map_and_mask_all(pcid_handle) };
|
||||
|
||||
// Allocate one msi vector.
|
||||
|
||||
let method = {
|
||||
// primary interrupter
|
||||
let k = 0;
|
||||
|
||||
let table_entry_pointer = info.table_entry_pointer(k);
|
||||
|
||||
let destination_id = read_bsp_apic_id().expect("rtl8168d: failed to read BSP apic id");
|
||||
let (msg_addr_and_data, interrupt_handle) =
|
||||
allocate_single_interrupt_vector_for_msi(destination_id);
|
||||
table_entry_pointer.write_addr_and_data(msg_addr_and_data);
|
||||
table_entry_pointer.unmask();
|
||||
|
||||
interrupt_handle
|
||||
};
|
||||
|
||||
pcid_handle.enable_feature(PciFeature::MsiX);
|
||||
log::debug!("Enabled MSI-X");
|
||||
|
||||
method
|
||||
} else if has_msi {
|
||||
allocate_first_msi_interrupt_on_bsp(pcid_handle)
|
||||
} else if let Some(irq) = pci_config.func.legacy_interrupt_line {
|
||||
// legacy INTx# interrupt pins.
|
||||
irq.irq_handle("rtl8168d")
|
||||
} else {
|
||||
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 PciFunctionHandle) -> File {
|
||||
let pci_config = pcid_handle.config();
|
||||
|
||||
if let Some(irq) = pci_config.func.legacy_interrupt_line {
|
||||
// legacy INTx# interrupt pins.
|
||||
irq.irq_handle("rtl8168d")
|
||||
} else {
|
||||
panic!("rtl8168d: no interrupts supported at all")
|
||||
}
|
||||
}
|
||||
|
||||
fn map_bar(pcid_handle: &mut PciFunctionHandle) -> *mut u8 {
|
||||
let config = pcid_handle.config();
|
||||
|
||||
@@ -121,8 +55,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
|
||||
|
||||
let bar = map_bar(&mut pcid_handle);
|
||||
|
||||
//TODO: MSI-X
|
||||
let mut irq_file = get_int_method(&mut pcid_handle);
|
||||
let mut irq_file = pci_allocate_interrupt_vector(&mut pcid_handle, "rtl8168d");
|
||||
|
||||
let mut scheme = NetworkScheme::new(
|
||||
move || unsafe {
|
||||
|
||||
@@ -227,3 +227,57 @@ pub fn allocate_first_msi_interrupt_on_bsp(
|
||||
|
||||
interrupt_handle
|
||||
}
|
||||
|
||||
/// Get the most optimal supported interrupt mechanism: either (in the order of preference):
|
||||
/// MSI-X, MSI, and INTx# pin. Returns the handles to the interrupts.
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
pub fn pci_allocate_interrupt_vector(
|
||||
pcid_handle: &mut crate::driver_interface::PciFunctionHandle,
|
||||
driver: &str,
|
||||
) -> File {
|
||||
let features = pcid_handle.fetch_all_features();
|
||||
|
||||
let has_msi = features.iter().any(|feature| feature.is_msi());
|
||||
let has_msix = features.iter().any(|feature| feature.is_msix());
|
||||
|
||||
if has_msix {
|
||||
let capability_struct = match pcid_handle.feature_info(super::PciFeature::MsiX) {
|
||||
super::PciFeatureInfo::MsiX(msix) => msix,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let mut info = unsafe { capability_struct.map_and_mask_all(pcid_handle) };
|
||||
|
||||
pcid_handle.enable_feature(crate::driver_interface::PciFeature::MsiX);
|
||||
|
||||
let entry = info.table_entry_pointer(0);
|
||||
|
||||
let bsp_cpu_id = read_bsp_apic_id()
|
||||
.unwrap_or_else(|err| panic!("{driver}: failed to read BSP APIC ID: {err}"));
|
||||
let (msg_addr_and_data, irq_handle) = allocate_single_interrupt_vector_for_msi(bsp_cpu_id);
|
||||
entry.write_addr_and_data(msg_addr_and_data);
|
||||
entry.unmask();
|
||||
|
||||
irq_handle
|
||||
} else if has_msi {
|
||||
allocate_first_msi_interrupt_on_bsp(pcid_handle)
|
||||
} else if let Some(irq) = pcid_handle.config().func.legacy_interrupt_line {
|
||||
// INTx# pin based interrupts.
|
||||
irq.irq_handle(driver)
|
||||
} else {
|
||||
panic!("{driver}: no interrupts supported at all")
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME support MSI on non-x86 systems
|
||||
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
|
||||
fn pci_allocate_interrupt_vector(
|
||||
pcid_handle: &mut crate::driver_interface::PcidServerHandle,
|
||||
driver: &str,
|
||||
) -> Vec<File> {
|
||||
if let Some(irq) = pcid_handle.config().func.legacy_interrupt_line {
|
||||
// INTx# pin based interrupts.
|
||||
irq.irq_handle(driver)
|
||||
} else {
|
||||
panic!("{driver}: no interrupts supported at all")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user