78 lines
2.0 KiB
Rust
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()
|
|
}
|
|
}
|