1/*# 2 *#Copyright 2019, Data61 3 *#Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 *#ABN 41 687 119 230. 5 *# 6 *#This software may be distributed and modified according to the terms of 7 *#the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 *#See "LICENSE_BSD2.txt" for details. 9 *# 10 *#@TAG(DATA61_BSD) 11 #*/ 12 13#include <sel4/sel4.h> 14#include <camkes.h> 15#include <camkes/msgqueue.h> 16#include <camkes/msgqueue_template.h> 17#include <camkes/virtqueue_template.h> 18#include <virtqueue.h> 19#include <utils/util.h> 20 21/*- include 'seL4SharedData.template.c' -*/ 22 23/*# Message Type #*/ 24 25/*- set type = macros.dataport_type(me.interface.type) -*/ 26/*- set type_size_macro = macros.dataport_size(me.interface.type) -*/ 27 28/*# Sanity check to make sure that there is only one receiver connected #*/ 29/*- if len(me.parent.to_ends) != 1 -*/ 30 /*? raise(Exception('MessageQueue for %s.%s is missing a receiver or has more than one receiver' % (me.instance.name, me.interface.name))) ?*/ 31/*- endif -*/ 32 33/*- set receiver = me.parent.to_ends[0] -*/ 34 35/*# Notifications #*/ 36 37/*# Need a badge as we also want the clients to be able to poll #*/ 38/*- set receiver_ntfn = alloc_obj('%s_%s_receiver_ntfn' % (me.instance.name, me.interface.name), seL4_NotificationObject) -*/ 39/*- set receiver_ntfn_cap = alloc_cap('%s_%s_receiver_ntfn' % (me.instance.name, me.interface.name), receiver_ntfn, read=True, write=True, badge=1) -*/ 40 41/*# Queue Size #*/ 42 43/*- set queue_size = configuration[me.parent.name].get("queue_size", 128) -*/ 44/*- set virtqueue_length = 2 * queue_size -*/ 45 46/*- set queue_total_size = '%s * %s + sizeof(vq_vring_avail_t) + sizeof(uint16_t) * %s + sizeof(vq_vring_used_t) + sizeof(struct vq_vring_used_elem) * %s + sizeof(vq_vring_desc_t) * %s' % (type_size_macro, queue_size, virtqueue_length, virtqueue_length, virtqueue_length) -*/ 47/*- set index = me.parent.from_ends.index(me) -*/ 48/*# TODO This isn't so resilient, maybe stash the name of the buffer? #*/ 49/*- set single_shmem_size = 'sizeof(from_%d_%s_data)' % (index, me.interface.name) -*/ 50 51/*- set interface_name = me.interface.type.name -*/ 52 53/*- set queue_id = configuration[me.instance.name].get("%s_id" % me.interface.name) -*/ 54/*- if queue_id is none or not isinstance(queue_id, six.integer_types) -*/ 55 /*? raise(Exception('%s.%s_id must be set to a number and should be unique across seL4MessageQueue connections in an instance ' % (me.instance.name, me.interface.name))) ?*/ 56/*- endif -*/ 57 58static_assert(/*? queue_total_size ?*/ <= /*? single_shmem_size ?*/, 59 "Queue size is too large for msgqueue /*? receiver.instance.name ?*/./*? receiver.interface.name ?*/," 60 " consider increasing the size of the buffer"); 61 62static void /*? me.interface.name ?*/_notify(void) 63{ 64 seL4_Signal(/*? receiver_ntfn_cap ?*/); 65} 66 67void /*? me.interface.name ?*/__init() 68{ 69 int error = 0; 70 error = camkes_msgqueue_channel_register_sender(/*? queue_id ?*/, 71 /*? me.interface.name ?*/, 72 /*? virtqueue_length ?*/, 73 /*? single_shmem_size ?*/, 74 /*? type_size_macro ?*/, 75 /*? me.interface.name ?*/_notify); 76 if (error) { 77 assert(!"Failed to initialise the msgqueue for connection /*? me.instance.name ?*/./*? me.interface.name ?*/"); 78 } 79} 80