/*
 * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230)
 *
 * SPDX-License-Identifier: GPL-2.0-only
 */

#include <ethdrivers/virtio_pci.h>
#include <assert.h>
#include <ethdrivers/helpers.h>
#include <ethdrivers/virtio/virtio_config.h>
#include <ethdrivers/virtio/virtio_pci.h>
#include <ethdrivers/virtio/virtio_ring.h>
#include <ethdrivers/virtio/virtio_net.h>
#include <string.h>

/* Mask of features we will use */
#define FEATURES_REQUIRED (BIT(VIRTIO_NET_F_MAC))

#define BUF_SIZE 2048
#define DMA_ALIGN 16

#define RX_QUEUE 0
#define TX_QUEUE 1

typedef struct virtio_dev {
    void *mmio_base;
    uint16_t io_base;
    ps_io_port_ops_t ioops;
    /* R/T Descriptor Head represents the beginning of the block of
     * descriptors that are currently in use */
    unsigned int tdh;
    unsigned int rdh;
    /* R/T Descriptor Tail represents the next free slot to add
     * a descriptor */
    unsigned int tdt;
    unsigned int rdt;
    /* R/T Used Head represents the index in the used ring that
     * we last observed */
    uint16_t tuh;
    uint16_t ruh;
    /* descriptor rings */
    uintptr_t rx_ring_phys;
    struct vring rx_ring;
    unsigned int rx_size;
    unsigned int rx_remain;
    void **rx_cookies;
    uintptr_t tx_ring_phys;
    struct vring tx_ring;
    unsigned int tx_size;
    unsigned int tx_remain;
    void **tx_cookies;
    unsigned int *tx_lengths;
    /* preallocated header. Since we do not actually use any features
     * in the header we put the same one before every send/receive packet */
    uintptr_t virtio_net_hdr_phys;
} virtio_dev_t;

static uint8_t read_reg8(virtio_dev_t *dev, uint16_t port)
{
    uint32_t val;
    ps_io_port_in(&dev->ioops, dev->io_base + port, 1, &val);
    return (uint8_t)val;
}

static uint16_t read_reg16(virtio_dev_t *dev, uint16_t port)
{
    uint32_t val;
    ps_io_port_in(&dev->ioops, dev->io_base + port, 2, &val);
    return (uint16_t)val;
}

static uint32_t read_reg32(virtio_dev_t *dev, uint16_t port)
{
    uint32_t val;
    ps_io_port_in(&dev->ioops, dev->io_base + port, 4, &val);
    return val;
}

static void write_reg8(virtio_dev_t *dev, uint16_t port, uint8_t val)
{
    ps_io_port_out(&dev->ioops, dev->io_base + port, 1, val);
}

static void write_reg16(virtio_dev_t *dev, uint16_t port, uint16_t val)
{
    ps_io_port_out(&dev->ioops, dev->io_base + port, 2, val);
}

static void write_reg32(virtio_dev_t *dev, uint16_t port, uint32_t val)
{
    ps_io_port_out(&dev->ioops, dev->io_base + port, 4, val);
}

static void set_status(virtio_dev_t *dev, uint8_t status)
{
    write_reg8(dev, VIRTIO_PCI_STATUS, status);
}

static uint8_t get_status(virtio_dev_t *dev)
{
    return read_reg8(dev, VIRTIO_PCI_STATUS);
}

static void add_status(virtio_dev_t *dev, uint8_t status)
{
    write_reg8(dev, VIRTIO_PCI_STATUS, get_status(dev) | status);
}

static uint32_t get_features(virtio_dev_t *dev)
{
    return read_reg32(dev, VIRTIO_PCI_HOST_FEATURES);
}

static void set_features(virtio_dev_t *dev, uint32_t features)
{
    write_reg32(dev, VIRTIO_PCI_GUEST_FEATURES, features);
}

