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