/*
 * Copyright 2019, Data61
 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
 * ABN 41 687 119 230.
 *
 * This software may be distributed and modified according to the terms of
 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
 * See "LICENSE_BSD2.txt" for details.
 *
 * @TAG(DATA61_BSD)
 */

#include <utils/util.h>
#include <virtqueue.h>

void virtqueue_init_driver(virtqueue_driver_t *vq, unsigned queue_len, vq_vring_avail_t *avail_ring,
                           vq_vring_used_t *used_ring, vq_vring_desc_t *desc, void (*notify)(void),
                           void *cookie)
{
    if (!IS_POWER_OF_2(queue_len)) {
        ZF_LOGE("Invalid queue_len: %d, must be a power of 2.", queue_len);
    }
    vq->free_desc_head = 0;
    vq->queue_len = queue_len;
    vq->u_ring_last_seen = vq->queue_len - 1;
    vq->avail_ring = avail_ring;
    vq->used_ring = used_ring;
    vq->desc_table = desc;
    vq->notify = notify;
    vq->cookie = cookie;
    virtqueue_init_desc_table(desc, vq->queue_len);
    virtqueue_init_avail_ring(avail_ring);
    virtqueue_init_used_ring(used_ring);

}

void virtqueue_init_device(virtqueue_device_t *vq, unsigned queue_len, vq_vring_avail_t *avail_ring,
                           vq_vring_used_t *used_ring, vq_vring_desc_t *desc, void (*notify)(void),
                           void *cookie)
{
    if (!IS_POWER_OF_2(queue_len)) {
        ZF_LOGE("Invalid queue_len: %d, must be a power of 2.", queue_len);
    }
    vq->queue_len = queue_len;
    vq->a_ring_last_seen = vq->queue_len - 1;
    vq->avail_ring = avail_ring;
    vq->used_ring = used_ring;
    vq->desc_table = desc;
    vq->notify = notify;
    vq->cookie = cookie;
}

void virtqueue_init_desc_table(vq_vring_desc_t *table, unsigned queue_len)
{
    unsigned i;
    for (i = 0; i < queue_len; i++) {
        table[i].addr = 0;
        table[i].len = 0;
        table[i].flags = 0;
        table[i].next = i + 1;
    }
}

void virtqueue_init_avail_ring(vq_vring_avail_t *ring)
{
    ring->flags = 0;
    ring->idx = 0;
}

void virtqueue_init_used_ring(vq_vring_used_t *ring)
{
    ring->flags = 0;
    ring->idx = 0;
}

static unsigned vq_add_desc(virtqueue_driver_t *vq, void *buf, unsigned len,
                            vq_flags_t flag, int prev)
{
    unsigned new;
    vq_vring_desc_t *desc;

    new = vq->free_desc_head;
    if (new == vq->queue_len) {
        return new;
    }
    vq->free_desc_head = vq->desc_table[new].next;
    desc = vq->desc_table + new;

    // casting pointers to integers directly is not allowed, must cast the
    // pointer to a uintptr_t first
    desc->addr = (uintptr_t)buf;

    desc->len = len;
    desc->flags = flag;
    desc->next = vq->queue_len;

    if (prev < vq->queue_len) {
        desc = vq->desc_table + prev;
        desc->next = new;
    }
    return new;
}

static unsigned vq_pop_desc(virtqueue_driver_t *vq, unsigned idx,
                            void **buf, unsigned *len, vq_flags_t *flag)
{
    unsigned next = vq->desc_table[idx].next;

    // casting integers to pointers directly is not allowed, must cast the
    // integer to a uintptr_t first
    *buf = (void *)(uintptr_t)(vq->desc_table[idx].addr);

    *len = vq->desc_table[idx].len;
    *flag = vq->desc_table[idx].flags;
    vq->desc_table[idx].next = vq->free_desc_head;
    vq->free_desc_head = idx;

    return next;
}

int virtqueue_add_available_buf(virtqueue_driver_t *vq, virtqueue_ring_object_t *obj,
                                void *buf, unsigned len, vq_flags_t flag)
{
    unsigned idx;

    /* If descriptor table full */
    if ((idx = vq_add_desc(vq, buf, len, flag, obj->cur)) == vq->queue_len) {
        return 0;
    }
    obj->cur = idx;

    /* If this is the first buffer in the descriptor chain */
    if (obj->first >= vq->queue_len) {
        obj->first = idx;
        vq->avail_ring->ring[vq->avail_ring->idx] = idx;
        vq->avail_ring->idx = (vq->avail_ring->idx + 1) & (vq->queue_len - 1);
    }
    return 1;
}

int virtqueue_get_used_buf(virtqueue_driver_t *vq, virtqueue_ring_object_t *obj, uint32_t *len)
{
    unsigned next = (vq->u_ring_last_seen + 1) & (vq->queue_len - 1);

    if (next == vq->used_ring->idx) {
        return 0;
    }
    obj->first = vq->used_ring->ring[next].id;
    *len = vq->used_ring->ring[next].len;
    obj->cur = obj->first;
    vq->u_ring_last_seen = next;
    return 1;
}

int virtqueue_add_used_buf(virtqueue_device_t *vq, virtqueue_ring_object_t *robj, uint32_t len)
{
    unsigned cur = vq->used_ring->idx;

    vq->used_ring->ring[cur].id = robj->first;
    vq->used_ring->ring[cur].len = len;
    vq->used_ring->idx = (cur + 1) & (vq->queue_len - 1);
    return 1;
}

int virtqueue_get_available_buf(virtqueue_device_t *vq, virtqueue_ring_object_t *robj)
{
    unsigned next = (vq->a_ring_last_seen + 1) & (vq->queue_len - 1);

    if (next == vq->avail_ring->idx) {
        return 0;
    }
    robj->first = vq->avail_ring->ring[next];
    robj->cur = robj->first;
    vq->a_ring_last_seen = next;
    return 1;
}

void virtqueue_init_ring_object(virtqueue_ring_object_t *obj)
{
    obj->cur = (uint32_t) -1;
    obj->first = (uint32_t) -1;
}

uint32_t virtqueue_scattered_available_size(virtqueue_device_t *vq, virtqueue_ring_object_t *robj)
{
    uint32_t ret = 0;
    unsigned cur = robj->first;

    while (cur < vq->queue_len) {
        ret += vq->desc_table[cur].len;
        cur = vq->desc_table[cur].next;
    }
    return ret;
}

int virtqueue_gather_available(virtqueue_device_t *vq, virtqueue_ring_object_t *robj,
                               void **buf, unsigned *len, vq_flags_t *flag)
{
    unsigned idx = robj->cur;

    if (idx >= vq->queue_len) {
        return 0;
    }

    // casting integers to pointers directly is not allowed, must cast the
    // integer to a uintptr_t first
    *buf = (void *)(uintptr_t)(vq->desc_table[idx].addr);

    *len = vq->desc_table[idx].len;
    *flag = vq->desc_table[idx].flags;
    robj->cur = vq->desc_table[idx].next;
    return 1;
}

int virtqueue_gather_used(virtqueue_driver_t *vq, virtqueue_ring_object_t *robj,
                          void **buf, unsigned *len, vq_flags_t *flag)
{
    if (robj->cur >= vq->queue_len) {
        return 0;
    }
    robj->cur = vq_pop_desc(vq, robj->cur, buf, len, flag);
    return 1;
}
