/*
 * IPMI KCS test cases, using the local interface.
 *
 * Copyright (c) 2012 Corey Minyard <cminyard@mvista.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "qemu/osdep.h"

#include "libqtest-single.h"

#define IPMI_IRQ        5

#define IPMI_KCS_BASE   0xca2

#define IPMI_KCS_STATUS_ABORT           0x60
#define IPMI_KCS_CMD_WRITE_START        0x61
#define IPMI_KCS_CMD_WRITE_END          0x62
#define IPMI_KCS_CMD_READ               0x68

#define IPMI_KCS_ABORTED_BY_CMD         0x01

#define IPMI_KCS_CMDREG_GET_STATE() ((kcs_get_cmdreg() >> 6) & 3)
#define IPMI_KCS_STATE_IDLE     0
#define IPMI_KCS_STATE_READ     1
#define IPMI_KCS_STATE_WRITE    2
#define IPMI_KCS_STATE_ERROR    3
#define IPMI_KCS_CMDREG_GET_CD()    ((kcs_get_cmdreg() >> 3) & 1)
#define IPMI_KCS_CMDREG_GET_ATN()   ((kcs_get_cmdreg() >> 2) & 1)
#define IPMI_KCS_CMDREG_GET_IBF()   ((kcs_get_cmdreg() >> 1) & 1)
#define IPMI_KCS_CMDREG_GET_OBF()   ((kcs_get_cmdreg() >> 0) & 1)

static int kcs_ints_enabled;

static uint8_t kcs_get_cmdreg(void)
{
    return inb(IPMI_KCS_BASE + 1);
}

static void kcs_write_cmdreg(uint8_t val)
{
    outb(IPMI_KCS_BASE + 1, val);
}

static uint8_t kcs_get_datareg(void)
{
    return inb(IPMI_KCS_BASE);
}

static void kcs_write_datareg(uint8_t val)
{
    outb(IPMI_KCS_BASE, val);
}

static void kcs_wait_ibf(void)
{
    unsigned int count = 1000;
    while (IPMI_KCS_CMDREG_GET_IBF() != 0) {
        --count;
        g_assert(count != 0);
    }
}

static void kcs_wait_obf(void)
{
    unsigned int count = 1000;
    while (IPMI_KCS_CMDREG_GET_OBF() == 0) {
        --count;
        g_assert(count != 0);
    }
}

static void kcs_clear_obf(void)
{
    if (kcs_ints_enabled) {
        g_assert(get_irq(IPMI_IRQ));
    } else {
        g_assert(!get_irq(IPMI_IRQ));
    }
    g_assert(IPMI_KCS_CMDREG_GET_OBF() == 1);
    kcs_get_datareg();
    g_assert(IPMI_KCS_CMDREG_GET_OBF() == 0);
    g_assert(!get_irq(IPMI_IRQ));
}

static void kcs_check_state(uint8_t state)
{
    g_assert(IPMI_KCS_CMDREG_GET_STATE() == state);
}

static void kcs_cmd(uint8_t *cmd, unsigned int cmd_len,
                    uint8_t *rsp, unsigned int *rsp_len)
{
    unsigned int i, j = 0;

    /* Should be idle */
    g_assert(kcs_get_cmdreg() == 0);

    kcs_write_cmdreg(IPMI_KCS_CMD_WRITE_START);
    kcs_wait_ibf();
    kcs_check_state(IPMI_KCS_STATE_WRITE);
    kcs_clear_obf();
    for (i = 0; i < cmd_len; i++) {
        kcs_write_datareg(cmd[i]);
        kcs_wait_ibf();
        kcs_check_state(IPMI_KCS_STATE_WRITE);
        kcs_clear_obf();
    }
    kcs_write_cmdreg(IPMI_KCS_CMD_WRITE_END);
    kcs_wait_ibf();
    kcs_check_state(IPMI_KCS_STATE_WRITE);
    kcs_clear_obf();
    kcs_write_datareg(0);
 next_read_byte:
    kcs_wait_ibf();
    switch (IPMI_KCS_CMDREG_GET_STATE()) {
    case IPMI_KCS_STATE_READ:
        kcs_wait_obf();
        g_assert(j < *rsp_len);
        rsp[j++] = kcs_get_datareg();
        kcs_write_datareg(IPMI_KCS_CMD_READ);
        goto next_read_byte;
        break;

    case IPMI_KCS_STATE_IDLE:
        kcs_wait_obf();
        kcs_get_datareg();
        break;

    default:
        g_assert_not_reached();
    }
    *rsp_len = j;
}

