/*
 * libqos driver framework
 *
 * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <http://www.gnu.org/licenses/>
 */

 #include "qemu/osdep.h"
#include "libqtest.h"
#include "libqos/qgraph.h"
#include "pci-spapr.h"
#include "libqos/malloc-spapr.h"

typedef struct QSPAPR_pci_host QSPAPR_pci_host;
typedef struct Qppc64_pseriesMachine Qppc64_pseriesMachine;

struct QSPAPR_pci_host {
    QOSGraphObject obj;
    QPCIBusSPAPR pci;
};

struct Qppc64_pseriesMachine {
    QOSGraphObject obj;
    QGuestAllocator alloc;
    QSPAPR_pci_host bridge;
};

/* QSPAPR_pci_host */

static QOSGraphObject *QSPAPR_host_get_device(void *obj, const char *device)
{
    QSPAPR_pci_host *host = obj;
    if (!g_strcmp0(device, "pci-bus-spapr")) {
        return &host->pci.obj;
    }
    fprintf(stderr, "%s not present in QSPAPR_pci_host\n", device);
    g_assert_not_reached();
}

static void qos_create_QSPAPR_host(QSPAPR_pci_host *host,
                                   QTestState *qts,
                                   QGuestAllocator *alloc)
{
    host->obj.get_device = QSPAPR_host_get_device;
    qpci_init_spapr(&host->pci, qts, alloc);
}

/* ppc64/pseries machine */

static void spapr_destructor(QOSGraphObject *obj)
{
    Qppc64_pseriesMachine *machine = (Qppc64_pseriesMachine *) obj;
    alloc_destroy(&machine->alloc);
}

static void *spapr_get_driver(void *object, const char *interface)
{
    Qppc64_pseriesMachine *machine = object;
    if (!g_strcmp0(interface, "memory")) {
        return &machine->alloc;
    }

    fprintf(stderr, "%s not present in ppc64/pseries\n", interface);
    g_assert_not_reached();
}

static QOSGraphObject *spapr_get_device(void *obj, const char *device)
{
    Qppc64_pseriesMachine *machine = obj;
    if (!g_strcmp0(device, "spapr-pci-host-bridge")) {
        return &machine->bridge.obj;
    }

    fprintf(stderr, "%s not present in ppc64/pseries\n", device);
    g_assert_not_reached();
}

static void *qos_create_machine_spapr(QTestState *qts)
{
    Qppc64_pseriesMachine *machine = g_new0(Qppc64_pseriesMachine, 1);
    machine->obj.get_device = spapr_get_device;
    machine->obj.get_driver = spapr_get_driver;
    machine->obj.destructor = spapr_destructor;
    spapr_alloc_init(&machine->alloc, qts, ALLOC_NO_FLAGS);

    qos_create_QSPAPR_host(&machine->bridge, qts, &machine->alloc);

    return &machine->obj;
}

static void spapr_machine_register_nodes(void)
{
    qos_node_create_machine("ppc64/pseries", qos_create_machine_spapr);
    qos_node_create_driver("spapr-pci-host-bridge", NULL);
    qos_node_contains("ppc64/pseries", "spapr-pci-host-bridge", NULL);
    qos_node_contains("spapr-pci-host-bridge", "pci-bus-spapr", NULL);
}

libqos_init(spapr_machine_register_nodes);

