1/*
2 * Copyright 2017, 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#pragma once
14
15#include <camkes/dataport.h>
16#include <camkes/error.h>
17#include <stdint.h>
18#include <stdlib.h>
19#include <utils/util.h>
20#include <platsupport/io.h>
21#include <platsupport/irq.h>
22
23/*? macros.show_includes(me.type.includes) ?*/
24/*- for i in me.type.uses -*/
25    /*? macros.show_includes(i.type.includes) ?*/
26/*- endfor -*/
27/*- for i in me.type.provides -*/
28    /*? macros.show_includes(i.type.includes) ?*/
29/*- endfor -*/
30
31const char *get_instance_name(void);
32
33/* Attributes */
34
35// This macro allows using attributes as "rvalues" e.g. in the array size
36// declarations. Unfortunately, the C language (in contrast to C++) does not
37// support using "lvalues" in this case, even if declared as const.
38#define CAMKES_CONST_ATTR(attr) attr##_DEF
39
40/*- set myconf = configuration[me.name] -*/
41/*? macros.print_type_definitions(me.type.attributes, myconf) ?*/
42/*- for a in me.type.attributes -*/
43    /*- set value = myconf.get(a.name) -*/
44    /*- if value is not none -*/
45        #define /*? a.name ?*/_DEF /*? macros.show_attribute_value(a, value) ?*/
46    /*- endif -*/
47
48    extern const /*? macros.show_type(a.type) ?*/ /*? a.name ?*/ /*- if a.array -*/ [/*?len(value)?*/] /*- endif -*/;
49/*- endfor -*/
50
51/*- for u in me.type.uses + me.type.provides -*/
52    /*- for m in u.type.methods -*/
53        /*- if m.return_type is not none -*/
54            /*- if m.return_type == 'string' -*/
55                char *
56            /*- else -*/
57                /*? macros.show_type(m.return_type) ?*/
58            /*- endif -*/
59        /*- else -*/
60            void
61        /*- endif -*/
62        /*? u.name ?*/_/*? m.name ?*/(
63            /*- for p in m.parameters -*/
64              /*- if p.direction == 'in' -*/
65                /*- if p.array -*/
66                  size_t /*? p.name ?*/_sz,
67                  /*- if p.type == 'string' -*/
68                    char **
69                  /*- else -*/
70                    const /*? macros.show_type(p.type) ?*/ *
71                  /*- endif -*/
72                /*- elif p.type == 'string' -*/
73                  const char *
74                /*- else -*/
75                  /*? macros.show_type(p.type) ?*/
76                /*- endif -*/
77                /*? p.name ?*/
78              /*- else -*/
79                /*? assert(p.direction in ['refin', 'out', 'inout']) ?*/
80                /*- if p.array -*/
81                  /*- if p.direction == 'refin' -*/
82                    const
83                  /*- endif -*/
84                  size_t * /*? p.name ?*/_sz,
85                  /*- if p.type == 'string' -*/
86                    char ***
87                  /*- else -*/
88                    /*? macros.show_type(p.type) ?*/ **
89                  /*- endif -*/
90                /*- elif p.type == 'string' -*/
91                  char **
92                /*- else -*/
93                  /*- if p.direction == 'refin' -*/
94                    const
95                  /*- endif -*/
96                  /*? macros.show_type(p.type) ?*/ *
97                /*- endif -*/
98                /*? p.name ?*/
99              /*- endif -*/
100              /*- if not loop.last -*/
101                ,
102              /*- endif -*/
103            /*- endfor -*/
104            /*- if len(m.parameters) == 0 -*/
105              void
106            /*- endif -*/
107        ) NONNULL_ALL /*- if isinstance(u, camkes.ast.Uses) and u.optional -*/ WEAK /*- endif -*/;
108    /*- endfor -*/
109/*- endfor -*/
110
111/*- for c in me.type.consumes -*/
112    /*# HACK: Connection-specific check here to just be nice to the user and
113     *# trigger a compile-time warning if they try to use functions that aren't
114     *# implemented.
115     #*/
116    /*- set irq = [False] -*/
117    /*- set dtb_connector = [False] -*/
118    /*- for conn in composition.connections -*/
119      /*- if conn.type.name == 'seL4HardwareInterrupt' and id(conn.to_ends[0].interface) == id(c) -*/
120        /*- do irq.__setitem__(0, True) -*/
121        /*- break -*/
122      /*- endif -*/
123      /*- if conn.type.name == 'seL4DTBHardware' -*/
124        /*# We need to loop over ends as there may be multiple 'consumes' devices connected to
125         *# the same dummy source, e.g.
126         *#     emits Dummy dummy_source;
127         *#     consumes Dummy pwm_timer_1;
128         *#     consumes Dummy pwm_timer_2;
129         *#     ...
130         *#     connection seL4DTBHardware pwm_conn_1(from dummy_source, to pwm_timer_1);
131         *#     connection seL4DTBHardware pwm_conn_2(from dummy_source, to pwm_timer_2);
132         *# the whole connection becomes:
133         *#     component.pwm_conn_1.component.pwm_conn_2
134         #*/
135        /*- for end in conn.to_ends -*/
136            /*- if id(end.interface) == id(c) -*/
137                /*- do irq.__setitem__(0, True) -*/
138                /*- do dtb_connector.__setitem__(0, True) -*/
139                /*- break -*/
140            /*- endif -*/
141        /*- endfor -*/
142        /*- if irq[0] -*/
143            /*- break -*/
144        /*- endif -*/
145      /*- endif -*/
146    /*- endfor -*/
147    void /*? c.name ?*/_wait(void)
148        /*- if c.optional -*/ WEAK /*- endif -*/
149        /*- if irq[0] -*/ WARNING("/*? c.name ?*/_wait is not provided by "
150            "seL4HardwareInterrupt or seL4DTBHardware") /*- endif -*/
151        ;
152    int /*? c.name ?*/_poll(void) WARN_UNUSED_RESULT
153        /*- if c.optional -*/ WEAK /*- endif -*/
154        /*- if irq[0] -*/ WARNING("/*? c.name ?*/_poll is not provided by "
155            "seL4HardwareInterrupt or seL4DTBHardware") /*- endif -*/
156        ;
157    int /*? c.name ?*/_reg_callback(void (*callback)(void*), void *arg) WARN_UNUSED_RESULT
158        /*- if c.optional -*/ WEAK /*- endif -*/
159        /*- if irq[0] -*/ WARNING("/*? c.name ?*/_reg_callback is not provided "
160            "by seL4HardwareInterrupt or seL4DTBHardware") /*- endif -*/
161        ;
162    /*- if dtb_connector[0] -*/
163        /*# Since the interfaces of the seL4DTBHardware connector are 'consumes', we
164         *# have to declare the buffers here, and not inside the dataport block
165         #*/
166        /*- set config_name = '%s.%s' % (me.name, c) -*/
167        /*- set dtb_config = configuration[config_name]['dtb'] -*/
168        /*- if dtb_config is none -*/
169            /*? raise(TemplateError('Couldn\'t grab the DTB for the %s seL4DTBHardware connection.' % config_name)) ?*/
170        /*- endif -*/
171        /*- set dtb_query = dtb_config.get('query') -*/
172        /*- if dtb_query is none -*/
173            /*? raise(TemplateError('Couldn\'t grab the DTB query for the %s seL4DTBHardware connection.' % config_name)) ?*/
174        /*- endif -*/
175        /*- if len(dtb_query) != 1 -*/
176            /*? raise(TemplateError('Invalid number of DTB paths for the %s seL4DTBHardware connection.' % config_name)) ?*/
177        /*- endif -*/
178        /*- if dtb_query[0] is none -*/
179            /*? raise(TemplateError('Missing DTB path for the %s seL4DTBHardware connection.' % config_name)) ?*/
180        /*- endif -*/
181        /*- set dtb = dtb_query[0] -*/
182        /*- set num_registers = len(dtb['reg']) // (dtb['this_address_cells'][0] + dtb['this_size_cells'][0]) -*/
183        /*# Declare all the initialised buffers #*/
184        /*- for i in range(0, num_registers) -*/
185            extern void * /*? c ?*/_/*? i ?*/;
186        /*- endfor -*/
187    /*- endif -*/
188    /*- if irq[0] and dtb_connector[0] -*/
189        int /*? c.name ?*/_irq_acknowledge(ps_irq_t *irq) WARN_UNUSED_RESULT;
190        /* Implemented by user code or substituted for the IRQ interface. */
191        void /*? c.name ?*/_irq_handle(ps_irq_t *irq) WEAK;
192    /*- else -*/
193        int /*? c.name ?*/_acknowledge(void) WARN_UNUSED_RESULT
194        /*- if c.optional -*/ WEAK /*- endif -*/;
195        /* Implemented by user code or substituted for the IRQ interface. */
196        void /*? c.name ?*/_handle(void) WEAK;
197    /*- endif -*/
198/*- endfor -*/
199
200/*- for e in me.type.emits -*/
201    void /*? e.name ?*/_emit(void);
202/*- endfor -*/
203
204/*- for d in me.type.dataports -*/
205    extern /*? macros.dataport_type(d.type) ?*/ * /*? d.name ?*/
206    /*- if d.optional -*/
207        WEAK
208    /*- endif -*/;
209    int /*? d.name ?*/_cache_op(size_t start_offset, size_t size, dma_cache_op_t cache_op)
210    /*- if d.optional -*/
211        __attribute__((weak))
212    /*- endif -*/;
213    #define /*? d.name ?*/_release() COMPILER_MEMORY_RELEASE()
214    #define /*? d.name ?*/_acquire() COMPILER_MEMORY_ACQUIRE()
215
216/*- endfor -*/
217
218/*- for m in me.type.mutexes -*/
219    int /*? m.name ?*/_lock(void) WARN_UNUSED_RESULT;
220    int /*? m.name ?*/_unlock(void) WARN_UNUSED_RESULT;
221/*- endfor -*/
222
223/*- for s in me.type.semaphores -*/
224    int /*? s.name ?*/_wait(void) WARN_UNUSED_RESULT;
225    int /*? s.name ?*/_trywait(void) WARN_UNUSED_RESULT;
226    int /*? s.name ?*/_post(void) WARN_UNUSED_RESULT;
227/*- endfor -*/
228
229/*- for b in me.type.binary_semaphores -*/
230    int /*? b.name ?*/_wait(void) WARN_UNUSED_RESULT;
231    int /*? b.name ?*/_post(void) WARN_UNUSED_RESULT;
232/*- endfor -*/
233
234/* Entry point expected to be provided by the user. */
235int run(void);
236
237/*- set all_interfaces = me.type.provides + me.type.uses + me.type.emits + me.type.consumes + me.type.dataports -*/
238
239/* Optional init functions provided by the user. */
240void pre_init(void) WEAK;
241void post_init(void) WEAK;
242/*- for i in all_interfaces -*/
243    void /*? i.name ?*/__init(void) WEAK;
244
245    void /*? i.name ?*/_timing_get_points(char ***points, size_t *size);
246    uint64_t /*? i.name ?*/_timing_get_entry(unsigned iteration, char *point);
247    void /*? i.name ?*/_timing_reset(void);
248/*- endfor -*/
249
250void set_putchar(void (*putchar)(int c));
251
252/*- for i in all_interfaces -*/
253  camkes_error_handler_t /*? i.name ?*/_register_error_handler(
254    camkes_error_handler_t handler);
255/*- endfor -*/
256
257@CMAKE_INTERFACE_INCLUDES@
258