1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - MI -
3   File:     dma_red.h
4 
5   Copyright 2003-2008 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   $Date:: 2008-09-18#$
14   $Rev: 8573 $
15   $Author: okubata_ryoma $
16 
17  *---------------------------------------------------------------------------*/
18 
19 #ifndef NITRO_MI_DMA_RED_H_
20 #define NITRO_MI_DMA_RED_H_
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 
26 #include <nitro/misc.h>
27 #include <nitro/types.h>
28 #include <nitro/memorymap.h>
29 #include <nitro/os/systemCall.h>
30 #include <nitro/mi/dma.h>
31 
32 //----------------------------------------------------------------
33 //      Interface created by Research & Engineering
34 //      Kept by request.
35 //      Comes here without being included in nitro-sdk/include/nitro/mi/dma.h.
36 //
37 
38 //----------------------------------------------------------------------
39 //                      DMA Setting
40 //----------------------------------------------------------------------
41 //#define SIMULATOR
42 #ifndef SIMULATOR
43 #define __MI_DmaSet(dmaNo, srcp, destp, dmaCntData)                       \
44 {                                                                    \
45     vu32 *dmaCntp = &((vu32 *)REG_DMA0SAD_ADDR)[dmaNo * 3];                  \
46     dmaCntp[0] = (vu32 )(srcp);                                      \
47     dmaCntp[1] = (vu32 )(destp);                                     \
48     dmaCntp[2] = (vu32 )(dmaCntData);                                \
49     {u32 dummy = dmaCntp[2];}                                        \
50     {u32 dummy = dmaCntp[2];}                                        \
51 }
52 #define __MI_DmaSetAsync(dmaNo, srcp, destp, dmaCntData)                  \
53 {                                                                    \
54     vu32 *dmaCntp = &((vu32 *)REG_DMA0SAD_ADDR)[dmaNo * 3];                  \
55     dmaCntp[0] = (vu32 )(srcp);                                      \
56     dmaCntp[1] = (vu32 )(destp);                                     \
57     dmaCntp[2] = (vu32 )(dmaCntData);                                \
58 }
59 #else
60 #define __MI_DmaSet(dmaNo, srcp, destp, dmaCntData)                       \
61 {                                                                    \
62     int    i;                                                        \
63     for (i=0; i<(dmaCntData & 0x1ffff); i++)                         \
64         if ((dmaCntData) & MI_DMA_SRC_FIX) {                            \
65             if ((dmaCntData) & MI_DMA_32BIT_BUS)                        \
66                     ((vu32 *)(destp))[i] = ((vu32 *)(srcp))[0];      \
67             else    ((vu16 *)(destp))[i] = ((vu16 *)(srcp))[0];      \
68          } else {                                                    \
69             if ((dmaCntData) & MI_DMA_32BIT_BUS)                        \
70                 ((vu32 *)(destp))[i] = ((vu32 *)(srcp))[i];          \
71             else    ((vu16 *)(destp))[i] = ((vu16 *)(srcp))[i];      \
72         }                                                            \
73 }
74 #define __MI_DmaSetAsync(dmaNo, srcp, destp, dmaCntData)                  \
75         __MI_DmaSet(     dmaNo, srcp, destp, dmaCntData)
76 #endif
77 
78 //- Set parameter in DMA controller.
79 //- When SIMULATER is defined, then simulation occurs on the CPU.
80 //  Enabled during situations such as debugging with GDB.
81 //- Finally, the "LDR" command is inserted to wait for DMA to start.
82 //
83 //Arguments:
84 //  dmaNo:       DMA number
85 //  srcp:        Source address
86 //  destp:       Destination address
87 //  dmaCntData:  Parameter data
88 //
89 //Note: When DMA is started by a program in the CPU internal RAM, the next instruction will be executed first
90 //
91 //  Therefore, if an attempt is made to change the transfer destination in the CPU immediately after starting DMA, the DMA transfer destination data sometimes becomes an unintended value because DMA starts up during read/write
92 //
93 //
94 //  In that case, the impact on subsequent code can be avoided by inserting WaitDma() immediately after, and checking if DMA has finished or not
95 //
96 
97 
98 //----------------------------------------------------------------------
99 //                      DMA Clear
100 //----------------------------------------------------------------------
101 
102 #define __MI_DmaClear(dmaNo, data, destp, size, bit)             \
103 {                                                           \
104     *(vu##bit *)HW_DMA_CLEAR_DATA_BUF = (vu##bit )(data);           \
105     __MI_DmaSet(dmaNo, HW_DMA_CLEAR_DATA_BUF, destp, (                  \
106         MI_DMA_ENABLE         | MI_DMA_TIMING_IMM |              \
107         MI_DMA_SRC_FIX        | MI_DMA_DEST_INC    |              \
108         MI_DMA_##bit##BIT_BUS | ((size)/(bit/8))));            \
109 }
110 
111 #define __MI_DmaClearIf(dmaNo, data, destp, size, bit)           \
112 {                                                           \
113     *(vu##bit *)DMA_CLEAR_DATA_BUF = (vu##bit )(data);       \
114     __MI_DmaSet(dmaNo, DMA_CLEAR_DATA_BUF, destp, (                \
115         MI_DMA_ENABLE         | MI_DMA_TIMING_IMM |              \
116         MI_DMA_IF_ENABLE      |                                \
117         MI_DMA_SRC_FIX        | MI_DMA_DEST_INC    |              \
118         MI_DMA_##bit##BIT_BUS | ((size)/(bit/8))));            \
119 }
120 
121 #define __MI_DmaClearArray(  dmaNo, data, destp, bit)            \
122     __MI_DmaClear(       dmaNo, data, destp, sizeof(destp), bit)
123 
124 #define MI_DmaClearArrayIf(dmaNo, data, destp, bit)            \
125     __MI_DmaClearIf(     dmaNo, data, destp, sizeof(destp), bit)
126 
127 //- Clear RAM with DMA
128 //- Clear data is put in stack, and that is copied to the destination.
129 //- When MI_DmaClearIf or MI_DmaClearArrayIf ends, they generate an interrupt request.
130 //- MI_DmaClearArray/MI_DmaClearArrayIf clears entire destination array.
131 //
132 //Arguments:
133 //  dmaNo:       DMA number
134 //  data:        Clear data
135 //  destp:       Destination address
136 //  size:        Number of cleared bytes
137 //  bit:         Transfer bit width (16|32)
138 //
139 //
140 //Note: When DMA is started by a program in the CPU internal RAM, the next instruction will be executed first
141 //
142 //  Therefore, if an attempt is made to change the transfer destination in the CPU immediately after starting DMA, the DMA transfer destination data sometimes becomes an unintended value because DMA starts up during read/write
143 //
144 //
145 //  In that case, the impact on subsequent code can be avoided by inserting WaitDma() immediately after, and checking if DMA has finished or not
146 //
147 
148 //----------------------------------------------------------------------
149 //                      DMA Copy
150 //----------------------------------------------------------------------
151 
152 #define __MI_DmaCopy(dmaNo, srcp, destp, size, bit)              \
153                                                             \
154     __MI_DmaSet(dmaNo, srcp, destp,  (                           \
155         MI_DMA_ENABLE         | MI_DMA_TIMING_IMM |              \
156         MI_DMA_SRC_INC        | MI_DMA_DEST_INC    |              \
157         MI_DMA_##bit##BIT_BUS | ((size)/((bit)/8))))
158 
159 #define __MI_DmaCopyIf(dmaNo, srcp, destp, size, bit)            \
160                                                             \
161     __MI_DmaSet(dmaNo, srcp, destp,  (                           \
162         MI_DMA_ENABLE         | MI_DMA_TIMING_IMM |              \
163         MI_DMA_IF_ENABLE      |                                \
164         MI_DMA_SRC_INC        | MI_DMA_DEST_INC    |              \
165         MI_DMA_##bit##BIT_BUS | ((size)/(bit/8))))
166 
167 #define __MI_DmaCopyArray(  dmaNo, srcp, destp, bit)             \
168     __MI_DmaCopy(       dmaNo, srcp, destp, sizeof(srcp), bit)
169 
170 #define __MI_DmaCopyArrayIf(dmaNo, srcp, destp, bit)             \
171     __MI_DmaCopyIf(     dmaNo, srcp, destp, sizeof(srcp), bit)
172 
173 //- Copy using DMA.
174 //- When MI_DmaCopyIf or MI_DmaCopyArrayIf ends, they generate an interrupt request.
175 //- MI_DmaCopyArray/MI_DmaCopyArrayIf copy the entire source array.
176 //
177 //Arguments:
178 //  dmaNo:       DMA number
179 //  srcp:        Source address
180 //  destp:       Destination address
181 //  size:        Number of transfer bytes
182 //  bit:         Transfer bit width (16|32)
183 //
184 //
185 //Note: When DMA is started by a program in the CPU internal RAM, the next instruction will be executed first
186 //
187 //  Therefore, if an attempt is made to change the transfer destination in the CPU immediately after starting DMA, the DMA transfer destination data sometimes becomes an unintended value because DMA starts up during read/write
188 //
189 //
190 //  In that case, the impact on subsequent code can be avoided by inserting WaitDma() immediately after, and checking if DMA has finished or not
191 //
192 
193 //----------------------------------------------------------------------
194 //                  H-Blank DMA Copy
195 //----------------------------------------------------------------------
196 
197 #define __MI_H_DmaCopy(dmaNo, srcp, destp, size, bit)            \
198                                                             \
199     __MI_DmaSet(dmaNo, srcp, destp,  (                           \
200         MI_DMA_ENABLE         | MI_DMA_TIMING_H_BLANK |          \
201         MI_DMA_SRC_INC        | MI_DMA_DEST_RELOAD     |          \
202         MI_DMA_CONTINUOUS_ON  |                                \
203         MI_DMA_##bit##BIT_BUS | ((size)/((bit)/8))))
204 
205 #define __MI_H_DmaCopyIf(dmaNo, srcp, destp, size, bit)          \
206                                                             \
207     __MI_DmaSet(dmaNo, srcp, destp,  (                           \
208         MI_DMA_ENABLE         | MI_DMA_TIMING_H_BLANK |          \
209         MI_DMA_IF_ENABLE      |                                \
210         MI_DMA_SRC_INC        | MI_DMA_DEST_RELOAD     |          \
211         MI_DMA_CONTINUOUS_ON  |                                \
212         MI_DMA_##bit##BIT_BUS | ((size)/(bit/8))))
213 
214 #define __MI_H_DmaCopyArray(  dmaNo, srcp, destp, bit)           \
215     __MI_H_DmaCopy(       dmaNo, srcp, destp, sizeof(srcp), bit)
216 
217 #define __MI_H_DmaCopyArrayIf(dmaNo, srcp, destp, bit)           \
218     __MI_H_DmaCopyIf(     dmaNo, srcp, destp, sizeof(srcp), bit)
219 
220 //- Synchronizes with H-Blank and copies using DMA.
221 //- When MI_H_DmaCopyIf or MI_H_DmaCopyArrayIf ends, they generate an interrupt request.
222 //- MI_H_DmaCopyArray or MI_H_DmaCopyArrayIf copies the entire source array.
223 //
224 //Arguments:
225 //  dmaNo:       DMA number
226 //  srcp:        Source address
227 //  destp:       Destination address
228 //  size:        Number of transfer bytes
229 //  bit:         Transfer bit width (16|32)
230 
231 //----------------------------------------------------------------------
232 //                  V-Blank DMA Copy
233 //----------------------------------------------------------------------
234 
235 #define __MI_V_DmaCopy(dmaNo, srcp, destp, size, bit)            \
236                                                             \
237     __MI_DmaSet(dmaNo, srcp, destp,  (                           \
238         MI_DMA_ENABLE         | MI_DMA_TIMING_V_BLANK |          \
239         MI_DMA_SRC_INC        | MI_DMA_DEST_INC        |          \
240         MI_DMA_##bit##BIT_BUS | ((size)/(bit/8))))
241 
242 #define __MI_V_DmaCopyIf(dmaNo, srcp, destp, size, bit)          \
243                                                             \
244     __MI_DmaSet(dmaNo, srcp, destp,  (                           \
245         MI_DMA_ENABLE         | MI_DMA_TIMING_V_BLANK |          \
246         MI_DMA_IF_ENABLE      |                                \
247         MI_DMA_SRC_INC        | MI_DMA_DEST_INC        |          \
248         MI_DMA_##bit##BIT_BUS | ((size)/(bit/8))))
249 
250 #define __MI_V_DmaCopyArray(  dmaNo, srcp, destp, bit)           \
251     __MI_V_DmaCopy(       dmaNo, srcp, destp, sizeof(srcp), bit)
252 
253 #define __MI_V_DmaCopyArrayIf(dmaNo, srcp, destp, bit)           \
254     __MI_V_DmaCopyIf(     dmaNo, srcp, destp, sizeof(srcp), bit)
255 
256 //- Synchronizes with V-Blank and copies using DMA.
257 //- When MI_V_DmaCopyIf or MI_V_DmaCopyArrayIf ends, they generate an interrupt request.
258 //- MI_V_DmaCopyArray or MI_V_DmaCopyArrayIf copies entire source array.
259 //
260 //Arguments:
261 //  dmaNo:       DMA number
262 //  srcp:        Source address
263 //  destp:       Destination address
264 //  size:        Number of transfer bytes
265 //  bit:         Transfer bit width (16|32)
266 
267 //----------------------------------------------------------------------
268 //                  Main Memory Display DMA
269 //----------------------------------------------------------------------
270 
271 #define __MI_DmaDispMainmem(dmaNo, srcp)                         \
272                                                             \
273     __MI_DmaSet(dmaNo, srcp, REG_DISP_MMEM_FIFO_ADDR,  (              \
274         MI_DMA_ENABLE         | MI_DMA_TIMING_DISP_MMEM |        \
275         MI_DMA_SRC_INC        | MI_DMA_DEST_FIX          |        \
276 		MI_DMA_CONTINUOUS_ON  |								\
277         MI_DMA_32BIT_BUS      | (4)))
278 
279 //- Performs a DMA transfer to display an image that is in main memory.
280 //
281 //Arguments:
282 //  dmaNo:       DMA number
283 //  srcp:        Source address
284 
285 //----------------------------------------------------------------------
286 //                  Geometry FIFO-DMA
287 //----------------------------------------------------------------------
288 
289 #define __MI_GX_Dma(dmaNo, srcp, length)                         \
290                                                             \
291     __MI_DmaSetAsync(dmaNo, srcp, REG_GXFIFO_ADDR,  (                 \
292         MI_DMA_ENABLE         | MI_DMA_TIMING_GXFIFO  |          \
293         MI_DMA_SRC_INC        | MI_DMA_DEST_FIX        |          \
294         MI_DMA_32BIT_BUS      | (length)))
295 
296 #define __MI_GX_DmaIf(dmaNo, srcp, length)                       \
297                                                             \
298     __MI_DmaSetAsync(dmaNo, srcp, REG_GXFIFO_ADDR  (                 \
299         MI_DMA_ENABLE         | MI_DMA_TIMING_GXFIFO  |          \
300         MI_DMA_IF_ENABLE      |                                \
301         MI_DMA_SRC_INC        | MI_DMA_DEST_FIX        |          \
302         MI_DMA_32BIT_BUS      | (length)))
303 
304 #define __MI_GX_DmaFast(dmaNo, srcp, length)                     \
305                                                             \
306     __MI_DmaSetAsync(dmaNo, srcp, REG_GXFIFO_ADDR,  (                 \
307         MI_DMA_ENABLE         | MI_DMA_TIMING_IMM     |          \
308         MI_DMA_SRC_INC        | MI_DMA_DEST_FIX        |          \
309         MI_DMA_32BIT_BUS      | (length)))
310 
311 #define __MI_GX_DmaFastIf(dmaNo, srcp, length)                   \
312                                                             \
313     __MI_DmaSetAsync(dmaNo, srcp, REG_GXFIFO_ADDR,  (                 \
314         DMA_ENABLE         | DMA_TIMING_IMM     |          \
315         DMA_IF_ENABLE      |                                \
316         DMA_SRC_INC        | DMA_DEST_FIX        |          \
317         DMA_32BIT_BUS      | (length)))
318 
319 #define __MI_GX_DmaArray(  dmaNo, srcp, destp, bit)              \
320     __MI_GX_Dma(  dmaNo, srcp, destp, sizeof(srcp), bit)
321 
322 #define __MI_GX_DmaArrayIf(dmaNo, srcp, destp, bit)              \
323     __MI_GX_DmaIf(dmaNo, srcp, destp, sizeof(srcp), bit)
324 
325 #define __MI_GX_DmaArrayFast(  dmaNo, srcp, destp, bit)          \
326     __MI_GX_DmaFast(  dmaNo, srcp, destp, sizeof(srcp), bit)
327 
328 #define __MI_GX_DmaArrayFastIf(dmaNo, srcp, destp, bit)          \
329     __MI_GX_DmaFastIf(dmaNo, srcp, destp, sizeof(srcp), bit)
330 
331 //- Copies using DMA by request from geometry FIFO.
332 //- MI_GX_DmaIf, MI_GX_DmaArrayIf, MI_GX_DmaFastIf, or MI_GX_DmaArrayFastIf generate interrupt requests when ending.
333 //
334 //- MI_GX_DmaArray, MI_GX_DmaArrayIf, MI_GX_DmaArrayFast, and MI_GX_DmaArrayFastIf copy the entire source array.
335 //
336 //
337 //Arguments:
338 //  dmaNo:       DMA number
339 //  srcp:        Source address
340 //  size:        Number of transfer bytes
341 
342 
343 //----------------------------------------------------------------------
344 //                      Wait for DMA End
345 //----------------------------------------------------------------------
346 
347 #define __MI_WaitDma(dmaNo)                                      \
348 {                                                           \
349     vu32 *(dmaCntp) = &((vu32 *)REG_DMA0SAD_ADDR)[dmaNo * 3];       \
350     while (dmaCntp[2] & MI_DMA_ENABLE) ;                       \
351 }
352 
353 //- Wait for end of DMA
354 //
355 //Arguments:
356 //  dmaNo:       DMA number
357 
358 
359 //----------------------------------------------------------------------
360 //                      DMA Stop
361 //----------------------------------------------------------------------
362 
363 #define __MI_StopDma(dmaNo)                                      \
364 {                                                           \
365     vu16* dmaCntp = &((vu16 *)REG_DMA0SAD_ADDR)[dmaNo * 6];       \
366     dmaCntp[5] &= ~((MI_DMA_TIMING_MASK | MI_DMA_CONTINUOUS_ON)  \
367                    >> 16);                                  \
368     dmaCntp[5] &= ~( MI_DMA_ENABLE   >> 16);                   \
369     {u32 dummy = dmaCntp[5];}                               \
370     {u32 dummy = dmaCntp[5];}                               \
371 }
372 
373 //- Stops DMA.
374 //- However, DMA runs only once if automatically started during processing.
375 //
376 //Arguments:
377 //  dmaNo:       DMA number
378 
379 
380 //----------------------------------------------------------------------
381 //                      CPU Clear
382 //----------------------------------------------------------------------
383 
384 #define __MI_CpuClear(data, destp, size, bit)    UTL_CpuClear##bit(data, (void *)(destp), size)
385 
386 #define __MI_CpuClearArray(data, destp, bit)                     \
387     __MI_CpuClear(     data, destp, sizeof(destp), bit)
388 
389 //- Calls system call that does RAM clear on CPU.
390 //- Clear data is put in stack, and that is copied to the destination.
391 //- CpuClearArray clears entire destination array.
392 //
393 //Arguments:
394 //  data:        Clear data
395 //  destp:       Destination address
396 //  size:        Number of cleared bytes
397 //  bit:         Transfer bit width (16|32)
398 
399 //----------------------------------------------------------------------
400 //                      CPU Copy
401 //----------------------------------------------------------------------
402 
403 #define __MI_CpuCopy(srcp, destp, size, bit)    UTL_CpuCopy##bit((void *)(srcp), (void *)(destp), size)
404 
405 #define __MI_CpuCopyArray(srcp, destp, bit)                      \
406     __MI_CpuCopy(     srcp, destp, sizeof(srcp), bit)
407 
408 //- Calls system call that does copy on CPU.
409 //- CpuCopyArray copies entire source array.
410 //
411 //Arguments:
412 //  srcp:        Source address
413 //  destp:       Destination address
414 //  size:        Number of transfer bytes
415 //  bit:         Transfer bit width (16|32)
416 
417 //----------------------------------------------------------------------
418 //                  CPU High-speed Clear (32Byte units)
419 //----------------------------------------------------------------------
420 
421 #define __MI_CpuClearFast(data, destp, size)  UTL_CpuClearFast(data, (void *)(destp), size)
422 
423 #define MI_CpuClearArrayFast(data, destp)                      \
424     __MI_CpuClearFast(     data, destp, sizeof(destp))
425 
426 //- Calls a system call that rapidly clears RAM in the CPU.
427 //- Clear data is put in stack, and that is copied to the destination.
428 //- CpuClearArrayFast clears entire destination array.
429 //
430 //Arguments:
431 //  data:        Clear data
432 //  destp:       Destination address
433 //  size:        Number of cleared bytes
434 
435 //----------------------------------------------------------------------
436 //                  CPU High-speed Copy (32Byte unit)
437 //----------------------------------------------------------------------
438 
439 #define __MI_CpuCopyFast(srcp, destp, size)   UTL_CpuCopyFast((void *)(srcp), (void *)(destp), size)
440 
441 
442 #define MI_CpuCopyArrayFast(srcp, destp)                       \
443     __MI_CpuCopyFast(     srcp, destp, sizeof(srcp))
444 
445 //- Calls a system call that rapidly copies in the CPU.
446 //- CpuCopyArrayFast copies entire source array.
447 //
448 //Arguments:
449 //  srcp:        Source address
450 //  destp:       Destination address
451 //  size:        Number of transfer bytes
452 
453 
454 
455 
456 
457 #ifdef __cplusplus
458 } /* extern "C" */
459 #endif
460 
461 /* NITRO_MI_DMA_RED_H_ */
462 #endif
463