1/**
2 * \file
3 * \brief
4 */
5
6/*
7 * Copyright (c) 2007, 2008, 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, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
13 */
14
15#ifndef ARCH_X86_32_BARRELFISH_LMP_CHAN_H
16#define ARCH_X86_32_BARRELFISH_LMP_CHAN_H
17
18#include <barrelfish/syscall_arch.h>
19#include <barrelfish/caddr.h>
20#include <barrelfish_kpi/lmp.h>
21
22/**
23 * \brief Send a message on the given LMP channel, if possible
24 *
25 * Non-blocking, may fail if there is no space in the receiver's endpoint.
26 *
27 * \param ep Remote endpoint cap
28 * \param flags LMP send flags
29 * \param send_cap (Optional) capability to send with the message
30 * \param length_words Length of the message in words; payload beyond this
31 *                      size will not be delivered
32 * \param arg1..N Message payload
33 */
34static inline errval_t lmp_ep_send(struct capref ep, lmp_send_flags_t flags,
35                                   struct capref send_cap, uint8_t length_words,
36                                   uintptr_t arg1, uintptr_t arg2, uintptr_t arg3,
37                                   uintptr_t arg4)
38{
39    uint8_t invoke_bits = get_cap_valid_bits(ep);
40    capaddr_t invoke_cptr = get_cap_addr(ep) >> (CPTR_BITS - invoke_bits);
41
42    uint8_t send_bits = get_cap_valid_bits(send_cap);
43    capaddr_t send_cptr = get_cap_addr(send_cap) >> (CPTR_BITS - send_bits);
44
45    assert(length_words <= LMP_MSG_LENGTH);
46
47    return syscall7((length_words << 28) | ((flags & 0xf) << 24)
48                    | (invoke_bits << 16) | (send_bits << 8) | SYSCALL_INVOKE,
49                    invoke_cptr, send_cptr, arg1, arg2, arg3, arg4).error;
50}
51
52#define lmp_ep_send4(ep, flags, send_cap, a, b, c, d) \
53  lmp_ep_send((ep), (flags), (send_cap), 4, (a), (b), (c), (d))
54#define lmp_ep_send3(ep, flags, send_cap, a, b, c) \
55  lmp_ep_send((ep), (flags), (send_cap), 3, (a), (b), (c), 0)
56#define lmp_ep_send2(ep, flags, send_cap, a, b) \
57  lmp_ep_send((ep), (flags), (send_cap), 2, (a), (b), 0, 0)
58#define lmp_ep_send1(ep, flags, send_cap, a) \
59  lmp_ep_send((ep), (flags), (send_cap), 1, (a), 0, 0, 0)
60#define lmp_ep_send0(ep, flags, send_cap) \
61  lmp_ep_send((ep), (flags), (send_cap), 0, 0, 0, 0, 0)
62
63#define lmp_chan_send(lc, flags, send_cap, len, a, b, c, d) \
64  lmp_ep_send((lc)->remote_cap, (flags), (send_cap), (len), (a), (b), (c), (d))
65
66#define lmp_chan_send4(lc, flags, send_cap, a, b, c, d) \
67  lmp_ep_send4((lc)->remote_cap, (flags), (send_cap), (a), (b), (c), (d))
68#define lmp_chan_send3(lc, flags, send_cap, a, b, c) \
69  lmp_ep_send3((lc)->remote_cap, (flags), (send_cap), (a), (b), (c))
70#define lmp_chan_send2(lc, flags, send_cap, a, b) \
71  lmp_ep_send2((lc)->remote_cap, (flags), (send_cap), (a), (b))
72#define lmp_chan_send1(lc, flags, send_cap, a) \
73  lmp_ep_send1((lc)->remote_cap, (flags), (send_cap), (a))
74#define lmp_chan_send0(lc, flags, send_cap) \
75  lmp_ep_send0((lc)->remote_cap, (flags), (send_cap))
76
77#endif
78