/*
 * Emulated ccw-attached 3270 implementation
 *
 * Copyright 2017 IBM Corp.
 * Author(s): Yang Chen <bjcyang@linux.vnet.ibm.com>
 *            Jing Liu <liujbjl@linux.vnet.ibm.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or (at
 * your option) any later version. See the COPYING file in the top-level
 * directory.
 */

#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu/module.h"
#include "hw/s390x/css.h"
#include "hw/s390x/css-bridge.h"
#include "hw/qdev-properties.h"
#include "hw/s390x/3270-ccw.h"

/* Handle READ ccw commands from guest */
static int handle_payload_3270_read(EmulatedCcw3270Device *dev, CCW1 *ccw)
{
    EmulatedCcw3270Class *ck = EMULATED_CCW_3270_GET_CLASS(dev);
    CcwDevice *ccw_dev = CCW_DEVICE(dev);
    int len;

    if (!ccw->cda) {
        return -EFAULT;
    }

    len = ck->read_payload_3270(dev);
    if (len < 0) {
        return len;
    }
    ccw_dev->sch->curr_status.scsw.count = ccw->count - len;

    return 0;
}

/* Handle WRITE ccw commands to write data to client */
static int handle_payload_3270_write(EmulatedCcw3270Device *dev, CCW1 *ccw)
{
    EmulatedCcw3270Class *ck = EMULATED_CCW_3270_GET_CLASS(dev);
    CcwDevice *ccw_dev = CCW_DEVICE(dev);
    int len;

    if (!ccw->cda) {
        return -EFAULT;
    }

    len = ck->write_payload_3270(dev, ccw->cmd_code);

    if (len <= 0) {
        return len ? len : -EIO;
    }

    ccw_dev->sch->curr_status.scsw.count = ccw->count - len;
    return 0;
}

static int emulated_ccw_3270_cb(SubchDev *sch, CCW1 ccw)
{
    int rc = 0;
    EmulatedCcw3270Device *dev = sch->driver_data;

    switch (ccw.cmd_code) {
    case TC_WRITESF:
    case TC_WRITE:
    case TC_EWRITE:
    case TC_EWRITEA:
        rc = handle_payload_3270_write(dev, &ccw);
        break;
    case TC_RDBUF:
    case TC_READMOD:
        rc = handle_payload_3270_read(dev, &ccw);
        break;
    default:
        rc = -ENOSYS;
        break;
    }

    if (rc == -EIO) {
        /* I/O error, specific devices generate specific conditions */
        SCHIB *schib = &sch->curr_status;

        sch->curr_status.scsw.dstat = SCSW_DSTAT_UNIT_CHECK;
        sch->sense_data[0] = 0x40;    /* intervention-req */
        schib->scsw.ctrl &= ~SCSW_ACTL_START_PEND;
        schib->scsw.ctrl &= ~SCSW_CTRL_MASK_STCTL;
        schib->scsw.ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
                   SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
    }

    return rc;
}

static void emulated_ccw_3270_realize(DeviceState *ds, Error **errp)
{
    uint16_t chpid;
    EmulatedCcw3270Device *dev = EMULATED_CCW_3270(ds);
    EmulatedCcw3270Class *ck = EMULATED_CCW_3270_GET_CLASS(dev);
    CcwDevice *cdev = CCW_DEVICE(ds);
    CCWDeviceClass *cdk = CCW_DEVICE_GET_CLASS(cdev);
    SubchDev *sch;
    Error *err = NULL;

    sch = css_create_sch(cdev->devno, errp);
    if (!sch) {
        return;
    }

    if (!ck->init) {
        goto out_err;
    }

    sch->driver_data = dev;
    cdev->sch = sch;
    chpid = css_find_free_chpid(sch->cssid);

    if (chpid > MAX_CHPID) {
        error_setg(&err, "No available chpid to use.");
        goto out_err;
    }

    sch->id.reserved = 0xff;
    sch->id.cu_type = EMULATED_CCW_3270_CU_TYPE;
    css_sch_build_virtual_schib(sch, (uint8_t)chpid,
                                EMULATED_CCW_3270_CHPID_TYPE);
    sch->do_subchannel_work = do_subchannel_work_virtual;
    sch->ccw_cb = emulated_ccw_3270_cb;
    sch->irb_cb = build_irb_virtual;

    ck->init(dev, &err);
    if (err) {
        goto out_err;
    }

    cdk->realize(cdev, &err);
    if (err) {
        goto out_err;
    }

    return;

out_err:
    error_propagate(errp, err);
    css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
    cdev->sch = NULL;
    g_free(sch);
}

static Property emulated_ccw_3270_properties[] = {
    DEFINE_PROP_END_OF_LIST(),
};

static void emulated_ccw_3270_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);

    device_class_set_props(dc, emulated_ccw_3270_properties);
    dc->realize = emulated_ccw_3270_realize;
    dc->hotpluggable = false;
    set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
}

static const TypeInfo emulated_ccw_3270_info = {
    .name = TYPE_EMULATED_CCW_3270,
    .parent = TYPE_CCW_DEVICE,
    .instance_size = sizeof(EmulatedCcw3270Device),
    .class_init = emulated_ccw_3270_class_init,
    .class_size = sizeof(EmulatedCcw3270Class),
    .abstract = true,
};

static void emulated_ccw_register(void)
{
    type_register_static(&emulated_ccw_3270_info);
}

type_init(emulated_ccw_register)
