1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
use core::fmt;

pub mod ctx;
pub use self::ctx::Context;

/// An interrupt controller for a platform.
pub trait Control {
    type Registers: fmt::Debug + fmt::Display;

    /// Disable all interrupts.
    ///
    /// # Safety
    ///
    /// This may cause a fault if called when interrupts are already disabled
    /// (depending on the platform). It does not guarantee that interrupts will
    /// ever be unmasked.
    unsafe fn disable(&mut self);

    /// Enable all interrupts.
    ///
    /// # Safety
    ///
    /// This may cause a fault if called when interrupts are already enabled
    /// (depending on the platform).
    unsafe fn enable(&mut self);

    /// Returns `true` if interrupts are enabled.
    fn is_enabled(&self) -> bool;

    fn register_handlers<H>(&mut self) -> Result<(), RegistrationError>
    where
        H: Handlers<Self::Registers>;

    /// Enter a critical section, returning a guard.
    fn enter_critical(&mut self) -> CriticalGuard<'_, Self> {
        unsafe {
            self.disable();
        }
        CriticalGuard { ctrl: self }
    }
}

pub trait Handlers<R: fmt::Debug + fmt::Display> {
    fn page_fault<C>(cx: C)
    where
        C: ctx::Context<Registers = R> + ctx::PageFault;

    fn code_fault<C>(cx: C)
    where
        C: ctx::Context<Registers = R> + ctx::CodeFault;

    fn double_fault<C>(cx: C)
    where
        C: ctx::Context<Registers = R>;

    fn timer_tick();

    /// Called when a PS/2 keyboard interrupt is fired. The handler is provided
    /// with the scancode read from the PS/2 keyboard controller.
    fn ps2_keyboard(scancode: u8);

    fn test_interrupt<C>(_cx: C)
    where
        C: ctx::Context<Registers = R>,
    {
        // nop
    }
}

/// Errors that may occur while registering an interrupt handler.
#[derive(Clone, Eq, PartialEq)]
pub struct RegistrationError {
    kind: RegistrationErrorKind,
}

#[derive(Debug)]
pub struct CriticalGuard<'a, C: Control + ?Sized> {
    ctrl: &'a mut C,
}

#[derive(Debug, Clone, Eq, PartialEq)]
enum RegistrationErrorKind {
    Nonexistant,
    AlreadyRegistered,
    Other(&'static str),
}

// === impl CriticalGuard ===

impl<'a, C: Control + ?Sized> Drop for CriticalGuard<'a, C> {
    fn drop(&mut self) {
        unsafe {
            self.ctrl.enable();
        }
    }
}

// === impl RegistrationError ===
impl RegistrationError {
    /// Returns a new error indicating that the registered interrupt vector does
    /// not exist.
    pub fn nonexistant() -> Self {
        Self {
            kind: RegistrationErrorKind::Nonexistant,
        }
    }

    /// Returns a new error indicating that the registered interrupt vector has
    /// already been registered and cannot be registered again.
    pub fn already_registered() -> Self {
        Self {
            kind: RegistrationErrorKind::AlreadyRegistered,
        }
    }

    /// Returns a new platform-specific error with the provided message.
    pub fn other(message: &'static str) -> Self {
        Self {
            kind: RegistrationErrorKind::Other(message),
        }
    }

    pub fn is_nonexistant(&self) -> bool {
        matches!(self.kind, RegistrationErrorKind::Nonexistant)
    }

    pub fn is_already_registered(&self) -> bool {
        matches!(self.kind, RegistrationErrorKind::AlreadyRegistered)
    }
}

impl fmt::Debug for RegistrationError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let Self { kind } = self;
        f.debug_struct("RegistrationError")
            .field("kind", kind)
            .finish()
    }
}