DeviceQueue: Solarflare backend fully implemented
authorRoni Häcki <roni.haecki@inf.ethz.ch>
Fri, 9 Sep 2016 14:46:37 +0000 (16:46 +0200)
committerRoni Häcki <roni.haecki@inf.ethz.ch>
Fri, 9 Sep 2016 14:46:37 +0000 (16:46 +0200)
Signed-off-by: Roni Häcki <roni.haecki@inf.ethz.ch>

15 files changed:
devices/sfn5122f.dev
errors/errno.fugu
if/sfn5122f_devif.if
include/devif/queue_interface.h
lib/devif/queue_interface.c
usr/drivers/solarflare/Hakefile
usr/drivers/solarflare/buffer_tbl.c
usr/drivers/solarflare/buffer_tbl.h
usr/drivers/solarflare/sfn5122f_cdriver.c
usr/drivers/solarflare/sfn5122f_devif_direct.c
usr/drivers/solarflare/sfn5122f_qdriver.c
usr/drivers/solarflare/sfn5122f_queue.h
usr/tests/devif/Hakefile
usr/tests/devif/queue_interface.c
usr/tests/devif/sfn5122f_device.c [deleted file]

index f0deb54..5c5866d 100644 (file)
@@ -267,7 +267,7 @@ device sfn5122f msbfirst ( addr base )
    //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";
index 1b0067d..117016f 100755 (executable)
@@ -1242,6 +1242,8 @@ errors sfn SFN_ERR_{
     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", 
 };
 
index 4f5cbed..26db092 100644 (file)
@@ -23,5 +23,6 @@ interface sfn5122f_devif "sfn5122f devif communication interface" {
 
     // 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);
 
 };
index 69bde31..c20d14d 100644 (file)
@@ -27,6 +27,7 @@
 
 #define DEVQ_BUF_FLAG_TX 0x1
 #define DEVQ_BUF_FLAG_RX 0x2
+#define DEVQ_BUF_FLAG_LAST 0x4
 
 
 typedef uint32_t regionid_t;
@@ -284,6 +285,16 @@ void devq_allocate_state(struct devq *q, size_t bytes);
  */
 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
index 3ab245c..a6cf6ac 100644 (file)
@@ -641,6 +641,11 @@ 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;
index ae412fb..188867a 100644 (file)
                     }, 
 
   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"]
index 97a5931..fc3894e 100644 (file)
@@ -74,3 +74,17 @@ uint64_t alloc_buf_tbl_entries(uint64_t phys_addr,
     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); 
+}
+
index cb1521e..52d9622 100644 (file)
@@ -33,4 +33,15 @@ uint64_t alloc_buf_tbl_entries(uint64_t phys_addr,
                                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_
index 6f4013b..605c28c 100644 (file)
@@ -1374,8 +1374,8 @@ static struct sfn5122f_rx_vtbl rx_vtbl = {
 };
 
 
-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
@@ -1425,7 +1425,8 @@ static void cd_create_queue(struct sfn5122f_devif_binding *b, struct capref rx,
     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;
@@ -1451,6 +1452,17 @@ static void cd_register_region(struct sfn5122f_devif_binding *b, uint16_t qid, s
     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");
@@ -1461,6 +1473,7 @@ static struct sfn5122f_devif_rx_vtbl rx_vtbl_devif = {
     .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)
index 8b72436..c9b538b 100644 (file)
 #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  
@@ -50,22 +110,131 @@ errval_t sfn5122f_create_direct(struct devq* q, uint64_t flags)
         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, &regs, &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;
 }
 
@@ -86,16 +255,154 @@ errval_t sfn5122f_destroy_direct(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)
+{
+    // 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;
 }
 
index 59f8746..4796b63 100644 (file)
@@ -231,7 +231,7 @@ static size_t check_for_new_events(void)
 }
 
 /**  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;
@@ -246,7 +246,7 @@ static errval_t update_rxtail(void *opaque, size_t tail)
     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;
index 5d46916..8f16ec1 100644 (file)
 #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;
@@ -42,6 +56,7 @@ struct sfn5122f_queue {
         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;
@@ -55,6 +70,16 @@ struct sfn5122f_queue {
     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;
@@ -77,6 +102,7 @@ static inline sfn5122f_queue_t* sfn5122f_queue_init(void* tx,
         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;
@@ -87,6 +113,7 @@ static inline sfn5122f_queue_t* sfn5122f_queue_init(void* tx,
         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;
@@ -125,13 +152,13 @@ static inline uint8_t sfn5122f_get_event_code(sfn5122f_queue_t* queue)
 
 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);
 }
 
 
@@ -215,6 +242,34 @@ static inline int sfn5122f_queue_add_user_rxbuf(sfn5122f_queue_t* q,
     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)
@@ -264,10 +319,69 @@ static inline errval_t sfn5122f_queue_handle_rx_ev(sfn5122f_queue_t* q,
 
     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;
@@ -341,6 +455,51 @@ static inline errval_t sfn5122f_queue_handle_tx_ev(sfn5122f_queue_t* q, void** o
 
     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, 
@@ -364,5 +523,41 @@ static inline int sfn5122f_queue_add_txbuf(sfn5122f_queue_t* q,
     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_
 
index e9f2661..6faac02 100644 (file)
@@ -12,7 +12,7 @@
 
 [ 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" ],
@@ -20,9 +20,5 @@
 
   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" ] }
 ]
index 01cb4a0..19b0d7d 100644 (file)
@@ -14,6 +14,7 @@
 #include <barrelfish/waitset.h>
 #include <barrelfish/deferred.h>
 #include <devif/queue_interface.h>
+#include <devif/sfn5122f_devif_direct.h>
 
 
 //#define TEST_FOWARD
@@ -278,6 +279,82 @@ static void test_direct_device(void)
     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, &regid);
+    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) 
 {
@@ -360,6 +437,8 @@ int main(int argc, char *argv[])
     
     phys = id.base;
 
+    test_sfn5122f_device();
+    barrelfish_usleep(1000*1000*5);
 #ifdef TEST_FORWARD
     test_forward_device();
     barrelfish_usleep(1000*1000*5);
diff --git a/usr/tests/devif/sfn5122f_device.c b/usr/tests/devif/sfn5122f_device.c
deleted file mode 100644 (file)
index 96166a5..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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();
-}
-