1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - MI
3 File: mi_ndma_gxcommand.c
4
5 Copyright 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-00-00#$
14 $Rev: 0 $
15 $Author: x $
16 *---------------------------------------------------------------------------*/
17 #ifdef SDK_ARM9
18 #include <twl.h>
19 #include "../include/mi_ndma.h"
20
21 #include <twl/ltdmain_begin.h>
22
23 //---- flagmental DMA size
24 #define MIi_GX_LENGTH_ONCE (118 * sizeof(u32)) //(byte)
25
26 //---- flagment NDMA parameters
27 typedef struct
28 {
29 volatile BOOL isBusy;
30
31 u32 ndmaNo;
32 u32 src;
33 u32 length;
34 MINDmaCallback callback;
35 void *arg;
36
37 GXFifoIntrCond fifoCond;
38 void (*fifoFunc) (void);
39 }
40 MIiGXNDmaParams;
41
42 static MIiGXNDmaParams MIi_GXNDmaParams = { FALSE };
43
44 static void MIi_FIFOCallback(void);
45 static void MIi_NDMACallback(void *);
46 static void MIi_NDMAFastCallback(void *);
47
48 /*---------------------------------------------------------------------------*
49 Name: MI_SendNDmaGXCommand
50
51 Description: send GX command with geometry FIFO NDMA.
52 sync version.
53 send data with small fragmental NDMA, so NDMA autostart may not occur.
54
55 Arguments: ndmaNo : NDMA channel No. (0-3)
56 src : source address
57 commandLength : GX command length. (byte)
58
59 Returns: None
60 *---------------------------------------------------------------------------*/
MI_SendNDmaGXCommand(u32 ndmaNo,const void * src,u32 commandLength)61 void MI_SendNDmaGXCommand(u32 ndmaNo, const void *src, u32 commandLength)
62 {
63 vu32 *ndmaCntp;
64 u32 leftLength = commandLength;
65 u32 currentSrc = (u32)src;
66 OSIntrMode enabled;
67
68 MIi_ASSERT_DMANO( ndmaNo );
69
70 if (leftLength == 0)
71 {
72 return;
73 }
74
75 enabled = OS_DisableInterrupts();
76 ndmaCntp = (vu32*)MI_NDMA_REGADDR(ndmaNo, MI_NDMA_REG_CNT_WOFFSET );
77
78 //---- wait while busy
79 while( *ndmaCntp & REG_MI_NDMA0CNT_E_MASK)
80 {
81 }
82
83 while(leftLength > 0)
84 {
85 u32 length = (leftLength > MIi_GX_LENGTH_ONCE)? MIi_GX_LENGTH_ONCE : leftLength;
86
87 MIi_NDma_withConfig_Dev(MIi_NDMA_TYPE_GXCOPY, ndmaNo, (const void*)currentSrc, (void*)REG_GXFIFO_ADDR, 0/*not used*/,
88 length, &MIi_NDmaConfig[ndmaNo], MI_NDMA_TIMING_GXFIFO, MI_NDMA_ENABLE );
89
90 leftLength -= length;
91 currentSrc += length;
92 }
93
94 //---- wait while busy
95 while( *ndmaCntp & REG_MI_NDMA0CNT_E_MASK)
96 {
97 }
98 (void)OS_RestoreInterrupts(enabled);
99 }
100
101 /*---------------------------------------------------------------------------*
102 Name: MI_SendNDmaGXCommandAsync
103
104 Description: send GX command with geometry FIFO NDMA.
105 async version.
106 send data with small fragmental NDMA, so NDMA autostart may not occur.
107
108 Arguments: ndmaNo : NDMA channel No. (0-3)
109 src : source address
110 commandLength : GX command length. (byte)
111 callback : callback function
112 arg : callback argument
113
114 Returns: None
115 *---------------------------------------------------------------------------*/
MI_SendNDmaGXCommandAsync(u32 ndmaNo,const void * src,u32 commandLength,MINDmaCallback callback,void * arg)116 void MI_SendNDmaGXCommandAsync(u32 ndmaNo, const void *src, u32 commandLength, MINDmaCallback callback, void *arg)
117 {
118 MIi_ASSERT_DMANO( ndmaNo );
119
120 //---- if size==0, call callback immediately
121 if ( commandLength == 0)
122 {
123 MIi_CallCallback(callback, arg);
124 return;
125 }
126
127 //---- wait till other task end
128 while(MIi_GXNDmaParams.isBusy)
129 {
130 }
131
132 //---- wait till geometryEngine FIFO is underhalf
133 while (!(G3X_GetCommandFifoStatus() & GX_FIFOSTAT_UNDERHALF))
134 {
135 }
136
137 //---- fragmental DMA params
138 MIi_GXNDmaParams.isBusy = TRUE;
139 MIi_GXNDmaParams.ndmaNo = ndmaNo;
140 MIi_GXNDmaParams.src = (u32)src;
141 MIi_GXNDmaParams.length = commandLength;
142 MIi_GXNDmaParams.callback = callback;
143 MIi_GXNDmaParams.arg = arg;
144
145 MI_WaitNDma(ndmaNo);
146 {
147 OSIntrMode enabled = OS_DisableInterrupts();
148
149 //---- remember FIFO interrupt setting
150 MIi_GXNDmaParams.fifoCond = (GXFifoIntrCond)((reg_G3X_GXSTAT & REG_G3X_GXSTAT_FI_MASK) >> REG_G3X_GXSTAT_FI_SHIFT);
151 MIi_GXNDmaParams.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_SendNDmaGXCommandAsync)
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_GXNDmaParams.length == 0)
179 {
180 return;
181 }
182
183 //---- parameters for this fragment
184 length = (MIi_GXNDmaParams.length >= MIi_GX_LENGTH_ONCE) ? MIi_GX_LENGTH_ONCE : MIi_GXNDmaParams.length;
185 src = MIi_GXNDmaParams.src;
186
187 //---- arrange fragmental DMA params
188 MIi_GXNDmaParams.length -= length;
189 MIi_GXNDmaParams.src += length;
190
191 //---- disable GX interrupt if last
192 if ( MIi_GXNDmaParams.length == 0 )
193 {
194 (void)OS_DisableIrqMask(OS_IE_GXFIFO);
195 }
196 (void)OS_ResetRequestIrqMask(OS_IE_GXFIFO);
197
198 //---- start fragmental DMA. if last, set DMA callback
199 MIi_NDmaAsync( (MIi_GXNDmaParams.length == 0)? MIi_NDMA_TYPE_GXCOPY_IF: MIi_NDMA_TYPE_GXCOPY,
200 MIi_GXNDmaParams.ndmaNo,
201 (const void*)src,
202 (void*)REG_GXFIFO_ADDR,
203 0/*not used*/,
204 length,
205 (MIi_GXNDmaParams.length == 0)? MIi_NDMACallback: NULL,
206 NULL,
207 MI_NDMA_ENABLE );
208 }
209
210 /*---------------------------------------------------------------------------*
211 Name: MIi_NDMACallback
212
213 Description: callback for NDMA
214 (used for MI_SendNDmaGXCommandAsync)
215
216 Arguments: not use
217
218 Returns: None
219 *---------------------------------------------------------------------------*/
MIi_NDMACallback(void *)220 static void MIi_NDMACallback(void *)
221 {
222 (void)OS_DisableIrqMask(OS_IE_GXFIFO);
223
224 //---- restore FIFO interrupt setting
225 G3X_SetFifoIntrCond(MIi_GXNDmaParams.fifoCond);
226 OS_SetIrqFunction(OS_IE_GXFIFO, MIi_GXNDmaParams.fifoFunc);
227
228 MIi_GXNDmaParams.isBusy = FALSE;
229
230 MIi_CallCallback(MIi_GXNDmaParams.callback, MIi_GXNDmaParams.arg);
231 }
232
233 /*---------------------------------------------------------------------------*
234 Name: MI_SendNDmaGXCommandFast
235
236 Description: send GX command with geometry FIFO NDMA.
237 sync version.
238 send data at once, so NDMA autostart may occur.
239
240 Arguments: ndmaNo : NDMA channel No.
241 src : source address
242 commandLength : GX command length. (byte)
243
244 Returns: None
245 *---------------------------------------------------------------------------*/
MI_SendNDmaGXCommandFast(u32 ndmaNo,const void * src,u32 commandLength)246 void MI_SendNDmaGXCommandFast(u32 ndmaNo, const void *src, u32 commandLength)
247 {
248 vu32 *ndmaCntp;
249 OSIntrMode enabled;
250
251 MIi_ASSERT_DMANO(ndmaNo);
252
253 if (commandLength == 0)
254 {
255 return;
256 }
257
258 enabled = OS_DisableInterrupts();
259 ndmaCntp = (vu32*)MI_NDMA_REGADDR(ndmaNo, MI_NDMA_REG_CNT_WOFFSET );
260
261 //---- wait while busy
262 while( *ndmaCntp & REG_MI_NDMA0CNT_E_MASK)
263 {
264 }
265
266 MIi_NDmaAsync( MIi_NDMA_TYPE_GXCOPY,
267 ndmaNo,
268 (const void*)src,
269 (void*)REG_GXFIFO_ADDR,
270 0/*not used*/,
271 commandLength,
272 NULL,
273 NULL,
274 MI_NDMA_ENABLE );
275
276 //---- wait while busy
277 while( *ndmaCntp & REG_MI_NDMA0CNT_E_MASK)
278 {
279 }
280 (void)OS_RestoreInterrupts(enabled);
281 }
282
283 /*---------------------------------------------------------------------------*
284 Name: MI_SendNDmaGXCommandAsyncFast
285
286 Description: send GX command with geometry FIFO NDMA.
287 async version.
288 send data at once, so NDMA autostart may occur.
289
290 Arguments: ndmaNo : NDMA channel No.
291 src : source address
292 commandLength : GX command length. (byte)
293 callback : callback function
294 arg : callback argument
295
296 Returns: None
297 *---------------------------------------------------------------------------*/
MI_SendNDmaGXCommandAsyncFast(u32 ndmaNo,const void * src,u32 commandLength,MINDmaCallback callback,void * arg)298 void MI_SendNDmaGXCommandAsyncFast(u32 ndmaNo, const void *src, u32 commandLength, MINDmaCallback callback, void *arg)
299 {
300 MIi_ASSERT_DMANO(ndmaNo);
301
302 if (commandLength == 0)
303 {
304 MIi_CallCallback(callback, arg);
305 return;
306 }
307
308 //---- wait till other task end
309 while (MIi_GXNDmaParams.isBusy /*volatile valiable */ )
310 {
311 }
312
313 //---- DMA params
314 MIi_GXNDmaParams.isBusy = TRUE;
315 MIi_GXNDmaParams.ndmaNo = ndmaNo;
316 MIi_GXNDmaParams.callback = callback;
317 MIi_GXNDmaParams.arg = arg;
318
319 MI_WaitNDma(ndmaNo);
320
321 MIi_NDmaAsync( MIi_NDMA_TYPE_GXCOPY_IF,
322 ndmaNo,
323 (const void*)src,
324 (void*)REG_GXFIFO_ADDR,
325 0/*not used*/,
326 commandLength,
327 MIi_NDMAFastCallback,
328 NULL,
329 MI_NDMA_ENABLE );
330 }
331
332 /*---------------------------------------------------------------------------*
333 Name: MIi_NDMAFastCallback
334
335 Description: callback for NDMA
336 (used for MI_SendNDmaGXCommandAsyncFast)
337
338 Arguments: not use
339
340 Returns: None
341 *---------------------------------------------------------------------------*/
MIi_NDMAFastCallback(void *)342 static void MIi_NDMAFastCallback(void *)
343 {
344 MIi_GXNDmaParams.isBusy = FALSE;
345
346 MIi_CallCallback(MIi_GXNDmaParams.callback, MIi_GXNDmaParams.arg);
347 }
348
349 //================================================================================
350 #endif // SDK_ARM9
351