//5.49
// regarray buf_full_tbl rw addr(base, 0x00800000) [147456; 0x8] "Buffer Table" {
- regarray buf_full_tbl rw addr(base, 0x00800000) [1024; 0x8] "Buffer Table" {
+ regarray buf_full_tbl rw addr(base, 0x00800000) [8196; 0x8] "Buffer Table" {
buf_full_unused 13 "unused bits";
ip_dat_buf_size 1 type(ip_dat_buf_size)
"Buffer size";
failure RX_DISCARD "Error, packet needs to be discared",
failure ALLOC_BUF "Error allocating buffer",
failure REGISTER_REGION "Error registering a region",
+ failure DEREGISTER_REGION "Error deregistering a region",
failure ALLOC_QUEUE "Failure allocating queue",
+ failure ENQUEUE "Failure during enqueue",
};
// add a memory region to the buffer table
rpc register_region(in uint16 qid, in cap reg, out uint64 buftbl_id, out errval err);
+ rpc deregister_region(in uint64 buftbl_id, in uint64 size, out errval err);
};
#define DEVQ_BUF_FLAG_TX 0x1
#define DEVQ_BUF_FLAG_RX 0x2
+#define DEVQ_BUF_FLAG_LAST 0x4
typedef uint32_t regionid_t;
*/
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
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;
},
build library { target = "sfn5122f_devif_direct",
- cFiles = [ "sfn5122f_devif_direct.c"],
- flounderBindings = [ "sfn5122f"],
+ 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"]
return (buffer_offset - (num_buf));
}
+
+void free_buf_tbl_entries(uint64_t buftbl_idx,
+ uint32_t num_buf,
+ sfn5122f_t *d)
+{
+ uint64_t reg;
+ reg = 0;
+ reg = sfn5122f_buf_tbl_upd_reg_lo_buf_clr_cmd_insert(reg, 1);
+ reg = sfn5122f_buf_tbl_upd_reg_lo_buf_clr_start_id_insert(reg, buftbl_idx);
+ reg = sfn5122f_buf_tbl_upd_reg_lo_buf_clr_end_id_insert(reg, buftbl_idx+num_buf);
+ sfn5122f_buf_tbl_upd_reg_lo_wr(d, reg);
+ sfn5122f_buf_tbl_upd_reg_hi_wr(d, 0);
+}
+
bool userspace,
sfn5122f_t *d);
+/**
+ * @brief removes one or several 4k buffer from the buffer table
+ *
+ * @param buftbl_idx the index from which to remove the entry
+ * @param num_buf the number of buffers to remove
+ * @param d handle to device registers
+ *
+ */
+void free_buf_tbl_entries(uint64_t buftbl_idx,
+ uint32_t num_buf,
+ sfn5122f_t *d);
#endif // ndef BUFFER_TBL_H_
};
-static void cd_create_queue(struct sfn5122f_devif_binding *b, struct capref rx, struct capref tx,
- struct capref ev)
+static void cd_create_queue(struct sfn5122f_devif_binding *b, struct capref rx,
+ struct capref tx, struct capref ev)
{
// Save state so we can restore the configuration in case we need to do a
// reset
assert(err_is_ok(err));
}
-static void cd_register_region(struct sfn5122f_devif_binding *b, uint16_t qid, struct capref region)
+static void cd_register_region(struct sfn5122f_devif_binding *b, uint16_t qid,
+ struct capref region)
{
errval_t err;
struct frame_identity id;
assert(err_is_ok(err));
}
+
+static void cd_deregister_region(struct sfn5122f_devif_binding *b, uint64_t buftbl_id,
+ uint64_t size)
+{
+ errval_t err;
+ free_buf_tbl_entries(buftbl_id, size/BUF_SIZE, d);
+
+ err = b->tx_vtbl.deregister_region_response(b, NOP_CONT, SYS_ERR_OK);
+ assert(err_is_ok(err));
+}
+
static void cd_destroy_queue(struct sfn5122f_devif_binding *b, uint16_t qid)
{
USER_PANIC("NIY \n");
.create_queue_call = cd_create_queue,
.destroy_queue_call = cd_destroy_queue,
.register_region_call = cd_register_region,
+ .deregister_region_call = cd_deregister_region,
};
static void export_cb(void *st, errval_t err, iref_t iref)
#include <time.h>
#include <barrelfish/barrelfish.h>
#include <barrelfish/waitset.h>
-#include <barrelfish/deferred.h>
+#include <barrelfish/nameservice_client.h>
#include <devif/queue_interface.h>
#include <devif/sfn5122f_devif_direct.h>
+#include <if/sfn5122f_devif_defs.h>
+#include <if/sfn5122f_devif_rpcclient_defs.h>
#include "sfn5122f.h"
#include "sfn5122f_queue.h"
+#include "sfn5122f_debug.h"
+#include "helper.h"
+
+/** Misc */
+static errval_t update_rxtail(struct sfn5122f_queue* q, void *opaque, 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, void *opaque, 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 devq* q = (struct devq*) st;
+ assert(err_is_ok(err));
+
+ struct sfn5122f_queue* queue = devq_get_state(q);
+ 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;
+ DEBUG_QUEUE("Bound to interface \n");
+}
+
errval_t sfn5122f_create_direct(struct devq* q, uint64_t flags)
{
+ 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 = NULL,
- .update_rxtail = NULL
+ .update_txtail = update_txtail,
+ .update_rxtail = update_rxtail
};
/* Allocate memory for descriptor rings
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);
- // q->q = queue;
- // TODO set queue state
+ queue->bound = false;
+ devq_set_state(q, queue);
+
+ 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(),
+ IDC_BIND_FLAGS_DEFAULT);
+ 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, 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;
+ }
+
+ sfn5122f_initialize(queue->device, va);
+
return SYS_ERR_OK;
}
errval_t sfn5122f_register_direct(struct devq* q, struct capref cap,
regionid_t rid)
{
- return SYS_ERR_OK;
+ uint64_t buftbl_idx = 0;
+ errval_t err, err2;
+ struct frame_identity id;
+
+ struct sfn5122f_queue* queue = devq_get_state(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;
+ }
+
+ while (cur->next != NULL) {
+ cur = cur->next;
+ }
+
+ cur->next = entry;
+
+ return SYS_ERR_OK;
}
errval_t sfn5122f_deregister_direct(struct devq* q, regionid_t rid)
{
+ errval_t err, err2;
+ struct sfn5122f_queue* queue = devq_get_state(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;
}
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)
+{
+ // 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 & 0x0000DFFF;
+
+ 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)
+{
+ // 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 & 0x0000DFFF;
+
+ sfn5122f_queue_add_user_txbuf_devif(q, buftbl_idx, offset,
+ rid, bid, base, len, flags);
+ sfn5122f_queue_bump_txtail(q);
+ return SYS_ERR_OK;
+}
+
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 err;
+
+ struct sfn5122f_queue* queue = devq_get_state(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;
}
errval_t sfn5122f_dequeue_direct(struct devq* q, regionid_t* rid, bufferid_t* bid,
lpaddr_t* base, size_t* len, uint64_t* flags)
{
- return SYS_ERR_OK;
+ uint8_t ev_code;
+ bool exit = false;
+ errval_t err;
+
+ struct sfn5122f_queue* queue = devq_get_state(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;
}
}
/** Misc */
-static errval_t update_rxtail(void *opaque, size_t tail)
+static errval_t update_rxtail(struct sfn5122f_queue* que, void *opaque, size_t tail)
{
assert(d != NULL);
uint64_t reg = 0;
return SYS_ERR_OK;
}
-static errval_t update_txtail(void *opaque, size_t tail)
+static errval_t update_txtail(struct sfn5122f_queue* que, void *opaque, size_t tail)
{
assert(d != NULL);
uint64_t reg = 0;
#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)(void*, size_t);
- errval_t (*update_rxtail)(void*, size_t);
+ errval_t (*update_txtail)(struct sfn5122f_queue*, void*, size_t);
+ errval_t (*update_rxtail)(struct sfn5122f_queue*, void*, size_t);
};
-struct sfn5122f_queue {
+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 {
union {
sfn5122f_q_tx_user_desc_array_t* user;
sfn5122f_q_tx_ker_desc_array_t* ker;
} tx_ring;
void** tx_opaque;
+ struct devq_buf* tx_bufs;
uint16_t tx_head;
uint16_t tx_tail;
size_t tx_size;
sfn5122f_q_rx_ker_desc_array_t* ker;
} rx_ring;
void** rx_opaque;
+ struct devq_buf* rx_bufs;
uint16_t rx_head;
uint16_t rx_tail;
uint16_t rx_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;
q->tx_ring.ker = tx;
}
q->tx_opaque = malloc(sizeof(void*) * tx_size);
+ q->tx_bufs = malloc(sizeof(struct devq_buf) * tx_size);
q->tx_head = 0;
q->tx_tail = 0;
q->tx_size = tx_size;
q->rx_ring.ker = rx;
}
q->rx_opaque = malloc(sizeof(void*) * rx_size);
+ q->rx_bufs = malloc(sizeof(struct devq_buf) * rx_size);
q->rx_head = 0;
q->rx_tail = 0;
q->rx_size = rx_size;
static inline errval_t sfn5122f_queue_bump_txtail(sfn5122f_queue_t* q)
{
- return q->ops.update_txtail(q->opaque, q->tx_tail);
+ return q->ops.update_txtail(q, q->opaque, q->tx_tail);
}
static inline errval_t sfn5122f_queue_bump_rxtail(sfn5122f_queue_t* q)
{
- return q->ops.update_rxtail(q->opaque, q->rx_tail);
+ return q->ops.update_rxtail(q, q->opaque, q->rx_tail);
}
return 0;
}
+
+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);
+ q->rx_tail = (tail + 1) % q->rx_size;
+ return 0;
+}
+
static inline errval_t sfn5122f_queue_handle_rx_ev(sfn5122f_queue_t* q,
void** opaque,
size_t* len)
q->rx_head = (rx_head + 1) % q->rx_size;
return SYS_ERR_OK;
-
}
+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");
+ 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;
return SYS_ERR_OK;
}
+
+
+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(sfn5122f_queue_t* q,
uint64_t phys,
size_t len,
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_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_buf_id_insert(d, offset);
+
+ __sync_synchronize();
+
+ q->tx_tail = (tail + 1) % q->tx_size;
+ return 0;
+}
+
#endif //ndef SFN5122F_CHANNEL_H_
[ build application { target = "devif_test",
cFiles = [ "queue_interface.c" ],
- addLibraries = [ "devif" ] },
+ addLibraries = [ "devif" , "sfn5122f_devif_direct"] },
build application { target = "devif_loopback_device",
cFiles = [ "loopback_device.c" ],
build application { target = "devif_forward_device",
cFiles = [ "forward_device.c" ],
- addLibraries = [ "devif" ] },
-
- build application { target = "devif_test_sfn5122f",
- cFiles = [ "sfn5122f_device.c" ],
- addLibraries = [ "devif" , "sfn5122f_devif_direct"] }
+ addLibraries = [ "devif" ] }
]
#include <barrelfish/waitset.h>
#include <barrelfish/deferred.h>
#include <devif/queue_interface.h>
+#include <devif/sfn5122f_devif_direct.h>
//#define TEST_FOWARD
printf("Direct device test ended\n");
}
+
+static void test_sfn5122f_device(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,
+ };
+
+ printf("SFN5122F device test started \n");
+ err = devq_create(&q, &my_state, "sfn5122f", 1);
+ if (err_is_fail(err)){
+ USER_PANIC("Allocating devq failed \n");
+ }
+
+ err = devq_register(q, memory, ®id);
+ 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+(j*NUM_ENQ*2048+i*2048);
+ err = devq_enqueue(q, regid, 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, &memory);
+ if (err_is_fail(err)){
+ printf("%s \n", err_getstring(err));
+ USER_PANIC("Devq deregister failed \n");
+ }
+
+ err = devq_destroy(q);
+
+ printf("SFN5122F device test ended\n");
+}
+
#ifdef TEST_FORWARD
static void test_forward_device(void)
{
phys = id.base;
+ test_sfn5122f_device();
+ barrelfish_usleep(1000*1000*5);
#ifdef TEST_FORWARD
test_forward_device();
barrelfish_usleep(1000*1000*5);
+++ /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/sfn5122f_devif_direct.h>
-
-int main(int argc, char *argv[])
-{
-
- errval_t err;
- struct devq* q;
-
- struct endpoint_state my_state = {
- .endpoint_type = ENDPOINT_TYPE_FORWARD,
- .device_name = "", // name will be assigned
- .features = 0,
- // TODO .f
- };
-
- printf("Forward queue created\n");
- err = devq_create(&q, &my_state, "sfn5122f", 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();
-}
-