L4Re - L4 Runtime Environment
dma_space
Go to the documentation of this file.
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 
34 namespace L4Re
35 {
36 
37 /**
38  * \defgroup api_l4re_dma DMA API for L4Re
39  */
40 
41 /**
42  * DMA Address Space.
43  *
44  * A Dma_space represents the DMA address space of a device.
45  * Whenever a device needs direct access to parts of an L4Re::Dataspace, that
46  * part of the data space must be mapped to the DMA address space that is
47  * assigned to that device. After the DMA accesses to the memory are finished
48  * the memory must be unmapped from the device's DMA address space.
49  *
50  * Mapping to a DMA address space, using map(), makes the given parts of
51  * the data space visible to the associated device at the returned
52  * DMA address. As long as the memory is mapped into a DMA space it is 'pinned'
53  * and cannot be subject to dynamic memory management such as swapping.
54  * Additionally, map() is responsible for the necessary syncing operations before
55  * the DMA.
56  *
57  * unmap() is the reverse operation to map() and unmaps the given
58  * data-space part for the DMA address space. unmap() is responsible for the
59  * necessary sync operations after the DMA.
60  */
61 class Dma_space :
62  public L4::Kobject_0t< Dma_space,
63  L4RE_PROTO_DMA_SPACE,
64  L4::Type_info::Demand_t<1> >
65 {
66 public:
67  /// Data type for DMA addresses.
68  typedef l4_uint64_t Dma_addr;
69 
70  /**
71  * Direction of the DMA transfers
72  */
73  enum Direction
74  {
75  Bidirectional, ///< device reads and writes to the memory
76  To_device, ///< device reads the memory
77  From_device, ///< device writes to the memory
78  None ///< device is coherently connected to the memory
79  };
80 
81  /**
82  * Attributes used for the memory region during the transfer.
83  * \sa Attributes
84  */
85  enum Attribute
86  {
87  /**
88  * Do not sync the memory hierarchy.
89  *
90  * When this flag is _not set_ (default) the memory region shall be made
91  * coherent to the point-of-coherency of the device associated with this
92  * Dma_space.
93  * When using this attribute the client is responsible for syncing the
94  * memory hierarchy for DMA. This can either be done using the cache API
95  * or by another map() or unmap() operation of the same part of the data
96  * space (without the #No_sync attribute).
97  */
98  No_sync
99  };
100 
101  /**
102  * Attributes for DMA mappings.
103  *
104  * \sa Attribute
105  */
106  typedef L4::Types::Flags<Attribute> Attributes;
107 
108  /**
109  * Attributes assigned to the DMA space when associated with a
110  * specific device.
111  * \sa Space_attribs
112  */
113  enum Space_attrib
114  {
115  /**
116  * The device is connected coherently with the cache.
117  *
118  * This means that the map() and unmap() do not need to sync
119  * CPU caches before and after DMA.
120  */
121  Coherent,
122 
123  /**
124  * The DMA space has no DMA task assigned and uses the CPUs
125  * physical memory.
126  */
127  Phys_space
128  };
129 
130  /// Attributes used when configuring the DMA space.
131  typedef L4::Types::Flags<Space_attrib> Space_attribs;
132 
133  /**
134  * Map the given part of this data space into the DMA address space.
135  *
136  * \caprights{R}
137  * \param[in] src Source data space (that describes the memory).
138  * Caller needs write rights to the data space.
139  * \param[in] offset The offset (bytes) within `src`.
140  * \param[in,out] size The size (bytes) of the of the region to be mapped
141  * to for DMA, after successful mapping the size
142  * returned is the size mapped for DMA as single
143  * block, this size might be smaller than the
144  * original input size, in this case the caller might
145  * call map() again with a new offset and the
146  * remaining size.
147  * \param[in] attrs The attributes used for this DMA mapping
148  * (a combination of Dma_space::Attribute values).
149  * \param[in] dir The direction of the DMA transfer issued with
150  * this mapping. The same value must later be passed
151  * to unmap().
152  * \param[out] dma_addr The DMA address to use for DMA with the associated
153  * device.
154  *
155  * \return 0 in the case of success, a negative error code otherwise.
156  */
157  L4_INLINE_RPC(
158  long, map, (L4::Ipc::Cap<L4Re::Dataspace> src, l4_addr_t offset,
159  L4::Ipc::In_out<l4_size_t *> size,
160  Attributes attrs, Direction dir,
161  Dma_addr *dma_addr));
162 
163  /**
164  * Unmap the given part of this data space from the DMA address space.
165  * \caprights{R}
166  * \param dma_addr The DMA address (returned by Dma_space::map()).
167  * \param size The size (bytes) of the memory region to unmap.
168  * \param attrs The attributes for the unmap (currently none).
169  * \param dir The direction of the finished DMA operation.
170  */
171  L4_INLINE_RPC(
172  long, unmap, (Dma_addr dma_addr,
173  l4_size_t size, Attributes attrs, Direction dir));
174 
175  /**
176  * Associate a DMA task for a device to this Dma_space.
177  *
178  * \caprights{RW}
179  * \param[in] dma_task The DMA task used for the device that shall be
180  * associated with this DMA space. The dma_task might
181  * be an invalid capability when #Phys_space is set in
182  * `attr`, in this case the CPUs physical memory
183  * is used as DMA address space.
184  * \param[in] attr Attributes for this DMA space. See #Space_attrib.
185  */
186  L4_INLINE_RPC(
187  long, associate, (L4::Ipc::Opt<L4::Ipc::Cap<L4::Task> > dma_task,
188  Space_attribs attr),
189  L4::Ipc::Call_t<L4_CAP_FPAGE_RW>);
190 
191  /**
192  * Disassociate the DMA task from this Dma_space.
193  *
194  * \caprights{RW}
195  */
196  L4_INLINE_RPC(
197  long, disassociate, (),
198  L4::Ipc::Call_t<L4_CAP_FPAGE_RW>);
199 
200  typedef L4::Typeid::Rpcs<map_t, unmap_t, associate_t, disassociate_t> Rpcs;
201 };
202 
203 }
204