/*
 * CXL Utility library for devices
 *
 * Copyright(C) 2020 Intel Corporation.
 *
 * This work is licensed under the terms of the GNU GPL, version 2. See the
 * COPYING file in the top-level directory.
 */

#include "qemu/osdep.h"
#include "qemu/log.h"
#include "hw/cxl/cxl.h"

/*
 * Device registers have no restrictions per the spec, and so fall back to the
 * default memory mapped register rules in 8.2:
 *   Software shall use CXL.io Memory Read and Write to access memory mapped
 *   register defined in this section. Unless otherwise specified, software
 *   shall restrict the accesses width based on the following:
 *   • A 32 bit register shall be accessed as a 1 Byte, 2 Bytes or 4 Bytes
 *     quantity.
 *   • A 64 bit register shall be accessed as a 1 Byte, 2 Bytes, 4 Bytes or 8
 *     Bytes
 *   • The address shall be a multiple of the access width, e.g. when
 *     accessing a register as a 4 Byte quantity, the address shall be
 *     multiple of 4.
 *   • The accesses shall map to contiguous bytes.If these rules are not
 *     followed, the behavior is undefined
 */

static uint64_t caps_reg_read(void *opaque, hwaddr offset, unsigned size)
{
    CXLDeviceState *cxl_dstate = opaque;

    switch (size) {
    case 4:
        return cxl_dstate->caps_reg_state32[offset / size];
    case 8:
        return cxl_dstate->caps_reg_state64[offset / size];
    default:
        g_assert_not_reached();
    }
}

static uint64_t dev_reg_read(void *opaque, hwaddr offset, unsigned size)
{
    CXLDeviceState *cxl_dstate = opaque;

    switch (size) {
    case 1:
        return cxl_dstate->dev_reg_state[offset];
    case 2:
        return cxl_dstate->dev_reg_state16[offset / size];
    case 4:
        return cxl_dstate->dev_reg_state32[offset / size];
    case 8:
        return cxl_dstate->dev_reg_state64[offset / size];
    default:
        g_assert_not_reached();
    }
}

static uint64_t mailbox_reg_read(void *opaque, hwaddr offset, unsigned size)
{
    CXLDeviceState *cxl_dstate;
    CXLCCI *cci = opaque;

    if (object_dynamic_cast(OBJECT(cci->intf), TYPE_CXL_TYPE3)) {
        cxl_dstate = &CXL_TYPE3(cci->intf)->cxl_dstate;
    } else if (object_dynamic_cast(OBJECT(cci->intf),
                                   TYPE_CXL_SWITCH_MAILBOX_CCI)) {
        cxl_dstate = &CXL_SWITCH_MAILBOX_CCI(cci->intf)->cxl_dstate;
    } else {
        return 0;
    }

    switch (size) {
    case 1:
        return cxl_dstate->mbox_reg_state[offset];
    case 2:
        return cxl_dstate->mbox_reg_state16[offset / size];
    case 4:
        return cxl_dstate->mbox_reg_state32[offset / size];
    case 8:
        if (offset == A_CXL_DEV_BG_CMD_STS) {
            uint64_t bg_status_reg;
            bg_status_reg = FIELD_DP64(0, CXL_DEV_BG_CMD_STS, OP,
                                       cci->bg.opcode);
            bg_status_reg = FIELD_DP64(bg_status_reg, CXL_DEV_BG_CMD_STS,
                                       PERCENTAGE_COMP, cci->bg.complete_pct);
            bg_status_reg = FIELD_DP64(bg_status_reg, CXL_DEV_BG_CMD_STS,
                                       RET_CODE, cci->bg.ret_code);
            /* endian? */
            cxl_dstate->mbox_reg_state64[offset / size] = bg_status_reg;
        }
        if (offset == A_CXL_DEV_MAILBOX_STS) {
            uint64_t status_reg = cxl_dstate->mbox_reg_state64[offset / size];
            if (cci->bg.complete_pct) {
                status_reg = FIELD_DP64(status_reg, CXL_DEV_MAILBOX_STS, BG_OP,
                                        0);
                cxl_dstate->mbox_reg_state64[offset / size] = status_reg;
            }
        }
        return cxl_dstate->mbox_reg_state64[offset / size];
    default:
        g_assert_not_reached();
    }
}

