//! virtio device
//!
//! This module contains the virtio device structural code.
//!
//! # Notes
//! <https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html#x1-20001>

pub struct VirtioDevice {
    _status: VirtioDeviceStatus,
}

use crate::devices::pci::PciDeviceInfo;

pub fn device_handler(device: PciDeviceInfo) {
    use crate::devices::pci::PciClass::*;
    match device.class() {
        // Unclassified => todo!(),
        // MassStorage => todo!(),
        // Network => todo!(),
        Display => {
            trace!("Display found");
            println!("{}", device.interrupt_pin());
        }
        // Multimedia => todo!(),
        // Memory => todo!(),
        // Bridge => todo!(),
        // Other => todo!(),
        _ => {}
    }
}

#[repr(C)]
pub enum VirtioDeviceStatus {
    // Indicates that the guest OS has found the device and recognized it as a valid virtio device.
    Acknowleged = 1,
    // Indicates that the guest OS knows how to drive the device. Note: There could be a significant (or infinite) delay before setting this bit. For example, under Linux, drivers can be loadable modules.
    Driver = 2,
    // Indicates that the driver has acknowledged all the features it understands, and feature negotiation is complete.
    FeaturesOk = 8,
    // Indicates that the device is set up and ready to drive the device.
    DriverOk = 4,
    // Indicates that the device needs to be reset.
    DeviceNeedsReset = 64,
    // Indicates that the device has failed.
    Failed = 128,
}

pub struct FeaturesBits(u64);
impl FeaturesBits {
    // bit mask the first 23 bits and return a u64
    //  0 to 23
    // Feature bits for the specific device type
    pub fn device_type_features(&self) -> u64 {
        0
    }

    // bit mask the 24th bit to the 37th bit and return a u64
    // 24 to 37
    // Feature bits reserved for extensions to the queue and feature negotiation mechanisms
    pub fn extension_features(&self) -> u64 {
        0
    }

    // bit mask the 38th bit to the 63th bit and return a u64
    // 38 and above
    // Feature bits reserved for future extensions.
    pub fn future_features(&self) -> u64 {
        0
    }
}

// configuration change notification
// available buffer notification
// used buffer notification.

#[repr(C)]
pub struct VirtioDeviceNotification {
    pub type_: u32,
    pub index: u32,
    pub value: u32,
}

pub struct Vring {
    pub addr: u64,
    pub len: u32,
    pub flags: u16,
    pub next: u16,
}

pub struct VringAvail {
    pub flags: u16,
    pub idx: u16,
    pub ring: [u16; 0xFFFF],
}