// Copyright 2019 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 "uart16550.h"

#include <fuchsia/hardware/serial/c/banjo.h>
#include <fuchsia/hardware/serial/c/fidl.h>
#include <fuchsia/hardware/serialimpl/c/banjo.h>
#include <lib/uart/ns8250.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>

#include <algorithm>

#include <ddk/debug.h>
#include <ddk/metadata.h>
#include <hw/inout.h>

#include "src/devices/serial/drivers/uart16550/uart16550_bind.h"

// The register types and constants are defined in the uart library.
using namespace uart::ns8250;

namespace uart16550 {

static constexpr int64_t kPioIndex = 0;
static constexpr int64_t kIrqIndex = 0;

static constexpr uint8_t kDefaultConfig =
    SERIAL_DATA_BITS_8 | SERIAL_STOP_BITS_1 | SERIAL_PARITY_NONE;

static constexpr serial_port_info_t kInfo = {
    .serial_class = fuchsia_hardware_serial_Class_GENERIC,
    .serial_vid = 0,
    .serial_pid = 0,
};

Uart16550::Uart16550() : DeviceType(nullptr) {}

Uart16550::Uart16550(zx_device_t* parent) : DeviceType(parent), acpi_(parent) {}

zx_status_t Uart16550::Create(void* /*ctx*/, zx_device_t* parent) {
  auto dev = std::make_unique<Uart16550>(parent);

  auto status = dev->Init();
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s: Init failed", __func__);
    return status;
  }

  dev->DdkAdd("uart16550");

  // Release because devmgr is now in charge of the device.
  static_cast<void>(dev.release());
  return ZX_OK;
}

size_t Uart16550::FifoDepth() const { return uart_fifo_len_; }

bool Uart16550::Enabled() {
  std::lock_guard<std::mutex> lock(device_mutex_);
  return enabled_;
}

bool Uart16550::NotifyCallbackSet() {
  std::lock_guard<std::mutex> lock(device_mutex_);
  return notify_cb_.callback != nullptr;
}

// Create RX and TX FIFOs, obtain interrupt and port handles from the ACPI
// device, obtain port permissions, set up default configuration, and start the
// interrupt handler thread.
zx_status_t Uart16550::Init() {
  zx::resource io_port;
  auto status = acpi_.GetPio(kPioIndex, &io_port);
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s: acpi_.GetPio failed", __func__);
    return status;
  }

  status = acpi_.MapInterrupt(kIrqIndex, &interrupt_);
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s: acpi_.MapInterrupt failed", __func__);
    return status;
  }

  zx_info_resource_t resource_info;
  status =
      io_port.get_info(ZX_INFO_RESOURCE, &resource_info, sizeof(resource_info), nullptr, nullptr);
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s: io_port.get_info failed", __func__);
    return status;
  }

  const auto port_base = static_cast<uint16_t>(resource_info.base);
  const auto port_size = static_cast<uint32_t>(resource_info.size);

  if (port_base != resource_info.base) {
    zxlogf(ERROR, "%s: overflowing UART port base", __func__);
    return ZX_ERR_BAD_STATE;
  }

  if (port_size != resource_info.size) {
    zxlogf(ERROR, "%s: overflowing UART port size", __func__);
    return ZX_ERR_BAD_STATE;
  }

  if (port_size != kPortCount) {
    zxlogf(ERROR, "%s: unsupported UART port count", __func__);
    return ZX_ERR_NOT_SUPPORTED;
  }

  status = zx_ioports_request(io_port.get(), port_base, port_size);
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s: zx_ioports_request failed", __func__);
    return status;
  }

  {
    std::lock_guard<std::mutex> lock(device_mutex_);
#ifdef __x86_64__
    port_io_.emplace<hwreg::RegisterPio>(port_base);
#else
    ZX_PANIC("uart16550 driver supports only direct PIO, which is x86-only");
#endif
    InitFifosLocked();
  }

  status = SerialImplConfig(kMaxBaudRate, kDefaultConfig);
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s: SerialImplConfig failed", __func__);
    return status;
  }

  interrupt_thread_ = std::thread([&] { HandleInterrupts(); });

  return ZX_OK;
}

