/*
 * vhost-scsi-common
 *
 * Copyright (c) 2016 Nutanix Inc. All rights reserved.
 *
 * Author:
 *  Felipe Franciosi <felipe@nutanix.com>
 *
 * This work is largely based on the "vhost-scsi" implementation by:
 *  Stefan Hajnoczi    <stefanha@linux.vnet.ibm.com>
 *  Nicholas Bellinger <nab@risingtidesystems.com>
 *
 * This work is licensed under the terms of the GNU LGPL, version 2 or later.
 * See the COPYING.LIB file in the top-level directory.
 *
 */

#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "qemu/module.h"
#include "hw/virtio/vhost.h"
#include "hw/virtio/vhost-scsi-common.h"
#include "hw/virtio/virtio-scsi.h"
#include "hw/virtio/virtio-bus.h"
#include "hw/virtio/virtio-access.h"
#include "hw/fw-path-provider.h"

int vhost_scsi_common_start(VHostSCSICommon *vsc, Error **errp)
{
    int ret, i;
    VirtIODevice *vdev = VIRTIO_DEVICE(vsc);
    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);

    VirtIOSCSICommon *vs = (VirtIOSCSICommon *)vsc;

    if (!k->set_guest_notifiers) {
        error_setg(errp, "binding does not support guest notifiers");
        return -ENOSYS;
    }

    ret = vhost_dev_enable_notifiers(&vsc->dev, vdev);
    if (ret < 0) {
        error_setg_errno(errp, -ret, "Error enabling host notifiers");
        return ret;
    }

    ret = k->set_guest_notifiers(qbus->parent, vsc->dev.nvqs, true);
    if (ret < 0) {
        error_setg_errno(errp, -ret, "Error binding guest notifier");
        goto err_host_notifiers;
    }

    vsc->dev.acked_features = vdev->guest_features;

    ret = vhost_dev_prepare_inflight(&vsc->dev, vdev);
    if (ret < 0) {
        error_setg_errno(errp, -ret, "Error setting inflight format");
        goto err_guest_notifiers;
    }

    if (vsc->inflight) {
        if (!vsc->inflight->addr) {
            ret = vhost_dev_get_inflight(&vsc->dev,
                                        vs->conf.virtqueue_size,
                                        vsc->inflight);
            if (ret < 0) {
                error_setg_errno(errp, -ret, "Error getting inflight");
                goto err_guest_notifiers;
            }
        }

        ret = vhost_dev_set_inflight(&vsc->dev, vsc->inflight);
        if (ret < 0) {
            error_setg_errno(errp, -ret, "Error setting inflight");
            goto err_guest_notifiers;
        }
    }

    ret = vhost_dev_start(&vsc->dev, vdev, true);
    if (ret < 0) {
        error_setg_errno(errp, -ret, "Error starting vhost dev");
        goto err_guest_notifiers;
    }

    /* guest_notifier_mask/pending not used yet, so just unmask
     * everything here.  virtio-pci will do the right thing by
     * enabling/disabling irqfd.
     */
    for (i = 0; i < vsc->dev.nvqs; i++) {
        vhost_virtqueue_mask(&vsc->dev, vdev, vsc->dev.vq_index + i, false);
    }

    return ret;

err_guest_notifiers:
    k->set_guest_notifiers(qbus->parent, vsc->dev.nvqs, false);
err_host_notifiers:
    vhost_dev_disable_notifiers(&vsc->dev, vdev);
    return ret;
}

void vhost_scsi_common_stop(VHostSCSICommon *vsc)
{
    VirtIODevice *vdev = VIRTIO_DEVICE(vsc);
    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
    int ret = 0;

    vhost_dev_stop(&vsc->dev, vdev, true);

    if (k->set_guest_notifiers) {
        ret = k->set_guest_notifiers(qbus->parent, vsc->dev.nvqs, false);
        if (ret < 0) {
                error_report("vhost guest notifier cleanup failed: %d", ret);
        }
    }
    assert(ret >= 0);

    vhost_dev_disable_notifiers(&vsc->dev, vdev);
}

uint64_t vhost_scsi_common_get_features(VirtIODevice *vdev, uint64_t features,
                                        Error **errp)
{
    VHostSCSICommon *vsc = VHOST_SCSI_COMMON(vdev);

    /* Turn on predefined features supported by this device */
    features |= vsc->host_features;

    return vhost_get_features(&vsc->dev, vsc->feature_bits, features);
}

void vhost_scsi_common_set_config(VirtIODevice *vdev, const uint8_t *config)
{
    VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);

    if ((uint32_t)virtio_ldl_p(vdev, &scsiconf->sense_size) != vs->sense_size ||
        (uint32_t)virtio_ldl_p(vdev, &scsiconf->cdb_size) != vs->cdb_size) {
        error_report("vhost-scsi does not support changing the sense data and "
                     "CDB sizes");
        exit(1);
    }
}

/*
 * Implementation of an interface to adjust firmware path
 * for the bootindex property handling.
 */
char *vhost_scsi_common_get_fw_dev_path(FWPathProvider *p, BusState *bus,
                                        DeviceState *dev)
{
    VHostSCSICommon *vsc = VHOST_SCSI_COMMON(dev);
    /* format: /channel@channel/vhost-scsi@target,lun */
    return g_strdup_printf("/channel@%x/%s@%x,%x", vsc->channel,
                           qdev_fw_name(dev), vsc->target, vsc->lun);
}

static const TypeInfo vhost_scsi_common_info = {
    .name = TYPE_VHOST_SCSI_COMMON,
    .parent = TYPE_VIRTIO_SCSI_COMMON,
    .instance_size = sizeof(VHostSCSICommon),
    .abstract = true,
};

static void virtio_register_types(void)
{
    type_register_static(&vhost_scsi_common_info);
}

type_init(virtio_register_types)
