2021-10-09 06:11:52 +00:00
|
|
|
|
2021-10-09 18:00:32 +00:00
|
|
|
use std::iter;
|
|
|
|
|
2021-10-09 06:11:52 +00:00
|
|
|
use crate::error::Error;
|
2021-10-17 17:39:43 +00:00
|
|
|
use crate::devices::TransmutableBox;
|
2021-10-09 06:11:52 +00:00
|
|
|
|
|
|
|
|
|
|
|
pub struct Signal {
|
|
|
|
pub current: bool,
|
|
|
|
pub previous: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Signal {
|
|
|
|
pub fn new() -> Signal {
|
|
|
|
Signal {
|
|
|
|
current: false,
|
|
|
|
previous: false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-09 18:00:32 +00:00
|
|
|
pub fn has_changed(&mut self) -> Option<bool> {
|
2021-10-09 06:11:52 +00:00
|
|
|
if self.current != self.previous {
|
|
|
|
self.previous = self.current;
|
2021-10-09 18:00:32 +00:00
|
|
|
Some(self.current)
|
2021-10-09 06:11:52 +00:00
|
|
|
} else {
|
2021-10-09 18:00:32 +00:00
|
|
|
None
|
2021-10-09 06:11:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set(&mut self, value: bool) {
|
|
|
|
self.current = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub struct InterruptController {
|
2021-10-17 17:39:43 +00:00
|
|
|
pub target: Option<TransmutableBox>,
|
2021-10-09 18:00:32 +00:00
|
|
|
pub priority: Vec<Signal>,
|
2021-10-09 06:11:52 +00:00
|
|
|
}
|
|
|
|
|
2021-10-09 18:00:32 +00:00
|
|
|
impl InterruptController {
|
|
|
|
pub fn new() -> InterruptController {
|
|
|
|
InterruptController {
|
|
|
|
target: None,
|
|
|
|
priority: iter::repeat_with(|| Signal::new()).take(7).collect::<Vec<_>>(), //vec![Signal::new(); 7],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-17 17:39:43 +00:00
|
|
|
pub fn set_target(&mut self, dev: TransmutableBox) -> Result<(), Error> {
|
2021-10-09 18:00:32 +00:00
|
|
|
if self.target.is_some() {
|
|
|
|
return Err(Error::new("Interruptable device already set, and interrupt controller only supports one receiver"));
|
|
|
|
}
|
|
|
|
|
|
|
|
self.target = Some(dev);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set(&mut self, state: bool, priority: u8, number: u8) -> Result<(), Error> {
|
|
|
|
let signal = &mut self.priority[priority as usize];
|
|
|
|
signal.set(state);
|
|
|
|
match signal.has_changed() {
|
|
|
|
Some(value) => self.notify_interrupt_state(value, priority, number)?,
|
|
|
|
None => { },
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn notify_interrupt_state(&mut self, state: bool, priority: u8, number: u8) -> Result<(), Error> {
|
|
|
|
// TODO how does this find the specific device it's connected to?
|
|
|
|
// TODO for the time being, this will find the first device to handle it or fail
|
|
|
|
|
2021-10-15 21:37:31 +00:00
|
|
|
debug!("interrupts: priority {} state changed to {}", priority, state);
|
2021-10-09 18:00:32 +00:00
|
|
|
match &self.target {
|
|
|
|
Some(dev) => {
|
2021-10-17 17:39:43 +00:00
|
|
|
Ok(dev.borrow_mut().as_interruptable().unwrap().interrupt_state_change(state, priority, number)?)
|
2021-10-09 18:00:32 +00:00
|
|
|
},
|
|
|
|
None => {
|
|
|
|
Err(Error::new(&format!("unhandled interrupt: {:x}", number)))
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-10-09 06:11:52 +00:00
|
|
|
|