// Copyright 2020 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.

#ifndef LIB_UART_UART_H_
#define LIB_UART_UART_H_

#include <lib/arch/intrin.h>
#include <lib/devicetree/devicetree.h>
#include <lib/zbi-format/driver-config.h>
#include <lib/zbi-format/zbi.h>
#include <lib/zircon-internal/macros.h>
#include <lib/zircon-internal/thread_annotations.h>
#include <zircon/assert.h>
#include <zircon/compiler.h>

#include <cstdlib>
#include <optional>
#include <string_view>
#include <type_traits>
#include <utility>

#include <hwreg/mmio.h>
#include <hwreg/pio.h>

#include "chars-from.h"

// While this header is unused in this file, it provides the basic implementations
// for `Sync` types.
#include "sync.h"

namespace acpi_lite {
struct AcpiDebugPortDescriptor;
}

namespace uart {

//
// These types are used in configuring the line control settings (i.e., in the
// `SetLineControl()` method).
//

// Number of bits transmitted per character.
enum class DataBits {
  k5,
  k6,
  k7,
  k8,
};

// The bit pattern mechanism to help detect transmission errors.
enum class Parity {
  kNone,  // No bits dedicated to parity.
  kEven,  // Parity bit present; is 0 iff the number of 1s in the word is even.
  kOdd,   // Parity bit present; is 0 iff the number of 1s in the word is odd.
};

// The duration of the stop period in terms of the transmitted bit rate.
enum class StopBits {
  k1,
  k2,
};

// This template is specialized by payload configuration type (see below).
// It parses bits out of strings from the "kernel.serial" boot option.
template <typename Config>
inline std::optional<Config> ParseConfig(std::string_view) {
  static_assert(std::is_void_v<Config>, "missing specialization");
  return {};
}

// This template is specialized by payload configuration type (see below).
// It recreates a string for Parse.
template <typename Config>
inline void UnparseConfig(const Config& config, FILE* out) {
  static_assert(std::is_void_v<Config>, "missing specialization");
}

enum class IoRegisterType {
  // MMIO is performed without any scaling what so ever, this means that
  // registers offsets are treated as byte offsets from the base address.
  kMmio8,

  // MMIO is performed with an scaling factor of 4, this means that
  // register offsets are treated as 4-byte offsets from the base address.
  kMmio32,

  // PIO.
  kPio,
};

template <IoRegisterType IoRegType>
using IoSlotType = std::conditional_t<IoRegType == IoRegisterType::kPio, uint16_t, size_t>;

// Constant indicating that the number of `io_slots()` is to be determined at
// runtime.
constexpr size_t kDynamicIoSlot = std::numeric_limits<size_t>::max();

// Specific hardware support is implemented in a class uart::xyz::Driver,
// referred to here as UartDriver.  The uart::DriverBase template class
// provides a helper base class for UartDriver implementations.
//
// The UartDriver object represents the hardware itself.  Many UartDriver
// classes hold no state other than the initial configuration data used in the
// constructor, but a UartDriver is not required to be stateless.  However, a
// UartDriver is required to be copy-constructible, trivially destructible,
// and contain no pointers.  This makes it safe to copy an object set up by
// physboot into a new object in the virtual-memory kernel to hand off the
// configuration and the state of the hardware.
//
// All access to the UartDriver object is serialized by its caller, so it does
// no synchronization of its own.  This serves to serialize the actual access
// to the hardware.
//
// The UartDriver API fills four roles:
//  1. Match a ZBI item that configures this driver.
//  2. Generate a ZBI item for another kernel to match this configuration.
//  3. Configure the IoProvider (see below).
//  4. Drive the actual hardware.
//
// The first three are handled by DriverBase.  The KdrvExtra and KdrvConfig
// template arguments give the ZBI_KERNEL_DRIVER_* value and the zbi_dcfg_*_t type for the ZBI
// item.  The Pio template argument tells the IoProvider whether this driver
// uses MMIO or PIO (including PIO via MMIO): the number of consecutive PIO
// ports used, or 0 for simple MMIO.
//
// Item matching is done by the MaybeCreate static method.  If the item
// matches KdrvExtra, then the UartDriver(KdrvConfig) constructor is called.
// DriverBase provides this constructor to fill the cfg_ field, which the
// UartDriver can then refer to.  The UartDriver copy constructor copies it.
//
// The calls to drive the hardware are all template functions passed an
// IoProvider object (see below).  The driver accesses device registers using
// hwreg ReadFrom and WriteTo calls on the pointers from the provider.  The
// IoProvider constructed is passed uart.config() and uart.pio_size().
//
// `IoSlots` is an opaque parameter whose meaning is tied to the value of `IoRegType`.
// A very broad description would be the number of 'slots' to perform I/O operations.
// * `kMmio8` and `kMmio32` represents the number of bytes from the base address with the proper
//    scaling factor applied, 1 and 4 respectively.
// * `kPio` represents the number the port count.
template <typename Driver, uint32_t KdrvExtra, typename KdrvConfig, IoRegisterType IoRegType,
          IoSlotType<IoRegType> IoSlots = kDynamicIoSlot>
class DriverBase {
 public:
  using config_type = KdrvConfig;

