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