Xeon Phi DMA: Service stubs
authorReto Achermann <acreto@student.ethz.ch>
Tue, 24 Jun 2014 15:24:03 +0000 (17:24 +0200)
committerStefan Kaestle <stefan.kaestle@inf.ethz.ch>
Wed, 20 Aug 2014 21:35:48 +0000 (23:35 +0200)
Added some stubs for the service interface of the Xeon Phi DMA server.

15 files changed:
devices/xeon_phi/xeon_phi_dma.dev
errors/errno.fugu
include/xeon_phi/xeon_phi.h
lib/xeon_phi/xeon_phi_dma.c [deleted file]
lib/xeon_phi/xeon_phi_manager_client.c
lib/xeon_phi/xeon_phi_messaging.c
usr/drivers/xeon_phi/Hakefile
usr/drivers/xeon_phi/dma/dma.c [new file with mode: 0644]
usr/drivers/xeon_phi/dma/dma.h
usr/drivers/xeon_phi/dma/dma_channel.c
usr/drivers/xeon_phi/dma/dma_channel.h
usr/drivers/xeon_phi/dma/dma_mem.c [new file with mode: 0644]
usr/drivers/xeon_phi/dma/dma_mem.h [new file with mode: 0644]
usr/drivers/xeon_phi/dma/dma_service.c
usr/drivers/xeon_phi/dma/dma_service.h [new file with mode: 0644]

