1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - MI
3   File:     mi_dma.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 #ifndef NITRO_COMMON_MI_DMA_H_
18 #define NITRO_COMMON_MI_DMA_H_
19 
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23 
24 #include <nitro.h>
25 
26 //================================================================================
27 //          DMA system work
28 //================================================================================
29 #ifdef SDK_ARM9
30 # ifdef SDK_TS
31 #  define MIi_DMA_CLEAR_DATA_BUF    REG_DMA0_CLR_DATA_ADDR      // ARM9-TS:  defined ARM9/ioreg_MI.h
32 # else
33 #  define MIi_DMA_CLEAR_DATA_BUF    HW_DMA_CLEAR_DATA_BUF       // ARM9-TEG: defined common/mmap_shared.h
34 # endif
35 #else  // ifdef SDK_ARM9
36 # define MIi_DMA_CLEAR_DATA_BUF     HW_PRV_WRAM_DMA_CLEAR_DATA_BUF      // ARM7:  defined ARM7/mmap_wram.h
37 #endif // ifdef SDK_ARM9
38 
39 typedef union
40 {
41     u32     b32;
42     u16     b16;
43 }
44 MIiDmaClearSrc;
45 
46 //================================================================================
47 //          setting DMA
48 //================================================================================
49 //---------------- set parameters
50 #ifdef SDK_ARM9
51 
52 void    MIi_DmaSetParams(u32 dmaNo, u32 src, u32 dest, u32 ctrl);
53 void    MIi_DmaSetParams_wait(u32 dmaNo, u32 src, u32 dest, u32 ctrl);
54 void    MIi_DmaSetParams_noInt(u32 dmaNo, u32 src, u32 dest, u32 ctrl);
55 void    MIi_DmaSetParams_wait_noInt(u32 dmaNo, u32 src, u32 dest, u32 ctrl);
56 
57 #else  // ifdef SDK_ARM9
MIi_DmaSetParams(u32 dmaNo,u32 src,u32 dest,u32 ctrl)58 static inline void MIi_DmaSetParams(u32 dmaNo, u32 src, u32 dest, u32 ctrl)
59 {
60     OSIntrMode enabled = OS_DisableInterrupts();
61     vu32   *p = (vu32 *)((u32)REG_DMA0SAD_ADDR + dmaNo * 12);
62     *p = (vu32)src;
63     *(p + 1) = (vu32)dest;
64     *(p + 2) = (vu32)ctrl;
65     (void)OS_RestoreInterrupts(enabled);
66 }
67 
MIi_DmaSetParams_wait(u32 dmaNo,u32 src,u32 dest,u32 ctrl)68 static inline void MIi_DmaSetParams_wait(u32 dmaNo, u32 src, u32 dest, u32 ctrl)
69 {
70     OSIntrMode enabled = OS_DisableInterrupts();
71     vu32   *p = (vu32 *)((u32)REG_DMA0SAD_ADDR + dmaNo * 12);
72     *p = (vu32)src;
73     *(p + 1) = (vu32)dest;
74     *(p + 2) = (vu32)ctrl;
75 
76     // ARM7 must wait 2 cycle (load is 3 cycle)
77     {
78         u32     dummy = reg_MI_DMA0SAD;
79     }
80 
81     (void)OS_RestoreInterrupts(enabled);
82 }
83 
MIi_DmaSetParams_noInt(u32 dmaNo,u32 src,u32 dest,u32 ctrl)84 static inline void MIi_DmaSetParams_noInt(u32 dmaNo, u32 src, u32 dest, u32 ctrl)
85 {
86     vu32   *p = (vu32 *)((u32)REG_DMA0SAD_ADDR + dmaNo * 12);
87     *p = (vu32)src;
88     *(p + 1) = (vu32)dest;
89     *(p + 2) = (vu32)ctrl;
90 }
91 
MIi_DmaSetParams_wait_noInt(u32 dmaNo,u32 src,u32 dest,u32 ctrl)92 static inline void MIi_DmaSetParams_wait_noInt(u32 dmaNo, u32 src, u32 dest, u32 ctrl)
93 {
94     vu32   *p = (vu32 *)((u32)REG_DMA0SAD_ADDR + dmaNo * 12);
95     *p = (vu32)src;
96     *(p + 1) = (vu32)dest;
97     *(p + 2) = (vu32)ctrl;
98 
99     // ARM7 must wait 2 cycle (load is 3 cycle)
100     {
101         u32     dummy = reg_MI_DMA0SAD;
102     }
103 }
104 #endif
105 
106 
MIi_DmaSetParams_src32(u32 dmaNo,u32 data,u32 dest,u32 ctrl)107 static inline void MIi_DmaSetParams_src32(u32 dmaNo, u32 data, u32 dest, u32 ctrl)
108 {
109     OSIntrMode enabled = OS_DisableInterrupts();
110 
111     MIiDmaClearSrc *srcp = (MIiDmaClearSrc *) ((u32)MIi_DMA_CLEAR_DATA_BUF + dmaNo * 4);
112     srcp->b32 = data;
113     MIi_DmaSetParams_noInt(dmaNo, (u32)srcp, dest, ctrl);
114 
115     (void)OS_RestoreInterrupts(enabled);
116 }
117 
MIi_DmaSetParams_src16(u32 dmaNo,u16 data,u32 dest,u32 ctrl)118 static inline void MIi_DmaSetParams_src16(u32 dmaNo, u16 data, u32 dest, u32 ctrl)
119 {
120     OSIntrMode enabled = OS_DisableInterrupts();
121 
122     MIiDmaClearSrc *srcp = (MIiDmaClearSrc *) ((u32)MIi_DMA_CLEAR_DATA_BUF + dmaNo * 4);
123     srcp->b16 = data;
124     MIi_DmaSetParams_noInt(dmaNo, (u32)srcp, dest, ctrl);
125 
126     (void)OS_RestoreInterrupts(enabled);
127 }
128 
MIi_DmaSetParams_wait_src32(u32 dmaNo,u32 data,u32 dest,u32 ctrl)129 static inline void MIi_DmaSetParams_wait_src32(u32 dmaNo, u32 data, u32 dest, u32 ctrl)
130 {
131     OSIntrMode enabled = OS_DisableInterrupts();
132 
133     MIiDmaClearSrc *srcp = (MIiDmaClearSrc *) ((u32)MIi_DMA_CLEAR_DATA_BUF + dmaNo * 4);
134     srcp->b32 = data;
135     MIi_DmaSetParams_wait_noInt(dmaNo, (u32)srcp, dest, ctrl);
136 
137     (void)OS_RestoreInterrupts(enabled);
138 }
139 
MIi_DmaSetParams_wait_src16(u32 dmaNo,u16 data,u32 dest,u32 ctrl)140 static inline void MIi_DmaSetParams_wait_src16(u32 dmaNo, u16 data, u32 dest, u32 ctrl)
141 {
142     OSIntrMode enabled = OS_DisableInterrupts();
143 
144     MIiDmaClearSrc *srcp = (MIiDmaClearSrc *) ((u32)MIi_DMA_CLEAR_DATA_BUF + dmaNo * 4);
145     srcp->b16 = data;
146     MIi_DmaSetParams_wait_noInt(dmaNo, (u32)srcp, dest, ctrl);
147 
148     (void)OS_RestoreInterrupts(enabled);
149 }
150 
151 //================================================================================
152 //          CALLBACK
153 //================================================================================
154 extern void OSi_EnterDmaCallback(u32 dmaNo, MIDmaCallback callback, void *arg);
155 
MIi_CallCallback(MIDmaCallback callback,void * arg)156 static inline void MIi_CallCallback(MIDmaCallback callback, void *arg)
157 {
158     if (callback)
159     {
160         (callback) (arg);
161     }
162 }
163 
164 //================================================================================
165 //          WAIT
166 //================================================================================
167 //----------------------------------------------------------------
168 //     for waiting DMA busy
169 #define MIi_Wait_BeforeDMA( dmaCntp, dmaNo )                  \
170     do {                                                      \
171       dmaCntp = &((vu32*)REG_DMA0SAD_ADDR)[dmaNo * 3 + 2];    \
172       MIi_ASSERT_DMANO( dmaNo );                              \
173       while ( *dmaCntp & REG_MI_DMA0CNT_E_MASK ) {}           \
174     }while(0)
175 
176 #define MIi_Wait_AfterDMA( dmaCntp )                          \
177     do {                                                      \
178       while ( *dmaCntp & REG_MI_DMA0CNT_E_MASK ) {}           \
179     }while(0)
180 
181 
182 //================================================================================
183 //         ASSERT
184 //================================================================================
185 #define MIi_ASSERT_DMANO( dmaNo )        SDK_ASSERTMSG( (dmaNo) <= MI_DMA_MAX_NUM, "illegal DMA No." )
186 #define MIi_ASSERT_MUL2( size )          SDK_ASSERTMSG( ((size) & 1) == 0, "size & 1 must be 0" )
187 #define MIi_ASSERT_MUL4( size )          SDK_ASSERTMSG( ((size) & 3) == 0, "size & 3 must be 0" )
188 #define MIi_ASSERT_SRC_ALIGN512( src )   SDK_ASSERTMSG( ((u32)(src) & 511) == 0, "source address must be in 512-byte alignment" )
189 #define MIi_ASSERT_SRC_ALIGN4( src )     SDK_ASSERTMSG( ((u32)(src) & 3) == 0, "source address must be in 4-byte alignment" )
190 #define MIi_ASSERT_SRC_ALIGN2( src )     SDK_ASSERTMSG( ((u32)(src) & 1) == 0, "source address must be in 2-byte alignment" )
191 #define MIi_ASSERT_DEST_ALIGN4( dest )   SDK_ASSERTMSG( ((u32)(dest) & 3) == 0, "destination address must be in 4-byte alignment" )
192 #define MIi_ASSERT_DEST_ALIGN2( dest )   SDK_ASSERTMSG( ((u32)(dest) & 1) == 0, "destination address must be in 2-byte alignment" )
193 
194 #ifdef SDK_ARM9
195 #  define MIi_ASSERT_SIZE( dmaNo, size ) SDK_ASSERTMSG( (size) <= 0x1fffff, "size too large" );
196 #else  //SDK_ARM7
197 #  define MIi_ASSERT_SIZE( dmaNo, size )                        \
198     do{                                                         \
199         if ( dmaNo <= 2 )                                       \
200         {                                                       \
201             SDK_ASSERTMSG( (size) <= 0x3fff, "size too large" );\
202         }                                                       \
203         else                                                    \
204         {                                                       \
205             SDK_ASSERTMSG( (size) <= 0xffff, "size too large" );\
206         }                                                       \
207     } while(0)
208 #endif
209 
210 
211 //================================================================================
212 //         CHECK
213 //================================================================================
214 //----------------------------------------------------------------
215 //      Check if specified area is in ITCM/DTCM.
216 //
217 #if defined( SDK_ARM9 ) && defined( SDK_DEBUG )
218 void    MIi_CheckAddressInTCM(u32 addr, u32 size);
219 #define MIi_WARNING_ADDRINTCM( addr, size )  MIi_CheckAddressInTCM( (u32)addr, (u32)size )
220 #else
221 #define MIi_WARNING_ADDRINTCM( addr, size )  ((void)0)
222 #endif
223 
224 
225 //----------------------------------------------------------------
226 //      for DMA check
227 //      (must avoid multiple auto start DMA)
228 //
229 #ifdef SDK_ARM9
230 void    MIi_CheckAnotherAutoDMA(u32 dmaNo, u32 dmaType);
231 #endif
232 
233 //----------------------------------------------------------------
234 //      for DMA0 check
235 //       Source address which is in I/O register or cartridge bus
236 //       is not available.
237 void    MIi_CheckDma0SourceAddress(u32 dmaNo, u32 src, u32 size, u32 dir);
238 
239 //================================================================================
240 //           dummy DMA for multi DMA problem
241 //================================================================================
242 #define MIi_DUMMY_DMA_NO   0
243 #define MIi_DUMMY_SRC      0
244 #define MIi_DUMMY_DEST     0
245 #define MIi_DUMMY_CNT      ( MI_DMA_ENABLE | MI_DMA_SRC_FIX | MI_DMA_DEST_FIX | MI_DMA_16BIT_BUS | 1 )
246 
247 #ifdef __cplusplus
248 } /* extern "C" */
249 #endif
250 
251 /* MI_COMMON_MI_DMA_H_ */
252 #endif
253