static void mailbox_mem_writel(uint32_t *reg_state, hwaddr offset,
                               uint64_t value)
{
    switch (offset) {
    case A_CXL_DEV_MAILBOX_CTRL:
        /* fallthrough */
    case A_CXL_DEV_MAILBOX_CAP:
        /* RO register */
        break;
    default:
        qemu_log_mask(LOG_UNIMP,
                      "%s Unexpected 32-bit access to 0x%" PRIx64 " (WI)\n",
                      __func__, offset);
        return;
    }

    reg_state[offset / sizeof(*reg_state)] = value;
}

static void mailbox_mem_writeq(uint64_t *reg_state, hwaddr offset,
                               uint64_t value)
{
    switch (offset) {
    case A_CXL_DEV_MAILBOX_CMD:
        break;
    case A_CXL_DEV_BG_CMD_STS:
        break;
    case A_CXL_DEV_MAILBOX_STS:
        /* Read only register, will get updated by the state machine */
        return;
    default:
        qemu_log_mask(LOG_UNIMP,
                      "%s Unexpected 64-bit access to 0x%" PRIx64 " (WI)\n",
                      __func__, offset);
        return;
    }


    reg_state[offset / sizeof(*reg_state)] = value;
}

static void mailbox_reg_write(void *opaque, hwaddr offset, uint64_t value,
                              unsigned size)
{
    CXLDeviceState *cxl_dstate;
    CXLCCI *cci = opaque;

    if (object_dynamic_cast(OBJECT(cci->intf), TYPE_CXL_TYPE3)) {
        cxl_dstate = &CXL_TYPE3(cci->intf)->cxl_dstate;
    } else if (object_dynamic_cast(OBJECT(cci->intf),
                                   TYPE_CXL_SWITCH_MAILBOX_CCI)) {
        cxl_dstate = &CXL_SWITCH_MAILBOX_CCI(cci->intf)->cxl_dstate;
    } else {
        return;
    }

    if (offset >= A_CXL_DEV_CMD_PAYLOAD) {
        memcpy(cxl_dstate->mbox_reg_state + offset, &value, size);
        return;
    }

    switch (size) {
    case 4:
        mailbox_mem_writel(cxl_dstate->mbox_reg_state32, offset, value);
        break;
    case 8:
        mailbox_mem_writeq(cxl_dstate->mbox_reg_state64, offset, value);
        break;
    default:
        g_assert_not_reached();
    }

    if (ARRAY_FIELD_EX32(cxl_dstate->mbox_reg_state32, CXL_DEV_MAILBOX_CTRL,
                         DOORBELL)) {
        uint64_t command_reg =
            cxl_dstate->mbox_reg_state64[R_CXL_DEV_MAILBOX_CMD];
        uint8_t cmd_set = FIELD_EX64(command_reg, CXL_DEV_MAILBOX_CMD,
                                     COMMAND_SET);
        uint8_t cmd = FIELD_EX64(command_reg, CXL_DEV_MAILBOX_CMD, COMMAND);
        size_t len_in = FIELD_EX64(command_reg, CXL_DEV_MAILBOX_CMD, LENGTH);
        uint8_t *pl = cxl_dstate->mbox_reg_state + A_CXL_DEV_CMD_PAYLOAD;
        /*
         * Copy taken to avoid need for individual command handlers to care
         * about aliasing.
         */
        g_autofree uint8_t *pl_in_copy = NULL;
        size_t len_out = 0;
        uint64_t status_reg;
        bool bg_started = false;
        int rc;

        pl_in_copy = g_memdup2(pl, len_in);
        if (len_in == 0 || pl_in_copy) {
            /* Avoid stale data  - including from earlier cmds */
            memset(pl, 0, CXL_MAILBOX_MAX_PAYLOAD_SIZE);
            rc = cxl_process_cci_message(cci, cmd_set, cmd, len_in, pl_in_copy,
                                         &len_out, pl, &bg_started);
        } else {
            rc = CXL_MBOX_INTERNAL_ERROR;
        }

        /* Set bg and the return code */
        status_reg = FIELD_DP64(0, CXL_DEV_MAILBOX_STS, BG_OP,
                                bg_started ? 1 : 0);
        status_reg = FIELD_DP64(status_reg, CXL_DEV_MAILBOX_STS, ERRNO, rc);
        /* Set the return length */
        command_reg = FIELD_DP64(0, CXL_DEV_MAILBOX_CMD, COMMAND_SET, cmd_set);
        command_reg = FIELD_DP64(command_reg, CXL_DEV_MAILBOX_CMD,
                                 COMMAND, cmd);
        command_reg = FIELD_DP64(command_reg, CXL_DEV_MAILBOX_CMD,
                                 LENGTH, len_out);

        cxl_dstate->mbox_reg_state64[R_CXL_DEV_MAILBOX_CMD] = command_reg;
        cxl_dstate->mbox_reg_state64[R_CXL_DEV_MAILBOX_STS] = status_reg;
        /* Tell the host we're done */
        ARRAY_FIELD_DP32(cxl_dstate->mbox_reg_state32, CXL_DEV_MAILBOX_CTRL,
                         DOORBELL, 0);
    }
}

