// Copyright 2017 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 "usb-mass-storage.h"

#include <ddk/debug.h>

#include <stdio.h>
#include <string.h>

static void ums_block_queue(void* ctx, block_op_t* op, block_impl_queue_callback completion_cb,
                            void* cookie) {
    ums_block_t* dev = ctx;
    ums_txn_t* txn = block_op_to_txn(op);
    txn->completion_cb = completion_cb;
    txn->cookie = cookie;

    switch (op->command & BLOCK_OP_MASK) {
    case BLOCK_OP_READ:
    case BLOCK_OP_WRITE:
        zxlogf(TRACE, "UMS QUEUE %s %u @%zu (%p)\n",
               (op->command & BLOCK_OP_MASK) == BLOCK_OP_READ ? "RD" : "WR",
               op->rw.length, op->rw.offset_dev, op);
        break;
    case BLOCK_OP_FLUSH:
        zxlogf(TRACE, "UMS QUEUE FLUSH (%p)\n", op);
        break;
    default:
        zxlogf(ERROR, "ums_block_queue: unsupported command %u\n", op->command);
        completion_cb(cookie, ZX_ERR_NOT_SUPPORTED, &txn->op);
        return;
    }

    ums_t* ums = block_to_ums(dev);
    txn->dev = dev;

    mtx_lock(&ums->txn_lock);
    list_add_tail(&ums->queued_txns, &txn->node);
    mtx_unlock(&ums->txn_lock);
    sync_completion_signal(&ums->txn_completion);
}

static void ums_get_info(void* ctx, block_info_t* info) {
    ums_block_t* dev = ctx;
    ums_t* ums = block_to_ums(dev);
    memset(info, 0, sizeof(*info));
    info->block_size = dev->block_size;
    info->block_count = dev->total_blocks;
    info->max_transfer_size = ums->max_transfer;
    info->flags = dev->flags;
}

static void ums_block_query(void* ctx, block_info_t* info_out, size_t* block_op_size_out) {
    ums_get_info(ctx, info_out);
    *block_op_size_out = sizeof(ums_txn_t);
}

static block_impl_protocol_ops_t ums_block_ops = {
    .query = ums_block_query,
    .queue = ums_block_queue,
};

static zx_status_t ums_block_ioctl(void* ctx, uint32_t op, const void* cmd, size_t cmdlen,
                                   void* reply, size_t max, size_t* out_actual) {
    ums_block_t* dev = ctx;

    // TODO implement other block ioctls
    switch (op) {
    case IOCTL_BLOCK_GET_INFO: {
        block_info_t* info = reply;
        if (max < sizeof(*info))
            return ZX_ERR_BUFFER_TOO_SMALL;
        ums_get_info(dev, info);
        *out_actual = sizeof(*info);
        return ZX_OK;
    }
    case IOCTL_DEVICE_SYNC: {
        return ZX_OK;
    }
    default:
        return ZX_ERR_NOT_SUPPORTED;
    }
}

static zx_off_t ums_block_get_size(void* ctx) {
    ums_block_t* dev = ctx;
    return dev->block_size * dev->total_blocks;
}

static zx_protocol_device_t ums_block_proto = {
    .version = DEVICE_OPS_VERSION,
    .ioctl = ums_block_ioctl,
    .get_size = ums_block_get_size,
};

zx_status_t ums_block_add_device(ums_t* ums, ums_block_t* dev) {
    char name[16];
    snprintf(name, sizeof(name), "lun-%03d", dev->lun);

    device_add_args_t args = {
        .version = DEVICE_ADD_ARGS_VERSION,
        .name = name,
        .ctx = dev,
        .ops = &ums_block_proto,
        .proto_id = ZX_PROTOCOL_BLOCK_IMPL,
        .proto_ops = &ums_block_ops,
    };

    return device_add(ums->zxdev, &args, &dev->zxdev);
}
