libdma: added stubbs for Xeon Phi DMA Driver
authorReto Achermann <acreto@student.ethz.ch>
Thu, 24 Jul 2014 17:16:46 +0000 (19:16 +0200)
committerStefan Kaestle <stefan.kaestle@inf.ethz.ch>
Wed, 20 Aug 2014 21:39:55 +0000 (23:39 +0200)
20 files changed:
devices/xeon_phi/xeon_phi_dma_chan.dev [new file with mode: 0644]
include/dma/xeon_phi/xeon_phi_dma.h [new file with mode: 0644]
include/dma/xeon_phi/xeon_phi_dma_channel.h [new file with mode: 0644]
include/dma/xeon_phi/xeon_phi_dma_descriptors.h [new file with mode: 0644]
include/dma/xeon_phi/xeon_phi_dma_device.h [new file with mode: 0644]
include/dma/xeon_phi/xeon_phi_dma_request.h [new file with mode: 0644]
lib/dma/Hakefile
lib/dma/client/dma_client_channel.c
lib/dma/dma_service.c
lib/dma/include/debug.h
lib/dma/include/xeon_phi/xeon_phi_dma_channel_internal.h [new file with mode: 0644]
lib/dma/include/xeon_phi/xeon_phi_dma_descriptors_internal.h [new file with mode: 0644]
lib/dma/include/xeon_phi/xeon_phi_dma_device_internal.h [new file with mode: 0644]
lib/dma/include/xeon_phi/xeon_phi_dma_internal.h [new file with mode: 0644]
lib/dma/include/xeon_phi/xeon_phi_dma_request_internal.h [new file with mode: 0644]
lib/dma/xeon_phi/xeon_phi_dma.c [new file with mode: 0644]
lib/dma/xeon_phi/xeon_phi_dma_channel.c [new file with mode: 0644]
lib/dma/xeon_phi/xeon_phi_dma_descriptors.c [new file with mode: 0644]
lib/dma/xeon_phi/xeon_phi_dma_device.c [new file with mode: 0644]
lib/dma/xeon_phi/xeon_phi_dma_request.c [new file with mode: 0644]