index ddc8ff1..179ce21 100644 (file)
@@ -14,7 +14,7 @@
 
 device xeon_phi_dma lsbfirst(addr base) "Intel Xeon Phi DMA System" {
 
-    regarray car rw addr(base, 0xA000) [8; 0x40] "DMA Channel Attribute Register" {
+    regarray dcar rw addr(base, 0xA000) [8; 0x40] "DMA Channel Attribute Register" {
         _ 23 "";
         apic_irq 1 "APIC Interrupt mask bit";
         msix_irq 1 "MSI-X Interrupt mask bit";
@@ -68,6 +68,11 @@ device xeon_phi_dma lsbfirst(addr base) "Intel Xeon Phi DMA System" {
         r 32 "";
     };
 
+    constants drar_shifts "Shift amounts for the field values" {
+        drar_size_shift=2;
+        drar_base_shift=6;
+    };
+    
     /*
      * Protection Level: Ring 0
      * Visibility: Host / Coprocessor
@@ -76,12 +81,13 @@ device xeon_phi_dma lsbfirst(addr base) "Intel Xeon Phi DMA System" {
      * Number: 8
      */
     regarray drar rw addr(base, 0xA014) [8; 0x40] "DMA Descriptor Ring Attributes Register Lo" {
-        _ 6 "";
-        base 30 "base address";
-        _ 2 "";
-        size 15 "size of the descriptor ring";
-        page 5 "";
-        _ 6 "";
+        _        6 "";
+        base    30 "base address";
+        _        2 "";  
+        size    15 "size of the descriptor ring";
+        page     5 "";
+        sysbit   1 "";
+        _        5 "";
     };
 
     /*
@@ -103,7 +109,8 @@ device xeon_phi_dma lsbfirst(addr base) "Intel Xeon Phi DMA System" {
      * Number: 8
      */
     regarray dstat rw addr(base, 0xA020) [8; 0x40] "DMA Status Channel Register" {
-        r 32 "";
+        completions 16 "Completition count";
+        _           16 "";
     };
 
     /*
@@ -159,19 +166,19 @@ device xeon_phi_dma lsbfirst(addr base) "Intel Xeon Phi DMA System" {
     register dcr rw addr(base, 0xA280) "DMA Configuration Register" {
         co0 1 "DMA Channel 0 Owner";
         ce0 1 "DMA Channel 0 Enable";
-        co1 1 "DMA Channel 0 Owner";
+        co1 1 "DMA Channel 1 Owner";
         ce1 1 "DMA Channel 1 Enable";
-        co2 1 "DMA Channel 0 Owner";
+        co2 1 "DMA Channel 2 Owner";
         ce2 1 "DMA Channel 2 Enable";
-        co3 1 "DMA Channel 0 Owner";
+        co3 1 "DMA Channel 3 Owner";
         ce3 1 "DMA Channel 3 Enable";
-        co4 1 "DMA Channel 0 Owner";
+        co4 1 "DMA Channel 4 Owner";
         ce4 1 "DMA Channel 4 Enable";
-        co5 1 "DMA Channel 0 Owner";
+        co5 1 "DMA Channel 5 Owner";
         ce5 1 "DMA Channel 5 Enable";
-        co6 1 "DMA Channel 0 Owner";
+        co6 1 "DMA Channel 6 Owner";
         ce6 1 "DMA Channel 6 Enable";
-        co7 1 "DMA Channel 0 Owner";
+        co7 1 "DMA Channel 7 Owner";
         ce7 1 "DMA Channel 7 Enable";
         arb_h 8 "Arb H";
         arb_l 7 "Arb L";
@@ -185,7 +192,7 @@ device xeon_phi_dma lsbfirst(addr base) "Intel Xeon Phi DMA System" {
      * Register Access: CRU
      */
     register dqar rw addr(base, 0xA284) "Descriptor Queue Access Register" {
-        r 32 "";
+        r 32 "";    
     };
 
     /*
index 403ad4a..31d6b19 100755 (executable)
@@ -1044,6 +1044,7 @@ errors virtio VIRTIO_ERR_ {
 errors xeon_phi XEON_PHI_ERR_ {
     failure DMA_ID_NOT_EXISTS    "The DMA transfer with that ID does not exist ",
     failure DMA_BUSY              "All DMA channels are busy",
+    failure DMA_IDLE             "All DMA channels are idle",
     failure DMA_MEM_REGISTERED   "The memory has not been registered",
     failure DMA_RPC_IN_PROGRESS  "There is currently an RPC going on",
     failure DMA_MEM_ALIGN        "The address / bytes has a wrong alignment",
index 9ab9bb7..311e748 100644 (file)
@@ -63,6 +63,9 @@
 #define XEON_PHI_SYSMEM_SIZE_BITS 39
 #define XEON_PHI_SYSMEM_SIZE (1ULL << XEON_PHI_SYSMEM_SIZE_BITS)
 
+#define XEON_PHI_SYSMEM_PAGE_SIZE (16UL*1024*1024*1024)
+#define XEON_PHI_SYSMEM_PAGE_BITS 34
+
 #define XEON_PHI_MEM_MASK 0xFFFFFFFFFFULL
 
 struct xeon_phi_boot_params
diff --git a/lib/xeon_phi/xeon_phi_dma.c b/lib/xeon_phi/xeon_phi_dma.c
deleted file mode 100644 (file)
index 32f6323..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2014 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.
- */
-
-#include <string.h>
-#include <barrelfish/barrelfish.h>
-#include <barrelfish/nameservice_client.h>
-
-typedef void (*xeon_phi_dma_done_t)(void);
-
-
-#define XEON_PHI_DMA_ALIGNMENT 64
-#define XEON_PHI_DMA_GRANULARITY 64
-
-struct xeon_phi_dma_chan
-{
-
-};
-
-/**
- * represents a DMA request which is currently being executed
- */
-struct xeon_phi_dma_request
-{
-    lpaddr_t from;
-    lpaddr_t to;
-    size_t length;
-    void *st;
-    xeon_phi_dma_done_t cb;
-    struct xeon_phi_dma_request *next;
-    struct xeon_phi_dma_request *prev;
-};
-
-#define XEON_PHI_DMA_MEM_HOST 1
-#define XEON_PHI_DMA_MEM_CARD 2
-
-/**
- * stores the memory information about the registered memory
- */
-struct xeon_phi_dma_mem
-{
-    lpaddr_t base;
-    size_t   size;
-    struct capref *cap;
-    uint8_t type;
-    struct xeon_phi_dma_mem *next;
-};
-
-static struct xeon_phi_dma_mem *dma_mem;
-
-static bool verify_address(lpaddr_t base, size_t size)
-{
-    if (dma_mem == NULL) {
-        return 0;
-    }
-
-    static struct xeon_phi_dma_mem *mem = dma_mem;
-
-    while(mem) {
-        if (mem->base > base) {
-            return 0;
-        }
-        if (mem->base <= base
-                && (base + size) <= (mem->base +mem->size)) {
-            return 1;
-        }
-        mem = mem->next;
-    }
-
-    return 0;
-}
-
-/**
- * \brief   initializes the DMA library
- */
-errval_t xeon_phi_dma_init(void);
-
-/**
- * \brief   opens a new DMA channel
- *
- * all descriptor rings owned by the host driver must exist
- * in system memory while rings owned by the coprocessor OS must
- * exist in GDDR5 memory.
- */
-errval_t xeon_phi_dma_chan_open(struct xeon_phi_dma_chan **chan);
-
-
-/**
- * \brief   closes an opened DMA channel
- */
-errval_t xeon_phi_dma_chan_close(struct xeon_phi_dma_chan *chan);
-
-errval_t xeon_phi_dma_register_memory(struct capref cap);
-
-errval_t xeon_phi_dma_deregister_memory(struct capref cap);
-
-errval_t xeon_phi_dma_exec();
-
-errval_t xeon_phi_dma_stop();
index fc974d7..0d8b8e3 100644 (file)
@@ -51,7 +51,10 @@ static void xpm_recv_register_response(struct xeon_phi_manager_binding *_binding
                                        size_t n,
                                        xeon_phi_manager_errval_t msgerr)
 {
-    DEBUG_XPMC("Registration response: ID=0x%x, num=0x%lx, err=0x%lx\n", id, n/sizeof(iref_t), msgerr);
+    DEBUG_XPMC("Registration response: ID=0x%x, num=0x%lx, err=0x%lx\n",
+               id,
+               n / sizeof(iref_t),
+               msgerr);
 
     if (err_is_fail(msgerr)) {
         conn_state = XPM_STATE_REGISTER_FAIL;
@@ -158,8 +161,11 @@ static errval_t xpm_bind(void)
     conn_state = XPM_STATE_BINDING;
 
     DEBUG_XPMC("binding... \n");
-    err = xeon_phi_manager_bind(xpm_iref, xpm_bind_cb, NULL,
-                                get_default_waitset(), IDC_BIND_FLAGS_DEFAULT);
+    err = xeon_phi_manager_bind(xpm_iref,
+                                xpm_bind_cb,
+                                NULL,
+                                get_default_waitset(),
+                                IDC_BIND_FLAGS_DEFAULT);
     if (err_is_fail(err)) {
         return err;
     }
index a3d9e09..e9f6b2a 100644 (file)
@@ -64,7 +64,6 @@ static void open_iface_call_rx(struct xeon_phi_messaging_binding *_binding,
     }
 }
 
-
 static void spawn_call_rx(struct xeon_phi_messaging_binding *_binding,
                           uint8_t core,
                           char *name,
@@ -136,8 +135,11 @@ errval_t xeon_phi_messaging_service_init(struct xeon_phi_messaging_cb *fn)
 
     struct waitset *ws = get_default_waitset();
 
-    err = xeon_phi_messaging_export(NULL, svc_export_cb, svc_connect_cb, ws,
-    IDC_EXPORT_FLAGS_DEFAULT);
+    err = xeon_phi_messaging_export(NULL,
+                                    svc_export_cb,
+                                    svc_connect_cb,
+                                    ws,
+                                    IDC_EXPORT_FLAGS_DEFAULT);
     if (err_is_fail(err)) {
         return err;
     }
@@ -203,9 +205,7 @@ errval_t xeon_phi_messaging_service_start_phi(uint8_t xeon_phi_id)
 #else
     snprintf(buf, 50, "%s", XEON_PHI_MESSAGING_NAME);
 #endif
-    XPHI_MSG_DBG("Registering iref [%u] with name [%s]\n",
-                 messaging_iref,
-                 buf);
+    XPHI_MSG_DBG("Registering iref [%u] with name [%s]\n", messaging_iref, buf);
     err = nameservice_register(buf, messaging_iref);
     if (err_is_fail(err)) {
         return err;
index 8052896..a6148e0 100644 (file)
@@ -23,7 +23,7 @@
                                  "sysmem_caps.c",
                                  "messaging.c", 
                                  "sleep.c",
-                                 "dma/dma_service.c",
+                                 "dma/dma.c",
                                  "dma/dma_channel.c",
                                  "dma/dma_descriptor_ring.c" ],
                       addLibraries = libDeps ["skb", 
@@ -53,7 +53,7 @@
                                  "sysmem_caps.c",
                                  "spawn.c",
                                  "messaging.c",
-                                 "dma/dma_service.c",
+                                 "dma/dma.c",
                                  "dma/dma_channel.c",
                                  "dma/dma_descriptor_ring.c" ],                      
                       -- flounderExtraDefs = [ ("monitor_blocking",["rpcclient"]) ],
diff --git a/usr/drivers/xeon_phi/dma/dma.c b/usr/drivers/xeon_phi/dma/dma.c
new file mode 100644 (file)
index 0000000..9c9b1fe
--- /dev/null
@@ -0,0 +1,102 @@
+/**
+ * \file
+ * \brief Driver for booting the Xeon Phi Coprocessor card on a Barrelfish Host
+ */
+
+/*
+ * Copyright (c) 2014 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <barrelfish/barrelfish.h>
+
+#include <dev/xeon_phi/xeon_phi_dma_dev.h>
+
+#include "xeon_phi.h"
+#include "dma.h"
+#include "dma_channel.h"
+#include "dma_descriptor_ring.h"
+#include "debug.h"
+
+struct dma_info
+{
+    struct xdma_channel channels[XEON_PHI_DMA_CHAN_NUM];
+    xeon_phi_dma_t dma_dev;
+    uint8_t chan_alloc_next;
+};
+
+/**
+ * \brief Initializes the DMA structure for the Xeon Phi
+ *
+ * \param phi the xeon phi DMA structure
+ *
+ * \return SYS_ERR_OK on success,
+ */
+errval_t dma_init(struct xeon_phi *phi)
+{
+    errval_t err;
+
+    /* check if already initialized */
+    if (phi->dma) {
+        return SYS_ERR_OK;
+    }
+
+    struct dma_info *info = calloc(1, sizeof(struct dma_info));
+    if (info == NULL) {
+        return LIB_ERR_MALLOC_FAIL;
+    }
+
+    xeon_phi_dma_initialize(&info->dma_dev, XEON_PHI_MMIO_TO_SBOX(phi));
+
+    XDMA_DEBUG("initializing %u channels\n", XEON_PHI_DMA_CHAN_NUM);
+    for (uint32_t i = 0; i < XEON_PHI_DMA_CHAN_NUM; ++i) {
+        struct xdma_channel *chan = &info->channels[i];
+        err = xdma_channel_init(chan,
+                                XEON_PHI_DMA_DESC_NUM,
+                                &info->dma_dev,
+                                i + XEON_PHI_DMA_CHAN_OFFSET);
+        if (err_is_fail(err)) {
+            free(info);
+            return err;
+        }
+    }
+
+    XDMA_DEBUG("initializing %u channels\n", XEON_PHI_DMA_CHAN_NUM);
+
+    phi->dma = info;
+
+    return SYS_ERR_OK;
+}
+
+/**
+ * \brief polls the owned channels for competed transfers
+ *
+ * \param phi the xeon phi to poll
+ *
+ * \returns SYS_ERR_OK if there was a transfer completed and executed correctly
+ *          XEON_PHI_ERR_DMA_IDLE if there was no transfer completed
+ *          errno otherwise
+ */
+errval_t dma_poll_channels(struct xeon_phi *phi)
+{
+    errval_t err, ret_err = XEON_PHI_ERR_DMA_IDLE;
+    for (uint32_t i = 0; i < XEON_PHI_DMA_CHAN_NUM; ++i) {
+        err = xdma_channel_poll(&phi->dma->channels[i]);
+        if (err_is_fail(err)) {
+            if (err_no(err) == XEON_PHI_ERR_DMA_IDLE) {
+                continue;
+            }
+            return err;
+        } else {
+            ret_err = SYS_ERR_OK;
+        }
+    }
+    return ret_err;
+}
+
index b826a0b..f169cfc 100644 (file)
 #define XEON_PHI_DMA_OWNER_HOST         1
 #define XEON_PHI_DMA_OWNER_CARD         2
 
-
+/// the number of dma descriptors we allocate
+#define XEON_PHI_DMA_DESC_NUM  128
 
 
 /// alignment constraint of the descriptor ring (cache line)
 #define XEON_PHI_DMA_DESC_RING_ALIGN 64
 
 
+
 /**
  * \brief Initializes the DMA structure for the Xeon Phi
  *
  */
 errval_t dma_init(struct xeon_phi *phi);
 
+/**
+ * \brief polls the owned channels for competed transfers
+ *
+ * \param phi the xeon phi to poll
+ *
+ * \returns SYS_ERR_OK if there was a transfer completed and executed correctly
+ *          XEON_PHI_ERR_DMA_IDLE if there was no transfer completed
+ *          errno otherwise
+ */
+errval_t dma_poll_channels(struct xeon_phi *phi);
+
+
+
 #endif /* XEON_PHI_DMA_H */
index bc04c7e..8d940d8 100644 (file)
 #include "dma_descriptor_ring.h"
 #include "debug.h"
 
-
 static inline void xdma_channel_set_headptr(struct xdma_channel *chan,
                                             uint16_t entry)
 {
-    xeon_phi_dma_dhpr_index_wrf(chan->regs, chan->chanid, entry);
+    chan->head = entry;
+    xeon_phi_dma_dhpr_index_wrf(chan->regs, chan->chanid, entry - 1);
 }
 
 static inline uint16_t xdma_channel_get_headptr(struct xdma_channel *chan)
@@ -48,6 +48,159 @@ static inline uint16_t xdma_channel_get_tailptr(struct xdma_channel *chan)
     return xeon_phi_dma_dtpr_index_rdf(chan->regs, chan->chanid);
 }
 
+static void xdma_channel_set_owner(struct xdma_channel *chan,
+                                   enum xdma_chan_owner owner)
+{
+    xeon_phi_dma_dcr_t dcr = xeon_phi_dma_dcr_rd(chan->regs);
+
+    uint8_t owner_val;
+    if (owner == XDMA_CHAN_CARD_OWNED) {
+        owner_val = 0;
+    } else {
+        owner_val = 1;
+    }
+
+    switch (chan->chanid) {
+        case 0x0:
+            dcr = xeon_phi_dma_dcr_co0_insert(dcr, owner_val);
+            break;
+        case 0x1:
+            dcr = xeon_phi_dma_dcr_co1_insert(dcr, owner_val);
+            break;
+        case 0x2:
+            dcr = xeon_phi_dma_dcr_co2_insert(dcr, owner_val);
+            break;
+        case 0x3:
+            dcr = xeon_phi_dma_dcr_co3_insert(dcr, owner_val);
+            break;
+        case 0x4:
+            dcr = xeon_phi_dma_dcr_co4_insert(dcr, owner_val);
+            break;
+        case 0x5:
+            dcr = xeon_phi_dma_dcr_co5_insert(dcr, owner_val);
+            break;
+        case 0x6:
+            dcr = xeon_phi_dma_dcr_co6_insert(dcr, owner_val);
+            break;
+        case 0x7:
+            dcr = xeon_phi_dma_dcr_co7_insert(dcr, owner_val);
+            break;
+    }
+
+    xeon_phi_dma_dcr_wr(chan->regs, dcr);
+
+    chan->owner = owner;
+}
+
+static void xdma_channel_set_state(struct xdma_channel *chan,
+                                   enum xdma_chan_state state)
+{
+    xeon_phi_dma_dcr_t dcr = xeon_phi_dma_dcr_rd(chan->regs);
+
+    uint8_t enabled_val;
+    if (state == XDMA_CHAN_STATE_ENABLED) {
+        enabled_val = 0x1;
+    } else {
+        enabled_val = 0x0;
+    }
+    switch (chan->chanid) {
+        case 0x0:
+            dcr = xeon_phi_dma_dcr_ce0_insert(dcr, enabled_val);
+            break;
+        case 0x1:
+            dcr = xeon_phi_dma_dcr_ce1_insert(dcr, enabled_val);
+            break;
+        case 0x2:
+            dcr = xeon_phi_dma_dcr_ce2_insert(dcr, enabled_val);
+            break;
+        case 0x3:
+            dcr = xeon_phi_dma_dcr_ce3_insert(dcr, enabled_val);
+            break;
+        case 0x4:
+            dcr = xeon_phi_dma_dcr_ce4_insert(dcr, enabled_val);
+            break;
+        case 0x5:
+            dcr = xeon_phi_dma_dcr_ce5_insert(dcr, enabled_val);
+            break;
+        case 0x6:
+            dcr = xeon_phi_dma_dcr_ce6_insert(dcr, enabled_val);
+            break;
+        case 0x7:
+            dcr = xeon_phi_dma_dcr_ce7_insert(dcr, enabled_val);
+            break;
+    }
+
+    chan->state = state;
+
+    xeon_phi_dma_dcr_wr(chan->regs, dcr);
+}
+
+
+static inline void xdma_channel_set_dstat_wb(struct xdma_channel *chan,
+                                             lpaddr_t dstat_wb)
+{
+    xeon_phi_dma_dstatwb_lo_wr(chan->regs, chan->chanid, (uint32_t)dstat_wb);
+    xeon_phi_dma_dstatwb_hi_wr(chan->regs, chan->chanid, (uint32_t)(dstat_wb >> 32));
+    chan->dstat_wb = dstat_wb;
+}
+
+
+static inline uint8_t xdma_channel_intr_pending(struct xdma_channel *chan)
+{
+    return xeon_phi_dma_dcar_irq_status_rdf(chan->regs, chan->chanid);
+}
+
+/**
+ * \brief sets the interrupt status according to the mask flag
+ *
+ * \param chan the dma channel to change the interrupts
+ * \param mask if 0 unmask or enabling the interrupts
+ *             if 1 masking or disabling the interrupts
+ */
+static uint32_t xdma_channel_mask_intr(struct xdma_channel *chan,
+                                       uint8_t mask)
+{
+    uint8_t mask_val = (mask) ? 0x1 : 0x0;
+
+    if (chan->owner == XDMA_CHAN_HOST_OWNED) {
+        xeon_phi_dma_dcar_msix_irq_wrf(chan->regs, chan->chanid, mask_val);
+    } else {
+        xeon_phi_dma_dcar_apic_irq_wrf(chan->regs, chan->chanid, mask_val);
+    }
+
+    return xeon_phi_dma_dcar_rd(chan->regs, chan->chanid);
+}
+
+
+static errval_t xdma_channel_set_ring(struct xdma_channel *chan)
+{
+    assert(!(chan->ring.size & 0x3));
+    assert(!(chan->ring.pbase & 0x3F));
+
+    xdma_channel_set_state(chan, XDMA_CHAN_STATE_DISABLED);
+
+    xeon_phi_dma_drar_t drar = 0x0;
+
+    drar = xeon_phi_dma_drar_size_insert(drar, chan->size >> 2);
+
+    if (chan->owner == XDMA_CHAN_HOST_OWNED) {
+        drar = xeon_phi_dma_drar_sysbit_insert(drar, 0x1);
+        uint32_t sysmem_page = (chan->ring.pbase >> XEON_PHI_SYSMEM_PAGE_BITS);
+        drar = xeon_phi_dma_drar_page_insert(drar, sysmem_page);
+    }
+
+    drar = xeon_phi_dma_drar_base_insert(drar, chan->ring.pbase >> 6);
+
+    xeon_phi_dma_drar_wr(chan->regs, chan->chanid, drar);
+
+    chan->size = chan->ring.size;
+
+    chan->tail = xdma_channel_get_tailptr(chan);
+
+    xdma_channel_set_state(chan, XDMA_CHAN_STATE_ENABLED);
+}
+
+
 static uint16_t xdma_channel_get_desc_avail_count(struct xdma_channel *chan)
 {
     assert(!"NYI");
@@ -73,7 +226,21 @@ errval_t xdma_channel_init(struct xdma_channel *chan,
                            xeon_phi_dma_t *regs,
                            uint8_t chanid)
 {
+    assert(!"NYI");
+
+    /*
+     * initialize the configuration register
+     */
+#ifdef __k1om__
+    xdma_channel_set_owner(chan, XDMA_CHAN_CARD_OWNED);
+#else
+    xdma_channel_set_owner(chan, XDMA_CHAN_HOST_OWNED);
+#endif
+
+
+    xdma_channel_set_state(chan, XDMA_CHAN_STATE_ENABLED);
 
+    return SYS_ERR_OK;
 }
 
 /**
@@ -85,7 +252,8 @@ errval_t xdma_channel_init(struct xdma_channel *chan,
  */
 errval_t xdma_channel_free(struct xdma_channel *chan)
 {
-
+    assert(!"NYI");
+    return SYS_ERR_OK;
 }
 
 /**
@@ -104,27 +272,65 @@ errval_t xdma_channel_req_memcpy(struct xdma_channel *chan,
     assert(setup->type == XDMA_REQ_TYPE_MEMCPY);
     assert(!(setup->info.mem.dst & XEON_PHI_MEM_MASK));
     assert(!(setup->info.mem.src & XEON_PHI_MEM_MASK));
+    assert(!(setup->info.mem.bytes & (XEON_PHI_DMA_ALIGNMENT-1)));
 
-    uint32_t num_desc_needed = (setup->info.mem.bytes
-                    + XEON_PHI_DMA_REQ_SIZE_MAX - 1) / XEON_PHI_DMA_REQ_SIZE_MAX;
+    uint32_t num_desc_needed =
+                    (setup->info.mem.bytes + XEON_PHI_DMA_REQ_SIZE_MAX - 1) / XEON_PHI_DMA_REQ_SIZE_MAX;
 
-    if (num_desc_needed > XEON_PHI_DMA_DESC_RING_MAX
-                    || num_desc_needed > xdma_channel_get_desc_avail_count(chan)) {
+    if (num_desc_needed > XEON_PHI_DMA_DESC_RING_MAX || num_desc_needed
+                    > xdma_channel_get_desc_avail_count(chan)) {
         /* we do not support huge requests at this stage... */
     }
 
+    XDMA_DEBUG("memcpy request: %lu bytes, %u descriptors\n",
+               setup->info.mem.bytes,
+               num_desc_needed);
 
+    lpaddr_t src = setup->info.mem.src;
+    lpaddr_t dst = setup->info.mem.dst;
+    size_t bytes = setup->info.mem.bytes;
+    uint16_t entry = chan->head;
+    void *desc = NULL;
+    struct xdma_req_info *rinfo = chan->rinfo + entry;
 
-    XDEBUG_DMA("memcpy request: %lu bytes, %lu descriptors\n",
-               setup->info.mem.bytes, num_desc_needed);
+    rinfo->binding = setup->binding;
+    while (bytes > XEON_PHI_DMA_REQ_SIZE_MAX) {
+        desc = xdma_desc_get_entry(&chan->ring, entry);
+        assert(desc);
 
-    for(uint16_t i = 0; i < num_desc_needed; ++i) {
+        xdma_desc_set_memcpy(desc, src, dst, XEON_PHI_DMA_REQ_SIZE_MAX, 0);
 
+        rinfo->head = 0;
+        rinfo->done = 0;
+        rinfo->last = 0;
+
+        dst += XEON_PHI_DMA_REQ_SIZE_MAX;
+        src += XEON_PHI_DMA_REQ_SIZE_MAX;
+        bytes -= XEON_PHI_DMA_REQ_SIZE_MAX;
+        entry = (entry + 1) % chan->ring.size;
+        rinfo = chan->rinfo + entry;
     }
 
+    if (bytes) {
+        assert(bytes < XEON_PHI_DMA_REQ_SIZE_MAX);
+        xdma_desc_set_memcpy(desc, src, dst, bytes, 0);
+        entry = (entry + 1) % chan->ring.size;
+        rinfo->head = 0;
+        rinfo->done = 0;
+        rinfo->last = 1;
+    }
 
+    rinfo = chan->rinfo + chan->head;
+    rinfo->head = 1;
+    rinfo = chan->rinfo + entry - 1;
+    rinfo->last = 1;
+
+    xdma_channel_set_headptr(chan, entry);
 
     if (id) {
 
     }
+
+    assert(!"NYI");
+    return SYS_ERR_OK;
 }
index 901f984..d727c91 100644 (file)
 
 #define XEON_PHI_DMA_REQ_SIZE_MAX  (((1U) * 1024 * 1024) >> 1)
 
+enum xdma_chan_owner {
+    XDMA_CHAN_CARD_OWNED = 0,
+    XDMA_CHAN_HOST_OWNED
+};
+
+enum xdma_chan_state {
+    XDMA_CHAN_STATE_INVALID,
+    XDMA_CHAN_STATE_DISABLED,
+    XDMA_CHAN_STATE_ENABLED
+};
+
 struct xdma_req_info
 {
     struct xeon_phi_dma_binding *binding;
@@ -40,9 +51,12 @@ struct xdma_channel
     uint16_t tail;           ///< the tail pointer of the ring (cached)
     uint16_t head;           ///< the head pointer of the ring
     uint16_t size;           ///< size of the channel (elements in descriptor ring)
-    struct xdma_req *reqs;   ///< stores request information for the descriptors
+    struct xdma_req_info *rinfo;  ///< stores request information for the descriptors
     uint8_t chanid;          ///< channel id
+    enum xdma_chan_owner owner; ///< the owner of the channel
+    enum xdma_chan_state state;
     uint32_t reqcoutner;     ///< request counter
+    lpaddr_t dstat_wb;
 };
 
 enum xdma_req_type
@@ -162,6 +176,14 @@ errval_t xdma_channel_req_stop(struct xdma_channel *chan,
 /**
  *
  */
+errval_t xdma_channel_intr_handler(struct xdma_channel *chan);
+
+/**
+ *
+ */
 errval_t xdma_channel_poll(struct xdma_channel *chan);
 
+
+
+
 #endif /* XEON_PHI_DMA_DESC_RING_H */
diff --git a/usr/drivers/xeon_phi/dma/dma_mem.c b/usr/drivers/xeon_phi/dma/dma_mem.c
new file mode 100644 (file)
index 0000000..826bbd2
--- /dev/null
@@ -0,0 +1,92 @@
+/**
+ * \file
+ * \brief Driver for booting the Xeon Phi Coprocessor card on a Barrelfish Host
+ */
+
+/*
+ * Copyright (c) 2014 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.
+ */
+
+#include <barrelfish/barrelfish.h>
+#include "xeon_phi.h"
+
+#include <if/xeon_phi_dma_defs.h>
+
+struct xdma_mem
+{
+    struct xeon_phi *phi;
+    struct xeon_phi_dma_binding *b;
+    struct xdma_mem_entry *head;
+};
+
+struct xdma_mem_entry
+{
+    struct capref cap;
+    lpaddr_t paddr;
+    size_t size;
+    struct xdma_mem_entry *next;
+    struct xdma_mem_entry *prev;
+};
+
+/**
+ * \brief initializes the memory manager for the range checks
+ */
+errval_t xdma_mem_init(struct xeon_phi_dma_binding *binding,
+                       struct xeon_phi *phi)
+{
+    struct xdma_mem *xmem = calloc(1, sizeof(struct xdma_mem));
+    if (xmem == NULL) {
+        return LIB_ERR_MALLOC_FAIL;
+    }
+
+    xmem->b = binding;
+    xmem->phi = phi;
+    binding->st = xmem;
+
+    return SYS_ERR_OK;
+}
+
+/**
+ * \brief registers a new block of memory to be used with the DMA engine
+ */
+errval_t xdma_mem_register(struct xdma_mem *mem,
+                           struct capref cap)
+{
+
+}
+
+/**
+ * \brief removes a block of memory from the usable regions
+ */
+errval_t xdma_mem_deregister(struct xdma_mem *mem,
+                             struct capref cap)
+{
+
+}
+
+/**
+ * \brief verifies that a certain memory range is within the previously
+ *        registered memory range
+ */
+errval_t xdma_mem_verify(struct xdma_mem *mem,
+                         lpaddr_t addr,
+                         size_t size)
+{
+
+}
+
+/**
+ * \brief verifies the memory range and translates into the DMA usable format
+ */
+lpaddr_t xdma_mem_translate(struct xdma_mem *mem,
+                            lpaddr_t addr,
+                            size_t size)
+{
+
+}
+
diff --git a/usr/drivers/xeon_phi/dma/dma_mem.h b/usr/drivers/xeon_phi/dma/dma_mem.h
new file mode 100644 (file)
index 0000000..33f750b
--- /dev/null
@@ -0,0 +1,56 @@
+/**
+ * \file
+ * \brief Driver for booting the Xeon Phi Coprocessor card on a Barrelfish Host
+ */
+
+/*
+ * Copyright (c) 2014 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.
+ */
+
+#ifndef XEON_PHI_DMA_MEM_H
+#define XEON_PHI_DMA_MEM_H
+
+struct xdma_mem;
+
+enum xdma_mem_type
+{
+    XDMA_MEM_TYPE_HOST,
+    XDMA_MEM_TYPE_CARD
+};
+
+
+/**
+ * \brief initializes the memory manager for the range checks
+ */
+errval_t xdma_mem_init(struct xeon_phi_dma_binding *binding,
+                       struct xeon_phi *phi);
+
+/**
+ * \brief registers a new block of memory to be used with the DMA engine
+ */
+errval_t xdma_mem_register(struct xdma_mem *mem,
+                           struct capref cap);
+
+
+/**
+ * \brief removes a block of memory from the usable regions
+ */
+errval_t xdma_mem_deregister(struct xdma_mem *mem,
+                             struct capref cap);
+
+
+/**
+ * \brief verifies that a certain memory range is within the previously
+ *        registered memory range
+ */
+errval_t xdma_mem_verify(struct xdma_mem *mem,
+                         lpaddr_t addr,
+                         size_t   size);
+
+
+#endif /* XEON_PHI_DMA_DESC_RING_H */
index 5e853df..8e5b4d9 100644 (file)
 #include <string.h>
 #include <barrelfish/barrelfish.h>
 
-#include <dev/xeon_phi/xeon_phi_dma_dev.h>
+#include <if/xeon_phi_dma_defs.h>
 
 #include "xeon_phi.h"
 #include "dma.h"
+#include "dma_mem.h"
 #include "dma_channel.h"
-#include "dma_descriptor_ring.h"
 #include "debug.h"
 
+/**
+ * enumration of all possible states of the service exportation process
+ */
+enum xpm_svc_state
+{
+    XPM_SVC_STATE_EXPORTING,
+    XPM_SVC_STATE_EXPORT_OK,
+    XPM_SVC_STATE_EXPORT_FAIL,
+    XPM_SVC_STATE_NS_REGISTERING,
+    XPM_SVC_STATE_NS_REGISTER_OK,
+    XPM_SVC_STATE_NS_REGISTER_FAIL,
+    XPM_SVC_STATE_RUNNING
+};
+
+/// represents the current state of the exporting process
+static enum xpm_svc_state svc_state = XPM_SVC_STATE_EXPORTING;
+
+/// our own iref of the exported service
+static iref_t dma_iref;
+
+/*
+ * ----------------------------------------------------------------------------
+ * Memory:  registration
+ * ----------------------------------------------------------------------------
+ */
+
+struct dma_reg_resp_st
+{
+    struct xeon_phi_dma_binding *b;
+    errval_t err;
+};
+
+static void dma_register_response_tx(void *a)
+{
+    errval_t err;
+
+    struct dma_reg_resp_st *st = a;
+
+    struct event_closure txcont = MKCONT(free, a);
+
+    err = xeon_phi_dma_register_response__tx(st->b, txcont, st->err);
+    if (err_is_fail(err)) {
+        if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
+            txcont = MKCONT(dma_register_response_tx, a);
+            if (err_is_fail(err)) {
+                USER_PANIC_ERR(err, "could not send reply");
+            }
+        }
+    }
+}
+
+static void dma_register_call_rx(struct xeon_phi_dma_binding *_binding,
+                                 struct capref memory)
+{
+
+}
+
+/*
+ * ----------------------------------------------------------------------------
+ * Memory: de-registration
+ * ----------------------------------------------------------------------------
+ */
+
+struct dma_dereg_resp_st
+{
+    struct xeon_phi_dma_binding *b;
+    errval_t err;
+};
+
+static void dma_deregister_response_tx(void *a)
+{
+    errval_t err;
+
+    struct dma_dereg_resp_st *st = a;
+
+    struct event_closure txcont = MKCONT(free, a);
+
+    err = xeon_phi_dma_deregister_response__tx(st->b, txcont, st->err);
+    if (err_is_fail(err)) {
+        if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
+            txcont = MKCONT(dma_deregister_response_tx, a);
+            if (err_is_fail(err)) {
+                USER_PANIC_ERR(err, "could not send reply");
+            }
+        }
+    }
+}
+
+static void dma_deregister_call_rx(struct xeon_phi_dma_binding *_binding,
+                                   struct capref memory)
+{
+
+}
+
+/*
+ * ----------------------------------------------------------------------------
+ * Transfer Control: START
+ * ----------------------------------------------------------------------------
+ */
+struct dma_exec_resp_st
+{
+    struct xeon_phi_dma_binding *b;
+    xeon_phi_dma_id_t id;
+    errval_t err;
+};
 
-struct dma_info {
-    struct xdma_channel channels[XEON_PHI_DMA_CHAN_NUM];
-    xeon_phi_dma_t dma_dev;
+static void dma_exec_response_tx(void *a)
+{
+    errval_t err;
+
+    struct dma_exec_resp_st *st = a;
+
+    struct event_closure txcont = MKCONT(free, a);
+
+    err = xeon_phi_dma_exec_response__tx(st->b, txcont, st->id, st->err);
+    if (err_is_fail(err)) {
+        if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
+            txcont = MKCONT(dma_exec_response_tx, a);
+            if (err_is_fail(err)) {
+                USER_PANIC_ERR(err, "could not send reply");
+            }
+        }
+    }
+}
+
+static void dma_exec_call_rx(struct xeon_phi_dma_binding *_binding,
+                             uint64_t src,
+                             uint64_t dst,
+                             uint64_t length)
+{
+
+}
+
+/*
+ * ----------------------------------------------------------------------------
+ * Transfer Control: STOP
+ * ----------------------------------------------------------------------------
+ */
+
+struct dma_stop_resp_st
+{
+    struct xeon_phi_dma_binding *b;
+    errval_t err;
 };
 
+static void dma_stop_response_tx(void *a)
+{
+    errval_t err;
+
+    struct dma_exec_resp_st *st = a;
+
+    struct event_closure txcont = MKCONT(free, a);
+
+    err = xeon_phi_dma_stop_response__tx(st->b, txcont, st->err);
+    if (err_is_fail(err)) {
+        if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
+            txcont = MKCONT(dma_stop_response_tx, a);
+            if (err_is_fail(err)) {
+                USER_PANIC_ERR(err, "could not send reply");
+            }
+        }
+    }
+}
+
+static void dma_stop_call_rx(struct xeon_phi_dma_binding *_binding,
+                             xeon_phi_dma_id_t id)
+{
+
+}
+
+struct xeon_phi_dma_rx_vtbl dma_rx_vtbl = {
+    .register_call = dma_register_call_rx,
+    .deregister_call = dma_deregister_call_rx,
+    .exec_call = dma_exec_call_rx,
+    .stop_call = dma_stop_call_rx
+};
+
+/*
+ * ----------------------------------------------------------------------------
+ * Flounder callbacks for export and connect events
+ * ----------------------------------------------------------------------------
+ */
+
+static errval_t svc_connect_cb(void *st,
+                               struct xeon_phi_dma_binding *b)
+{
+    XPHI_MSG_DBG("New connection request\n");
+    b->rx_vtbl = dma_rx_vtbl;
+
+    /*
+     * TODO: set the state
+     */
+
+    return SYS_ERR_OK;
+}
+
 /**
- * \brief Initializes the DMA structure for the Xeon Phi
- *
- * \param phi the xeon phi DMA structure
- *
- * \return SYS_ERR_OK on success,
+ * \brief
  */
-errval_t dma_init(struct xeon_phi *phi)
+static void svc_export_cb(void *st,
+                          errval_t err,
+                          iref_t iref)
 {
-    /* check if already initialized */
-    if (phi->dma) {
-        return SYS_ERR_OK;
+    if (err_is_fail(err)) {
+        svc_state = XPM_SVC_STATE_EXPORT_FAIL;
+        return;
     }
 
-    struct dma_info *info = calloc(1, sizeof(struct dma_info));
-    if (info == NULL) {
-        return LIB_ERR_MALLOC_FAIL;
+    dma_iref = iref;
+
+    svc_state = XPM_SVC_STATE_EXPORT_OK;
+}
+
+errval_t dma_service_init(uint8_t xeon_phi_id)
+{
+    errval_t err;
+
+#ifdef __k1om__
+    assert(xeon_phi_id == 0);
+#endif
+
+    XDMA_DEBUG("Initializing DMA service\n");
+
+    struct waitset *ws = get_default_waitset();
+
+    err = xeon_phi_messaging_export(NULL,
+                                    svc_export_cb,
+                                    svc_connect_cb,
+                                    ws,
+                                    IDC_EXPORT_FLAGS_DEFAULT);
+    if (err_is_fail(err)) {
+        return err;
     }
 
-    XDMA_DEBUG("initializing %u channels\n", XEON_PHI_DMA_CHAN_NUM);
-    for (uint32_t i = 0; i < XEON_PHI_DMA_CHAN_NUM; ++i) {
-        struct xdma_channel *chan = &info->channels[i];
-        chan->chanid = i + XEON_PHI_DMA_CHAN_OFFSET;
+    XDMA_DEBUG("Waiting for export...\n");
+    while (svc_state == XPM_SVC_STATE_EXPORTING) {
+        messages_wait_and_handle_next();
+    }
 
+    if (svc_state == XPM_SVC_STATE_EXPORT_FAIL) {
+        return FLOUNDER_ERR_BIND;
     }
 
+    svc_state = XPM_SVC_STATE_NS_REGISTERING;
 
+    char buf[50];
+    snprintf(buf, 50, "%s.%u", XEON_PHI_DMA_SERVICE_NAME, xeon_phi_id);
+
+    XDMA_DEBUG("Registering iref [%u] with name [%s]\n", dma_iref, buf);
+    err = nameservice_register(buf, dma_iref);
+    if (err_is_fail(err)) {
+        svc_state = XPM_SVC_STATE_NS_REGISTER_FAIL;
+        return err;
+    }
+
+    svc_state = XPM_SVC_STATE_RUNNING;
 
     return SYS_ERR_OK;
+
 }
 
+/*
+ * ---------------------------------------------------------------------------
+ * Send the done notification
+ * ---------------------------------------------------------------------------
+ */
+struct dma_done_st
+{
+    struct xeon_phi_dma_binding *b;
+    xeon_phi_dma_id_t id;
+    errval_t err;
+};
+
+static void dma_done_tx(void *a)
+{
+    errval_t err;
+
+    struct dma_done_st *st = a;
+
+    struct event_closure txcont = MKCONT(free, a);
+
+    err = xeon_phi_dma_stop_response__tx(st->b, txcont, st->id, st->err);
+    if (err_is_fail(err)) {
+        if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
+            txcont = MKCONT(dma_done_tx, a);
+            if (err_is_fail(err)) {
+                USER_PANIC_ERR(err, "could not send reply");
+            }
+        }
+    }
+}
+
+errval_t dma_service_send_done(struct xeon_phi_dma_binding *b,
+                               xeon_phi_dma_id_t id,
+                               errval_t err)
+{
+    XDMA_DEBUG("sending done notification: %lu\n", id);
+
+    struct dma_done_st *st = malloc(sizeof(struct dma_done_st));
+    if (st == NULL) {
+        return LIB_ERR_MALLOC_FAIL;
+    }
+
+    st->b = b;
+    st->id = id;
+    st->err = err;
+
+    dma_done_tx(st);
+
+    return SYS_ERR_OK;
+}
diff --git a/usr/drivers/xeon_phi/dma/dma_service.h b/usr/drivers/xeon_phi/dma/dma_service.h
new file mode 100644 (file)
index 0000000..c336136
--- /dev/null
@@ -0,0 +1,22 @@
+/**
+ * \file
+ * \brief Driver for booting the Xeon Phi Coprocessor card on a Barrelfish Host
+ */
+
+/*
+ * Copyright (c) 2014 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.
+ */
+#ifndef XEON_PHI_DMA_SERVICE_H
+#define XEON_PHI_DMA_SERVICE_H
+
+
+errval_t dma_service_init(void);
+
+
+
+#endif /* XEON_PHI_DMA_H */