//! 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 Mailbox {
    regs: StaticRef<MailboxRegisters>,
    plic_wtirq: u32,
    plic_rtirq: u32,
    plic_eirq: u32,
}

pub const MAILBOX: Mailbox = Mailbox {
    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 Mailbox {
    // 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::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::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();
        }
    }
}
