/*
 * QTest testcase for USB EHCI
 *
 * Copyright (c) 2014 SUSE LINUX Products GmbH
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 */

#include "qemu/osdep.h"
#include "libqtest.h"
#include "libqos/pci-pc.h"
#include "hw/usb/uhci-regs.h"
#include "hw/usb/ehci-regs.h"
#include "libqos/usb.h"

static QPCIBus *pcibus;
static struct qhc uhci1;
static struct qhc uhci2;
static struct qhc uhci3;
static struct qhc ehci1;

/* helpers */

#if 0
static void uhci_port_update(struct qhc *hc, int port,
                             uint16_t set, uint16_t clear)
{
    void *addr = hc->base + 0x10 + 2 * port;
    uint16_t value;

    value = qpci_io_readw(hc->dev, addr);
    value |= set;
    value &= ~clear;
    qpci_io_writew(hc->dev, addr, value);
}
#endif

static void ehci_port_test(struct qhc *hc, int port, uint32_t expect)
{
    uint32_t value = qpci_io_readl(hc->dev, hc->bar, 0x64 + 4 * port);
    uint16_t mask = ~(PORTSC_CSC | PORTSC_PEDC | PORTSC_OCC);

#if 0
    fprintf(stderr, "%s: %d, have 0x%08x, want 0x%08x\n",
            __func__, port, value & mask, expect & mask);
#endif
    g_assert((value & mask) == (expect & mask));
}

/* tests */

static void test_init(void)
{
    pcibus = qpci_init_pc(NULL);
    g_assert(pcibus != NULL);

    qusb_pci_init_one(pcibus, &uhci1, QPCI_DEVFN(0x1d, 0), 4);
    qusb_pci_init_one(pcibus, &uhci2, QPCI_DEVFN(0x1d, 1), 4);
    qusb_pci_init_one(pcibus, &uhci3, QPCI_DEVFN(0x1d, 2), 4);
    qusb_pci_init_one(pcibus, &ehci1, QPCI_DEVFN(0x1d, 7), 0);
}

static void test_deinit(void)
{
    uhci_deinit(&uhci1);
    uhci_deinit(&uhci2);
    uhci_deinit(&uhci3);
    uhci_deinit(&ehci1);
    qpci_free_pc(pcibus);
}

static void pci_uhci_port_1(void)
{
    g_assert(pcibus != NULL);

    uhci_port_test(&uhci1, 0, UHCI_PORT_CCS); /* usb-tablet  */
    uhci_port_test(&uhci1, 1, UHCI_PORT_CCS); /* usb-storage */
    uhci_port_test(&uhci2, 0, 0);
    uhci_port_test(&uhci2, 1, 0);
    uhci_port_test(&uhci3, 0, 0);
    uhci_port_test(&uhci3, 1, 0);
}

static void pci_ehci_port_1(void)
{
    int i;

    g_assert(pcibus != NULL);

    for (i = 0; i < 6; i++) {
        ehci_port_test(&ehci1, i, PORTSC_POWNER | PORTSC_PPOWER);
    }
}

static void pci_ehci_config(void)
{
    /* hands over all ports from companion uhci to ehci */
    qpci_io_writew(ehci1.dev, ehci1.bar, 0x60, 1);
}

static void pci_uhci_port_2(void)
{
    g_assert(pcibus != NULL);

    uhci_port_test(&uhci1, 0, 0); /* usb-tablet,  @ehci */
    uhci_port_test(&uhci1, 1, 0); /* usb-storage, @ehci */
    uhci_port_test(&uhci2, 0, 0);
    uhci_port_test(&uhci2, 1, 0);
    uhci_port_test(&uhci3, 0, 0);
    uhci_port_test(&uhci3, 1, 0);
}

static void pci_ehci_port_2(void)
{
    static uint32_t expect[] = {
        PORTSC_PPOWER | PORTSC_CONNECT, /* usb-tablet  */
        PORTSC_PPOWER | PORTSC_CONNECT, /* usb-storage */
        PORTSC_PPOWER,
        PORTSC_PPOWER,
        PORTSC_PPOWER,
        PORTSC_PPOWER,
    };
    int i;

    g_assert(pcibus != NULL);

    for (i = 0; i < 6; i++) {
        ehci_port_test(&ehci1, i, expect[i]);
    }
}

static void pci_ehci_port_3_hotplug(void)
{
    /* check for presence of hotplugged usb-tablet */
    g_assert(pcibus != NULL);
    ehci_port_test(&ehci1, 2, PORTSC_PPOWER | PORTSC_CONNECT);
}

static void pci_ehci_port_hotplug(void)
{
    usb_test_hotplug("ich9-ehci-1", 3, pci_ehci_port_3_hotplug);
}


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

    g_test_init(&argc, &argv, NULL);

    qtest_add_func("/ehci/pci/uhci-port-1", pci_uhci_port_1);
    qtest_add_func("/ehci/pci/ehci-port-1", pci_ehci_port_1);
    qtest_add_func("/ehci/pci/ehci-config", pci_ehci_config);
    qtest_add_func("/ehci/pci/uhci-port-2", pci_uhci_port_2);
    qtest_add_func("/ehci/pci/ehci-port-2", pci_ehci_port_2);
    qtest_add_func("/ehci/pci/ehci-port-3-hotplug", pci_ehci_port_hotplug);

    qtest_start("-machine q35 -device ich9-usb-ehci1,bus=pcie.0,addr=1d.7,"
                "multifunction=on,id=ich9-ehci-1 "
                "-device ich9-usb-uhci1,bus=pcie.0,addr=1d.0,"
                "multifunction=on,masterbus=ich9-ehci-1.0,firstport=0 "
                "-device ich9-usb-uhci2,bus=pcie.0,addr=1d.1,"
                "multifunction=on,masterbus=ich9-ehci-1.0,firstport=2 "
                "-device ich9-usb-uhci3,bus=pcie.0,addr=1d.2,"
                "multifunction=on,masterbus=ich9-ehci-1.0,firstport=4 "
                "-drive if=none,id=usbcdrom,media=cdrom "
                "-device usb-tablet,bus=ich9-ehci-1.0,port=1,usb_version=1 "
                "-device usb-storage,bus=ich9-ehci-1.0,port=2,drive=usbcdrom ");

    test_init();
    ret = g_test_run();
    test_deinit();

    qtest_end();

    return ret;
}