diff --git a/devices/xeon_phi/xeon_phi_dma_chan.dev b/devices/xeon_phi/xeon_phi_dma_chan.dev
new file mode 100644 (file)
index 0000000..896c7e5
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * 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, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+/*
+ * xeon_phi_dma.dev
+ *
+ * description: register definitions for the Xeon Phi DMA
+ */
+
+device xeon_phi_dma_chan lsbfirst(addr base) "Intel Xeon Phi DMA Channel" {
+
+    register dcar rw addr(base, 0x00) "DMA Channel Attribute Register" {
+        _ 23 "";
+        apic_irq 1 "APIC Interrupt mask bit";
+        msix_irq 1 "MSI-X Interrupt mask bit";
+        irq_status 1 "Interrupt status";
+        _ 6 "";
+    };
+
+    /*
+     * Protection Level: Ring 0
+     * Visibility: Host / Coprocessor
+     * Reset Dmain: GRPB_REset
+     * Register Access: CRU
+     * Number: 8
+     */
+    register dhpr rw addr(base, 0x04) "DMA Descriptor Head Pointer Register" {
+        index 16 "Index of the head pointer";
+        _     16 "Reserved";
+    };
+
+    /*
+     * Protection Level: Ring 0
+     * Visibility: Host / Coprocessor
+     * Reset Dmain: GRPB_REset
+     * Register Access: CRU
+     * Number: 8
+     */
+    register dtpr rw addr(base, 0x08) "DMA Descriptor Tail Pointer Register" {
+        index 16 "Index of the head pointer";
+         _    16 "Reserved";
+    };
+
+    /*
+     * Protection Level: Ring 0
+     * Visibility: Host / Coprocessor
+     * Reset Dmain: GRPB_REset
+     * Register Access: CRU
+     * Number: 8
+     */
+    register aux_lo rw addr(base, 0x0C) "DMA Auxiliary Register 0 Lo" {
+        r 32 "";
+    };
+
+    /*
+     * Protection Level: Ring 0
+     * Visibility: Host / Coprocessor
+     * Reset Dmain: GRPB_REset
+     * Register Access: CRU
+     * Number: 8
+     */
+    register aux_hi rw addr(base, 0x10)  "DMA Auxiliary Register 0 Hi" {
+        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
+     * Reset Dmain: GRPB_REset
+     * Register Access: CRU
+     * Number: 8
+     */
+/*
+    register 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 "";
+        sysbit   1 "";
+        _        5 "";
+    };
+*/
+    
+    /*
+     * Protection Level: Ring 0
+     * Visibility: Host / Coprocessor
+     * Reset Dmain: GRPB_REset
+     * Register Access: CRU
+     * Number: 8
+     */
+    register drar_hi rw addr(base, 0x18) "DMA Descriptor Ring Attributes Register Lo" {
+        base     4 "base address hi part";
+        _        2 "";  
+        size    15 "size of the descriptor ring";
+        page     5 "";
+        sysbit   1 "";
+        _        5 "";
+    };
+
+    /*
+     * Protection Level: Ring 0
+     * Visibility: Host / Coprocessor
+     * Reset Dmain: GRPB_REset
+     * Register Access: CRU
+     * Number: 8
+     */
+    register drar_lo rw addr(base, 0x14) "DMA Descriptor Ring Attributes Register Lo" {
+        _        6 "";
+        base    26 "base address lo part";
+    };
+    
+
+    /*
+     * Protection Level: Ring 0
+     * Visibility: Host / Coprocessor
+     * Reset Dmain: GRPB_REset
+     * Register Access: CRU
+     * Number: 8
+     */
+    register ditr rw addr(base, 0x1C)  "DMA Interrupt Timer Register" {
+        r 32 "";
+    };
+
+    /*
+     * Protection Level: Ring 0
+     * Visibility: Host / Coprocessor
+     * Reset Dmain: GRPB_REset
+     * Register Access: CRU
+     * Number: 8
+     */
+    register dstat rw addr(base, 0x20)  "DMA Status Channel Register" {
+        completions 16 "Completition count";
+        _           16 "";
+    };
+
+    /*
+     * Protection Level: Ring 0
+     * Visibility: Host / Coprocessor
+     * Reset Dmain: GRPB_REset
+     * Register Access: CRU
+     * Number: 8
+     */
+    register dstatwb_lo rw addr(base, 0x24)  "DMA Tail Pointer Write Back Register Lo" {
+        r 32 "";
+    };
+
+    /*
+     * Protection Level: Ring 0
+     * Visibility: Host / Coprocessor
+     * Reset Dmain: GRPB_REset
+     * Register Access: CRU
+     * Number: 8
+     */
+    register dstatwb_hi rw addr(base, 0x28)  "DMA Tail Pointer Write Back Register Hi" {
+        r 32 "";
+    };
+
+    /*
+     * Protection Level: Ring 0
+     * Visibility: Host / Coprocessor
+     * Reset Dmain: GRPB_REset
+     * Register Access: CRU
+     * Number: 8
+     */
+    register dcherr rw addr(base, 0x2C)  "DMA Channel Error Register" {
+        r 32 "";
+    };
+
+    /*
+     * Protection Level: Ring 0
+     * Visibility: Host / Coprocessor
+     * Reset Dmain: GRPB_REset
+     * Register Access: CRU
+     * Number: 8
+     */
+    register dcherrmsk rw addr(base, 0x30)  "DMA Channel Error Register Mask" {
+        r 32 "";
+    };    
+};
\ No newline at end of file
diff --git a/include/dma/xeon_phi/xeon_phi_dma.h b/include/dma/xeon_phi/xeon_phi_dma.h
new file mode 100644 (file)
index 0000000..1ed04cd
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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 LIB_XEON_PHI_DMA_H
+#define LIB_XEON_PHI_DMA_H
+
+#include <dma/dma.h>
+
+struct xeon_phi_dma_device;
+struct xeon_phi_dma_channel;
+struct xeon_phi_dma_request;
+
+/// the service name for the exported devices
+#define XEON_PHI_DMA_SERVICE_NAME "xeon_phi_dma_svc"
+
+/// size of the Xeon PHI DMA descriptor ring in bits
+#define XEON_PHI_DMA_RING_SIZE 8
+
+/**
+ * \brief initializes the DMA library
+ */
+errval_t xeon_phi_dma_init(void);
+
+
+#endif  /* LIB_IOAT_DMA_H */
diff --git a/include/dma/xeon_phi/xeon_phi_dma_channel.h b/include/dma/xeon_phi/xeon_phi_dma_channel.h
new file mode 100644 (file)
index 0000000..d58e28e
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * 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 LIB_XEON_PHI_DMA_CHANNEL_H
+#define LIB_XEON_PHI_DMA_CHANNEL_H
+
+#include <dma/dma_channel.h>
+
+typedef enum xeon_phi_dma_owner {
+    XEON_PHI_DMA_OWNER_CARD = 0,
+    XEON_PHI_DMA_OWNER_HOST
+} xeon_phi_dma_owner_t;
+
+
+
+
+/**
+ * \brief pointer type conversion
+ */
+static inline struct xeon_phi_dma_channel *dma_channel_to_xeon_phi(struct dma_channel *chan)
+{
+    return (struct xeon_phi_dma_channel *)chan;
+}
+
+/*
+ * ----------------------------------------------------------------------------
+ * Channel State Management
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief Resets a Xeon Phi DMA channel
+ *
+ * \param chan  Xeon Phi DMA channel to be reset
+ *
+ * \returns SYS_ERR_OK on success
+ *          DMA_ERR_CHAN_RESET on reset timeout
+ */
+errval_t xeon_phi_dma_channel_reset(struct xeon_phi_dma_channel *chan);
+
+/**
+ * \brief restarts a Xeon Phi DMA channel this updates the chain address register
+ *        and the DMA count register.
+ *
+ * \param chan  Xeon Phi DMA channel
+ *
+ * \returns SYS_ERR_OK on success
+ *          DMA_ERR_* on failure
+ */
+errval_t xeon_phi_dma_channel_restart(struct xeon_phi_dma_channel *chan);
+
+/**
+ * \brief starts a Xeon Phi DMA channel. This sets the chain address to the first
+ *        entry of the ring and the DMA count to zero.
+ *
+ * \param chan  Xeon Phi DMA channel
+ *
+ * \returns SYS_ERR_OK on success
+ *          DMA_ERR_* on failure
+ */
+errval_t xeon_phi_dma_channel_start(struct xeon_phi_dma_channel *chan);
+
+/**
+ * \brief stopps the processing of the descriptors.
+ *
+ * \param chan  Xeon Phi DMA channel
+ *
+ * \returns SYS_ERR_OK on success
+ *          DMA_ERR_* on failure
+ */
+errval_t xeon_phi_dma_channel_stop(struct xeon_phi_dma_channel *chan);
+
+/**
+ * \brief Puts the Xeon Phi DMA channel into the suspended state
+ *
+ * \param chan  Xeon Phi DMA channel
+ *
+ * \returns SYS_ERR_OK on success
+ *          DMA_ERR_* on failure
+ */
+errval_t xeon_phi_dma_channel_suspend(struct xeon_phi_dma_channel *chan);
+
+/**
+ * \brief Submits the pending descriptors to the hardware queue
+ *
+ * \param chan  Xeon Phi DMA channel
+ *
+ * \returns number of submitted descriptors
+ */
+uint16_t xeon_phi_dma_channel_issue_pending(struct xeon_phi_dma_channel *chan);
+
+/**
+ * \brief polls the Xeon Phi DMA channel for completed events
+ *
+ * \param chan  Xeon Phi DMA channel
+ *
+ * \returns SYS_ERR_OK if there was something processed
+ *
+ */
+errval_t xeon_phi_dma_channel_poll(struct xeon_phi_dma_channel *chan);
+
+
+/*
+ * ----------------------------------------------------------------------------
+ * Getter / Setter Functions
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief returns the associated Xeon Phi DMA descriptor ring of a channel
+ *
+ * \param chan  Xeon Phi DMA channel
+ *
+ * \returns Xeon Phi DMA descriptor ring handle
+ */
+struct xeon_phi_dma_ring *xeon_phi_dma_channel_get_ring(struct xeon_phi_dma_channel *chan);
+
+/**
+ * \brief updates the channel status flag by reading the CHANSTS register
+ *
+ * \param chan Xeon Phi DMA channel
+ */
+uint64_t xeon_phi_dma_channel_get_status(struct xeon_phi_dma_channel *chan);
+
+/*
+ * ----------------------------------------------------------------------------
+ * Channel Status
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief reads the CHANSTS register and and checks if the channel is active
+ *
+ * \param chan Xeon Phi DMA channel
+ *
+ * \returns true if channel is active
+ *          false if not
+ */
+static inline bool xeon_phi_dma_channel_is_active(uint64_t status)
+{
+    assert(!"NYI");
+    return 0;
+}
+
+/**
+ * \brief reads the CHANSTS register and and checks if the channel is idle
+ *
+ * \param chan Xeon Phi DMA channel
+ *
+ * \returns true if channel is idle
+ *          false if not
+ */
+static inline bool xeon_phi_dma_channel_is_idle(uint64_t status)
+{
+    assert(!"NYI");
+    return 0;
+}
+
+/**
+ * \brief reads the CHANSTS register and and checks if the channel is halted
+ *        i.e. if there was an error condition
+ *
+ * \param chan Xeon Phi DMA channel
+ *
+ * \returns true if channel is halted (there was an error)
+ *          false if not
+ */
+static inline bool xeon_phi_dma_channel_is_halted(uint64_t status)
+{
+    assert(!"NYI");
+    return 0;
+}
+
+/**
+ * \brief reads the CHANSTS register and and checks if the channel is suspended
+ *
+ * \param chan Xeon Phi DMA channel
+ *
+ * \returns true if channel is suspended
+ *          false if not
+ */
+static inline bool xeon_phi_dma_channel_is_suspended(uint64_t status)
+{
+    assert(!"NYI");
+    return 0;
+}
+
+/*
+ * ----------------------------------------------------------------------------
+ * Request Management
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ *
+ */
+void xeon_phi_dma_channel_request_enqueue(struct dma_channel *chan,
+                                          struct dma_request *req);
+
+
+#endif  /* LIB_XEON_PHI_DMA_CHANNEL_H */
diff --git a/include/dma/xeon_phi/xeon_phi_dma_descriptors.h b/include/dma/xeon_phi/xeon_phi_dma_descriptors.h
new file mode 100644 (file)
index 0000000..7939492
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * 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 LIB_XEON_PHI_DMA_DESCRIPTORS_H
+#define LIB_XEON_PHI_DMA_DESCRIPTORS_H
+
+struct dma_descriptor;
+
+/// flags how the descriptors are mapped
+#define XEON_PHI_DMA_DESC_MAP_FLAGS VREGION_FLAGS_READ_WRITE
+
+/// the size of the Xeon Phi descriptor
+#define XEON_PHI_DMA_DESC_SIZE 16
+
+/// the size of the Xeon Phi descriptor
+#define XEON_PHI_DMA_DESC_ALIGN 16
+
+/*
+ * ----------------------------------------------------------------------------
+ * DMA Descriptor Allocation / Free
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ * ----------------------------------------------------------------------------
+ * DMA Descriptor Setup Functions
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief initializes the hardware specific part of the descriptor to be used
+ *        for memcpy descriptors
+ *
+ * \param desc  IOAT DMA descriptor
+ * \param src   Source address of the transfer
+ * \param dst   destination address of the transfer
+ * \param size  number of bytes to copy
+ * \param ctrl  control flags
+ *
+ * XXX: this function assumes that the size of the descriptor has already been
+ *      checked and must match the maximum transfer size of the channel
+ */
+void xeon_phi_dma_desc_fill_memcpy(struct dma_descriptor *desc,
+                                   lpaddr_t src,
+                                   lpaddr_t dst,
+                                   uint32_t size);
+
+/**
+ * \brief initializes the hardware specific part of the descriptor to be used
+ *        for nop descriptors (null descriptors)
+ *
+ * \param desc  IOAT DMA descriptor
+ */
+void xeon_phi_dma_desc_fill_nop(struct dma_descriptor *desc);
+
+/*
+ * ----------------------------------------------------------------------------
+ * Getters / Setters
+ * ----------------------------------------------------------------------------
+ */
+
+#endif  /* LIB_XEON_PHI_DMA_DESCRIPTORS_H */
diff --git a/include/dma/xeon_phi/xeon_phi_dma_device.h b/include/dma/xeon_phi/xeon_phi_dma_device.h
new file mode 100644 (file)
index 0000000..1390bf9
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * 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 LIB_XEON_PHI_DMA_DEVICE_H
+#define LIB_XEON_PHI_DMA_DEVICE_H
+
+/// forward declaration of the device
+struct xeon_phi_dma_device;
+struct xeon_phi_dma_channel;
+
+/// The maximum transfer size per descriptor
+#define XEON_PHI_DMA_DEVICE_MAX_XFER (512 * 1024)
+
+/*
+ * ----------------------------------------------------------------------------
+ * Device Channel Setup
+ *
+ * The DMA device has 8 channels which can be owned by the card or by the host.
+ *
+ * We give 4 to the card and 4 to the host side drivers.
+ */
+
+/// the maximum number of DMA channels on the card
+#define XEON_PHI_DMA_DEVICE_CHAN_TOTAL 8
+
+/// the number of DMA channels for the host
+#define XEON_PHI_DMA_DEVICE_CHAN_HOST 4
+
+#ifdef __k1om__
+#define XEON_PHI_DMA_DEVICE_CHANNELS (XEON_PHI_DMA_DEVICE_CHAN_TOTAL- XEON_PHI_DMA_DEVICE_CHAN_HOST)
+#define XEON_PHI_DMA_DEVICE_CHAN_OFFSET XEON_PHI_DMA_DEVICE_CHAN_HOST
+#else
+#define XEON_PHI_DMA_DEVICE_CHANNELS XEON_PHI_DMA_DEVICE_CHAN_HOST
+#define XEON_PHI_DMA_DEVICE_CHAN_OFFSET 0
+#endif
+
+/**
+ * \brief pointer type conversion
+ */
+static inline struct xeon_phi_dma_device *dma_device_to_ioat(struct dma_device *dev)
+{
+    return (struct xeon_phi_dma_device *) dev;
+}
+
+/*
+ * ----------------------------------------------------------------------------
+ * device initialization / termination
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief initializes a Xeon Phi DMA device with the giving capability
+ *
+ * \param mmio capability representing the device's MMIO registers
+ * \param dev  returns a pointer to the device structure
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on error
+ */
+errval_t xeon_phi_dma_device_init(mackerel_addr_t mmio_base,
+                                  struct xeon_phi_dma_device **dev);
+
+/**
+ * \brief terminates the device operation and frees up the allocated resources
+ *
+ * \param dev Xeon Phi DMA device to shutdown
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on error
+ */
+errval_t xeon_phi_dma_device_shutdown(struct xeon_phi_dma_device *dev);
+
+/*
+ * ----------------------------------------------------------------------------
+ * Interrupt management
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief enables the interrupts for the device
+ *
+ * \param dev   Xeon Phi DMA device
+ * \param type  interrupt type
+ * \param fn    interrupt handler function
+ * \param arg   argument supplied to the handler function
+ */
+errval_t xeon_phi_dma_device_intr_enable(struct xeon_phi_dma_device *dev,
+                                         dma_irq_t type,
+                                         dma_irq_fn_t fn,
+                                         void *arg);
+
+/**
+ * \brief disables the interrupts for the device
+ *
+ * \param dev   Xeon Phi DMA device
+ */
+void xeon_phi_dma_device_intr_disable(struct xeon_phi_dma_device *dev);
+
+
+/*
+ * ----------------------------------------------------------------------------
+ * Device Operation Functions
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief polls the channels of the Xeon Phi DMA device
+ *
+ * \param dev   Xeon Phi DMA device
+ *
+ * \returns SYS_ERR_OK on success
+ *          DMA_ERR_DEVICE_IDLE if there is nothing completed on the channels
+ *          errval on error
+ */
+errval_t xeon_phi_dma_device_poll_channels(struct dma_device *dev);
+
+#endif  /* LIB_XEON_PHI_DMA_DEVICE_H */
diff --git a/include/dma/xeon_phi/xeon_phi_dma_request.h b/include/dma/xeon_phi/xeon_phi_dma_request.h
new file mode 100644 (file)
index 0000000..0636cb7
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * 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 LIB_XEON_PHI_DMA_REQUEST_H
+#define LIB_XEON_PHI_DMA_REQUEST_H
+
+#include <dma/dma_request.h>
+
+/**
+ * \brief pointer type conversion
+ */
+static inline struct xeon_phi_dma_request *dma_request_to_xphi(struct dma_request *req)
+{
+    return (struct xeon_phi_dma_request *) req;
+}
+
+/*
+ * ----------------------------------------------------------------------------
+ * Request Execution
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief issues a memcpy request to the given channel
+ *
+ * \param chan  Xeon Phi DMA channel
+ * \param setup request setup information
+ * \param id    returns the generated request id
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on failure
+ */
+errval_t xeon_phi_dma_request_memcpy_chan(struct xeon_phi_dma_channel *chan,
+                                          struct dma_req_setup *setup,
+                                          dma_req_id_t *id);
+
+/**
+ * \brief issues a memcpy request to a channel of the given device
+ *
+ * \param dev   Xeon Phi DMA device
+ * \param setup request setup information
+ * \param id    returns the generated request id
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on failure
+ */
+errval_t xeon_phi_request_memcpy(struct xeon_phi_dma_device *dev,
+                                 struct dma_req_setup *setup,
+                                 dma_req_id_t *id);
+
+/**
+ * \brief issues a status request to the given channel
+ *
+ * \param chan  Xeon Phi DMA channel
+ * \param setup request setup information
+ * \param id    returns the generated request id
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on failure
+ */
+errval_t xeon_phi_dma_request_status_chan(struct xeon_phi_dma_channel *chan,
+                                          struct dma_req_setup *setup,
+                                          dma_req_id_t *id);
+
+/**
+ * \brief issues a status request to a channel of the given device
+ *
+ * \param dev   Xeon Phi DMA device
+ * \param setup request setup information
+ * \param id    returns the generated request id
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on failure
+ */
+errval_t xeon_phi_request_status(struct xeon_phi_dma_device *dev,
+                                 struct dma_req_setup *setup,
+                                 dma_req_id_t *id);
+
+/**
+ * \brief issues a general request to the given channel
+ *
+ * \param chan  Xeon Phi DMA channel
+ * \param setup request setup information
+ * \param id    returns the generated request id
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on failure
+ */
+errval_t xeon_phi_dma_request_general_chan(struct xeon_phi_dma_channel *chan,
+                                           struct dma_req_setup *setup,
+                                           dma_req_id_t *id);
+
+/**
+ * \brief issues a general request to a channel of the given device
+ *
+ * \param dev   Xeon Phi DMA device
+ * \param setup request setup information
+ * \param id    returns the generated request id
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on failure
+ */
+errval_t xeon_phi_request_general(struct xeon_phi_dma_device *dev,
+                                  struct dma_req_setup *setup,
+                                  dma_req_id_t *id);
+
+/**
+ * \brief issues a keynoncecent request to the given channel
+ *
+ * \param chan  Xeon Phi DMA channel
+ * \param setup request setup information
+ * \param id    returns the generated request id
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on failure
+ */
+errval_t xeon_phi_dma_request_keynoncecent_chan(struct xeon_phi_dma_channel *chan,
+                                                struct dma_req_setup *setup,
+                                                dma_req_id_t *id);
+
+/**
+ * \brief issues a keynoncecent request to a channel of the given device
+ *
+ * \param dev   Xeon Phi DMA device
+ * \param setup request setup information
+ * \param id    returns the generated request id
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on failure
+ */
+errval_t xeon_phi_request_keynoncecent(struct xeon_phi_dma_device *dev,
+                                       struct dma_req_setup *setup,
+                                       dma_req_id_t *id);
+
+/**
+ * \brief issues a key request to the given channel
+ *
+ * \param chan  Xeon Phi DMA channel
+ * \param setup request setup information
+ * \param id    returns the generated request id
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on failure
+ */
+errval_t xeon_phi_dma_request_keynoncecent(struct xeon_phi_dma_channel *chan,
+                                           struct dma_req_setup *setup,
+                                           dma_req_id_t *id);
+
+/**
+ * \brief issues a key request to a channel of the given device
+ *
+ * \param dev   Xeon Phi DMA device
+ * \param setup request setup information
+ * \param id    returns the generated request id
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on failure
+ */
+errval_t xeon_phi_request_key(struct xeon_phi_dma_device *dev,
+                              struct dma_req_setup *setup,
+                              dma_req_id_t *id);
+
+/**
+ * \brief issues a NOP / NULL descriptor request on the given channel
+ *
+ * \param chan  Xeon Phi DMA channel
+ * \param setup request setup information
+ */
+void xeon_phi_dma_request_nop_chan(struct xeon_phi_dma_channel *chan);
+
+/**
+ * \brief issues a NOP / NULL descriptor request on the given device
+ *
+ * \param dev   Xeon Phi DMA device
+ * \param setup request setup information
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on failure
+ */
+void xeon_phi_dma_request_nop(struct xeon_phi_dma_device *dev);
+
+/*
+ * ----------------------------------------------------------------------------
+ * Getters / Setters
+ * ----------------------------------------------------------------------------
+ */
+
+#endif  /* LIB_XEON_PHI_DMA_REQUEST_H */
index 8388b2a..0e31f32 100644 (file)
       "dma_device.c",
       "dma_channel.c",
       "dma_request.c",
+      "dma_ring.c",
+      "dma_descriptor.c",
       "dma_bench.c",
       "ioat/ioat_dma_channel.c",
       "ioat/ioat_dma_dca.c",
       "ioat/ioat_dma_descriptors.c",
       "ioat/ioat_dma_device.c",
       "ioat/ioat_dma_request.c",
-      "ioat/ioat_dma_ring.c",
       "ioat/ioat_dma.c",
+      "xeon_phi/xeon_phi_dma.c",
+      "xeon_phi/xeon_phi_dma_device.c",
+      "xeon_phi/xeon_phi_dma_channel.c",
+      "xeon_phi/xeon_phi_dma_request.c",
+      "xeon_phi/xeon_phi_dma_descriptors.c",
       "client/dma_client_device.c",
       "client/dma_client_channel.c",
       "client/dma_client_request.c"
     flounderBindings = [ "dma", "ioat_dma_mgr", "dma_mgr" ],
     flounderDefs = [ "dma" ],
     flounderExtraBindings = [ ("dma_mgr",["rpcclient"]) ],
-    mackerelDevices = [ "ioat_dma", "ioat_dma_chan" ]
+    mackerelDevices = [ 
+      "ioat_dma", 
+      "ioat_dma_chan", 
+      "xeon_phi/xeon_phi_dma", 
+      "xeon_phi/xeon_phi_dma_chan" ]
   },
   
   build library { 
index 61b0462..f2fab81 100644 (file)
@@ -259,7 +259,7 @@ static void chan_init_bind_cb(void *st,
     }
 
     txq_init(&chan->txq, b, b->waitset, (txq_register_fn_t) b->register_send,
-             sizeof(struct svc_msg_st));
+             (txq_can_send_fn_t) b->can_send, sizeof(struct svc_msg_st));
 
     chan->binding = b;
     chan->client_st = DMA_CLIENT_STATE_BIND_OK;
