diff --git a/kernel/src/arch/mipsel/interrupt.rs b/kernel/src/arch/mipsel/interrupt.rs index 031cd7a6..96858f39 100644 --- a/kernel/src/arch/mipsel/interrupt.rs +++ b/kernel/src/arch/mipsel/interrupt.rs @@ -1,6 +1,6 @@ pub use self::context::*; use crate::arch::paging::get_root_page_table_ptr; -use crate::drivers::DRIVERS; +use crate::drivers::{DRIVERS, IRQ_MANAGER}; use log::*; use mips::addr::*; use mips::interrupts; @@ -131,13 +131,7 @@ fn try_process_serial() -> bool { } fn try_process_drivers() -> bool { - // TODO - for driver in DRIVERS.read().iter() { - if driver.try_handle_interrupt(None) == true { - return true; - } - } - return false; + IRQ_MANAGER.read().try_handle_interrupt(None) } fn ipi() { diff --git a/kernel/src/arch/riscv32/interrupt.rs b/kernel/src/arch/riscv32/interrupt.rs index d8dfa78f..8a342b91 100644 --- a/kernel/src/arch/riscv32/interrupt.rs +++ b/kernel/src/arch/riscv32/interrupt.rs @@ -1,5 +1,5 @@ pub use self::context::*; -use crate::drivers::DRIVERS; +use crate::drivers::{DRIVERS, IRQ_MANAGER}; use log::*; use riscv::register::*; @@ -99,12 +99,7 @@ fn try_process_serial() -> bool { } fn try_process_drivers() -> bool { - for driver in DRIVERS.read().iter() { - if driver.try_handle_interrupt(None) == true { - return true; - } - } - return false; + IRQ_MANAGER.read().try_handle_interrupt(None) } fn ipi() { diff --git a/kernel/src/arch/x86_64/interrupt/handler.rs b/kernel/src/arch/x86_64/interrupt/handler.rs index 2b5c0998..55a51f72 100644 --- a/kernel/src/arch/x86_64/interrupt/handler.rs +++ b/kernel/src/arch/x86_64/interrupt/handler.rs @@ -66,7 +66,7 @@ use super::consts::*; use super::TrapFrame; -use crate::drivers::DRIVERS; +use crate::drivers::{DRIVERS, IRQ_MANAGER}; use bitflags::*; use log::*; @@ -96,11 +96,9 @@ pub extern "C" fn rust_trap(tf: &mut TrapFrame) { COM2 => com2(), IDE => ide(), _ => { - for driver in DRIVERS.read().iter() { - if driver.try_handle_interrupt(Some(irq.into())) == true { - debug!("driver processed interrupt"); - return; - } + if IRQ_MANAGER.read().try_handle_interrupt(Some(irq.into())) { + debug!("driver processed interrupt"); + return; } warn!("unhandled external IRQ number: {}", irq); } diff --git a/kernel/src/drivers/block/virtio_blk.rs b/kernel/src/drivers/block/virtio_blk.rs index 5510851e..d3344815 100644 --- a/kernel/src/drivers/block/virtio_blk.rs +++ b/kernel/src/drivers/block/virtio_blk.rs @@ -14,7 +14,7 @@ use volatile::Volatile; use crate::sync::SpinNoIrqLock as Mutex; use super::super::bus::virtio_mmio::*; -use super::super::{DeviceType, Driver, BLK_DRIVERS, DRIVERS}; +use super::super::{DeviceType, Driver, BLK_DRIVERS, DRIVERS, IRQ_MANAGER}; use crate::memory::phys_to_virt; pub struct VirtIOBlk { @@ -213,5 +213,6 @@ pub fn virtio_blk_init(node: &Node) { let driver = Arc::new(driver); DRIVERS.write().push(driver.clone()); + IRQ_MANAGER.write().register_all(driver.clone()); BLK_DRIVERS.write().push(driver); } diff --git a/kernel/src/drivers/gpu/virtio_gpu.rs b/kernel/src/drivers/gpu/virtio_gpu.rs index 63c9f9d2..d0782058 100644 --- a/kernel/src/drivers/gpu/virtio_gpu.rs +++ b/kernel/src/drivers/gpu/virtio_gpu.rs @@ -16,7 +16,7 @@ use crate::sync::SpinNoIrqLock as Mutex; use crate::HEAP_ALLOCATOR; use super::super::bus::virtio_mmio::*; -use super::super::{DeviceType, Driver, DRIVERS}; +use super::super::{DeviceType, Driver, DRIVERS, IRQ_MANAGER}; use super::test::mandelbrot; use crate::memory::phys_to_virt; @@ -399,5 +399,6 @@ pub fn virtio_gpu_init(node: &Node) { setup_framebuffer(&mut driver); let driver = Arc::new(VirtIOGpuDriver(Mutex::new(driver))); + IRQ_MANAGER.write().register_all(driver.clone()); DRIVERS.write().push(driver); } diff --git a/kernel/src/drivers/input/virtio_input.rs b/kernel/src/drivers/input/virtio_input.rs index 9c3fd5d0..0838426f 100644 --- a/kernel/src/drivers/input/virtio_input.rs +++ b/kernel/src/drivers/input/virtio_input.rs @@ -18,7 +18,7 @@ use crate::arch::cpu; use crate::sync::SpinNoIrqLock as Mutex; use super::super::bus::virtio_mmio::*; -use super::super::{DeviceType, Driver, DRIVERS}; +use super::super::{DeviceType, Driver, DRIVERS, IRQ_MANAGER}; use crate::memory::phys_to_virt; struct VirtIOInput { @@ -222,5 +222,6 @@ pub fn virtio_input_init(node: &Node) { .write(VirtIODeviceStatus::DRIVER_OK.bits()); let driver = Arc::new(VirtIOInputDriver(Mutex::new(driver))); + IRQ_MANAGER.write().register_all(driver.clone()); DRIVERS.write().push(driver); } diff --git a/kernel/src/drivers/irq.rs b/kernel/src/drivers/irq.rs index 425537a6..6892cc18 100644 --- a/kernel/src/drivers/irq.rs +++ b/kernel/src/drivers/irq.rs @@ -4,7 +4,7 @@ use alloc::collections::BTreeMap; use alloc::sync::Arc; use alloc::vec::Vec; -struct IrqManager { +pub struct IrqManager { // drivers that only respond to specific irq mapping: BTreeMap>>, // drivers that respond to all irqs @@ -36,6 +36,14 @@ impl IrqManager { self.all.push(driver); } + pub fn register_opt(&mut self, irq_opt: Option, driver: Arc) { + if let Some(irq) = irq_opt { + self.register_irq(irq, driver); + } else { + self.register_all(driver); + } + } + pub fn deregister_irq(&mut self, irq: u32, driver: Arc) { if let Some(e) = self.mapping.get_mut(&irq) { e.retain(|d| !Arc::ptr_eq(&d, &driver)); @@ -46,17 +54,19 @@ impl IrqManager { self.all.retain(|d| !Arc::ptr_eq(&d, &driver)); } - pub fn handle_interrupt(&self, irq: u32) -> bool { - if let Some(e) = self.mapping.get(&irq) { - for dri in e.iter() { - if dri.try_handle_interrupt(Some(irq)) { - return true; + pub fn try_handle_interrupt(&self, irq_opt: Option) -> bool { + if let Some(irq) = irq_opt { + if let Some(e) = self.mapping.get(&irq) { + for dri in e.iter() { + if dri.try_handle_interrupt(Some(irq)) { + return true; + } } } } for dri in self.all.iter() { - if dri.try_handle_interrupt(Some(irq)) { + if dri.try_handle_interrupt(irq_opt) { return true; } } diff --git a/kernel/src/drivers/mod.rs b/kernel/src/drivers/mod.rs index c7ba751e..2ad36367 100644 --- a/kernel/src/drivers/mod.rs +++ b/kernel/src/drivers/mod.rs @@ -97,6 +97,7 @@ lazy_static! { pub static ref DRIVERS: RwLock>> = RwLock::new(Vec::new()); pub static ref NET_DRIVERS: RwLock>> = RwLock::new(Vec::new()); pub static ref BLK_DRIVERS: RwLock>> = RwLock::new(Vec::new()); + pub static ref IRQ_MANAGER: RwLock = RwLock::new(irq::IrqManager::new()); } pub struct BlockDriver(pub Arc); diff --git a/kernel/src/drivers/net/e1000.rs b/kernel/src/drivers/net/e1000.rs index 24e34aa9..76c8b101 100644 --- a/kernel/src/drivers/net/e1000.rs +++ b/kernel/src/drivers/net/e1000.rs @@ -20,7 +20,7 @@ use crate::drivers::provider::Provider; use crate::net::SOCKETS; use crate::sync::SpinNoIrqLock as Mutex; -use super::super::{DeviceType, Driver, DRIVERS, NET_DRIVERS, SOCKET_ACTIVITY}; +use super::super::{DeviceType, Driver, DRIVERS, IRQ_MANAGER, NET_DRIVERS, SOCKET_ACTIVITY}; #[derive(Clone)] pub struct E1000Driver(Arc>>); @@ -202,5 +202,6 @@ pub fn init(name: String, irq: Option, header: usize, size: usize, index: u let driver = Arc::new(e1000_iface); DRIVERS.write().push(driver.clone()); + IRQ_MANAGER.write().register_opt(irq, driver.clone()); NET_DRIVERS.write().push(driver); } diff --git a/kernel/src/drivers/net/ixgbe.rs b/kernel/src/drivers/net/ixgbe.rs index 2921a785..9973f62c 100644 --- a/kernel/src/drivers/net/ixgbe.rs +++ b/kernel/src/drivers/net/ixgbe.rs @@ -19,7 +19,9 @@ use crate::net::SOCKETS; use crate::sync::FlagsGuard; use crate::sync::SpinNoIrqLock as Mutex; -use super::super::{provider::Provider, DeviceType, Driver, DRIVERS, NET_DRIVERS, SOCKET_ACTIVITY}; +use super::super::{ + provider::Provider, DeviceType, Driver, DRIVERS, IRQ_MANAGER, NET_DRIVERS, SOCKET_ACTIVITY, +}; #[derive(Clone)] struct IXGBEDriver { @@ -220,6 +222,7 @@ pub fn ixgbe_init( }; let driver = Arc::new(ixgbe_iface); + IRQ_MANAGER.write().register_opt(irq, driver.clone()); DRIVERS.write().push(driver.clone()); NET_DRIVERS.write().push(driver.clone()); driver diff --git a/kernel/src/drivers/net/router.rs b/kernel/src/drivers/net/router.rs index 6577d5b2..5aa38c05 100644 --- a/kernel/src/drivers/net/router.rs +++ b/kernel/src/drivers/net/router.rs @@ -15,7 +15,7 @@ use smoltcp::Result; use crate::net::SOCKETS; use crate::sync::SpinNoIrqLock as Mutex; -use super::super::{DeviceType, Driver, DRIVERS, NET_DRIVERS, SOCKET_ACTIVITY}; +use super::super::{DeviceType, Driver, DRIVERS, IRQ_MANAGER, NET_DRIVERS, SOCKET_ACTIVITY}; use crate::memory::phys_to_virt; const AXI_STREAM_FIFO_ISR: *mut u32 = phys_to_virt(0x64A0_0000) as *mut u32; @@ -253,6 +253,7 @@ pub fn router_init() { let driver = Arc::new(router_iface); DRIVERS.write().push(driver.clone()); + IRQ_MANAGER.write().register_all(driver.clone()); NET_DRIVERS.write().push(driver.clone()); } diff --git a/kernel/src/drivers/net/virtio_net.rs b/kernel/src/drivers/net/virtio_net.rs index c18e3106..da1f31c2 100644 --- a/kernel/src/drivers/net/virtio_net.rs +++ b/kernel/src/drivers/net/virtio_net.rs @@ -20,7 +20,7 @@ use crate::sync::SpinNoIrqLock as Mutex; use crate::HEAP_ALLOCATOR; use super::super::bus::virtio_mmio::*; -use super::super::{DeviceType, Driver, DRIVERS, NET_DRIVERS}; +use super::super::{DeviceType, Driver, DRIVERS, IRQ_MANAGER, NET_DRIVERS}; use crate::memory::phys_to_virt; pub struct VirtIONet { @@ -290,5 +290,6 @@ pub fn virtio_net_init(node: &Node) { let net_driver = Arc::new(VirtIONetDriver(Arc::new(Mutex::new(driver)))); DRIVERS.write().push(net_driver.clone()); + IRQ_MANAGER.write().register_all(net_driver.clone()); NET_DRIVERS.write().push(net_driver); }