"xmplrpc",
"xmplthc",
"xomp",
- "devif_ctrl",
- "devif_data",
"xomp_gateway",
"sfn5122f",
"sfn5122f_devif"
+++ /dev/null
-/** \file
- * \brief Device Queue message interface control plane
- */
-
-/*
- * Copyright (c) 2016, 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, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
- */
-
-interface devif_ctrl "Device Queue Interface Control Plane" {
- /* Setup before we can create the queue on both sides */
- // in coreid is the coreid of the client side
- //
- rpc setup(in uint32 coreid, in uint64 flags, out uint64 features,
- out uint32 default_qsize, out uint32 default_bufsiz,
- out bool reconnect, out String reconnect_name[256]);
-
- /* Create a device queue */
- rpc create(in cap rx, in cap tx, in uint64 flags,
- in uint64 size, out errval err);
-
-
- /* Destroy a device queue */
- rpc destroy();
-
- /* Add a memory region to the device queue
- cann not use register as name since it will be a problem
- with compiling it */
- rpc reg(in cap mem, in uint32 region_id, out errval err);
- rpc dereg(in uint32 region_id, out errval err);
-
- /* Control messages to the other end */
- rpc control(in uint64 cmd, in uint64 value, out errval err);
-
-};
+++ /dev/null
-/** \file
- * \brief Device Queue message interface data plane
- */
-
-/*
- * Copyright (c) 2016, 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, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
- */
-
-interface devif_data "Device Queue Interface Data Plane" {
-
- /* Notify other end of the queue about new entries */
- message notify(uint8 num_slots);
-
-};
--- /dev/null
+/*
+ * Copyright (c) 2016 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, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
+ */
+#ifndef SFN5122F_DEVIF_H_
+#define SFN5122F_DEVIF_H_ 1
+
+struct sfn5122f_queue;
+
+errval_t sfn5122f_queue_create(struct sfn5122f_queue** q, bool userspace, bool interrupts);
+errval_t sfn5122f_queue_destroy(struct sfn5122f_queue* q);
+#endif
#include <barrelfish/barrelfish.h>
-#define MAX_DEVICE_NAME 256
-
-#define ENDPOINT_TYPE_FORWARD 0x1
-#define ENDPOINT_TYPE_BLOCK 0x3
-#define ENDPOINT_TYPE_DEVICE 0x4
-#define ENDPOINT_TYPE_DIRECT 0x5
-
-// the user side of the queue
-#define ENDPOINT_TYPE_USER 0xF
-// only internal?
-#define ENDPOINT_TYPE_FORWARD_TX 0x11
-
-
#define DEVQ_BUF_FLAG_TX 0x1
#define DEVQ_BUF_FLAG_RX 0x2
#define DEVQ_BUF_FLAG_TX_LAST 0x4
-#define DEVQ_SETUP_FLAGS_DIRECT 0x1
-
-#define DEVQ_FEATURE_DIRECT 0x1
typedef uint32_t regionid_t;
typedef uint32_t bufferid_t;
+
struct devq;
+struct region_pool;
+// For convinience reason buffer descritpion in one struct
struct devq_buf{
regionid_t rid; // 4
bufferid_t bid; // 8
* Backend function definitions
* ===========================================================================
*/
+// Creation and Destruction of queues is device specific
-// These functions must be implemented by the driver which is using the library
-
- /**
- * @brief Setup function called on the device side
- *
- * @param coreid The core the client side is running on
- * @param flags Flags to prepare for create
- * @param features Return pointer to the features of the device
- * @param default_qsize Return pointer to the default hardware device
- * queue size
- * @param default_bufsize Return pointer to the default buffer size used by the
- * device
- * @param reconnect Return pointer to a bool that inicates if the other
- * other endpoint has to reconnect to another serivce
- * (i.e. reconnect from device_manager to queue_manager)
- * @param name String of the service to reconnect to
- *
- * @returns error on failure or SYS_ERR_OK on success
- */
-typedef errval_t (*devq_setup_t)(uint32_t coreid, uint64_t flags,
- uint64_t *features, uint32_t* default_qsize,
- uint32_t* default_bufsize, bool* reconnect, char* name);
-
- /**
- * @brief Create function that initializes the queue on the device side, or
- * for direct queues get all the necessary state so that direct function calls
- * to the hardware registers can be used. To set this state up,
- * communication to other services might be necessary (e.g. device_manager).
- * The pointer to the device specific state can be aquired by devq_get_state()
- *
- * @param q The device queue to create the device state from
- * @param flags Flags that inidicate which features the queue should have
- * enabled
- *
- * @returns error on failure or SYS_ERR_OK on success
- */
-typedef errval_t (*devq_create_t)(struct devq *q, uint64_t flags);
- /**
- * @brief Destroy function that cleans up all the resouces used by the queue.
- * Similar to create, for direct endpoint types further communication
- * is necessary in this function
- *
- * @param q The device queue to destroy
- *
- * @returns error on failure or SYS_ERR_OK on success
- */
-typedef errval_t (*devq_destroy_t)(struct devq *q);
-
/**
* @brief Notifies the device of new descriptors in the queue.
- * On a notificaton, the device can dequeue num_slots descritpors
+ * On a notificaton, the device can dequeue descritpors
* from the queue. NOTE: Does nothing for direct queues since there
* is no other endpoint to notify! (i.e. it is the same process)
*
- * @param q The device queue to destroy
+ * @param q The device queue
*
* @returns error on failure or SYS_ERR_OK on success
*/
-typedef errval_t (*devq_notify_t) (struct devq *q, uint8_t num_slots);
+typedef errval_t (*devq_notify_t) (struct devq *q);
/**
* @brief Registers a memory region. For direct queues this function
*
* @returns error on failure or SYS_ERR_OK on success
*/
-typedef errval_t (*devq_control_t)(struct devq *q, uint64_t request,
+typedef errval_t (*devq_control_t)(struct devq *q,
+ uint64_t request,
uint64_t value);
bufferid_t* buffer_id, lpaddr_t* base, size_t* length,
uint64_t* misc_flags);
+/**
+ * Represent the device queue itself
+ */
+
+
// The functions that the device driver has to export
struct devq_func_pointer {
- devq_setup_t setup;
- devq_create_t create;
- devq_destroy_t destroy;
devq_register_t reg;
devq_deregister_t dereg;
devq_control_t ctrl;
devq_dequeue_t deq;
};
-// The devif device state
-struct endpoint_state {
- // device type
- uint8_t endpoint_type;
- // name of the endpoint
- char device_name[MAX_DEVICE_NAME];
- // features of the endpoint
- uint64_t features;
- // setup function pointer
- struct devq_func_pointer f;
- // bool to check export
- bool export_done;
- // binding
- struct devif_ctrl_binding* ctrl;
- struct devif_data_binding* data;
+struct devq {
+ // Region management
+ struct region_pool* pool;
+
+ // Funciton pointers
+ struct devq_func_pointer f;
};
- /*
- * ===========================================================================
- * Device queue interface export (for devices)
- * ===========================================================================
- */
- /**
- * @brief exports the devq interface so others (client side) can connect
- *
- * @param s An endpoint state containing all the information
- * of a device including function pointers
- *
- * @returns error on failure or SYS_ERR_OK on success
- */
-
-errval_t devq_driver_export(struct endpoint_state* s);
-
-/* ===========================================================================
- * Device queue creation and destruction
- * ===========================================================================
- */
-
- /**
- * @brief creates a queue
- *
- * @param q Return pointer to the devq (handle)
- * @param end Endpoint state containing the function pointers
- * @param device_name Device name of the device to which this queue belongs
- * (Driver itself is running in a separate process)
- * @param device_type The type of the device
- * @param flags Anything you can think of that makes sense for the device
- * and its driver?
- *
- * @returns error on failure or SYS_ERR_OK on success
- */
-
-errval_t devq_create(struct devq **q,
- struct endpoint_state* end,
- char* device_name,
- uint64_t flags);
-
- /**
- * @brief destroys the device queue
- *
- * @param q The queue state to free (and the device queue to be
- shut down in the driver)
- *
- * @returns error on failure or SYS_ERR_OK on success
- */
-errval_t devq_destroy(struct devq *q);
-
-
-/*
- * ===========================================================================
- * Device specific state
- * ===========================================================================
- */
-
-/**
- * @brief allocate device specific state of size bytes
- *
- * @param q The device queue to allocate the state for
- * @param bytes Size of the state to allocate
- *
- */
-void devq_allocate_state(struct devq *q, size_t bytes);
-
-/**
- * @brief get the device specific state for a queue
- *
- * @param q The device queue to get the state for
- *
- * @returns void pointer to the defice specific state
- */
-void* devq_get_state(struct devq *q);
-
-
-/**
- * @brief set the device specific state for a queue
- *
- * @param q The device queue to get the state for
- * @param state The device specific state
- *
- */
-void devq_set_state(struct devq *q, void* state);
-
/*
* ===========================================================================
* Datapath functions
uint64_t request,
uint64_t value);
-
-errval_t devq_event_loop(struct endpoint_state* s);
#endif /* QUEUE_INTERFACE_H_ */
+++ /dev/null
-/*
- * Copyright (c) 2016 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, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
- */
-#ifndef SFN5122F_DEVIF_DIRECT_H_
-#define SFN5122F_DEVIF_DIRECT_H_ 1
-
-#include <devif/queue_interface.h>
-
-errval_t sfn5122f_create_direct(struct devq* q, uint64_t flags);
-errval_t sfn5122f_register_direct(struct devq* q, struct capref cap,
- regionid_t rid);
-errval_t sfn5122f_deregister_direct(struct devq* q, regionid_t rid);
-errval_t sfn5122f_control_direct(struct devq* q, uint64_t cmd, uint64_t value);
-errval_t sfn5122f_destroy_direct(struct devq* q);
-errval_t sfn5122f_notify_direct(struct devq* q, uint8_t num_slots);
-errval_t sfn5122f_enqueue_direct(struct devq* q, regionid_t rid, bufferid_t bid,
- lpaddr_t base, size_t len, uint64_t flags);
-errval_t sfn5122f_dequeue_direct(struct devq* q, regionid_t* rid, bufferid_t* bid,
- lpaddr_t* base, size_t* len, uint64_t* flags);
-#endif
build library {
target = "devif",
cFiles = ["queue_interface.c", "region_pool.c",
- "region.c", "desc_queue.c", "loopback_device.c"],
- addCFlags = [ "-DLIBRARY" ],
- flounderBindings = [ "devif_ctrl", "devif_data" ],
- flounderExtraBindings = [ ("devif_ctrl", ["rpcclient"]) ],
- flounderDefs = [ "devif_ctrl", "devif_data" ],
- flounderExtraDefs = [ ("devif_ctrl", ["rpcclient"]) ]
+ "region.c"],
+ addCFlags = [ "-DLIBRARY" ]
+ },
+
+ build library {
+ target = "devif_internal",
+ cFiles = ["queue_interface_internal.c", "region_pool.c",
+ "region.c"],
+ addCFlags = [ "-DLIBRARY" ]
}
]
--- /dev/null
+--------------------------------------------------------------------------
+-- Copyright (c) 2016, 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, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
+--
+-- Hakefile for lib/device_interfaces
+--
+-- Provides a general interface for device drivers.
+--
+--------------------------------------------------------------------------
+
+[
+ build library {
+ target = "devif_backend_idc",
+ cFiles = ["desc_queue.c"],
+ addCFlags = [ "-DLIBRARY" ],
+ addIncludes = [ "/lib/devif/" ]
+ }
+]
#include <devif/queue_interface.h>
#include "desc_queue.h"
#include "dqi_debug.h"
+#include "../../queue_interface_internal.h"
struct __attribute__((aligned(DESCQ_ALIGNMENT))) desc {
uint8_t pad[64];
};
-struct descq {
- // Shared memory of the queue
- size_t slots;
-
- size_t local_head;
- size_t local_tail;
- // Queue pointers
- volatile union pointer* head;
- volatile union pointer* tail;
-
- // The queue itself
- struct desc* descs;
-};
-
/**
- * @brief initialized a descriptor queue
+ * @brief Check if the descriptor queue is full
*
- * @param q Return pointer to the descriptor queue
- * @param shm Cap of the shared memory of the queue
- * @param slots Number of slots in the queue
+ * @param q The descriptor queue
*
- * @returns error on failure or SYS_ERR_OK on success
+ * @returns true if the queue is full, otherwise false
*/
-errval_t descq_init(struct descq** q,
- struct capref shm,
- size_t slots)
+static bool descq_full(struct descq* q)
{
- errval_t err;
- struct descq* tmp;
-
- // Init basic struct fields
- tmp = malloc(sizeof(struct descq));
- assert(tmp != NULL);
-
- tmp->slots = slots-2;
-
- struct frame_identity id;
- // Check if the frame is big enough
- err = invoke_frame_identify(shm, &id);
- if (err_is_fail(err)) {
- free(tmp);
- return DEVQ_ERR_DESCQ_INIT;
- }
-
- if (id.bytes < DESCQ_ALIGNMENT*slots) {
- free(tmp);
- return DEVQ_ERR_DESCQ_INIT;
- }
-
- // TODO what about the non cache coherent case?
- err = vspace_map_one_frame_attr((void**) &(tmp->head),
- slots*DESCQ_ALIGNMENT, shm,
- VREGION_FLAGS_READ_WRITE, NULL, NULL);
- if (err_is_fail(err)) {
- free(tmp);
- return DEVQ_ERR_DESCQ_INIT;
+ size_t head = q->local_head;
+ size_t tail = q->tail->value;
+ if (head >= tail) {
+ return ((q->slots - (head - tail)) == 0);
+ } else {
+ return ((q->slots - (head + q->slots - tail)) == 0);
}
-
- tmp->tail = tmp->head + 1;
- tmp->descs = (struct desc*) tmp->head + 2;
- tmp->tail->value = 0;
- tmp->head->value = 0;
- tmp->local_head = 0;
- tmp->local_tail = 0;
-
- DQI_DEBUG_QUEUE("Head=%p Tail=%p Descs=%p \n",
- tmp->head, tmp->tail, tmp->descs);
-
- *q = tmp;
- return SYS_ERR_OK;
}
-
-
/**
- * @brief Destroys a descriptor queue and frees its resources
+ * @brief Check if the descriptor queue is empty
*
* @param q The descriptor queue
*
- * @returns error on failure or SYS_ERR_OK on success
+ * @returns true if the queue is empty, otherwise false
*/
-errval_t descq_destroy(struct descq* q)
-{
- free(q);
-
- return SYS_ERR_OK;
+static bool descq_empty(struct descq* q)
+{
+ size_t head = q->head->value;
+ size_t tail = q->local_tail;
+ if (head >= tail) {
+ return ((head - tail) == 0);
+ } else {
+ return (((head + q->slots) - tail) == 0);
+ }
}
/**
*
* @returns error if queue is full or SYS_ERR_OK on success
*/
-errval_t descq_enqueue(struct descq* q,
- regionid_t region_id,
- bufferid_t buffer_id,
- lpaddr_t base,
- size_t len,
- uint64_t misc_flags)
+static errval_t descq_enqueue(struct devq* queue,
+ regionid_t region_id,
+ bufferid_t buffer_id,
+ lpaddr_t base,
+ size_t len,
+ uint64_t misc_flags)
{
+ struct descq* q = (struct descq*) queue;
if (descq_full(q)) {
return DEVQ_ERR_TX_FULL;
}
*
* @returns error if queue is empty or SYS_ERR_OK on success
*/
-errval_t descq_dequeue(struct descq* q,
- regionid_t* region_id,
- bufferid_t* buffer_id,
- lpaddr_t* base,
- size_t* len,
- uint64_t* misc_flags)
+static errval_t descq_dequeue(struct devq* queue,
+ regionid_t* region_id,
+ bufferid_t* buffer_id,
+ lpaddr_t* base,
+ size_t* len,
+ uint64_t* misc_flags)
{
+ struct descq* q = (struct descq*) queue;
if (descq_empty(q)) {
return DEVQ_ERR_RX_EMPTY;
}
return SYS_ERR_OK;
}
+
+static errval_t descq_notify(struct devq* q)
+{
+ return SYS_ERR_OK;
+}
+
+static errval_t descq_control(struct devq* q, uint64_t cmd,
+ uint64_t value)
+{
+ return SYS_ERR_OK;
+}
+
+static errval_t descq_register(struct devq* q, struct capref cap,
+ regionid_t rid)
+{
+ return SYS_ERR_OK;
+}
+
+static errval_t descq_deregister(struct devq* q, regionid_t rid)
+{
+ return SYS_ERR_OK;
+}
+
/**
* @brief Writes the local head pointer into the shared memory
* making the state of the queue visible to the other end
* @param q The descriptor queue
*
*/
-void descq_writeout_head(struct descq* q)
+/*
+static void descq_writeout_head(struct descq* q)
{
q->head->value = q->local_head;
DQI_DEBUG_QUEUE("Global_head=%lu \n", q->local_head);
}
-
+*/
/**
* @brief Writes the local tail pointer into the shared memory
* making the state of the queue visible to the other end
* @param q The descriptor queue
*
*/
-void descq_writeout_tail(struct descq* q)
+/*
+static void descq_writeout_tail(struct descq* q)
{
q->tail->value = q->local_tail;
DQI_DEBUG_QUEUE("Global_tail=%lu \n", q->local_tail);
}
-
+*/
/**
- * @brief Check if the descriptor queue is full
+ * @brief Returns the number of occupied slots in the queue
*
* @param q The descriptor queue
*
- * @returns true if the queue is full, otherwise false
+ * @returns the number of occupied slots
*/
-bool descq_full(struct descq* q)
+/*
+static size_t descq_full_slots(struct descq* q)
{
size_t head = q->local_head;
- size_t tail = q->tail->value;
+ size_t tail = q->head->value;
if (head >= tail) {
- return ((q->slots - (head - tail)) == 0);
+ return (head - tail);
} else {
- return ((q->slots - (head + q->slots - tail)) == 0);
+ return (head + q->slots) - tail;
}
}
+*/
+
+
/**
- * @brief Check if the descriptor queue is empty
+ * @brief initialized a descriptor queue
*
- * @param q The descriptor queue
+ * @param q Return pointer to the descriptor queue
+ * @param slots Number of slots in the queue
*
- * @returns true if the queue is empty, otherwise false
+ * @returns error on failure or SYS_ERR_OK on success
*/
-bool descq_empty(struct descq* q)
+errval_t devif_descq_create(struct descq** q,
+ size_t slots)
{
- size_t head = q->head->value;
- size_t tail = q->local_tail;
- if (head >= tail) {
- return ((head - tail) == 0);
- } else {
- return (((head + q->slots) - tail) == 0);
+ // TODO init frames
+ errval_t err;
+ struct descq* tmp;
+ struct capref shm;
+
+ // Init basic struct fields
+ tmp = malloc(sizeof(struct descq));
+ assert(tmp != NULL);
+
+ tmp->slots = slots-2;
+
+ struct frame_identity id;
+ // Check if the frame is big enough
+ err = invoke_frame_identify(shm, &id);
+ if (err_is_fail(err)) {
+ free(tmp);
+ return DEVQ_ERR_DESCQ_INIT;
+ }
+
+ if (id.bytes < DESCQ_ALIGNMENT*slots) {
+ free(tmp);
+ return DEVQ_ERR_DESCQ_INIT;
}
+
+ // TODO what about the non cache coherent case?
+ err = vspace_map_one_frame_attr((void**) &(tmp->head),
+ slots*DESCQ_ALIGNMENT, shm,
+ VREGION_FLAGS_READ_WRITE, NULL, NULL);
+ if (err_is_fail(err)) {
+ free(tmp);
+ return DEVQ_ERR_DESCQ_INIT;
+ }
+
+ tmp->tail = tmp->head + 1;
+ tmp->descs = (struct desc*) tmp->head + 2;
+ tmp->tail->value = 0;
+ tmp->head->value = 0;
+ tmp->local_head = 0;
+ tmp->local_tail = 0;
+
+
+ devq_init(&tmp->q);
+
+ tmp->q.f.enq = descq_enqueue;
+ tmp->q.f.deq = descq_dequeue;
+ tmp->q.f.notify = descq_notify;
+ tmp->q.f.reg = descq_register;
+ tmp->q.f.dereg = descq_deregister;
+ tmp->q.f.ctrl = descq_control;
+
+ *q = tmp;
+
+
+ return SYS_ERR_OK;
}
+
+
/**
- * @brief Returns the number of occupied slots in the queue
+ * @brief Destroys a descriptor queue and frees its resources
*
* @param q The descriptor queue
*
- * @returns the number of occupied slots
+ * @returns error on failure or SYS_ERR_OK on success
*/
-size_t descq_full_slots(struct descq* q)
-{
- size_t head = q->local_head;
- size_t tail = q->head->value;
- if (head >= tail) {
- return (head - tail);
- } else {
- return (head + q->slots) - tail;
- }
+errval_t devif_descq_destroy(struct descq* q)
+{
+ free(q);
+
+ return SYS_ERR_OK;
}
--- /dev/null
+/*
+ * Copyright (c) 2016 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, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
+ */
+#ifndef DESCQ_H_
+#define DESCQ_H_ 1
+
+
+#include <barrelfish/barrelfish.h>
+#include <devif/queue_interface.h>
+
+#define DESCQ_DEFAULT_SIZE 64
+#define DESCQ_ALIGNMENT 64
+
+struct descq {
+ struct devq q;
+ // Shared memory of the queue
+ size_t slots;
+
+ size_t local_head;
+ size_t local_tail;
+ // Queue pointers
+ volatile union pointer* head;
+ volatile union pointer* tail;
+
+ // The queue itself
+ struct desc* descs;
+};
+/**
+ * @brief initialized a descriptor queue
+ *
+ * @param q Return pointer to the descriptor queue
+ * @param slots Number of slots in the queue
+ *
+ * @returns error on failure or SYS_ERR_OK on success
+ */
+errval_t devif_descq_create(struct descq** q,
+ size_t slots);
+
+/**
+ * @brief Destroys a descriptor queue and frees its resources
+ *
+ * @param q The descriptor queue
+ *
+ * @returns error on failure or SYS_ERR_OK on success
+ */
+errval_t devif_descq_destroy(struct descq* q);
+
+
+#endif /* DESCQ_H_ */
--- /dev/null
+--------------------------------------------------------------------------
+-- Copyright (c) 2016, 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, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
+--
+-- Hakefile for lib/device_interfaces
+--
+-- Solarflare backend implementation
+--
+--------------------------------------------------------------------------
+
+ [
+ build library { target = "devif_backend_solarflare",
+ cFiles = [ "devif_backend_solarflare.c", "helper.c"],
+ flounderBindings = [ "sfn5122f_devif"],
+ flounderExtraBindings = [ ("sfn5122f_devif", ["rpcclient"])],
+ flounderDefs = [ "sfn5122f_devif" ],
+ flounderExtraDefs = [ ("sfn5122f_devif",["rpcclient"]) ],
+ mackerelDevices = [ "sfn5122f", "sfn5122f_q"],
+ addLibraries = libDeps ["pci", "skb", "devif_internal"],
+ addIncludes = ["/lib/devif/"]
+ }
+ ]
+
+
--- /dev/null
+/*
+ * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, 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, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <barrelfish/barrelfish.h>
+#include <barrelfish/waitset.h>
+#include <barrelfish/nameservice_client.h>
+#include <devif/queue_interface.h>
+#include <if/sfn5122f_devif_defs.h>
+#include <if/sfn5122f_devif_rpcclient_defs.h>
+#include <devif/backends/net/sfn5122f_devif.h>
+#include "../../../queue_interface_internal.h"
+#include "hw_queue.h"
+#include "helper.h"
+
+#define DEBUG_SFN
+#ifdef DEBUG_SFN
+ #define DEBUG_QUEUE(x...) printf("sfn5122f_q : " x)
+#else
+ #define DEBUG_QUEUE(x...) do {} while (0)
+#endif
+
+
+// TX Queue
+#define TX_ENTRIES 2048
+#define RX_ENTRIES 2048
+// Event Queue
+#define EV_CODE_RX 0
+#define EV_CODE_TX 2
+#define EV_CODE_DRV 5
+#define EV_CODE_DRV_GEN 7
+#define EV_CODE_USER 8
+#define EV_CODE_MCDI 12
+#define EV_CODE_GLOBAL 6
+
+#define BUF_SIZE 4096
+
+/* for each TX/RX entry one entry plus an additonal 2 for mcdi completion
+and link state events */
+#define EV_ENTRIES 4096
+
+/** Misc */
+static errval_t update_rxtail(struct sfn5122f_queue* q, size_t tail)
+{
+ assert(q->device != NULL);
+ uint64_t reg = 0;
+
+ reg = sfn5122f_rx_desc_upd_reg_hi_rx_desc_wptr_insert(reg, tail);
+ /* don't want to push an additional rx descriptor with the write pointer */
+ reg = sfn5122f_rx_desc_upd_reg_hi_rx_desc_push_cmd_insert(reg, 0);
+ /* the lower register will be ignored */
+ sfn5122f_rx_desc_upd_reg_lo_wr(q->device, q->id, 0);
+ sfn5122f_rx_desc_upd_reg_hi_wr(q->device, q->id, reg);
+
+ return SYS_ERR_OK;
+}
+
+static errval_t update_txtail(struct sfn5122f_queue* q, size_t tail)
+{
+ assert(q->device != NULL);
+ uint64_t reg = 0;
+ reg = sfn5122f_tx_desc_upd_reg_hi_tx_desc_wptr_insert(reg, tail);
+ /* don't want to push an additional tx descriptor with the write pointer */
+ reg = sfn5122f_tx_desc_upd_reg_hi_tx_desc_push_cmd_insert(reg, 0);
+ reg = sfn5122f_tx_desc_upd_reg_hi_tx_desc_insert(reg, 0);
+
+ /* the lower register will be ignored */
+ sfn5122f_tx_desc_upd_reg_lo_wr(q->device, q->id, 0);
+ sfn5122f_tx_desc_upd_reg_hi_wr(q->device, q->id, reg);
+ return SYS_ERR_OK;
+}
+
+static void bind_cb(void *st, errval_t err, struct sfn5122f_devif_binding *b)
+{
+
+ struct sfn5122f_queue* queue = st;
+ b->st = queue;
+ // Initi RPC client
+
+ queue->b = b;
+ queue->rpc = malloc(sizeof(struct sfn5122f_devif_rpc_client));
+ assert(queue->rpc != NULL);
+
+ err = sfn5122f_devif_rpc_client_init(queue->rpc, b);
+ if (err_is_fail(err)) {
+ free(queue->rpc);
+ }
+
+ queue->bound = true;
+}
+
+
+static errval_t sfn5122f_register(struct devq* q, struct capref cap,
+ regionid_t rid)
+{
+ uint64_t buftbl_idx = 0;
+ errval_t err, err2;
+ struct frame_identity id;
+
+ struct sfn5122f_queue* queue = (struct sfn5122f_queue*) q;
+ err = queue->rpc->vtbl.register_region(queue->rpc, queue->id, cap,
+ &buftbl_idx, &err2);
+ if (err_is_fail(err) || err_is_fail(err2)) {
+ err = err_is_fail(err) ? err: err2;
+ return err;
+ }
+
+ err = invoke_frame_identify(cap, &id);
+ if (err_is_fail(err)) {
+ return err;
+ }
+
+ // Setup datastructure for translating region ID to buffer table entry id
+ // Currently only a linked list
+ struct region_entry* entry = malloc(sizeof(struct region_entry));
+ entry->rid = rid;
+ entry->phys = id.base;
+ entry->size = id.bytes;
+ entry->cap = cap;
+ entry->buftbl_idx = buftbl_idx;
+ entry->next = NULL;
+
+ struct region_entry* cur = queue->regions;
+
+ if (cur == NULL) {
+ queue->regions = entry;
+ return SYS_ERR_OK;
+ }
+
+ while (cur->next != NULL) {
+ cur = cur->next;
+ }
+
+ cur->next = entry;
+
+ return SYS_ERR_OK;
+}
+
+static errval_t sfn5122f_deregister(struct devq* q, regionid_t rid)
+{
+ errval_t err, err2;
+
+ struct sfn5122f_queue* queue = (struct sfn5122f_queue*) q;
+
+ // find region and translate to buftlb entry
+ struct region_entry* cur = queue->regions;
+
+ if (cur == NULL) {
+ return SFN_ERR_DEREGISTER_REGION;
+ }
+
+ while (cur->next != NULL && cur->rid != rid) {
+ cur = cur->next;
+ }
+
+ // do rpc do inform carddriver to remove buftbl entries
+ err = queue->rpc->vtbl.deregister_region(queue->rpc, cur->buftbl_idx, cur->size,
+ &err2);
+ if (err_is_fail(err) || err_is_fail(err2)) {
+ err = err_is_fail(err) ? err: err2;
+ return err;
+ }
+
+ return SYS_ERR_OK;
+}
+
+
+static errval_t sfn5122f_control(struct devq* q, uint64_t cmd, uint64_t value)
+{
+ return SYS_ERR_OK;
+}
+
+
+static errval_t sfn5122f_notify(struct devq* q)
+{
+ return SYS_ERR_OK;
+}
+
+static errval_t enqueue_rx_buf(struct sfn5122f_queue* q, regionid_t rid,
+ bufferid_t bid, lpaddr_t base, size_t len,
+ uint64_t flags)
+{
+
+ DEBUG_QUEUE("Enqueueing RX buf \n");
+ // check if there is space
+ if (sfn5122f_queue_free_rxslots(q) == 0) {
+ printf("SFN5122F_%d: Not enough space in RX ring, not adding buffer\n",
+ q->id);
+ return SFN_ERR_ENQUEUE;
+ }
+
+ // find region
+ struct region_entry* entry = q->regions;
+
+ while((entry->next != NULL) && (entry->rid != rid)) {
+ entry = entry->next;
+ }
+
+ if (entry == NULL) {
+ return SFN_ERR_ENQUEUE;
+ }
+
+ // compute buffer table entry of the rx buffer and the within it offset
+ uint64_t buftbl_idx = entry->buftbl_idx + (bid/BUF_SIZE);
+ uint16_t offset = bid & 0x00000FFF;
+
+
+ DEBUG_QUEUE("RX_BUF tbl_idx=%lu offset=%d flags=%lu \n",
+ buftbl_idx, offset, flags);
+ sfn5122f_queue_add_user_rxbuf_devif(q, buftbl_idx, offset,
+ rid, bid, base, len, flags);
+ sfn5122f_queue_bump_rxtail(q);
+ return SYS_ERR_OK;
+}
+
+
+static errval_t enqueue_tx_buf(struct sfn5122f_queue* q, regionid_t rid,
+ bufferid_t bid, lpaddr_t base, size_t len,
+ uint64_t flags)
+{
+ DEBUG_QUEUE("Enqueueing TX buf \n");
+ // check if there is space
+ if (sfn5122f_queue_free_txslots(q) == 0) {
+ printf("SFN5122F_%d: Not enough space in TX ring, not adding buffer\n",
+ q->id);
+ return SFN_ERR_ENQUEUE;
+ }
+
+ // find region
+ struct region_entry* entry = q->regions;
+
+ while((entry->next != NULL) && (entry->rid != rid)) {
+ entry = entry->next;
+ }
+
+ if (entry == NULL) {
+ return SFN_ERR_ENQUEUE;
+ }
+
+ // compute buffer table entry of the rx buffer and the within it offset
+ uint64_t buftbl_idx = entry->buftbl_idx + (bid/BUF_SIZE);
+ uint16_t offset = bid & 0x00000FFF;
+
+ DEBUG_QUEUE("TX_BUF tbl_idx=%lu offset=%d flags=%lu \n", buftbl_idx, offset,
+ flags);
+ sfn5122f_queue_add_user_txbuf_devif(q, buftbl_idx, offset,
+ rid, bid, base, len, flags);
+ sfn5122f_queue_bump_txtail(q);
+ return SYS_ERR_OK;
+}
+
+
+static errval_t sfn5122f_enqueue(struct devq* q, regionid_t rid, bufferid_t bid,
+ lpaddr_t base, size_t len, uint64_t flags)
+{
+ errval_t err;
+
+ struct sfn5122f_queue* queue = (struct sfn5122f_queue*) q;
+ if (flags & DEVQ_BUF_FLAG_RX) {
+ err = enqueue_rx_buf(queue, rid, bid, base, len, flags);
+ if (err_is_fail(err)) {
+ return err;
+ }
+ } else if (flags & DEVQ_BUF_FLAG_TX) {
+ err = enqueue_tx_buf(queue, rid, bid, base, len, flags);
+ if (err_is_fail(err)) {
+ return err;
+ }
+ }
+
+ return SYS_ERR_OK;
+}
+
+static errval_t sfn5122f_dequeue(struct devq* q, regionid_t* rid, bufferid_t* bid,
+ lpaddr_t* base, size_t* len, uint64_t* flags)
+{
+ uint8_t ev_code;
+ bool exit = false;
+ errval_t err;
+
+ struct sfn5122f_queue* queue = (struct sfn5122f_queue*) q;
+
+ while(!exit) {
+ ev_code = sfn5122f_get_event_code(queue);
+ switch(ev_code){
+ case EV_CODE_RX:
+ // TODO multiple packets
+ err = sfn5122f_queue_handle_rx_ev_devif(queue, rid, bid, base,
+ len, flags);
+ exit = true;
+ if (err_is_ok(err)) {
+ DEBUG_QUEUE(" RX_EV Q_ID: %d len %ld \n", queue->id, *len);
+ }
+ sfn5122f_queue_bump_evhead(queue);
+ break;
+ case EV_CODE_TX:
+ err = sfn5122f_queue_handle_tx_ev_devif(queue, rid, bid, base,
+ len, flags);
+ if (err_is_ok(err)) {
+ DEBUG_QUEUE("TX EVENT OK %d \n", queue->id);
+ } else {
+ DEBUG_QUEUE("TX EVENT ERR %d \n", queue->id);
+ }
+
+ exit = true;
+ sfn5122f_queue_bump_evhead(queue);
+ break;
+ case EV_CODE_DRV:
+ //DEBUG_QUEUE("DRIVER EVENT %d\n", qi);
+ sfn5122f_handle_drv_ev(queue, queue->id);
+ sfn5122f_queue_bump_evhead(queue);
+ break;
+ case EV_CODE_DRV_GEN:
+ DEBUG_QUEUE("DRIVER GENERATED EVENT \n");
+ sfn5122f_queue_bump_evhead(queue);
+ break;
+ case EV_CODE_USER:
+ DEBUG_QUEUE("USER EVENT \n");
+ sfn5122f_queue_bump_evhead(queue);
+ break;
+ case EV_CODE_MCDI:
+ //DEBUG_QUEUE("MCDI EVENT \n");
+ sfn5122f_queue_handle_mcdi_event(queue);
+ sfn5122f_queue_bump_evhead(queue);
+ break;
+ case EV_CODE_GLOBAL:
+ DEBUG_QUEUE("GLOBAL EVENT \n");
+ sfn5122f_queue_bump_evhead(queue);
+ break;
+ }
+ sfn5122f_evq_rptr_reg_wr(queue->device, queue->id,
+ queue->ev_head);
+ }
+
+ return err;
+}
+
+/**
+ * Public functions
+ *
+ */
+
+errval_t sfn5122f_queue_create(struct sfn5122f_queue** q, bool userlevel,
+ bool interrupts)
+{
+
+ errval_t err;
+ struct capref tx_frame, rx_frame, ev_frame;
+ size_t tx_size, rx_size, ev_size;
+ void *tx_virt, *rx_virt, *ev_virt;
+ struct sfn5122f_queue* queue;
+ struct frame_identity id;
+
+ struct sfn5122f_queue_ops ops = {
+ .update_txtail = update_txtail,
+ .update_rxtail = update_rxtail
+ };
+
+ /* Allocate memory for descriptor rings
+ No difference for userspace networking*/
+ tx_size = sfn5122f_q_tx_ker_desc_size * TX_ENTRIES;
+ tx_virt = alloc_map_frame(VREGION_FLAGS_READ_WRITE, tx_size, &tx_frame);
+ if (tx_virt == NULL) {
+ return SFN_ERR_ALLOC_QUEUE;
+ }
+
+ rx_size = sfn5122f_q_rx_user_desc_size * RX_ENTRIES;
+ rx_virt = alloc_map_frame(VREGION_FLAGS_READ_WRITE, rx_size, &rx_frame);
+ if (rx_virt == NULL) {
+ return SFN_ERR_ALLOC_QUEUE;
+ }
+
+ ev_size = sfn5122f_q_event_entry_size * EV_ENTRIES;
+ ev_virt = alloc_map_frame(VREGION_FLAGS_READ_WRITE, ev_size, &ev_frame);
+ if (ev_virt == NULL) {
+ return SFN_ERR_ALLOC_QUEUE;
+ }
+
+ // Init queue
+ queue = sfn5122f_queue_init(tx_virt, TX_ENTRIES, rx_virt, RX_ENTRIES,
+ ev_virt, EV_ENTRIES, &ops, NULL, true);
+
+ queue->bound = false;
+
+ iref_t iref;
+ const char *name = "sfn5122f_sfn5122fmng_devif";
+
+ // Connect to solarflare card driver
+ err = nameservice_blocking_lookup(name, &iref);
+ if (err_is_fail(err)) {
+ return err;
+ }
+
+ err = sfn5122f_devif_bind(iref, bind_cb, q, get_default_waitset(),
+ 1);
+
+ if (err_is_fail(err)) {
+ return err;
+ }
+
+ // wait until bound
+ while(!queue->bound) {
+ event_dispatch(get_default_waitset());
+ }
+
+ errval_t err2;
+ struct capref regs;
+ // Inform card driver about new queue and get the registers/queue id
+ err = queue->rpc->vtbl.create_queue(queue->rpc, true, rx_frame, tx_frame, ev_frame,
+ &queue->id, ®s, &err2);
+ if (err_is_fail(err) || err_is_fail(err2)) {
+ err = err_is_fail(err) ? err: err2;
+ return err;
+ }
+
+ void* va;
+
+ err = invoke_frame_identify(regs, &id);
+ if (err_is_fail(err)) {
+ return err;
+ }
+
+ err = vspace_map_one_frame_attr(&va, id.bytes, regs,
+ VREGION_FLAGS_READ_WRITE, NULL, NULL);
+ if (err_is_fail(err)) {
+ return err;
+ }
+
+ queue->device = malloc(sizeof(sfn5122f_t));
+ sfn5122f_initialize(queue->device, va);
+
+ err = devq_init(&queue->q);
+ if (err_is_fail(err)) {
+ return err;
+ }
+
+ queue->q.f.enq = sfn5122f_enqueue;
+ queue->q.f.deq = sfn5122f_dequeue;
+ queue->q.f.reg = sfn5122f_register;
+ queue->q.f.dereg = sfn5122f_deregister;
+ queue->q.f.ctrl = sfn5122f_control;
+ queue->q.f.notify = sfn5122f_notify;
+
+ *q = queue;
+
+ return SYS_ERR_OK;
+}
+
+errval_t sfn5122f_queue_destroy(struct sfn5122f_queue* q)
+{
+ USER_PANIC("NIY\n");
+ return SYS_ERR_OK;
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2007-2011, 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, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#include "helper.h"
+
+#include <skb/skb.h>
+#include <stdio.h>
+#include <stdint.h>
+
+
+/* allocate a single frame, mapping it into our vspace with given attributes */
+void* alloc_map_frame(vregion_flags_t attr, size_t size, struct capref *retcap)
+{
+ struct capref frame;
+ errval_t r;
+
+ r = frame_alloc(&frame, size, NULL);
+ assert(err_is_ok(r));
+ void *va;
+ r = vspace_map_one_frame_attr(&va, size, frame, attr,
+ NULL, NULL);
+ if (err_is_fail(r)) {
+ DEBUG_ERR(r, "vspace_map_one_frame failed");
+ return NULL;
+ }
+
+ if (retcap != NULL) {
+ *retcap = frame;
+ }
+
+ return va;
+}
+
+/* Get APIC id for specified core */
+errval_t get_apicid_from_core(coreid_t cid, uint8_t *apicid)
+{
+ static bool connected = false;
+ errval_t err;
+ unsigned int i;
+
+ if (!connected) {
+ err = skb_client_connect();
+ if (err_is_fail(err)) {
+ return err;
+ }
+ connected = true;
+ }
+
+ err = skb_execute_query("corename(%d,_,apic(ApicID)),write(ApicID).",
+ cid);
+ if (err_is_fail(err)) {
+ return err;
+ }
+ err = skb_read_output("%u.", &i);
+ *apicid = i;
+ return err;
+}
+
+
+/*****************************************************************************/
+/* Bitmap based allocator */
+
+
+/** Init allocator for n objects. */
+bool bmallocator_init(struct bmallocator *alloc, size_t n)
+{
+ alloc->count = n;
+ alloc->bitmap = calloc((n + BMALLOCATOR_BITS - 1) / BMALLOCATOR_BITS,
+ BMALLOCATOR_BITS / 8);
+ return alloc->bitmap != NULL;
+}
+
+/** Release memory associated with allocator. */
+void bmallocator_destroy(struct bmallocator *alloc)
+{
+ free(alloc->bitmap);
+ alloc->bitmap = NULL;
+}
+
+/** Allocate object, return index in *n if successful (return true). */
+bool bmallocator_alloc(struct bmallocator *alloc, size_t *n)
+{
+ size_t i;
+ BMALLOCATOR_TYPE bit;
+ size_t idx;
+
+ // This could be improved
+ for (i = 0; i < alloc->count; i++) {
+ bit = 1 << (i % BMALLOCATOR_BITS);
+ idx = i / BMALLOCATOR_BITS;
+
+ if (!(alloc->bitmap[idx] & bit)) {
+ alloc->bitmap[idx] |= bit;
+ *n = i;
+ return true;
+ }
+ }
+ return false;
+}
+
+/** Free object n, return value indicates if it was allocated before. */
+bool bmallocator_free(struct bmallocator *alloc, size_t n)
+{
+ bool result;
+ BMALLOCATOR_TYPE bit;
+ size_t idx;
+
+ if (n >= alloc->count) {
+ return false;
+ }
+
+ bit = (1 << (n % BMALLOCATOR_BITS));
+ idx = n / BMALLOCATOR_BITS;
+
+ result = alloc->bitmap[idx] & bit;
+ alloc->bitmap[idx] &= ~bit;
+
+ return result;
+}
--- /dev/null
+/*
+ * Copyright (c) 2007-2011, 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, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#ifndef HELPER_H_
+#define HELPER_H_
+
+#include <errors/errno.h>
+#include <barrelfish/barrelfish.h>
+#include <barrelfish/vregion.h>
+
+void* alloc_map_frame(vregion_flags_t attr, size_t size, struct capref *retcap);
+
+errval_t get_apicid_from_core(coreid_t cid, uint8_t *apicid);
+
+/* Simple bitmap-based allocator */
+#define BMALLOCATOR_BITS 8
+#define BMALLOCATOR_TYPE uint8_t
+struct bmallocator {
+ BMALLOCATOR_TYPE *bitmap;
+ size_t count;
+};
+
+/** Init allocator for n objects. */
+bool bmallocator_init(struct bmallocator *alloc, size_t n);
+/** Release memory associated with allocator. */
+void bmallocator_destroy(struct bmallocator *alloc);
+/** Allocate object, return index in *n if successful (return true). */
+bool bmallocator_alloc(struct bmallocator *alloc, size_t *n);
+/** Free object n, return value indicates if it was allocated before. */
+bool bmallocator_free(struct bmallocator *alloc, size_t n);
+
+#endif // ndef HELPER_H_
--- /dev/null
+/*
+ *Copyright (c) 2007-2011, 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, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#ifndef SFN5122F_CHANNEL_H_
+#define SFN5122F_CHANNEL_H_
+
+
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <devif/queue_interface.h>
+#include <dev/sfn5122f_q_dev.h>
+#include <dev/sfn5122f_dev.h>
+#include "helper.h"
+
+#define MTU_MAX 2048
+
+struct sfn5122f_devif_binding;
+struct sfn5122f_devif_rpc_client;
+struct sfn5122f_queue;
+
+struct sfn5122f_queue_ops {
+ errval_t (*update_txtail)(struct sfn5122f_queue*, size_t);
+ errval_t (*update_rxtail)(struct sfn5122f_queue*, size_t);
+};
+
+struct region_entry {
+ uint32_t rid;
+ lpaddr_t phys;
+ size_t size;
+ uint64_t buftbl_idx;
+ struct capref cap;
+ struct region_entry* next;
+};
+
+struct sfn5122f_queue {
+ struct devq q;
+ union {
+ sfn5122f_q_tx_user_desc_array_t* user;
+ sfn5122f_q_tx_ker_desc_array_t* ker;
+ } tx_ring;
+ struct devq_buf* tx_bufs;
+ uint16_t tx_head;
+ uint16_t tx_tail;
+ size_t tx_size;
+
+ union {
+ sfn5122f_q_rx_user_desc_array_t* user;
+ sfn5122f_q_rx_ker_desc_array_t* ker;
+ } rx_ring;
+ struct devq_buf* rx_bufs;
+ uint16_t rx_head;
+ uint16_t rx_tail;
+ uint16_t rx_size;
+
+ sfn5122f_q_event_entry_array_t* ev_ring;
+ uint32_t ev_head;
+ uint32_t ev_tail;
+ size_t ev_size;
+
+ struct sfn5122f_queue_ops ops;
+ void* opaque;
+ bool userspace;
+
+ // state for devif interface
+ struct sfn5122f_devif_binding* b;
+ struct sfn5122f_devif_rpc_client* rpc;
+ bool bound;
+
+ // Direct interface fields
+ uint16_t id;
+ sfn5122f_t *device;
+ struct region_entry* regions;
+};
+
+typedef struct sfn5122f_queue sfn5122f_queue_t;
+
+static inline sfn5122f_queue_t* sfn5122f_queue_init(void* tx,
+ size_t tx_size,
+ void* rx,
+ size_t rx_size,
+ void* ev,
+ size_t ev_size,
+ struct sfn5122f_queue_ops* ops,
+ void* opaque, bool userspace)
+{
+
+ sfn5122f_queue_t* q = malloc(sizeof(*q));
+
+ if (userspace) {
+ q->tx_ring.user = tx;
+ } else {
+ q->tx_ring.ker = tx;
+ }
+ q->tx_bufs = malloc(sizeof(struct devq_buf) * tx_size);
+ q->tx_head = 0;
+ q->tx_tail = 0;
+ q->tx_size = tx_size;
+
+ if (userspace) {
+ q->rx_ring.user = rx;
+ } else {
+ q->rx_ring.ker = rx;
+ }
+ q->rx_bufs = malloc(sizeof(struct devq_buf) * rx_size);
+ q->rx_head = 0;
+ q->rx_tail = 0;
+ q->rx_size = rx_size;
+
+ q->ev_ring = ev;
+ q->ev_head = 0;
+ q->ev_tail = 0;
+ q->ev_size = ev_size;
+ q->userspace = userspace;
+
+ q -> ops = *ops;
+ if(!userspace) {
+ q->opaque = opaque;
+ }
+
+ // Initialize ring memory with 0xff
+ if(!userspace){
+ memset(tx, 0xff, tx_size * sfn5122f_q_tx_ker_desc_size);
+ memset(rx, 0xff, rx_size * sfn5122f_q_rx_ker_desc_size);
+ }else{
+ memset(tx, 0xff, tx_size * sfn5122f_q_tx_user_desc_size);
+ memset(rx, 0xff, rx_size * sfn5122f_q_rx_user_desc_size);
+ }
+ /* all 0 is potential valid event */
+ memset(ev, 0xff, ev_size * sfn5122f_q_event_entry_size);
+ return q;
+}
+
+static inline uint8_t sfn5122f_get_event_code(sfn5122f_queue_t* queue)
+{
+ sfn5122f_q_event_entry_t ev;
+ ev = queue->ev_ring[queue->ev_head];
+ return sfn5122f_q_event_entry_ev_code_extract(ev);
+}
+
+
+static inline errval_t sfn5122f_queue_bump_txtail(sfn5122f_queue_t* q)
+{
+ return q->ops.update_txtail(q, q->tx_tail);
+}
+
+
+static inline errval_t sfn5122f_queue_bump_rxtail(sfn5122f_queue_t* q)
+{
+ return q->ops.update_rxtail(q, q->rx_tail);
+}
+
+
+static inline errval_t sfn5122f_handle_drv_ev(sfn5122f_queue_t* q, uint16_t n)
+{
+ size_t ev_head = q->ev_head;
+
+ sfn5122f_q_event_entry_t code;
+ code = q->ev_ring[ev_head];
+
+ if (sfn5122f_q_driver_ev_driver_ev_subcode_extract(code) == 2) {
+ printf("Event queue init done %d \n", n);
+ }
+
+ if (sfn5122f_q_driver_ev_driver_ev_subcode_extract(code) == 9) {
+ printf("Packet neither TCP nor UPD %d \n", n);
+ }
+
+ if (sfn5122f_q_driver_ev_driver_ev_subcode_extract(code) == 14) {
+ printf("RX error %d \n", n);
+ return SFN_ERR_RX_PKT;
+ }
+
+ if (sfn5122f_q_driver_ev_driver_ev_subcode_extract(code) == 15) {
+ printf("TX error %d \n", n);
+ return SFN_ERR_TX_PKT;
+ }
+
+ memset(code, 0xff, sfn5122f_q_event_entry_size);
+ return SYS_ERR_OK;
+
+}
+
+
+
+static inline errval_t sfn5122f_queue_handle_mcdi_event(sfn5122f_queue_t* q)
+{
+ // TODO handle different events
+ size_t ev_head = q->ev_head;
+ sfn5122f_q_event_entry_t ev;
+ uint64_t reg;
+ ev = q->ev_ring[ev_head];
+ reg = sfn5122f_q_event_entry_ev_data_extract(ev);
+ memset(ev, 0xff, sfn5122f_q_event_entry_size);
+
+ return SYS_ERR_OK;
+
+}
+
+/* RX */
+static inline int sfn5122f_queue_add_user_rxbuf_devif(sfn5122f_queue_t* q,
+ uint32_t buf_id,
+ uint16_t offset,
+ regionid_t rid,
+ bufferid_t devq_bid,
+ lpaddr_t base,
+ size_t len,
+ uint64_t flags)
+{
+ struct devq_buf* buf;
+ sfn5122f_q_rx_user_desc_t d;
+ size_t tail = q->rx_tail;
+
+ d = q->rx_ring.user[tail];
+ buf = &q->rx_bufs[tail];
+
+ buf->rid = rid;
+ buf->bid = devq_bid;
+ buf->addr = base;
+ buf->len = len;
+ buf->flags = flags;
+ sfn5122f_q_rx_user_desc_rx_user_buf_id_insert(d, buf_id);
+ sfn5122f_q_rx_user_desc_rx_user_2byte_offset_insert(d, offset >> 1);
+ q->rx_tail = (tail + 1) % q->rx_size;
+ return 0;
+}
+
+static inline int sfn5122f_queue_add_rxbuf_devif(sfn5122f_queue_t* q,
+ regionid_t rid,
+ bufferid_t bid,
+ lpaddr_t addr,
+ size_t len,
+ uint64_t flags)
+{
+ struct devq_buf* buf;
+ sfn5122f_q_rx_ker_desc_t d;
+ size_t tail = q->rx_tail;
+
+ d = q->rx_ring.ker[tail];
+
+ buf = &q->rx_bufs[tail];
+
+ buf->rid = rid;
+ buf->bid = bid;
+ buf->addr = addr;
+ buf->len = len;
+ buf->flags = flags;
+
+ sfn5122f_q_rx_ker_desc_rx_ker_buf_addr_insert(d, addr);
+ sfn5122f_q_rx_ker_desc_rx_ker_buf_region_insert(d, 0);
+ // TODO: Check size
+ sfn5122f_q_rx_ker_desc_rx_ker_buf_size_insert(d, len);
+ q->rx_tail = (tail + 1) % q->rx_size;
+ return 0;
+}
+
+static inline errval_t sfn5122f_queue_handle_rx_ev_devif(sfn5122f_queue_t* q,
+ regionid_t* rid,
+ bufferid_t* bid,
+ lpaddr_t* base,
+ size_t* len,
+ uint64_t* flags)
+{
+ /* Only one event is generated even if there is more than one
+ descriptor per packet */
+ struct devq_buf* buf;
+ size_t ev_head = q->ev_head;
+ size_t rx_head;
+ sfn5122f_q_rx_ev_t ev;
+ sfn5122f_q_rx_user_desc_t d_user = 0;
+
+ ev = q->ev_ring[ev_head];
+ rx_head = sfn5122f_q_rx_ev_rx_ev_desc_ptr_extract(ev);
+
+ buf = &q->rx_bufs[rx_head];
+
+ *rid = buf->rid;
+ *bid = buf->bid;
+ *base = buf->addr;
+ *flags = buf->flags;
+
+ if(!sfn5122f_q_rx_ev_rx_ev_pkt_ok_extract(ev)) {
+ // TODO error handling
+ q->rx_head = (rx_head + 1) % q->rx_size;
+ if (sfn5122f_q_rx_ev_rx_ev_tobe_disc_extract(ev)) {
+ // packet discared by softare -> ok
+ return SFN_ERR_RX_DISCARD;
+ }
+
+ printf("Packet not ok \n");
+ if (sfn5122f_q_rx_ev_rx_ev_buf_owner_id_extract(ev)) {
+ printf("Wrong owner \n");
+ }
+ return SFN_ERR_RX_PKT;
+ }
+
+ *len = sfn5122f_q_rx_ev_rx_ev_byte_ctn_extract(ev);
+ /* Length of 0 is treated as 16384 bytes */
+ if (*len == 0) {
+ *len = 16384;
+ }
+
+ rx_head = sfn5122f_q_rx_ev_rx_ev_desc_ptr_extract(ev);
+ d_user = q->rx_ring.user[rx_head];
+
+ buf = &q->rx_bufs[rx_head];
+
+ *rid = buf->rid;
+ *bid = buf->bid;
+ *base = buf->addr;
+ *flags = buf->flags;
+
+ memset(ev, 0xff, sfn5122f_q_event_entry_size);
+ memset(d_user, 0 , sfn5122f_q_rx_user_desc_size);
+
+ q->rx_head = (rx_head + 1) % q->rx_size;
+ return SYS_ERR_OK;
+}
+
+static inline void sfn5122f_queue_bump_evhead(sfn5122f_queue_t* q)
+{
+ q->ev_head = (q->ev_head +1) % q->ev_size;
+}
+
+static inline size_t sfn5122f_queue_free_rxslots(sfn5122f_queue_t* q)
+{
+ size_t head = q->rx_head;
+ size_t tail = q->rx_tail;
+ size_t size = q->rx_size;
+
+ if (tail >= head) {
+ return size - (tail - head) -1;
+ } else {
+ return size - (tail + size - head) -1;
+ }
+}
+
+
+/* TX */
+static inline size_t sfn5122f_queue_free_txslots(sfn5122f_queue_t* q)
+{
+ size_t head = q->tx_head;
+ size_t tail = q->tx_tail;
+ size_t size = q->tx_size;
+
+ if (tail >= head) {
+ return size - (tail - head) - 1;
+ } else {
+ return size - (tail + size - head) - 1;
+ }
+
+}
+
+static inline errval_t sfn5122f_queue_handle_tx_ev_devif(sfn5122f_queue_t* q,
+ regionid_t* rid,
+ bufferid_t* bid,
+ lpaddr_t* base,
+ size_t* len,
+ uint64_t* flags)
+{
+ /* Only one event is generated even if there is more than one
+ descriptor per packet */
+ size_t ev_head = q->ev_head;
+ size_t tx_head;
+ struct devq_buf* buf;
+ sfn5122f_q_tx_ev_t ev;
+ sfn5122f_q_tx_user_desc_t d_user= 0;
+
+ ev = q->ev_ring[ev_head];
+ tx_head = sfn5122f_q_tx_ev_tx_ev_desc_ptr_extract(ev);
+
+
+ buf = &q->tx_bufs[tx_head];
+
+ *rid = buf->rid;
+ *bid = buf->bid;
+ *base = buf->addr;
+ *flags = buf->flags;
+
+ if (sfn5122f_q_tx_ev_tx_ev_pkt_err_extract(ev)){
+ q->tx_head = (tx_head +1) % q->tx_size;
+ return SFN_ERR_TX_PKT;
+ }
+
+ if (sfn5122f_q_tx_ev_tx_ev_comp_extract(ev) == 1){
+ d_user = q->tx_ring.user[tx_head];
+
+ // reset entry event in queue
+ memset(ev, 0xff, sfn5122f_q_event_entry_size);
+ memset(d_user, 0 , sfn5122f_q_tx_user_desc_size);
+ q->tx_head = (tx_head +1) % q->tx_size;
+ }
+
+ return SYS_ERR_OK;
+}
+
+static inline int sfn5122f_queue_add_txbuf_devif(sfn5122f_queue_t* q,
+ regionid_t rid,
+ bufferid_t bid,
+ lpaddr_t base,
+ size_t len,
+ uint64_t flags)
+{
+ struct devq_buf* buf;
+ sfn5122f_q_tx_ker_desc_t d;
+ size_t tail = q->tx_tail;
+
+ d = q->tx_ring.ker[tail];
+
+ buf = &q->tx_bufs[tail];
+
+ bool last = flags & DEVQ_BUF_FLAG_TX_LAST;
+ buf->rid = rid;
+ buf->bid = bid;
+ buf->addr = base;
+ buf->len = len;
+ buf->flags = flags;
+
+ sfn5122f_q_tx_ker_desc_tx_ker_buf_addr_insert(d, base);
+ sfn5122f_q_tx_ker_desc_tx_ker_byte_count_insert(d, len);
+ sfn5122f_q_tx_ker_desc_tx_ker_cont_insert(d, !last);
+ sfn5122f_q_tx_ker_desc_tx_ker_buf_region_insert(d, 0);
+
+ __sync_synchronize();
+
+ q->tx_tail = (tail + 1) % q->tx_size;
+ return 0;
+}
+
+
+static inline int sfn5122f_queue_add_user_txbuf_devif(sfn5122f_queue_t* q,
+ uint64_t buftbl_idx,
+ uint64_t offset,
+ regionid_t rid,
+ bufferid_t devq_bid,
+ lpaddr_t base,
+ size_t len,
+ uint64_t flags)
+{
+ sfn5122f_q_tx_user_desc_t d;
+ struct devq_buf* buf;
+ size_t tail = q->tx_tail;
+
+ d = q->tx_ring.ker[tail];
+ buf = &q->tx_bufs[tail];
+
+ bool last = flags & DEVQ_BUF_FLAG_TX_LAST;
+ buf->rid = rid;
+ buf->bid = devq_bid;
+ buf->addr = base;
+ buf->len = len;
+ buf->flags = flags;
+
+ sfn5122f_q_tx_user_desc_tx_user_sw_ev_en_insert(d, 0);
+ sfn5122f_q_tx_user_desc_tx_user_cont_insert(d, !last);
+ sfn5122f_q_tx_user_desc_tx_user_byte_cnt_insert(d, len);
+ sfn5122f_q_tx_user_desc_tx_user_buf_id_insert(d, buftbl_idx);
+ sfn5122f_q_tx_user_desc_tx_user_byte_ofs_insert(d, offset);
+
+ __sync_synchronize();
+
+ q->tx_tail = (tail + 1) % q->tx_size;
+ return 0;
+}
+
+#endif //ndef SFN5122F_CHANNEL_H_
+
+++ /dev/null
-/*
- * Copyright (c) 2016 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, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
- */
-#ifndef DESCQ_H_
-#define DESCQ_H_ 1
-
-
-#include <barrelfish/barrelfish.h>
-#include <devif/queue_interface.h>
-
-#define DESCQ_DEFAULT_SIZE 64
-#define DESCQ_ALIGNMENT 64
-
-struct descq;
-/**
- * @brief initialized a descriptor queue
- *
- * @param q Return pointer to the descriptor queue
- * @param shm Cap to the the shared memory of the queue
- * @param slots Number of slots in the queue
- *
- * @returns error on failure or SYS_ERR_OK on success
- */
-errval_t descq_init(struct descq** q,
- struct capref shm,
- size_t slots);
-
-/**
- * @brief Destroys a descriptor queue and frees its resources
- *
- * @param q The descriptor queue
- *
- * @returns error on failure or SYS_ERR_OK on success
- */
-errval_t descq_destroy(struct descq* q);
-
-/**
- * @brief Enqueue a descriptor (as seperate fields)
- * into the descriptor queue
- *
- * @param q The descriptor queue
- * @param region_id Region id of the enqueued buffer
- * @param buffer_id Buffer id of the buffer
- * @param base Physical address of hte buffer
- * @param len Lenght of the buffer
- * @param misc_flags Miscellaneous flags
- *
- * @returns error if queue is full or SYS_ERR_OK on success
- */
-errval_t descq_enqueue(struct descq* q,
- regionid_t region_id,
- bufferid_t buffer_id,
- lpaddr_t base,
- size_t len,
- uint64_t misc_flags);
-
-/**
- * @brief Dequeue a descriptor (as seperate fields)
- * from the descriptor queue
- *
- * @param q The descriptor queue
- * @param region_id Return pointer to the region id of
- * the denqueued buffer
- * @param buffer_id Return pointer to the buffer id of the buffer
- * @param base Return pointer to the physical address
- * of the buffer
- * @param len Return pointer to the lenght of the buffer
- * @param misc_flags Return pointer to miscellaneous flags
- *
- * @returns error if queue is empty or SYS_ERR_OK on success
- */
-errval_t descq_dequeue(struct descq* q,
- regionid_t* region_id,
- bufferid_t* buffer_id,
- lpaddr_t* base,
- size_t* len,
- uint64_t* misc_flags);
-
-/**
- * @brief Writes the local head pointer into the shared memory
- * making the state of the queue visible to the other end
- *
- * @param q The descriptor queue
- *
- */
-void descq_writeout_head(struct descq* q);
-/**
- * @brief Writes the local tail pointer into the shared memory
- * making the state of the queue visible to the other end
- *
- * @param q The descriptor queue
- *
- */
-void descq_writeout_tail(struct descq* q);
-
-/**
- * @brief Check if the descriptor queue is full
- *
- * @param q The descriptor queue
- *
- * @returns true if the queue is full, otherwise false
- */
-bool descq_full(struct descq* q);
-
-/**
- * @brief Check if the descriptor queue is empty
- *
- * @param q The descriptor queue
- *
- * @returns true if the queue is empty, otherwise false
- */
-bool descq_empty(struct descq* q);
-
-/**
- * @brief Returns the number of occupied slots in the queue
- *
- * @param q The descriptor queue
- *
- * @returns the number of occupied slots
- */
-size_t descq_full_slots(struct descq* q);
-
-#endif /* DESCQ_H_ */
#include <barrelfish/deferred.h>
#include <barrelfish/nameservice_client.h>
#include <devif/queue_interface.h>
-#include <if/devif_ctrl_defs.h>
-#include <if/devif_ctrl_rpcclient_defs.h>
-#include <if/devif_data_defs.h>
#include "region_pool.h"
-#include "desc_queue.h"
#include "dqi_debug.h"
-#define FORWARD_PREFIX_LEN 8
-
-enum devq_state {
- DEVQ_STATE_UNINITIALIZED,
- DEVQ_STATE_BINDING_CTRL,
- DEVQ_STATE_BINDING_DATA,
- DEVQ_STATE_CONNECTED,
- DEVQ_STATE_RECONNECTING,
- DEVQ_STATE_READY,
-};
-
-/**
- * Represent the device queue itself
- */
-struct devq {
- // Endpoint state
- struct endpoint_state* end;
- // The name of the endpoint on the other side
- char endpoint_name[MAX_DEVICE_NAME];
- // Region management
- struct region_pool* pool;
-
- // queues
- struct capref rx_cap;
- struct capref tx_cap;
-
- struct descq* rx;
- struct descq* tx;
-
- // out of band communication to endpoint
- struct devif_ctrl_binding* ctrl;
- struct devif_ctrl_rpc_client* ctrl_rpc;
- struct devif_data_binding* data;
-
- // state of the queue
- enum devq_state state;
- // pointer to queue specific state
- void* q;
-
- // setup
- bool reconnect;
- char reconnect_name[MAX_DEVICE_NAME];
- // rpc error
- errval_t err;
-
- // default device state (mostly for direct interface)
- uint32_t q_size;
- uint32_t buf_size;
-
- //TODO Other state needed ...
-};
-
-
-// Prototypes
-// Init functions
-static errval_t devq_init_forward(struct devq *q, uint64_t flags);
-static errval_t devq_init_user(struct devq *q, uint64_t flags);
-static errval_t devq_init_direct(struct devq *q, uint64_t flags);
-
-static errval_t devq_init_descqs(struct devq *q, struct capref rx,
- struct capref tx, size_t slots);
-
-// Message Passing functions
-// ...
-
-static void mp_setup_request(struct devif_ctrl_binding* b, uint32_t coreid,
- uint64_t flags)
-{
- DQI_DEBUG("setup_request coreid=%d flags=%lu\n", coreid, flags);
- errval_t err;
- uint64_t features;
- uint32_t default_qsize, default_bufsize;
- char reconnect_name[MAX_DEVICE_NAME];
- bool reconnect = false;
-
- struct endpoint_state* state = (struct endpoint_state*) b->st;
-
- // Call setup function on local device
- if (state->endpoint_type == ENDPOINT_TYPE_FORWARD) {
- // TODO forward default size etc.
- reconnect = false;
- } else {
-
- err = state->f.setup(coreid, flags, &features, &default_qsize,
- &default_bufsize, &reconnect, reconnect_name);
- assert(err_is_ok(err));
- }
-
-
- err = b->tx_vtbl.setup_response(b, NOP_CONT, features, default_qsize,
- default_bufsize, reconnect, reconnect_name);
- assert(err_is_ok(err));
-
-}
-
-
-static void mp_create(struct devif_ctrl_binding* b, struct capref rx,
- struct capref tx, uint64_t flags, uint64_t size)
-{
- errval_t err;
- struct endpoint_state* state = (struct endpoint_state* ) b->st;
-
- struct devq* q;
-
- // Create the device queue
- // TODO we might need to know the name of the
- // endpoint that connected to the device
-
- if (state->endpoint_type != ENDPOINT_TYPE_FORWARD) {
- err = devq_create(&q, state, "", 0);
- if (err_is_fail(err)) {
- err = b->tx_vtbl.create_response(b, NOP_CONT, err);
- assert(err_is_ok(err));
- }
- } else {
-
- struct devq* q2;
- state->endpoint_type = ENDPOINT_TYPE_DEVICE;
- err = devq_create(&q, state, "", 0);
- if (err_is_fail(err)) {
- err = b->tx_vtbl.create_response(b, NOP_CONT, err);
- assert(err_is_ok(err));
- }
-
- state->endpoint_type = ENDPOINT_TYPE_USER;
- err = devq_create(&q2, state, state->device_name+FORWARD_PREFIX_LEN, 0);
- if (err_is_fail(err)) {
- err = b->tx_vtbl.create_response(b, NOP_CONT, err);
- assert(err_is_ok(err));
- }
- state->endpoint_type = ENDPOINT_TYPE_FORWARD;
- q->q = q2;
- }
-
- q->end = state;
-
- // Init queues (tx/rx are switched)
- err = devq_init_descqs(q, tx, rx, size);
- if (err_is_fail(err)) {
- // TODO deallocate queues
- err = b->tx_vtbl.create_response(b, NOP_CONT, err);
- assert(err_is_ok(err));
- }
-
- // Call create on device
- err = q->end->f.create(q, flags);
- if (err_is_fail(err)) {
- err = b->tx_vtbl.create_response(b, NOP_CONT, err);
- assert(err_is_ok(err));
- }
-
- DQI_DEBUG("create_request %p \n", q);
- // Send response
- err = b->tx_vtbl.create_response(b, NOP_CONT, err);
- assert(err_is_ok(err));
- b->st = q;
- q->data->st = q;
-}
-
-static void mp_register(struct devif_ctrl_binding* b, struct capref mem,
- regionid_t region_id)
-{
- errval_t err;
- struct devq* q = (struct devq*) b->st;
-
- if (q->end->endpoint_type == ENDPOINT_TYPE_FORWARD) {
- // forward directly
- assert(!capcmp(mem, NULL_CAP));
- struct devq* tx = (struct devq*) q->q;
-
- DQI_DEBUG("Register top_q q=%p tx_q=%p Rid=%d \n", q, tx, region_id);
- err = tx->ctrl_rpc->vtbl.reg(tx->ctrl_rpc, mem, region_id, &tx->err);
- if (err_is_fail(tx->err) || err_is_fail(err)) {
- err = err_is_fail(err) ? err: tx->err;
- err = b->tx_vtbl.reg_response(b, NOP_CONT, err);
- assert(err_is_ok(err));
- }
-
- if (tx->q == NULL) {
- tx->q = q;
- }
-
- } else {
-
- DQI_DEBUG("Register q=%p Rid=%d \n", q, region_id);
- err = region_pool_add_region_with_id(q->pool, mem, region_id);
- if (err_is_fail(err)) {
- err = b->tx_vtbl.reg_response(b, NOP_CONT, err);
- assert(err_is_ok(err));
- }
-
- }
-
- err = q->end->f.reg(q, mem, region_id);
- if (err_is_fail(err)) {
- err = b->tx_vtbl.reg_response(b, NOP_CONT, err);
- assert(err_is_ok(err));
- }
-
- err = b->tx_vtbl.reg_response(b, NOP_CONT, err);
- assert(err_is_ok(err));
-}
-
-static void mp_deregister(struct devif_ctrl_binding* b, regionid_t region_id)
-{
- errval_t err;
- DQI_DEBUG("Deregister Rid=%d\n", region_id);
- struct devq* q = (struct devq*) b->st;
- struct capref* cap = NULL;
-
-
- if (q->end->endpoint_type == ENDPOINT_TYPE_FORWARD) {
- // forward directly
- struct devq* tx = (struct devq*) q->q;
-
- err = tx->ctrl_rpc->vtbl.dereg(tx->ctrl_rpc, region_id, &tx->err);
- if (err_is_fail(tx->err) || err_is_fail(err)) {
- err = err_is_fail(err) ? err: tx->err;
- err = b->tx_vtbl.dereg_response(b, NOP_CONT, err);
- assert(err_is_ok(err));
- }
-
- } else {
- err = region_pool_remove_region(q->pool, region_id, cap);
- if (err_is_fail(err)) {
- err = b->tx_vtbl.dereg_response(b, NOP_CONT, err);
- assert(err_is_ok(err));
- }
-
- }
-
- err = q->end->f.dereg(q, region_id);
- if (err_is_fail(err)) {
- err = b->tx_vtbl.dereg_response(b, NOP_CONT, err);
- assert(err_is_ok(err));
- }
-
- err = b->tx_vtbl.dereg_response(b, NOP_CONT, SYS_ERR_OK);
- assert(err_is_ok(err));
-}
-
-static void mp_control(struct devif_ctrl_binding* b, uint64_t cmd,
- uint64_t value)
-{
- errval_t err;
- struct devq* q = (struct devq*) b->st;
-
- DQI_DEBUG("Control cmd=%lu value=%lu \n", cmd, value);
- if (q->end->endpoint_type == ENDPOINT_TYPE_FORWARD) {
- struct devq* tx = (struct devq*) q->q;
- err = tx->ctrl_rpc->vtbl.control(tx->ctrl_rpc, cmd, value, &tx->err);
- if (err_is_fail(err) || err_is_fail(tx->err)) {
- err = err_is_fail(err) ? err: tx->err;
- err = b->tx_vtbl.control_response(b, NOP_CONT, err);
- assert(err_is_ok(err));
- }
-
- }
-
- err = q->end->f.ctrl(q, cmd, value);
- if (err_is_fail(err)) {
- err = b->tx_vtbl.control_response(b, NOP_CONT, err);
- assert(err_is_ok(err));
- }
-
- err = b->tx_vtbl.control_response(b, NOP_CONT, SYS_ERR_OK);
- assert(err_is_ok(err));
-}
-
-static void mp_notify(struct devif_data_binding* b, uint8_t num_slots)
-{
- errval_t err;
- struct devq* q = (struct devq*) b->st;
- // Sending notification
-
- regionid_t region_id;
- bufferid_t buffer_id;
- lpaddr_t base;
- size_t len;
- uint64_t misc_flags;
-
- DQI_DEBUG("notify q=%p slots=%d endpoint %p \n", q, num_slots, q->end);
-
- if (q->end->endpoint_type == ENDPOINT_TYPE_FORWARD) {
- // forward user -> device:
- struct devq* tx = (struct devq*) q->q;
-
- if (tx->q == NULL) {
- tx->q = q;
- }
-
- DQI_DEBUG("notify forward q=%p slots=%d \n", tx, num_slots);
- for (int i = 0; i < num_slots; i++) {
-
- err = descq_dequeue(q->rx, ®ion_id, &buffer_id,
- &base, &len, &misc_flags);
- assert(err_is_ok(err));
-
- // local function call
- err = q->end->f.enq(q, region_id, buffer_id, base, len , misc_flags);
- assert(err_is_ok(err));
- DQI_DEBUG("Dequeue q=%p rid=%d, bid=%d \n", q, region_id, buffer_id);
- // TODO call function locally to inform point (dequeue)
- err = descq_enqueue(tx->tx, region_id, buffer_id,
- base, len, misc_flags);
- DQI_DEBUG("Enqueue q=%p rid=%d, bid=%d \n", tx, region_id, buffer_id);
- assert(err_is_ok(err));
- }
-
- descq_writeout_head(tx->tx);
- err = tx->data->tx_vtbl.notify(tx->data, NOP_CONT, num_slots);
- assert(err_is_ok(err));
-
- err = tx->end->f.notify(q, num_slots);
- } else if (q->end->endpoint_type == ENDPOINT_TYPE_FORWARD_TX) {
- // forward device -> user
- struct devq* tx = (struct devq*) q->q;
- DQI_DEBUG("notify forward_tx q=%p slots=%d \n", tx, num_slots);
- for (int i = 0; i < num_slots; i++) {
- err = descq_dequeue(q->rx, ®ion_id, &buffer_id,
- &base, &len, &misc_flags);
- assert(err_is_ok(err));
- DQI_DEBUG("Dequeue q=%p rid=%d, bid=%d \n", q, region_id, buffer_id);
-
- // local function call // TODO only enqueue makes sense ? use flags?
- err = q->end->f.enq(q, region_id, buffer_id, base, len , misc_flags);
- assert(err_is_ok(err));
-
- err = descq_enqueue(tx->tx, region_id, buffer_id,
- base, len, misc_flags);
- DQI_DEBUG("Enqueue q=%p rid=%d, bid=%d \n", tx, region_id, buffer_id);
- assert(err_is_ok(err));
- }
-
- descq_writeout_head(tx->tx);
- err = tx->data->tx_vtbl.notify(tx->data, NOP_CONT, num_slots);
- assert(err_is_ok(err));
-
- err = q->end->f.notify(q, num_slots);
- } else {
- err = q->end->f.notify(q, num_slots);
- assert(err_is_ok(err));
-
- descq_writeout_tail(q->rx);
- }
-}
-
-static struct devif_ctrl_rx_vtbl rx_vtbl_ctrl = {
- .setup_call = mp_setup_request,
- .create_call= mp_create,
- .reg_call = mp_register,
- .dereg_call = mp_deregister,
- .control_call = mp_control,
-};
-
-
-static struct devif_data_rx_vtbl rx_vtbl_data = {
- .notify = mp_notify,
-};
-
-static void bind_cb_ctrl(void *st, errval_t err, struct devif_ctrl_binding *b)
-{
- struct devq* q = (struct devq*) st;
- assert(err_is_ok(err));
-
- b->rx_vtbl = rx_vtbl_ctrl;
- b->st = q;
- q->ctrl = b;
- // Initi RPC client
-
- q->ctrl_rpc = malloc(sizeof(struct devif_ctrl_rpc_client));
- assert(q->ctrl_rpc != NULL);
-
- err = devif_ctrl_rpc_client_init(q->ctrl_rpc, b);
- if (err_is_fail(err)) {
- free(q->ctrl_rpc);
- }
-
- q->state = DEVQ_STATE_BINDING_CTRL;
- DQI_DEBUG("Bound to interface \n");
-}
-
-static void bind_cb_data(void *st, errval_t err, struct devif_data_binding *b)
-{
- struct devq* q = (struct devq*) st;
- assert(err_is_ok(err));
-
- b->rx_vtbl = rx_vtbl_data;
- b->st = q;
- q->data = b;
- // Initi RPC client
-
- q->state = DEVQ_STATE_BINDING_DATA;
- DQI_DEBUG("Bound to interface \n");
-}
-
-static void export_cb_ctrl(void *st, errval_t err, iref_t iref)
-{
- assert(err_is_ok(err));
- struct endpoint_state* state = (struct endpoint_state*) st;
- const char *suffix = "_devif_ctrl";
-
- char name[strlen(state->device_name) + strlen(suffix) + 1];
- sprintf(name, "%s%s", state->device_name, suffix);
-
- err = nameservice_register(name, iref);
- assert(err_is_ok(err));
-
- DQI_DEBUG("Interface %s exported \n", name);
-}
-
-// TODO try to not duplicate this?
-static void export_cb_data(void *st, errval_t err, iref_t iref)
-{
- assert(err_is_ok(err));
- struct endpoint_state* state = (struct endpoint_state*) st;
- const char *suffix = "_devif_data";
-
- char name[strlen(state->device_name) + strlen(suffix) + 1];
- sprintf(name, "%s%s", state->device_name, suffix);
-
- err = nameservice_register(name, iref);
- assert(err_is_ok(err));
-
- DQI_DEBUG("Interface %s exported \n", name);
- state->export_done = true;
-}
-
-static errval_t connect_cb_ctrl(void *st, struct devif_ctrl_binding* b)
-{
- DQI_DEBUG("New connection on interface \n");
- struct endpoint_state* end = (struct endpoint_state*) st;
-
- b->rx_vtbl = rx_vtbl_ctrl;
- b->st = st;
- // Set binding for bidirectional communication
- end->ctrl = b;
- return SYS_ERR_OK;
-}
-
-
-static errval_t connect_cb_data(void *st, struct devif_data_binding* b)
-{
- DQI_DEBUG("New connection on interface \n");
- struct endpoint_state* end = (struct endpoint_state*) st;
-
- b->rx_vtbl = rx_vtbl_data;
- b->st = st;
- // Set binding for bidirectional communication
- end->data = b;
- return SYS_ERR_OK;
-}
-
- /*
- * ===========================================================================
- * Device queue interface export (for devices)
- * ===========================================================================
- */
- /**
- * @brief exports the devq interface so others (client side) can connect
- *
- * @param device_name Device name that is exported to the other endpoints.
- * Required by the "user" side to connect to
- * @param features The features the driver exports
- *
- * @returns error on failure or SYS_ERR_OK on success
- */
-
-errval_t devq_driver_export(struct endpoint_state* s)
-{
- DQI_DEBUG("Driver export with endpoint %p \n", s);
- errval_t err;
-
- err = devif_ctrl_export(s, export_cb_ctrl, connect_cb_ctrl, get_default_waitset(),
- 1);
- if (err_is_fail(err)) {
- DQI_DEBUG("Exporting devif interface failed \n");
- return err;
- }
-
- err = devif_data_export(s, export_cb_data, connect_cb_data, get_default_waitset(),
- IDC_BIND_FLAGS_DEFAULT);
- if (err_is_fail(err)) {
- DQI_DEBUG("Exporting devif interface failed \n");
- return err;
- }
-
- while (!s->export_done) {
- event_dispatch(get_default_waitset());
- }
-
- return SYS_ERR_OK;
-}
-
- /*
- * ===========================================================================
- * Device queue creation and destruction
- * ===========================================================================
- */
- /**
- * @brief creates a queue
- *
- * @param q Return pointer to the devq (handle)
- * @param end Endpoint state containing require function pointers and
- * some other info
- * @param endpoint_name Device name of the device to which this queue belongs
- * (Driver itself is running in a separate process)
- * @param flags Anything you can think of that makes sense for the device
- * and its driver?
- *
- * @returns error on failure or SYS_ERR_OK on success
- */
-
-errval_t devq_create(struct devq **q,
- struct endpoint_state* end,
- char* endpoint_name,
- uint64_t flags)
-{
-
- errval_t err;
-
- struct devq* tmp = malloc(sizeof(struct devq));
- tmp->end = end;
-
- DQI_DEBUG("start create %p\n", tmp);
- strncpy(tmp->endpoint_name, endpoint_name, MAX_DEVICE_NAME);
-
- err = region_pool_init(&(tmp->pool));
- if (err_is_fail(err)) {
- free(tmp);
- return err;
- }
-
- tmp->end = end;
- tmp->state = DEVQ_STATE_UNINITIALIZED;
-
- switch (tmp->end->endpoint_type) {
- case ENDPOINT_TYPE_FORWARD:
- err = devq_init_forward(tmp, flags);
- if (err_is_fail(err)) {
- return err;
- }
- break;
- case ENDPOINT_TYPE_DEVICE:
- // set bindings for communication back
- tmp->ctrl = tmp->end->ctrl;
- tmp->data = tmp->end->data;
- break;
- case ENDPOINT_TYPE_DIRECT:
- flags = flags | DEVQ_SETUP_FLAGS_DIRECT;
- err = devq_init_direct(tmp, flags);
- if (err_is_fail(err)) {
- return err;
- }
- break;
- case ENDPOINT_TYPE_USER:
- err = devq_init_user(tmp, flags);
- if (err_is_fail(err)) {
- return err;
- }
- break;
- default:
- USER_PANIC("Devq: unknown device type \n");
-
- }
-
- tmp->state = DEVQ_STATE_READY;
- *q = tmp;
- DQI_DEBUG("end create %p\n", tmp);
- return SYS_ERR_OK;
-}
-
-
- /**
- * @brief destroys the device queue
- *
- * @param q The queue state to free (and the device queue to be
- shut down in the driver)
- *
- * @returns error on failure or SYS_ERR_OK on success
- */
-errval_t devq_destroy(struct devq *q)
-{
- errval_t err;
-
- err = descq_destroy(q->rx);
- if (err_is_fail(err)) {
- return err;
- }
-
- err = descq_destroy(q->tx);
- if (err_is_fail(err)) {
- return err;
- }
-
- err = region_pool_destroy(q->pool);
- if (err_is_fail(err)) {
- return err;
- }
-
- free(q);
- return SYS_ERR_OK;
-}
-
-/**
- * @brief allocate device specific state of size bytes
- *
- * @param q The device queue to allocate the state for
- * @param bytes Size of the state to allocate
- *
- */
-void devq_allocate_state(struct devq *q, size_t bytes)
-{
- q->q = calloc(1, bytes);
-}
-/**
- * @brief get the device specific state for a queue
- *
- * @param q The device queue to get the state for
- *
- * @returns void pointer to the defice specific state
- */
-void* devq_get_state(struct devq *q)
-{
- return q->q;
-}
-
-void devq_set_state(struct devq *q, void* state)
-{
- q->q = state;
-}
-
-static errval_t connect_to_if(struct devq *q, char* if_name, bool data)
-{
- enum devq_state state;
- errval_t err;
- iref_t iref;
-
- char* suffix;
- if (data) {
- suffix = "_devif_data";
- } else {
- suffix = "_devif_ctrl";
- }
-
- char name[strlen(if_name) + strlen(suffix)+1];
- sprintf(name, "%s%s", if_name, suffix);
- DQI_DEBUG("connecting to %s \n", name);
-
- err = nameservice_blocking_lookup(name, &iref);
- if (err_is_fail(err)) {
- return err;
- }
-
- // Bind to driver interface
- if (data) {
- err = devif_data_bind(iref, bind_cb_data, q, get_default_waitset(),
- IDC_BIND_FLAGS_DEFAULT);
- if (err_is_fail(err)) {
- return err;
- }
- state = DEVQ_STATE_BINDING_DATA;
- } else {
- err = devif_ctrl_bind(iref, bind_cb_ctrl, q, get_default_waitset(),
- IDC_BIND_FLAGS_DEFAULT);
- if (err_is_fail(err)) {
- return err;
- }
- state = DEVQ_STATE_BINDING_CTRL;
- }
-
- // wiat until bound
- while (q->state != state) {
- event_dispatch(get_default_waitset());
- }
-
- return SYS_ERR_OK;
-}
-
-static errval_t devq_init_descqs(struct devq *q,
- struct capref rx,
- struct capref tx,
- size_t slots)
-{
- errval_t err;
- q->rx_cap = rx;
- q->tx_cap = tx;
-
- err = descq_init(&q->rx, rx, slots);
- if (err_is_fail(err)) {
- // TODO cleanup mapped frame
- return DEVQ_ERR_DESCQ_INIT;
- }
-
- err = descq_init(&q->tx, tx, slots);
- if (err_is_fail(err)) {
- // TODO cleanup mapped frame
- return DEVQ_ERR_DESCQ_INIT;
- }
-
-
- DQI_DEBUG("RX/TX queue mapped and initaialized, successfully"
- " q %p tx %p rx %p \n", q, q->tx, q->rx);
- return SYS_ERR_OK;
-}
-
-static errval_t devq_init_forward(struct devq *q,
- uint64_t flags)
-{
- errval_t err;
-
- char* end_name = malloc(MAX_DEVICE_NAME);
-
- sprintf(end_name, "%s_%s", "forward", q->endpoint_name);
- strncpy(q->end->device_name, end_name, MAX_DEVICE_NAME);
-
- // export interface
- err = devif_ctrl_export(q->end, export_cb_ctrl, connect_cb_ctrl, get_default_waitset(),
- IDC_BIND_FLAGS_DEFAULT);
- if (err_is_fail(err)) {
- DQI_DEBUG("Exporting devif interface failed \n");
- return err;
- }
-
- err = devif_data_export(q->end, export_cb_data, connect_cb_data, get_default_waitset(),
- IDC_BIND_FLAGS_DEFAULT);
- if (err_is_fail(err)) {
- DQI_DEBUG("Exporting devif interface failed \n");
- return err;
- }
-
- DQI_DEBUG("Waiting for export done\n");
- while (!q->end->export_done) {
- event_dispatch(get_default_waitset());
- }
-
- DQI_DEBUG("Export done\n");
-
- return SYS_ERR_OK;
-}
-
-static errval_t devq_init_user(struct devq *q,
- uint64_t flags)
-{
- errval_t err;
- struct capref rx;
- struct capref tx;
-
- // Allocate shared memory
- err = frame_alloc(&rx, DESCQ_DEFAULT_SIZE*DESCQ_ALIGNMENT, NULL);
- if (err_is_fail(err)) {
- return err;
- }
-
- err = frame_alloc(&tx, DESCQ_DEFAULT_SIZE*DESCQ_ALIGNMENT, NULL);
- if (err_is_fail(err)) {
- return err;
- }
-
- err = devq_init_descqs(q, rx, tx, DESCQ_DEFAULT_SIZE);
- if (err_is_fail(err)) {
- return err;
- }
-
- err = connect_to_if(q, q->endpoint_name, false);
- if (err_is_fail(err)) {
- return err;
- }
-
- err = q->ctrl_rpc->vtbl.setup(q->ctrl_rpc, disp_get_core_id(), flags,
- &q->end->features, &q->q_size,
- &q->buf_size, &q->reconnect, q->reconnect_name);
- if (err_is_fail(err)) {
- return err;
- }
-
- // Do setup
- // might have to connect again to different process
- if (q->reconnect) {
- DQI_DEBUG("Reconnecting \n");
- q->state = DEVQ_STATE_RECONNECTING;
- err = connect_to_if(q, q->reconnect_name, false);
- if (err_is_fail(err)) {
- return err;
- }
-
- err = connect_to_if(q, q->reconnect_name, true);
- if (err_is_fail(err)) {
- return err;
- }
-
- } else {
- err = connect_to_if(q, q->endpoint_name, true);
- if (err_is_fail(err)) {
- return err;
- }
- }
-
- err = q->ctrl_rpc->vtbl.create(q->ctrl_rpc, rx, tx, flags,
- DESCQ_DEFAULT_SIZE, &q->err);
- if (err_is_fail(err) || err_is_fail(q->err)) {
- return err_is_fail(err) ? err: q->err;
- }
-
- q->state = DEVQ_STATE_CONNECTED;
-
- return SYS_ERR_OK;
-}
-
-static errval_t devq_init_direct(struct devq *q,
- uint64_t flags)
-{
- errval_t err;
- struct capref rx;
- struct capref tx;
-
- // Allocate shared memory
- err = frame_alloc(&rx, DESCQ_DEFAULT_SIZE*DESCQ_ALIGNMENT, NULL);
- if (err_is_fail(err)) {
- return err;
- }
-
- err = frame_alloc(&tx, DESCQ_DEFAULT_SIZE*DESCQ_ALIGNMENT, NULL);
- if (err_is_fail(err)) {
- return err;
- }
-
- err = devq_init_descqs(q, rx, tx, DESCQ_DEFAULT_SIZE);
- if (err_is_fail(err)) {
- return err;
- }
-
- // need to get some stuff from the device itself
- err = connect_to_if(q, q->endpoint_name, false);
- if (err_is_fail(err)) {
- return err;
- }
-
- err = q->ctrl_rpc->vtbl.setup(q->ctrl_rpc, disp_get_core_id(),
- flags, &q->end->features, &q->q_size,
- &q->buf_size, &q->reconnect, q->reconnect_name);
- if (err_is_fail(err)) {
- return err;
- }
- err = q->end->f.create(q, flags);
-
- return err;
-}
/*
* ===========================================================================
* Datapath functions
access. In the device case, we keep track of the buffers the device
actually has access to.
*/
- if (q->end->endpoint_type == ENDPOINT_TYPE_USER ||
- q->end->endpoint_type == ENDPOINT_TYPE_DIRECT) {
- err = region_pool_get_buffer_id_from_region(q->pool, region_id, base,
- buffer_id);
- if (err_is_fail(err)) {
- return err;
- }
- } else {
- err = region_pool_return_buffer_to_region(q->pool, region_id,
- base);
- if (err_is_fail(err)) {
- return err;
- }
- }
- // Enqueue into queue
- if (q->end->endpoint_type == ENDPOINT_TYPE_DIRECT) {
- err = q->end->f.enq(q, region_id, *buffer_id, base, length,
- misc_flags);
- } else {
- err = descq_enqueue(q->tx, region_id, *buffer_id,
- base, length, misc_flags);
+ err = region_pool_get_buffer_id_from_region(q->pool, region_id, base,
+ buffer_id);
+ if (err_is_fail(err)) {
+ return err;
}
+ err = q->f.enq(q, region_id, *buffer_id, base, length,
+ misc_flags);
+
DQI_DEBUG("Enqueue q=%p rid=%d, bid=%d \n", q, region_id, *buffer_id);
return err;
{
errval_t err;
- // Directly queue
- if (q->end->endpoint_type == ENDPOINT_TYPE_DIRECT) {
- err = q->end->f.deq(q, region_id, buffer_id, base, length,
- misc_flags);
- if (err_is_fail(err)) {
- return err;
- }
- } else {
-
- // Dequeue descriptor from descriptor queue
- err = descq_dequeue(q->rx, region_id, buffer_id,
- base, length, misc_flags);
- if (err_is_fail(err)) {
- return err;
- }
+ err = q->f.deq(q, region_id, buffer_id, base, length,
+ misc_flags);
+ if (err_is_fail(err)) {
+ return err;
}
/* In the user case we keep track of the buffers the user should not
actually has access to.
*/
// Add buffer to free ones
- if (q->end->endpoint_type == ENDPOINT_TYPE_USER ||
- q->end->endpoint_type == ENDPOINT_TYPE_DIRECT) {
- err = region_pool_return_buffer_id_to_region(q->pool, *region_id,
- *buffer_id);
+ err = region_pool_return_buffer_id_to_region(q->pool, *region_id,
+ *buffer_id);
- if (err_is_fail(err)) {
- return err;
- }
- } else {
- err = region_pool_set_buffer_id_from_region(q->pool, *region_id, *base,
- *buffer_id);
- if (err_is_fail(err)) {
- return DEVQ_ERR_BUFFER_ID;
- }
+ if (err_is_fail(err)) {
+ return err;
}
DQI_DEBUG("Dequeue q=%p rid=%d, bid=%d \n", q, *region_id, *buffer_id);
DQI_DEBUG("register q=%p, cap=%p, regionid=%d \n", (void*) q,
(void*) &cap, *region_id);
- if (q->end->endpoint_type == ENDPOINT_TYPE_DIRECT) {
- /* Directly call it, if communication to the device
- driver is necessary it is most likely device specific
- and can not be handled in the devq library
- */
- err = q->end->f.reg(q, cap, *region_id);
- } else {
- err = q->ctrl_rpc->vtbl.reg(q->ctrl_rpc, cap, *region_id, &q->err);
- if (err_is_fail(q->err)) {
- return q->err;
- }
- }
+ err = q->f.reg(q, cap, *region_id);
+
return err;
}
DQI_DEBUG("deregister q=%p, cap=%p, regionid=%d \n", (void*) q,
(void*) cap, region_id);
- if (q->end->endpoint_type == ENDPOINT_TYPE_DIRECT) {
- err = q->end->f.dereg(q, region_id);
- } else {
- err = q->ctrl_rpc->vtbl.dereg(q->ctrl_rpc, region_id, &q->err);
- if (err_is_fail(q->err)) {
- return q->err;
- }
- }
+ err = q->f.dereg(q, region_id);
return err;
}
-// Notify helper
-struct pending_reply {
- uint8_t num_slots;
- struct devif_data_binding* b;
-};
-
-static void resend_notify(void* a)
-{
- errval_t err;
- struct pending_reply* r = (struct pending_reply*) a;
-
- err = r->b->tx_vtbl.notify(r->b, NOP_CONT, r->num_slots);
- if (err_is_fail(err)) {
- err = r->b->register_send(r->b, get_default_waitset(),
- MKCONT(resend_notify, r));
- assert(err_is_ok(err));
- } else {
- free(r);
- }
-
-}
-
/**
* @brief Send a notification about new buffers on the queue
* Does nothing for direct queues.
{
errval_t err;
- if (q->end->endpoint_type == ENDPOINT_TYPE_DIRECT) {
- return SYS_ERR_OK;
- } else {
- // get number of full slots
- uint8_t num_slots = descq_full_slots(q->tx);
- DQI_DEBUG("notify called q=%p slots=%d \n",q, num_slots);
- descq_writeout_head(q->tx);
-
- err = q->data->tx_vtbl.notify(q->data, NOP_CONT, num_slots);
- // send notification
- if (err == FLOUNDER_ERR_TX_BUSY) {
- struct pending_reply* r = malloc(sizeof(struct pending_reply));
- r->num_slots = num_slots;
- r->b = q->data;
+ err = q->f.notify(q);
- err = q->data->register_send(q->data, get_default_waitset(),
- MKCONT(resend_notify, r));
- // If registering fails, dispatch event to get further with
- // state and retry
- if (err_is_fail(err)) {
- while (true) {
- err = r->b->register_send(r->b, get_default_waitset(),
- MKCONT(resend_notify, r));
- if (err_is_ok(err)) {
- break;
- } else {
- event_dispatch(get_default_waitset());
- }
- }
- }
- }
- }
- return SYS_ERR_OK;
+ return err;
}
/**
uint64_t value)
{
errval_t err;
-
- DQI_DEBUG("control request=%lu, value=%lu \n", request, value);
- if (q->end->endpoint_type == ENDPOINT_TYPE_DIRECT) {
- err = q->end->f.ctrl(q, request, value);
- return err;
- } else {
- err = q->ctrl_rpc->vtbl.control(q->ctrl_rpc, request, value, &q->err);
- if (err_is_fail(err) || err_is_fail(q->err)) {
- err = err_is_fail(err) ? err : q->err;
- return err;
- }
- }
- return q->err;
-}
+ err = q->f.ctrl(q, request, value);
+ return err;
-errval_t devq_event_loop(struct endpoint_state* s)
-{
- while(true) {
- event_dispatch(get_default_waitset());
- }
}
+
--- /dev/null
+/*
+ * Copyright (c) 2016 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, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#include <barrelfish/barrelfish.h>
+#include <devif/queue_interface.h>
+
+
+#include "region_pool.h"
+#include "queue_interface_internal.h"
+
+ /*
+ * ===========================================================================
+ * Device queue creation and destruction (General devif initalisation)
+ * ===========================================================================
+ */
+ /**
+ * @brief creates a queue
+ *
+ * @param q Return pointer to the devq (handle)
+ *
+ * @returns error on failure or SYS_ERR_OK on success
+ */
+
+errval_t devq_init(struct devq *q)
+{
+
+ errval_t err;
+
+ err = region_pool_init(&(q->pool));
+ if (err_is_fail(err)) {
+ return err;
+ }
+
+ return SYS_ERR_OK;
+}
+
+
+ /**
+ * @brief destroys the device queue
+ *
+ * @param q The queue state to free (and the device queue to be
+ shut down in the driver)
+ *
+ * @returns error on failure or SYS_ERR_OK on success
+ */
+errval_t devq_destroy(struct devq *q)
+{
+ errval_t err;
+
+ err = region_pool_destroy(q->pool);
+ if (err_is_fail(err)) {
+ return err;
+ }
+
+ return SYS_ERR_OK;
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2016 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, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
+ */
+#ifndef QUEUE_INTERFACE_INTERNAL_H_
+#define QUEUE_INTERFACE_INTERNAL_H_ 1
+
+#include <devif/queue_interface.h>
+
+errval_t devq_init(struct devq *q);
+errval_t devq_destroy(struct devq *q);
+
+
+#endif /* QUEUE_INTERFACE_INTERNAL_H_ */
USER_PANIC_ERR(err, "AHCI HBA init failed.");
}
- err = devq_create(ad, "", 0, &dq);
- if (err_is_fail(err)) {
- USER_PANIC_ERR(err, "devq create failed.");
- }
-
#if DISABLE_INTERRUPTS
waitset_init(&disk_ws);
#include <pci/pci.h>
#include <skb/skb.h>
#include <blk/ahci.h>
-#include <devif/queue.h>
#define DISABLE_INTERRUPTS 1
#include <stdarg.h>
#include <bench/bench.h>
+#include <devif/queue.h>
struct dma_mem {
lvaddr_t vaddr; ///< virtual address of the mapped region
"skb"]
},
- build application { target = "sfn5122f_devif_queue",
- cFiles = ["sfn5122f_devif_qdriver.c", "helper.c" ],
- flounderBindings = [ "sfn5122f_devif" ],
- flounderExtraBindings = [ ("sfn5122f_devif", ["rpcclient"]) ],
- flounderDefs = [ "sfn5122f_devif" ],
- flounderExtraDefs = [ ("sfn5122f_devif",["rpcclient"]) ],
- mackerelDevices = ["sfn5122f", "sfn5122f_q"],
- addLibraries = libDeps ["devif", "skb"]
- },
-
build application { target = "sfn5122f",
cFiles = [ "sfn5122f_cdriver.c", "mcdi_rpc.c", "helper.c",
"buffer_tbl.c"],
flounderDefs = [ "sfn5122f", "sfn5122f_devif" ],
flounderExtraDefs = [ ("sfn5122f_devif",["rpcclient"]) ],
mackerelDevices = [ "sfn5122f"],
- addLibraries = libDeps["netQmng", "pci", "contmng", "devif",
+ addLibraries = libDeps["netQmng", "pci", "contmng",
"net_device_manager", "bench", "trace", "skb",
"spawndomain" ]
- },
-
- build library { target = "sfn5122f_devif_direct",
- cFiles = [ "sfn5122f_devif_direct.c", "helper.c"],
- flounderBindings = [ "sfn5122f_devif"],
- flounderExtraBindings = [ ("sfn5122f_devif", ["rpcclient"])],
- flounderDefs = [ "sfn5122f_devif" ],
- flounderExtraDefs = [ ("sfn5122f_devif",["rpcclient"]) ],
- mackerelDevices = [ "sfn5122f", "sfn5122f_q"],
- addLibraries = libDeps ["netQmng", "pci", "net_device_manager",
- "skb"]
}
]
#include <if/sfn5122f_devif_rpcclient_defs.h>
#include <if/net_ARP_rpcclient_defs.h>
#include <if/net_ARP_defs.h>
-#include <devif/loopback_device.h>
-#include <devif/queue_interface.h>
#include "sfn5122f.h"
return SYS_ERR_OK;
}
-static errval_t sfn5122f_setup(uint32_t coreid, uint64_t flag,
- uint64_t *features, uint32_t* default_qsize,
- uint32_t* default_bufsize, bool* reconnect,
- char* name)
-{
- errval_t err;
-
- DEBUG("Setup called\n");
-
- *features = DEVQ_FEATURE_DIRECT;
- *default_qsize = TX_ENTRIES;
- *default_bufsize = MTU_MAX;
- // If it is not direct, start new queue driver
- if (!(flag & DEVQ_SETUP_FLAGS_DIRECT)) {
- // TODO find better name for qdrivers
- sprintf(name, "sfn5122f_devif_qdriver_%d", coreid);
- DEBUG("sprintf called\n");
- *reconnect = true;
- char** args = (char**) malloc(sizeof(char*)*4);
- char* string = malloc(256);
- args[0] = "/x86_64/sbin/sfn5122f_devif_queue";
- // TODO find exact size
- DEBUG("sprintf2 called\n");
- sprintf(string, "core=%d", coreid);
- args[1] = string;
- args[2] = NULL;
-
- DEBUG("spawn called\n");
- err = spawn_program(coreid, "/x86_64/sbin/sfn5122f_devif_queue",
- args, NULL, SPAWN_FLAGS_DEFAULT,
- NULL);
- if (err_is_fail(err)) {
- return SFN_ERR_QDRIVER;
- }
-
- DEBUG("free called\n");
- free(string);
- free(args);
- } else {
- *reconnect = false;
- name = "";
- }
- return SYS_ERR_OK;
-}
-
-
-static struct devq_func_pointer devif_f = {
- .setup = sfn5122f_setup,
-};
-
-static struct endpoint_state devif_state;
/**
* Initialize management interface for queue drivers.
* This has to be done _after_ the hardware is initialized.
get_default_waitset(), 1);
assert(err_is_ok(r));
- devif_state.f = devif_f;
- devif_state.features = 0;
- devif_state.endpoint_type = ENDPOINT_TYPE_DIRECT;
- strncpy(devif_state.device_name, service_name, strlen(service_name));
-
- r = devq_driver_export(&devif_state);
- assert(err_is_ok(r));
}
/*****************************************************************************/
[ build application { target = "devif_test",
cFiles = [ "queue_interface.c" ],
- addLibraries = [ "devif" , "sfn5122f_devif_direct"] },
-
- build application { target = "devif_loopback_device",
- cFiles = [ "loopback_device.c" ],
- addLibraries = [ "devif" ] },
-
- build application { target = "devif_forward_device",
- cFiles = [ "forward_device.c" ],
- addLibraries = [ "devif" ] }
+ addLibraries = [ "devif" , "devif_backend_solarflare",
+ "devif_backend_idc"] }
]
+++ /dev/null
-/*
- * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, 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, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-#include <barrelfish/barrelfish.h>
-#include <barrelfish/waitset.h>
-#include <barrelfish/deferred.h>
-#include <devif/queue_interface.h>
-
-static struct devq_func_pointer f;
-
-errval_t create_forward(struct devq* q, uint64_t flags);
-errval_t register_forward(struct devq* q, struct capref cap,
- regionid_t rid);
-errval_t deregister_forward(struct devq* q, regionid_t rid);
-errval_t control_forward(struct devq* q, uint64_t cmd, uint64_t value);
-errval_t destroy_forward(struct devq* q);
-errval_t notify_forward(struct devq* q, uint8_t num_slots);
-errval_t enqueue_forward(struct devq* q, regionid_t rid, bufferid_t bid, lpaddr_t base,
- size_t len, uint64_t flags);
-
-
-errval_t create_forward(struct devq* q, uint64_t flags)
-{
- return SYS_ERR_OK;
-}
-
-errval_t register_forward(struct devq* q, struct capref cap,
- regionid_t rid)
-{
- return SYS_ERR_OK;
-}
-
-
-errval_t deregister_forward(struct devq* q, regionid_t rid)
-{
- return SYS_ERR_OK;
-}
-
-
-errval_t control_forward(struct devq* q, uint64_t cmd, uint64_t value)
-{
- return SYS_ERR_OK;
-}
-
-
-errval_t notify_forward(struct devq* q, uint8_t num_slots)
-{
- return SYS_ERR_OK;
-}
-
-errval_t destroy_forward(struct devq* q)
-{
- return SYS_ERR_OK;
-}
-
-
-errval_t enqueue_forward(struct devq* q, regionid_t rid, bufferid_t bid, lpaddr_t base,
- size_t len, uint64_t flags)
-{
- return SYS_ERR_OK;
-}
-
-int main(int argc, char *argv[])
-{
-
- errval_t err;
- struct devq* q;
- f.create = create_forward;
- f.reg = register_forward;
- f.dereg = deregister_forward;
- f.notify = notify_forward;
- f.destroy = destroy_forward;
- f.ctrl = control_forward;
- f.enq = enqueue_forward;
-
- struct endpoint_state my_state = {
- .endpoint_type = ENDPOINT_TYPE_FORWARD,
- .device_name = "", // name will be assigned
- .features = 0,
- .f = f,
- };
-
- printf("Forward queue created\n");
- err = devq_create(&q, &my_state, "loopback", 1);
- if (err_is_fail(err)){
- printf("%s \n", err_getstring(err));
- USER_PANIC("Allocating devq failed \n");
- }
-
- devq_event_loop(&my_state);
- //messages_handler_loop();
-}
-
+++ /dev/null
-/*
- * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, 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, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-#include <barrelfish/barrelfish.h>
-#include <barrelfish/waitset.h>
-#include <barrelfish/deferred.h>
-#include <devif/queue_interface.h>
-#include <devif/loopback_device.h>
-
-static struct endpoint_state* state;
-
-// Prototypes
-int main(int argc, char *argv[])
-{
- errval_t err;
- struct devq_func_pointer f = {
- .setup = devq_loopback_setup,
- .create = devq_loopback_create,
- .reg = devq_loopback_register,
- .notify = devq_loopback_notify,
- .dereg = devq_loopback_deregister,
- .ctrl = devq_loopback_control,
- };
-
- struct endpoint_state my_state = {
- .endpoint_type = ENDPOINT_TYPE_DEVICE,
- .device_name = "loopback",
- .features = 0,
- .f = f,
- };
-
-
- state = &my_state;
-
- err = devq_driver_export(&my_state);
- if (err_is_fail(err)){
- abort();
- }
-
- devq_event_loop(&my_state);
-}
-
#include <barrelfish/waitset.h>
#include <barrelfish/deferred.h>
#include <devif/queue_interface.h>
-#include <devif/sfn5122f_devif.h>
+#include <devif/backends/net/sfn5122f_devif.h>
//#define TEST_FORWARD
static struct frame_identity id;
static lpaddr_t phys_rx;
static lpaddr_t phys_tx;
-static uint32_t num_dequeue = 0;
static void* va_rx;
static void* va_tx;
*/
}
-static errval_t create_direct(struct devq* q, uint64_t flags)
-{
- devq_allocate_state(q, sizeof(struct direct_state));
-
- return SYS_ERR_OK;
-}
-
-static errval_t enqueue_direct(struct devq* q, regionid_t rid,
- bufferid_t bid, lpaddr_t addr, size_t len,
- uint64_t flags)
-{
- struct direct_state* s = (struct direct_state*) devq_get_state(q);
- struct list_ele* ele;
-
- ele = (struct list_ele*) malloc(sizeof(struct list_ele));
- ele->rid = rid;
- ele->bid = bid;
- ele->addr = addr;
- ele->len = len;
- ele->flags = flags;
- ele->next = NULL;
-
- if (s->first == NULL) {
- s->first = ele;
- s->last = ele;
- } else {
- s->last->next = ele;
- s->last = ele;
- }
- return SYS_ERR_OK;
-}
-
-static errval_t dequeue_direct(struct devq* q, regionid_t* rid,
- bufferid_t* bid, lpaddr_t* addr, size_t* len,
- uint64_t* flags)
-{
-
- struct direct_state* s = (struct direct_state*) devq_get_state(q);
- struct list_ele* ele;
-
- if (s->first == NULL) {
- return DEVQ_ERR_RX_EMPTY;
- } else {
- *rid = s->first->rid;
- *bid = s->first->bid;
- *addr = s->first->addr;
- *len = s->first->len;
- *flags = s->first->flags;
- ele = s->first;
- s->first = s->first->next;
- free(ele);
- }
- return SYS_ERR_OK;
-}
-
-static errval_t register_direct(struct devq* q, struct capref cap,
- regionid_t rid)
-{
- return SYS_ERR_OK;
-}
-
-
-static errval_t deregister_direct(struct devq* q, regionid_t rid)
-{
- return SYS_ERR_OK;
-}
-
-
-static errval_t control_direct(struct devq* q, uint64_t cmd, uint64_t value)
-{
- return SYS_ERR_OK;
-}
-
-static errval_t notify_normal(struct devq* q, uint8_t num_slots)
-{
- errval_t err;
- struct devq_buf* bufs = malloc(sizeof(struct devq_buf)*num_slots);
- for (int i = 0; i < num_slots; i++) {
- err = devq_dequeue(q, &(bufs[i].rid), &(bufs[i].addr),
- &(bufs[i].len), &(bufs[i].bid), &(bufs[i].flags));
- if (err_is_fail(err)) {
- return err;
- }
- }
- return SYS_ERR_OK;
-}
-
-
-static errval_t notify_sfn5122f(struct devq* q, uint8_t num_slots)
-{
- if (num_dequeue >= 64) {
- return SYS_ERR_OK;
- }
-
- errval_t err;
- struct devq_buf* buf = malloc(sizeof(struct devq_buf));
- for (int i = 0; i < num_slots; i++) {
- err = devq_dequeue(q, &(buf->rid), &(buf->addr),
- &(buf->len), &(buf->bid), &(buf->flags));
- if (err_is_fail(err)) {
- return err;
- }
-
- switch(buf->flags) {
- case DEVQ_BUF_FLAG_TX:
- printf("TX buffer returned \n");
- break;
- case (DEVQ_BUF_FLAG_TX & DEVQ_BUF_FLAG_TX_LAST):
- printf("TX buffer returned \n");
- break;
- case DEVQ_BUF_FLAG_RX:
- print_buffer(buf->len, buf->bid);
- break;
- default:
- printf("Unknown flags %ld \n", buf->flags);
- }
- num_dequeue++;
- }
- return SYS_ERR_OK;
-}
-
-static void test_normal_device(void)
-{
-
- errval_t err;
- struct devq* q;
-
- struct devq_func_pointer f = {
- .notify = notify_normal,
- };
-
- struct endpoint_state my_state = {
- .endpoint_type = ENDPOINT_TYPE_USER,
- .device_name = "my_queue",
- .features = 0,
- .f = f,
- };
-
- printf("Normal device test started \n");
- err = devq_create(&q, &my_state, "loopback", 1);
- if (err_is_fail(err)){
- USER_PANIC("Allocating devq failed \n");
- }
-
- err = devq_register(q, memory_rx, ®id_rx);
- if (err_is_fail(err)){
- USER_PANIC("Registering memory to devq failed \n");
- }
-
- bufferid_t ids[NUM_ENQ];
- for (int j = 0; j < NUM_ROUNDS; j++) {
- for (int i = 0; i < NUM_ENQ; i++) {
- lpaddr_t addr = phys_rx+(j*NUM_ENQ*2048+i*2048);
- err = devq_enqueue(q, regid_rx, addr, 2048,
- 1, &ids[i]);
- if (err_is_fail(err)){
- USER_PANIC("Devq enqueue failed \n");
- }
- }
-
- err = devq_notify(q);
- if (err_is_fail(err)) {
- printf("%s",err_getstring(err));
- }
- event_dispatch(get_default_waitset());
- }
-
- err = devq_control(q, 1, 1);
- if (err_is_fail(err)){
- USER_PANIC("Devq deregister failed \n");
- }
-
- err = devq_deregister(q, regid_rx, &memory_rx);
- if (err_is_fail(err)){
- USER_PANIC("Devq deregister failed \n");
- }
-
- err = devq_destroy(q);
-
- printf("Normal device test ended\n");
-}
-
-static void test_direct_device(void)
-{
-
- errval_t err;
- struct devq* q;
-
- struct devq_func_pointer f = {
- .create = create_direct,
- .enq = enqueue_direct,
- .deq = dequeue_direct,
- .reg = register_direct,
- .dereg = deregister_direct,
- .ctrl = control_direct,
- };
-
- struct endpoint_state my_state = {
- .endpoint_type = ENDPOINT_TYPE_DIRECT,
- .device_name = "my_queue",
- .features = 0,
- .f = f,
- };
-
- printf("Direct device test started \n");
- err = devq_create(&q, &my_state, "loopback", 1);
- if (err_is_fail(err)){
- USER_PANIC("Allocating devq failed \n");
- }
-
- err = devq_register(q, memory_rx, ®id_rx);
- if (err_is_fail(err)){
- USER_PANIC("Registering memory to devq failed \n");
- }
-
- regionid_t rid;
- bufferid_t ids[NUM_ENQ];
- lpaddr_t addr;
- size_t len;
- uint64_t flags;
- for (int j = 0; j < NUM_ROUNDS; j++) {
- for (int i = 0; i < NUM_ENQ; i++) {
- addr = phys_rx+(j*NUM_ENQ*2048+i*2048);
- err = devq_enqueue(q, regid_rx, addr, 2048,
- 1, &ids[i]);
- if (err_is_fail(err)){
- USER_PANIC("Devq enqueue failed \n");
- }
- }
-
- for (int i = 0; i < NUM_ENQ; i++) {
- err = devq_dequeue(q, &rid, &addr, &len, &ids[i], &flags);
- if (err_is_fail(err)){
- USER_PANIC("Devq dequeue failed \n");
- }
- }
- }
-
- err = devq_control(q, 1, 1);
- if (err_is_fail(err)){
- printf("%s \n", err_getstring(err));
- USER_PANIC("Devq control failed \n");
- }
-
- err = devq_deregister(q, regid_rx, &memory_rx);
- if (err_is_fail(err)){
- printf("%s \n", err_getstring(err));
- USER_PANIC("Devq deregister failed \n");
- }
-
- err = devq_destroy(q);
-
- printf("Direct device test ended\n");
-}
-
-#ifdef SFN_TEST_DIRECT
static void test_sfn5122f_device_direct(void)
{
errval_t err;
struct devq* q;
-
- struct devq_func_pointer f = {
- .create = sfn5122f_create_direct,
- .enq = sfn5122f_enqueue_direct,
- .deq = sfn5122f_dequeue_direct,
- .reg = sfn5122f_register_direct,
- .dereg = sfn5122f_deregister_direct,
- .ctrl = sfn5122f_control_direct,
- };
-
- struct endpoint_state my_state = {
- .endpoint_type = ENDPOINT_TYPE_DIRECT,
- .device_name = "my_queue",
- .features = 0,
- .f = f,
- };
+ struct sfn5122f_queue* queue;
printf("SFN5122F direct device test started \n");
- err = devq_create(&q, &my_state, "sfn5122f", 1);
+ err = sfn5122f_queue_create(&queue, true, false);
if (err_is_fail(err)){
USER_PANIC("Allocating devq failed \n");
}
+
+ q = (struct devq*) queue;
err = devq_register(q, memory_rx, ®id_rx);
if (err_is_fail(err)){
USER_PANIC("Devq deregister tx failed \n");
}
- err = devq_destroy(q);
+ err = sfn5122f_queue_destroy((struct sfn5122f_queue*) q);
printf("SFN5122F direct device test ended\n");
}
-#else
-
-static void test_sfn5122f_device(void)
-{
-
- errval_t err;
- struct devq* q;
-
- struct devq_func_pointer f = {
- .create = sfn5122f_create_direct,
- .notify = notify_sfn5122f,
- };
-
- struct endpoint_state my_state = {
- .endpoint_type = ENDPOINT_TYPE_USER,
- .device_name = "my_queue",
- .features = 0,
- .f = f,
- };
-
- printf("SFN5122F device test started \n");
- err = devq_create(&q, &my_state, "sfn5122f", 0);
- if (err_is_fail(err)){
- USER_PANIC("Allocating devq failed \n");
- }
- err = devq_register(q, memory_rx, ®id_rx);
- if (err_is_fail(err)){
- USER_PANIC("Registering memory to devq failed \n");
- }
-
- err = devq_register(q, memory_tx, ®id_tx);
- if (err_is_fail(err)){
- USER_PANIC("Registering memory to devq failed \n");
- }
-
- bufferid_t ids[NUM_RX_BUF];
- lpaddr_t addr;
-
- // Enqueue RX buffers to receive into
- for (int i = 0; i < NUM_ROUNDS; i++){
- addr = phys_rx+(i*2048);
- err = devq_enqueue(q, regid_rx, addr, 2048,
- DEVQ_BUF_FLAG_RX, &ids[i]);
- if (err_is_fail(err)){
- USER_PANIC("Devq enqueue failed: %s\n", err_getstring(err));
- }
- }
-
- err = devq_notify(q);
- if (err_is_fail(err)){
- USER_PANIC("Devq notify failed: %s\n", err_getstring(err));
- }
-
- // Wait until we removed all receive buffers
- while (num_dequeue < 32) {
- event_dispatch(get_default_waitset());
- };
-
- // Send something
- char* write = NULL;
- for (int i = 0; i < NUM_ROUNDS; i++) {
- for (int z = 0; z < NUM_ENQ; z++) {
- addr = phys_tx+(i*NUM_ENQ*2048)+z*2048;
- write = va_tx + (i*NUM_ENQ*2048)+z*2048;
- for (int j = 0; j < 8; j++) {
- write[j] = udp_header[j];
- }
- for (int j = 8; j < 128; j++) {
- write[j] = 'a';
- }
-
- err = devq_enqueue(q, regid_tx, addr, 2048,
- DEVQ_BUF_FLAG_TX | DEVQ_BUF_FLAG_TX_LAST, &ids[i]);
- if (err_is_fail(err)){
- USER_PANIC("Devq enqueue failed: %s \n", err_getstring(err));
- }
- }
-
- err = devq_notify(q);
- if (err_is_fail(err)){
- USER_PANIC("Devq notify failed \n");
- }
-
- }
-
- // Dequeue TX buffers
- while (num_dequeue < 64) {
- event_dispatch(get_default_waitset());
- };
-
- err = devq_control(q, 1, 1);
- if (err_is_fail(err)){
- printf("%s \n", err_getstring(err));
- USER_PANIC("Devq control failed \n");
- }
-
- err = devq_deregister(q, regid_rx, &memory_rx);
- if (err_is_fail(err)){
- printf("%s \n", err_getstring(err));
- USER_PANIC("Devq deregister rx failed \n");
- }
-
- err = devq_deregister(q, regid_tx, &memory_tx);
- if (err_is_fail(err)){
- printf("%s \n", err_getstring(err));
- USER_PANIC("Devq deregister tx failed \n");
- }
-
- err = devq_destroy(q);
- printf("SFN5122F device test ended\n");
-}
-
-#endif
-
-#ifdef TEST_FORWARD
-static void test_forward_device(void)
-{
-
- errval_t err;
- struct devq* q;
-
- struct devq_func_pointer f = {
- .notify = notify_normal,
- };
-
- struct endpoint_state my_state = {
- .endpoint_type = ENDPOINT_TYPE_USER,
- .features = 0,
- .f = f,
- };
-
- printf("Forward device test started \n");
- err = devq_create(&q, &my_state, "forward_loopback", 1);
- if (err_is_fail(err)){
- USER_PANIC("Allocating devq failed \n");
- }
-
- err = devq_register(q, memory_rx, ®id_rx);
- if (err_is_fail(err)){
- USER_PANIC("Registering memory to devq failed \n");
- }
-
- bufferid_t ids[NUM_ENQ];
- lpaddr_t addr;
- for (int j = 0; j < NUM_ROUNDS; j++) {
- for (int i = 0; i < NUM_ENQ; i++) {
- addr = phys_rx+(j*NUM_ENQ*2048+i*2048);
- err = devq_enqueue(q, regid_rx, addr, 2048,
- 1, &ids[i]);
- if (err_is_fail(err)){
- USER_PANIC("Devq enqueue failed \n");
- }
- }
-
- err = devq_notify(q);
- if (err_is_fail(err)) {
- printf("%s",err_getstring(err));
- }
- event_dispatch(get_default_waitset());
- }
-
- err = devq_control(q, 1, 1);
- if (err_is_fail(err)){
- printf("%s \n", err_getstring(err));
- USER_PANIC("Devq control failed \n");
- }
-
- err = devq_deregister(q, regid_rx, &memory_rx);
- if (err_is_fail(err)){
- printf("%s \n", err_getstring(err));
- USER_PANIC("Devq deregister failed \n");
- }
-
- err = devq_destroy(q);
-
- printf("Forward device test ended\n");
-}
-#endif
-
int main(int argc, char *argv[])
{
//barrelfish_usleep(1000*1000*5);
}
phys_tx = id.base;
-
-#ifdef TEST_FORWARD
- test_forward_device();
- barrelfish_usleep(1000*1000*5);
-#endif
-#ifdef SFN_TEST_DIRECT
test_sfn5122f_device_direct();
barrelfish_usleep(1000*1000*5);
-#else
- test_sfn5122f_device();
- barrelfish_usleep(1000*1000*5);
-#endif
- test_normal_device();
- barrelfish_usleep(1000*1000*5);
- test_direct_device();
}