static void free_desc_ring(virtio_dev_t *dev, ps_dma_man_t *dma_man)
{
    if (dev->rx_ring.desc) {
        dma_unpin_free(dma_man, (void *)dev->rx_ring.desc, vring_size(dev->rx_size, VIRTIO_PCI_VRING_ALIGN));
        dev->rx_ring.desc = NULL;
    }
    if (dev->tx_ring.desc) {
        dma_unpin_free(dma_man, (void *)dev->tx_ring.desc, vring_size(dev->tx_size, VIRTIO_PCI_VRING_ALIGN));
        dev->tx_ring.desc = NULL;
    }
    if (dev->rx_cookies) {
        free(dev->rx_cookies);
        dev->rx_cookies = NULL;
    }
    if (dev->tx_cookies) {
        free(dev->tx_cookies);
        dev->tx_cookies = NULL;
    }
    if (dev->tx_lengths) {
        free(dev->tx_lengths);
        dev->tx_lengths = NULL;
    }
}

static int initialize_desc_ring(virtio_dev_t *dev, ps_dma_man_t *dma_man)
{
    dma_addr_t rx_ring = dma_alloc_pin(dma_man, vring_size(dev->rx_size, VIRTIO_PCI_VRING_ALIGN), 1,
                                       VIRTIO_PCI_VRING_ALIGN);
    if (!rx_ring.phys) {
        ZF_LOGE("Failed to allocate rx_ring");
        return -1;
    }
    memset(rx_ring.virt, 0, vring_size(dev->rx_size, VIRTIO_PCI_VRING_ALIGN));
    vring_init(&dev->rx_ring, dev->rx_size, rx_ring.virt, VIRTIO_PCI_VRING_ALIGN);
    dev->rx_ring_phys = rx_ring.phys;
    dma_addr_t tx_ring = dma_alloc_pin(dma_man, vring_size(dev->tx_size, VIRTIO_PCI_VRING_ALIGN), 1,
                                       VIRTIO_PCI_VRING_ALIGN);
    if (!tx_ring.phys) {
        ZF_LOGE("Failed to allocate tx_ring");
        free_desc_ring(dev, dma_man);
        return -1;
    }
    memset(tx_ring.virt, 0, vring_size(dev->tx_size, VIRTIO_PCI_VRING_ALIGN));
    vring_init(&dev->tx_ring, dev->tx_size, tx_ring.virt, VIRTIO_PCI_VRING_ALIGN);
    dev->tx_ring_phys = tx_ring.phys;
    dev->rx_cookies = malloc(sizeof(void *) * dev->rx_size);
    dev->tx_cookies = malloc(sizeof(void *) * dev->tx_size);
    dev->tx_lengths = malloc(sizeof(unsigned int) * dev->tx_size);
    if (!dev->rx_cookies || !dev->tx_cookies || !dev->tx_lengths) {
        ZF_LOGE("Failed to malloc");
        free_desc_ring(dev, dma_man);
        return -1;
    }
    /* Remaining needs to be 2 less than size as we cannot actually enqueue size many descriptors,
     * since then the head and tail pointers would be equal, indicating empty. */
    dev->rx_remain = dev->rx_size - 2;
    dev->tx_remain = dev->tx_size - 2;

    dev->tdh = dev->tdt = 0;
    dev->rdh = dev->rdt = 0;
    dev->tuh = dev->ruh = 0;

    return 0;
}

static int initialize(virtio_dev_t *dev, ps_dma_man_t *dma_man)
{
    int err;
    /* perform a reset */
    set_status(dev, 0);
    /* acknowledge to the host that we found it */
    add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE);
    /* read device features */
    uint32_t features;
    features = get_features(dev);
    if ((features & FEATURES_REQUIRED) != FEATURES_REQUIRED) {
        ZF_LOGE("Required features 0x%x, have 0x%x", (unsigned int)FEATURES_REQUIRED, features);
        return -1;
    }
    features &= FEATURES_REQUIRED;
    /* write the features we will use */
    set_features(dev, features);
    /* determine the queue size */
    write_reg16(dev, VIRTIO_PCI_QUEUE_SEL, RX_QUEUE);
    dev->rx_size = read_reg16(dev, VIRTIO_PCI_QUEUE_NUM);
    write_reg16(dev, VIRTIO_PCI_QUEUE_SEL, TX_QUEUE);
    dev->tx_size = read_reg16(dev, VIRTIO_PCI_QUEUE_NUM);
    /* create the rings */
    err = initialize_desc_ring(dev, dma_man);
    if (err) {
        return -1;
    }
    /* write the virtqueue locations */
    write_reg16(dev, VIRTIO_PCI_QUEUE_SEL, RX_QUEUE);
    write_reg32(dev, VIRTIO_PCI_QUEUE_PFN, ((uintptr_t)dev->rx_ring_phys) / 4096);
    write_reg16(dev, VIRTIO_PCI_QUEUE_SEL, TX_QUEUE);
    write_reg32(dev, VIRTIO_PCI_QUEUE_PFN, ((uintptr_t)dev->tx_ring_phys) / 4096);
    /* tell the driver everything is okay */
    add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
    return 0;
}

