/*
 * SPDX-License-Identifier: GPL-2.0-or-later
 *
 * Goldfish TTY
 *
 * (c) 2020 Laurent Vivier <laurent@vivier.eu>
 *
 */

#include "qemu/osdep.h"
#include "hw/irq.h"
#include "hw/qdev-properties-system.h"
#include "hw/sysbus.h"
#include "migration/vmstate.h"
#include "chardev/char-fe.h"
#include "qemu/log.h"
#include "trace.h"
#include "exec/address-spaces.h"
#include "sysemu/dma.h"
#include "hw/char/goldfish_tty.h"

#define GOLDFISH_TTY_VERSION 1

/* registers */

enum {
    REG_PUT_CHAR      = 0x00,
    REG_BYTES_READY   = 0x04,
    REG_CMD           = 0x08,
    REG_DATA_PTR      = 0x10,
    REG_DATA_LEN      = 0x14,
    REG_DATA_PTR_HIGH = 0x18,
    REG_VERSION       = 0x20,
};

/* commands */

enum {
    CMD_INT_DISABLE   = 0x00,
    CMD_INT_ENABLE    = 0x01,
    CMD_WRITE_BUFFER  = 0x02,
    CMD_READ_BUFFER   = 0x03,
};

static uint64_t goldfish_tty_read(void *opaque, hwaddr addr,
                                  unsigned size)
{
    GoldfishTTYState *s = opaque;
    uint64_t value = 0;

    switch (addr) {
    case REG_BYTES_READY:
        value = fifo8_num_used(&s->rx_fifo);
        break;
    case REG_VERSION:
        value = GOLDFISH_TTY_VERSION;
        break;
    default:
        qemu_log_mask(LOG_UNIMP,
                      "%s: unimplemented register read 0x%02"HWADDR_PRIx"\n",
                      __func__, addr);
        break;
    }

    trace_goldfish_tty_read(s, addr, size, value);

    return value;
}

static void goldfish_tty_cmd(GoldfishTTYState *s, uint32_t cmd)
{
    uint32_t to_copy;
    uint8_t data_out[GOLFISH_TTY_BUFFER_SIZE];
    int len;
    uint64_t ptr;

    switch (cmd) {
    case CMD_INT_DISABLE:
        if (s->int_enabled) {
            if (!fifo8_is_empty(&s->rx_fifo)) {
                qemu_set_irq(s->irq, 0);
            }
            s->int_enabled = false;
        }
        break;
    case CMD_INT_ENABLE:
        if (!s->int_enabled) {
            if (!fifo8_is_empty(&s->rx_fifo)) {
                qemu_set_irq(s->irq, 1);
            }
            s->int_enabled = true;
        }
        break;
    case CMD_WRITE_BUFFER:
        len = s->data_len;
        ptr = s->data_ptr;
        while (len) {
            to_copy = MIN(GOLFISH_TTY_BUFFER_SIZE, len);

            dma_memory_read_relaxed(&address_space_memory, ptr,
                                    data_out, to_copy);
            qemu_chr_fe_write_all(&s->chr, data_out, to_copy);

            len -= to_copy;
            ptr += to_copy;
        }
        break;
    case CMD_READ_BUFFER:
        len = s->data_len;
        ptr = s->data_ptr;
        while (len && !fifo8_is_empty(&s->rx_fifo)) {
            const uint8_t *buf = fifo8_pop_bufptr(&s->rx_fifo, len, &to_copy);

            dma_memory_write_relaxed(&address_space_memory, ptr, buf, to_copy);

            len -= to_copy;
            ptr += to_copy;
        }
        if (s->int_enabled && fifo8_is_empty(&s->rx_fifo)) {
            qemu_set_irq(s->irq, 0);
        }
        break;
    }
}

static void goldfish_tty_write(void *opaque, hwaddr addr,
                               uint64_t value, unsigned size)
{
    GoldfishTTYState *s = opaque;
    unsigned char c;

    trace_goldfish_tty_write(s, addr, size, value);

    switch (addr) {
    case REG_PUT_CHAR:
        c = value;
        qemu_chr_fe_write_all(&s->chr, &c, sizeof(c));
        break;
    case REG_CMD:
        goldfish_tty_cmd(s, value);
        break;
    case REG_DATA_PTR:
        s->data_ptr = value;
        break;
    case REG_DATA_PTR_HIGH:
        s->data_ptr = deposit64(s->data_ptr, 32, 32, value);
        break;
    case REG_DATA_LEN:
        s->data_len = value;
        break;
    default:
        qemu_log_mask(LOG_UNIMP,
                      "%s: unimplemented register write 0x%02"HWADDR_PRIx"\n",
                      __func__, addr);
        break;
    }
}

