//! Matcha hardware mailbox.

// We want constants & registers to stay together even if they're not currently
// used in this file.
#![allow(dead_code)]

use core::mem::transmute;
use kernel::common::registers::{register_structs, ReadOnly, ReadWrite, WriteOnly};
use kernel::common::StaticRef;

use crate::*;

const MAILBOX_BASE: u32 = 0x40800000; // TOP_MATCHA_MAILBOX_SEC_BASE_ADDR
const MAILBOX_WTIRQ: u32 = 181; // kTopMatchaPlicIrqIdMailboxSecWtirq
const MAILBOX_RTIRQ: u32 = 182; // kTopMatchaPlicIrqIdMailboxSecRtirq
const MAILBOX_EIRQ: u32 = 183; // kTopMatchaPlicIrqIdMailboxSecEirq

const MAILBOX_SIZE_DWORDS: u32 = 8;

const INTR_STATE_BIT_WTIRQ: u32 = 0b001;
const INTR_STATE_BIT_RTIRQ: u32 = 0b010;
const INTR_STATE_BIT_EIRQ: u32 = 0b100;

const INTR_ENABLE_BIT_WTIRQ: u32 = 0b001;
const INTR_ENABLE_BIT_RTIRQ: u32 = 0b010;
const INTR_ENABLE_BIT_EIRQ: u32 = 0b100;

const STATUS_BIT_EMPTY: u32 = 0b0001;
const STATUS_BIT_FULL: u32 = 0b0010;
const STATUS_BIT_WFIFOL: u32 = 0b0100;
const STATUS_BIT_RFIFOL: u32 = 0b1000;

register_structs! {
    pub MailboxRegisters {
        (0x000 => reg_intr_state:  ReadWrite<u32>),
        (0x004 => reg_intr_enable: ReadWrite<u32>),
        (0x008 => reg_intr_test:   ReadWrite<u32>),
        (0x00C => reg_mboxw:       WriteOnly<u32>),
        (0x010 => reg_mboxr:       ReadOnly<u32>),
        (0x014 => reg_status:      ReadOnly<u32>),
        (0x018 => reg_error:       ReadOnly<u32>),
        (0x01C => reg_wirqt:       ReadWrite<u32>),
        (0x020 => reg_rirqt:       ReadWrite<u32>),
        (0x024 => reg_ctrl:        WriteOnly<u32>),
        (0x028 => @END),
    }
}

pub struct MailboxHAL {
    regs: StaticRef<MailboxRegisters>,
    plic_wtirq: u32,
    plic_rtirq: u32,
    plic_eirq: u32,
}

pub const MAILBOX: MailboxHAL = MailboxHAL {
    regs: unsafe { StaticRef::new(MAILBOX_BASE as *mut MailboxRegisters) },
    plic_wtirq: MAILBOX_WTIRQ,
    plic_rtirq: MAILBOX_RTIRQ,
    plic_eirq: MAILBOX_EIRQ,
};

// 32-bit-word bitfield helpers for the PLIC's irq enable lines.

pub unsafe fn set_bit(base: u32, bit_index: isize) {
    let buf: *mut u32 = transmute(base);
    let mut bits = buf.offset(bit_index >> 5).read_volatile();
    bits |= 1 << (bit_index & 31);
    buf.offset(bit_index >> 5).write_volatile(bits);
}

pub unsafe fn clear_bit(base: u32, bit_index: isize) {
    let buf: *mut u32 = transmute(base);
    let mut bits = buf.offset(bit_index >> 5).read_volatile();
    bits &= !(1 << (bit_index & 31));
    buf.offset(bit_index >> 5).write_volatile(bits);
}

impl MailboxHAL {
    // Synchronously send a message. Blocks the caller if there's no room in the
    // outbox.
    pub fn send_message_sync(&self, message: &[u32]) {
        for i in 0..message.len() {
            // NOTE: The spec for the TLUL mailbox says that the write interrupt
            // fires when the FIFO is _above_ the threshold, which is useless
            // for us as we need to wait for it to fall _below_ a threshold.
            // So, we have to busy-wait here, which is slightly annoying.
            while (self.regs.reg_status.get() & STATUS_BIT_FULL) != 0 {}
            self.regs.reg_mboxw.set(message[i]);
        }
    }

    // Synchronously wait on a message to arrive. Blocks the caller if no
    // message is in the inbox.

    pub fn wait_recv_sync(&self) {
        // Set the mailbox to fire the read interrupt when there's more than
        // zero items in it and enable the corresponding IRQ line in the PLIC so
        // the interrupt will make it through to the CPU.
        self.regs.reg_rirqt.set(0);
        self.regs.reg_intr_enable.set(INTR_ENABLE_BIT_RTIRQ);

        unsafe {
            set_bit(plic_hal::PLIC_EN0, self.plic_rtirq as isize);
        }

        // Wait for the read interrupt to fire.
        while (self.regs.reg_intr_state.get() & INTR_STATE_BIT_RTIRQ) == 0 {
            unsafe {
                asm!("wfi");
            }
        }
        // NOTE: We don't need to deal with the PLIC claim/complete registers here
        // as we're disabling the interrupt immediately after it arrives and before
        // any other bit of code has a chance to claim it.

        // Turn the interrupt and IRQ line back off.
        unsafe {
            clear_bit(plic_hal::PLIC_EN0, self.plic_rtirq as isize);
        }
        self.regs.reg_intr_enable.set(0);

        // Ack it in the mailbox so it doesn't re-fire later.
        self.regs.reg_intr_state.set(INTR_STATE_BIT_RTIRQ);
    }

    // Synchronously receive a message. Blocks the caller if no message is in
    // the inbox.
    pub unsafe fn recv_message_sync(&self, message: &mut [u32]) {
        for i in 0..message.len() {
            while (self.regs.reg_status.get() & STATUS_BIT_EMPTY) != 0 {
                self.wait_recv_sync();
            }
            message[i] = self.regs.reg_mboxr.get();
        }
    }
}
