// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "acpi_multiply.h"

#include <fidl/fuchsia.hardware.acpi/cpp/wire.h>
#include <fidl/fuchsia.hardware.acpi/cpp/wire_types.h>
#include <fidl/sample.acpi.multiply/cpp/wire_types.h>
#include <lib/async/cpp/irq.h>
#include <lib/async/cpp/task.h>
#include <lib/driver2/record_cpp.h>
#include <lib/driver2/structured_logger.h>
#include <lib/mmio/mmio-buffer.h>
#include <zircon/errors.h>
#include <zircon/types.h>

#include "registers.h"

namespace acpi_multiply {

namespace fio = fuchsia_io;
namespace facpi = fuchsia_hardware_acpi;

zx::status<std::unique_ptr<AcpiMultiplyDriver>> AcpiMultiplyDriver::Start(
    fuchsia_driver_framework::wire::DriverStartArgs& start_args, fdf::UnownedDispatcher dispatcher,
    fidl::WireSharedClient<fuchsia_driver_framework::Node> node, driver::Namespace ns,
    driver::Logger logger) {
  auto driver = std::make_unique<AcpiMultiplyDriver>(
      dispatcher->async_dispatcher(), std::move(node), std::move(ns), std::move(logger));
  auto result = driver->Run(std::move(start_args.outgoing_dir()));
  if (result.is_error()) {
    return result.take_error();
  }

  return zx::ok(std::move(driver));
}

zx::status<> AcpiMultiplyDriver::Run(fidl::ServerEnd<fio::Directory> outgoing_dir) {
  auto status = outgoing_.AddProtocol<sample_acpi_multiply::Device>(this, Name());
  if (status.is_error()) {
    FDF_SLOG(ERROR, "Failed to add protocol", KV("status", status.status_string()));
    return status.take_error();
  }

  // Connect to the ACPI protocol exposed by the parent driver.
  auto client = ns_.Connect<facpi::Device>();
  if (client.is_error()) {
    FDF_SLOG(ERROR, "Failed to connect to ACPI", KV("status", client.status_string()));
    return client.take_error();
  }
  acpi_.Bind(std::move(client.value()));

  // Get interrupt.
  auto irq_result = acpi_->MapInterrupt(0);
  if (!irq_result.ok() || irq_result->is_error()) {
    return irq_result.ok() ? irq_result->take_error() : zx::error(irq_result.error().status());
  }

  irq_ = std::move(irq_result->value()->irq);
  // Start listening for interrupts.
  irq_method_.set_object(irq_.get());
  irq_method_.Begin(dispatcher_);

  // Get MMIO region.
  auto mmio_result = acpi_->GetMmio(0);
  if (!mmio_result.ok() || mmio_result->is_error()) {
    return mmio_result.ok() ? mmio_result->take_error() : zx::error(mmio_result.error().status());
  }

  auto& mmio = mmio_result->value()->mmio;
  auto buf_result = fdf::MmioBuffer::Create(mmio.offset, mmio.size, std::move(mmio.vmo),
                                            ZX_CACHE_POLICY_UNCACHED_DEVICE);
  if (buf_result.is_error()) {
    return buf_result.take_error();
  }
  mmio_ = std::move(buf_result.value());

  // This is not strictly necessary, but it does a multiplication to prove that the driver
  // behaves as expected.
  async::PostTask(dispatcher_, [this]() {
    auto endpoints = fidl::CreateEndpoints<sample_acpi_multiply::Device>();
    if (endpoints.is_error()) {
      FDF_LOG(ERROR, "Failed to create endpoints");
      return;
    }

    fidl::BindServer(dispatcher_, std::move(endpoints->server), this);
    client_.Bind(std::move(endpoints->client), dispatcher_);
    // Do the multiply
    client_->Multiply(UINT32_MAX, 9)
        .Then([this](fidl::WireUnownedResult<sample_acpi_multiply::Device::Multiply>& response) {
          if (response.ok() && response->is_ok()) {
            FDF_SLOG(INFO, "UINT32_MAX*9: Got result",
                     KV("result", response.value().value()->result),
                     KV("overflowed", response.value().value()->overflowed));
          } else {
            FDF_SLOG(ERROR, "Multiply failed",
                     KV("fidl status", (const char*)response.FormatDescription().data()),
                     KV("device status",
                        (const char*)(response.ok() ? response.status_string() : "N/A")));
          }
        });
    client_->Multiply(2, 9).Then(
        [this](fidl::WireUnownedResult<sample_acpi_multiply::Device::Multiply>& response) {
          if (response.ok() && response->is_ok()) {
            FDF_SLOG(INFO, "2*9: Got result", KV("result", response.value().value()->result),
                     KV("overflowed", response.value().value()->overflowed));
          } else {
            FDF_SLOG(ERROR, "Multiply failed",
                     KV("fidl status", (const char*)response.FormatDescription().data()),
                     KV("device status",
                        (const char*)(response.ok() ? response.status_string() : "N/A")));
          }
        });
  });
  return zx::ok();
}

void AcpiMultiplyDriver::Multiply(MultiplyRequestView request, MultiplyCompleter::Sync& completer) {
  std::scoped_lock lock(completer_lock_);
  // Queue operations if there is already one in-flight.
  if (cur_completer_.has_value()) {
    operation_queue_.emplace_back(Operation{
        .a = request->a,
        .b = request->b,
        .completer = completer.ToAsync(),
    });
    return;
  }

  DoMultiply(Operation{
      .a = request->a,
      .b = request->b,
      .completer = completer.ToAsync(),
  });
}

void AcpiMultiplyDriver::DoMultiply(Operation operation) {
  // Write the operands to the two MMIO registers.
  MultiplyArgumentReg::Get(true).FromValue(0).set_operand(operation.a).WriteTo(&mmio_.value());
  MultiplyArgumentReg::Get(false).FromValue(0).set_operand(operation.b).WriteTo(&mmio_.value());

  cur_completer_ = std::move(operation.completer);
  fidl::Arena arena;
  // Call the ACPI method that will trigger the multiply operation.
  auto result = acpi_->EvaluateObject(fidl::StringView::FromExternal("_MUL"),
                                      facpi::wire::EvaluateObjectMode::kPlainObject,
                                      fidl::VectorView<facpi::wire::Object>(arena, 0));
  if (!result.ok() || result->is_error()) {
    FDF_SLOG(ERROR, "Failed to send EvaluateObject",
             KV("error", (const char*)(result.ok() ? std::to_string(result->error_value()).data()
                                                   : result.FormatDescription().data())));
    cur_completer_->ReplyError(ZX_ERR_INTERNAL);
    cur_completer_ = std::nullopt;
    return;
  }

  // We will receive an interrupt when the operation is done.
}

void AcpiMultiplyDriver::HandleIrq(async_dispatcher_t* dispatcher, async::IrqBase* irq,
                                   zx_status_t status, const zx_packet_interrupt_t* interrupt) {
  irq_.ack();
  std::scoped_lock lock(completer_lock_);
  if (!cur_completer_.has_value()) {
    FDF_LOG(ERROR, "Spurious interrupt!");
    return;
  }
  auto completer = std::move(cur_completer_.value());
  cur_completer_ = std::nullopt;
  if (status != ZX_OK) {
    FDF_SLOG(ERROR, "Failed to wait for interrupt", KV("status", zx_status_get_string(status)));
    completer.ReplyError(status);
    return;
  }

  auto status_reg = MultiplyStatusReg::Get().ReadFrom(&mmio_.value());
  if (!status_reg.finished()) {
    FDF_LOG(ERROR, "Interrupt came too soon!");
    completer.ReplyError(ZX_ERR_BAD_STATE);
    return;
  }

  auto result = MultiplyResultReg::Get().ReadFrom(&mmio_.value());
  completer.ReplySuccess(result.result(), status_reg.overflow());

  // Start the next operation if there is one.
  if (!operation_queue_.empty()) {
    DoMultiply(std::move(operation_queue_.front()));
    operation_queue_.pop_front();
  }
}

}  // namespace acpi_multiply

FUCHSIA_DRIVER_RECORD_CPP_V1(acpi_multiply::AcpiMultiplyDriver);
