LIB DMA: introduced generic parts of the structs (not fully done yet)
authorReto Achermann <acreto@student.ethz.ch>
Fri, 18 Jul 2014 13:10:11 +0000 (15:10 +0200)
committerStefan Kaestle <stefan.kaestle@inf.ethz.ch>
Wed, 20 Aug 2014 21:39:53 +0000 (23:39 +0200)
33 files changed:
errors/errno.fugu
include/dma/dma_channel.h [new file with mode: 0644]
include/dma/dma_device.h [new file with mode: 0644]
include/dma/dma_request.h [new file with mode: 0644]
include/dma/ioat/ioat_dma.h
include/dma/ioat/ioat_dma_channel.h
include/dma/ioat/ioat_dma_descriptors.h [new file with mode: 0644]
include/dma/ioat/ioat_dma_device.h [new file with mode: 0644]
include/dma/ioat/ioat_dma_request.h
include/dma/ioat/ioat_dma_ring.h [new file with mode: 0644]
lib/dma/Hakefile
lib/dma/dma_channel.c [new file with mode: 0644]
lib/dma/dma_device.c [new file with mode: 0644]
lib/dma/dma_mem_utils.c
lib/dma/dma_request.c [new file with mode: 0644]
lib/dma/include/dma_channel_internal.h [new file with mode: 0644]
lib/dma/include/dma_device_internal.h [new file with mode: 0644]
lib/dma/include/dma_request_internal.h [new file with mode: 0644]
lib/dma/include/ioat/ioat_dma_channel_internal.h
lib/dma/include/ioat/ioat_dma_dca_internal.h
lib/dma/include/ioat/ioat_dma_descriptors_internal.h
lib/dma/include/ioat/ioat_dma_device_internal.h
lib/dma/include/ioat/ioat_dma_request_internal.h
lib/dma/include/ioat/ioat_dma_ring_internal.h
lib/dma/ioat/ioat_dma.c
lib/dma/ioat/ioat_dma_channel.c
lib/dma/ioat/ioat_dma_dca.c
lib/dma/ioat/ioat_dma_descriptors.c
lib/dma/ioat/ioat_dma_device.c
lib/dma/ioat/ioat_dma_request.c
lib/dma/ioat/ioat_dma_ring.c
usr/drivers/ioat_dma/ioat_dma_descriptors.c
usr/drivers/ioat_dma/ioat_dma_ring.h