#if UART16550_TESTING
zx_status_t Uart16550::Init(zx::interrupt interrupt, hwreg::Mock::RegisterIo port_mock) {
  interrupt_ = std::move(interrupt);
  {
    std::lock_guard<std::mutex> lock(device_mutex_);
    port_io_.emplace<hwreg::Mock::RegisterIo>(port_mock);
    InitFifosLocked();
  }

  auto status = SerialImplConfig(kMaxBaudRate, kDefaultConfig);
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s: SerialImplConfig failed", __func__);
    return status;
  }

  interrupt_thread_ = std::thread([&] { HandleInterrupts(); });

  return ZX_OK;
}
#endif  // UART16550_TESTING

zx::unowned_interrupt Uart16550::InterruptHandle() { return zx::unowned_interrupt(interrupt_); }

zx_status_t Uart16550::SerialImplGetInfo(serial_port_info_t* info) {
  *info = kInfo;
  return ZX_OK;
}

zx_status_t Uart16550::SerialImplConfig(uint32_t baud_rate, uint32_t flags) {
  if (Enabled()) {
    zxlogf(ERROR, "%s: attempted to configure when enabled", __func__);
    return ZX_ERR_BAD_STATE;
  }

  if (baud_rate == 0) {
    return ZX_ERR_INVALID_ARGS;
  }

  const auto divisor = static_cast<uint16_t>(kMaxBaudRate / baud_rate);
  if (divisor != kMaxBaudRate / baud_rate || divisor == 0) {
    return ZX_ERR_INVALID_ARGS;
  }

  if ((flags & SERIAL_FLOW_CTRL_MASK) != SERIAL_FLOW_CTRL_NONE && !SupportsAutomaticFlowControl()) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  const auto lower = static_cast<uint8_t>(divisor);
  const auto upper = static_cast<uint8_t>(divisor >> 8);

  std::lock_guard<std::mutex> lock(device_mutex_);

  auto lcr = LineControlRegister::Get().ReadFrom(&port_io_);

  lcr.set_divisor_latch_access(true).WriteTo(&port_io_);

  DivisorLatchLowerRegister::Get().FromValue(0).set_data(lower).WriteTo(&port_io_);
  DivisorLatchUpperRegister::Get().FromValue(0).set_data(upper).WriteTo(&port_io_);

  lcr.set_divisor_latch_access(false);

  if (flags & SERIAL_SET_BAUD_RATE_ONLY) {
    lcr.WriteTo(&port_io_);
    return ZX_OK;
  }

  switch (flags & SERIAL_DATA_BITS_MASK) {
    case SERIAL_DATA_BITS_5:
      lcr.set_word_length(LineControlRegister::kWordLength5);
      break;
    case SERIAL_DATA_BITS_6:
      lcr.set_word_length(LineControlRegister::kWordLength6);
      break;
    case SERIAL_DATA_BITS_7:
      lcr.set_word_length(LineControlRegister::kWordLength7);
      break;
    case SERIAL_DATA_BITS_8:
      lcr.set_word_length(LineControlRegister::kWordLength8);
      break;
  }

  switch (flags & SERIAL_STOP_BITS_MASK) {
    case SERIAL_STOP_BITS_1:
      lcr.set_stop_bits(LineControlRegister::kStopBits1);
      break;
    case SERIAL_STOP_BITS_2:
      lcr.set_stop_bits(LineControlRegister::kStopBits2);
      break;
  }

  switch (flags & SERIAL_PARITY_MASK) {
    case SERIAL_PARITY_NONE:
      lcr.set_parity_enable(false);
      lcr.set_even_parity(false);
      break;
    case SERIAL_PARITY_ODD:
      lcr.set_parity_enable(true);
      lcr.set_even_parity(false);
      break;
    case SERIAL_PARITY_EVEN:
      lcr.set_parity_enable(true);
      lcr.set_even_parity(true);
      break;
  }

  lcr.WriteTo(&port_io_);

  auto mcr = ModemControlRegister::Get().FromValue(0);

  // The below is necessary for interrupts on some devices.
  mcr.set_auxiliary_out_2(true);

  switch (flags & SERIAL_FLOW_CTRL_MASK) {
    case SERIAL_FLOW_CTRL_NONE:
      mcr.set_automatic_flow_control_enable(false);
      mcr.set_data_terminal_ready(true);
      mcr.set_request_to_send(true);
      break;
    case SERIAL_FLOW_CTRL_CTS_RTS:
      mcr.set_automatic_flow_control_enable(true);
      mcr.set_data_terminal_ready(false);
      mcr.set_request_to_send(false);
      break;
  }

  mcr.WriteTo(&port_io_);

  return ZX_OK;
}

