/*
 * QEMU rocker switch emulation - front-panel ports
 *
 * Copyright (c) 2014 Scott Feldman <sfeldma@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 */

#include "qemu/osdep.h"
#include "qapi/qapi-types-rocker.h"
#include "rocker.h"
#include "rocker_hw.h"
#include "rocker_fp.h"
#include "rocker_world.h"

enum duplex {
    DUPLEX_HALF = 0,
    DUPLEX_FULL
};

struct fp_port {
    Rocker *r;
    World *world;
    unsigned int index;
    char *name;
    uint32_t pport;
    bool enabled;
    uint32_t speed;
    uint8_t duplex;
    uint8_t autoneg;
    uint8_t learning;
    NICState *nic;
    NICConf conf;
};

char *fp_port_get_name(FpPort *port)
{
    return port->name;
}

bool fp_port_get_link_up(FpPort *port)
{
    return !qemu_get_queue(port->nic)->link_down;
}

RockerPort *fp_port_get_info(FpPort *port)
{
    RockerPort *value = g_malloc0(sizeof(*value));

    value->name = g_strdup(port->name);
    value->enabled = port->enabled;
    value->link_up = fp_port_get_link_up(port);
    value->speed = port->speed;
    value->duplex = port->duplex;
    value->autoneg = port->autoneg;
    return value;
}

void fp_port_get_macaddr(FpPort *port, MACAddr *macaddr)
{
    memcpy(macaddr->a, port->conf.macaddr.a, sizeof(macaddr->a));
}

void fp_port_set_macaddr(FpPort *port, MACAddr *macaddr)
{
/* XXX TODO implement and test setting mac addr
 * XXX memcpy(port->conf.macaddr.a, macaddr.a, sizeof(port->conf.macaddr.a));
 */
}

uint8_t fp_port_get_learning(FpPort *port)
{
    return port->learning;
}

void fp_port_set_learning(FpPort *port, uint8_t learning)
{
    port->learning = learning;
}

int fp_port_get_settings(FpPort *port, uint32_t *speed,
                         uint8_t *duplex, uint8_t *autoneg)
{
    *speed = port->speed;
    *duplex = port->duplex;
    *autoneg = port->autoneg;

    return ROCKER_OK;
}

int fp_port_set_settings(FpPort *port, uint32_t speed,
                         uint8_t duplex, uint8_t autoneg)
{
    /* XXX validate inputs */

    port->speed = speed;
    port->duplex = duplex;
    port->autoneg = autoneg;

    return ROCKER_OK;
}

bool fp_port_from_pport(uint32_t pport, uint32_t *port)
{
    if (pport < 1 || pport > ROCKER_FP_PORTS_MAX) {
        return false;
    }
    *port = pport - 1;
    return true;
}

int fp_port_eg(FpPort *port, const struct iovec *iov, int iovcnt)
{
    NetClientState *nc = qemu_get_queue(port->nic);

    if (port->enabled) {
        qemu_sendv_packet(nc, iov, iovcnt);
    }

    return ROCKER_OK;
}

static ssize_t fp_port_receive_iov(NetClientState *nc, const struct iovec *iov,
                                   int iovcnt)
{
    FpPort *port = qemu_get_nic_opaque(nc);

    /* If the port is disabled, we want to drop this pkt
     * now rather than queing it for later.  We don't want
     * any stale pkts getting into the device when the port
     * transitions to enabled.
     */

    if (!port->enabled) {
        return -1;
    }

    return world_ingress(port->world, port->pport, iov, iovcnt);
}

static ssize_t fp_port_receive(NetClientState *nc, const uint8_t *buf,
                               size_t size)
{
    const struct iovec iov = {
        .iov_base = (uint8_t *)buf,
        .iov_len = size
    };

    return fp_port_receive_iov(nc, &iov, 1);
}

static void fp_port_cleanup(NetClientState *nc)
{
}

static void fp_port_set_link_status(NetClientState *nc)
{
    FpPort *port = qemu_get_nic_opaque(nc);

    rocker_event_link_changed(port->r, port->pport, !nc->link_down);
}

static NetClientInfo fp_port_info = {
    .type = NET_CLIENT_DRIVER_NIC,
    .size = sizeof(NICState),
    .receive = fp_port_receive,
    .receive_iov = fp_port_receive_iov,
    .cleanup = fp_port_cleanup,
    .link_status_changed = fp_port_set_link_status,
};

World *fp_port_get_world(FpPort *port)
{
    return port->world;
}

void fp_port_set_world(FpPort *port, World *world)
{
    DPRINTF("port %d setting world \"%s\"\n", port->index, world_name(world));
    port->world = world;
}

bool fp_port_check_world(FpPort *port, World *world)
{
    return port->world == world;
}

bool fp_port_enabled(FpPort *port)
{
    return port->enabled;
}

static void fp_port_set_link(FpPort *port, bool up)
{
    NetClientState *nc = qemu_get_queue(port->nic);

    if (up == nc->link_down) {
        nc->link_down = !up;
        nc->info->link_status_changed(nc);
    }
}

void fp_port_enable(FpPort *port)
{
    fp_port_set_link(port, true);
    port->enabled = true;
    DPRINTF("port %d enabled\n", port->index);
}

void fp_port_disable(FpPort *port)
{
    port->enabled = false;
    fp_port_set_link(port, false);
    DPRINTF("port %d disabled\n", port->index);
}

FpPort *fp_port_alloc(Rocker *r, char *sw_name,
                      MACAddr *start_mac, unsigned int index,
                      NICPeers *peers)
{
    FpPort *port = g_new0(FpPort, 1);

    port->r = r;
    port->index = index;
    port->pport = index + 1;

    /* front-panel switch port names are 1-based */

    port->name = g_strdup_printf("%sp%d", sw_name, port->pport);

    memcpy(port->conf.macaddr.a, start_mac, sizeof(port->conf.macaddr.a));
    port->conf.macaddr.a[5] += index;
    port->conf.bootindex = -1;
    port->conf.peers = *peers;

    port->nic = qemu_new_nic(&fp_port_info, &port->conf,
                             sw_name, NULL, port);
    qemu_format_nic_info_str(qemu_get_queue(port->nic),
                             port->conf.macaddr.a);

    fp_port_reset(port);

    return port;
}

void fp_port_free(FpPort *port)
{
    qemu_del_nic(port->nic);
    g_free(port->name);
    g_free(port);
}

void fp_port_reset(FpPort *port)
{
    fp_port_disable(port);
    port->speed = 10000;   /* 10Gbps */
    port->duplex = DUPLEX_FULL;
    port->autoneg = 0;
}
