1/*
2 * Copyright (c) 2007-12 ETH Zurich.
3 * All rights reserved.
4 *
5 * This file is distributed under the terms in the attached LICENSE file.
6 * If you do not find this file, copies can be found by writing to:
7 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
8 */
9
10#include <stdio.h>
11#include <string.h>
12#include <stdlib.h>
13
14#include <barrelfish/barrelfish.h>
15#include <barrelfish/dispatch.h>
16#include <barrelfish/ump_chan.h>
17
18#include <dma/xeon_phi/xeon_phi_dma.h>
19#include <dma/dma_request.h>
20#include <dma/client/dma_client_device.h>
21#include <dma/dma_manager_client.h>
22
23#include <xeon_phi/xeon_phi.h>
24#include <xeon_phi/xeon_phi_client.h>
25#include <driverkit/iommu.h>
26
27#include <if/xomp_defs.h>
28
29
30#define HLINE debug_printf("========================================================\n");
31#define hline debug_printf("--------------------------------------------------------\n");
32#define PRINTF(x...) debug_printf("[HW Models] " x)
33#define TODO(x...) debug_printf("[HW Models] TODO: " x)
34
35#define DATA_SIZE (1UL << 30)
36#define MSG_CHANNEL_SIZE (1UL << 20)
37#define MSG_FRAME_SIZE (2 * MSG_CHANNEL_SIZE)
38
39static uint8_t finished = 0;
40
41static void do_work_rx(struct xomp_binding *_binding, uint64_t fn, uint64_t arg,
42                       uint64_t tid, uint64_t flags)
43{
44    errval_t err;
45
46    hline
47    PRINTF("Co-processor start doing work...\n");
48
49    for(size_t i = 0; i < arg; i += sizeof(uint64_t)) {
50        uint64_t *p = (uint64_t *)(fn + i);
51        *p = *p + 1;
52    }
53
54    hline
55    PRINTF("Co-processor done doing work...\n");
56
57    err = _binding->tx_vtbl.done_notify(_binding, NOP_CONT, 0, SYS_ERR_OK);
58    assert(err_is_ok(err));
59}
60
61static void bind_cb(void *st, errval_t err, struct xomp_binding *_binding)
62{
63    hline
64    PRINTF("Bind callback.\n");
65
66    if (err_is_fail(err)) {
67        USER_PANIC_ERR(err, "failed to bind to host\n");
68    }
69
70    _binding->rx_vtbl.do_work = do_work_rx;
71}
72
73static void message_passing_init(struct dmem *msgmem)
74{
75    errval_t err;
76
77    hline
78    PRINTF("Initializing message passing\n");
79
80
81    struct xomp_frameinfo fi = {
82            .sendbase = msgmem->devaddr + MSG_CHANNEL_SIZE,
83            .inbuf = (void *)(msgmem->vbase),
84            .inbufsize = MSG_CHANNEL_SIZE,
85            .outbuf = (void *)(msgmem->vbase + MSG_CHANNEL_SIZE),
86            .outbufsize = MSG_CHANNEL_SIZE,
87    };
88
89
90    err = xomp_connect(&fi, bind_cb, NULL, get_default_waitset(),
91                       IDC_BIND_FLAGS_DEFAULT);
92    if (err_is_fail(err)) {
93        USER_PANIC_ERR(err, "failed to connect");
94    }
95
96}
97
98static errval_t msg_open_cb(xphi_dom_id_t domain,
99                            uint64_t usrdata,
100                            struct capref msgframe,
101                            uint8_t type)
102{
103    errval_t err;
104
105    hline
106    PRINTF("Co-processor handling msg_open_cb\n");
107
108    struct frame_identity id;
109    err = frame_identify(msgframe, &id);
110    if (err_is_fail(err)) {
111        return err;
112    }
113
114    PRINTF("Obtained message cap: %lx..%lx\n", id.base, id.base + id.bytes - 1);
115
116
117    PRINTF("Mapping at address 0x%lx\n", usrdata);
118
119    err = vspace_map_one_frame_fixed(usrdata, id.bytes, msgframe, NULL, NULL);
120    if (err_is_fail(err)) {
121        DEBUG_ERR(err, "faield to map!");
122        return err;
123    }
124
125
126    PRINTF("Setup successfull %s\n", err_getstring(err));
127
128    return SYS_ERR_OK;
129}
130
131static struct xeon_phi_callbacks callbacks = {
132    .open = msg_open_cb
133};
134
135
136int main(int argc, char **argv)
137{
138    HLINE
139    PRINTF("Co-processor starts executing...\n");
140    HLINE
141
142    /* set the connection */
143    xeon_phi_client_init(disp_xeon_phi_id());
144
145    /* set the callbacks */
146    xeon_phi_client_set_callbacks(&callbacks);
147
148    /* */
149    errval_t err;
150
151    struct cnoderef argcnref;
152
153    argcnref = build_cnoderef(cap_argcn, CNODE_TYPE_OTHER);
154
155    struct capref msgframe = {
156            .cnode = argcnref,
157            .slot = 0
158    };
159
160
161    struct dmem dmem;
162    struct frame_identity id;
163    err = frame_identify(msgframe, &id);
164    if (err_is_fail(err)) {
165        USER_PANIC_ERR(err, "failed to invoke frame identify\n");
166    }
167
168    PRINTF("Using messaging frame 0x%lx..0x%lx\n", id.base, id.base + id.bytes - 1);
169
170
171
172    dmem.devaddr = id.base;
173    dmem.mem = msgframe;
174    dmem.size = id.bytes;
175
176    err = vspace_map_one_frame((void **)&dmem.vbase, dmem.size, dmem.mem, NULL, NULL);
177    if (err_is_fail(err)) {
178        return err;
179    }
180
181    message_passing_init(&dmem);
182
183    PRINTF("Waiting for the commands...\n");
184
185    while(!finished) {
186        messages_wait_and_handle_next();
187    }
188
189
190    PRINTF("Co-processor terminated...\n");
191}
192