#![allow(dead_code)]
pub mod bus;
pub mod device;
use alloc::vec::Vec;
use core::ops::Range;
#[cfg(feature = "intel_tdx")]
use ::tdx_guest::tdx_is_enabled;
use log::debug;
use self::bus::MmioBus;
#[cfg(feature = "intel_tdx")]
use crate::arch::tdx_guest;
use crate::{
    arch::kernel::IO_APIC, bus::mmio::device::MmioCommonDevice, mm::paddr_to_vaddr, sync::SpinLock,
    trap::IrqLine,
};
const VIRTIO_MMIO_MAGIC: u32 = 0x74726976;
pub static MMIO_BUS: SpinLock<MmioBus> = SpinLock::new(MmioBus::new());
static IRQS: SpinLock<Vec<IrqLine>> = SpinLock::new(Vec::new());
pub fn init() {
    #[cfg(feature = "intel_tdx")]
    if tdx_is_enabled() {
        unsafe {
            tdx_guest::unprotect_gpa_range(0xFEB0_0000, 4).unwrap();
        }
    }
    iter_range(0xFEB0_0000..0xFEB0_4000);
}
fn iter_range(range: Range<usize>) {
    debug!("[Virtio]: Iter MMIO range:{:x?}", range);
    let mut current = range.end;
    let mut lock = MMIO_BUS.lock();
    let io_apics = IO_APIC.get().unwrap();
    let is_ioapic2 = io_apics.len() == 2;
    let mut io_apic = if is_ioapic2 {
        io_apics.get(1).unwrap().lock()
    } else {
        io_apics.first().unwrap().lock()
    };
    let mut device_count = 0;
    while current > range.start {
        current -= 0x100;
        let value = unsafe { *(paddr_to_vaddr(current) as *const u32) };
        if value == VIRTIO_MMIO_MAGIC {
            let device_id = unsafe { *(paddr_to_vaddr(current + 8) as *const u32) };
            device_count += 1;
            if device_id == 0 {
                continue;
            }
            let handle = IrqLine::alloc().unwrap();
            io_apic.enable(24 - device_count, handle.clone()).unwrap();
            let device = MmioCommonDevice::new(current, handle);
            lock.register_mmio_device(device);
        }
    }
}