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

/// NandOperation's are submitted for processing via the queue() method of the
/// Nand Protocol. Once submitted, the contents of the NandOperation may be modified
/// while it's being processed.
///
/// The completion_cb() must eventually be called upon success or failure and
/// at that point the cookie field must contain whatever value was in it when
/// the NandOperation was originally queued.
///
/// corrected_bit_flips are always related to nand_info.ecc_bits, so it is
/// possible to obtain a value that is larger than what is being read (in the oob
/// case). On the other hand, if errors cannot be corrected, the operation will
/// fail, and corrected_bit_flips will be undefined.
library fuchsia.hardware.nand;

using fuchsia.hardware.nandinfo;
using zx;

/// NOTE: The protocol can be extended with barriers to support controllers that
/// may issue multiple simultaneous request to the IO chips.
enum NandOp : uint32 {
    READ = 0x1;
    WRITE = 0x2;
    ERASE = 0x3;
};

/// A single operation can read or write an arbitrary number of pages,
/// including out of band (OOB) data for each page. If either regular
/// data or OOB is not required, the relevant VMO handle should be set to
/// ZX_HANDLE_INVALID.
///
/// Note that length dictates the number of pages to access, regardless
/// of the type of data requested: regular data, OOB or both.
///
/// The OOB data will be copied to (and from) a contiguous memory range
/// starting at the given offset. Note that said offset is given in nand
/// pages even though OOB is just a handful of bytes per page. In other
/// words, after said offset, the OOB data for each page is located
/// nand_info.oob_size bytes apart.
///
/// For example, to read 5 pages worth of data + OOB, with page size of
/// 2 kB and 16 bytes of OOB per page, setting:
///
///     data_vmo = oob_vmo = vmo_handle
///     length = 5
///     offset_nand = 20
///     offset_data_vmo = 0
///     offset_oob_vmo = 5
///
/// will transfer pages [20, 24] to the first 2048 * 5 bytes of the vmo,
/// followed by 16 * 5 bytes of OOB data starting at offset 2048 * 5.
resource struct NandReadWrite {
    /// Command.
    NandOp command;

    /// vmo of data to read or write.
    zx.handle:VMO data_vmo;

    /// vmo of OOB data to read or write.
    zx.handle:VMO oob_vmo;

    /// Number of pages to access.
    /// (0 is invalid).
    uint32 length;

    /// Offset into nand, in pages.
    uint32 offset_nand;

    /// Data vmo offset in (nand) pages.
    uint64 offset_data_vmo;

    /// OOB vmo offset in (nand) pages.
    uint64 offset_oob_vmo;

    /// Return value from READ_DATA, max corrected bit flips in any
    /// underlying ECC chunk read. The caller can compare this value
    /// against ecc_bits to decide whether the nand erase block needs to
    /// be recycled.
    uint32 corrected_bit_flips;
};

struct NandErase {
    /// Command.
    NandOp command;

    /// Offset into nand, in erase blocks.
    uint32 first_block;

    /// Number of blocks to erase. (0 is invalid).
    uint32 num_blocks;
};

resource union NandOperation {
    /// All Commands.
    1: NandOp command;

    /// NAND_OP_READ, NAND_OP_WRITE.
    2: NandReadWrite rw;

    /// NAND_OP_ERASE.
    3: NandErase erase;
};

[Transport = "Banjo", BanjoLayout = "ddk-protocol"]
protocol Nand {
    /// Obtains the parameters of the nand device and the required
    /// size of |NandOperation|. The |NandOperation| submitted via Queue() must have
    /// `nand_op_size - sizeof(NandOperation)` bytes available at the end of the
    /// structure for the use of the driver.
    Query() -> (fuchsia.hardware.nandinfo.NandInfo info, uint64 nand_op_size);

    /// Submits an IO request for processing. Success or failure will be reported
    /// via the callback. The callback may be called before the Queue() method returns.
    /// Should return ZX_ERR_IO *only* when error ocurred due to underlying hardware.
    /// When the hardware is not able to correct all bitflips for a page, the
    /// driver should return ZX_ERR_IO_DATA_INTEGRITY.
    [Async]
    Queue([InOut] NandOperation op) -> (zx.status status, [Mutable] NandOperation op);

    /// Gets the list of bad erase blocks, as reported by the nand manufacturer.
    /// This should only be called before writing any data to the nand, and the
    /// returned data should be saved somewhere else, along blocks that become
    /// bad after they've been in use.
    GetFactoryBadBlockList() -> (zx.status status, vector<uint32> bad_blocks);
};
