/*
 * Xen para-virtualization device
 *
 *  (c) 2008 Gerd Hoffmann <kraxel@redhat.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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 "qemu/log.h"
#include "qemu/main-loop.h"
#include "hw/qdev-core.h"
#include "hw/xen/xen-legacy-backend.h"
#include "hw/xen/xen-bus-helper.h"
#include "hw/xen/xen_pvdev.h"

/* private */
static int debug;

struct xs_dirs {
    char *xs_dir;
    QTAILQ_ENTRY(xs_dirs) list;
};

static QTAILQ_HEAD(, xs_dirs) xs_cleanup =
    QTAILQ_HEAD_INITIALIZER(xs_cleanup);

static QTAILQ_HEAD(, XenLegacyDevice) xendevs =
    QTAILQ_HEAD_INITIALIZER(xendevs);

/* ------------------------------------------------------------- */

static void xenstore_cleanup_dir(char *dir)
{
    struct xs_dirs *d;

    d = g_malloc(sizeof(*d));
    d->xs_dir = dir;
    QTAILQ_INSERT_TAIL(&xs_cleanup, d, list);
}

void xen_config_cleanup(void)
{
    struct xs_dirs *d;

    QTAILQ_FOREACH(d, &xs_cleanup, list) {
        qemu_xen_xs_destroy(xenstore, 0, d->xs_dir);
    }
}

int xenstore_mkdir(char *path, int p)
{
    if (!qemu_xen_xs_create(xenstore, 0, 0, xen_domid, p, path)) {
        xen_pv_printf(NULL, 0, "xs_mkdir %s: failed\n", path);
        return -1;
    }
    xenstore_cleanup_dir(g_strdup(path));
    return 0;
}

int xenstore_write_str(const char *base, const char *node, const char *val)
{
    char abspath[XEN_BUFSIZE];

    snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
    if (!qemu_xen_xs_write(xenstore, 0, abspath, val, strlen(val))) {
        return -1;
    }
    return 0;
}

char *xenstore_read_str(const char *base, const char *node)
{
    char *str, *ret = NULL;

    str = xs_node_read(xenstore, 0, NULL, NULL, "%s/%s", base, node);
    if (str != NULL) {
        /* move to qemu-allocated memory to make sure
         * callers can safely g_free() stuff. */
        ret = g_strdup(str);
        free(str);
    }
    return ret;
}

int xenstore_write_int(const char *base, const char *node, int ival)
{
    char val[12];

    snprintf(val, sizeof(val), "%d", ival);
    return xenstore_write_str(base, node, val);
}

int xenstore_write_int64(const char *base, const char *node, int64_t ival)
{
    char val[21];

    snprintf(val, sizeof(val), "%"PRId64, ival);
    return xenstore_write_str(base, node, val);
}

int xenstore_read_int(const char *base, const char *node, int *ival)
{
    char *val;
    int rc = -1;

    val = xenstore_read_str(base, node);
    if (val && 1 == sscanf(val, "%d", ival)) {
        rc = 0;
    }
    g_free(val);
    return rc;
}

int xenstore_read_uint64(const char *base, const char *node, uint64_t *uval)
{
    char *val;
    int rc = -1;

    val = xenstore_read_str(base, node);
    if (val && 1 == sscanf(val, "%"SCNu64, uval)) {
        rc = 0;
    }
    g_free(val);
    return rc;
}

const char *xenbus_strstate(enum xenbus_state state)
{
    static const char *const name[] = {
        [XenbusStateUnknown]       = "Unknown",
        [XenbusStateInitialising]  = "Initialising",
        [XenbusStateInitWait]      = "InitWait",
        [XenbusStateInitialised]   = "Initialised",
        [XenbusStateConnected]     = "Connected",
        [XenbusStateClosing]       = "Closing",
        [XenbusStateClosed]        = "Closed",
    };
    return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID";
}

