/* Virtio helper functions from linux/tools/lguest/lguest.c
 *
 * Copyright (C) 1991-2016, the Linux Kernel authors
 * Copyright (c) 2016 Google Inc.
 *
 * Author:
 *  Rusty Russell <rusty@rustcorp.com.au>
 *  Michael Taufen <mtaufen@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.
 *
 * The code from lguest.c has been modified for Akaros.
 *
 * Original linux/tools/lguest/lguest.c:
 *   https://github.com/torvalds/linux/blob/v4.5/tools/lguest/lguest.c
 *   most recent hash on the file as of v4.5 tag:
 *     e523caa601f4a7c2fa1ecd040db921baf7453798
 */

#include <stdlib.h>
#include <err.h>
#include <sys/eventfd.h>
#include <sys/uio.h>
#include <vmm/virtio.h>
#include <vmm/virtio_mmio.h>

void cons_receiveq_fn(void *_vq) // host -> guest
{
	struct virtio_vq *vq = _vq;
	uint32_t head;
	uint32_t olen, ilen;
	uint32_t i, j;
	int num_read;
	struct iovec *iov;
	struct virtio_mmio_dev *dev = vq->vqdev->transport_dev;

	if (!vq)
		errx(1,
			"\n  %s:%d\n"
			"  Virtio device: (not sure which one): Error, device behavior.\n"
			"  The device must provide a valid virtio_vq as an argument to %s."
			, __FILE__, __LINE__, __func__);

	// NOTE: The virtio_next_avail_vq_desc will not write more than
	//       vq->vring.num entries to iov, and the device implementation
	//       (virtio_mmio.c) will not allow the driver to set vq->vring.num to a
	//       value greater than QueueNumMax (vq->qnum_max), so you are safe as
	//       long as your iov is at least vq->qnum_max iovecs in size.
	iov = malloc(vq->qnum_max * sizeof(struct iovec));

	if (vq->qready == 0x0)
		VIRTIO_DEV_ERRX(vq->vqdev,
			"The service function for queue '%s' was launched before the driver set QueueReady to 0x1."
			, vq->name);

	// NOTE: This will block in 2 places:
	//       - reading from stdin
	//       - reading from eventfd in virtio_next_avail_vq_desc
	while (1) {
		head = virtio_next_avail_vq_desc(vq, iov, &olen, &ilen);

		if (olen) {
			// virtio-v1.0-cs04 s5.3.6.1 Device Operation (console section)
			VIRTIO_DRI_ERRX(vq->vqdev,
				"The driver placed a device-readable buffer in the console device's receiveq.\n"
				"  See virtio-v1.0-cs04 s5.3.6.1 Device Operation");
		}

		// TODO: We may want to add some sort of console abort
		//       (e.g. type q and enter to quit)
		// readv from stdin as much as we can (to end of bufs or end of input)
		num_read = readv(0, iov, ilen);
		if (num_read < 0)
			VIRTIO_DEV_ERRX(vq->vqdev,
				"Encountered an error trying to read input from stdin (fd 0).");

		// You pass the number of bytes written to virtio_add_used_desc
		virtio_add_used_desc(vq, head, num_read);

		// Poke the guest however the mmio transport prefers
		// NOTE: assuming that the mmio transport was used for now.
		virtio_mmio_set_vring_irq(dev);
		if (dev->poke_guest)
			dev->poke_guest(dev->vec);
		else
			VIRTIO_DEV_ERRX(vq->vqdev,
				"The host MUST provide a way for device interrupts to be sent to the guest. The 'poke_guest' function pointer on the vq->vqdev->transport_dev (assumed to be a struct virtio_mmio_dev) was not set.");
	}
	free(iov);
}

void cons_transmitq_fn(void *_vq) // guest -> host
{
	struct virtio_vq *vq = _vq;
	uint32_t head;
	uint32_t olen, ilen;
	uint32_t i, j;
	struct iovec *iov;
	struct virtio_mmio_dev *dev = vq->vqdev->transport_dev;

	if (!vq)
		errx(1,
			"\n  %s:%d\n"
			"  Virtio device: (not sure which one): Error, device behavior.\n"
			"  The device must provide a valid virtio_vq as an argument to %s."
			, __FILE__, __LINE__, __func__);

	// NOTE: The virtio_next_avail_vq_desc will not write more than
	//       vq->vring.num entries to iov, and the device implementation
	//       (virtio_mmio.c) will not allow the driver to set vq->vring.num to a
	//       value greater than QueueNumMax (vq->qnum_max), so you are safe as
	//       long as your iov is at least vq->qnum_max iovecs in size.
	iov = malloc(vq->qnum_max * sizeof(struct iovec));

	if (vq->qready == 0x0)
		VIRTIO_DEV_ERRX(vq->vqdev,
			"The service function for queue '%s' was launched before the driver set QueueReady to 0x1."
			, vq->name);

	while (1) {
		// Get the buffers:
		head = virtio_next_avail_vq_desc(vq, iov, &olen, &ilen);

		if (ilen) {
			// virtio-v1.0-cs04 s5.3.6.1 Device Operation (console section)
			VIRTIO_DRI_ERRX(vq->vqdev,
				"The driver placed a device-writeable buffer in the console device's transmitq.\n"
				"  See virtio-v1.0-cs04 s5.3.6.1 Device Operation");
		}
		// Process the buffers:
		for (i = 0; i < olen; ++i) {
			for (j = 0; j < iov[i].iov_len; ++j)
				printf("%c", ((char *)iov[i].iov_base)[j]);
		}
		fflush(stdout);

		// Add all the buffers to the used ring.
		// Pass 0 because we wrote nothing.
		virtio_add_used_desc(vq, head, 0);

		// Poke the guest however the mmio transport prefers
		// NOTE: assuming that the mmio transport was used for now
		virtio_mmio_set_vring_irq(dev);
		if (dev->poke_guest)
			dev->poke_guest(dev->vec);
		else
			VIRTIO_DEV_ERRX(vq->vqdev,
				"The host MUST provide a way for device interrupts to be sent to the guest. The 'poke_guest' function pointer on the vq->vqdev->transport_dev (assumed to be a struct virtio_mmio_dev) was not set.");
	}
	free(iov);
}
