/* * Copyright (c) 2016,2017 ETH Zurich. * All rights reserved. * * This file is distributed under the terms in the attached LICENSE file. * If you do not find this file, copies can be found by writing to: * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. */ #include #include #include #include #define LOOPBACK_QUEUE_SIZE 256 struct loopback_queue { struct devq q; struct devq_buf queue[LOOPBACK_QUEUE_SIZE]; size_t head; size_t tail; size_t num_ele; }; static errval_t loopback_enqueue(struct devq* q, regionid_t rid, genoffset_t offset, genoffset_t length, genoffset_t valid_data, genoffset_t valid_length, uint64_t flags) { struct loopback_queue *lq = (struct loopback_queue *)q; if (lq->num_ele == LOOPBACK_QUEUE_SIZE) { //debug_printf("enqueue: head=%lu tail=%lu full\n", lq->head, lq->tail); return DEVQ_ERR_QUEUE_FULL; } //debug_printf("enqueue: head=%lu tail=%lu \n", lq->head, lq->tail); lq->queue[lq->head].offset = offset; // 8 lq->queue[lq->head].length = length; // 16 lq->queue[lq->head].valid_data = valid_data; // 24 lq->queue[lq->head].valid_length = valid_length; // 32 lq->queue[lq->head].flags = flags; // 40 lq->queue[lq->head].rid = rid; // 44 lq->head = (lq->head + 1) % LOOPBACK_QUEUE_SIZE; lq->num_ele++; return SYS_ERR_OK; } static errval_t loopback_dequeue(struct devq* q, regionid_t* rid, genoffset_t* offset, genoffset_t* length, genoffset_t* valid_data, genoffset_t* valid_length, uint64_t* flags) { struct loopback_queue *lq = (struct loopback_queue *)q; if (lq->num_ele == 0) { //debug_printf("dequeue: head=%lu tail=%lu emtpy\n", lq->head, lq->tail); return DEVQ_ERR_QUEUE_EMPTY; } //debug_printf("dequeue: head=%lu tail=%lu \n", lq->head, lq->tail); *offset = lq->queue[lq->tail].offset; // 8 *length = lq->queue[lq->tail].length; // 16 *valid_data = lq->queue[lq->tail].valid_data; // 24 *valid_length =lq->queue[lq->tail].valid_length; // 32 *flags = lq->queue[lq->tail].flags; // 40 *rid = lq->queue[lq->tail].rid; // 44 lq->tail = (lq->tail + 1) % LOOPBACK_QUEUE_SIZE; lq->num_ele--; return SYS_ERR_OK; } static errval_t loopback_notify(struct devq *q) { #if 0 err = devq_dequeue(q, &(buf.rid), &(buf.addr), &(buf.len), &(buf.bid), &(buf.flags)); if (err_is_fail(err)) { return err; } err = devq_enqueue(q, buf.rid, buf.addr, buf.len, buf.flags, &buf.bid); if (err_is_fail(err)) { return err; } #endif return SYS_ERR_OK; } static errval_t loopback_register(struct devq *q, struct capref cap, regionid_t region_id) { return SYS_ERR_OK; } static errval_t loopback_deregister(struct devq *q, regionid_t region_id) { return SYS_ERR_OK; } static errval_t loopback_control(struct devq *q, uint64_t request, uint64_t value, uint64_t *result) { // TODO Might have some options for loopback device? return SYS_ERR_OK; } static errval_t loopback_destroy(struct devq* q) { free((struct loopback_queue*)q); return SYS_ERR_OK; } errval_t loopback_queue_create(struct loopback_queue** q) { errval_t err; struct loopback_queue *lq = calloc(1, sizeof(struct loopback_queue)); if (lq == NULL) { return LIB_ERR_MALLOC_FAIL; } err = devq_init(&lq->q, false); if (err_is_fail(err)) { free(lq); return err; } lq->head = 0; lq->tail = 0; lq->num_ele = 0; lq->q.f.enq = loopback_enqueue; lq->q.f.deq = loopback_dequeue; lq->q.f.reg = loopback_register; lq->q.f.dereg = loopback_deregister; lq->q.f.ctrl = loopback_control; lq->q.f.notify = loopback_notify; lq->q.f.destroy = loopback_destroy; *q = lq; return SYS_ERR_OK; }