zx_status_t Uart16550::SerialImplEnable(bool enable) {
  std::lock_guard<std::mutex> lock(device_mutex_);
  if (enabled_) {
    if (!enable) {
      // The device is enabled, and will be disabled.
      InterruptEnableRegister::Get()
          .FromValue(0)
          .set_rx_available(false)
          .set_line_status(false)
          .set_modem_status(false)
          .set_tx_empty(false)
          .WriteTo(&port_io_);
    }
  } else {
    if (enable) {
      // The device is disabled, and will be enabled.
      ResetFifosLocked();
      InterruptEnableRegister::Get()
          .FromValue(0)
          .set_rx_available(true)
          .set_line_status(true)
          .set_modem_status(true)
          .set_tx_empty(false)
          .WriteTo(&port_io_);
    }
  }
  enabled_ = enable;
  return ZX_OK;
}

zx_status_t Uart16550::SerialImplRead(uint8_t* buf, size_t size, size_t* actual) {
  std::lock_guard<std::mutex> lock(device_mutex_);
  *actual = 0;

  if (!enabled_) {
    zxlogf(ERROR, "%s: attempted to read when disabled", __func__);
    return ZX_ERR_BAD_STATE;
  }

  auto p = buf;

  auto lcr = LineStatusRegister::Get();

  auto data_ready_and_notify = [&]() __TA_REQUIRES(device_mutex_) {
    auto ready = lcr.ReadFrom(&port_io_).data_ready();
    auto state = state_;
    if (!ready) {
      state &= ~SERIAL_STATE_READABLE;
    } else {
      state |= SERIAL_STATE_READABLE;
    }
    if (state_ != state) {
      state_ = state;
      NotifyLocked();
    }
    return ready;
  };

  if (!data_ready_and_notify()) {
    return ZX_ERR_SHOULD_WAIT;
  }

  auto rbr = RxBufferRegister::Get();

  while (data_ready_and_notify() && size != 0) {
    *p++ = rbr.ReadFrom(&port_io_).data();
    *actual += 1;
    --size;
  }

  return ZX_OK;
}

zx_status_t Uart16550::SerialImplWrite(const uint8_t* buf, size_t size, size_t* actual) {
  std::lock_guard<std::mutex> lock(device_mutex_);
  *actual = 0;

  if (!enabled_) {
    zxlogf(ERROR, "%s: attempted to write when disabled", __func__);
    return ZX_ERR_BAD_STATE;
  }

  auto p = buf;
  size_t writable = std::min(size, uart_fifo_len_);

  auto lsr = LineStatusRegister::Get();
  auto ier = InterruptEnableRegister::Get();

  if (!lsr.ReadFrom(&port_io_).tx_empty()) {
    ier.ReadFrom(&port_io_).set_tx_empty(true).WriteTo(&port_io_);
    return ZX_ERR_SHOULD_WAIT;
  }

  auto tbr = TxBufferRegister::Get();

  while (writable != 0) {
    tbr.FromValue(0).set_data(*p++).WriteTo(&port_io_);
    *actual += 1;
    --writable;
  }

  if (*actual != size) {
    ier.ReadFrom(&port_io_).set_tx_empty(true).WriteTo(&port_io_);
  }

  if (*actual != 0) {
    auto state = state_;
    state &= ~SERIAL_STATE_WRITABLE;
    if (state_ != state) {
      state_ = state;
      NotifyLocked();
    }
  }

  return ZX_OK;
}

zx_status_t Uart16550::SerialImplSetNotifyCallback(const serial_notify_t* cb) {
  std::lock_guard<std::mutex> lock(device_mutex_);
  if (enabled_) {
    zxlogf(ERROR, "%s: attempted to set notify callback when enabled", __func__);
    return ZX_ERR_BAD_STATE;
  }

  if (!cb) {
    notify_cb_.callback = nullptr;
    notify_cb_.ctx = nullptr;
  } else {
    notify_cb_ = *cb;
  }

  return ZX_OK;
}

void Uart16550::DdkRelease() {
  SerialImplEnable(false);
  // End the interrupt loop by canceling waits.
  interrupt_.destroy();
  interrupt_thread_.join();
  delete this;
}

void Uart16550::DdkUnbind(ddk::UnbindTxn txn) { txn.Reply(); }

bool Uart16550::SupportsAutomaticFlowControl() const { return uart_fifo_len_ == kFifoDepth16750; }

