1/**
2 * \file
3 * \brief
4 */
5
6/*
7 * Copyright (c) 2015, ETH Zurich.
8 * All rights reserved.
9 *
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
13 */
14
15#ifndef ARCH_AARCH64_BARRELFISH_LMP_CHAN_H
16#define ARCH_AARCH64_BARRELFISH_LMP_CHAN_H
17
18#include <barrelfish/syscall_arch.h>
19#include <barrelfish/caddr.h>
20#include <barrelfish_kpi/lmp.h>
21#include <barrelfish_kpi/syscalls.h>
22
23/**
24 * \brief Send a message on the given LMP channel, if possible
25 *
26 * Non-blocking, may fail if there is no space in the receiver's endpoint.
27 *
28 * \param ep Remote endpoint cap
29 * \param flags LMP send flags
30 * \param send_cap (Optional) capability to send with the message
31 * \param length_words Length of the message in words; payload beyond this
32 *                      size will not be delivered
33 * \param arg1..N Message payload
34 */
35static inline errval_t
36lmp_ep_send(
37    struct capref ep,
38    lmp_send_flags_t flags,
39    struct capref send_cap,
40    uint8_t length_words,
41    uintptr_t arg1,
42    uintptr_t arg2,
43    uintptr_t arg3,
44    uintptr_t arg4
45    )
46{
47    uint8_t invoke_level = get_cap_level(ep);
48    capaddr_t invoke_cptr = get_cap_addr(ep);
49
50    uint8_t send_level = get_cap_level(send_cap);
51    capaddr_t send_cptr = get_cap_addr(send_cap);
52
53    assert(length_words <= LMP_MSG_LENGTH);
54
55    return syscall7((length_words << 28) | ((flags & 0xf) << 24) |
56                    (invoke_level << 16) | (send_level << 8) | SYSCALL_INVOKE,
57                    invoke_cptr, send_cptr,
58                    arg1, arg2, arg3, arg4).error;
59}
60
61#define lmp_ep_send4(ep, flags, send_cap, a, b, c, d) \
62  lmp_ep_send((ep), (flags), (send_cap), 4, (a), (b), (c), (d))
63#define lmp_ep_send3(ep, flags, send_cap, a, b, c) \
64  lmp_ep_send((ep), (flags), (send_cap), 3, (a), (b), (c), 0)
65#define lmp_ep_send2(ep, flags, send_cap, a, b) \
66  lmp_ep_send((ep), (flags), (send_cap), 2, (a), (b), 0, 0)
67#define lmp_ep_send1(ep, flags, send_cap, a) \
68  lmp_ep_send((ep), (flags), (send_cap), 1, (a), 0, 0, 0)
69#define lmp_ep_send0(ep, flags, send_cap) \
70  lmp_ep_send((ep), (flags), (send_cap), 0, 0, 0, 0, 0)
71
72#define lmp_chan_send(lc, flags, send_cap, len, a, b, c, d) \
73  lmp_ep_send((lc)->remote_cap, (flags), (send_cap), (len), (a), (b), (c), (d))
74
75#define lmp_chan_send4(lc, flags, send_cap, a, b, c, d) \
76  lmp_ep_send4((lc)->remote_cap, (flags), (send_cap), (a), (b), (c), (d))
77#define lmp_chan_send3(lc, flags, send_cap, a, b, c) \
78  lmp_ep_send3((lc)->remote_cap, (flags), (send_cap), (a), (b), (c))
79#define lmp_chan_send2(lc, flags, send_cap, a, b) \
80  lmp_ep_send2((lc)->remote_cap, (flags), (send_cap), (a), (b))
81#define lmp_chan_send1(lc, flags, send_cap, a) \
82  lmp_ep_send1((lc)->remote_cap, (flags), (send_cap), (a))
83#define lmp_chan_send0(lc, flags, send_cap) \
84  lmp_ep_send0((lc)->remote_cap, (flags), (send_cap))
85
86#endif
87