1 /*-------------------------------------------------------------
6 Michael Wiedenbauer (shagkur)
7 Dave Murphy (WinterMute)
9 This software is provided 'as-is', without any express or implied
10 warranty. In no event will the authors be held liable for any
11 damages arising from the use of this software.
13 Permission is granted to anyone to use this software for any
14 purpose, including commercial applications, and to alter it and
15 redistribute it freely, subject to the following restrictions:
17 1. The origin of this software must not be misrepresented; you
18 must not claim that you wrote the original software. If you use
19 this software in a product, an acknowledgment in the product
20 documentation would be appreciated but is not required.
22 2. Altered source versions must be plainly marked as such, and
23 must not be misrepresented as being the original software.
25 3. This notice may not be removed or altered from any source
29 -------------------------------------------------------------*/
35 #include "processor.h"
42 #define DSPCR_DSPRESET 0x0800 // Reset DSP
43 #define DSPCR_DSPDMA 0x0200 // ARAM dma in progress, if set
44 #define DSPCR_DSPINTMSK 0x0100 // * interrupt mask (RW)
45 #define DSPCR_DSPINT 0x0080 // * interrupt active (RWC)
46 #define DSPCR_ARINTMSK 0x0040
47 #define DSPCR_ARINT 0x0020
48 #define DSPCR_AIINTMSK 0x0010
49 #define DSPCR_AIINT 0x0008
50 #define DSPCR_HALT 0x0004 // halt DSP
51 #define DSPCR_PIINT 0x0002 // assert DSP PI interrupt
52 #define DSPCR_RES 0x0001 // reset DSP
54 #define _SHIFTL(v, s, w) \
55 ((u32) (((u32)(v) & ((0x01 << (w)) - 1)) << (s)))
56 #define _SHIFTR(v, s, w) \
57 ((u32)(((u32)(v) >> (s)) & ((0x01 << (w)) - 1)))
59 static u32 __dsp_inited
= FALSE
;
60 static u32 __dsp_rudetask_pend
= FALSE
;
61 static DSPCallback __dsp_intcb
= NULL
;
62 static dsptask_t
*__dsp_currtask
,*__dsp_lasttask
,*__dsp_firsttask
,*__dsp_rudetask
,*tmp_task
;
64 static vu16
* const _dspReg
= (u16
*)0xCC005000;
66 static void __dsp_inserttask(dsptask_t
*task
)
70 if(!__dsp_firsttask
) {
71 __dsp_currtask
= task
;
72 __dsp_lasttask
= task
;
73 __dsp_firsttask
= task
;
81 if(task
->prio
<t
->prio
) {
86 __dsp_firsttask
= task
;
89 task
->prev
->next
= task
;
97 __dsp_lasttask
->next
= task
;
99 task
->prev
= __dsp_lasttask
;
100 __dsp_lasttask
= task
;
103 static void __dsp_removetask(dsptask_t
*task
)
105 task
->flags
= DSPTASK_CLEARALL
;
106 task
->state
= DSPTASK_DONE
;
107 if(__dsp_firsttask
==task
) {
109 __dsp_firsttask
= task
->next
;
110 __dsp_firsttask
->prev
= NULL
;
113 __dsp_currtask
= NULL
;
114 __dsp_lasttask
= NULL
;
115 __dsp_firsttask
= NULL
;
118 if(__dsp_lasttask
==task
) {
119 __dsp_lasttask
= task
->prev
;
120 __dsp_lasttask
->next
= NULL
;
121 __dsp_currtask
= __dsp_firsttask
;
124 __dsp_currtask
= __dsp_currtask
->next
;
127 static void __dsp_boottask(dsptask_t
*task
)
131 printf("__dsp_boottask(%p)\n",task
);
133 while(!DSP_CheckMailFrom());
134 mail
= DSP_ReadMailFrom();
136 if(mail
!=0x8071FEED) { //if the overflow calculation applies here too, this should be the value which the dsp should deliver on succesfull sync.
137 printf("__dsp_boottask(): failed to sync DSP on boot (%08x)\n",mail
);
140 DSP_SendMailTo(0x80F3A001);
141 while(DSP_CheckMailTo());
142 DSP_SendMailTo((u32
)task
->iram_maddr
);
143 while(DSP_CheckMailTo());
144 DSP_SendMailTo(0x80F3C002);
145 while(DSP_CheckMailTo());
146 DSP_SendMailTo((task
->iram_addr
&0xffff));
147 while(DSP_CheckMailTo());
148 DSP_SendMailTo(0x80F3A002);
149 while(DSP_CheckMailTo());
150 DSP_SendMailTo(task
->iram_len
);
151 while(DSP_CheckMailTo());
152 DSP_SendMailTo(0x80F3B002);
153 while(DSP_CheckMailTo());
155 while(DSP_CheckMailTo());
156 DSP_SendMailTo(0x80F3D001);
157 while(DSP_CheckMailTo());
158 DSP_SendMailTo(task
->init_vec
);
159 while(DSP_CheckMailTo());
162 static void __dsp_exectask(dsptask_t
*exec
,dsptask_t
*hire
)
165 printf("__dsp_exectask(%p,%p)\n",exec
,hire
);
169 while(DSP_CheckMailTo());
171 while(DSP_CheckMailTo());
173 while(DSP_CheckMailTo());
175 DSP_SendMailTo((u32
)exec
->dram_maddr
);
176 while(DSP_CheckMailTo());
177 DSP_SendMailTo(exec
->dram_len
);
178 while(DSP_CheckMailTo());
179 DSP_SendMailTo(exec
->dram_addr
);
180 while(DSP_CheckMailTo());
183 DSP_SendMailTo((u32
)hire
->iram_maddr
);
184 while(DSP_CheckMailTo());
185 DSP_SendMailTo(hire
->iram_len
);
186 while(DSP_CheckMailTo());
187 DSP_SendMailTo(hire
->iram_addr
);
188 while(DSP_CheckMailTo());
189 if(hire
->state
==DSPTASK_INIT
) {
190 DSP_SendMailTo(hire
->init_vec
);
191 while(DSP_CheckMailTo());
193 while(DSP_CheckMailTo());
195 while(DSP_CheckMailTo());
197 while(DSP_CheckMailTo());
201 DSP_SendMailTo(hire
->resume_vec
);
202 while(DSP_CheckMailTo());
204 DSP_SendMailTo((u32
)hire
->dram_maddr
);
205 while(DSP_CheckMailTo());
206 DSP_SendMailTo(hire
->dram_len
);
207 while(DSP_CheckMailTo());
208 DSP_SendMailTo(hire
->dram_addr
);
209 while(DSP_CheckMailTo());
212 static void __dsp_def_taskcb()
216 printf("__dsp_def_taskcb()\n");
218 while(!DSP_CheckMailFrom());
220 mail
= DSP_ReadMailFrom();
222 printf("__dsp_def_taskcb(mail = 0x%08x)\n",mail
);
224 if(__dsp_currtask
->flags
&DSPTASK_CANCEL
) {
225 if(mail
==0xDCD10002) mail
= 0xDCD10003;
230 __dsp_currtask
->state
= DSPTASK_RUN
;
231 if(__dsp_currtask
->init_cb
) __dsp_currtask
->init_cb(__dsp_currtask
);
234 __dsp_currtask
->state
= DSPTASK_RUN
;
235 if(__dsp_currtask
->res_cb
) __dsp_currtask
->res_cb(__dsp_currtask
);
238 if(__dsp_rudetask_pend
==TRUE
) {
239 if(__dsp_rudetask
==__dsp_currtask
) {
240 DSP_SendMailTo(0xCDD10003);
241 while(DSP_CheckMailTo());
243 __dsp_rudetask
= NULL
;
244 __dsp_rudetask_pend
= FALSE
;
245 if(__dsp_currtask
->res_cb
) __dsp_currtask
->res_cb(__dsp_currtask
);
247 DSP_SendMailTo(0xCDD10001);
248 while(DSP_CheckMailTo());
250 __dsp_exectask(__dsp_currtask
,__dsp_rudetask
);
251 __dsp_currtask
->flags
= DSPTASK_YIELD
;
252 __dsp_currtask
= __dsp_rudetask
;
253 __dsp_rudetask
= NULL
;
254 __dsp_rudetask_pend
= FALSE
;
256 } else if(__dsp_currtask
->next
==NULL
) {
257 if(__dsp_firsttask
==__dsp_currtask
) {
258 DSP_SendMailTo(0xCDD10003);
259 while(DSP_CheckMailTo());
261 if(__dsp_currtask
->res_cb
) __dsp_currtask
->res_cb(__dsp_currtask
);
263 DSP_SendMailTo(0xCDD10001);
264 while(DSP_CheckMailTo());
266 __dsp_exectask(__dsp_currtask
,__dsp_firsttask
);
267 __dsp_currtask
->state
= DSPTASK_YIELD
;
268 __dsp_currtask
= __dsp_firsttask
;
271 DSP_SendMailTo(0xCDD10001);
272 while(DSP_CheckMailTo());
274 __dsp_exectask(__dsp_currtask
,__dsp_currtask
->next
);
275 __dsp_currtask
->state
= DSPTASK_YIELD
;
276 __dsp_currtask
= __dsp_currtask
->next
;
280 if(__dsp_rudetask_pend
==TRUE
) {
281 if(__dsp_currtask
->done_cb
) __dsp_currtask
->done_cb(__dsp_currtask
);
282 DSP_SendMailTo(0xCDD10001);
283 while(DSP_CheckMailTo());
285 __dsp_exectask(NULL
,__dsp_rudetask
);
286 __dsp_removetask(__dsp_currtask
);
288 __dsp_currtask
= __dsp_rudetask
;
289 __dsp_rudetask_pend
= FALSE
;
290 __dsp_rudetask
= NULL
;
291 } else if(__dsp_currtask
->next
==NULL
) {
292 if(__dsp_firsttask
==__dsp_currtask
) {
293 if(__dsp_currtask
->done_cb
) __dsp_currtask
->done_cb(__dsp_currtask
);
294 DSP_SendMailTo(0xCDD10002);
295 while(DSP_CheckMailTo());
297 __dsp_currtask
->state
= DSPTASK_DONE
;
298 __dsp_removetask(__dsp_currtask
);
301 if(__dsp_currtask
->done_cb
) __dsp_currtask
->done_cb(__dsp_currtask
);
303 DSP_SendMailTo(0xCDD10001);
304 while(DSP_CheckMailTo());
306 __dsp_currtask
->state
= DSPTASK_DONE
;
307 __dsp_exectask(NULL
,__dsp_firsttask
);
308 __dsp_currtask
= __dsp_firsttask
;
309 __dsp_removetask(__dsp_lasttask
);
313 if(__dsp_currtask
->req_cb
) __dsp_currtask
->req_cb(__dsp_currtask
);
319 static void __dsp_inthandler(u32 nIrq
,void *pCtx
)
321 _dspReg
[5] = (_dspReg
[5]&~(DSPCR_AIINT
|DSPCR_ARINT
))|DSPCR_DSPINT
;
322 if(__dsp_intcb
) __dsp_intcb();
329 printf("DSP_Init()\n");
331 _CPU_ISR_Disable(level
);
332 if(__dsp_inited
==FALSE
) {
333 __dsp_intcb
= __dsp_def_taskcb
;
335 IRQ_Request(IRQ_DSP_DSP
,__dsp_inthandler
,NULL
);
336 __UnmaskIrq(IRQMASK(IRQ_DSP_DSP
));
338 _dspReg
[5] = (_dspReg
[5]&~(DSPCR_AIINT
|DSPCR_ARINT
|DSPCR_DSPINT
))|DSPCR_DSPRESET
;
339 _dspReg
[5] = (_dspReg
[5]&~(DSPCR_HALT
|DSPCR_AIINT
|DSPCR_ARINT
|DSPCR_DSPINT
));
341 __dsp_currtask
= NULL
;
342 __dsp_firsttask
= NULL
;
343 __dsp_lasttask
= NULL
;
347 _CPU_ISR_Restore(level
);
350 DSPCallback
DSP_RegisterCallback(DSPCallback usr_cb
)
355 printf("DSP_RegisterCallback()\n");
357 _CPU_ISR_Disable(level
);
360 __dsp_intcb
= usr_cb
;
362 __dsp_intcb
= __dsp_def_taskcb
;
363 _CPU_ISR_Restore(level
);
368 u32
DSP_CheckMailTo()
371 sent_mail
= _SHIFTR(_dspReg
[0],15,1);
373 printf("DSP_CheckMailTo(%02x)\n",sent_mail
);
378 u32
DSP_CheckMailFrom()
381 has_mail
= _SHIFTR(_dspReg
[2],15,1);
383 printf("DSP_CheckMailFrom(%02x)\n",has_mail
);
388 u32
DSP_ReadMailFrom()
391 mail
= (_SHIFTL(_dspReg
[2],16,16)|(_dspReg
[3]&0xffff));
393 printf("DSP_ReadMailFrom(%08x)\n",mail
);
398 void DSP_SendMailTo(u32 mail
)
401 printf("DSP_SendMailTo(%08x)\n",mail
);
403 _dspReg
[0] = _SHIFTR(mail
,16,16);
404 _dspReg
[1] = (mail
&0xffff);
407 u32
DSP_ReadCPUtoDSP()
410 cpu_dsp
= (_SHIFTL(_dspReg
[0],16,16)|(_dspReg
[1]&0xffff));
412 printf("DSP_ReadCPUtoDSP(%08x)\n",cpu_dsp
);
421 printf("DSP_AssertInt()\n");
423 _CPU_ISR_Disable(level
);
424 _dspReg
[5] = (_dspReg
[5]&~(DSPCR_AIINT
|DSPCR_ARINT
|DSPCR_DSPINT
))|DSPCR_PIINT
;
425 _CPU_ISR_Restore(level
);
433 _CPU_ISR_Disable(level
);
435 _dspReg
[5] = (old
&~(DSPCR_AIINT
|DSPCR_ARINT
|DSPCR_DSPINT
))|(DSPCR_DSPRESET
|DSPCR_RES
);
436 _CPU_ISR_Restore(level
);
443 _CPU_ISR_Disable(level
);
445 _dspReg
[5] = (old
&~(DSPCR_AIINT
|DSPCR_ARINT
|DSPCR_DSPINT
))|DSPCR_HALT
;
446 _CPU_ISR_Restore(level
);
453 _CPU_ISR_Disable(level
);
454 _dspReg
[5] = (_dspReg
[5]&~(DSPCR_AIINT
|DSPCR_ARINT
|DSPCR_DSPINT
|DSPCR_HALT
));
455 _CPU_ISR_Restore(level
);
458 u32
DSP_GetDMAStatus()
460 return _dspReg
[5]&DSPCR_DSPDMA
;
463 dsptask_t
* DSP_AddTask(dsptask_t
*task
)
467 printf("DSP_AddTask(%p)\n",task
);
469 _CPU_ISR_Disable(level
);
470 __dsp_inserttask(task
);
471 task
->state
= DSPTASK_INIT
;
472 task
->flags
= DSPTASK_ATTACH
;
473 _CPU_ISR_Restore(level
);
475 if(__dsp_firsttask
==task
) __dsp_boottask(task
);
479 void DSP_CancelTask(dsptask_t
*task
)
483 _CPU_ISR_Disable(level
);
484 task
->flags
|= DSPTASK_CANCEL
;
485 _CPU_ISR_Restore(level
);
488 dsptask_t
* DSP_AssertTask(dsptask_t
*task
)
491 dsptask_t
*ret
= NULL
;
493 _CPU_ISR_Disable(level
);
494 if(task
==__dsp_currtask
) {
495 __dsp_rudetask
= task
;
496 __dsp_rudetask_pend
= TRUE
;
499 if(task
->prio
<__dsp_currtask
->prio
) {
500 __dsp_rudetask
= task
;
501 __dsp_rudetask_pend
= TRUE
;
502 if(__dsp_currtask
->state
==DSPTASK_RUN
)
503 _dspReg
[5] = ((_dspReg
[5]&~(DSPCR_DSPINT
|DSPCR_ARINT
|DSPCR_AIINT
))|DSPCR_PIINT
);
508 _CPU_ISR_Restore(level
);