1/* 2 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7 8#include <assert.h> 9#include <camkes/io.h> 10#include "client.h" 11 12 13seL4_CPtr echo_control_notification(); 14 15virtqueue_driver_t tx_virtqueue; 16virtqueue_driver_t rx_virtqueue; 17 18 19static void handle_picoserver_notification(UNUSED seL4_Word badge, UNUSED void *cookie) 20{ 21 picoserver_event_t server_event = echo_control_event_poll(); 22 int socket = 0; 23 uint16_t events = 0; 24 while (server_event.num_events_left > 0 || server_event.events) { 25 socket = server_event.socket_fd; 26 events = server_event.events; 27 if (socket == utiliz_socket || socket == peer_socket) { 28 handle_tcp_utiliz_notification(events, socket); 29 server_event = echo_control_event_poll(); 30 } else if (socket == socket_in || socket == tcp_echo_client) { 31 handle_tcp_echo_notification(events, socket); 32 server_event = echo_control_event_poll(); 33 34 } else { 35 ZF_LOGE("Got event for socket: %d but no registered handler", socket); 36 } 37 38 server_event = echo_control_event_poll(); 39 } 40} 41 42static tx_msg_t *get_msg_from_queue(virtqueue_driver_t *queue) 43{ 44 virtqueue_ring_object_t handle; 45 uint32_t len; 46 if (virtqueue_get_used_buf(queue, &handle, &len) == 0) { 47 return NULL; 48 } 49 50 vq_flags_t flag; 51 void *buf; 52 int more = virtqueue_gather_used(queue, &handle, &buf, &len, &flag); 53 if (more == 0) { 54 ZF_LOGF("Failed to dequeue message from the queue"); 55 } 56 return DECODE_DMA_ADDRESS(buf); 57 58} 59 60 61 62static void async_event(UNUSED seL4_Word badge, void *cookie) 63{ 64 while (true) { 65 66 tx_msg_t *msg = get_msg_from_queue(&tx_virtqueue); 67 if (!msg) { 68 break; 69 } 70 if ((uintptr_t)msg->client_cookie == UDP_SOCKETS_ASYNC_ID) { 71 udp_socket_handle_async_sent(msg); 72 73 } else if ((uintptr_t)msg->client_cookie == TCP_SOCKETS_ASYNC_ID) { 74 tcp_socket_handle_async_sent(msg); 75 } else { 76 ZF_LOGE("Message sent but bad socket: %d", msg->socket_fd); 77 } 78 } 79 while (true) { 80 81 tx_msg_t *msg = get_msg_from_queue(&rx_virtqueue); 82 if (!msg) { 83 break; 84 } 85 if ((uintptr_t)msg->client_cookie == UDP_SOCKETS_ASYNC_ID) { 86 udp_socket_handle_async_received(msg); 87 } else if ((uintptr_t)msg->client_cookie == TCP_SOCKETS_ASYNC_ID) { 88 tcp_socket_handle_async_received(msg); 89 } else { 90 ZF_LOGE("Message received but bad socket: %d", msg->socket_fd); 91 } 92 } 93 94 tx_virtqueue.notify(); 95} 96 97 98int setup_echo_server(ps_io_ops_t *io_ops) 99{ 100 seL4_Word tx_badge; 101 seL4_Word rx_badge; 102 /* Initialise read virtqueue */ 103 int error = camkes_virtqueue_driver_init_with_recv(&tx_virtqueue, camkes_virtqueue_get_id_from_name("echo_tx"), 104 NULL, &tx_badge); 105 if (error) { 106 ZF_LOGE("Unable to initialise TX virtqueue"); 107 } 108 109 /* Initialise write virtqueue */ 110 error = camkes_virtqueue_driver_init_with_recv(&rx_virtqueue, camkes_virtqueue_get_id_from_name("echo_rx"), 111 NULL, &rx_badge); 112 if (error) { 113 ZF_LOGE("Unable to initialise RX virtqueue"); 114 } 115 116 /* Now poll for events and handle them */ 117 single_threaded_component_register_handler(tx_badge, "async_notification", async_event, NULL); 118 single_threaded_component_register_handler(echo_control_notification_badge(), "sync_notification", 119 handle_picoserver_notification, NULL); 120 tx_virtqueue.notify(); 121 return 0; 122} 123 124CAMKES_POST_INIT_MODULE_DEFINE(setup_echo, setup_echo_server); 125