index 461a487..c000b96 100644 (file)
@@ -248,6 +248,7 @@ static errval_t svc_connect_cb(void *st,
 
     txq_init(&state->queue, binding, binding->waitset,
              (txq_register_fn_t) binding->register_send,
+             (txq_can_send_fn_t) binding->can_send,
              sizeof(struct dma_svc_reply_st));
 
     err = event_handlers->connect(&state->usr_st);
index bd218ea..0759f38 100644 (file)
@@ -26,7 +26,7 @@
 #define DMA_DEBUG_MEM_ENABLED     1
 #define DMA_DEBUG_CLIENT_ENABLED  1
 #define DMA_DEBUG_MGR_ENABLED     1
-
+#define DMA_DEBUG_DESC_ENABLED    1
 /*
  * ---------------------------------------------------------------------------
  *  IOAT debug switches
 
 /*
  * ---------------------------------------------------------------------------
+ *  Xeon Phi debug switches
+ */
+#define XEON_PHI_DEBUG_ENABLED     1
+#define XPHI_DEBUG_CHAN_ENABLED    1
+#define XPHI_DEBUG_DEVICE_ENABLED  1
+#define XPHI_DEBUG_REQUEST_ENABLED 1
+#define XPHI_DEBUG_DESC_ENABLED    1
+#define XPHI_DEBUG_INTR_ENABLED    1
+
+/*
+ * ---------------------------------------------------------------------------
  *  DMA client debug switches
  */
 #define DMA_CLIENT_DEBUG_ENABLED 1
 #else
 #define DMAMGR_DEBUG(x...)
 #endif
-
+#if DMA_DEBUG_DESC_ENABLED
+#define DMADESC_DEBUG(x...) IOAT_DEBUG_PRINT("[dma desc] " x)
+#else
+#define DMADESC_DEBUG(x...)
+#endif
 
 /*
  * --------------------------------------------------------------------------
 #define IOATDCA_DEBUG(x...)
 #endif
 
+
+/*
+ * --------------------------------------------------------------------------
+ *  XPHI Debug output generation
+ */
+
+#if (LIB_DMA_DEBUG_ENABLED && XEON_PHI_DEBUG_ENABLED)
+#define XPHI_DEBUG_PRINT(x...) debug_printf(x)
+#else
+#define XPHI_DEBUG_PRINT(x... )
+#endif
+#if XPHI_DEBUG_INTR_ENABLED
+#define XPHIINT_DEBUG(x...) XPHI_DEBUG_PRINT("[xdma intr] " x)
+#else
+#define XPHIINT_DEBUG(x...)
+#endif
+#if XPHI_DEBUG_CHAN_ENABLED
+#define XPHICHAN_DEBUG(x...) XPHI_DEBUG_PRINT("[xdma chan.%04x] " x)
+#else
+#define XPHICHAN_DEBUG(x...)
+#endif
+#if XPHI_DEBUG_REQUEST_ENABLED
+#define XPHIREQ_DEBUG(x...) XPHI_DEBUG_PRINT("[xdma req] " x)
+#else
+#define XPHIREQ_DEBUG(x...)
+#endif
+#if XPHI_DEBUG_DEVICE_ENABLED
+#define XPHIDEV_DEBUG(x...) XPHI_DEBUG_PRINT("[xdma dev.%02x] " x)
+#else
+#define XPHIDEV_DEBUG(x...)
+#endif
+#if XPHI_DEBUG_DESC_ENABLED
+#define XPHIDESC_DEBUG(x...) XPHI_DEBUG_PRINT("[xdma desc] " x)
+#else
+#define XPHIDESC_DEBUG(x...)
+#endif
+
+
 /*
  * --------------------------------------------------------------------------
  *  DMA Client debug output generation
diff --git a/lib/dma/include/xeon_phi/xeon_phi_dma_channel_internal.h b/lib/dma/include/xeon_phi/xeon_phi_dma_channel_internal.h
new file mode 100644 (file)
index 0000000..74e3ab7
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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_CHANNEL_INTERNAL_H
+#define XEON_PHI_DMA_CHANNEL_INTERNAL_H
+
+#include <dma_channel_internal.h>
+#include <dma/xeon_phi/xeon_phi_dma_channel.h>
+
+/**
+ * \brief initializes and allocates resources for a new channel DMA channel
+ *        belonging to a device
+ *
+ * \param dev       IOAT DMA device
+ * \param id        id of this channel
+ * \param max_xfer  maximum size in bytes for a transfer
+ * \param ret_chan  returned channel pointer
+ *
+ * \returns SYS_ERR_OK on success
+ */
+errval_t xeon_phi_dma_channel_init(struct xeon_phi_dma_device *dev,
+                                   uint8_t id,
+                                   uint32_t max_xfer,
+                                   struct xeon_phi_dma_channel **ret_chan);
+
+/**
+ * \brief enqueues a request onto the IOAT DMA channel and submits it to the
+ *        hardware
+ *
+ * \param chan  IOAT DMA channel
+ * \param req   IOAT DMA request to be submitted
+ *
+ * \returns SYS_ERR_OK on success
+ *          DMA_ERR_* on failure
+ */
+errval_t xeon_phi_dma_channel_submit_request(struct xeon_phi_dma_channel *chan,
+                                             struct xeon_phi_dma_request *req);
+
+/**
+ * \brief initializes the MSI-X interrupts for the channel
+ */
+errval_t xeon_phi_dma_channel_irq_setup_msix(struct xeon_phi_dma_channel *chan);
+
+#endif /* XEON_PHI_DMA_CHANNEL_INTERNAL_H */
diff --git a/lib/dma/include/xeon_phi/xeon_phi_dma_descriptors_internal.h b/lib/dma/include/xeon_phi/xeon_phi_dma_descriptors_internal.h
new file mode 100644 (file)
index 0000000..425910c
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * 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_DESCRIPTORS_INTERNAL_H
+#define XEON_PHI_DMA_DESCRIPTORS_INTERNAL_H
+
+#include <dma/xeon_phi/xeon_phi_dma_descriptors.h>
+
+
+/*
+ * ----------------------------------------------------------------------------
+ * Allocation / Deallocation
+ * ----------------------------------------------------------------------------
+ */
+
+
+#endif /* XEON_PHI_DMA_DESCRIPTORS_INTERNAL_H */
diff --git a/lib/dma/include/xeon_phi/xeon_phi_dma_device_internal.h b/lib/dma/include/xeon_phi/xeon_phi_dma_device_internal.h
new file mode 100644 (file)
index 0000000..5be9070
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * 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_DEVICE_INTERNAL_H
+#define XEON_PHI_DMA_DEVICE_INTERNAL_H
+
+#include <dma_mem_utils.h>
+
+#include <dma_device_internal.h>
+#include <dma/xeon_phi/xeon_phi_dma_device.h>
+
+#include <dev/xeon_phi/xeon_phi_dma_dev.h>
+
+
+/**
+ * \brief globally enables the interrupts for the given device
+ *
+ * \param dev   IOAT DMA device
+ * \param type  the interrupt type to enable
+ */
+errval_t xeon_phi_dma_device_irq_setup(struct xeon_phi_dma_device *dev,
+                                       dma_irq_t type);
+
+
+/**
+ * \brief gets the Xeon Phi virtual base address of the DMA channel with
+ *        the given id
+ *
+ * \param dev   Xeon Phi DMA device
+ * \param idx   DMA channel index
+ *
+ * \returns virtual address of MMIO registers for the channel
+ */
+void *xeon_phi_dma_device_get_channel_vbase(struct xeon_phi_dma_device *dev,
+                                            uint8_t idx);
+
+
+#endif /* XEON_PHI_DMA_DEVICE_INTERNAL_H */
diff --git a/lib/dma/include/xeon_phi/xeon_phi_dma_internal.h b/lib/dma/include/xeon_phi/xeon_phi_dma_internal.h
new file mode 100644 (file)
index 0000000..fe7e6e6
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * 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_INTERNAL_H
+#define XEON_PHI_DMA_INTERNAL_H
+
+#include <dma_internal.h>
+#include <dma/xeon_phi/xeon_phi_dma.h>
+
+
+#endif /* XEON_PHI_DMA_INTERNAL_H */
diff --git a/lib/dma/include/xeon_phi/xeon_phi_dma_request_internal.h b/lib/dma/include/xeon_phi/xeon_phi_dma_request_internal.h
new file mode 100644 (file)
index 0000000..6172812
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * 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_REQUEST_INTERNAL_H
+#define XEON_PHI_DMA_REQUEST_INTERNAL_H
+
+#include <dma_request_internal.h>
+#include <dma/xeon_phi/xeon_phi_dma_request.h>
+
+
+/**
+ * \brief handles the processing of completed DMA requests
+ *
+ * \param req   the DMA request to process
+ *
+ * \returns SYS_ERR_OK on sucess
+ *          errval on failure
+ */
+errval_t xeon_phi_dma_request_process(struct xeon_phi_dma_request *req);
+
+#endif /* XEON_PHI_DMA_REQUEST_INTERNAL_H */
diff --git a/lib/dma/xeon_phi/xeon_phi_dma.c b/lib/dma/xeon_phi/xeon_phi_dma.c
new file mode 100644 (file)
index 0000000..c6cfcec
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+#if 0
+#include <barrelfish/barrelfish.h>
+
+#include <dma_internal.h>
+#include <xeon_phi/xeon_phi_dma_internal.h>
+
+#endif
+/*
+ * ===========================================================================
+ * Public Interface
+ * ===========================================================================
+ */
diff --git a/lib/dma/xeon_phi/xeon_phi_dma_channel.c b/lib/dma/xeon_phi/xeon_phi_dma_channel.c
new file mode 100644 (file)
index 0000000..16448ac
--- /dev/null
@@ -0,0 +1,395 @@
+/*
+ * 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 <dev/xeon_phi/xeon_phi_dma_chan_dev.h>
+
+#include <dma_mem_utils.h>
+
+#include <xeon_phi/xeon_phi_dma_internal.h>
+#include <xeon_phi/xeon_phi_dma_device_internal.h>
+#include <xeon_phi/xeon_phi_dma_channel_internal.h>
+#include <dma_ring_internal.h>
+#include <xeon_phi/xeon_phi_dma_descriptors_internal.h>
+#include <xeon_phi/xeon_phi_dma_request_internal.h>
+
+#include <debug.h>
+
+struct xeon_phi_dma_channel
+{
+    struct dma_channel common;
+    xeon_phi_dma_chan_t channel;         ///< Mackerel address
+    lpaddr_t last_processed;            ///<
+    struct dma_ring *ring;      ///< Descriptor ring
+    xeon_phi_dma_owner_t owner;
+};
+
+/**
+ * \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 xeon_phi_dma_channel *chan,
+                                       uint8_t mask)
+{
+    uint8_t mask_val = (mask) ? 0x1 : 0x0;
+
+    if (chan->owner == XEON_PHI_DMA_OWNER_CARD) {
+        xeon_phi_dma_chan_dcar_msix_irq_wrf(&chan->channel, mask_val);
+    } else {
+        xeon_phi_dma_chan_dcar_apic_irq_wrf(&chan->channel, mask_val);
+    }
+
+    return xeon_phi_dma_chan_dcar_rd(&chan->channel);
+}
+
+/**
+ * \brief acknowledges the interrupts by masking them and renable them
+ *
+ * \param chan  Xeon Phi DMA channel
+ */
+static inline void xdma_channel_ack_intr(struct xeon_phi_dma_channel *chan)
+{
+    xdma_channel_mask_intr(chan, 1);
+    xdma_channel_mask_intr(chan, 0);
+}
+
+/**
+ * \brief sets the error mask of a Xeon Phi DMA channel
+ *
+ * \param chan Xeon Phi DMA channel
+ * \param mask bitmask for the errors
+ */
+static inline void xdma_channel_set_error_mask(struct xeon_phi_dma_channel *chan,
+                                               uint32_t mask)
+{
+    xeon_phi_dma_chan_dcherr_wr(&chan->channel, mask);
+}
+
+/*
+ * ============================================================================
+ * Library Internal Interface
+ * ============================================================================
+ */
+
+/**
+ * \brief initializes and allocates resources for a new channel DMA channel
+ *        belonging to a device
+ *
+ * \param dev       IOAT DMA device
+ * \param id        id of this channel
+ * \param max_xfer  maximum size in bytes for a transfer
+ * \param ret_chan  returned channel pointer
+ *
+ * \returns SYS_ERR_OK on success
+ */
+errval_t xeon_phi_dma_channel_init(struct xeon_phi_dma_device *dev,
+                                   uint8_t id,
+                                   uint32_t max_xfer,
+                                   struct xeon_phi_dma_channel **ret_chan)
+{
+
+    errval_t err;
+
+    struct xeon_phi_dma_channel *chan = calloc(1, sizeof(*chan));
+    if (chan == NULL) {
+        return LIB_ERR_MALLOC_FAIL;
+    }
+
+#ifdef __k1om__
+    chan->owner = XEON_PHI_DMA_OWNER_CARD;
+#else
+    chan->owner = XEON_PHI_DMA_OWNER_HOST;
+#endif
+
+    xeon_phi_dma_chan_initialize(&chan->channel,
+                                 xeon_phi_dma_device_get_channel_vbase(dev, id));
+
+    xdma_channel_set_error_mask(chan, 0);
+    xdma_channel_ack_intr(chan);
+
+    err = dma_ring_alloc(XEON_PHI_DMA_RING_SIZE, XEON_PHI_DMA_DESC_ALIGN,
+                         XEON_PHI_DMA_DESC_SIZE, &chan->ring, &chan->common);
+
+    xdma_channel_mask_intr(chan, 0x1);
+
+    return SYS_ERR_OK;
+}
+
+#if 0
+
+/**
+ * \brief Submits the pending descriptors to the hardware queue
+ *
+ * \param chan  IOAT DMA channel
+ *
+ * \returns number of submitted descriptors
+ */
+uint16_t xeon_phi_dma_channel_issue_pending(struct xeon_phi_dma_channel *chan)
+{
+    errval_t err;
+
+    uint16_t pending = xeon_phi_dma_ring_get_pendig(chan->ring);
+
+    IOATCHAN_DEBUG("issuing %u pending descriptors to hardware\n",
+                    chan->common.id, pending);
+
+    if (chan->common.state != DMA_CHAN_ST_RUNNING) {
+        err = xeon_phi_dma_channel_start(chan);
+    }
+    if (pending > 0) {
+        uint16_t dmacnt = xeon_phi_dma_ring_submit_pending(chan->ring);
+        xeon_phi_dma_chan_dmacount_wr(&chan->channel, dmacnt);
+
+        IOATCHAN_DEBUG(" setting dma_count to [%u]\n", chan->common.id, dmacnt);
+    }
+
+    return pending;
+}
+
+/*
+ * ============================================================================
+ * Public Interface
+ * ============================================================================
+ */
+
+/*
+ * ----------------------------------------------------------------------------
+ * Channel State Management
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief Resets a IOAT DMA channel
+ *
+ * \param chan  IOAT DMA channel to be reset
+ *
+ * \returns SYS_ERR_OK on success
+ *          DMA_ERR_CHAN_RESET on reset timeout
+ */
+errval_t xeon_phi_dma_channel_reset(struct xeon_phi_dma_channel *chan)
+{
+    struct dma_channel *dma_chan = &chan->common;
+
+    IOATCHAN_DEBUG("reset channel.\n", dma_chan->id);
+
+    if (dma_chan->state == DMA_CHAN_ST_ERROR) {
+        xeon_phi_dma_chan_err_t chanerr = xeon_phi_dma_chan_err_rd(&chan->channel);
+        xeon_phi_dma_chan_err_wr(&chan->channel, chanerr);
+        IOATCHAN_DEBUG("Reseting channel from error state: [%08x]\n",
+                        dma_chan->id, chanerr);
+
+        /*
+         * errval_t pci_read_conf_header(uint32_t dword, uint32_t *val);
+
+         errval_t pci_write_conf_header(uint32_t dword, uint32_t val);
+         * TODO: clear the xeon_phi_dma_pci_chanerr register in PCI config space
+         *       (same approach as above)
+         *       -> How to access this ?
+         */
+    }
+    dma_chan->state = DMA_CHAN_ST_RESETTING;
+
+    /* perform reset */
+    xeon_phi_dma_chan_cmd_reset_wrf(&chan->channel, 0x1);
+
+    uint16_t reset_counter = 0xFFF;
+    do {
+        if (!xeon_phi_dma_chan_cmd_reset_rdf(&chan->channel)) {
+            break;
+        }
+        thread_yield();
+    }while (reset_counter--);
+
+    if (xeon_phi_dma_chan_cmd_reset_rdf(&chan->channel)) {
+        /* reset failed */
+        return DMA_ERR_RESET_TIMEOUT;
+    }
+
+    /* XXX: Intel BD architecture will need some additional work here */
+
+    dma_chan->state = DMA_CHAN_ST_UNINITIALEZED;
+
+    return SYS_ERR_OK;
+}
+
+/**
+ * \brief restarts a IOAT DMA channel this updates the chain address register
+ *        and the DMA count register.
+ *
+ * \param chan  IOAT DMA channel
+ *
+ * \returns SYS_ERR_OK on success
+ *          DMA_ERR_* on failure
+ */
+errval_t xeon_phi_dma_channel_restart(struct xeon_phi_dma_channel *chan)
+{
+    assert(!"NYI");
+    return SYS_ERR_OK;
+}
+
+/**
+ * \brief starts a IOAT DMA channel. This sets the chain address to the first
+ *        entry of the ring and the DMA count to zero.
+ *
+ * \param chan  IOAT DMA channel
+ *
+ * \returns SYS_ERR_OK on success
+ *          DMA_ERR_* on failure
+ */
+errval_t xeon_phi_dma_channel_start(struct xeon_phi_dma_channel *chan)
+{
+    if (chan->common.state == DMA_CHAN_ST_ERROR) {
+        return xeon_phi_dma_channel_restart(chan);
+    }
+
+    if (chan->common.state == DMA_CHAN_ST_RUNNING) {
+        return SYS_ERR_OK;
+    }
+
+    IOATCHAN_DEBUG("starting channel.\n", chan->common.id);
+
+    chan->common.state = DMA_CHAN_ST_RUNNING;
+    channel_set_chain_addr(chan);
+
+    return SYS_ERR_OK;
+}
+
+/**
+ * \brief stopps the processing of the descriptors.
+ *
+ * \param chan  IOAT DMA channel
+ *
+ * \returns SYS_ERR_OK on success
+ *          DMA_ERR_* on failure
+ */
+errval_t xeon_phi_dma_channel_stop(struct xeon_phi_dma_channel *chan)
+{
+    assert(!"NYI");
+    return SYS_ERR_OK;
+}
+
+/**
+ * \brief Puts the IOAT DMA channel into the suspended state
+ *
+ * \param chan  IOAT DMA channel
+ *
+ * \returns SYS_ERR_OK on success
+ *          DMA_ERR_* on failure
+ */
+errval_t xeon_phi_dma_channel_suspend(struct xeon_phi_dma_channel *chan)
+{
+    assert(!"NYI");
+    return SYS_ERR_OK;
+}
+
+/**
+ * \brief enqueues a request onto the IOAT DMA channel and submits it to the
+ *        hardware
+ *
+ * \param chan  IOAT DMA channel
+ * \param req   IOAT DMA request to be submitted
+ *
+ * \returns SYS_ERR_OK on success
+ *          DMA_ERR_* on failure
+ */
+errval_t xeon_phi_dma_channel_submit_request(struct xeon_phi_dma_channel *chan,
+                struct xeon_phi_dma_request *req)
+{
+    IOATCHAN_DEBUG("submit request [%016lx]\n", chan->common.id,
+                    dma_request_get_id((struct dma_request * )req));
+
+    dma_channel_enq_request_tail(&chan->common, (struct dma_request *) req);
+
+    xeon_phi_dma_channel_issue_pending(chan);
+
+    return SYS_ERR_OK;
+}
+
+/**
+ * \brief polls the IOAT DMA channel for completed events
+ *
+ * \param chan  IOAT DMA channel
+ *
+ * \returns SYS_ERR_OK if there was something processed
+ *          DMA_ERR_CHAN_IDLE if there was no request on the channel
+ *          DMA_ERR_REQUEST_UNFINISHED if the request has not been completed yet
+ *
+ */
+errval_t xeon_phi_dma_channel_poll(struct dma_channel *chan)
+{
+    errval_t err;
+
+    struct xeon_phi_dma_channel *xeon_phi_chan = (struct xeon_phi_dma_channel *)chan;
+
+    uint64_t status = xeon_phi_dma_channel_get_status(xeon_phi_chan);
+
+    if (xeon_phi_dma_channel_is_halted(status)) {
+        IOATCHAN_DEBUG("channel is in error state\n", chan->id);
+        assert(!"NYI: error event handling");
+    }
+
+    /* check if there can be something to process */
+    if (chan->req_list.head == NULL) {
+        return DMA_ERR_CHAN_IDLE;
+    }
+
+    lpaddr_t compl_addr_phys = channel_has_completed_descr(xeon_phi_chan);
+    if (!compl_addr_phys) {
+        return DMA_ERR_CHAN_IDLE;
+    }
+
+    err = channel_process_descriptors(xeon_phi_chan, compl_addr_phys);
+    switch (err_no(err)) {
+        case SYS_ERR_OK:
+        /* this means we processed a descriptor request */
+        return SYS_ERR_OK;
+        case DMA_ERR_REQUEST_UNFINISHED:
+        return DMA_ERR_CHAN_IDLE;
+        default:
+        return err;
+    }
+}
+
+/*
+ * ----------------------------------------------------------------------------
+ * Getter / Setter Functions
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief returns the associated IOAT DMA descriptor ring of a channel
+ *
+ * \param chan  IOAT DMA channel
+ *
+ * \returns IOAT DMA descriptor ring handle
+ */
+inline struct xeon_phi_dma_ring *xeon_phi_dma_channel_get_ring(struct xeon_phi_dma_channel *chan)
+{
+    return chan->ring;
+}
+
+/**
+ * \brief updates the channel status flag by reading the CHANSTS register
+ *
+ * \param chan IOAT DMA channel
+ */
+inline uint64_t xeon_phi_dma_channel_get_status(struct xeon_phi_dma_channel *chan)
+{
+    uint32_t status_lo = xeon_phi_dma_chan_sts_lo_rd(&chan->channel);
+    chan->status = xeon_phi_dma_chan_sts_hi_rd(&chan->channel);
+    chan->status <<= 32;
+    chan->status |= status_lo;
+
+    return chan->status;
+}
+
+#endif
diff --git a/lib/dma/xeon_phi/xeon_phi_dma_descriptors.c b/lib/dma/xeon_phi/xeon_phi_dma_descriptors.c
new file mode 100644 (file)
index 0000000..ad75f1d
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * 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 <xeon_phi/xeon_phi.h>
+#include <dev/xeon_phi/xeon_phi_dma_dev.h>
+
+#include <dma_mem_utils.h>
+
+#include <xeon_phi/xeon_phi_dma_internal.h>
+#include <xeon_phi/xeon_phi_dma_descriptors_internal.h>
+
+#include <debug.h>
+
+
+/*
+ * ============================================================================
+ * Library Internal Interface
+ * ============================================================================
+ */
+
+#if 0
+/*
+ * ----------------------------------------------------------------------------
+ * Descriptor getters / setters
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief sets the next pointer of the descriptor and does the corresponding
+ *        hardware linkage
+ *
+ * \param desc descriptor to set the next field
+ * \param next following descriptor
+ */
+inline void xeon_phi_dma_desc_set_next(struct xeon_phi_dma_descriptor *desc,
+                struct xeon_phi_dma_descriptor *next)
+{
+    xeon_phi_dma_desc_next_insert(desc->desc, next->paddr);
+    desc->next = next;
+}
+
+/**
+ * \brief returns a virtual address pointer to the location where the descriptor
+ *        is mapped
+ *
+ * \param desc XEON_PHI DMA descriptor
+ */
+inline xeon_phi_dma_desc_t xeon_phi_dma_desc_get_desc_handle(struct xeon_phi_dma_descriptor *desc)
+{
+    return desc->desc;
+}
+
+/*
+ * ============================================================================
+ * Public Interface
+ * ============================================================================
+ */
+
+/**
+ * \brief initializes the hardware specific part of the descriptor
+ *
+ * \param desc  XEON_PHI DMA descriptor
+ * \param src   Source address of the transfer
+ * \param dst   destination address of the transfer
+ * \param size  number of bytes to copy
+ * \param ctrl  control flags
+ *
+ * XXX: this function assumes that the size of the descriptor has already been
+ *      checked and must match the maximum transfer size of the channel
+ */
+inline void xeon_phi_dma_desc_fill_memcpy(struct xeon_phi_dma_descriptor *desc,
+                lpaddr_t src,
+                lpaddr_t dst,
+                uint32_t size,
+                xeon_phi_dma_desc_ctrl_t ctrl)
+{
+    xeon_phi_dma_desc_size_insert(desc->desc, size);
+    xeon_phi_dma_desc_ctrl_insert(desc->desc, *((uint32_t *) ctrl));
+    xeon_phi_dma_desc_src_insert(desc->desc, src);
+    xeon_phi_dma_desc_dst_insert(desc->desc, dst);
+}
+
+/**
+ * \brief initializes the hardware specific part of the descriptor to be used
+ *        for nop descriptors (null descriptors)
+ *
+ * \param desc  XEON_PHI DMA descriptor
+ */
+inline void xeon_phi_dma_desc_fill_nop(struct xeon_phi_dma_descriptor *desc)
+{
+    uint32_t ctrl = 0;
+    xeon_phi_dma_desc_ctrl_t dma_ctrl = (xeon_phi_dma_desc_ctrl_t)(&ctrl);
+    xeon_phi_dma_desc_ctrl_int_en_insert(dma_ctrl, 0x1);
+    xeon_phi_dma_desc_ctrl_null_insert(dma_ctrl, 0x1);
+    xeon_phi_dma_desc_ctrl_compl_write_insert(dma_ctrl, 0x1);
+
+    xeon_phi_dma_desc_size_insert(desc->desc, 1);   // size must be non zero
+    xeon_phi_dma_desc_ctrl_insert(desc->desc, ctrl);
+    xeon_phi_dma_desc_src_insert(desc->desc, 0);
+    xeon_phi_dma_desc_dst_insert(desc->desc, 0);
+}
+
+/*
+ * ----------------------------------------------------------------------------
+ * Descriptor getters / setters
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief returns the corresponding XEON_PHI DMA request this descriptor belongs
+ *
+ * \param desc XEON_PHI DMA descriptor
+ *
+ * \brief pointer to the request
+ *        NULL if there is none
+ */
+inline struct xeon_phi_dma_request *xeon_phi_dma_desc_get_request(struct xeon_phi_dma_descriptor *desc)
+{
+    return desc->req;
+}
+
+/**
+ * \brief returns a pointer to the next descriptor in a chain
+ *
+ * \param desc XEON_PHI DMA descriptor
+ *
+ * \returns next descriptor
+ *          NULL if the end of chain
+ */
+struct xeon_phi_dma_descriptor *xeon_phi_dma_desc_get_next(struct xeon_phi_dma_descriptor *desc)
+{
+    return desc->next;
+}
+
+/**
+ * \brief returns the physical address of the descriptor
+ *
+ * \param desc XEON_PHI DMA descriptor
+ *
+ * \returns physical address of the descriptor
+ */
+inline lpaddr_t xeon_phi_dma_desc_get_paddr(struct xeon_phi_dma_descriptor *desc)
+{
+    return desc->paddr;
+}
+
+/**
+ * \brief returns a virtual address pointer to the location where the descriptor
+ *        is mapped
+ *
+ * \param desc XEON_PHI DMA descriptor
+ */
+inline xeon_phi_dma_desc_t xeon_phi_dma_desc_get_desc(struct xeon_phi_dma_descriptor *desc)
+{
+    return desc->desc;
+}
+
+/**
+ * \brief sets the corresponding request
+ *
+ * \param desc XEON_PHI DMA descriptor
+ */
+inline void xeon_phi_dma_desc_set_request(struct xeon_phi_dma_descriptor *desc,
+                struct xeon_phi_dma_request *req)
+{
+    desc->req = req;
+}
+#endif
diff --git a/lib/dma/xeon_phi/xeon_phi_dma_device.c b/lib/dma/xeon_phi/xeon_phi_dma_device.c
new file mode 100644 (file)
index 0000000..a5644b3
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * 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 <dev/xeon_phi/xeon_phi_dma_dev.h>
+
+#include <dma_mem_utils.h>
+
+#include <xeon_phi/xeon_phi_dma_internal.h>
+#include <xeon_phi/xeon_phi_dma_device_internal.h>
+#include <xeon_phi/xeon_phi_dma_channel_internal.h>
+
+#include <debug.h>
+
+/**
+ * Xeon Phi DMA device representation
+ */
+struct xeon_phi_dma_device
+{
+    struct dma_device common;
+
+    xeon_phi_dma_t device;                  ///< mackerel device base
+
+    uint32_t flags;
+};
+
+/// counter for device ID enumeration
+static dma_dev_id_t device_id = 1;
+
+/*
+ * ===========================================================================
+ * Library Internal Interface
+ * ===========================================================================
+ */
+
+/**
+ * \brief globally enables the interrupts for the given device
+ *
+ * \param dev   Xeon Phi DMA device
+ * \param type  the interrupt type to enable
+ */
+errval_t xeon_phi_dma_device_irq_setup(struct xeon_phi_dma_device *dev,
+                                       dma_irq_t type)
+{
+    assert(!"NYI");
+
+    return SYS_ERR_OK;
+}
+
+/**
+ * \brief gets the Xeon Phi virtual base address of the DMA channel with
+ *        the given id
+ *
+ * \param dev   Xeon Phi DMA device
+ * \param idx   DMA channel index
+ *
+ * \returns virtual address of MMIO registers for the channel
+ */
+void *xeon_phi_dma_device_get_channel_vbase(struct xeon_phi_dma_device *dev,
+                                            uint8_t idx)
+{
+    idx += XEON_PHI_DMA_DEVICE_CHAN_OFFSET;
+    assert(idx < XEON_PHI_DMA_DEVICE_CHAN_TOTAL);
+    return (void *)(dev->common.mmio.vaddr + (idx * 0x80));
+}
+
+/*
+ * ===========================================================================
+ * Public Interface
+ * ===========================================================================
+ */
+
+/*
+ * ----------------------------------------------------------------------------
+ * device initialization / termination
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief initializes a Xeon Phi DMA device with the giving capability
+ *
+ * \param mmio capability representing the device's MMIO registers
+ * \param dev  returns a pointer to the device structure
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on error
+ */
+errval_t xeon_phi_dma_device_init(mackerel_addr_t mmio_base,
+                                  struct xeon_phi_dma_device **dev)
+{
+    errval_t err;
+
+    struct xeon_phi_dma_device *xdev = calloc(1, sizeof(*xdev));
+    if (xdev == NULL) {
+        return LIB_ERR_MALLOC_FAIL;
+    }
+
+    struct dma_device *dma_dev = (struct dma_device *) xdev;
+
+    XPHIDEV_DEBUG("initializing Xeon Phi DMA device @ %p", device_id, mmio_base);
+
+    dma_dev->id = device_id++;
+    dma_dev->irq_type = DMA_IRQ_DISABLED;
+    dma_dev->type = DMA_DEV_TYPE_XEON_PHI;
+    dma_dev->mmio.vaddr = (lvaddr_t)mmio_base;
+
+    xeon_phi_dma_initialize(&xdev->device, mmio_base);
+
+
+    XPHIDEV_DEBUG("initializing %u channels", device_id,
+                  XEON_PHI_DMA_DEVICE_CHANNELS);
+
+    dma_dev->channels.count = XEON_PHI_DMA_DEVICE_CHANNELS;
+    dma_dev->channels.c = calloc(XEON_PHI_DMA_DEVICE_CHANNELS,
+                                 sizeof(*dma_dev->channels.c));
+
+    if (dma_dev->channels.c == NULL) {
+        device_id--;
+        free(xdev);
+        return LIB_ERR_MALLOC_FAIL;
+    }
+
+    for (uint8_t i = 0; i < XEON_PHI_DMA_DEVICE_CHANNELS; ++i) {
+        struct dma_channel **chan = &dma_dev->channels.c[i];
+        err = xeon_phi_dma_channel_init(xdev, i, XEON_PHI_DMA_DEVICE_MAX_XFER,
+                                        (struct xeon_phi_dma_channel **) chan);
+        if (err_is_fail(err)) {
+            free(dma_dev->channels.c);
+            device_id--;
+            free(xdev);
+            return err;
+        }
+
+        /*
+         * set the channel owner
+         */
+
+    }
+
+    *dev = xdev;
+
+    return err;
+}
+
+/**
+ * \brief terminates the device operation and frees up the allocated resources
+ *
+ * \param dev Xeon Phi DMA device to shutdown
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on error
+ */
+errval_t xeon_phi_dma_device_shutdown(struct xeon_phi_dma_device *dev)
+{
+    assert(!"NYI");
+    return SYS_ERR_OK;
+}
+
+/*
+ * ----------------------------------------------------------------------------
+ * Interrupt management
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief enables the interrupts for the device
+ *
+ * \param dev   Xeon Phi DMA device
+ * \param type  interrupt type
+ * \param fn    interrupt handler function
+ * \param arg   argument supplied to the handler function
+ */
+errval_t xeon_phi_dma_device_intr_enable(struct xeon_phi_dma_device *dev,
+                                         dma_irq_t type,
+                                         dma_irq_fn_t fn,
+                                         void *arg)
+{
+    assert(!"NYI");
+    return SYS_ERR_OK;
+}
+
+/**
+ * \brief disables the interrupts for the device
+ *
+ * \param dev   Xeon Phi DMA device
+ */
+void xeon_phi_dma_device_intr_disable(struct xeon_phi_dma_device *dev)
+{
+    assert(!"NYI");
+}
+
+/*
+ * ----------------------------------------------------------------------------
+ * Device Operation Functions
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief polls the channels of the Xeon Phi DMA device
+ *
+ * \param dev   Xeon Phi DMA device
+ *
+ * \returns SYS_ERR_OK on success
+ *          DMA_ERR_DEVICE_IDLE if there is nothing completed on the channels
+ *          errval on error
+ */
+errval_t xeon_phi_dma_device_poll_channels(struct dma_device *dev)
+{
+    errval_t err;
+
+    assert(!"CHECK");
+
+    uint8_t idle = 0x1;
+
+    struct xeon_phi_dma_channel * chan;
+    for (uint8_t i = 0; i < dev->channels.count; ++i) {
+        chan = (struct xeon_phi_dma_channel *)dev->channels.c[i];
+        err = xeon_phi_dma_channel_poll(chan);
+        switch (err_no(err)) {
+            case DMA_ERR_CHAN_IDLE:
+                idle = idle && 0x1;
+                break;
+            case SYS_ERR_OK:
+                idle = 0;
+                break;
+            default:
+                return err;
+        }
+    }
+
+    if (idle) {
+        return DMA_ERR_DEVICE_IDLE;
+    }
+
+    return SYS_ERR_OK;
+}
+
diff --git a/lib/dma/xeon_phi/xeon_phi_dma_request.c b/lib/dma/xeon_phi/xeon_phi_dma_request.c
new file mode 100644 (file)
index 0000000..6c7d84b
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * 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.
+ */
+#if 0
+#include<barrelfish/barrelfish.h>
+
+#include <xeon_phi/xeon_phi_dma_internal.h>
+#include <xeon_phi/xeon_phi_dma_device_internal.h>
+#include <xeon_phi/xeon_phi_dma_channel_internal.h>
+#include <xeon_phi/xeon_phi_dma_request_internal.h>
+#include <xeon_phi/xeon_phi_dma_descriptors_internal.h>
+#include <xeon_phi/xeon_phi_dma_ring_internal.h>
+
+#include <debug.h>
+
+/**
+ * represens the IOAT specific DMA requests
+ */
+struct xeon_phi_dma_request
+{
+    struct dma_request common;
+    struct xeon_phi_dma_descriptor *desc_head;
+    struct xeon_phi_dma_descriptor *desc_tail;
+};
+
+/*
+ * ---------------------------------------------------------------------------
+ * Request Management
+ * ---------------------------------------------------------------------------
+ */
+
+/// caches allocated requests which are no longer used
+static struct dma_request *req_free_list = NULL;
+
+/**
+ * \brief allocates a IOAT DMA request structure
+ *
+ * \returns IOAT DMA request
+ *          NULL on failure
+ */
+static struct xeon_phi_dma_request *request_alloc(void)
+{
+    struct xeon_phi_dma_request *ret;
+
+    if (req_free_list) {
+        ret = (struct xeon_phi_dma_request *) req_free_list;
+        req_free_list = ret->common.next;
+
+        DMAREQ_DEBUG("meta: reusing request %p. freelist:%p\n", ret,
+                     req_free_list);
+
+        return ret;
+    }
+    return calloc(1, sizeof(*ret));
+}
+
+/**
+ * \brief frees up the used DMA request structure
+ *
+ * \param req   DMA request to be freed
+ */
+static void request_free(struct xeon_phi_dma_request *req)
+{
+    DMAREQ_DEBUG("meta: freeing request %p.\n", req);
+    req->common.next = req_free_list;
+    req_free_list = &req->common;
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Helper Functions
+ * ---------------------------------------------------------------------------
+ */
+
+inline static uint32_t req_num_desc_needed(struct xeon_phi_dma_channel *chan,
+                                           size_t bytes)
+{
+    struct dma_channel *dma_chan = (struct dma_channel *) chan;
+    uint32_t max_xfer_size = dma_channel_get_max_xfer_size(dma_chan);
+    bytes += (max_xfer_size - 1);
+    return (uint32_t) (bytes / max_xfer_size);
+}
+
+/*
+ * ===========================================================================
+ * Library Internal Interface
+ * ===========================================================================
+ */
+
+/**
+ * \brief handles the processing of completed DMA requests
+ *
+ * \param req   the DMA request to process
+ *
+ * \returns SYS_ERR_OK on sucess
+ *          errval on failure
+ */
+errval_t xeon_phi_dma_request_process(struct xeon_phi_dma_request *req)
+{
+    errval_t err;
+
+    req->common.state = DMA_REQ_ST_DONE;
+
+    err = dma_request_process(&req->common);
+    if (err_is_fail(err)) {
+        return err;
+    }
+
+    request_free(req);
+
+    return SYS_ERR_OK;
+}
+
+/*
+ * ===========================================================================
+ * Public Interface
+ * ===========================================================================
+ */
+
+/**
+ * \brief issues a memcpy request to the given channel
+ *
+ * \param chan  IOAT DMA channel
+ * \param setup request setup information
+ * \param id    returns the generated request id
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on failure
+ */
+errval_t xeon_phi_dma_request_memcpy_chan(struct dma_channel *chan,
+                                      struct dma_req_setup *setup,
+                                      dma_req_id_t *id)
+{
+    assert(chan->device->type == DMA_DEV_TYPE_IOAT);
+
+    struct xeon_phi_dma_channel *xeon_phi_chan = (struct xeon_phi_dma_channel *) chan;
+
+    uint32_t num_desc = req_num_desc_needed(xeon_phi_chan, setup->args.memcpy.bytes);
+
+    IOATREQ_DEBUG("DMA Memcpy request: [0x%016lx]->[0x%016lx] of %lu bytes (%u desc)\n",
+                  setup->args.memcpy.src, setup->args.memcpy.dst,
+                  setup->args.memcpy.bytes, num_desc);
+
+    struct xeon_phi_dma_ring *ring = xeon_phi_dma_channel_get_ring(xeon_phi_chan);
+
+    if (num_desc > xeon_phi_dma_ring_get_space(ring)) {
+        IOATREQ_DEBUG("Too less space in ring: %u / %u\n", num_desc,
+                      xeon_phi_dma_ring_get_space(ring));
+        return DMA_ERR_NO_DESCRIPTORS;
+    }
+
+    struct xeon_phi_dma_request *req = request_alloc();
+    if (req == NULL) {
+        IOATREQ_DEBUG("No request descriptors for holding request data\n");
+        return DMA_ERR_NO_REQUESTS;
+    }
+
+    xeon_phi_dma_desc_ctrl_array_t ctrl = {
+        0
+    };
+
+    struct xeon_phi_dma_descriptor *desc;
+    size_t length = setup->args.memcpy.bytes;
+    lpaddr_t src = setup->args.memcpy.src;
+    lpaddr_t dst = setup->args.memcpy.dst;
+    size_t bytes, max_xfer_size = dma_channel_get_max_xfer_size(chan);
+    do {
+        desc = xeon_phi_dma_ring_get_next_desc(ring);
+
+        if (!req->desc_head) {
+            req->desc_head = desc;
+        }
+        if (length <= max_xfer_size) {
+            /* the last one */
+            bytes = length;
+            req->desc_tail = desc;
+
+            xeon_phi_dma_desc_ctrl_fence_insert(ctrl, setup->args.memcpy.ctrl_fence);
+            xeon_phi_dma_desc_ctrl_int_en_insert(ctrl, setup->args.memcpy.ctrl_intr);
+            xeon_phi_dma_desc_ctrl_compl_write_insert(ctrl, 0x1);
+        } else {
+            bytes = max_xfer_size;
+        }
+
+        xeon_phi_dma_desc_fill_memcpy(desc, src, dst, bytes, ctrl);
+        xeon_phi_dma_desc_set_request(desc, NULL);
+
+        length -= bytes;
+        src += bytes;
+        dst += bytes;
+    } while (length > 0);
+
+    req->common.setup = *setup;
+    req->common.id = dma_request_generate_req_id((struct dma_channel *) xeon_phi_chan);
+
+    *id = req->common.id;
+
+    /* set the request pointer in the last descriptor */
+    xeon_phi_dma_desc_set_request(desc, req);
+
+    assert(req->desc_tail);
+    assert(xeon_phi_dma_desc_get_request(req->desc_tail));
+
+    return xeon_phi_dma_channel_submit_request(xeon_phi_chan, req);
+}
+
+/**
+ * \brief issues a memcpy request to a channel of the given device
+ *
+ * \param dev   IOAT DMA device
+ * \param setup request setup information
+ * \param id    returns the generated request id
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on failure
+ */
+errval_t xeon_phi_dma_request_memcpy(struct dma_device *dev,
+                                 struct dma_req_setup *setup,
+                                 dma_req_id_t *id)
+{
+    struct dma_channel *chan = dma_device_get_channel(dev);
+    return xeon_phi_dma_request_memcpy_chan(chan, setup, id);
+}
+
+/**
+ * \brief issues a NOP / NULL descriptor request on the given channel
+ *
+ * \param chan  IOAT DMA channel
+ * \param setup request setup information
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on failure
+ */
+void xeon_phi_dma_request_nop_chan(struct xeon_phi_dma_channel *chan)
+{
+
+    struct xeon_phi_dma_ring *ring = xeon_phi_dma_channel_get_ring(chan);
+    assert(ring);
+
+    struct xeon_phi_dma_descriptor *desc = xeon_phi_dma_ring_get_next_desc(ring);
+    assert(desc);
+    IOATREQ_DEBUG("New DMA NOP request: descriptor=%p\n", desc);
+
+    xeon_phi_dma_desc_fill_nop(desc);
+}
+
+/**
+ * \brief issues a NOP / NULL descriptor request on the given device
+ *
+ * \param dev   IOAT DMA device
+ * \param setup request setup information
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on failure
+ */
+inline void xeon_phi_dma_request_nop(struct xeon_phi_dma_device *dev)
+{
+    struct xeon_phi_dma_channel *chan;
+    struct dma_device *dma_dev = (struct dma_device *)dev;
+    chan = (struct xeon_phi_dma_channel *)dma_device_get_channel(dma_dev);
+    xeon_phi_dma_request_nop_chan(chan);
+}
+#endif