  // No devicetree bindings by default.
  static constexpr std::array<std::string_view, 0> kDevicetreeBindings{};

  // Register Io Type.
  static constexpr IoRegisterType kIoType = IoRegType;

  explicit DriverBase(const config_type& cfg) : cfg_(cfg) {}

  constexpr bool operator==(const Driver& other) const {
    return memcmp(&cfg_, &other.cfg_, sizeof(cfg_)) == 0;
  }
  constexpr bool operator!=(const Driver& other) const { return !(*this == other); }

  // API to fill a ZBI item describing this UART.
  constexpr uint32_t type() const { return ZBI_TYPE_KERNEL_DRIVER; }
  constexpr uint32_t extra() const { return KdrvExtra; }
  constexpr size_t size() const { return sizeof(cfg_); }
  void FillItem(void* payload) const { memcpy(payload, &cfg_, sizeof(cfg_)); }

  // API to match a ZBI item describing this UART.
  static std::optional<Driver> MaybeCreate(const zbi_header_t& header, const void* payload) {
    static_assert(alignof(config_type) <= ZBI_ALIGNMENT);
    if (header.type == ZBI_TYPE_KERNEL_DRIVER && header.extra == KdrvExtra &&
        header.length >= sizeof(config_type)) {
      return Driver{*reinterpret_cast<const config_type*>(payload)};
    }
    return {};
  }

  // API to match a configuration string.
  static std::optional<Driver> MaybeCreate(std::string_view string) {
    const auto config_name = Driver::config_name();
    if (string.substr(0, config_name.size()) == config_name) {
      string.remove_prefix(config_name.size());
      auto config = ParseConfig<KdrvConfig>(string);
      if (config) {
        return Driver{*config};
      }
    }
    return {};
  }

  // API to match a devicetree bindings.
  static bool MatchDevicetree(const devicetree::PropertyDecoder& decoder) {
    if constexpr (Driver::kDevicetreeBindings.size() == 0) {
      return false;
    } else {
      auto compatible = decoder.FindProperty("compatible");
      if (!compatible) {
        return false;
      }

      auto compatible_list = compatible->AsStringList();
      if (!compatible_list) {
        return false;
      }

      return std::find_first_of(compatible_list->begin(), compatible_list->end(),
                                Driver::kDevicetreeBindings.begin(),
                                Driver::kDevicetreeBindings.end()) != compatible_list->end();
    }
  }

  // API to match DBG2 Table (ACPI). Currently only 16550 compatible uarts are supported.
  static std::optional<Driver> MaybeCreate(const acpi_lite::AcpiDebugPortDescriptor& debug_port) {
    return {};
  }

  // API to reproduce a configuration string.
  void Unparse(FILE* out) const {
    fprintf(out, "%.*s", static_cast<int>(Driver::config_name().size()),
            Driver::config_name().data());
    UnparseConfig<KdrvConfig>(cfg_, out);
  }

  // TODO(https://fxbug.dev/42053694): Remove once all drivers define this method.
  template <class IoProvider>
  void SetLineControl(IoProvider& io, std::optional<DataBits> data_bits,
                      std::optional<Parity> parity, std::optional<StopBits> stop_bits) {
    static_assert(!std::is_same_v<IoProvider, IoProvider>,
                  "TODO(https://fxbug.dev/42053694): implment me");
  }

  // API for use in IoProvider setup.
  const config_type& config() const { return cfg_; }

  // Number of 'slots' to perform I/O operations.
  template <IoSlotType<IoRegType> _IoSlots = IoSlots,
            std::enable_if_t<_IoSlots != kDynamicIoSlot, bool> = true>
  constexpr IoSlotType<IoRegType> io_slots() const {
    return IoSlots;
  }

