1// -*- Mode: C++ -*- 2// vim:ft=cpp 3/** 4 * \file 5 */ 6/* 7 * (c) 2014 Alexander Warg <alexander.warg@kernkonzept.com> 8 * 9 * This file is part of TUD:OS and distributed under the terms of the 10 * GNU General Public License 2. 11 * Please see the COPYING-GPL-2 file for details. 12 * 13 * As a special exception, you may use this file as part of a free software 14 * library without restriction. Specifically, if other files instantiate 15 * templates or use macros or inline functions from this file, or you compile 16 * this file and link it with other files to produce an executable, this 17 * file does not by itself cause the resulting executable to be covered by 18 * the GNU General Public License. This exception does not however 19 * invalidate any other reasons why the executable file might be covered by 20 * the GNU General Public License. 21 */ 22 23#pragma once 24 25#include <l4/sys/types.h> 26#include <l4/sys/l4int.h> 27#include <l4/sys/capability> 28#include <l4/re/dataspace> 29#include <l4/re/protocols.h> 30#include <l4/sys/cxx/types> 31#include <l4/sys/cxx/ipc_types> 32#include <l4/sys/cxx/ipc_iface> 33 34namespace L4Re 35{ 36 37/** 38 * DMA Address Space. 39 * 40 * A Dma_space represents the DMA address space of a device. 41 * Whenever a device needs direct access to parts of an L4Re::Dataspace, that 42 * part of the data space must be mapped to the DMA address space that is 43 * assigned to that device. After the DMA accesses to the memory are finished 44 * the memory must be unmapped from the device's DMA address space. 45 * 46 * Mapping to a DMA address space, using map(), makes the given parts of 47 * the data space visible to the associated device at the returned 48 * DMA address. As long as the memory is mapped into a DMA space it is 'pinned' 49 * and cannot be subject to dynamic memory management such as swapping. 50 * Additionally, map() is responsible for the necessary syncing operations before 51 * the DMA. 52 * 53 * unmap() is the reverse operation to map() and unmaps the given 54 * data-space part for the DMA address space. unmap() is responsible for the 55 * necessary sync operations after the DMA. 56 */ 57class Dma_space : 58 public L4::Kobject_0t< Dma_space, 59 L4RE_PROTO_DMA_SPACE, 60 L4::Type_info::Demand_t<1> > 61{ 62public: 63 /// Data type for DMA addresses. 64 typedef l4_uint64_t Dma_addr; 65 66 /** 67 * Direction of the DMA transfers 68 */ 69 enum Direction 70 { 71 Bidirectional, ///< device reads and writes to the memory 72 To_device, ///< device reads the memory 73 From_device, ///< device writes to the memory 74 None ///< device is coherently connected to the memory 75 }; 76 77 /** 78 * Attributes used for the memory region during the transfer. 79 * \sa Attributes 80 */ 81 enum Attribute 82 { 83 /** 84 * Do not sync the memory hierarchy. 85 * 86 * When this flag is _not set_ (default) the memory region shall be made 87 * coherent to the point-of-coherency of the device associated with this 88 * Dma_space. 89 * When using this attribute the client is responsible for syncing the 90 * memory hierarchy for DMA. This can either be done using the cache API 91 * or by another map() or unmap() operation of the same part of the data 92 * space (without the #No_sync attribute). 93 */ 94 No_sync 95 }; 96 97 /** 98 * Attributes for DMA mappings. 99 * 100 * \sa Attribute 101 */ 102 typedef L4::Types::Flags<Attribute> Attributes; 103 104 /** 105 * Attributes assigned to the DMA space when associated with a 106 * specific device. 107 * \sa Space_attribs 108 */ 109 enum Space_attrib 110 { 111 /** 112 * The device is connected coherently with the cache. 113 * 114 * This means that the map() and unmap() do not need to sync 115 * CPU caches before and after DMA. 116 */ 117 Coherent, 118 119 /** 120 * The DMA space has no DMA task assigned and uses the CPUs 121 * physical memory. 122 */ 123 Phys_space 124 }; 125 126 /// Attributes used when configuring the DMA space. 127 typedef L4::Types::Flags<Space_attrib> Space_attribs; 128 129 /** 130 * Map the given part of this data space into the DMA address space. 131 * 132 * \caprights{R} 133 * \param[in] src Source data space (that describes the memory). 134 * Caller needs write rights to the data space. 135 * \param[in] offset The offset (bytes) within `src`. 136 * \param[in,out] size The size (bytes) of the region to be mapped 137 * for DMA, after successful mapping the size 138 * returned is the size mapped for DMA as a single 139 * block. This size might be smaller than the 140 * original input size, in this case the caller might 141 * call map() again with a new offset and the 142 * remaining size. 143 * \param[in] attrs The attributes used for this DMA mapping 144 * (a combination of Dma_space::Attribute values). 145 * \param[in] dir The direction of the DMA transfer issued with 146 * this mapping. The same value must later be passed 147 * to unmap(). 148 * \param[out] dma_addr The DMA address to use for DMA with the associated 149 * device. 150 * 151 * \return 0 in the case of success, a negative error code otherwise. 152 */ 153 L4_INLINE_RPC( 154 long, map, (L4::Ipc::Cap<L4Re::Dataspace> src, 155 L4Re::Dataspace::Offset offset, 156 L4::Ipc::In_out<l4_size_t *> size, 157 Attributes attrs, Direction dir, 158 Dma_addr *dma_addr)); 159 160 /** 161 * Unmap the given part of this data space from the DMA address space. 162 * \caprights{R} 163 * \param dma_addr The DMA address (returned by Dma_space::map()). 164 * \param size The size (bytes) of the memory region to unmap. 165 * \param attrs The attributes for the unmap (currently none). 166 * \param dir The direction of the finished DMA operation. 167 */ 168 L4_INLINE_RPC( 169 long, unmap, (Dma_addr dma_addr, 170 l4_size_t size, Attributes attrs, Direction dir)); 171 172 /** 173 * Associate a DMA task for a device to this Dma_space. 174 * 175 * \caprights{RW} 176 * \param[in] dma_task The DMA task used for the device that shall be 177 * associated with this DMA space. The dma_task might 178 * be an invalid capability when 179 * L4Re::Dma_space::Phys_space is set in 180 * `attr`, in this case the CPUs physical memory 181 * is used as DMA address space. 182 * \param[in] attr Attributes for this DMA space. See 183 * L4Re::Dma_space::Space_attrib. 184 */ 185 L4_INLINE_RPC( 186 long, associate, (L4::Ipc::Opt<L4::Ipc::Cap<L4::Task> > dma_task, 187 Space_attribs attr), 188 L4::Ipc::Call_t<L4_CAP_FPAGE_RW>); 189 190 /** 191 * Disassociate the DMA task from this Dma_space. 192 * 193 * \caprights{RW} 194 */ 195 L4_INLINE_RPC( 196 long, disassociate, (), 197 L4::Ipc::Call_t<L4_CAP_FPAGE_RW>); 198 199 typedef L4::Typeid::Rpcs<map_t, unmap_t, associate_t, disassociate_t> Rpcs; 200}; 201 202} 203