1/*
2 * Copyright (c) 2017 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 <stdlib.h>
11#include <stdio.h>
12#include <time.h>
13#include <barrelfish/barrelfish.h>
14#include <barrelfish/waitset.h>
15#include <barrelfish/deferred.h>
16#include <barrelfish/nameservice_client.h>
17#include <devif/queue_interface.h>
18#include <devif/backends/descq.h>
19#include <devif/backends/debug.h>
20#include <if/devif_test_defs.h>
21
22
23static uint16_t qid = 0;
24
25static struct ele* list = NULL;
26static struct ele* end = NULL;
27static struct devq* descq;
28static struct devq* debug;
29
30
31struct ele {
32    struct  descq* q;
33    uint16_t qid;
34    struct ele* next;
35};
36
37static errval_t create(struct descq* q, uint64_t* queue_id)
38{
39    if (list == NULL) {
40        list = malloc(sizeof(struct ele));
41        list->q = q;
42        list->qid = qid;
43        list->next = NULL;
44        end = list;
45    } else {
46        struct ele* item = malloc(sizeof(struct ele));
47        item->q = q;
48        item->qid = qid;
49        item->next = NULL;
50        end->next = item;
51        end = item;
52    }
53
54    // stack debug queue on top
55    errval_t err;
56    err = debug_create((struct debug_q**) &debug, (struct devq*) q);
57    if (err_is_fail(err)) {
58        USER_PANIC("Allocating debug q failed \n");
59    }
60
61    qid++;
62    return SYS_ERR_OK;
63}
64
65static errval_t destroy(struct descq* q)
66{
67    return SYS_ERR_OK;
68}
69
70static errval_t rpc_request_ep(struct devif_test_binding* b, coreid_t core,
71                               errval_t* err, struct capref* cap)
72{
73    *err = slot_alloc(cap);
74    if (err_is_fail(*err)) {
75        return *err;
76    }
77
78    *err = descq_create_ep((struct descq*) descq, core, cap);
79    if (err_is_fail(*err)) {
80        slot_free(*cap);
81        return *err;
82    }
83
84    return *err;
85}
86
87static void request_ep(struct devif_test_binding* b, coreid_t core)
88{
89    errval_t err, err2;
90    struct capref ep;
91    err = rpc_request_ep(b, core, &err2, &ep);
92    err = b->tx_vtbl.request_ep_response(b, NOP_CONT, err, ep);
93    assert(err_is_ok(err));
94}
95
96static errval_t notify(struct descq* q)
97{
98
99    //struct devq* queue = (struct devq*) q;
100    struct devq* queue = (struct devq*) debug;
101    errval_t err = SYS_ERR_OK;
102    //errval_t err2 = SYS_ERR_OK;
103    regionid_t rid;
104    genoffset_t offset;
105    genoffset_t length;
106    genoffset_t valid_data;
107    genoffset_t valid_length;
108    uint64_t flags;
109    bool exit = false;
110    uint16_t num_enq = 0;
111    while(!exit) {
112        err = devq_dequeue(queue, &rid, &offset, &length,
113                           &valid_data, &valid_length, &flags);
114        if (err_is_fail(err)) {
115            exit = true;
116        } else {
117           bool exit2 = false;
118            while(!exit2) {
119                err = devq_enqueue(queue, rid, offset, length, valid_data,
120                                   valid_length, flags);
121                if (err_is_ok(err)) {
122                    exit2 = true;
123                    num_enq++;
124                }
125            }
126        }
127    }
128
129    if (num_enq > 0) {
130        err = devq_notify(queue);
131    } else {
132        err = SYS_ERR_OK;
133    }
134
135    return err;
136}
137
138static errval_t reg(struct descq* q, struct capref cap,
139                    regionid_t rid)
140{
141    return debug_add_region((struct debug_q*) debug, cap, rid);
142}
143
144
145static errval_t dereg(struct descq* q, regionid_t rid)
146{
147    return debug_remove_region((struct debug_q*) debug, rid);
148}
149
150
151static errval_t control(struct descq* q, uint64_t cmd, uint64_t value, uint64_t* res)
152{
153    return SYS_ERR_OK;
154}
155
156static struct devif_test_rpc_rx_vtbl rpc_rx_vtbl = {
157    .request_ep_call = rpc_request_ep,
158};
159
160static struct devif_test_rx_vtbl rx_vtbl = {
161    .request_ep_call = request_ep,
162};
163
164
165static void export_cb(void *st, errval_t err, iref_t iref)
166{
167    printf("exported devif_test_ep: interface\n");
168    err = nameservice_register("devif_test_ep", iref);
169    assert(err_is_ok(err));
170}
171
172
173static errval_t connect_cb(void *st, struct devif_test_binding *b)
174{
175    printf("New connection on devif_test_ep interface\n");
176    b->rx_vtbl = rx_vtbl;
177    b->rpc_rx_vtbl = rpc_rx_vtbl;
178    b->st = st;
179    return SYS_ERR_OK;
180}
181
182int main(int argc, char *argv[])
183{
184    uint64_t id;
185    errval_t err;
186    struct descq_func_pointer* f = malloc(sizeof(struct descq_func_pointer));
187    assert(f != NULL);
188
189    f->notify = notify;
190    f->create = create;
191    f->destroy = destroy;
192    f->reg = reg;
193    f->dereg = dereg;
194    f->control = control;
195
196    err = descq_create((struct descq**)&descq, DESCQ_DEFAULT_SIZE, "test_queue",
197                       true, &id, f);
198    if (err_is_fail(err)) {
199        USER_PANIC("Allocating debug q failed \n");
200    }
201
202    err = devif_test_export(&descq, export_cb, connect_cb, get_default_waitset(),
203                            IDC_BIND_FLAGS_DEFAULT);
204    if (err_is_fail(err)) {
205        USER_PANIC("Exporting devif_test failed\n");
206    }
207
208    while(true) {
209        event_dispatch(get_default_waitset());
210    }
211}
212
213