1 /*---------------------------------------------------------------------------*
2 Project: DMAEngine library
3 File: dmae.h
4
5 Copyright (C) 2011 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12 *---------------------------------------------------------------------------*/
13
14 #ifndef __DMAE_H__
15 #define __DMAE_H__
16
17 #ifdef __cplusplus
18 extern "C" {
19 #endif
20
21 /// @defgroup DMAE DMAE
22
23 /// @defgroup DMAEConstants Constants
24 /// @ingroup DMAE
25 /// @addtogroup DMAEConstants
26 /// @{
27
28 #define DMAE_INLINE inline
29
30 /// \brief DMAE data buffers must be aligned by this many bytes.
31 /// \note Semaphores must be aligned by sizeof(u64) = 8 bytes.
32 #define DMAE_DATA_ALIGNMENT 4
33
34 /// \brief Default timeout for \ref DMAEWaitDone in milliseconds.
35 /// This timeout value can be set via \ref DMAESetTimeout API
36 #define DMAE_DEFAULT_TIMEOUT_IN_MILLISEC (30 * 1000)
37
38 /// \brief Type used for DMA Engine time stamps
39 ///
40 /// Time stamps are used to check when DMA commands complete.
41 ///
42 typedef u64 DMAETimeStamp;
43 /// @}
44
45 /// @defgroup DMAEEnums Enums
46 /// @ingroup DMAE
47 /// @addtogroup DMAEEnums
48 /// @{
49
50 /// \brief Type of endian swapping mode
51 ///
52 typedef enum DMAEEndian {
53 DMAE_ENDIAN_NONE = 0x00000000, ///< do-nothing
54 DMAE_ENDIAN_8IN16 = 0x00000001, ///< 8IN16 swapping mode. Endian swap in 16-bit int buffer.
55 DMAE_ENDIAN_8IN32 = 0x00000002, ///< 8IN32 swapping mode. Endian swap in 32-bit int buffer.
56 DMAE_ENDIAN_8IN64 = 0x00000003, ///< 8IN64 swapping mode. Endian swap in 64-bit int buffer.
57 } DMAEEndian;
58
59 /// \brief Type of DMA semaphore action
60 ///
61 typedef enum _DMAESemaphoreAction {
62 DMAE_SEMAPHORE_WAIT = 0x00000000, ///< Wait before processing next command
63 DMAE_SEMAPHORE_SIGNAL = 0x00000001, ///< Signal after all previous work is done
64 } DMAESemaphoreAction;
65 /// @}
66
67 /// @defgroup DMAESynchronization Synchronization
68 /// @ingroup DMAE
69 /// @addtogroup DMAESynchronization
70 /// @{
71
72 /// \brief Wait for a DMA command to complete.
73 ///
74 /// Returns false if a time-out occurs, true otherwise.
75 /// A time-out should never occur in a correctly written program.
76 /// The time-out value is set at 5 seconds.
77 ///
78 /// \param ts time stamp of command in question
79 /// \return TRUE normally; FALSE if a time-out occurred
80 ///
81 /// \donotcall \fgonly \threadsafe \notinterrupt \notexception \devonly \enddonotcall
82 ///
83 /// \writesdmae
84 ///
85 BOOL DMAEWaitDone(DMAETimeStamp ts);
86
87 /// \brief Get time stamp of last submitted command.
88 ///
89 /// \donotcall \threadsafe \devonly \enddonotcall
90 ///
91 DMAETimeStamp DMAEGetLastSubmittedTimeStamp(void);
92
93 /// \brief Indicate most recent time stamp completed (retired).
94 ///
95 /// When the value of this function matches or exceeds that of a specified command,
96 /// then that command is completely finished.
97 ///
98 /// \return The value of the most recently completed time stamp
99 ///
100 /// \donotcall \fgonly \notthreadsafe \devonly \enddonotcall
101 ///
102 DMAETimeStamp DMAEGetRetiredTimeStamp(void);
103
104 /// \brief Check if a command is done.
105 ///
106 /// A helper function to indicate if a specified command is completed.
107 ///
108 /// \param ts time stamp of command in question
109 /// \return TRUE if the command is done, FALSE otherwise.
110 ///
111 /// \donotcall \fgonly \notthreadsafe \devonly \enddonotcall
112 ///
DMAEIsDone(DMAETimeStamp ts)113 DMAE_INLINE BOOL DMAEIsDone(DMAETimeStamp ts) {
114 return ts <= DMAEGetRetiredTimeStamp();
115 }
116
117 /// \brief Initialize DMAE semaphore.
118 ///
119 /// This function is used to initialize the semaphore to syncronize DMA Engine
120 /// with the GPU7.
121 /// The semaphore value is kept in memory at the specified location.
122 /// It is initialized to a specified count and flushed from the cache.
123 /// This API has exactly the same functional capability as \ref GX2InitSemaphore.
124 ///
125 /// \param semaphoreAddr Location of semaphore data in memory
126 /// \param semaphoreCount Initial semaphore count
127 ///
128 /// \donotcall \notthreadsafe \devonly \enddonotcall
129 ///
DMAEInitSemaphore(u64 * semaphoreAddr,u64 semaphoreCount)130 DMAE_INLINE void DMAEInitSemaphore(u64 *semaphoreAddr, u64 semaphoreCount) {
131 // Store u64 byte-reversed (hardware requirement), so do lower half first:
132 * (__bytereversed u32 *) semaphoreAddr = (u32) (semaphoreCount & 0xffffffff);
133 * (((__bytereversed u32 *) semaphoreAddr)+1) = (u32) (semaphoreCount >> 32);
134 DCFlushRange(semaphoreAddr, sizeof(u64));
135 }
136
137 /// \brief Have DMA Engine wait on or signal a memory semaphore.
138 ///
139 /// This function is used to syncronize the DMA Engine with the GPU.
140 /// The semaphore value is kept in memory at the specified location.
141 /// It should be initialized and flushed from the cache before use.
142 ///
143 /// The command is put into the DMAEngine command queue immediately.
144 ///
145 /// \param semaphoreAddr Location of semaphore data in memory
146 /// \param semaphoreAction Indicates whether to wait on or signal the semaphore
147 /// \return time stamp for command submission
148 ///
149 /// \donotcall \fgonly \threadsafe \notinterrupt \notexception \devonly \enddonotcall
150 ///
151 /// \writesdmae
152 ///
153 DMAETimeStamp DMAESemaphore(u64 *semaphoreAddr, DMAESemaphoreAction semaphoreAction);
154 /// @}
155
156 /// @defgroup DMAECopy Copy
157 /// @ingroup DMAE
158 /// @addtogroup DMAECopy
159 /// @{
160
161 /// \brief Issue a DMA command to copy memory from one range to another.
162 ///
163 /// The command is put into the DMAEngine command queue immediately.
164 /// However, this function does not wait for it to complete.
165 /// Both ranges should be flushed or invalidated from the CPU cache
166 /// prior to calling this function.
167 ///
168 /// \param dst Destination of data to copy (8B aligned)
169 /// \param src Source of data to copy (8B aligned)
170 /// \param sizeInU32s Size of data to copy (in u32 units)
171 /// \param endian Endian mode for swapping destination data
172 /// \return time stamp for command submission
173 ///
174 /// \donotcall \fgonly \threadsafe \notinterrupt \notexception \devonly \enddonotcall
175 ///
176 /// \writesdmae
177 ///
178 DMAETimeStamp DMAECopyMem(void *dst, const void *src, u32 sizeInU32s, DMAEEndian endian);
179
180 /// \brief Issue a DMA command to copy memory from one range to another.
181 ///
182 /// The command is put into the DMAEngine command queue immediately and waits for it to complete.
183 /// Both ranges should be flushed or invalidated from the CPU cache
184 /// prior to calling this function.
185 ///
186 /// \param dst Destination of data to copy (8B aligned)
187 /// \param src Source of data to copy (8B aligned)
188 /// \param sizeInU32s Size of data to copy (in u32 units)
189 /// \param endian Endian mode for swapping destination data
190 /// \return TRUE normally; FALSE if a time-out occurred
191 ///
192 /// \donotcall \fgonly \threadsafe \notinterrupt \notexception \devonly \enddonotcall
193 ///
194 /// \writesdmae
195 ///
DMAECopyMemWait(void * dst,const void * src,u32 sizeInU32s,DMAEEndian endian)196 DMAE_INLINE BOOL DMAECopyMemWait(void *dst, const void *src, u32 sizeInU32s, DMAEEndian endian) {
197 return DMAEWaitDone( DMAECopyMem(dst, src, sizeInU32s, endian) );
198 }
199 /// @}
200
201 /// @defgroup DMAEFill Fill
202 /// @ingroup DMAE
203 /// @addtogroup DMAEFill
204 /// @{
205
206 /// \brief Issue a DMA command to fill a memory range with a specified value.
207 ///
208 /// The command is put into the DMAEngine command queue immediately.
209 /// However, this function does not wait for it to complete.
210 /// The range should be flushed or invalidated from the CPU cache
211 /// prior to calling this function.
212 ///
213 /// \param dst Start of range to fill (8B aligned)
214 /// \param fillData Value to fill range with (a u32)
215 /// \param sizeInU32s Size of range to fill (in u32 units)
216 /// \return time stamp for command submission
217 ///
218 /// \donotcall \fgonly \threadsafe \notinterrupt \notexception \devonly \enddonotcall
219 ///
220 /// \writesdmae
221 ///
222 DMAETimeStamp DMAEFillMem(void *dst, u32 fillData, u32 sizeInU32s);
223
224 /// \brief Issue a DMA command to fill a memory range with a specified value.
225 ///
226 /// The command is put into the DMAEngine command queue and waits for it to complete.
227 /// The range should be flushed or invalidated from the CPU cache
228 /// prior to calling this function.
229 ///
230 /// \param dst Start of range to fill (8B aligned)
231 /// \param fillData Value to fill range with (a u32)
232 /// \param sizeInU32s Size of range to fill (in u32 units)
233 /// \return TRUE normally; FALSE if a time-out occurred
234 ///
235 /// \donotcall \fgonly \threadsafe \notinterrupt \notexception \devonly \enddonotcall
236 ///
237 /// \writesdmae
238 ///
DMAEFillMemWait(void * dst,u32 fillData,u32 sizeInU32s)239 DMAE_INLINE BOOL DMAEFillMemWait(void *dst, u32 fillData, u32 sizeInU32s) {
240 return DMAEWaitDone( DMAEFillMem(dst, fillData, sizeInU32s) );
241 }
242 /// @}
243
244 // For Nintendo use only
245
246 // \brief Issue a DMA command to fill a physical memory range with a specified value.
247 //
248 // The range should be flushed or invalidated from the CPU cache
249 // prior to calling this function.
250 //
251 // \param dst_pa Physical address of start of range to fill (8B aligned)
252 // \param fillData Value to fill range with (a u32)
253 // \param sizeInU32s Size of range to fill (in u32 units)
254 // \return TRUE normally; FALSE if a time-out occurred
255 //
256 // \donotcall \fgonly \threadsafe \notinterrupt \notexception \devonly \enddonotcall
257 //
258 // \writesdmae
259 //
260 DMAETimeStamp DMAEFillMemPhys(u32 dst_pa, u32 fillData, u32 sizeInU32s);
261
262 // \brief Issue a DMA command to fill a physical memory range with a specified value.
263 //
264 // The command is put into the DMAEngine command queue and wait for it to complete.
265 // The range should be flushed or invalidated from the CPU cache
266 // prior to calling this function.
267 //
268 // \param dst_pa Physical address of start of range to fill (8B aligned)
269 // \param fillData Value to fill range with (a u32)
270 // \param sizeInU32s Size of range to fill (in u32 units)
271 // \return TRUE normally; FALSE if a time-out occurred
272 //
273 // \donotcall \fgonly \threadsafe \notinterrupt \notexception \devonly \enddonotcall
274 //
275 // \writesdmae
276 //
DMAEFillMemPhysWait(u32 dst_pa,u32 fillData,u32 sizeInU32s)277 DMAE_INLINE BOOL DMAEFillMemPhysWait(u32 dst_pa, u32 fillData, u32 sizeInU32s) {
278 return DMAEWaitDone( DMAEFillMemPhys(dst_pa, fillData, sizeInU32s) );
279 }
280
281 /// @defgroup DMAEMiscellaneous Miscellaneous
282 /// @ingroup DMAE
283 /// @addtogroup DMAEMiscellaneous
284 /// @{
285
286 /// \brief This sets the millisecond timeout value used to determine whether
287 /// the DMA Engine is hung when the app is doing a heavy workload.
288 ///
289 /// \param millisec set milli seconds that DMA Engine regards as hang
290 ///
291 /// \donotcall \fgonly \notthreadsafe \devonly \enddonotcall
292 ///
293 void DMAESetTimeout(u32 millisec);
294
295 /// \brief This returns the timeout value in milliseconds used to
296 /// determine whether the DMA Engine is hung when the app is doing a heavy workload.
297 ///
298 /// \donotcall \threadsafe \devonly \enddonotcall
299 ///
300 u32 DMAEGetTimeout(void);
301 /// @}
302
303 #ifdef __cplusplus
304 }
305 #endif
306
307 #endif // __DMAE_H__
308