blob: 369b5dab5f88eb67fde8b1b8ab4aba9726b93233 [file] [log] [blame]
/*#
*#Copyright 2019, Data61, CSIRO (ABN 41 687 119 230)
*#
*#SPDX-License-Identifier: BSD-2-Clause
#*/
#include <sel4/sel4.h>
#include <camkes.h>
#include <camkes/msgqueue.h>
#include <camkes/msgqueue_template.h>
#include <camkes/virtqueue_template.h>
#include <virtqueue.h>
#include <utils/util.h>
/*- include 'seL4SharedData.template.c' -*/
/*# Message Type #*/
/*- set type = macros.dataport_type(me.interface.type) -*/
/*- set type_size_macro = macros.dataport_size(me.interface.type) -*/
/*# Sanity check to make sure that there is only one receiver connected #*/
/*- if len(me.parent.to_ends) != 1 -*/
/*? raise(Exception('MessageQueue for %s.%s is missing a receiver or has more than one receiver' % (me.instance.name, me.interface.name))) ?*/
/*- endif -*/
/*- set receiver = me.parent.to_ends[0] -*/
/*# Notifications #*/
/*# Need a badge as we also want the clients to be able to poll #*/
/*- set receiver_ntfn = alloc_obj('%s_%s_receiver_ntfn' % (me.instance.name, me.interface.name), seL4_NotificationObject) -*/
/*- set receiver_ntfn_cap = alloc_cap('%s_%s_receiver_ntfn' % (me.instance.name, me.interface.name), receiver_ntfn, read=True, write=True, badge=1) -*/
/*# Queue Size #*/
/*- set queue_size = configuration[me.parent.name].get("queue_size", 128) -*/
/*- set virtqueue_length = 2 * queue_size -*/
/*- 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) -*/
/*- set index = me.parent.from_ends.index(me) -*/
/*# TODO This isn't so resilient, maybe stash the name of the buffer? #*/
/*- set single_shmem_size = 'sizeof(from_%d_%s_data)' % (index, me.interface.name) -*/
/*- set interface_name = me.interface.type.name -*/
/*- set queue_id = configuration[me.instance.name].get("%s_id" % me.interface.name) -*/
/*- if queue_id is none or not isinstance(queue_id, six.integer_types) -*/
/*? 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))) ?*/
/*- endif -*/
static_assert(/*? queue_total_size ?*/ <= /*? single_shmem_size ?*/,
"Queue size is too large for msgqueue /*? receiver.instance.name ?*/./*? receiver.interface.name ?*/,"
" consider increasing the size of the buffer");
static void /*? me.interface.name ?*/_notify(void)
{
seL4_Signal(/*? receiver_ntfn_cap ?*/);
}
void /*? me.interface.name ?*/__init()
{
int error = 0;
error = camkes_msgqueue_channel_register_sender(/*? queue_id ?*/,
/*? me.interface.name ?*/,
/*? virtqueue_length ?*/,
/*? single_shmem_size ?*/,
/*? type_size_macro ?*/,
/*? me.interface.name ?*/_notify);
if (error) {
assert(!"Failed to initialise the msgqueue for connection /*? me.instance.name ?*/./*? me.interface.name ?*/");
}
}