static uint64_t mdev_reg_read(void *opaque, hwaddr offset, unsigned size)
{
    uint64_t retval = 0;

    retval = FIELD_DP64(retval, CXL_MEM_DEV_STS, MEDIA_STATUS, 1);
    retval = FIELD_DP64(retval, CXL_MEM_DEV_STS, MBOX_READY, 1);

    return retval;
}

static void ro_reg_write(void *opaque, hwaddr offset, uint64_t value,
                           unsigned size)
{
    /* Many register sets are read only */
}

static const MemoryRegionOps mdev_ops = {
    .read = mdev_reg_read,
    .write = ro_reg_write,
    .endianness = DEVICE_LITTLE_ENDIAN,
    .valid = {
        .min_access_size = 1,
        .max_access_size = 8,
        .unaligned = false,
    },
    .impl = {
        .min_access_size = 8,
        .max_access_size = 8,
    },
};

static const MemoryRegionOps mailbox_ops = {
    .read = mailbox_reg_read,
    .write = mailbox_reg_write,
    .endianness = DEVICE_LITTLE_ENDIAN,
    .valid = {
        .min_access_size = 1,
        .max_access_size = 8,
        .unaligned = false,
    },
    .impl = {
        .min_access_size = 1,
        .max_access_size = 8,
    },
};

static const MemoryRegionOps dev_ops = {
    .read = dev_reg_read,
    .write = ro_reg_write,
    .endianness = DEVICE_LITTLE_ENDIAN,
    .valid = {
        .min_access_size = 1,
        .max_access_size = 8,
        .unaligned = false,
    },
    .impl = {
        .min_access_size = 1,
        .max_access_size = 8,
    },
};

static const MemoryRegionOps caps_ops = {
    .read = caps_reg_read,
    .write = ro_reg_write,
    .endianness = DEVICE_LITTLE_ENDIAN,
    .valid = {
        .min_access_size = 1,
        .max_access_size = 8,
        .unaligned = false,
    },
    .impl = {
        .min_access_size = 4,
        .max_access_size = 8,
    },
};

void cxl_device_register_block_init(Object *obj, CXLDeviceState *cxl_dstate,
                                    CXLCCI *cci)
{
    /* This will be a BAR, so needs to be rounded up to pow2 for PCI spec */
    memory_region_init(&cxl_dstate->device_registers, obj, "device-registers",
                       pow2ceil(CXL_MMIO_SIZE));

    memory_region_init_io(&cxl_dstate->caps, obj, &caps_ops, cxl_dstate,
                          "cap-array", CXL_CAPS_SIZE);
    memory_region_init_io(&cxl_dstate->device, obj, &dev_ops, cxl_dstate,
                          "device-status", CXL_DEVICE_STATUS_REGISTERS_LENGTH);
    memory_region_init_io(&cxl_dstate->mailbox, obj, &mailbox_ops, cci,
                          "mailbox", CXL_MAILBOX_REGISTERS_LENGTH);
    memory_region_init_io(&cxl_dstate->memory_device, obj, &mdev_ops,
                          cxl_dstate, "memory device caps",
                          CXL_MEMORY_DEVICE_REGISTERS_LENGTH);

    memory_region_add_subregion(&cxl_dstate->device_registers, 0,
                                &cxl_dstate->caps);
    memory_region_add_subregion(&cxl_dstate->device_registers,
                                CXL_DEVICE_STATUS_REGISTERS_OFFSET,
                                &cxl_dstate->device);
    memory_region_add_subregion(&cxl_dstate->device_registers,
                                CXL_MAILBOX_REGISTERS_OFFSET,
                                &cxl_dstate->mailbox);
    memory_region_add_subregion(&cxl_dstate->device_registers,
                                CXL_MEMORY_DEVICE_REGISTERS_OFFSET,
                                &cxl_dstate->memory_device);
}