  template <IoSlotType<IoRegType> _IoSlots = IoSlots,
            std::enable_if_t<_IoSlots == kDynamicIoSlot, bool> = true>
  constexpr IoSlotType<IoRegType> io_slots() const {
    static_assert(
        !std::is_same_v<void, void>,
        "|IoSlots| must be different from |kDynamicIoSlot| or |io_slots| implementation must be provided in derived class.");
    return IoSlots;
  }

 protected:
  config_type cfg_;

 private:
  template <typename T>
  static constexpr bool Uninstantiated = false;

  // uart::KernelDriver API
  //
  // These are here just to cause errors if Driver is missing its methods.
  // They also serve to document the API required by uart::KernelDriver.
  // They should all be overridden by Driver methods.
  //
  // Each method is a template parameterized by an hwreg-compatible type for
  // accessing the hardware registers via hwreg ReadFrom and WriteTo methods.
  // This lets Driver types be used with hwreg::Mock in tests independent of
  // actual hardware access.

  template <typename IoProvider>
  void Init(IoProvider& io) {
    static_assert(Uninstantiated<IoProvider>, "derived class is missing Init");
  }

  // Return true if Write can make forward progress right now.
  // The return value can be anything contextually convertible to bool.
  // The value will be passed on to Write.
  template <typename IoProvider>
  bool TxReady(IoProvider& io) {
    static_assert(Uninstantiated<IoProvider>, "derived class is missing TxReady");
    return false;
  }

  // This is called only when TxReady() has just returned something that
  // converts to true; that's passed here so it can convey more information
  // such as a count.  Advance the iterator at least one and as many as is
  // convenient but not past end, outputting each character before advancing.
  template <typename IoProvider, typename It1, typename It2>
  auto Write(IoProvider& io, bool ready, It1 it, const It2& end) {
    static_assert(Uninstantiated<IoProvider>, "derived class is missing Write");
    return end;
  }

  // Poll for an incoming character and return one if there is one.
  template <typename IoProvider>
  std::optional<uint8_t> Read(IoProvider& io) {
    static_assert(Uninstantiated<IoProvider>, "derived class is missing Read");
    return {};
  }

  // Set the UART up to deliver interrupts.  This is called after Init.
  // After this, Interrupt (below) may be called from interrupt context.
  template <typename IoProvider>
  void InitInterrupt(IoProvider& io) {
    static_assert(Uninstantiated<IoProvider>, "derived class is missing InitInterrupt");
  }

  // Enable transmit interrupts so Interrupt will be called when TxReady().
  template <typename IoProvider>
  void EnableTxInterrupt(IoProvider& io) {
    static_assert(Uninstantiated<IoProvider>, "derived class is missing EnableTxInterrupt");
  }

  // Service an interrupt.
  // Call tx(sync, disable_tx_irq) if transmission has become ready.
  // If receiving has become ready, call rx(sync, read_char, full) one or more
  // times, where read_char() -> uint8_t if there is receive buffer
  // space and full() -> void if there is no space.
  // |sync| provides access to the environment specific synchronization primitives(if any),
  // and synchronization related data structures(if any).
  template <typename IoProvider, typename Sync, typename Tx, typename Rx>
  void Interrupt(IoProvider& io, Sync& sync, Tx&& tx, Rx&& rx) {
    static_assert(Uninstantiated<IoProvider>, "derived class is missing Interrupt");
  }
};

// The IoProvider is a template class parameterized by UartDriver::config_type,
// i.e. the zbi_dcfg_*_t type for the ZBI item's format.  This class is responsible
// for supplying pointers to be passed to hwreg types' ReadFrom and WriteTo.
//
// The IoProvider(UartDriver::config_type, uint16_t pio_size) constructor
// initializes the object.  Then IoProvider::io() is called to yield the
// pointer to pass to hwreg calls.
//
// uart::BasicIoProvider handles the simple case where physical MMIO and PIO
// base addresses are used directly.  It also provides base classes that can be
// subclassed with an overridden constructor that does address mapping.
//
template <typename Config, IoRegisterType IoType>
class BasicIoProvider;

// This is the default "identity mapping" callback for BasicIoProvider::Init.
// A subclass can have an Init function that calls BasicIoProvider::Init with
// a different callback function.
//
// The `size` parameter represents the number of bytes from `phys`, such that
// the mmio region to be mapped is contained in p[`phys`, `phys` + `size`).
inline auto DirectMapMmio(uint64_t phys, size_t size) {
  return reinterpret_cast<volatile void*>(phys);
}

// The specialization used most commonly handles simple MMIO devices.
template <IoRegisterType IoType>
class BasicIoProvider<zbi_dcfg_simple_t, IoType> {
 public:
  // Just install the MMIO base pointer.  The third argument can be passed by
  // a subclass constructor method to map the physical address to a virtual
  // address.
  template <typename T>
  BasicIoProvider(const zbi_dcfg_simple_t& cfg, size_t io_slots, T&& map_mmio) {
    if constexpr (IoType == IoRegisterType::kMmio8) {
      io_.emplace<hwreg::RegisterMmio>(map_mmio(cfg.mmio_phys, io_slots));
    } else if constexpr (IoType == IoRegisterType::kMmio32) {
      io_.emplace<hwreg::RegisterMmioScaled<uint32_t>>(map_mmio(cfg.mmio_phys, io_slots * 4));
    } else {
      // Pio uses a different specialization, this should never be reached.
      static_assert(!std::is_same_v<T, T>);
    }
  }

