    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45

    pub const CLOCK_FREQ: usize = 12500000;

    pub const MMIO: &[(usize, usize)] = &[
        (0x1000_0000, 0x1000),
        (0x1000_1000, 0x1000),
        (0xC00_0000, 0x40_0000),
    ];

    pub type BlockDeviceImpl = crate::drivers::block::VirtIOBlock;
    pub type CharDeviceImpl = crate::drivers::chardev::NS16550a<VIRT_UART>;

    pub const VIRT_PLIC: usize = 0xC00_0000;
    pub const VIRT_UART: usize = 0x1000_0000;

    use crate::drivers::block::BLOCK_DEVICE;
    use crate::drivers::chardev::{CharDevice, UART};
    use crate::drivers::plic::{IntrTargetPriority, PLIC};

    pub fn device_init() {
        use riscv::register::sie;
        let mut plic = unsafe { PLIC::new(VIRT_PLIC) };
        let hart_id: usize = 0;
        let supervisor = IntrTargetPriority::Supervisor;
        let machine = IntrTargetPriority::Machine;
        plic.set_threshold(hart_id, supervisor, 0);
        plic.set_threshold(hart_id, machine, 1);
        for intr_src_id in [1usize, 10] {
            plic.enable(hart_id, supervisor, intr_src_id);
            plic.set_priority(intr_src_id, 1);
        }
        unsafe {
            sie::set_sext();
        }
    }

    pub fn irq_handler() {
        let mut plic = unsafe { PLIC::new(VIRT_PLIC) };
        let intr_src_id = plic.claim(0, IntrTargetPriority::Supervisor);
        match intr_src_id {
            1 => BLOCK_DEVICE.handle_irq(),
            10 => UART.handle_irq(),
            _ => panic!("unsupported IRQ {}", intr_src_id),
        }
        plic.complete(0, IntrTargetPriority::Supervisor, intr_src_id);
    }