blob: 6f581b2c14cf8935ae9e443dad7fc7cb8f6d0785 [file]
/*
* Copyright 2019, Data61, CSIRO (ABN 41 687 119 230)
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <autoconf.h>
#include <camkes.h>
#include <stdio.h>
#include <virtqueue.h>
#include <camkes/virtqueue.h>
#include <utils/util.h>
#include <string.h>
virtqueue_driver_t read_virtqueue;
virtqueue_driver_t write_virtqueue;
void handle_read_callback(virtqueue_driver_t *vq);
void handle_write_callback(virtqueue_driver_t *vq);
void write_output(char *write_data, size_t write_data_size)
{
if (camkes_virtqueue_driver_scatter_send_buffer(&write_virtqueue, write_data, write_data_size)) {
ZF_LOGE("Client write enqueue failed");
return;
}
write_virtqueue.notify();
}
void loopback_test(void)
{
size_t buffer_size = 4000;
if (camkes_virtqueue_driver_scatter_send_buffer(&read_virtqueue, NULL, buffer_size)) {
ZF_LOGE("Client read enqueue failed");
return;
}
fflush(stdout);
read_virtqueue.notify();
}
void handle_read_callback(virtqueue_driver_t *vq)
{
void *buf = NULL;
unsigned len = 0;
virtqueue_ring_object_t handle;
vq_flags_t flags;
if (!virtqueue_get_used_buf(vq, &handle, &len)) {
ZF_LOGE("Client virtqueue dequeue failed");
return;
}
if (!(buf = calloc(len, sizeof(char)))) {
ZF_LOGE("Could not allocate memory");
return;
}
if (camkes_virtqueue_driver_gather_copy_buffer(vq, &handle, buf, len) != 0) {
free(buf);
}
write_output(buf, len);
}
void handle_write_callback(virtqueue_driver_t *vq)
{
void *buf = NULL;
unsigned len = 0;
virtqueue_ring_object_t handle;
vq_flags_t flags;
if (!virtqueue_get_used_buf(vq, &handle, &len)) {
ZF_LOGE("Client virtqueue dequeue failed");
return;
}
while (camkes_virtqueue_driver_gather_buffer(vq, &handle, &buf, &len, &flags) == 0) {
/* Clean up and free the buffer we allocated */
camkes_virtqueue_buffer_free(vq, buf);
}
/* Moving the call here forces synchronicity but makes it a bit slower */
/* TODO: make it more asynchronous */
loopback_test();
}
/*
void serial_wait_callback(void)
{
if (VQ_DRV_POLL(&read_virtqueue)) {
handle_read_callback(&read_virtqueue);
}
if (VQ_DRV_POLL(&write_virtqueue)) {
handle_write_callback(&write_virtqueue);
}
}
*/
void serial_read_wait_callback(void)
{
if (VQ_DRV_POLL(&read_virtqueue)) {
handle_read_callback(&read_virtqueue);
}
}
void serial_write_wait_callback(void)
{
if (VQ_DRV_POLL(&write_virtqueue)) {
handle_write_callback(&write_virtqueue);
}
}
void pre_init(void)
{
set_putchar(serial_putchar_putchar);
}
int run(void)
{
ZF_LOGE("Starting loopback serial test");
/* Initialise read virtqueue */
int err = camkes_virtqueue_driver_init(&read_virtqueue, 0);
if (err) {
ZF_LOGE("Unable to initialise read virtqueue");
return 1;
}
/* Initialise write virtqueue */
err = camkes_virtqueue_driver_init(&write_virtqueue, 1);
if (err) {
ZF_LOGE("Unable to initialise write virtqueue");
return 1;
}
loopback_test();
return 0;
}