use std::sync::{Arc, Mutex};
use machina_core::address::GPA;
use crate::ram::RamBlock;
pub trait MmioOps: Send {
fn read(&self, offset: u64, size: u32) -> u64;
fn write(&self, offset: u64, size: u32, val: u64);
}
pub enum RegionType {
Ram {
block: Arc<RamBlock>,
},
Rom {
block: Arc<RamBlock>,
},
Io {
ops: Arc<Mutex<Box<dyn MmioOps>>>,
},
Alias {
target: Box<MemoryRegion>,
offset: u64,
},
Container,
}
pub struct SubRegion {
pub region: MemoryRegion,
pub offset: GPA,
}
pub struct MemoryRegion {
pub name: String,
pub size: u64,
pub region_type: RegionType,
pub priority: i32,
pub subregions: Vec<SubRegion>,
pub enabled: bool,
}
impl MemoryRegion {
pub fn container(name: &str, size: u64) -> Self {
Self {
name: name.to_string(),
size,
region_type: RegionType::Container,
priority: 0,
subregions: Vec::new(),
enabled: true,
}
}
pub fn ram(name: &str, size: u64) -> (Self, Arc<RamBlock>) {
let block = Arc::new(RamBlock::new(size));
let region = Self {
name: name.to_string(),
size,
region_type: RegionType::Ram {
block: Arc::clone(&block),
},
priority: 0,
subregions: Vec::new(),
enabled: true,
};
(region, block)
}
pub fn rom(name: &str, size: u64) -> (Self, Arc<RamBlock>) {
let block = Arc::new(RamBlock::new(size));
let region = Self {
name: name.to_string(),
size,
region_type: RegionType::Rom {
block: Arc::clone(&block),
},
priority: 0,
subregions: Vec::new(),
enabled: true,
};
(region, block)
}
pub fn io(name: &str, size: u64, ops: Box<dyn MmioOps>) -> Self {
Self {
name: name.to_string(),
size,
region_type: RegionType::Io {
ops: Arc::new(Mutex::new(ops)),
},
priority: 0,
subregions: Vec::new(),
enabled: true,
}
}
pub fn alias(
name: &str,
target: MemoryRegion,
offset: u64,
size: u64,
) -> Self {
Self {
name: name.to_string(),
size,
region_type: RegionType::Alias {
target: Box::new(target),
offset,
},
priority: 0,
subregions: Vec::new(),
enabled: true,
}
}
pub fn add_subregion(&mut self, region: MemoryRegion, offset: GPA) {
self.subregions.push(SubRegion { region, offset });
}
pub fn add_subregion_with_priority(
&mut self,
mut region: MemoryRegion,
offset: GPA,
priority: i32,
) {
region.priority = priority;
self.subregions.push(SubRegion { region, offset });
}
}