static void get_mac(virtio_dev_t *dev, uint8_t *mac)
{
    int i;
    for (i = 0; i < 6; i++) {
        mac[i] = read_reg8(dev, 0x14 + i);
    }
}

static void low_level_init(struct eth_driver *driver, uint8_t *mac, int *mtu)
{
    virtio_dev_t *dev = (virtio_dev_t *)driver->eth_data;
    get_mac(dev, mac);
    *mtu = 1500;
}

static void print_state(struct eth_driver *eth_driver)
{
}

static void complete_tx(struct eth_driver *driver)
{
    virtio_dev_t *dev = (virtio_dev_t *)driver->eth_data;
    while (dev->tuh != dev->tx_ring.used->idx) {
        uint16_t ring = dev->tuh % dev->tx_size;
        unsigned int UNUSED desc = dev->tx_ring.used->ring[ring].id;
        assert(desc == dev->tdh);
        void *cookie = dev->tx_cookies[dev->tdh];
        /* add 1 to the length we stored to account for the extra descriptor
         * we used for the virtio header */
        unsigned int used = dev->tx_lengths[dev->tdh] + 1;
        dev->tx_remain += used;
        dev->tdh = (dev->tdh + used) % dev->tx_size;
        dev->tuh++;
        /* give the buffer back */
        driver->i_cb.tx_complete(driver->cb_cookie, cookie);
    }
}

static void fill_rx_bufs(struct eth_driver *driver)
{
    virtio_dev_t *dev = (virtio_dev_t *)driver->eth_data;
    /* we need 2 free as we enqueue in pairs. One descriptor to hold the
     * virtio header, another one for the actual buffer */
    while (dev->rx_remain >= 2) {
        /* request a buffer */
        void *cookie;
        uintptr_t phys = driver->i_cb.allocate_rx_buf(driver->cb_cookie, BUF_SIZE, &cookie);
        if (!phys) {
            break;
        }
        unsigned int next_rdt = (dev->rdt + 1) % dev->rx_size;
        dev->rx_ring.desc[dev->rdt] = (struct vring_desc) {
            .addr = dev->virtio_net_hdr_phys,
            .len = sizeof(struct virtio_net_hdr),
            .flags = VRING_DESC_F_NEXT | VRING_DESC_F_WRITE,
            .next = next_rdt
        };
        dev->rx_cookies[dev->rdt] = cookie;
        dev->rx_ring.desc[next_rdt] = (struct vring_desc) {
            .addr = phys,
            .len = BUF_SIZE,
            .flags = VRING_DESC_F_WRITE,
            .next = 0
        };
        dev->rx_ring.avail->ring[dev->rx_ring.avail->idx % dev->rx_size] = dev->rdt;
        __atomic_thread_fence(__ATOMIC_RELEASE);
        dev->rx_ring.avail->idx++;
        __atomic_thread_fence(__ATOMIC_RELEASE);
        write_reg16(dev, VIRTIO_PCI_QUEUE_NOTIFY, RX_QUEUE);
        dev->rdt = (dev->rdt + 2) % dev->rx_size;
        dev->rx_remain -= 2;
    }
}

static void complete_rx(struct eth_driver *driver)
{
    virtio_dev_t *dev = (virtio_dev_t *)driver->eth_data;
    while (dev->ruh != dev->rx_ring.used->idx) {
        uint16_t ring = dev->ruh % dev->rx_size;
        unsigned int UNUSED desc = dev->rx_ring.used->ring[ring].id;
        assert(desc == dev->rdh);
        void *cookie = dev->rx_cookies[dev->rdh];
        /* subtract off length of the virtio header we received */
        unsigned int len = dev->rx_ring.used->ring[ring].len - sizeof(struct virtio_net_hdr);
        /* update rdh. remember we actually had two descriptors, one
         * is the header that we threw away, the other being the actual data */
        dev->rdh = (dev->rdh + 2) % dev->rx_size;
        dev->rx_remain += 2;
        dev->ruh++;
        /* Give the buffers back */
        driver->i_cb.rx_complete(driver->cb_cookie, 1, &cookie, &len);
    }
}

