// Copyright 2018 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 SRC_DEVICES_BLOCK_DRIVERS_FTL_BLOCK_DEVICE_H_
#define SRC_DEVICES_BLOCK_DRIVERS_FTL_BLOCK_DEVICE_H_

#include <fuchsia/hardware/badblock/c/banjo.h>
#include <fuchsia/hardware/badblock/cpp/banjo.h>
#include <fuchsia/hardware/block/c/banjo.h>
#include <fuchsia/hardware/block/cpp/banjo.h>
#include <fuchsia/hardware/block/partition/cpp/banjo.h>
#include <fuchsia/hardware/nand/c/banjo.h>
#include <lib/ftl/volume.h>
#include <lib/inspect/cpp/vmo/types.h>
#include <lib/sync/completion.h>
#include <lib/zircon-internal/thread_annotations.h>
#include <threads.h>
#include <zircon/boot/image.h>
#include <zircon/listnode.h>
#include <zircon/types.h>

#include <memory>

#include <ddktl/device.h>
#include <fbl/macros.h>
#include <fbl/mutex.h>

#include "src/devices/block/drivers//ftl/metrics.h"
#include "src/devices/block/drivers/ftl/nand_driver.h"

namespace ftl {

struct BlockParams {
  uint64_t GetSize() const { return static_cast<uint64_t>(page_size) * num_pages; }

  uint32_t page_size;
  uint32_t num_pages;
};

// Ftl version of block_op_t.
// TODO(rvargas): Explore using c++ lists.
struct FtlOp {
  block_op_t op;
  list_node_t node;
  block_impl_queue_callback completion_cb;
  void* cookie;
};

class BlockDevice;
using DeviceType = ddk::Device<BlockDevice, ddk::GetSizable, ddk::Unbindable, ddk::Messageable,
                               ddk::Suspendable, ddk::Resumable, ddk::GetProtocolable>;

// Exposes the FTL library as a Fuchsia BlockDevice protocol.
class BlockDevice : public DeviceType,
                    public ddk::BlockImplProtocol<BlockDevice, ddk::base_protocol>,
                    public ddk::BlockPartitionProtocol<BlockDevice>,
                    public ftl::FtlInstance {
 public:
  explicit BlockDevice(zx_device_t* parent = nullptr) : DeviceType(parent) {}
  ~BlockDevice();

  zx_status_t Bind();
  void DdkRelease() { delete this; }
  void DdkUnbind(ddk::UnbindTxn txn);

  // Performs the object initialization.
  zx_status_t Init();

  // Device protocol implementation.
  zx_off_t DdkGetSize() { return params_.GetSize(); }
  zx_status_t DdkMessage(fidl_incoming_msg_t* msg, fidl_txn_t* txn);
  zx_status_t Suspend();
  void DdkSuspend(ddk::SuspendTxn txn);
  void DdkResume(ddk::ResumeTxn txn) {
    txn.Reply(ZX_OK, DEV_POWER_STATE_D0, txn.requested_state());
  }
  zx_status_t DdkGetProtocol(uint32_t proto_id, void* out_protocol);

  // Block protocol implementation.
  void BlockImplQuery(block_info_t* info_out, size_t* block_op_size_out);
  void BlockImplQueue(block_op_t* operation, block_impl_queue_callback completion_cb, void* cookie);

  // Partition protocol implementation.
  zx_status_t BlockPartitionGetGuid(guidtype_t guid_type, guid_t* out_guid);
  zx_status_t BlockPartitionGetName(char* out_name, size_t capacity);

  // FtlInstance interface.
  bool OnVolumeAdded(uint32_t page_size, uint32_t num_pages) final;

  // Issues a command to format the FTL (aka, delete all data).
  zx_status_t Format();

  // Returns a read_only handle to the underlying Inspect VMO.
  zx::vmo DuplicateInspectVmo() const { return metrics_.DuplicateInspectVmo(); }

  OperationCounters& nand_counters() { return nand_counters_; }

  void SetVolumeForTest(std::unique_ptr<ftl::Volume> volume) { volume_ = std::move(volume); }

  void SetNandParentForTest(const nand_protocol_t& nand) { parent_ = nand; }

  DISALLOW_COPY_ASSIGN_AND_MOVE(BlockDevice);

 private:
  bool InitFtl();
  void Kill();
  bool AddToList(FtlOp* operation);
  bool RemoveFromList(FtlOp** operation);
  int WorkerThread();
  static int WorkerThreadStub(void* arg);

  // Implementation of the actual commands.
  zx_status_t ReadWriteData(block_op_t* operation);
  zx_status_t TrimData(block_op_t* operation);
  zx_status_t Flush();

  BlockParams params_ = {};

  fbl::Mutex lock_;
  list_node_t txn_list_ TA_GUARDED(lock_) = LIST_INITIAL_VALUE(txn_list_);
  bool dead_ TA_GUARDED(lock_) = false;

  bool thread_created_ = false;
  bool pending_flush_ = false;

  sync_completion_t wake_signal_;
  thrd_t worker_;

  nand_protocol_t parent_ = {};
  bad_block_protocol_t bad_block_ = {};

  std::unique_ptr<ftl::Volume> volume_;

  uint8_t guid_[ZBI_PARTITION_GUID_LEN] = {};

  Metrics metrics_;

  // Keeps track of the nand operations being issued for each incoming block operation.
  OperationCounters nand_counters_;
};

}  // namespace ftl

#endif  // SRC_DEVICES_BLOCK_DRIVERS_FTL_BLOCK_DEVICE_H_
