1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - MI
3 File: mi_dma_gxcommand.c
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-10-16#$
14 $Rev: 8957 $
15 $Author: yada $
16 *---------------------------------------------------------------------------*/
17
18 #ifdef SDK_ARM9
19 #include <nitro.h>
20 #include "../include/mi_dma.h"
21
22 //---- flagmental DMA size
23 #define MIi_GX_LENGTH_ONCE (118 * sizeof(u32)) //(byte)
24
25 //---- fmagment DMA parameters
26 typedef struct
27 {
28 volatile BOOL isBusy;
29
30 u32 dmaNo;
31 u32 src;
32 u32 length;
33 MIDmaCallback callback;
34 void *arg;
35
36 GXFifoIntrCond fifoCond;
37 void (*fifoFunc) (void);
38 }
39 MIiGXDmaParams;
40
41 static MIiGXDmaParams MIi_GXDmaParams = { FALSE };
42
43 static void MIi_FIFOCallback(void);
44 static void MIi_DMACallback(void *);
45 static void MIi_DMAFastCallback(void *);
46
47 //================================================================================
48 // not use auto-DMA
49 //================================================================================
50 /*---------------------------------------------------------------------------*
51 Name: MI_SendGXCommand
52
53 Description: send GX command with geometry FIFO DMA.
54 sync version.
55 send data with small fragmental DMA, so DMA autostart may not occur.
56
57 Arguments: dmaNo : DMA channel No.
58 src : source address
59 commandLength : GX command length. (byte)
60
61 Returns: None
62 *---------------------------------------------------------------------------*/
63 #include <nitro/itcm_begin.h>
MI_SendGXCommand(u32 dmaNo,const void * src,u32 commandLength)64 void MI_SendGXCommand(u32 dmaNo, const void *src, u32 commandLength)
65 {
66 vu32 *dmaCntp;
67 u32 leftLength = commandLength;
68 u32 currentSrc = (u32)src;
69
70 MIi_ASSERT_DMANO(dmaNo);
71 MIi_ASSERT_SRC_ALIGN4(src);
72 MIi_WARNING_ADDRINTCM(src, commandLength);
73
74 if (leftLength == 0)
75 {
76 return;
77 }
78
79 //---- check DMA0 source address
80 MIi_CheckDma0SourceAddress(dmaNo, (u32)src, commandLength, MI_DMA_SRC_INC);
81
82 MIi_Wait_BeforeDMA(dmaCntp, dmaNo);
83 while (leftLength > 0)
84 {
85 u32 length = (leftLength > MIi_GX_LENGTH_ONCE) ? MIi_GX_LENGTH_ONCE : leftLength;
86 MIi_DmaSetParameters(dmaNo, currentSrc, (u32)REG_GXFIFO_ADDR, MI_CNT_SEND32(length), 0);
87 leftLength -= length;
88 currentSrc += length;
89 }
90 MIi_Wait_AfterDMA(dmaCntp);
91 }
92
93 #include <nitro/itcm_end.h>
94
95 /*---------------------------------------------------------------------------*
96 Name: MI_SendGXCommandAsync
97
98 Description: send GX command with geometry FIFO DMA.
99 async version.
100 send data with small fragmental DMA, so DMA autostart may not occur.
101
102 Arguments: dmaNo : DMA channel No.
103 src : source address
104 commandLength : GX command length. (byte)
105 callback : callback function
106 arg : callback argument
107
108 Returns: None
109 *---------------------------------------------------------------------------*/
MI_SendGXCommandAsync(u32 dmaNo,const void * src,u32 commandLength,MIDmaCallback callback,void * arg)110 void MI_SendGXCommandAsync(u32 dmaNo, const void *src, u32 commandLength, MIDmaCallback callback,
111 void *arg)
112 {
113 MIi_ASSERT_DMANO(dmaNo);
114 MIi_ASSERT_SRC_ALIGN4(src);
115 MIi_WARNING_ADDRINTCM(src, commandLength);
116
117 //---- if size==0, call callback immediately
118 if (commandLength == 0)
119 {
120 MIi_CallCallback(callback, arg);
121 return;
122 }
123
124 //---- wait till other task end
125 while (MIi_GXDmaParams.isBusy /*volatile valiable */ )
126 {
127 }
128
129 //---- wait till geometryEngine FIFO is underhalf
130 while (!(G3X_GetCommandFifoStatus() & GX_FIFOSTAT_UNDERHALF))
131 {
132 }
133
134 //---- fragmental DMA params
135 MIi_GXDmaParams.isBusy = TRUE;
136 MIi_GXDmaParams.dmaNo = dmaNo;
137 MIi_GXDmaParams.src = (u32)src;
138 MIi_GXDmaParams.length = commandLength;
139 MIi_GXDmaParams.callback = callback;
140 MIi_GXDmaParams.arg = arg;
141
142 //---- check DMA0 source address
143 MIi_CheckDma0SourceAddress(dmaNo, (u32)src, commandLength, MI_DMA_SRC_INC);
144
145 MI_WaitDma(dmaNo);
146 {
147 OSIntrMode enabled = OS_DisableInterrupts();
148
149 //---- remember FIFO interrupt setting
150 MIi_GXDmaParams.fifoCond = (GXFifoIntrCond)((reg_G3X_GXSTAT & REG_G3X_GXSTAT_FI_MASK) >> REG_G3X_GXSTAT_FI_SHIFT);
151 MIi_GXDmaParams.fifoFunc = OS_GetIrqFunction(OS_IE_GXFIFO);
152
153 //---- set FIFO interrupt
154 G3X_SetFifoIntrCond(GX_FIFOINTR_COND_UNDERHALF);
155 OS_SetIrqFunction(OS_IE_GXFIFO, MIi_FIFOCallback);
156 (void)OS_EnableIrqMask(OS_IE_GXFIFO);
157
158 MIi_FIFOCallback();
159
160 (void)OS_RestoreInterrupts(enabled);
161 }
162 }
163
164 /*---------------------------------------------------------------------------*
165 Name: MIi_FIFOCallback
166
167 Description: callback for GX FIFO
168 (used for MI_SendGXCommandAsync)
169 Arguments: None
170
171 Returns: None
172 *---------------------------------------------------------------------------*/
MIi_FIFOCallback(void)173 static void MIi_FIFOCallback(void)
174 {
175 u32 length;
176 u32 src;
177
178 if (MIi_GXDmaParams.length == 0)
179 {
180 return;
181 }
182
183 //---- parameters for this fragment
184 length = (MIi_GXDmaParams.length >= MIi_GX_LENGTH_ONCE) ? MIi_GX_LENGTH_ONCE : MIi_GXDmaParams.length;
185 src = MIi_GXDmaParams.src;
186
187 //---- arrange fragmental DMA params
188 MIi_GXDmaParams.length -= length;
189 MIi_GXDmaParams.src += length;
190
191 //---- start fragmental DMA. if last, set DMA callback
192 if (MIi_GXDmaParams.length == 0)
193 {
194 OSi_EnterDmaCallback(MIi_GXDmaParams.dmaNo, MIi_DMACallback, NULL);
195 MIi_DmaSetParameters(MIi_GXDmaParams.dmaNo, src, (u32)REG_GXFIFO_ADDR, MI_CNT_SEND32_IF(length), 0);
196 (void)OS_ResetRequestIrqMask(OS_IE_GXFIFO);
197 }
198 else
199 {
200 MIi_DmaSetParameters(MIi_GXDmaParams.dmaNo, src, (u32)REG_GXFIFO_ADDR, MI_CNT_SEND32(length), 0);
201 (void)OS_ResetRequestIrqMask(OS_IE_GXFIFO);
202 }
203 }
204
205 /*---------------------------------------------------------------------------*
206 Name: MIi_DMACallback
207
208 Description: callback for DMA
209 (used for MI_SendGXCommandAsync)
210
211 Arguments: not use
212
213 Returns: None
214 *---------------------------------------------------------------------------*/
MIi_DMACallback(void *)215 static void MIi_DMACallback(void *)
216 {
217 (void)OS_DisableIrqMask(OS_IE_GXFIFO);
218
219 //---- restore FIFO interrupt setting
220 G3X_SetFifoIntrCond(MIi_GXDmaParams.fifoCond);
221 OS_SetIrqFunction(OS_IE_GXFIFO, MIi_GXDmaParams.fifoFunc);
222
223 MIi_GXDmaParams.isBusy = FALSE;
224
225 MIi_CallCallback(MIi_GXDmaParams.callback, MIi_GXDmaParams.arg);
226 }
227
228 //================================================================================
229 // use auto-DMA
230 //================================================================================
231 /*---------------------------------------------------------------------------*
232 Name: MI_SendGXCommandFast
233
234 Description: send GX command with geometry FIFO DMA.
235 sync version.
236 send data at once, so DMA autostart may occur.
237
238 Arguments: dmaNo : DMA channel No.
239 src : source address
240 commandLength : GX command length. (byte)
241
242 Returns: None
243 *---------------------------------------------------------------------------*/
244 #include <nitro/itcm_begin.h>
MI_SendGXCommandFast(u32 dmaNo,const void * src,u32 commandLength)245 void MI_SendGXCommandFast(u32 dmaNo, const void *src, u32 commandLength)
246 {
247 vu32 *dmaCntp;
248
249 MIi_ASSERT_DMANO(dmaNo);
250 MIi_ASSERT_SRC_ALIGN4(src);
251 MIi_WARNING_ADDRINTCM(src, commandLength);
252
253 if (commandLength == 0)
254 {
255 return;
256 }
257
258 MIi_Wait_BeforeDMA(dmaCntp, dmaNo);
259 MIi_DmaSetParameters(dmaNo, (u32)src, (u32)REG_GXFIFO_ADDR, MI_CNT_GXCOPY(commandLength), 0);
260 MIi_Wait_AfterDMA(dmaCntp);
261 }
262
263 #include <nitro/itcm_end.h>
264
265 /*---------------------------------------------------------------------------*
266 Name: MI_SendGXCommandAsyncFast
267
268 Description: send GX command with geometry FIFO DMA.
269 async version.
270 send data at once, so DMA autostart may occur.
271
272 Arguments: dmaNo : DMA channel No.
273 src : source address
274 commandLength : GX command length. (byte)
275 callback : callback function
276 arg : callback argument
277
278 Returns: None
279 *---------------------------------------------------------------------------*/
MI_SendGXCommandAsyncFast(u32 dmaNo,const void * src,u32 commandLength,MIDmaCallback callback,void * arg)280 void MI_SendGXCommandAsyncFast(u32 dmaNo, const void *src, u32 commandLength,
281 MIDmaCallback callback, void *arg)
282 {
283 MIi_ASSERT_DMANO(dmaNo);
284 MIi_ASSERT_SRC_ALIGN4(src);
285 MIi_WARNING_ADDRINTCM(src, commandLength);
286
287 if (commandLength == 0)
288 {
289 MIi_CallCallback(callback, arg);
290 return;
291 }
292
293 //---- wait till other task end
294 while (MIi_GXDmaParams.isBusy /*volatile valiable */ )
295 {
296 }
297
298 //---- DMA params
299 MIi_GXDmaParams.isBusy = TRUE;
300 MIi_GXDmaParams.dmaNo = dmaNo;
301 MIi_GXDmaParams.callback = callback;
302 MIi_GXDmaParams.arg = arg;
303
304 MIi_CheckAnotherAutoDMA(dmaNo, MI_DMA_TIMING_GXFIFO);
305 //---- check DMA0 source address
306 MIi_CheckDma0SourceAddress(dmaNo, (u32)src, commandLength, MI_DMA_SRC_INC);
307
308 MI_WaitDma(dmaNo);
309
310 OSi_EnterDmaCallback(dmaNo, MIi_DMAFastCallback, NULL);
311 MIi_DmaSetParameters(dmaNo, (u32)src, (u32)REG_GXFIFO_ADDR, MI_CNT_GXCOPY_IF(commandLength), 0);
312 }
313
314 /*---------------------------------------------------------------------------*
315 Name: MIi_DMAFastCallback
316
317 Description: callback for DMA
318 (used for MI_SendGXCommandAsyncFast)
319
320 Arguments: not use
321
322 Returns: None
323 *---------------------------------------------------------------------------*/
MIi_DMAFastCallback(void *)324 static void MIi_DMAFastCallback(void *)
325 {
326 MIi_GXDmaParams.isBusy = FALSE;
327
328 MIi_CallCallback(MIi_GXDmaParams.callback, MIi_GXDmaParams.arg);
329 }
330
331 #endif // SDK_ARM9
332