index 2d2db50..d37e70b 100755 (executable)
@@ -1067,6 +1067,7 @@ errors ioat IOAT_ERR_ {
     failure DEVICE_IDLE           "The device is idle, no transfers finished",
     failure ARG_INVALID           "Supplied argument was not valid",
     failure CHAN_ERROR            "Hardware channel error",
+    failure RESET_TIMEOUT         "The reset attempt timed out",
     failure NO_DESCRIPTORS        "There are too less descriptors available",
     failure NO_REQUESTS           "There are no request descriptors left",
     failure CHAN_BUSY             "The channel is busy and cannot accept more",
diff --git a/include/dma/dma_channel.h b/include/dma/dma_channel.h
new file mode 100644 (file)
index 0000000..c257581
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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_DMA_CHANNEL_H
+#define LIB_DMA_CHANNEL_H
+
+struct dma_channel;
+
+/// DMA channel id
+typedef uint16_t dma_chan_id_t;
+
+/// DMA channel state
+typedef enum dma_chan_st
+{
+    DMA_CHAN_ST_INVALID,
+    DMA_CHAN_ST_RESETTING,
+    DMA_CHAN_ST_UNINITIALEZED,
+    DMA_CHAN_ST_PREPARED,
+    DMA_CHAN_ST_RUNNING,
+    DMA_CHAN_ST_ERROR,
+    DMA_CHAN_ST_SUSPENDED
+} dma_chan_st_t;
+
+
+
+/**
+ * \brief generates the DMA channel ID from the device and the channel index
+ *
+ * \param dev   device ID
+ * \param idx   channel index
+ *
+ * \returns DMA channel ID
+ */
+static inline ioat_dma_chan_id_t dma_channel_build_id(ioat_dma_devid_t dev,
+                                                      uint8_t idx)
+{
+    return ((((uint16_t) dev) << 8) | idx);
+}
+
+#endif  /* LIB_DMA_CHANNEL_H */
diff --git a/include/dma/dma_device.h b/include/dma/dma_device.h
new file mode 100644 (file)
index 0000000..944f826
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * 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_DMA_DEVICE_H
+#define LIB_DMA_DEVICE_H
+
+struct dma_device;
+struct dma_channel;
+
+/// IOAT DMA channel id
+typedef uint8_t dma_dev_id_t;
+
+/// representation of a PCI address (with more bits)
+struct pci_addr {
+    uint32_t bus;
+    uint32_t device;
+    uint32_t function;
+};
+
+typedef enum dma_dev_type {
+
+} dma_dev_type_t;
+
+/**
+ * Device State Enumeration
+ */
+typedef enum dma_dev_st {
+    DMA_DEV_ST_INVALID,        ///< this device structure is invalid
+    DMA_DEV_ST_UNINITIALIZED,  ///< device has not been initialized yet
+    DMA_DEV_ST_CHAN_ENUM,      ///< device is doing channel enumeration
+    DMA_DEV_ST_RUNNING,        ///< device is operational
+    DMA_DEV_ST_SUSPENDED,      ///< device is suspended state
+    DMA_DEV_ST_ERR             ///< an error occurred
+} dma_dev_st_t;
+
+
+/**
+ * Enumeration of possible interrupt types supported by the hardware
+ */
+typedef enum dma_irq {
+    DMA_IRQ_DISABLED,          ///< interrupts are disabled
+    DMA_IRQ_MSIX,              ///< use MSI-X interrupts
+    DMA_IRQ_MSI,               ///< use MSI interrupts
+    DMA_IRQ_INTX,              ///< use normal INTx interrupts
+} dma_irq_t;
+
+/// interrupt handler function
+typedef void (*dma_irq_fn_t)(struct dma_channel *dev, void *);
+
+/*
+ * ----------------------------------------------------------------------------
+ * device initialization / termination
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief terminates the device operation and frees up the allocated resources
+ *
+ * \param dev IOAT DMA device to shutdown
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on error
+ */
+errval_t dma_device_shutdown(struct dma_device *dev);
+
+/**
+ * \brief requests access to a IOAT DMA device from the IOAT device manager
+ *        and initializes the device.
+ *
+ * \param dev  returns a pointer to the device structure
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on error
+ */
+errval_t dma_device_acquire(struct dma_device **dev);
+
+/**
+ * \brief terminates the device operation and frees up the allocated resources
+ *        and releases the device and returns it to the IOAT device manager.
+ *
+ * \param dev IOAT DMA device to be released
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on error
+ */
+errval_t dma_device_release(struct dma_device *dev);
+
+
+/*
+ * ----------------------------------------------------------------------------
+ * Interrupt management
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief enables the interrupts for the device
+ *
+ * \param dev   IOAT DMA device
+ * \param type  interrupt type
+ * \param fn    interrupt handler function
+ * \param arg   argument supplied to the handler function
+ */
+errval_t dma_device_intr_enable(struct dma_device *dev,
+                                     dma_irq_t type,
+                                     dma_irq_fn_t fn,
+                                     void *arg);
+
+/**
+ * \brief disables the interrupts for the device
+ *
+ * \param dev   IOAT DMA device
+ */
+void dma_device_intr_disable(struct dma_device *dev);
+
+/**
+ * \brief sets the interrupt delay for the device
+ *
+ * \param dev   IOAT DMA device
+ * \param usec  interrupt delay in microseconds
+ */
+void dma_device_set_intr_delay(struct dma_device *dev,
+                               uint16_t usec);
+
+/*
+ * ----------------------------------------------------------------------------
+ * Device Operation Functions
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief gets the device state from the IOAT DMA device
+ *
+ * \param dev   IOAT DMA device
+ *
+ * \returns device state enumeration
+ */
+dma_dev_st_t dma_device_get_state(struct dma_device *dev);
+
+
+/**
+ * \brief returns the channel count of this device
+ *
+ * \param dev   IOAT DMA device
+ *
+ * \returns number of channels this device has
+ */
+uint8_t dma_device_get_channel_count(struct dma_device *dev);
+
+/**
+ * \brief returns the device ID from the IOAT device
+ *
+ * \param dev   IOAT DMA device
+ *
+ * \returns IOAT DMA device ID
+ */
+dma_dev_id_t dma_device_get_id(struct dma_device *dev);
+
+/**
+ * \brief returns the channel belonging with the given ID
+ *
+ * \param dev   IOAT DMA device
+ * \param id    channel id
+ *
+ * return IOAT DMA channel handle
+ *        NULL if no such channel exist
+ */
+struct dma_channel *dma_device_get_channel(struct dma_device *dev,
+                                           uint16_t id);
+
+/**
+ * \brief returns a channel from the device based on a round robin fashion
+ *
+ * \param dev   IOAT DMA device
+ *
+ * return IOAT DMA channel handle
+ */
+struct dma_channel *dma_device_get_next_channel(struct dma_device *dev);
+
+
+
+#endif  /* LIB_DMA_CHANNEL_H */
diff --git a/include/dma/dma_request.h b/include/dma/dma_request.h
new file mode 100644 (file)
index 0000000..3c6dd27
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * 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_DMA_REQUEST_H
+#define LIB_DMA_REQUEST_H
+
+struct ioat_dma_request;
+
+/// IOAT DMA request ID
+typedef uint64_t dma_req_id_t;
+
+/// callback to be called when the request is finished
+typedef void (*dma_cb_t)(errval_t,
+                         dma_req_id_t,
+                         void *);
+
+/**
+ * enumeration of the possible request types
+ */
+typedef enum dma_req_type
+{
+    IOAT_DMA_REQ_TYPE_INVALID,  ///< invalid request
+    IOAT_DMA_REQ_TYPE_NOP,      ///< NULL / NOP request
+    IOAT_DMA_REQ_TYPE_MEMCPY    ///< Memcpy request
+} dma_req_type_t;
+
+/**
+ * enumeration of the request states
+ */
+typedef enum dma_req_st
+{
+    IOAT_DMA_REQ_ST_INVALID,    ///< request is invalid
+    IOAT_DMA_REQ_ST_PREPARED,   ///< request is prepared
+    IOAT_DMA_REQ_ST_SUBMITTED,  ///< request is submitted to hardware
+    IOAT_DMA_REQ_ST_DONE,       ///< request has been executed
+    IOAT_DMA_REQ_ST_ERR         ///< request execution failed
+} dma_req_st_t;
+
+/**
+ * specifies the DMA request setup fields
+ */
+struct dma_req_setup
+{
+    dma_req_type_t type;           ///< specifies the request type
+    dma_cb_t done_cb;              ///< callback for executed request
+    void *arg;                     ///< argument for the callback
+    union
+    {
+        struct
+        {
+            lpaddr_t src;          ///< source physical address
+            lpaddr_t dst;          ///< destination physical address
+            size_t bytes;          ///< size of the transfer in bytes
+            uint8_t ctrl_intr :1;  ///< do an interrupt upon completion
+            uint8_t ctrl_fence :1; ///< do a mem fence upon completion
+        } memcpy;                  ///< memcpy request
+
+    } args;                        ///< request setup arguments
+
+};
+
+/**
+ * common structure for all DMA requests
+ */
+struct dma_request
+{
+    dma_req_id_t id;            ///<
+    dma_req_st_t state;         ///<
+    struct dma_req_setup setup; ///<
+};
+
+/**
+ *
+ */
+errval_t dma_request_memcpy(struct dma_req_setup *setup);
+
+errval_t dma_request_nop(struct dma_req_setup *setup);
+
+errval_t dma_request_exec(struct dma_req_setup *setup);
+
+dma_req_st_t dma_request_get_state(struct dma_request *req);
+
+static inline dma_req_id_t dma_request_id_build(struct dma_channel *chan)
+{
+    dma_req_id_t id = dma_channel_get_id(chan);
+    id <<= 48;
+    id |= (0x0000FFFFFFFFFFFF & dma_channel_incr_req_counter(chan));
+    return id;
+}
+
+#endif  /* LIB_DMA_REQUEST_H */
index d1b8c7c..161e3fd 100644 (file)
  */
 errval_t ioat_dma_init(uint8_t dca_enabled);
 
-/**
- * \brief enables direct cache access
- */
-void ioat_dma_dca_enable(void);
-
-/**
- * \brief disables direct cache access
- */
-void ioat_dma_dca_disable(void);
-
-
-/**
- * \brief checks whether DCA is enabled
- *
- * \returns 1 if DCA is enabled
- *          0 if DCA is disabled
- */
-uint8_t ioat_dma_dca_is_enabled(void);
 
 #endif  /* LIB_IOAT_DMA_H */
index 9a455ae..6d53148 100644 (file)
 #ifndef LIB_IOAT_DMA_CHANNEL_H
 #define LIB_IOAT_DMA_CHANNEL_H
 
-typedef uint16_t ioat_dma_chan_id_t;
-
-enum ioat_dma_chan_st
-{
-    IOAT_DMA_CHAN_ST_INVALID,
-    IOAT_DMA_CHAN_ST_RESETTING,
-    IOAT_DMA_CHAN_ST_UNINITIALEZED,
-    IOAT_DMA_CHAN_ST_PREPARED,
-    IOAT_DMA_CHAN_ST_RUNNING,
-    IOAT_DMA_CHAN_ST_ERROR,
-    IOAT_DMA_CHAN_ST_SUSPENDED,
-    IOAT_DMA_CHAN_ST_INIT_FAIL,
-};
-
-static inline ioat_dma_chan_id_t ioat_dma_channel_build_id(ioat_dma_devid_t dev,
-                                                           uint8_t id)
-{
-    return ((((uint16_t) dev) << 8) | id);
-}
+struct ioat_dma_channel;
+struct ioat_dma_request;
+
+
+
+
+
+/**
+ * \brief Resets a IOAT DMA channel
+ *
+ * \param chan  IOAT DMA channel to be reset
+ *
+ * \returns SYS_ERR_OK on success
+ *          IOAT_ERR_CHAN_RESET on reset timeout
+ */
+errval_t ioat_dma_channel_reset(struct ioat_dma_channel *chan);
+
+
+/*
+ * ----------------------------------------------------------------------------
+ * Getter / Setter Functions
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief returns the IOAT DMA channel ID
+ *
+ * \param chan  IOAT DMA channel
+ *
+ * \returns IOAT DMA channel ID of the supplied channel
+ */
+ioat_dma_chan_id_t ioat_dma_channel_get_id(struct ioat_dma_channel *chan);
+
+/**
+ * \brief returns the associated IOAT DMA descriptor ring of a channel
+ *
+ * \param chan  IOAT DMA channel
+ *
+ * \returns IOAT DMA descriptor ring handle
+ */
+struct ioat_dma_ring *ioat_dma_channel_get_ring(struct ioat_dma_channel *chan);
+
+
+/**
+ * \brief returns the maximum number of bytes per DMA descritpor
+ *
+ * \param chan IOAT DMA channel
+ *
+ * \returns maximum number of bytes
+ */
+uint32_t ioat_dma_channel_get_max_xfer_size(struct ioat_dma_channel *chan);
+
+/*
+ * ----------------------------------------------------------------------------
+ * Request Management
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ *
+ */
+void ioat_dma_channel_request_enqueue(struct ioat_dma_channel *chan,
+                                      struct ioat_dma_request *req);
+
 
 #endif  /* LIB_IOAT_DMA_DEVICE_H */
diff --git a/include/dma/ioat/ioat_dma_descriptors.h b/include/dma/ioat/ioat_dma_descriptors.h
new file mode 100644 (file)
index 0000000..3fcc46f
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * 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_IOAT_DMA_DESCRIPTORS_H
+#define LIB_IOAT_DMA_DESCRIPTORS_H
+
+struct ioat_dma_descriptor;
+struct ioat_dma_request;
+
+/// flags how the descriptors are mapped
+#define IOAT_DMA_DESC_MAP_FLAGS VREGION_FLAGS_READ_WRITE
+
+/// the size of the basic descriptor XXX: does not hold for super extended desc!
+#define IOAT_DMA_DESC_SIZE 64
+
+/// minimum alignment constraint for the descriptors
+#define IOAT_DMA_DESC_ALIGN 64
+
+
+/*
+ * ----------------------------------------------------------------------------
+ * 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 ioat_dma_desc_fill_memcpy(struct ioat_dma_descriptor *desc,
+                               lpaddr_t src,
+                               lpaddr_t dst,
+                               uint32_t size,
+                               ioat_dma_desc_ctrl_t ctrl);
+
+/**
+ * \brief initializes the hardware specific part of the descriptor to be used
+ *        for nop descriptors (null descriptors)
+ *
+ * \param desc  IOAT DMA descriptor
+ */
+void ioat_dma_desc_fill_nop(struct ioat_dma_descriptor *desc);
+
+/*
+ * ----------------------------------------------------------------------------
+ * Getters / Setters
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief returns the corresponding IOAT DMA request this descriptor belongs
+ *
+ * \param desc IOAT DMA descriptor
+ *
+ * \brief pointer to the request
+ *        NULL if there is none
+ */
+struct ioat_dma_request *ioat_dma_desc_get_request(struct ioat_dma_descriptor *desc);
+
+/**
+ * \brief returns a pointer to the next descriptor in the descriptor chain
+ *
+ * \param desc IOAT DMA descriptor
+ *
+ * \returns next descriptor
+ *          NULL if the end of chain
+ */
+struct ioat_dma_descriptor *ioat_dma_desc_get_next(struct ioat_dma_descriptor *desc);
+
+
+#endif  /* LIB_IOAT_DMA_DESCRIPTORS_H */
diff --git a/include/dma/ioat/ioat_dma_device.h b/include/dma/ioat/ioat_dma_device.h
new file mode 100644 (file)
index 0000000..716d298
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * 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_IOAT_DMA_DEVICE_H
+#define LIB_IOAT_DMA_DEVICE_H
+
+/// forward declaration of the device
+struct ioat_dma_device;
+struct ioat_dma_channel;
+
+
+
+/*
+ * ----------------------------------------------------------------------------
+ * device initialization / termination
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief initializes a IOAT 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 ioat_dma_device_init(struct capref mmio,
+                              struct ioat_dma_device **dev);
+
+/**
+ * \brief terminates the device operation and frees up the allocated resources
+ *
+ * \param dev IOAT DMA device to shutdown
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on error
+ */
+errval_t ioat_dma_device_shutdown(struct ioat_dma_device *dev);
+
+/**
+ * \brief requests access to a IOAT DMA device from the IOAT device manager
+ *        and initializes the device.
+ *
+ * \param dev  returns a pointer to the device structure
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on error
+ */
+errval_t ioat_dma_device_acquire(struct ioat_dma_device **dev);
+
+/**
+ * \brief terminates the device operation and frees up the allocated resources
+ *        and releases the device and returns it to the IOAT device manager.
+ *
+ * \param dev IOAT DMA device to be released
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on error
+ */
+errval_t ioat_dma_device_release(struct ioat_dma_device *dev);
+
+
+/*
+ * ----------------------------------------------------------------------------
+ * Interrupt management
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief enables the interrupts for the device
+ *
+ * \param dev   IOAT DMA device
+ * \param type  interrupt type
+ * \param fn    interrupt handler function
+ * \param arg   argument supplied to the handler function
+ */
+errval_t ioat_dma_device_intr_enable(struct ioat_dma_device *dev,
+                                     dma_irq_t type,
+                                     dma_irq_fn_t fn,
+                                     void *arg);
+
+/**
+ * \brief disables the interrupts for the device
+ *
+ * \param dev   IOAT DMA device
+ */
+void ioat_dma_device_intr_disable(struct ioat_dma_device *dev);
+
+/**
+ * \brief sets the interrupt delay for the device
+ *
+ * \param dev   IOAT DMA device
+ * \param usec  interrupt delay in microseconds
+ */
+void ioat_dma_device_set_intr_delay(struct ioat_dma_device *dev,
+                                    uint16_t usec);
+
+/*
+ * ----------------------------------------------------------------------------
+ * Device Operation Functions
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief gets the device state from the IOAT DMA device
+ *
+ * \param dev   IOAT DMA device
+ *
+ * \returns device state enumeration
+ */
+dma_dev_st_t ioat_dma_device_get_state(struct ioat_dma_device *dev);
+
+
+/**
+ * \brief returns the channel count of this device
+ *
+ * \param dev   IOAT DMA device
+ *
+ * \returns number of channels this device has
+ */
+uint8_t ioat_dma_device_get_channel_count(struct ioat_dma_device *dev);
+
+/**
+ * \brief returns the device ID from the IOAT device
+ *
+ * \param dev   IOAT DMA device
+ *
+ * \returns IOAT DMA device ID
+ */
+dma_dev_id_t ioat_dma_device_get_id(struct ioat_dma_device *dev);
+
+/**
+ * \brief returns the channel belonging with the given ID
+ *
+ * \param dev   IOAT DMA device
+ * \param id    channel id
+ *
+ * return IOAT DMA channel handle
+ *        NULL if no such channel exist
+ */
+struct ioat_dma_channel *ioat_dma_device_get_channel(struct ioat_dma_device *dev,
+                                                     uint16_t id);
+
+/**
+ * \brief returns a channel from the device based on a round robin fashion
+ *
+ * \param dev   IOAT DMA device
+ *
+ * return IOAT DMA channel handle
+ */
+struct ioat_dma_channel *ioat_dma_device_get_next_channel(struct ioat_dma_device *dev);
+
+
+/**
+ * \brief polls the channels of the IOAT DMA device
+ *
+ * \param dev   IOAT DMA device
+ *
+ * \returns SYS_ERR_OK on success
+ *          IOAT_ERR_DEVICE_IDLE if there is nothing completed on the channels
+ *          errval on error
+ */
+errval_t ioat_dma_device_poll_channels(struct ioat_dma_device *dev);
+
+
+
+#endif  /* LIB_IOAT_DMA_DEVICE_H */
index b67fae4..67d7098 100644 (file)
 #ifndef LIB_IOAT_DMA_REQUEST_H
 #define LIB_IOAT_DMA_REQUEST_H
 
+struct ioat_dma_channel;
+struct ioat_dma_request;
+
+/*
+ * ----------------------------------------------------------------------------
+ * Request Execution
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief issues a memcpy request to the given channel
+ *
+ * \param chan  IOAT DMA channel
+ * \param setup request setup information
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on failure
+ */
+errval_t ioat_dma_request_memcpy_chan(struct ioat_dma_channel *chan,
+                                      struct dma_req_setup *setup);
+
+/**
+ * \brief issues a memcpy request to a channel of the given device
+ *
+ * \param dev   IOAT DMA device
+ * \param setup request setup information
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on failure
+ */
+static inline errval_t ioat_dma_request_memcpy(struct ioat_dma_device *dev,
+                                               struct dma_req_setup *setup)
+{
+    struct ioat_dma_channel *chan = ioat_dma_device_get_next_channel(dev);
+    return ioat_dma_request_memcpy_chan(chan, setup);
+}
+
+/**
+ * \brief issues a NOP / NULL descriptor request on the given channel
+ *
+ * \param chan  IOAT DMA channel
+ * \param setup request setup information
+ */
+void ioat_dma_request_nop_chan(struct ioat_dma_channel *chan);
+
+/**
+ * \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
+ */
+static inline void ioat_dma_request_nop(struct ioat_dma_device *dev)
+{
+    struct ioat_dma_channel *chan = ioat_dma_device_get_next_channel(dev);
+    ioat_dma_request_nop_chan(chan);
+}
+
+/*
+ * ----------------------------------------------------------------------------
+ * Getters / Setters
+ * ----------------------------------------------------------------------------
+ */
 
 
 
diff --git a/include/dma/ioat/ioat_dma_ring.h b/include/dma/ioat/ioat_dma_ring.h
new file mode 100644 (file)
index 0000000..f751545
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * 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_IOAT_DMA_RING_H
+#define LIB_IOAT_DMA_RING_H
+
+struct ioat_dma_channel;
+struct ioat_dma_descriptor;
+struct ioat_dma_ring;
+
+/// the minimum amount of DMA descriptors to allocate in bits
+#define IOAT_DMA_DESC_RING_SIZE 8
+
+
+/*
+ * ----------------------------------------------------------------------------
+ * Descriptor Ring Allocation / free
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief allocates a descriptor ring
+ *
+ * \param size_bits the size of the ring in bits
+ * \param ret_ring  where the ring pointer is returned
+ *
+ * \returns SYS_ERR_OK on succes
+ *          errval on error
+ */
+errval_t ioat_dma_ring_alloc(uint8_t size_bits,
+                             struct ioat_dma_ring **ret_ring,
+                             struct ioat_dma_channel *chan);
+
+/**
+ * \brief frees a previously allocated descriptor ring
+ *
+ * \param ring IAT DMA descriptor ring to be freed
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on failure
+ */
+errval_t ioat_dma_ring_free(struct ioat_dma_ring *ring);
+
+/*
+ * ----------------------------------------------------------------------------
+ * Getter Functions
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief returns the size of the ring
+ *
+ * \param ring  IOAT DMA descriptor ring
+ *
+ * \returns number of descriptors in the ring
+ */
+uint16_t ioat_dma_ring_get_size(struct ioat_dma_ring *ring);
+
+/**
+ * \brief returns the head pointer index of the ring
+ *
+ * \param ring  IOAT DMA descriptor ring
+ *
+ * \returns head element index
+ */
+uint16_t ioat_dma_ring_get_head(struct ioat_dma_ring *ring);
+
+/**
+ * \brief returns the tail pointer index of the ring
+ *
+ * \param ring  IOAT DMA descriptor ring
+ *
+ * \returns tail element index
+ */
+uint16_t ioat_dma_ring_get_tail(struct ioat_dma_ring *ring);
+
+/**
+ * \brief returns the issued pointer index of the ring
+ *
+ * \param ring  IOAT DMA descriptor ring
+ *
+ * \returns issued element index
+ */
+uint16_t ioat_dma_ring_get_issued(struct ioat_dma_ring *ring);
+
+/**
+ * \brief gets the next descriptor based on the index
+ *
+ * \param ring  the DMA ring
+ * \param index the index of the ring
+ *
+ * \returns pointer to a DMA descriptor
+ */
+struct ioat_dma_descriptor *ioat_dma_ring_get_desc(struct ioat_dma_ring *ring,
+                                                   uint16_t index);
+
+/*
+ * ----------------------------------------------------------------------------
+ * Ring Status Queries
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief returns the number of active descriptors i.e. those who have not yet
+ *        been finished by the DMA hardware. this includes submitted and pending
+ *        DMA descriptors
+ *
+ * \param ring  IOAT DMA descriptor ring
+ *
+ * \returns number of active descriptors
+ */
+uint16_t ioat_dma_ring_get_active(struct ioat_dma_ring *ring);
+
+
+/**
+ * \brief returns the number of prepared but not submitted descriptors
+ *
+ * \param ring  IOAT DMA descriptor ring
+ *
+ * \returns number of pending descriptors
+ */
+uint16_t ioat_dma_ring_get_pendig(struct ioat_dma_ring *ring);
+
+
+/**
+ * \brief calculates the free space of the ring
+ *
+ * \param ring  IOAT DMA descriptor ring
+ *
+ * \returns number of free descriptors
+ */
+static inline uint16_t ioat_dma_ring_get_space(struct ioat_dma_ring *ring)
+{
+    return ioat_dma_ring_get_size(ring) - ioat_dma_ring_get_active(ring);
+}
+
+
+
+#endif  /* LIB_IOAT_DMA_RING_H */
index c807483..636120b 100644 (file)
 --------------------------------------------------------------------------
 
 [ build library { 
-       target = "dma",
+    target = "dma",
     cFiles = [
-        "dma_memory_manager.c",
-        "dma_service.c"
+      "dma_memory_manager.c",
+      "dma_mem_utils.c",
+      "dma_client.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"
     ],
-       flounderBindings = [ "dma" ]
+    addIncludes = [ "include" ],
+    flounderBindings = [ "dma" ],
+    mackerelDevices = [ "ioat_dma", "ioat_dma_chan" ]
   },
   
   build library { 
-       target = "dma_client",
-       cFiles = [ 
-               "dma_client.c" 
-       ],
-       flounderBindings = [ "dma" ]
+    target = "dma_client",
+    cFiles = [ 
+      "dma_client.c" 
+    ],
+    addIncludes = [ "include" ],
+    flounderBindings = [ "dma" ]
   }
 ]
diff --git a/lib/dma/dma_channel.c b/lib/dma/dma_channel.c
new file mode 100644 (file)
index 0000000..1cff791
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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>
diff --git a/lib/dma/dma_device.c b/lib/dma/dma_device.c
new file mode 100644 (file)
index 0000000..1cff791
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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>
index 5081885..d9518e1 100644 (file)
@@ -7,6 +7,8 @@
  * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
  */
 
+#include <string.h>
+
 #include <barrelfish/barrelfish.h>
 
 #include <dma_mem_utils.h>
@@ -23,7 +25,7 @@
  */
 errval_t dma_mem_alloc(size_t bytes,
                        vregion_flags_t flags,
-                       struct ioat_dma_mem *mem)
+                       struct dma_mem *mem)
 {
     errval_t err;
 
@@ -39,7 +41,7 @@ errval_t dma_mem_alloc(size_t bytes,
     struct frame_identity id;
     err = invoke_frame_identify(mem->frame, &id);
     if (err_is_fail(err)) {
-        ioat_dma_mem_free(mem);
+        dma_mem_free(mem);
         return err;
     }
 
@@ -48,7 +50,7 @@ errval_t dma_mem_alloc(size_t bytes,
     err = vspace_map_one_frame_attr(&mem->addr, mem->bytes, mem->frame, flags, NULL,
                                     NULL);
     if (err_is_fail(err)) {
-        ioat_dma_mem_free(mem);
+        dma_mem_free(mem);
         return err;
     }
 
@@ -61,7 +63,7 @@ errval_t dma_mem_alloc(size_t bytes,
  * \returns SYS_ERR_OK on success
  *          errval on error
  */
-errval_t dma_mem_free(struct ioat_dma_mem *mem)
+errval_t dma_mem_free(struct dma_mem *mem)
 {
     errval_t err;
 
diff --git a/lib/dma/dma_request.c b/lib/dma/dma_request.c
new file mode 100644 (file)
index 0000000..1cff791
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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>
diff --git a/lib/dma/include/dma_channel_internal.h b/lib/dma/include/dma_channel_internal.h
new file mode 100644 (file)
index 0000000..e73cea9
--- /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 DMA_REQUEST_INTERNAL_H
+#define DMA_REQUEST_INTERNAL_H
+
+#include <dma/dma_request.h>
+
+struct dma_req_int
+{
+    struct dma_request req;
+
+};
+
+
+
+#endif /* DMA_REQUEST_INTERNAL_H */
diff --git a/lib/dma/include/dma_device_internal.h b/lib/dma/include/dma_device_internal.h
new file mode 100644 (file)
index 0000000..6b511d1
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * 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 DMA_DEVICE_INTERNAL_H
+#define DMA_DEVICE_INTERNAL_H
+
+#include <dma/dma_device.h>
+
+struct dma_dev_int
+{
+    dma_dev_id_t id;                ///< device id
+    dma_dev_st_t state;             ///< device state
+    struct {
+        void *vbase;                ///< virtual base of the mapped region
+        lpaddr_t pbase;             ///< physical base of the region
+        uint64_t bytes;             ///< size of the region in bytes
+        struct capref cap;          ///< devframe capability
+    } mmio;                         ///< MMIO register mappings
+
+    struct {
+        struct dma_channel **c;     ///< DMA channel pointers
+        uint8_t num;                ///< Number of channels of this device
+        uint8_t next;               ///< Next channel to allocate for requests
+    } channels;                     ///< Channel information
+    dma_irq_t irq_type;        ///< DMA interrupt type
+};
+
+#endif /* DMA_DEVICE_INTERNAL_H */
diff --git a/lib/dma/include/dma_request_internal.h b/lib/dma/include/dma_request_internal.h
new file mode 100644 (file)
index 0000000..e73cea9
--- /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 DMA_REQUEST_INTERNAL_H
+#define DMA_REQUEST_INTERNAL_H
+
+#include <dma/dma_request.h>
+
+struct dma_req_int
+{
+    struct dma_request req;
+
+};
+
+
+
+#endif /* DMA_REQUEST_INTERNAL_H */
index 0d84040..dd3f7db 100644 (file)
 #ifndef IOAT_DMA_CHANNEL_INTERNAL_H
 #define IOAT_DMA_CHANNEL_INTERNAL_H
 
+#include <dma_channel_internal.h>
 #include <dma/ioat/ioat_dma_channel.h>
 
 
+
 /**
  * \brief initializes and allocates resources for a new channel DMA channel
  *        belonging to a device
index 3d77577..e04c221 100644 (file)
@@ -1,5 +1,4 @@
 /*
-/*
  * Copyright (c) 2014 ETH Zurich.
  * All rights reserved.
  *
index 0e7cb55..d0d09cf 100644 (file)
 #ifndef IOAT_DMA_REQUEST_INTERNAL_H
 #define IOAT_DMA_REQUEST_INTERNAL_H
 
+#include <dma/ioat/ioat_dma_descriptors.h>
 
-void ioat_desc_foobar(void);
+/*
+ * ----------------------------------------------------------------------------
+ * Allocation / Deallocation
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief allocates a number of hardware DMA descriptors and fills them into the
+ *        array of descriptor pointers
+ *
+ * \param size  descriptor size
+ * \param align alignment constraints of the descriptors
+ * \param count number of descriptors to allocate
+ * \param desc  pointer to the array of descriptor pointers
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on error
+ */
+errval_t ioat_desc_alloc(uint16_t size,
+                         uint16_t align,
+                         uint16_t count,
+                         struct ioat_dma_descriptor **desc);
+
+/**
+ * \brief brief frees up the array of previously allocated descriptors
+ *        and releases the resources
+ *
+ * \param desc  the descriptors to be freed
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on failure
+ */
+errval_t ioat_desc_free(struct ioat_dma_descriptor *desc);
+
+/*
+ * ----------------------------------------------------------------------------
+ * Descriptor getters / setters
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief returns a virtual address pointer to the location where the descriptor
+ *        is mapped
+ *
+ * \param desc IOAT DMA descriptor
+ */
+ioat_dma_desc_t ioat_desc_get_desc(struct ioat_dma_descriptor *desc);
+
+/**
+ * \brief sets the corresponding request
+ *
+ * \param desc IOAT DMA descriptor
+ */
+void ioat_desc_set_request(struct ioat_dma_descriptor *desc,
+                               struct ioat_dma_request *req);
+
+/**
+ * \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
+ */
+void ioat_desc_set_next(struct ioat_dma_descriptor *desc,
+                        struct ioat_dma_descriptor *next);
+
+/**
+ * \brief returns the physical address of the descriptor
+ *
+ * \param desc IOAT DMA descriptor
+ *
+ * \returns physical address of the descriptor
+ */
+lpaddr_t ioat_desc_get_paddr(struct ioat_dma_descriptor *desc);
 
 #endif /* IOAT_DMA_REQUEST_INTERNAL_H */
index 6cb569e..b136a0b 100644 (file)
 #ifndef IOAT_DMA_DEVICE_INTERNAL_H
 #define IOAT_DMA_DEVICE_INTERNAL_H
 
-#include <dma/ioat/ioat_dma_device.h>
-#include <dev/ioat_dma_dev.h>
-
-/**
- * IOAT DMA device representation
- */
-struct ioat_dma_device
-{
-    ioat_dma_devid_t id;                ///< device ID
-    ioat_dma_t device;                  ///< mackerel device base
-    ioat_dma_cbver_t version;           ///< Crystal Beach version number
-    enum ioat_dma_dev_st state;         ///< device state
+#include <dma_mem_utils.h>
 
-    struct {
-        void    *vbase;                 ///< virtual base of the mapped region
-        lpaddr_t pbase;                 ///< physical base of the region
-        uint64_t bytes;                 ///< size of the region in bytes
-        struct capref cap;              ///< devframe capability
-    } mmio;                             ///< MMIO register mappings
+#include <dma_device_internal.h>
 
-    struct {
-        struct ioat_dma_channel **c;    ///< DMA channel pointers
-        uint8_t num;                    ///< Number of channels of this device
-        uint8_t next;                   ///< Next channel to allocate for requests
-    } channels;                         ///< Channel information
+#include <dma/ioat/ioat_dma_device.h>
+#include <dev/ioat_dma_dev.h>
 
-    struct dma_mem complstatus;         ///< memory region for channels CHANSTS
 
-    uint32_t flags;
-    struct ioat_dma_ctrl *dma_ctrl;
-    enum ioat_dma_irq irq_type;
-};
 
 
 /* device flags */
index 627258f..6c9a38e 100644 (file)
@@ -1,5 +1,4 @@
 /*
-/*
  * Copyright (c) 2014 ETH Zurich.
  * All rights reserved.
  *
index 491335f..12c4c3c 100644 (file)
@@ -7,10 +7,58 @@
  * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
  */
 
-#ifndef IOAT_DMA_REQUEST_INTERNAL_H
-#define IOAT_DMA_REQUEST_INTERNAL_H
+#ifndef IOAT_DMA_RING_INTERNAL_H
+#define IOAT_DMA_RING_INTERNAL_H
 
+#include <dma/ioat/ioat_dma_ring.h>
 
-void ioat_ring_foobar(void);
+/// maximum ring size in bits
+#define IOAT_DESC_RING_SIZE_MAX 16
 
-#endif /* IOAT_DMA_REQUEST_INTERNAL_H */
+/*
+ * ----------------------------------------------------------------------------
+ * Ring Manipulation
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief gets the next descriptor based on the head pointer and increments the
+ *        head pointer
+ *
+ * \param ring the DMA ring
+ *
+ * \returns pointer to a DMA descriptor
+ */
+struct ioat_dma_descriptor *ioat_ring_get_next_desc(struct ioat_dma_ring *ring);
+
+
+/**
+ * \brief gets the next descriptor based on the tail pointer and increases the
+ *        tail pointer index
+ *
+ * \param ring the DMA ring
+ *
+ * \returns pointer to a DMA descriptor
+ */
+struct ioat_dma_descriptor *ioat_ring_get_tail_desc(struct ioat_dma_ring *ring);
+
+/**
+ * \brief submits the pending descriptors to the hardware
+ *
+ * \param ring DMA ring to submit the pending descriptors
+ *
+ * \returns the current head of the descriptors
+ */
+uint16_t ioat_ring_submit_pending(struct ioat_dma_ring *ring);
+
+/**
+ * \brief obtains the physical address of the descriptor chain
+ *        (pending descriptors)
+ *
+ * \param ring the DMA ring
+ *
+ * \returns physical address of the pending descriptor chain
+ */
+lpaddr_t ioat_ring_get_chain_addr(struct ioat_dma_ring *ring);
+
+#endif /* IOAT_DMA_RING_INTERNAL_H */
index 0c185bd..8d8668b 100644 (file)
@@ -9,6 +9,7 @@
 #include <barrelfish/barrelfish.h>
 
 #include <ioat/ioat_dma_internal.h>
+#include <ioat/ioat_dma_dca_internal.h>
 
 
 /*
index ee0439d..b60179f 100644 (file)
@@ -26,7 +26,7 @@ struct ioat_dma_channel
     ioat_dma_chan_t channel;         ///< Mackerel address
     struct ioat_dma_device *dev;     ///< the DMA device this channel belongs to
     size_t max_xfer_size;            ///< maximum transfer size of this channel
-    enum ioat_dma_chan_st state;     ///< channel state
+    ioat_dma_chan_st_t state;        ///< channel state
     lpaddr_t last_completion;        ///<
     struct dma_mem completion;
     struct ioat_dma_ring *ring;      ///< Descriptor ring
@@ -37,6 +37,109 @@ struct ioat_dma_channel
     struct ioat_dma_request *req_tail;
 };
 
+/*
+ * ============================================================================
+ * Public Internal Interface
+ * ============================================================================
+ */
+
+/**
+ * \brief Resets a IOAT DMA channel
+ *
+ * \param chan  IOAT DMA channel to be reset
+ *
+ * \returns SYS_ERR_OK on success
+ *          IOAT_ERR_CHAN_RESET on reset timeout
+ */
+errval_t ioat_dma_channel_reset(struct ioat_dma_channel *chan)
+{
+    IOATCHAN_DEBUG("reset channel.\n", chan->id);
+
+    if (chan->state == IOAT_DMA_CHAN_ST_ERROR) {
+        ioat_dma_chan_err_t chanerr = ioat_dma_chan_err_rd(&chan->channel);
+        ioat_dma_chan_err_wr(&chan->channel, chanerr);
+        IOATCHAN_DEBUG("Reseting channel from error state: [%08x]\n", chan->id,
+                       chanerr);
+
+        /*
+         * TODO: clear the ioat_dma_pci_chanerr register in PCI config space
+         *       (same approach as above)
+         *       -> How to access this ?
+         */
+    }
+    chan->state = IOAT_DMA_CHAN_ST_RESETTING;
+
+    /* perform reset */
+    ioat_dma_chan_cmd_reset_wrf(&chan->channel, 0x1);
+
+    uint16_t reset_counter = 0xFFF;
+    do {
+        if (!ioat_dma_chan_cmd_reset_rdf(&chan->channel)) {
+            break;
+        }
+        thread_yield();
+    } while(reset_counter--);
+
+    if (ioat_dma_chan_cmd_reset_rdf(&chan->channel)) {
+        /* reset failed */
+        return IOAT_ERR_RESET_TIMEOUT;
+    }
+
+    /* XXX: Intel BD architecture will need some additional work here */
+
+    chan->state = IOAT_DMA_CHAN_ST_UNINITIALEZED;
+
+    return SYS_ERR_OK;
+}
+
+/*
+ * ----------------------------------------------------------------------------
+ * Getter / Setter Functions
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief returns the IOAT DMA channel ID
+ *
+ * \param chan  IOAT DMA channel
+ *
+ * \returns IOAT DMA channel ID of the supplied channel
+ */
+inline ioat_dma_chan_id_t ioat_dma_channel_get_id(struct ioat_dma_channel *chan)
+{
+    return chan->id;
+}
+
+/**
+ * \brief returns the associated IOAT DMA descriptor ring of a channel
+ *
+ * \param chan  IOAT DMA channel
+ *
+ * \returns IOAT DMA descriptor ring handle
+ */
+inline struct ioat_dma_ring *ioat_dma_channel_get_ring(struct ioat_dma_channel *chan)
+{
+    return chan->ring;
+}
+
+/**
+ * \brief returns the maximum number of bytes per DMA descritpor
+ *
+ * \param chan IOAT DMA channel
+ *
+ * \returns maximum number of bytes
+ */
+inline uint32_t ioat_dma_channel_get_max_xfer_size(struct ioat_dma_channel *chan)
+{
+    return chan->max_xfer_size;
+}
+
+/*
+ * ============================================================================
+ * Library Internal Interface
+ * ============================================================================
+ */
+
 /**
  * \brief initializes and allocates resources for a new channel DMA channel
  *        belonging to a device
@@ -53,18 +156,17 @@ errval_t ioat_channel_init(struct ioat_dma_device *dev,
                            uint32_t max_xfer,
                            struct ioat_dma_channel **ret_chan)
 {
-#if 0
+
     errval_t err;
 
     IOATCHAN_DEBUG("initialize channel with  max. xfer size of %u bytes\n", id,
                    max_xfer);
 
-    struct ioat_dma_channel *chan = malloc(sizeof(*chan));
+    struct ioat_dma_channel *chan = calloc(1, sizeof(*chan));
     if (chan == NULL) {
         return LIB_ERR_MALLOC_FAIL;
     }
 
-
     chan->id = ioat_dma_channel_build_id(ioat_dma_device_get_id(dev), id);
     chan->dev = dev;
     chan->max_xfer_size = max_xfer;
@@ -73,7 +175,7 @@ errval_t ioat_channel_init(struct ioat_dma_device *dev,
     ioat_dma_chan_initialize(&chan->channel, chan_base + ((id + 1) * 0x80));
 
     ioat_dma_chan_dcactrl_target_cpu_wrf(&chan->channel,
-                                         ioat_dma_chan_dca_ctr_target_any);
+    ioat_dma_chan_dca_ctr_target_any);
 
     err = ioat_dma_channel_reset(chan);
     if (err_is_fail(err)) {
@@ -82,7 +184,6 @@ errval_t ioat_channel_init(struct ioat_dma_device *dev,
 
     ioat_device_get_complsts_addr(dev, &chan->completion);
 
-
     /* write the completion address */
     ioat_dma_chan_cmpl_lo_wr(&chan->channel, chan->completion.paddr);
     ioat_dma_chan_cmpl_hi_wr(&chan->channel, chan->completion.paddr >> 32);
@@ -105,7 +206,7 @@ errval_t ioat_channel_init(struct ioat_dma_device *dev,
     /*
      * do a check if the channel operates correctly by issuing a NOP
      */
-
+#if 0
     IOATCHAN_DEBUG("performing selftest on channel with NOP\n", chan->id);
 
     ioat_dma_request_nop(chan);
@@ -115,16 +216,15 @@ errval_t ioat_channel_init(struct ioat_dma_device *dev,
         return err;
     }
 
-
     uint32_t j = 0xFFFF;
     do {
         thread_yield();
-    } while (j-- && !ioat_dma_channel_is_active(chan)
-             && !ioat_dma_channel_is_idle(chan));
+    }while (j-- && !ioat_dma_channel_is_active(chan)
+                    && !ioat_dma_channel_is_idle(chan));
 
     if (ioat_dma_channel_is_active(chan) || ioat_dma_channel_is_idle(chan)) {
         IOATCHAN_DEBUG("channel worked properly: %016lx\n", chan->id,
-                     *(uint64_t*) chan->completion.addr);
+                        *(uint64_t*) chan->completion.addr);
         return SYS_ERR_OK;
     } else {
         uint32_t error = ioat_dma_chan_err_rd(&chan->channel);
index 11c56eb..d448f3c 100644 (file)
@@ -11,6 +11,8 @@
 #include <ioat/ioat_dma_internal.h>
 #include <ioat/ioat_dma_dca_internal.h>
 
+#include <debug.h>
+
 /*
  * ===========================================================================
  * Library Internal Interface
index a1e5555..57b5fb0 100644 (file)
@@ -6,3 +6,293 @@
  * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
  */
 
+#include <string.h>
+#include <barrelfish/barrelfish.h>
+
+#include <dev/ioat_dma_dev.h>
+
+#include <dma_mem_utils.h>
+
+#include <ioat/ioat_dma_internal.h>
+#include <ioat/ioat_dma_descriptors_internal.h>
+
+#include <debug.h>
+
+/* helper makros */
+#define ALIGN(val, align) (((val) + (align)-1) & ~((align)-1))
+#define IS_POW2(num) (((num) != 0) && (((num) & (~(num) + 1)) == (num)))
+
+/* IOAT DMA Descriptor flags */
+
+/// this descriptor is valid
+#define IOAT_DMA_DESC_FLAG_VALID     0x01
+
+/// this descriptor is currently used in a request
+#define IOAT_DMA_DESC_FLAG_USED      0x02
+
+/// this is the first descriptor of a request
+#define IOAT_DMA_DESC_FLAG_FIRST     0x04
+
+/// this is the last descriptor in a request
+#define IOAT_DMA_DESC_FLAG_LAST      0x08
+
+/// the descriptor has not been processed yet
+#define IOAT_DMA_DESC_FLAG_PROGRESS  0x10
+
+/// this descriptor is the head of the allocation unit (only this can be freed)
+#define IOAT_DMA_DESC_FLAG_HEAD      0x20
+
+/// the descriptor has been executed
+#define IOAT_DMA_DESC_FLAG_DONE      0x40
+
+/// there was an error during the execution of this descriptor
+#define IOAT_DMA_DESC_FLAG_ERR       0x80
+
+/**
+ * IOAT DMA Descriptor Meta structure. This wrapps around the hardware descriptor
+ * and is used to keep track of the descriptors.
+ */
+struct ioat_dma_descriptor
+{
+    lpaddr_t paddr;                     ///< physical address of the descriptor
+    ioat_dma_desc_t desc;               ///< virtual address of the descriptor
+    uint32_t flags;                     ///< descriptor flags
+    struct ioat_dma_descriptor *next;   ///< next descriptor in the list
+    struct ioat_dma_request *req;       ///< pointer to the DMA request
+    struct dma_mem *mem;                ///< the dma memory information
+};
+
+
+/*
+ * ============================================================================
+ * Library Internal Interface
+ * ============================================================================
+ */
+
+/**
+ * \brief allocates a number of hardware DMA descriptors and fills them into the
+ *        array of descriptor pointers
+ *
+ * \param size  descriptor size
+ * \param align alignment constraints of the descriptors
+ * \param count number of descriptors to allocate
+ * \param desc  pointer to the array of descriptor pointers
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on error
+ */
+errval_t ioat_desc_alloc(uint16_t size,
+                         uint16_t align,
+                         uint16_t count,
+                         struct ioat_dma_descriptor **desc)
+{
+    errval_t err;
+
+    assert(desc);
+    assert(IS_POW2(count));
+    assert((align & (IOAT_DMA_DESC_ALIGN -1)) == 0);
+
+    struct ioat_dma_descriptor *dma_desc = calloc(count, sizeof(*dma_desc));
+    if (dma_desc == NULL) {
+        return LIB_ERR_MALLOC_FAIL;
+    }
+
+    size = ALIGN(size, align);
+
+    struct dma_mem *mem = malloc(sizeof(*mem));
+    err = dma_mem_alloc(count * size, IOAT_DMA_DESC_MAP_FLAGS, mem);
+    if (err_is_fail(err)) {
+        free(dma_desc);
+        return err;
+    }
+
+    memset(mem->addr, 0, count * size);
+
+    IOATDESC_DEBUG("Allocated frame of size %lu bytes @ [%016lx]\n",
+                 (uint64_t ) mem->bytes, mem->paddr);
+
+    lpaddr_t desc_paddr = mem->paddr;
+    uint8_t *desc_vaddr = mem->addr;
+
+    /* set the last virtual address pointer */
+    dma_desc[count-1].desc = desc_vaddr + ((count-1)*size);
+
+    for (uint32_t i = 0; i < count; ++i) {
+
+        if (i == (count -1)) {
+            assert(dma_desc[i].desc == desc_vaddr);
+        }
+
+        /* initialize the fields */
+        dma_desc[i].desc = desc_vaddr;
+        dma_desc[i].paddr = desc_paddr;
+        dma_desc[i].req = NULL;
+        dma_desc[i].flags = IOAT_DMA_DESC_FLAG_VALID;
+        dma_desc[i].mem = mem;
+
+        /* do the linkage */
+        ioat_desc_set_next(&dma_desc[(i-1) & (count - 1)], &dma_desc[i]);
+
+        /* set the entry in the array */
+        desc[i] = &dma_desc[i];
+
+        desc_vaddr += size;
+        desc_paddr += size;
+    }
+
+    IOATDESC_DEBUG("Allocated %u desc of size %u\n", count, size);
+
+    return SYS_ERR_OK;
+}
+
+
+/**
+ * \brief brief frees up the array of previously allocated descriptors
+ *        and releases the resources
+ *
+ * \param desc  the descriptors to be freed
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on failure
+ */
+errval_t ioat_desc_free(struct ioat_dma_descriptor *desc)
+{
+    assert(!"NYI");
+    return SYS_ERR_OK;
+}
+
+/*
+ * ----------------------------------------------------------------------------
+ * Descriptor getters / setters
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief returns the physical address of the descriptor
+ *
+ * \param desc IOAT DMA descriptor
+ *
+ * \returns physical address of the descriptor
+ */
+inline lpaddr_t ioat_desc_get_paddr(struct ioat_dma_descriptor *desc)
+{
+    return desc->paddr;
+}
+
+/**
+ * \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 ioat_desc_set_next(struct ioat_dma_descriptor *desc,
+                               struct ioat_dma_descriptor *next)
+{
+    ioat_dma_desc_next_insert(desc->desc, next->paddr);
+    desc->next = next;
+}
+
+/**
+ * \brief sets the corresponding request
+ *
+ * \param desc IOAT DMA descriptor
+ */
+inline void ioat_desc_set_request(struct ioat_dma_descriptor *desc,
+                                  struct ioat_dma_request *req)
+{
+    desc->req = req;
+}
+
+/**
+ * \brief returns a virtual address pointer to the location where the descriptor
+ *        is mapped
+ *
+ * \param desc IOAT DMA descriptor
+ */
+inline ioat_dma_desc_t ioat_desc_get_desc(struct ioat_dma_descriptor *desc)
+{
+    return desc->desc;
+}
+
+/*
+ * ============================================================================
+ * Public Interface
+ * ============================================================================
+ */
+
+/**
+ * \brief initializes the hardware specific part of the descriptor
+ *
+ * \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
+ */
+inline void ioat_dma_desc_fill_memcpy(struct ioat_dma_descriptor *desc,
+                                      lpaddr_t src,
+                                      lpaddr_t dst,
+                                      uint32_t size,
+                                      ioat_dma_desc_ctrl_t ctrl)
+{
+    ioat_dma_desc_size_insert(desc->desc, size);
+    ioat_dma_desc_ctrl_insert(desc->desc, *((uint32_t *) ctrl));
+    ioat_dma_desc_src_insert(desc->desc, src);
+    ioat_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  IOAT DMA descriptor
+ */
+inline void ioat_dma_desc_fill_nop(struct ioat_dma_descriptor *desc)
+{
+    uint32_t ctrl = 0;
+    ioat_dma_desc_ctrl_t dma_ctrl = (ioat_dma_desc_ctrl_t)(&ctrl);
+    ioat_dma_desc_ctrl_int_en_insert(dma_ctrl, 0x1);
+    ioat_dma_desc_ctrl_null_insert(dma_ctrl, 0x1);
+    ioat_dma_desc_ctrl_compl_write_insert(dma_ctrl, 0x1);
+
+    ioat_dma_desc_size_insert(desc->desc, 1);   // size must be non zero
+    ioat_dma_desc_ctrl_insert(desc->desc, ctrl);
+    ioat_dma_desc_src_insert(desc->desc, 0);
+    ioat_dma_desc_dst_insert(desc->desc, 0);
+}
+
+/*
+ * ----------------------------------------------------------------------------
+ * Descriptor getters / setters
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief returns the corresponding IOAT DMA request this descriptor belongs
+ *
+ * \param desc IOAT DMA descriptor
+ *
+ * \brief pointer to the request
+ *        NULL if there is none
+ */
+inline struct ioat_dma_request *ioat_dma_desc_get_request(struct ioat_dma_descriptor *desc)
+{
+    return desc->req;
+}
+
+/**
+ * \brief returns a pointer to the next descriptor in a chain
+ *
+ * \param desc IOAT DMA descriptor
+ *
+ * \returns next descriptor
+ *          NULL if the end of chain
+ */
+struct ioat_dma_descriptor *ioat_dma_desc_get_next(struct ioat_dma_descriptor *desc)
+{
+    return desc->next;
+}
index c96885a..e582aac 100644 (file)
 #include <dma_mem_utils.h>
 
 #include <ioat/ioat_dma_internal.h>
+#include <ioat/ioat_dma_dca_internal.h>
 #include <ioat/ioat_dma_device_internal.h>
 #include <ioat/ioat_dma_channel_internal.h>
 
 #include <debug.h>
 
+/**
+ * IOAT DMA device representation
+ */
+struct ioat_dma_device
+{
+    struct dma_dev_int common;
+
+    ioat_dma_t device;                  ///< mackerel device base
+    ioat_dma_cbver_t version;           ///< Crystal Beach version number
+
+    struct dma_mem complstatus;         ///< memory region for channels CHANSTS
+
+    uint32_t flags;
+};
+
 /// counter for device ID enumeration
-static ioat_dma_devid_t device_id = 1;
+static dma_dev_id_t device_id = 1;
 
 /*
  * ----------------------------------------------------------------------------
@@ -30,14 +46,14 @@ static ioat_dma_devid_t device_id = 1;
 static errval_t device_init_ioat_v1(struct ioat_dma_device *dev)
 {
     IOATDEV_DEBUG("devices of Crystal Beach Version 1.xx are currently not supported.\n",
-                  dev->id);
+                  dev->common.id);
     return IOAT_ERR_DEVICE_UNSUPPORTED;
 }
 
 static errval_t device_init_ioat_v2(struct ioat_dma_device *dev)
 {
     IOATDEV_DEBUG("devices of Crystal Beach Version 2.xx are currently not supported.\n",
-                  dev->id);
+                  dev->common.id);
     return IOAT_ERR_DEVICE_UNSUPPORTED;
 }
 
@@ -45,30 +61,30 @@ static errval_t device_init_ioat_v3(struct ioat_dma_device *dev)
 {
     errval_t err;
 
-    IOATDEV_DEBUG("initialize Crystal Beach 3 DMA device\n", dev->id);
+    IOATDEV_DEBUG("initialize Crystal Beach 3 DMA device\n", dev->common.id);
 
     ioat_dma_dmacapability_t cap = ioat_dma_dmacapability_rd(&dev->device);
 
     if (ioat_dma_cbver_minor_extract(dev->version) == 2) {
         IOATDEV_DEBUG("disabling XOR and PQ opcodes for Crystal Beach 3.2\n",
-                      dev->id);
+                      dev->common.id);
         cap = ioat_dma_dmacapability_xor_insert(cap, 0x0);
         cap = ioat_dma_dmacapability_pq_insert(cap, 0x0);
     } else if (ioat_dma_cbver_minor_extract(dev->version) == 3) {
         IOATDEV_DEBUG("devices of Crystal Beach Version 3.3 are not supported.\n",
-                      dev->id);
+                      dev->common.id);
         return IOAT_ERR_DEVICE_UNSUPPORTED;
     }
 
     /* if DCA is enabled, we cannot support the RAID functions */
     if (ioat_dma_dca_is_enabled()) {
-        IOATDEV_DEBUG("Disabling XOR and PQ while DCA is enabled\n", dev->id);
+        IOATDEV_DEBUG("Disabling XOR and PQ while DCA is enabled\n", dev->common.id);
         cap = ioat_dma_dmacapability_xor_insert(cap, 0x0);
         cap = ioat_dma_dmacapability_pq_insert(cap, 0x0);
     }
 
     if (ioat_dma_dmacapability_xor_extract(cap)) {
-        IOATDEV_DEBUG("device supports XOR RAID.\n", dev->id);
+        IOATDEV_DEBUG("device supports XOR RAID.\n", dev->common.id);
 
         dev->flags |= IOAT_DMA_DEV_F_RAID;
 
@@ -82,7 +98,7 @@ static errval_t device_init_ioat_v3(struct ioat_dma_device *dev)
     }
 
     if (ioat_dma_dmacapability_pq_extract(cap)) {
-        IOATDEV_DEBUG("device supports PQ RAID.\n", dev->id);
+        IOATDEV_DEBUG("device supports PQ RAID.\n", dev->common.id);
 
         dev->flags |= IOAT_DMA_DEV_F_RAID;
 
@@ -110,21 +126,21 @@ static errval_t device_init_ioat_v3(struct ioat_dma_device *dev)
         return err;
     }
 
-    dev->channels.num = ioat_dma_chancnt_num_rdf(&dev->device);
+    dev->common.channels.num = ioat_dma_chancnt_num_rdf(&dev->device);
 
-    dev->channels.c = calloc(dev->channels.num, sizeof(*dev->channels.c));
-    if (dev->channels.c == NULL) {
+    dev->common.channels.c = calloc(dev->common.channels.num, sizeof(*dev->common.channels.c));
+    if (dev->common.channels.c == NULL) {
         dma_mem_free(&dev->complstatus);
         return LIB_ERR_MALLOC_FAIL;
     }
 
     /* channel enumeration */
 
-    IOATDEV_DEBUG("channel enumeration. discovered %u channels\n", dev->id, dev->channels.num);
+    IOATDEV_DEBUG("channel enumeration. discovered %u channels\n", dev->common.id, dev->common.channels.num);
 
     uint32_t max_xfer_size = (1 << ioat_dma_xfercap_max_rdf(&dev->device));
-    for (uint8_t i = 0; i < dev->channels.num; ++i) {
-        err = ioat_channel_init(dev, i, max_xfer_size, &dev->channels.c[i]);
+    for (uint8_t i = 0; i < dev->common.channels.num; ++i) {
+        err = ioat_channel_init(dev, i, max_xfer_size, &dev->common.channels.c[i]);
     }
 
 
@@ -145,7 +161,7 @@ static errval_t device_init_ioat_v3(struct ioat_dma_device *dev)
 void ioat_device_get_complsts_addr(struct ioat_dma_device *dev,
                                        struct dma_mem *mem)
 {
-    if (dev->state != IOAT_DMA_DEV_ST_CHAN_ENUM) {
+    if (dev->common.state != IOAT_DMA_DEV_ST_CHAN_ENUM) {
         memset(mem, 0, sizeof(*mem));
     }
 
@@ -153,8 +169,8 @@ void ioat_device_get_complsts_addr(struct ioat_dma_device *dev,
 
     *mem = dev->complstatus;
     mem->bytes = IOAT_DMA_COMPLSTATUS_SIZE;
-    mem->paddr += (IOAT_DMA_COMPLSTATUS_SIZE * dev->channels.next);
-    mem->addr += (IOAT_DMA_COMPLSTATUS_SIZE * dev->channels.next++);
+    mem->paddr += (IOAT_DMA_COMPLSTATUS_SIZE * dev->common.channels.next);
+    mem->addr += (IOAT_DMA_COMPLSTATUS_SIZE * dev->common.channels.next++);
     mem->frame = NULL_CAP;
 }
 
@@ -190,6 +206,8 @@ errval_t ioat_dma_device_init(struct capref mmio,
         return LIB_ERR_MALLOC_FAIL;
     }
 
+    struct dma_device_int *dma_dev = &ioat_device->common;
+
     struct frame_identity mmio_id;
     err = invoke_frame_identify(mmio, &mmio_id);
     if (err_is_fail(err)) {
@@ -197,16 +215,16 @@ errval_t ioat_dma_device_init(struct capref mmio,
         return err;
     }
 
-    ioat_device->id = device_id++;
-    ioat_device->mmio.pbase = mmio_id.base;
-    ioat_device->mmio.bytes = (1UL << mmio_id.bits);
-    ioat_device->mmio.cap = mmio;
+    dma_dev->id = device_id++;
+    dma_dev->mmio.pbase = mmio_id.base;
+    dma_dev->mmio.bytes = (1UL << mmio_id.bits);
+    dma_dev->mmio.cap = mmio;
 
     IOATDEV_DEBUG("init device with mmio range: {paddr=0x%016lx, size=%u kB}\n",
-                  ioat_device->id, mmio_id.base, 1 << mmio_id.bits);
+                  dma_dev->id, mmio_id.base, 1 << mmio_id.bits);
 
-    err = vspace_map_one_frame_attr(&ioat_device->mmio.vbase,
-                                    ioat_device->mmio.bytes, ioat_device->mmio.cap,
+    err = vspace_map_one_frame_attr(&dma_dev->mmio.vbase,
+                                    dma_dev->mmio.bytes, dma_dev->mmio.cap,
                                     VREGION_FLAGS_READ_WRITE_NOCACHE,
                                     NULL, NULL);
     if (err_is_fail(err)) {
@@ -214,12 +232,12 @@ errval_t ioat_dma_device_init(struct capref mmio,
         return err;
     }
 
-    ioat_dma_initialize(&ioat_device->device, NULL, ioat_device->mmio.vbase);
+    ioat_dma_initialize(&ioat_device->device, NULL, dma_dev->mmio.vbase);
 
     ioat_device->version = ioat_dma_cbver_rd(&ioat_device->device);
 
     IOATDEV_DEBUG("device registers mapped at 0x%016lx. IOAT version: %u.%u\n",
-                  ioat_device->id, (lvaddr_t )ioat_device->mmio.vbase,
+                  dma_dev->id, (lvaddr_t )dma_dev->mmio.vbase,
                   ioat_dma_cbver_major_extract(ioat_device->version),
                   ioat_dma_cbver_minor_extract(ioat_device->version));
 
@@ -238,7 +256,7 @@ errval_t ioat_dma_device_init(struct capref mmio,
     }
 
     if (err_is_fail(err)) {
-        vspace_unmap(ioat_device->mmio.vbase);
+        vspace_unmap(dma_dev->mmio.vbase);
         free(ioat_device);
     }
 
@@ -369,7 +387,19 @@ ioat_dma_dev_st_t ioat_dma_device_get_state(struct ioat_dma_device *dev)
  */
 inline uint8_t ioat_dma_device_get_channel_count(struct ioat_dma_device *dev)
 {
-    return dev->channels.num;
+    return dev->common.channels.num;
+}
+
+/**
+ * \brief returns the device ID from the IOAT device
+ *
+ * \param dev   IOAT DMA device
+ *
+ * \returns IOAT DMA device ID
+ */
+inline ioat_dma_devid_t ioat_dma_device_get_id(struct ioat_dma_device *dev)
+{
+    return dev->common.id;
 }
 
 /**
@@ -385,12 +415,12 @@ struct ioat_dma_channel *ioat_dma_device_get_channel(struct ioat_dma_device *dev
                                                      uint16_t id)
 {
     /* channel ID belongs not to this device */
-    if ((id >> 8) != dev->id) {
+    if ((id >> 8) != dev->common.id) {
         return NULL;
     }
 
     /* channel index exceeds channel number */
-    if ((id & 0xFF) > dev->channels.num) {
+    if ((id & 0xFF) > dev->common.channels.num) {
         return NULL;
     }
     assert(!"NYI");
@@ -399,6 +429,22 @@ struct ioat_dma_channel *ioat_dma_device_get_channel(struct ioat_dma_device *dev
 }
 
 /**
+ * \brief returns a channel from the device based on a round robin fashion
+ *
+ * \param dev   IOAT DMA device
+ *
+ * return IOAT DMA channel handle
+ */
+struct ioat_dma_channel *ioat_dma_device_get_next_channel(struct ioat_dma_device *dev)
+{
+    if (dev->common.channels.next >= dev->common.channels.num) {
+        dev->common.channels.next = 0;
+    }
+    return dev->common.channels.c[dev->common.channels.next++];
+}
+
+
+/**
  * \brief polls the channels of the IOAT DMA device
  *
  * \param dev   IOAT DMA device
index a1e5555..74691aa 100644 (file)
@@ -6,3 +6,183 @@
  * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
  */
 
+#include<barrelfish/barrelfish.h>
+
+#include <dma_request_internal.h>
+#include <ioat/ioat_dma_device_internal.h>
+#include <ioat/ioat_dma_channel_internal.h>
+#include <ioat/ioat_dma_request_internal.h>
+#include <ioat/ioat_dma_descriptors_internal.h>
+#include <ioat/ioat_dma_ring_internal.h>
+
+#include <debug.h>
+
+/**
+ *
+ */
+struct ioat_dma_request
+{
+    struct dma_req_int common;
+    struct ioat_dma_descriptor *desc_head;
+    struct ioat_dma_descriptor *desc_tail;
+    struct ioat_dma_request *next;
+};
+
+/*
+ * ---------------------------------------------------------------------------
+ * Request Management
+ * ---------------------------------------------------------------------------
+ */
+
+static struct ioat_dma_request *req_free_list = NULL;
+
+static struct ioat_dma_request *request_alloc(void)
+{
+    struct ioat_dma_request *ret;
+
+    if (req_free_list) {
+        ret = req_free_list;
+        req_free_list = ret->next;
+
+        IOATREQ_DEBUG("meta: reusing request %p. freelist:%p\n", ret, req_free_list);
+
+        return ret;
+    }
+    return calloc(1, sizeof(*ret));
+}
+
+static void request_free(struct ioat_dma_request *req)
+{
+    IOATREQ_DEBUG("meta: freeing request %p.\n", req);
+    req->next = req_free_list;
+    req_free_list = req;
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Helper Functions
+ * ---------------------------------------------------------------------------
+ */
+
+inline static uint32_t req_num_desc_needed(struct ioat_dma_channel *chan,
+                                           size_t bytes)
+{
+    uint32_t max_xfer_size = ioat_dma_channel_get_max_xfer_size(chan);
+    bytes += (max_xfer_size - 1);
+    return (uint32_t) (bytes / max_xfer_size);
+}
+
+/*
+ * ===========================================================================
+ * Library Internal Interface
+ * ===========================================================================
+ */
+
+/*
+ * ===========================================================================
+ * Public Interface
+ * ===========================================================================
+ */
+
+/**
+ * \brief issues a memcpy request to the given channel
+ *
+ * \param chan  IOAT DMA channel
+ * \param setup request setup information
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on failure
+ */
+errval_t ioat_dma_request_memcpy_chan(struct ioat_dma_channel *chan,
+                                      struct dma_req_setup *setup)
+{
+    uint32_t num_desc = req_num_desc_needed(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 ioat_dma_ring *ring = ioat_dma_channel_get_ring(chan);
+
+    if (num_desc > ioat_dma_ring_get_space(ring)) {
+        IOATREQ_DEBUG("Too less space in ring: %u / %u\n", num_desc,
+                    ioat_dma_ring_get_space(ring));
+        return IOAT_ERR_NO_DESCRIPTORS;
+    }
+
+    struct ioat_dma_request *req = request_alloc();
+    if (req == NULL) {
+        IOATREQ_DEBUG("No request descriptors for holding request data\n");
+        return IOAT_ERR_NO_REQUESTS;
+    }
+
+    ioat_dma_desc_ctrl_array_t ctrl = {
+        0
+    };
+
+    struct ioat_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 = ioat_dma_channel_get_max_xfer_size(chan);
+    do {
+        desc = ioat_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;
+
+            ioat_dma_desc_ctrl_fence_insert(ctrl, setup->args.memcpy.ctrl_fence);
+            ioat_dma_desc_ctrl_int_en_insert(ctrl, setup->args.memcpy.ctrl_intr);
+            ioat_dma_desc_ctrl_compl_write_insert(ctrl, 0x1);
+        } else {
+            bytes = max_xfer_size;
+        }
+
+        ioat_dma_desc_fill_memcpy(desc, src, dst, bytes, ctrl);
+        ioat_desc_set_request(desc, NULL);
+
+        length -= bytes;
+        src += bytes;
+        dst += bytes;
+    } while (length > 0);
+
+    req->common.req.setup = *setup;
+    req->common.req.id = generate_req_id(chan);
+
+    /* set the request pointer in the last descriptor */
+    ioat_desc_set_request(desc, req);
+
+    assert(req->desc_tail);
+    assert(ioat_dma_desc_get_request(req->desc_tail));
+
+    ioat_dma_channel_enq_request(chan, req);
+
+    return SYS_ERR_OK;
+}
+
+/**
+ * \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 ioat_dma_request_nop_chan(struct ioat_dma_channel *chan)
+{
+
+    struct ioat_dma_ring *ring = ioat_dma_channel_get_ring(chan);
+    assert(ring);
+
+    struct ioat_dma_descriptor *desc = ioat_ring_get_next_desc(ring);
+
+    IOATREQ_DEBUG("New DMA NOP request: descriptor=%p\n", desc);
+
+    ioat_dma_desc_fill_nop(desc);
+}
+
index a1e5555..7cb5804 100644 (file)
@@ -6,3 +6,298 @@
  * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
  */
 
+#include <string.h>
+#include <barrelfish/barrelfish.h>
+
+#include <dev/ioat_dma_dev.h>
+
+#include <dma_mem_utils.h>
+
+#include <ioat/ioat_dma_internal.h>
+#include <ioat/ioat_dma_descriptors_internal.h>
+#include <ioat/ioat_dma_ring_internal.h>
+
+#include <debug.h>
+
+#define ALIGN(val, align) (((val) + (align)-1) & ~((align)-1))
+
+/**
+ * represents the IOAT DMA ring with its internal state
+ */
+struct ioat_dma_ring
+{
+    uint16_t size;          ///< size of the descriptor ring
+    uint16_t head;          ///< allocated index
+    uint16_t issued;        ///< hardware notification point
+    uint16_t tail;          ///< cleanup index
+    uint16_t dmacount;      ///< identical to 'head' except for occasionally resetting to zero
+    uint16_t alloc_order;   ///< log2 of the number of allocated descriptors
+    uint16_t produce;       ///< number of descriptors to produce at submit time
+    struct ioat_dma_descriptor **desc;  ///< descriptor pointer array
+    struct ioat_dma_channel *chan;
+};
+
+/*
+ * ============================================================================
+ * Library Internal Interface
+ * ============================================================================
+ */
+
+/*
+ * ----------------------------------------------------------------------------
+ * Ring Manipulation
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief gets the next descriptor based on the head pointer and increments the
+ *        head pointer
+ *
+ * \param ring the DMA ring
+ *
+ * \returns pointer to a DMA descriptor
+ */
+inline struct ioat_dma_descriptor *ioat_ring_get_next_desc(struct ioat_dma_ring *ring)
+{
+    struct ioat_dma_descriptor *desc = ioat_dma_ring_get_desc(ring, ring->head++);
+
+    IOATDESC_DEBUG("ring getting next head desc:%p @ [%016lx], new head:%u\n", desc,
+                 ioat_desc_get_paddr(desc), ring->head);
+
+    return desc;
+}
+
+
+/**
+ * \brief gets the next descriptor based on the tail pointer and increases the
+ *        tail pointer index
+ *
+ * \param ring the DMA ring
+ *
+ * \returns pointer to a DMA descriptor
+ */
+inline struct ioat_dma_descriptor *ioat_ring_get_tail_desc(struct ioat_dma_ring *ring)
+{
+    struct ioat_dma_descriptor *desc = ioat_dma_ring_get_desc(ring, ring->tail++);
+
+    IOATDESC_DEBUG("ring getting tail desc:%p @ [%016lx], new tail: %u\n", desc,
+                 ioat_desc_get_paddr(desc), ring->tail);
+
+    return desc;
+}
+
+/**
+ * \brief submits the pending descriptors to the hardware
+ *
+ * \param ring DMA ring to submit the pending descriptors
+ *
+ * \returns the current head of the descriptors
+ */
+uint16_t ioat_ring_submit_pending(struct ioat_dma_ring *ring)
+{
+    uint16_t num_pending = ioat_dma_ring_get_pendig(ring);
+
+    if (num_pending != 0) {
+        ring->dmacount += num_pending;
+        ring->issued = ring->head;
+    }
+
+    return ring->dmacount;
+}
+
+/**
+ * \brief obtains the physical address of the descriptor chain
+ *        (pending descriptors)
+ *
+ * \param ring the DMA ring
+ *
+ * \returns physical address of the pending descriptor chain
+ */
+inline lpaddr_t ioat_ring_get_chain_addr(struct ioat_dma_ring *ring)
+{
+    return ioat_desc_get_paddr(ioat_dma_ring_get_desc(ring, ring->issued));
+}
+
+/*
+ * ============================================================================
+ * Public Interface
+ * ============================================================================
+ */
+
+/*
+ * ----------------------------------------------------------------------------
+ * Descriptor Ring Allocation / free
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief allocates a descriptor ring
+ *
+ * \param size_bits the size of the ring in bits
+ * \param ret_ring  where the ring pointer is returned
+ *
+ * \returns SYS_ERR_OK on succes
+ *          errval on error
+ */
+errval_t ioat_dma_ring_alloc(uint8_t size_bits,
+                             struct ioat_dma_ring **ret_ring,
+                             struct ioat_dma_channel *chan)
+{
+    errval_t err;
+
+    IOATDESC_DEBUG("allocating descriptor ring of size %u\n", (1 << size_bits));
+
+    struct ioat_dma_ring *ring;
+
+    if (size_bits > IOAT_DESC_RING_SIZE_MAX) {
+        size_bits = IOAT_DESC_RING_SIZE_MAX;
+    }
+
+    uint16_t ndesc = (1UL << size_bits);
+
+    ring = malloc(sizeof(struct ioat_dma_ring) + ndesc * sizeof(void *));
+    if (ring == NULL) {
+        return LIB_ERR_MALLOC_FAIL;
+    }
+
+    memset(ring, 0, sizeof(struct ioat_dma_ring) + ndesc * sizeof(void *));
+
+    ring->chan = chan;
+    ring->size = ndesc;
+    ring->desc = (void *) (ring + 1);
+
+    err = ioat_desc_alloc(IOAT_DMA_DESC_SIZE, IOAT_DMA_DESC_ALIGN, ndesc,
+                              ring->desc);
+    if (err_is_fail(err)) {
+        free(ring);
+        return err;
+    }
+
+    *ret_ring = ring;
+
+    return SYS_ERR_OK;
+}
+
+/**
+ * \brief frees a previously allocated descriptor ring
+ *
+ * \param ring IAT DMA descriptor ring to be freed
+ *
+ * \returns SYS_ERR_OK on success
+ *          errval on failure
+ */
+errval_t ioat_dma_ring_free(struct ioat_dma_ring *ring)
+{
+    errval_t err;
+
+    IOATDESC_DEBUG("freeing descriptor ring %p\n", ring);
+
+    err = ioat_desc_free(ring->desc[0]);
+    if (err_is_fail(err)) {
+        return err;
+    }
+
+    free(ring);
+
+    return SYS_ERR_OK;
+}
+
+/*
+ * ----------------------------------------------------------------------------
+ * Ring Status Queries
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief returns the number of active descriptors i.e. those who have not yet
+ *        been finished by the DMA hardware. this includes submitted and pending
+ *        DMA descriptors
+ *
+ * \param ring  IOAT DMA descriptor ring
+ *
+ * \returns number of active descriptors
+ */
+inline uint16_t ioat_dma_ring_get_active(struct ioat_dma_ring *ring)
+{
+    return (ring->head - ring->tail) & (ring->size - 1);
+}
+
+/**
+ * \brief returns the number of prepared but not submitted descriptors
+ *
+ * \param ring  IOAT DMA descriptor ring
+ *
+ * \returns number of pending descriptors
+ */
+inline uint16_t ioat_dma_ring_get_pendig(struct ioat_dma_ring *ring)
+{
+    return (ring->head - ring->issued) & (ring->size - 1);
+}
+
+/*
+ * ----------------------------------------------------------------------------
+ * Getter Functions
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * \brief returns the size of the ring
+ *
+ * \param ring  IOAT DMA descriptor ring
+ *
+ * \returns number of descriptors in the ring
+ */
+inline uint16_t ioat_dma_ring_get_size(struct ioat_dma_ring *ring)
+{
+    return ring->size;
+}
+
+/**
+ * \brief returns the head pointer index of the ring
+ *
+ * \param ring  IOAT DMA descriptor ring
+ *
+ * \returns head element index
+ */
+inline uint16_t ioat_dma_ring_get_head(struct ioat_dma_ring *ring)
+{
+    return ring->head;
+}
+
+/**
+ * \brief returns the tail pointer index of the ring
+ *
+ * \param ring  IOAT DMA descriptor ring
+ *
+ * \returns tail element index
+ */
+inline uint16_t ioat_dma_ring_get_tail(struct ioat_dma_ring *ring)
+{
+    return ring->tail;
+}
+
+/**
+ * \brief returns the issued pointer index of the ring
+ *
+ * \param ring  IOAT DMA descriptor ring
+ *
+ * \returns issued element index
+ */
+inline uint16_t ioat_dma_ring_get_issued(struct ioat_dma_ring *ring)
+{
+    return ring->issued;
+}
+
+/**
+ * \brief gets the next descriptor based on the index
+ *
+ * \param ring  the DMA ring
+ * \param index the index of the ring
+ *
+ * \returns pointer to a DMA descriptor
+ */
+inline struct ioat_dma_descriptor *ioat_dma_ring_get_desc(struct ioat_dma_ring *ring,
+                                                          uint16_t index)
+{
+    return ring->desc[index & (ring->size - 1)];
+}
index d205da2..77c3ff5 100644 (file)
 
 #define IOAT_DMA_DESC_FLAG_VALID     0x01
 #define IOAT_DMA_DESC_FLAG_USED      0x02
-#define IOAT_DMA_DESC_FLAG_FIRST     0x03
+#define IOAT_DMA_DESC_FLAG_FIRST     0x04
 #define IOAT_DMA_DESC_FLAG_LAST      0x08
 #define IOAT_DMA_DESC_FLAG_PROGRESS  0x10
+#define IOAT_DMA_DESC_FLAG_HEAD      0x20
 #define IOAT_DMA_DESC_FLAG_DONE      0x40
 #define IOAT_DMA_DESC_FLAG_ERR       0x80
 
index 773bc5f..45c86c8 100644 (file)
@@ -16,19 +16,12 @@ struct ioat_dma_ring;
 struct ioat_dma_descriptor;
 
 
-#define IOAT_DMA_DESC_MAP_FLAGS VREGION_FLAGS_READ_WRITE
-
 /// the minimum amount of DMA descriptors to allocate in bits
 #define IOAT_DMA_DESC_RING_SIZE 8
 
 /// maximum ring size in bits
 #define IOAT_DMA_DESC_RING_SIZE_MAX 16
 
-/// the size of the basic descriptor
-#define IOAT_DMA_DESC_SIZE 64
-
-/// minimum alignment constraint for the descriptors
-#define IOAT_DMA_DESC_ALIGN 64
 
 
 /*