Files
k-os/crates/domain/src/irq/mod.rs

78 lines
2.0 KiB
Rust

use types::{
badge::Badge,
generation::Generation,
id::{IrqId, NotificationId, ProcessId},
};
#[cfg(test)]
#[path = "tests.rs"]
mod tests;
const MAX_IRQS: usize = if cfg!(kani) { 2 } else { 256 };
/// Where an interrupt is delivered: a signal on a notification, through a
/// capability snapshot (generation and badge) taken when the route was set.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct IrqRoute {
pub notification: NotificationId,
pub generation: Generation,
pub badge: Badge,
/// The process that set the route, and so owns the line.
pub owner: ProcessId,
}
pub struct IrqRoutingTable {
routes: [Option<IrqRoute>; MAX_IRQS],
}
impl IrqRoutingTable {
pub fn new() -> Self {
Self {
routes: [None; MAX_IRQS],
}
}
/// Whether `irq` is a line this table can route.
pub fn is_valid(&self, irq: IrqId) -> bool {
(irq.raw() as usize) < MAX_IRQS
}
/// Routes `irq`, replacing any previous route. Fails for lines beyond
/// the table.
pub fn set(&mut self, irq: IrqId, route: IrqRoute) -> bool {
match self.routes.get_mut(irq.raw() as usize) {
Some(slot) => {
*slot = Some(route);
true
}
None => false,
}
}
pub fn clear(&mut self, irq: IrqId) {
if let Some(slot) = self.routes.get_mut(irq.raw() as usize) {
*slot = None;
}
}
/// Drops every route `owner` set, when it dies.
pub fn clear_owned_by(&mut self, owner: ProcessId) {
for slot in self.routes.iter_mut() {
if slot.is_some_and(|r| r.owner == owner) {
*slot = None;
}
}
}
/// The route for `irq`; `None` for unknown or unrouted lines.
pub fn route(&self, irq: IrqId) -> Option<IrqRoute> {
*self.routes.get(irq.raw() as usize)?
}
}
impl Default for IrqRoutingTable {
fn default() -> Self {
Self::new()
}
}