1/* 2 * Copyright 2019, Data61, CSIRO (ABN 41 687 119 230) 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <autoconf.h> 8#include <camkes.h> 9#include <stdio.h> 10#include <virtqueue.h> 11#include <camkes/virtqueue.h> 12#include <utils/util.h> 13#include <string.h> 14 15virtqueue_driver_t read_virtqueue; 16virtqueue_driver_t write_virtqueue; 17 18void handle_read_callback(virtqueue_driver_t *vq); 19void handle_write_callback(virtqueue_driver_t *vq); 20 21void write_output(char *write_data, size_t write_data_size) 22{ 23 if (camkes_virtqueue_driver_scatter_send_buffer(&write_virtqueue, write_data, write_data_size)) { 24 ZF_LOGE("Client write enqueue failed"); 25 return; 26 } 27 write_virtqueue.notify(); 28} 29 30void loopback_test(void) 31{ 32 size_t buffer_size = 4000; 33 34 35 if (camkes_virtqueue_driver_scatter_send_buffer(&read_virtqueue, NULL, buffer_size)) { 36 ZF_LOGE("Client read enqueue failed"); 37 return; 38 } 39 40 fflush(stdout); 41 read_virtqueue.notify(); 42} 43 44void handle_read_callback(virtqueue_driver_t *vq) 45{ 46 void *buf = NULL; 47 unsigned len = 0; 48 virtqueue_ring_object_t handle; 49 vq_flags_t flags; 50 51 if (!virtqueue_get_used_buf(vq, &handle, &len)) { 52 ZF_LOGE("Client virtqueue dequeue failed"); 53 return; 54 } 55 if (!(buf = calloc(len, sizeof(char)))) { 56 ZF_LOGE("Could not allocate memory"); 57 return; 58 } 59 if (camkes_virtqueue_driver_gather_copy_buffer(vq, &handle, buf, len) != 0) { 60 free(buf); 61 } 62 write_output(buf, len); 63} 64 65void handle_write_callback(virtqueue_driver_t *vq) 66{ 67 void *buf = NULL; 68 unsigned len = 0; 69 virtqueue_ring_object_t handle; 70 vq_flags_t flags; 71 72 73 if (!virtqueue_get_used_buf(vq, &handle, &len)) { 74 ZF_LOGE("Client virtqueue dequeue failed"); 75 return; 76 } 77 while (camkes_virtqueue_driver_gather_buffer(vq, &handle, &buf, &len, &flags) == 0) { 78 /* Clean up and free the buffer we allocated */ 79 camkes_virtqueue_buffer_free(vq, buf); 80 } 81 /* Moving the call here forces synchronicity but makes it a bit slower */ 82 /* TODO: make it more asynchronous */ 83 loopback_test(); 84} 85 86/* 87void serial_wait_callback(void) 88{ 89 if (VQ_DRV_POLL(&read_virtqueue)) { 90 handle_read_callback(&read_virtqueue); 91 } 92 if (VQ_DRV_POLL(&write_virtqueue)) { 93 handle_write_callback(&write_virtqueue); 94 } 95} 96*/ 97 98void serial_read_wait_callback(void) 99{ 100 if (VQ_DRV_POLL(&read_virtqueue)) { 101 handle_read_callback(&read_virtqueue); 102 } 103} 104 105void serial_write_wait_callback(void) 106{ 107 if (VQ_DRV_POLL(&write_virtqueue)) { 108 handle_write_callback(&write_virtqueue); 109 } 110} 111 112void pre_init(void) 113{ 114 set_putchar(serial_putchar_putchar); 115} 116 117int run(void) 118{ 119 ZF_LOGE("Starting loopback serial test"); 120 121 /* Initialise read virtqueue */ 122 int err = camkes_virtqueue_driver_init(&read_virtqueue, 0); 123 if (err) { 124 ZF_LOGE("Unable to initialise read virtqueue"); 125 return 1; 126 } 127 128 /* Initialise write virtqueue */ 129 err = camkes_virtqueue_driver_init(&write_virtqueue, 1); 130 if (err) { 131 ZF_LOGE("Unable to initialise write virtqueue"); 132 return 1; 133 } 134 135 loopback_test(); 136 137 return 0; 138} 139