use axerrno::AxResult;
use axvisor_api::vmm::current_vcpu_id;
use spin::Mutex;
use crate::{interrupt::VgicInt, registers::GicRegister, vgicd::Vgicd};
pub struct Vgic {
vgicd: Mutex<Vgicd>,
}
impl Default for Vgic {
fn default() -> Self {
Self::new()
}
}
impl Vgic {
pub fn new() -> Vgic {
Vgic {
vgicd: Mutex::new(Vgicd::new()),
}
}
pub(crate) fn handle_read8(&self, addr: usize) -> AxResult<usize> {
let value = self.handle_read32(addr)?;
Ok((value >> (8 * (addr & 0x3))) & 0xff)
}
pub(crate) fn handle_read16(&self, addr: usize) -> AxResult<usize> {
let value = self.handle_read32(addr)?;
Ok((value >> (8 * (addr & 0x3))) & 0xffff)
}
pub fn handle_read32(&self, addr: usize) -> AxResult<usize> {
match GicRegister::from_addr(addr as u32) {
Some(reg) => match reg {
GicRegister::GicdCtlr => Ok(self.vgicd.lock().ctrlr as usize),
GicRegister::GicdTyper => Ok(self.vgicd.lock().typer as usize),
GicRegister::GicdIidr => Ok(self.vgicd.lock().iidr as usize),
GicRegister::GicdIsenabler(idx) => Ok(self.vgicd.lock().vgicd_isenabler_read(idx)),
_ => {
Ok(0)
}
},
None => {
Ok(0)
}
}
}
pub fn handle_write8(&self, addr: usize, value: usize) {
self.handle_write32(addr, value);
}
pub fn handle_write16(&self, addr: usize, value: usize) {
self.handle_write32(addr, value);
}
pub fn handle_write32(&self, addr: usize, value: usize) {
let _vcpu_id = current_vcpu_id();
if let Some(reg) = GicRegister::from_addr(addr as u32) {
match reg {
GicRegister::GicdCtlr => self.vgicd.lock().vgicd_ctrlr_write(value),
GicRegister::GicdIsenabler(idx) => {
self.vgicd.lock().vgicd_isenabler_write(idx, value)
}
_ => {
}
}
}
}
pub fn fetch_irq(&self, irq: u32) -> VgicInt {
self.vgicd.lock().fetch_irq(irq)
}
pub fn nothing(&self, _value: u32) {}
}