/*
 * Copyright 2023 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Special-purpose mailbox support for soundstream. Assumes a
 * companion implementation is running on the security core.
 */
#include "mailbox.h"

#include <fail-simulator-on-error.h>
#include <futex.h>
#include <interrupt.h>
#include <locks.h>
#include <thread.h>

#include <debug.hh>
#include <platform/sencha/platform-mailbox.hh>

#include "hw/top_matcha/sw/autogen/top_matcha.h"

/// Expose debugging features unconditionally for this compartment.
using Debug = ConditionalDebug<false, "Mailbox">;

#include "compat.h"

const uint32_t kMessageGpioPressed = 0xdeadbeef;
const uint32_t kMessageGpioReleased = 0x21524110;
const uint32_t kMessageEnableLed = 0xcafeb0ba;
const uint32_t kMessageDisableLed = 0x35014f45;

typedef uint32_t
    mailbox_mmio_t[TOP_MATCHA_TLUL_MAILBOX_SMC_SIZE_BYTES / sizeof(uint32_t)];

static dif_tlul_mailbox_t mailbox;
#define CHECK_INIT() CHECK(mailbox.base_addr.base != 0)

static CountingSemaphoreState startup = { 0, 1 };

void mailbox_init(void) {
  CHECK_DIF_OK(
      dif_tlul_mailbox_init(mmio_region_from_addr((uintptr_t)MMIO_CAPABILITY(
                                mailbox_mmio_t, mailbox_smc)),
                            &mailbox));
  semaphore_put(&startup);
}

// NB: could be atomic but not needed for our usage.
volatile bool button_pressed = false;

void mailbox_isr(void) {
  Timeout t = {0, UnlimitedTimeout};
  semaphore_get(&t, &startup);
  Debug::log("mailbox_isr: mailbox {} (Thread {})", mailbox.base_addr.base, thread_id_get());

  const uint32_t *mailboxRtFutex =
      interrupt_futex_get(STATIC_SEALED_VALUE(mailboxRtInterruptCapability));
  uint32_t last = *mailboxRtFutex;
  for (;;) {
    Debug::Assert(futex_wait(mailboxRtFutex, last) == 0, "futex_wait");
    last = *mailboxRtFutex;
    Debug::log("mailbox_isr: mailbox {} last {}", mailbox.base_addr.base, last);
    interrupt_complete(STATIC_SEALED_VALUE(mailboxRtInterruptCapability));

    // NB: this is NOT the TockOS mailbox protocol that exchanges
    // variable length packets that are encoded by Rust's postcard
    // crate.
    uint32_t message;
    CHECK_DIF_OK(dif_tlul_mailbox_read_message(&mailbox, &message));
    if (message == kMessageGpioPressed) {
      button_pressed = true;
    } else if (message == kMessageGpioReleased) {
      button_pressed = false;
    } else {
      CHECK(false, "Unknown message");
    }
  }
}
bool mailbox_button_pressed(void) { return button_pressed; }

// XXX temp until gpio's on the SEC can be used (either in simulation or for real)
void mailbox_set_button_pressed(bool pressed) { button_pressed = pressed; }

// Wait until the record switch is pushed
void mailbox_wait_for_button_pressed(void) {
  const uint32_t *mailboxRtFutex =
      interrupt_futex_get(STATIC_SEALED_VALUE(mailboxRtInterruptCapability));
  uint32_t last = *mailboxRtFutex;
  while (!mailbox_button_pressed()) {
    Debug::Assert(futex_wait(mailboxRtFutex, last) == 0, "futex_wait");
    last = *mailboxRtFutex;
  }
}

void mailbox_set_led(bool enabled) {
  CHECK_INIT();
  // NB: this is not the TockOS mailbox protocol.
  uint32_t message_enable_led =
      enabled ? kMessageEnableLed : kMessageDisableLed;
  CHECK_DIF_OK(dif_tlul_mailbox_send_message(&mailbox, &message_enable_led));
}