static void kcs_abort(uint8_t *cmd, unsigned int cmd_len,
                      uint8_t *rsp, unsigned int *rsp_len)
{
    unsigned int i, j = 0;
    unsigned int retries = 4;

    /* Should be idle */
    g_assert(kcs_get_cmdreg() == 0);

    kcs_write_cmdreg(IPMI_KCS_CMD_WRITE_START);
    kcs_wait_ibf();
    kcs_check_state(IPMI_KCS_STATE_WRITE);
    kcs_clear_obf();
    for (i = 0; i < cmd_len; i++) {
        kcs_write_datareg(cmd[i]);
        kcs_wait_ibf();
        kcs_check_state(IPMI_KCS_STATE_WRITE);
        kcs_clear_obf();
    }
    kcs_write_cmdreg(IPMI_KCS_CMD_WRITE_END);
    kcs_wait_ibf();
    kcs_check_state(IPMI_KCS_STATE_WRITE);
    kcs_clear_obf();
    kcs_write_datareg(0);
    kcs_wait_ibf();
    switch (IPMI_KCS_CMDREG_GET_STATE()) {
    case IPMI_KCS_STATE_READ:
        kcs_wait_obf();
        g_assert(j < *rsp_len);
        rsp[j++] = kcs_get_datareg();
        kcs_write_datareg(IPMI_KCS_CMD_READ);
        break;

    default:
        g_assert_not_reached();
    }

    /* Start the abort here */
 retry_abort:
    g_assert(retries > 0);

    kcs_wait_ibf();
    kcs_write_cmdreg(IPMI_KCS_STATUS_ABORT);
    kcs_wait_ibf();
    kcs_clear_obf();
    kcs_write_datareg(0);
    kcs_wait_ibf();
    if (IPMI_KCS_CMDREG_GET_STATE() != IPMI_KCS_STATE_READ) {
        retries--;
        goto retry_abort;
    }
    kcs_wait_obf();
    rsp[0] = kcs_get_datareg();
    kcs_write_datareg(IPMI_KCS_CMD_READ);
    kcs_wait_ibf();
    if (IPMI_KCS_CMDREG_GET_STATE() != IPMI_KCS_STATE_IDLE) {
        retries--;
        goto retry_abort;
    }
    kcs_wait_obf();
    kcs_clear_obf();

    *rsp_len = j;
}


static uint8_t get_dev_id_cmd[] = { 0x18, 0x01 };
static uint8_t get_dev_id_rsp[] = { 0x1c, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00,
                                    0x02, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00 };

/*
 * Send a get_device_id to do a basic test.
 */
static void test_kcs_base(void)
{
    uint8_t rsp[20];
    unsigned int rsplen = sizeof(rsp);

    kcs_cmd(get_dev_id_cmd, sizeof(get_dev_id_cmd), rsp, &rsplen);
    g_assert(rsplen == sizeof(get_dev_id_rsp));
    g_assert(memcmp(get_dev_id_rsp, rsp, rsplen) == 0);
}

/*
 * Abort a kcs operation while reading
 */
static void test_kcs_abort(void)
{
    uint8_t rsp[20];
    unsigned int rsplen = sizeof(rsp);

    kcs_abort(get_dev_id_cmd, sizeof(get_dev_id_cmd), rsp, &rsplen);
    g_assert(rsp[0] == IPMI_KCS_ABORTED_BY_CMD);
}

static uint8_t set_bmc_globals_cmd[] = { 0x18, 0x2e, 0x0f };
static uint8_t set_bmc_globals_rsp[] = { 0x1c, 0x2e, 0x00 };

/*
 * Enable interrupts
 */
static void test_enable_irq(void)
{
    uint8_t rsp[20];
    unsigned int rsplen = sizeof(rsp);

    kcs_cmd(set_bmc_globals_cmd, sizeof(set_bmc_globals_cmd), rsp, &rsplen);
    g_assert(rsplen == sizeof(set_bmc_globals_rsp));
    g_assert(memcmp(set_bmc_globals_rsp, rsp, rsplen) == 0);
    kcs_ints_enabled = 1;
}

int main(int argc, char **argv)
{
    char *cmdline;
    int ret;

    /* Run the tests */
    g_test_init(&argc, &argv, NULL);

    cmdline = g_strdup_printf("-device ipmi-bmc-sim,id=bmc0"
                              " -device isa-ipmi-kcs,bmc=bmc0");
    qtest_start(cmdline);
    g_free(cmdline);
    qtest_irq_intercept_in(global_qtest, "ioapic");
    qtest_add_func("/ipmi/local/kcs_base", test_kcs_base);
    qtest_add_func("/ipmi/local/kcs_abort", test_kcs_abort);
    qtest_add_func("/ipmi/local/kcs_enable_irq", test_enable_irq);
    qtest_add_func("/ipmi/local/kcs_base_irq", test_kcs_base);
    qtest_add_func("/ipmi/local/kcs_abort_irq", test_kcs_abort);
    ret = g_test_run();
    qtest_quit(global_qtest);

    return ret;
}
