pureikyubu/Docs/RE/dsp.txt
ogamespec@gmail.com 7b3118623b
2011-06-29 14:19:07 +00:00

229 lines
4.2 KiB
Text

// dsp.c
//
// low-level DSP mail delivery
//
u32 DSPCheckMailToDSP(void)
{
return ( *(u16 *)0xCC005000 & 0x8000 );
}
u32 DSPCheckMailFromDSP(void)
{
return ( *(u16 *)0xCC005004 & 0x8000 );
}
u32 DSPReadCPUToDSPMbox(void)
{
return ( (*(u16 *)0xCC005000 << 16) | *(u16 *)0xCC005002 );
}
u32 DSPReadMailFromDSP(void)
{
return ( (*(u16 *)0xCC005004 << 16) | *(u16 *)0xCC005006 );
}
void DSPSendMailToDSP(u32 mail)
{
*(u16 *)0xCC005000 = mail >> 16;
*(u16 *)0xCC005002 = (u16)mail;
}
//
// assert DSP interrupt
//
void DSPAssertInt(void)
{
u16 old, tmp;
BOOL lvl = OSDisableInterrupts();
old = *(u16 *)0xCC00500A;
tmp = old & ~0x00A8;
tmp |= 0x0002;
*(u16 *)0xCC00500A = tmp;
OSRestoreInterrupts(lvl);
}
//
// DSP management
//
BOOL __DSP_init_flag;
void DSPInit(void)
{
__DSP_debug_printf("DSPInit(): Build Date: %s %s\n", __DATE__, __TIME__);
if(__DSP_init_flag == FALSE)
{
u16 old, tmp;
BOOL lvl = OSDisableInterrupts();
__OSSetInterruptHandler(__OS_INTERRUPT_DSP_DSP, __DSPHandler);
__OSUnmaskInterrupts(OS_INTERRUPTMASK_DSP_DSP);
old = *(u16 *)0xCC00500A;
tmp = old & ~0x00A8;
tmp |= 0x0800;
*(u16 *)0xCC00500A = tmp;
old = *(u16 *)0xCC00500A;
tmp = old & ~0x00AC;
*(u16 *)0xCC00500A = tmp;
__DSP_tmp_task =
__DSP_curr_task =
__DSP_last_task =
__DSP_first_task = NULL;
__DSP_init_flag = TRUE;
OSRestoreInterrupts(lvl);
}
}
BOOL DSPCheckInit(void)
{
return __DSP_init_flag;
}
void DSPReset(void)
{
u16 old, tmp;
BOOL lvl = OSDisableInterrupts();
old = *(u16 *)0xCC00500A;
tmp = old & ~0x00A8;
tmp |= 0x0800;
tmp |= 0x0001;
*(u16 *)0xCC00500A = tmp;
__DSP_init_flag = FALSE;
OSRestoreInterrupts(lvl);
}
void DSPHalt(void)
{
u16 old, tmp;
BOOL lvl = OSDisableInterrupts();
old = *(u16 *)0xCC00500A;
tmp = old & ~0x00A8;
tmp |= 0x0004;
*(u16 *)0xCC00500A = tmp;
OSRestoreInterrupts(lvl);
}
void DSPUnhalt(void)
{
u16 old, tmp;
BOOL lvl = OSDisableInterrupts();
old = *(u16 *)0xCC00500A;
tmp = old & ~0x00AC;
*(u16 *)0xCC00500A = tmp;
OSRestoreInterrupts(lvl);
}
u32 DSPGetDMAStatus(void)
{
return ( *(u16 *)0xCC00500A & 0x0200 );
}
//
// DSP task control
//
DSPTaskInfo *DSPAddTask(DSPTaskInfo *task)
{
BOOL lvl;
if(__DSP_init_flag == FALSE)
{
OSHalt("DSPAddTask(): DSP driver not initialized!\n");
}
lvl = OSDisableInterrupts();
__DSP_insert_task(task);
state->state = DSP_TASK_STATE_INIT;
state->flags = DSP_TASK_FLAG_ATTACHED;
OSRestoreInterrupts(lvl);
if(task == __DSP_first_task)
{
__DSP_boot_task(task);
}
return task;
}
DSPTaskInfo *DSPCancelTask(DSPTaskInfo *task)
{
BOOL lvl;
if(__DSP_init_flag == FALSE)
{
OSHalt("DSPCancelTask(): DSP driver not initialized!\n");
}
lvl = OSDisableInterrupts();
task->flags |= DSP_TASK_FLAG_CANCEL;
OSRestoreInterrupts(lvl);
return task;
}
DSPTaskInfo *DSPAssertTask(DSPTaskInfo *task)
{
BOOL lvl;
if(__DSP_init_flag == FALSE)
{
OSHalt("DSPAssertTask(): DSP driver not initialized!\n");
}
if((task->flags & DSP_TASK_FLAG_ATTACHED) == 0)
{
OSHalt("DSPAssertTask(): Specified task not in active task list!\n");
}
lvl = OSDisableInterrupts();
if(task == __DSP_curr_task)
{
__DSP_rude_task = task;
__DSP_rude_task_pending = TRUE;
OSRestoreInterrupts(lvl);
return task;
}
else
{
if(DSPGetTaskPriority(task) < DSPGetTaskPriority(__DSP_curr_task))
{
__DSP_rude_task = task;
__DSP_rude_task_pending = TRUE;
if(DSPGetTaskState(__DSP_curr_task) == DSP_TASK_STATE_RUN)
{
DSPAssertInt();
}
OSRestoreInterrupts(lvl);
return task
}
}
OSRestoreInterrupts(lvl);
return NULL;
}