static const MemoryRegionOps goldfish_tty_ops = {
    .read = goldfish_tty_read,
    .write = goldfish_tty_write,
    .endianness = DEVICE_NATIVE_ENDIAN,
    .valid.max_access_size = 4,
    .impl.max_access_size = 4,
    .impl.min_access_size = 4,
};

static int goldfish_tty_can_receive(void *opaque)
{
    GoldfishTTYState *s = opaque;
    int available = fifo8_num_free(&s->rx_fifo);

    trace_goldfish_tty_can_receive(s, available);

    return available;
}

static void goldfish_tty_receive(void *opaque, const uint8_t *buffer, int size)
{
    GoldfishTTYState *s = opaque;

    trace_goldfish_tty_receive(s, size);

    g_assert(size <= fifo8_num_free(&s->rx_fifo));

    fifo8_push_all(&s->rx_fifo, buffer, size);

    if (s->int_enabled && !fifo8_is_empty(&s->rx_fifo)) {
        qemu_set_irq(s->irq, 1);
    }
}

static void goldfish_tty_reset(DeviceState *dev)
{
    GoldfishTTYState *s = GOLDFISH_TTY(dev);

    trace_goldfish_tty_reset(s);

    fifo8_reset(&s->rx_fifo);
    s->int_enabled = false;
    s->data_ptr = 0;
    s->data_len = 0;
}

static void goldfish_tty_realize(DeviceState *dev, Error **errp)
{
    GoldfishTTYState *s = GOLDFISH_TTY(dev);

    trace_goldfish_tty_realize(s);

    fifo8_create(&s->rx_fifo, GOLFISH_TTY_BUFFER_SIZE);
    memory_region_init_io(&s->iomem, OBJECT(s), &goldfish_tty_ops, s,
                          "goldfish_tty", 0x24);

    if (qemu_chr_fe_backend_connected(&s->chr)) {
        qemu_chr_fe_set_handlers(&s->chr, goldfish_tty_can_receive,
                                 goldfish_tty_receive, NULL, NULL,
                                 s, NULL, true);
    }
}

static void goldfish_tty_unrealize(DeviceState *dev)
{
    GoldfishTTYState *s = GOLDFISH_TTY(dev);

    trace_goldfish_tty_unrealize(s);

    fifo8_destroy(&s->rx_fifo);
}

static const VMStateDescription vmstate_goldfish_tty = {
    .name = "goldfish_tty",
    .version_id = 1,
    .minimum_version_id = 1,
    .fields = (const VMStateField[]) {
        VMSTATE_UINT32(data_len, GoldfishTTYState),
        VMSTATE_UINT64(data_ptr, GoldfishTTYState),
        VMSTATE_BOOL(int_enabled, GoldfishTTYState),
        VMSTATE_FIFO8(rx_fifo, GoldfishTTYState),
        VMSTATE_END_OF_LIST()
    }
};

static Property goldfish_tty_properties[] = {
    DEFINE_PROP_CHR("chardev", GoldfishTTYState, chr),
    DEFINE_PROP_END_OF_LIST(),
};

static void goldfish_tty_instance_init(Object *obj)
{
    SysBusDevice *dev = SYS_BUS_DEVICE(obj);
    GoldfishTTYState *s = GOLDFISH_TTY(obj);

    trace_goldfish_tty_instance_init(s);

    sysbus_init_mmio(dev, &s->iomem);
    sysbus_init_irq(dev, &s->irq);
}

static void goldfish_tty_class_init(ObjectClass *oc, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(oc);

    device_class_set_props(dc, goldfish_tty_properties);
    device_class_set_legacy_reset(dc, goldfish_tty_reset);
    dc->realize = goldfish_tty_realize;
    dc->unrealize = goldfish_tty_unrealize;
    dc->vmsd = &vmstate_goldfish_tty;
    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
}

static const TypeInfo goldfish_tty_info = {
    .name = TYPE_GOLDFISH_TTY,
    .parent = TYPE_SYS_BUS_DEVICE,
    .class_init = goldfish_tty_class_init,
    .instance_init = goldfish_tty_instance_init,
    .instance_size = sizeof(GoldfishTTYState),
};

static void goldfish_tty_register_types(void)
{
    type_register_static(&goldfish_tty_info);
}

type_init(goldfish_tty_register_types)