  BasicIoProvider(const zbi_dcfg_simple_t& cfg, size_t io_slots)
      : BasicIoProvider(cfg, io_slots, DirectMapMmio) {}

  BasicIoProvider& operator=(BasicIoProvider&& other) {
    io_.swap(other.io_);
    return *this;
  }

  auto* io() { return &io_; }

 private:
  std::variant<hwreg::RegisterMmio, hwreg::RegisterMmioScaled<uint32_t>> io_{std::in_place_index<0>,
                                                                             nullptr};
};

// The specialization for devices using actual PIO only occurs on x86.
#if defined(__x86_64__) || defined(__i386__)
template <IoRegisterType IoType>
class BasicIoProvider<zbi_dcfg_simple_pio_t, IoType> {
 public:
  explicit BasicIoProvider(const zbi_dcfg_simple_pio_t& cfg, uint16_t io_slots) : io_(cfg.base) {
    static_assert(IoType == IoRegisterType::kPio);
    ZX_DEBUG_ASSERT(io_slots > 0);
  }

  auto* io() { return &io_; }

 private:
  hwreg::RegisterDirectPio io_;
};
#endif

// Forward declaration.
namespace mock {
class Driver;
}

// The KernelDriver template class is parameterized by those three to implement
// actual driver logic for some environment.
//
// The KernelDriver constructor just passes its arguments through to the
// UartDriver constructor.  So it can be created directly from a configuration
// struct or copied from another UartDriver object.  In this way, the device is
// handed off from one KernelDriver instantiation to a different one using a
// different IoProvider (physboot vs kernel) and/or Sync (polling vs blocking).
//
template <class UartDriver, template <typename, IoRegisterType> class IoProvider, class SyncPolicy>
class KernelDriver {
  using Waiter = typename SyncPolicy::Waiter;

  template <typename LockPolicy>
  using Guard = typename SyncPolicy::template Guard<LockPolicy>;

  template <typename MemberOf>
  using Lock = typename SyncPolicy::template Lock<MemberOf>;

  using DefaultLockPolicy = typename SyncPolicy::DefaultLockPolicy;

 public:
  using uart_type = UartDriver;
  static_assert(std::is_copy_constructible_v<uart_type>);
  static_assert(std::is_trivially_destructible_v<uart_type> ||
                std::is_same_v<uart_type, mock::Driver>);

  // This sets up the object but not the device itself.  The device might
  // already have been set up by a previous instantiation's Init function,
  // or might never actually be set up because this instantiation gets
  // replaced with a different one before ever calling Init.
  template <typename... Args>
  explicit KernelDriver(Args&&... args)
      : uart_(std::forward<Args>(args)...), io_(uart_.config(), uart_.io_slots()) {
    if constexpr (std::is_same_v<mock::Driver, uart_type>) {
      // Initialize the mock sync object with the mock driver.
      lock_.Init(uart_);
      waiter_.Init(uart_);
    }
  }

  // Access underlying hardware driver object.
  const auto& uart() const { return uart_; }
  auto& uart() { return uart_; }

  // Access IoProvider object.
  auto& io() { return io_; }

  // Set up the device for nonblocking output and polling input.
  // If the device is handed off from a different instantiation,
  // this won't be called in the new instantiation.
  template <typename LockPolicy = DefaultLockPolicy>
  void Init() {
    Guard<LockPolicy> lock(&lock_, SOURCE_TAG);
    uart_.Init(io_);
  }