/*
 * msg_level:
 *  0 == errors (stderr + logfile).
 *  1 == informative debug messages (logfile only).
 *  2 == noisy debug messages (logfile only).
 *  3 == will flood your log (logfile only).
 */
G_GNUC_PRINTF(3, 0)
static void xen_pv_output_msg(struct XenLegacyDevice *xendev,
                              FILE *f, const char *fmt, va_list args)
{
    if (xendev) {
        fprintf(f, "xen be: %s: ", xendev->name);
    } else {
        fprintf(f, "xen be core: ");
    }
    vfprintf(f, fmt, args);
}

void xen_pv_printf(struct XenLegacyDevice *xendev, int msg_level,
                   const char *fmt, ...)
{
    FILE *logfile;
    va_list args;

    if (msg_level > (xendev ? xendev->debug : debug)) {
        return;
    }

    logfile = qemu_log_trylock();
    if (logfile) {
        va_start(args, fmt);
        xen_pv_output_msg(xendev, logfile, fmt, args);
        va_end(args);
        qemu_log_unlock(logfile);
    }

    if (msg_level == 0) {
        va_start(args, fmt);
        xen_pv_output_msg(xendev, stderr, fmt, args);
        va_end(args);
    }
}

void xen_pv_evtchn_event(void *opaque)
{
    struct XenLegacyDevice *xendev = opaque;
    evtchn_port_t port;

    port = qemu_xen_evtchn_pending(xendev->evtchndev);
    if (port != xendev->local_port) {
        xen_pv_printf(xendev, 0,
                      "xenevtchn_pending returned %d (expected %d)\n",
                      port, xendev->local_port);
        return;
    }
    qemu_xen_evtchn_unmask(xendev->evtchndev, port);

    if (xendev->ops->event) {
        xendev->ops->event(xendev);
    }
}

void xen_pv_unbind_evtchn(struct XenLegacyDevice *xendev)
{
    if (xendev->local_port == -1) {
        return;
    }
    qemu_set_fd_handler(qemu_xen_evtchn_fd(xendev->evtchndev), NULL, NULL, NULL);
    qemu_xen_evtchn_unbind(xendev->evtchndev, xendev->local_port);
    xen_pv_printf(xendev, 2, "unbind evtchn port %d\n", xendev->local_port);
    xendev->local_port = -1;
}

int xen_pv_send_notify(struct XenLegacyDevice *xendev)
{
    return qemu_xen_evtchn_notify(xendev->evtchndev, xendev->local_port);
}

/* ------------------------------------------------------------- */

struct XenLegacyDevice *xen_pv_find_xendev(const char *type, int dom, int dev)
{
    struct XenLegacyDevice *xendev;

    QTAILQ_FOREACH(xendev, &xendevs, next) {
        if (xendev->dom != dom) {
            continue;
        }
        if (xendev->dev != dev) {
            continue;
        }
        if (strcmp(xendev->type, type) != 0) {
            continue;
        }
        return xendev;
    }
    return NULL;
}

/*
 * release xen backend device.
 */
void xen_pv_del_xendev(struct XenLegacyDevice *xendev)
{
    if (xendev->ops->free) {
        xendev->ops->free(xendev);
    }

    if (xendev->fe) {
        qemu_xen_xs_unwatch(xenstore, xendev->watch);
        g_free(xendev->fe);
    }

    if (xendev->evtchndev != NULL) {
        qemu_xen_evtchn_close(xendev->evtchndev);
    }
    if (xendev->gnttabdev != NULL) {
        qemu_xen_gnttab_close(xendev->gnttabdev);
    }

    QTAILQ_REMOVE(&xendevs, xendev, next);

    qdev_unplug(DEVICE(xendev), NULL);
}

void xen_pv_insert_xendev(struct XenLegacyDevice *xendev)
{
    QTAILQ_INSERT_TAIL(&xendevs, xendev, next);
}