void Uart16550::ResetFifosLocked() {
  // 16750 requires we toggle extended fifo while divisor latch is enabled.
  LineControlRegister::Get().FromValue(0).set_divisor_latch_access(true).WriteTo(&port_io_);
  FifoControlRegister::Get()
      .FromValue(0)
      .set_fifo_enable(true)
      .set_rx_fifo_reset(true)
      .set_tx_fifo_reset(true)
      .set_dma_mode(0)
      .set_extended_fifo_enable(true)
      .set_receiver_trigger(FifoControlRegister::kMaxTriggerLevel)
      .WriteTo(&port_io_);
  LineControlRegister::Get().FromValue(0).set_divisor_latch_access(false).WriteTo(&port_io_);
}

void Uart16550::InitFifosLocked() {
  ResetFifosLocked();
  const auto iir = InterruptIdentRegister::Get().ReadFrom(&port_io_);
  if (iir.fifos_enabled()) {
    if (iir.extended_fifo_enabled()) {
      uart_fifo_len_ = kFifoDepth16750;
    } else {
      uart_fifo_len_ = kFifoDepth16550A;
    }
  } else {
    uart_fifo_len_ = kFifoDepthGeneric;
  }
}

void Uart16550::NotifyLocked() {
  if (notify_cb_.callback && enabled_) {
    notify_cb_.callback(notify_cb_.ctx, state_);
  }
}

// Loop and wait on the interrupt handle. When an interrupt is detected, read the interrupt
// identifier. If there is data available in the hardware RX FIFO, notify readable. If the
// hardware TX FIFO is empty, notify writable. If there is a line status error, log it. If
// there is a modem status, log it.
void Uart16550::HandleInterrupts() {
  // Ignore the timestamp.
  while (interrupt_.wait(nullptr) == ZX_OK) {
    std::lock_guard<std::mutex> lock(device_mutex_);

    if (!enabled_) {
      // Interrupts should be disabled now and we shouldn't respond to them.
      continue;
    }

    const auto identifier = InterruptIdentRegister::Get().ReadFrom(&port_io_).interrupt_id();

    switch (identifier) {
      case InterruptType::kNone:
        break;
      case InterruptType::kRxLineStatus: {
        // Clear the interrupt.
        const auto lsr = LineStatusRegister::Get().ReadFrom(&port_io_);
        if (lsr.overrun_error()) {
          zxlogf(ERROR, "%s: overrun error (OE) detected", __func__);
        }
        if (lsr.parity_error()) {
          zxlogf(ERROR, "%s: parity error (PE) detected", __func__);
        }
        if (lsr.framing_error()) {
          zxlogf(ERROR, "%s: framing error (FE) detected", __func__);
        }
        if (lsr.break_interrupt()) {
          zxlogf(ERROR, "%s: break interrupt (BI) detected", __func__);
        }
        if (lsr.error_in_rx_fifo()) {
          zxlogf(ERROR, "%s: error in rx fifo detected", __func__);
        }
        break;
      }
      case InterruptType::kRxDataAvailable:  // In both cases, there is data ready in the rx fifo.
      case InterruptType::kCharTimeout: {
        auto state = state_;
        state |= SERIAL_STATE_READABLE;
        if (state_ != state) {
          state_ = state;
          NotifyLocked();
        }
        break;
      }
      case InterruptType::kTxEmpty: {
        InterruptEnableRegister::Get().ReadFrom(&port_io_).set_tx_empty(false).WriteTo(&port_io_);
        auto state = state_;
        state |= SERIAL_STATE_WRITABLE;
        if (state_ != state) {
          state_ = state;
          NotifyLocked();
        }
        break;
      }
      case InterruptType::kModemStatus: {
        // Clear the interrupt.
        const auto msr = ModemStatusRegister::Get().ReadFrom(&port_io_);
        if (msr.clear_to_send()) {
          zxlogf(INFO, "%s: clear to send (CTS) detected", __func__);
        }
        if (msr.data_set_ready()) {
          zxlogf(INFO, "%s: data set ready (DSR) detected", __func__);
        }
        if (msr.ring_indicator()) {
          zxlogf(INFO, "%s: ring indicator (RI) detected", __func__);
        }
        if (msr.data_carrier_detect()) {
          zxlogf(INFO, "%s: data carrier (DCD) detected", __func__);
        }
        break;
      }
    }
  }
}

static constexpr zx_driver_ops_t driver_ops = [] {
  zx_driver_ops_t ops = {};
  ops.version = DRIVER_OPS_VERSION;
  ops.bind = Uart16550::Create;
  return ops;
}();

}  // namespace uart16550

// clang-format off
ZIRCON_DRIVER(uart16550, uart16550::driver_ops, "zircon", "0.1");