static int raw_tx(struct eth_driver *driver, unsigned int num, uintptr_t *phys, unsigned int *len, void *cookie)
{
    virtio_dev_t *dev = (virtio_dev_t *)driver->eth_data;
    /* we need to num + 1 free descriptors. The + 1 is for the virtio header */
    if (dev->tx_remain < num + 1) {
        complete_tx(driver);
        if (dev->tx_remain < num + 1) {
            return ETHIF_TX_FAILED;
        }
    }
    /* install the header */
    dev->tx_ring.desc[dev->tdt] = (struct vring_desc) {
        .addr = dev->virtio_net_hdr_phys,
        .len = sizeof(struct virtio_net_hdr),
        .flags = VRING_DESC_F_NEXT,
        .next = (dev->tdt + 1) % dev->tx_size
    };
    /* now all the buffers */
    unsigned int i;
    for (i = 0; i < num; i++) {
        unsigned int desc = (dev->tdt + i + 1) % dev->tx_size;
        unsigned int next_desc = (desc + 1) % dev->tx_size;
        dev->tx_ring.desc[desc] = (struct vring_desc) {
            .addr = phys[i],
            .len = len[i],
            .flags = (i + 1 == num ? 0 : VRING_DESC_F_NEXT),
            .next = next_desc
        };
    }
    dev->tx_ring.avail->ring[dev->tx_ring.avail->idx % dev->tx_size] = dev->tdt;
    dev->tx_cookies[dev->tdt] = cookie;
    dev->tx_lengths[dev->tdt] = num;
    /* ensure update to descriptors visible before updating the index */
    __atomic_thread_fence(__ATOMIC_SEQ_CST);
    dev->tdt = (dev->tdt + num + 1) % dev->tx_size;
    dev->tx_remain -= (num + 1);
    dev->tx_ring.avail->idx++;
    /* ensure index update visible before notifying */
    __atomic_thread_fence(__ATOMIC_SEQ_CST);
    write_reg16(dev, VIRTIO_PCI_QUEUE_NOTIFY, TX_QUEUE);
    return ETHIF_TX_ENQUEUED;
}

static void raw_poll(struct eth_driver *driver)
{
    complete_tx(driver);
    complete_rx(driver);
    fill_rx_bufs(driver);
}

static void handle_irq(struct eth_driver *driver, int irq)
{
    virtio_dev_t *dev = (virtio_dev_t *)driver->eth_data;
    /* read and throw away the ISR state. This will perform the ack */
    read_reg8(dev, VIRTIO_PCI_ISR);
    raw_poll(driver);
}
static struct raw_iface_funcs iface_fns = {
    .raw_handleIRQ = handle_irq,
    .print_state = print_state,
    .low_level_init = low_level_init,
    .raw_tx = raw_tx,
    .raw_poll = raw_poll
};

int ethif_virtio_pci_init(struct eth_driver *eth_driver, ps_io_ops_t io_ops, void *config)
{
    int err;
    ethif_virtio_pci_config_t *virtio_config = (ethif_virtio_pci_config_t *)config;
    virtio_dev_t *dev = (virtio_dev_t *)malloc(sizeof(*dev));
    if (!dev) {
        return -1;
    }

    dev->mmio_base = virtio_config->mmio_base;
    dev->io_base = virtio_config->io_base;
    dev->ioops = io_ops.io_port_ops;

    eth_driver->eth_data = dev;
    eth_driver->dma_alignment = 16;
    eth_driver->i_fn = iface_fns;

    err = initialize(dev, &io_ops.dma_manager);
    if (err) {
        goto error;
    }
    dma_addr_t packet = dma_alloc_pin(&io_ops.dma_manager, sizeof(struct virtio_net_hdr), 1, DMA_ALIGN);
    if (!packet.virt) {
        goto error;
    }
    memset(packet.virt, 0, sizeof(struct virtio_net_hdr));
    dev->virtio_net_hdr_phys = packet.phys;

    fill_rx_bufs(eth_driver);

    return 0;

error:
    set_status(dev, VIRTIO_CONFIG_S_FAILED);
    free_desc_ring(dev, &io_ops.dma_manager);
    free(dev);
    return -1;
}
