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/*# Do a sanity check to make sure there are no two senders #*/
24/*- if len(me.parent.from_ends) != 1 -*/
25    /*? raise(Exception('MessageQueue for %s.%s is missing a sender or has more than one sender' % (me.instance.me, me.interface.name))) ?*/
26/*- endif -*/
27
28/*- set from_instance_name = me.parent.from_ends[0].instance.name -*/
29/*- set from_interface_name = me.parent.from_ends[0].interface.name -*/
30
31/*# Grab the notification, that the sender allocated or allocate it for the sender #*/
32/*- set receiver_ntfn = alloc_obj('%s_%s_receiver_ntfn' % (from_instance_name, from_interface_name), seL4_NotificationObject) -*/
33/*- set receiver_ntfn_cap = alloc_cap('%s_%s_receiver_ntfn_cap' % (from_instance_name, from_interface_name), receiver_ntfn, read=True, write=True, badge=1) -*/
34
35/*- set type = macros.dataport_type(me.interface.type) -*/
36/*- set type_size_macro = macros.dataport_size(me.interface.type) -*/
37
38/*- set queue_id = configuration[me.instance.name].get("%s_id" % me.interface.name) -*/
39/*- if queue_id is none or not isinstance(queue_id, six.integer_types) -*/
40    /*? 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))) ?*/
41/*- endif -*/
42
43/*- set queue_size = configuration[me.parent.name].get("queue_size", 128) -*/
44/*- set virtqueue_length = 2 * queue_size -*/
45
46static int _/*? me.interface.name ?*/_poll()
47{
48    seL4_Word badge;
49    seL4_Poll(/*? receiver_ntfn_cap ?*/, &badge);
50    if (badge) {
51        return 1;
52    }
53    return 0;
54}
55
56static void _/*? me.interface.name ?*/_wait()
57{
58    seL4_Wait(/*? receiver_ntfn_cap ?*/, NULL);
59}
60
61void /*? me.interface.name ?*/__init()
62{
63    int error = 0;
64    error = camkes_msgqueue_channel_register_receiver(/*? queue_id ?*/,
65                                                      /*? me.interface.name ?*/,
66                                                      /*# TODO This isn't so resilient, maybe stash the name of the buffer? #*/
67                                                      /*? virtqueue_length ?*/,
68                                                      sizeof(/*? 'to_0_%s_data' % me.interface.name ?*/),
69                                                      /*? type_size_macro ?*/,
70                                                      _/*? me.interface.name ?*/_poll,
71                                                      _/*? me.interface.name ?*/_wait);
72    if (error) {
73        assert(!"Failed to initialise the msgqueue for /*? me.instance.name ?*/./*? me.interface.name ?*/");
74    }
75}
76