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