1/*
2 * Copyright (c) 2014, ETH Zurich. All rights reserved.
3 *
4 * This file is distributed under the terms in the attached LICENSE file.
5 * If you do not find this file, copies can be found by writing to:
6 * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
7 */
8
9#include <string.h>
10#include <barrelfish/barrelfish.h>
11#include <xeon_phi/xeon_phi.h>
12#include <dev/xeon_phi/xeon_phi_dma_dev.h>
13
14#include <dma_mem_utils.h>
15
16#include <xeon_phi/xeon_phi_dma_internal.h>
17#include <xeon_phi/xeon_phi_dma_descriptors_internal.h>
18
19#include <debug.h>
20
21#define ASSERT_ALIGNED(x) \
22    assert((x) && ((((uintptr_t)x) & (XEON_PHI_DMA_ALIGNMENT - 1)) == 0))
23
24static inline void clear_descriptor(void *descriptor)
25{
26    uint64_t *desc = descriptor;
27    desc[0] = 0;
28    desc[1] = 0;
29}
30
31/*
32 * ============================================================================
33 * Public Interface
34 * ============================================================================
35 */
36
37/**
38 * \brief initializes the hardware specific part of the descriptor to be used
39 *        for memcpy descriptors
40 *
41 * \param desc  Xeon Phi descriptor
42 * \param src   Source address of the transfer
43 * \param dst   destination address of the transfer
44 * \param size  number of bytes to copy
45 * \param flags control flags
46 *
47 * XXX: this function assumes that the size of the descriptor has already been
48 *      checked and must match the maximum transfer size of the channel
49 */
50inline void xeon_phi_dma_desc_fill_memcpy(struct dma_descriptor *desc,
51                                          lpaddr_t src,
52                                          lpaddr_t dst,
53                                          uint32_t size,
54                                          uint32_t flags)
55{
56    uint8_t *d = dma_desc_get_desc_handle(desc);
57
58    clear_descriptor(d);
59
60    ASSERT_ALIGNED(src);
61    ASSERT_ALIGNED(dst);
62    ASSERT_ALIGNED(size);
63
64    if (flags & XEON_PHI_DMA_DESC_FLAG_INTR) {
65        xeon_phi_dma_desc_memcpy_intr_insert(d, 0x1);
66    }
67    if (flags & XEON_PHI_DMA_DESC_FLAG_TWB) {
68        xeon_phi_dma_desc_memcpy_twb_insert(d, 0x1);
69    }
70    if (flags & XEON_PHI_DMA_DESC_FLAG_C) {
71        xeon_phi_dma_desc_memcpy_c_insert(d, 0x1);
72    }
73    if (flags & XEON_PHI_DMA_DESC_FLAG_CO) {
74        xeon_phi_dma_desc_memcpy_co_insert(d, 0x1);
75    }
76    if (flags & XEON_PHI_DMA_DESC_FLAG_ECY) {
77        xeon_phi_dma_desc_memcpy_ecy_insert(d, 0x1);
78    }
79
80    xeon_phi_dma_desc_memcpy_src_insert(d, src);
81    xeon_phi_dma_desc_memcpy_dst_insert(d, dst);
82    xeon_phi_dma_desc_memcpy_length_insert(d, (size >> XEON_PHI_DMA_ALIGN_SHIFT));
83    xeon_phi_dma_desc_memcpy_dtype_insert(d, xeon_phi_dma_desc_memcpy);
84
85}
86
87/**
88 * \brief initializes the hardware specific part of the descriptor to be used
89 *        for nop descriptors (null descriptors)
90 *
91 * \param desc  Xeon Phi descriptor
92 */
93inline void xeon_phi_dma_desc_fill_nop(struct dma_descriptor *desc)
94{
95    clear_descriptor(dma_desc_get_desc_handle(desc));
96}
97
98/**
99 * \brief initializes the hardware specific part of the descriptor to be used
100 *        for general descriptors
101 *
102 * \param desc  Xeon Phi descriptor
103 * \param dst   destination address
104 * \param data  Data payload for the request (request specific)
105 */
106inline void xeon_phi_dma_desc_fill_general(struct dma_descriptor *desc,
107                                           lpaddr_t dst,
108                                           uint64_t data)
109{
110    uint8_t *d = dma_desc_get_desc_handle(desc);
111
112    clear_descriptor(d);
113
114    ASSERT_ALIGNED(dst);
115
116    xeon_phi_dma_desc_general_data_insert(d, data);
117    xeon_phi_dma_desc_general_dst_insert(d, dst);
118
119    xeon_phi_dma_desc_general_dtype_insert(d,
120    xeon_phi_dma_desc_general);
121}
122
123/**
124 * \brief initializes the hardware specific part of the descriptor to be used
125 *        for status descriptors
126 *
127 * \param desc  Xeon Phi descriptor
128 * \param dst   destination address
129 * \param data  Data payload for the request (request specific)
130 * \param flags Descriptor flags
131 */
132inline void xeon_phi_dma_desc_fill_status(struct dma_descriptor *desc,
133                                          lpaddr_t dst,
134                                          uint64_t data,
135                                          uint32_t flags)
136{
137    uint8_t *d = dma_desc_get_desc_handle(desc);
138
139    clear_descriptor(d);
140
141    ASSERT_ALIGNED(dst);
142
143    xeon_phi_dma_desc_status_data_insert(d, data);
144    xeon_phi_dma_desc_status_dst_insert(d, dst);
145    if (flags & XEON_PHI_DMA_DESC_FLAG_INTR) {
146        xeon_phi_dma_desc_status_intr_insert(d, 0x1);
147    }
148
149    xeon_phi_dma_desc_status_dtype_insert(d,
150    xeon_phi_dma_desc_status);
151}
152