83 lines
1.9 KiB
Rust
83 lines
1.9 KiB
Rust
// All devices are implemented here.
|
|
|
|
use slog::Logger;
|
|
|
|
pub mod oscillator;
|
|
pub mod ram;
|
|
pub mod usart;
|
|
|
|
pub trait DeviceImpl {
|
|
/// addr relative to the start of the device memory map.
|
|
fn read(&mut self, addr: u32) -> u8;
|
|
/// addr relative to the start of the device memory map.
|
|
fn write(&mut self, addr: u32, value: u8);
|
|
}
|
|
|
|
pub struct Device {
|
|
start_addr: u32,
|
|
addr_len: u32,
|
|
device: Box<dyn DeviceImpl>,
|
|
}
|
|
|
|
impl Device {
|
|
pub fn new(device: Box<dyn DeviceImpl>, start_addr: u32, addr_len: u32) -> Self {
|
|
Self {
|
|
start_addr,
|
|
addr_len,
|
|
device,
|
|
}
|
|
}
|
|
|
|
pub fn handles_addr(&self, addr: u32) -> bool {
|
|
addr >= self.start_addr && addr - self.start_addr < self.addr_len
|
|
}
|
|
|
|
pub fn read(&mut self, addr: u32) -> u8 {
|
|
self.device.read(addr - self.start_addr)
|
|
}
|
|
|
|
pub fn write(&mut self, addr: u32, val: u8) {
|
|
self.device.write(addr - self.start_addr, val)
|
|
}
|
|
}
|
|
|
|
pub struct DeviceTree {
|
|
log: Logger,
|
|
devices: Vec<Device>,
|
|
}
|
|
|
|
impl DeviceTree {
|
|
pub fn new(log: Logger) -> Self {
|
|
Self {
|
|
log,
|
|
devices: Vec::new(),
|
|
}
|
|
}
|
|
|
|
pub fn add_device(&mut self, device: Device) {
|
|
self.devices.push(device);
|
|
}
|
|
|
|
fn get_device_for_addr(&mut self, addr: u32) -> Option<&mut Device> {
|
|
self.devices.iter_mut().find(|d| d.handles_addr(addr))
|
|
}
|
|
|
|
pub fn read(&mut self, addr: u32) -> u8 {
|
|
if let Some(ref mut d) = self.get_device_for_addr(addr) {
|
|
return d.read(addr);
|
|
}
|
|
warn!(self.log, "Trying to read unmapped I/O: {:08X}", addr);
|
|
0
|
|
}
|
|
|
|
pub fn write(&mut self, addr: u32, val: u8) {
|
|
if let Some(ref mut d) = self.get_device_for_addr(addr) {
|
|
return d.write(addr, val);
|
|
}
|
|
warn!(
|
|
self.log,
|
|
"Trying to write unmapped I/O: {:08X} <- {:02X}", addr, val
|
|
);
|
|
}
|
|
}
|