1/**
2 * \file
3 * \brief Driver for booting the Xeon Phi Coprocessor card on a Barrelfish Host
4 */
5
6/*
7 * Copyright (c) 2014 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, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
13 */
14
15#include <barrelfish/barrelfish.h>
16#include <barrelfish/waitset.h>
17
18#include <virtio/virtio.h>
19#include <virtio/virtqueue.h>
20#include <virtio/virtqueue_host.h>
21#include <virtio/virtio_device.h>
22#include <virtio/virtio_host.h>
23#include <virtio/devices/virtio_block.h>
24
25#include "host.h"
26#include "device.h"
27#include "request.h"
28#include "service.h"
29
30struct virtio_device *host;
31
32static errval_t handle_open(struct virtio_device *vdev, uint8_t backend, struct capref *ret_frame)
33{
34    assert(host);
35
36    virtio_host_get_device_cap(vdev, ret_frame);
37
38    assert(!capref_is_null(*ret_frame));
39
40    return SYS_ERR_OK;
41}
42
43static errval_t handle_add(struct virtio_device *vdev, struct capref ring,
44                    uint16_t ndesc, uint8_t buf_bits,uint16_t vq_id)
45{
46    debug_printf("handle_add\n");
47    return SYS_ERR_OK;
48}
49
50
51static struct virtio_host_cb host_cb = {
52  .open = handle_open,
53  .add = handle_add
54};
55
56static void virtq_do_work(struct virtqueue_host *vqh,
57                   void *arg,
58                   struct virtio_host_buf *buf,
59                   uint16_t idx)
60{
61    debug_printf("virtq_do_work");
62
63
64
65    virtio_vq_host_desc_enqueue(vqh, buf, idx);
66}
67
68int main(int argc, char *argv[])
69{
70    errval_t err;
71
72    debug_printf("VirtIO block device host started.\n");
73
74    struct virtqueue_setup vq_setup =  {
75            .name = "Request Virtqueue",
76            .vring_ndesc = 16,
77            .max_indirect =0,
78            .worker_arg = NULL,
79            .worker_fn = virtq_do_work
80        };
81
82    struct virtio_device_setup setup = {
83        .features = 0xFFFFFFFFFFFFFFFF,
84        .vq_num = 1,
85        .vq_setup = &vq_setup,
86        .hc_cb = &host_cb,
87        .hc_type = VIRTIO_HOST_CHAN_FLOUNDER,
88        .backend = {
89            .type = VIRTIO_DEVICE_BACKEND_MMIO,
90            .args = {}
91        },
92        .hc_iface = VIRTIO_BLOCK_FLOUNDER_IFACE,
93        .dev_type = VIRTIO_DEVICE_TYPE_BLOCK
94    };
95
96    err = virtio_host_init(&host,
97                           &setup);
98    if (err_is_fail(err)) {
99        USER_PANIC_ERR(err, "Service initialization failed.\n");
100    }
101
102    struct waitset *ws = get_default_waitset();
103    while(1) {
104        uint8_t idle_count = 0;
105        err = virtio_host_poll_device(host);
106        if (err_is_fail(err)) {
107            if (err_no(err) == VIRTIO_ERR_DEVICE_IDLE) {
108                idle_count++;
109            } else {
110                USER_PANIC_ERR(err, "error while polling device");
111            }
112        }
113        err = event_dispatch_non_block(ws);
114        if (err_is_fail(err)) {
115            if (err_no(err) == LIB_ERR_NO_EVENT) {
116                idle_count++;
117            } else {
118                USER_PANIC_ERR(err, "error while dispatching events");
119            }
120        }
121        if (idle_count == 2) {
122            thread_yield();
123        }
124    }
125
126    debug_printf("VirtIO block device host terminated.\n");
127}
128
129