  // Write out a string that Parse() can read back to recreate the driver
  // state.  This doesn't preserve the driver state, only the configuration.
  template <typename LockPolicy = DefaultLockPolicy>
  void Unparse(FILE* out) const {
    Guard<LockPolicy> lock(&lock_, SOURCE_TAG);
    uart_.Unparse(out);
  }

  // Configure the UART line control settings.
  //
  // An individual setting given by std::nullopt signifies that it should be
  // left as previously configured.
  //
  // TODO(https://fxbug.dev/42053694): Separate out the setting of baud rate.
  template <typename LockPolicy = DefaultLockPolicy>
  void SetLineControl(std::optional<DataBits> data_bits = DataBits::k8,
                      std::optional<Parity> parity = Parity::kNone,
                      std::optional<StopBits> stop_bits = StopBits::k1) {
    Guard<LockPolicy> lock(&lock_, SOURCE_TAG);
    uart_.SetLineControl(io_, data_bits, parity, stop_bits);
  }

  // TODO(https://fxbug.dev/42079801): Asses the need of |enable_interrupt_callback|.
  template <typename LockPolicy = DefaultLockPolicy, typename EnableInterruptCallback>
  void InitInterrupt(EnableInterruptCallback&& enable_interrupt_callback) {
    Guard<LockPolicy> lock(&lock_, SOURCE_TAG);
    uart_.InitInterrupt(io_, std::forward<EnableInterruptCallback>(enable_interrupt_callback));
  }

  template <typename Tx, typename Rx>
  void Interrupt(Tx&& tx, Rx&& rx) TA_NO_THREAD_SAFETY_ANALYSIS {
    // Interrupt is responsible for properly acquiring and releasing sync
    // where needed.
    uart_.Interrupt(io_, lock_, waiter_, std::forward<Tx>(tx), std::forward<Rx>(rx));
  }

  // This is the FILE-compatible API: `FILE::stdout_ = FILE{&driver};`.
  template <typename LockPolicy = DefaultLockPolicy, typename... Args>
  int Write(std::string_view str, Args&&... waiter_args) {
    uart::CharsFrom chars(str);  // Massage into uint8_t with \n -> CRLF.
    auto it = chars.begin();
    Guard<LockPolicy> lock(&lock_, SOURCE_TAG);
    while (it != chars.end()) {
      // Wait until the UART is ready for Write.
      auto ready = uart_.TxReady(io_);
      while (!ready) {
        // Block or just unlock and spin or whatever "wait" means to Sync.
        // If that means blocking for interrupt wakeup, enable tx interrupts.
        waiter_.template Wait(
            lock,
            [this]() {
              SyncPolicy::AssertHeld(lock_);
              uart_.EnableTxInterrupt(io_);
            },
            std::forward<Args>(waiter_args)...);
        ready = uart_.TxReady(io_);
      }
      // Advance the iterator by writing some.
      it = uart_.Write(io_, std::move(ready), it, chars.end());
    }
    return static_cast<int>(str.size());
  }

  // This is a direct polling read, not used in interrupt-based operation.
  template <typename LockPolicy = DefaultLockPolicy>
  auto Read() {
    Guard<LockPolicy> lock(&lock_, SOURCE_TAG);
    return uart_.Read(io_);
  }

  template <typename LockPolicy = DefaultLockPolicy>
  void EnableRxInterrupt() {
    Guard<LockPolicy> lock(&lock_, SOURCE_TAG);
    uart_.EnableRxInterrupt(io_);
  }

 private:
  Lock<KernelDriver> lock_;
  Waiter waiter_ TA_GUARDED(lock_);
  uart_type uart_ TA_GUARDED(lock_);

  IoProvider<typename uart_type::config_type, uart_type::kIoType> io_;
};

// These specializations are defined in the library to cover all the ZBI item
// payload types used by the various drivers.

template <>
std::optional<zbi_dcfg_simple_t> ParseConfig<zbi_dcfg_simple_t>(std::string_view string);

template <>
void UnparseConfig(const zbi_dcfg_simple_t& config, FILE* out);

template <>
std::optional<zbi_dcfg_simple_pio_t> ParseConfig<zbi_dcfg_simple_pio_t>(std::string_view string);

template <>
void UnparseConfig(const zbi_dcfg_simple_pio_t& config, FILE* out);

}  // namespace uart

#endif  // LIB_UART_UART_H_