void cxl_event_set_status(CXLDeviceState *cxl_dstate, CXLEventLogType log_type,
                          bool available)
{
    if (available) {
        cxl_dstate->event_status |= (1 << log_type);
    } else {
        cxl_dstate->event_status &= ~(1 << log_type);
    }

    ARRAY_FIELD_DP64(cxl_dstate->dev_reg_state64, CXL_DEV_EVENT_STATUS,
                     EVENT_STATUS, cxl_dstate->event_status);
}

static void device_reg_init_common(CXLDeviceState *cxl_dstate)
{
    CXLEventLogType log;

    for (log = 0; log < CXL_EVENT_TYPE_MAX; log++) {
        cxl_event_set_status(cxl_dstate, log, false);
    }
}

static void mailbox_reg_init_common(CXLDeviceState *cxl_dstate)
{
    const uint8_t msi_n = 9;

    /* 2048 payload size */
    ARRAY_FIELD_DP32(cxl_dstate->mbox_reg_state32, CXL_DEV_MAILBOX_CAP,
                     PAYLOAD_SIZE, CXL_MAILBOX_PAYLOAD_SHIFT);
    cxl_dstate->payload_size = CXL_MAILBOX_MAX_PAYLOAD_SIZE;
    /* irq support */
    ARRAY_FIELD_DP32(cxl_dstate->mbox_reg_state32, CXL_DEV_MAILBOX_CAP,
                     BG_INT_CAP, 1);
    ARRAY_FIELD_DP32(cxl_dstate->mbox_reg_state32, CXL_DEV_MAILBOX_CAP,
                     MSI_N, msi_n);
    cxl_dstate->mbox_msi_n = msi_n;
}

static void memdev_reg_init_common(CXLDeviceState *cxl_dstate) { }

void cxl_device_register_init_t3(CXLType3Dev *ct3d)
{
    CXLDeviceState *cxl_dstate = &ct3d->cxl_dstate;
    uint64_t *cap_h = cxl_dstate->caps_reg_state64;
    const int cap_count = 3;

    /* CXL Device Capabilities Array Register */
    ARRAY_FIELD_DP64(cap_h, CXL_DEV_CAP_ARRAY, CAP_ID, 0);
    ARRAY_FIELD_DP64(cap_h, CXL_DEV_CAP_ARRAY, CAP_VERSION, 1);
    ARRAY_FIELD_DP64(cap_h, CXL_DEV_CAP_ARRAY, CAP_COUNT, cap_count);

    cxl_device_cap_init(cxl_dstate, DEVICE_STATUS, 1, 2);
    device_reg_init_common(cxl_dstate);

    cxl_device_cap_init(cxl_dstate, MAILBOX, 2, 1);
    mailbox_reg_init_common(cxl_dstate);

    cxl_device_cap_init(cxl_dstate, MEMORY_DEVICE, 0x4000, 1);
    memdev_reg_init_common(cxl_dstate);

    cxl_initialize_mailbox_t3(&ct3d->cci, DEVICE(ct3d),
                              CXL_MAILBOX_MAX_PAYLOAD_SIZE);
}

void cxl_device_register_init_swcci(CSWMBCCIDev *sw)
{
    CXLDeviceState *cxl_dstate = &sw->cxl_dstate;
    uint64_t *cap_h = cxl_dstate->caps_reg_state64;
    const int cap_count = 3;

    /* CXL Device Capabilities Array Register */
    ARRAY_FIELD_DP64(cap_h, CXL_DEV_CAP_ARRAY, CAP_ID, 0);
    ARRAY_FIELD_DP64(cap_h, CXL_DEV_CAP_ARRAY, CAP_VERSION, 1);
    ARRAY_FIELD_DP64(cap_h, CXL_DEV_CAP_ARRAY, CAP_COUNT, cap_count);

    cxl_device_cap_init(cxl_dstate, DEVICE_STATUS, 1, 2);
    device_reg_init_common(cxl_dstate);

    cxl_device_cap_init(cxl_dstate, MAILBOX, 2, 1);
    mailbox_reg_init_common(cxl_dstate);

    cxl_device_cap_init(cxl_dstate, MEMORY_DEVICE, 0x4000, 1);
    memdev_reg_init_common(cxl_dstate);
}

uint64_t cxl_device_get_timestamp(CXLDeviceState *cxl_dstate)
{
    uint64_t time, delta;
    uint64_t final_time = 0;

    if (cxl_dstate->timestamp.set) {
        /* Find the delta from the last time the host set the time. */
        time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
        delta = time - cxl_dstate->timestamp.last_set;
        final_time = cxl_dstate->timestamp.host_set + delta;
    }

    return final_time;
}
