2008-11-06 23:27:06 +00:00
|
|
|
|
|
|
|
#define _GNU_SOURCE
|
|
|
|
|
|
|
|
#include "kloadcore.h"
|
|
|
|
#include "kexcepman.h"
|
|
|
|
#include "kintrman.h"
|
|
|
|
#include "err.h"
|
|
|
|
|
|
|
|
#define ICFG (*(volatile int*)0xbf801450)
|
|
|
|
#define IREG (*(volatile int*)0xbf801070)
|
|
|
|
#define IMASK (*(volatile int*)0xbf801074)
|
|
|
|
#define ICTRL (*(volatile int*)0xbf801078)
|
|
|
|
#define DMA_ICR (*(volatile int*)0xbf8010F4)
|
|
|
|
#define DMA_ICR2 (*(volatile int*)0xbf801574)
|
|
|
|
|
|
|
|
#define EXCEP_CAUSE (*(volatile int*)0x40C)
|
|
|
|
|
|
|
|
int debug=1;
|
|
|
|
|
|
|
|
#define _dprintf(fmt, args...) \
|
|
|
|
if (debug > 0) __printf("intrman: " fmt, ## args)
|
|
|
|
|
|
|
|
struct intrHandler {
|
|
|
|
u32 handler;
|
|
|
|
void *arg;
|
|
|
|
};
|
|
|
|
|
|
|
|
func context_switch_required_handler;
|
|
|
|
func context_switch_handler;
|
|
|
|
|
|
|
|
// Additional interrupt mask applied after IMASK
|
|
|
|
u32 soft_hw_intr_mask;
|
|
|
|
|
|
|
|
int unknown2[4]; //0x1280 up
|
|
|
|
|
|
|
|
#define INTR_STACK_SIZE 0x800
|
|
|
|
unsigned char tempstack[INTR_STACK_SIZE];
|
|
|
|
|
|
|
|
u32 *extable;
|
|
|
|
struct intrHandler *intrtable;
|
|
|
|
|
|
|
|
extern struct export export_stub;
|
|
|
|
|
|
|
|
int _start();
|
|
|
|
int IntrHandler();
|
|
|
|
void intrman_retonly();
|
|
|
|
|
|
|
|
/////////////////////////////syscalls//////////////////////////////////
|
|
|
|
__inline void syscall_0();
|
|
|
|
void syscall_1_CpuDisableIntr();
|
|
|
|
void syscall_2_CpuEnableIntr();
|
|
|
|
void syscall_3_intrman_call14();
|
|
|
|
void syscall_4_intrman_call17_19();
|
|
|
|
void syscall_5_intrman_call18_20();
|
|
|
|
void goto_EXCEP_Sys_handler();
|
|
|
|
void syscall_8_threadman();
|
|
|
|
|
|
|
|
func syscall[] = {
|
|
|
|
(func)syscall_0,
|
|
|
|
/* (func)syscall_1_CpuDisableIntr,
|
|
|
|
(func)syscall_2_CpuEnableIntr,
|
|
|
|
(func)syscall_3_intrman_call14,
|
|
|
|
(func)syscall_4_intrman_call17_19,
|
|
|
|
(func)syscall_5_intrman_call18_20,
|
|
|
|
(func)goto_EXCEP_Sys_handler,
|
|
|
|
(func)goto_EXCEP_Sys_handler,
|
|
|
|
(func)syscall_8_threadman,
|
|
|
|
(func)goto_EXCEP_Sys_handler,
|
|
|
|
(func)goto_EXCEP_Sys_handler,
|
|
|
|
(func)goto_EXCEP_Sys_handler,
|
|
|
|
(func)goto_EXCEP_Sys_handler,
|
|
|
|
(func)goto_EXCEP_Sys_handler,
|
|
|
|
(func)goto_EXCEP_Sys_handler,
|
|
|
|
(func)goto_EXCEP_Sys_handler*/
|
|
|
|
};
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
int intrmanDeinit() {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
int intrman_call2()
|
|
|
|
{
|
|
|
|
IMASK = 0x00;
|
|
|
|
DMA_ICR = 0x00;
|
|
|
|
DMA_ICR2 = 0x00;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
int intrman_call3(){
|
|
|
|
return (int)&unknown2;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// interrupt values 0x2E - 0x3F are equivalent to 0x1E - 0x2F with a mode set
|
|
|
|
// interrupt values 0x20 - 0x2D have their mode forced to zero
|
|
|
|
//
|
|
|
|
// mode specifies what registers to save around the call
|
|
|
|
// 0 = don't save anything, handler will not change anything
|
|
|
|
// 1 = save t0 - t9, gp and fp
|
|
|
|
// 2 = save t0 - t9, gp, fp and s0 - s7
|
|
|
|
//
|
|
|
|
// arg is the value passed to the interrupt handler when it is called
|
|
|
|
//
|
|
|
|
int RegisterIntrHandler(int interrupt, int mode, intrh_func handler, void *arg)
|
|
|
|
{
|
|
|
|
u32 ictrl;
|
|
|
|
|
|
|
|
_dprintf("%s interrupt=%x, mode=%x\n", __FUNCTION__, interrupt, mode);
|
|
|
|
if (QueryIntrContext()){
|
|
|
|
// cannot be called from within an interrupt
|
|
|
|
_dprintf("%s ERROR_INTR_CONTEXT\n", __FUNCTION__);
|
|
|
|
return ERROR_INTR_CONTEXT;
|
|
|
|
}
|
|
|
|
CpuSuspendIntr(&ictrl);
|
|
|
|
|
|
|
|
if (interrupt < 0 || interrupt > 0x3F) {
|
|
|
|
CpuResumeIntr(ictrl);
|
|
|
|
_dprintf("%s ERROR_ILLEGAL_INTRCODE\n", __FUNCTION__);
|
|
|
|
return ERROR_ILLEGAL_INTRCODE;
|
|
|
|
}
|
|
|
|
int real_interrupt = interrupt;
|
|
|
|
int real_mode = mode;
|
2010-04-25 00:31:27 +00:00
|
|
|
|
2008-11-06 23:27:06 +00:00
|
|
|
if (interrupt >= 0x2E){
|
2010-04-25 00:31:27 +00:00
|
|
|
real_interrupt -= 0x10;
|
2008-11-06 23:27:06 +00:00
|
|
|
} else if (interrupt >= 0x20){
|
2010-04-25 00:31:27 +00:00
|
|
|
real_mode = 0;
|
2008-11-06 23:27:06 +00:00
|
|
|
}
|
2010-04-25 00:31:27 +00:00
|
|
|
|
2008-11-06 23:27:06 +00:00
|
|
|
if (intrtable[real_interrupt].handler){
|
|
|
|
CpuResumeIntr(ictrl);
|
|
|
|
_dprintf("%s ERROR_DOES_EXIST\n", __FUNCTION__);
|
|
|
|
return ERROR_DOES_EXIST;
|
|
|
|
}
|
|
|
|
intrtable[real_interrupt].handler = (mode & 0x03) | (u32)handler;
|
|
|
|
intrtable[real_interrupt].arg = arg;
|
|
|
|
CpuResumeIntr(ictrl);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
int ReleaseIntrHandler(int interrupt)
|
|
|
|
{
|
|
|
|
u32 ictrl;
|
|
|
|
|
|
|
|
if (QueryIntrContext()){
|
|
|
|
// Cannot be called from within an interrupt
|
|
|
|
return ERROR_INTR_CONTEXT;
|
|
|
|
}
|
|
|
|
CpuSuspendIntr(&ictrl);
|
|
|
|
|
|
|
|
if (interrupt < 0 || interrupt >= 0x40) {
|
|
|
|
CpuResumeIntr(ictrl);
|
|
|
|
return ERROR_ILLEGAL_INTRCODE;
|
|
|
|
}
|
|
|
|
if (interrupt >= 0x2E){
|
2010-04-25 00:31:27 +00:00
|
|
|
interrupt -= 0x10;
|
2008-11-06 23:27:06 +00:00
|
|
|
}
|
2010-04-25 00:31:27 +00:00
|
|
|
|
2008-11-06 23:27:06 +00:00
|
|
|
if (intrtable[interrupt].handler){
|
|
|
|
intrtable[interrupt].handler = 0;
|
|
|
|
CpuResumeIntr(ictrl);
|
2010-04-25 00:31:27 +00:00
|
|
|
return 0;
|
2008-11-06 23:27:06 +00:00
|
|
|
}
|
|
|
|
CpuResumeIntr(ictrl);
|
|
|
|
return ERROR_DOES_EXIST;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
int CpuSuspendIntr(u32 *ictrl)
|
|
|
|
{
|
|
|
|
u32 rval = ICTRL;
|
|
|
|
if (ictrl) *ictrl = rval;
|
|
|
|
if (rval == 0) return ERROR_CPUDI;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
int CpuResumeIntr(u32 ictrl)
|
|
|
|
{
|
|
|
|
ICTRL = ictrl;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
int CpuDisableIntr()
|
|
|
|
{
|
|
|
|
if (ICTRL) return 0;
|
|
|
|
return ERROR_CPUDI;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
int CpuEnableIntr()
|
|
|
|
{
|
|
|
|
//_dprintf("%s\n", __FUNCTION__);
|
|
|
|
// intrman_syscall_08();
|
|
|
|
// _dprintf("syscall ok\n");
|
|
|
|
CpuEnableICTRL();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
int CpuGetICTRL()
|
|
|
|
{
|
|
|
|
return ICTRL;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
int CpuEnableICTRL()
|
|
|
|
{
|
|
|
|
ICTRL = 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
void intrman_syscall_04()
|
|
|
|
{
|
|
|
|
__asm__ (
|
|
|
|
"li $3, 4\n"
|
|
|
|
"syscall\n"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
void intrman_syscall_08()
|
|
|
|
{
|
|
|
|
__asm__ (
|
|
|
|
"li $3, 8\n"
|
|
|
|
"syscall\n"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
void intrman_syscall_10()
|
|
|
|
{
|
|
|
|
__asm__ (
|
|
|
|
"li $3, 16\n"
|
|
|
|
"syscall\n"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
void intrman_syscall_14()
|
|
|
|
{
|
|
|
|
__asm__ (
|
|
|
|
"li $3, 20\n"
|
|
|
|
"syscall\n"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
void intrman_syscall_0C()
|
|
|
|
{
|
|
|
|
__asm__ (
|
|
|
|
"li $3, 12\n"
|
|
|
|
"syscall\n"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Interrupt:
|
|
|
|
// 0 - 0x1F normal interrupt
|
2010-04-25 00:31:27 +00:00
|
|
|
// 0x20 - 0x26
|
2008-11-06 23:27:06 +00:00
|
|
|
// 0x27 - 0x2D
|
|
|
|
//
|
|
|
|
// Return 0 for success, -101 for invalid interrupt number
|
|
|
|
//
|
|
|
|
#define ERROR_BAD_NUMBER -101
|
|
|
|
#define INUM_DMA_0 0x20
|
|
|
|
#define INUM_DMA_BERR 0x27
|
|
|
|
#define INUM_DMA_7 0x28
|
|
|
|
#define IMODE_DMA_IRM 0x100
|
|
|
|
#define IMODE_DMA_IQE 0x200
|
|
|
|
#define INUM_DMA 3
|
|
|
|
|
|
|
|
int EnableIntr(int interrupt)
|
|
|
|
{
|
|
|
|
int retval = 0;
|
|
|
|
u32 low_irq = interrupt & 0xFF;
|
|
|
|
u32 high_irq = interrupt & 0xFFFFFF00;
|
2010-04-25 00:31:27 +00:00
|
|
|
|
2008-11-06 23:27:06 +00:00
|
|
|
u32 ictrl;
|
|
|
|
CpuSuspendIntr(&ictrl);
|
|
|
|
|
|
|
|
if( interrupt < 0 ) {
|
|
|
|
retval = ERROR_BAD_NUMBER;
|
|
|
|
}
|
|
|
|
else if (low_irq < INUM_DMA_0){
|
|
|
|
IMASK |= (1 << low_irq);
|
|
|
|
} else if (low_irq < INUM_DMA_BERR){
|
|
|
|
DMA_ICR = (DMA_ICR & ((~(1<<(low_irq-INUM_DMA_0)))&0x00FFFFFF))
|
|
|
|
| (1 << (INUM_DMA_BERR-INUM_DMA_0 + 16))
|
|
|
|
| (1<<(low_irq-INUM_DMA_0+0x10))
|
|
|
|
| ((high_irq & IMODE_DMA_IRM) ? (1<<(low_irq-INUM_DMA_0)) : 0);
|
2010-04-25 00:31:27 +00:00
|
|
|
|
2008-11-06 23:27:06 +00:00
|
|
|
DMA_ICR2 = (DMA_ICR2 & ((~(1<<(low_irq-INUM_DMA_0)))&0x00FFFFFF))
|
|
|
|
| ((high_irq & IMODE_DMA_IQE) ? (1<<(low_irq-0x10)) : 0);
|
2010-04-25 00:31:27 +00:00
|
|
|
|
2008-11-06 23:27:06 +00:00
|
|
|
IMASK |= 1<<INUM_DMA;
|
|
|
|
} else if ( (low_irq-INUM_DMA_7)<6){ // low_irq = 0x27 isn't handled?
|
|
|
|
|
|
|
|
u32 extra = 0;
|
|
|
|
if (high_irq & IMODE_DMA_IQE)
|
|
|
|
extra = (1<<(low_irq-INUM_DMA_7 + (INUM_DMA_BERR-INUM_DMA_0)));
|
|
|
|
|
|
|
|
DMA_ICR2=(DMA_ICR2&(~(1<<(low_irq-INUM_DMA_7 + (INUM_DMA_BERR-INUM_DMA_0))) & 0x00FFFFFF)) | (1<<(low_irq-INUM_DMA_7+0x10)) | extra;
|
|
|
|
DMA_ICR |= (DMA_ICR&0x00FFFFFF)| (1 << (INUM_DMA_BERR-INUM_DMA_0 + 16));
|
2010-04-25 00:31:27 +00:00
|
|
|
|
2008-11-06 23:27:06 +00:00
|
|
|
IMASK |= 1<<INUM_DMA;
|
|
|
|
} else {
|
|
|
|
retval = ERROR_BAD_NUMBER;
|
|
|
|
}
|
2010-04-25 00:31:27 +00:00
|
|
|
|
2008-11-06 23:27:06 +00:00
|
|
|
CpuResumeIntr(ictrl);
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
//not checked
|
|
|
|
int DisableIntr(int interrupt, int *oldstat){
|
|
|
|
u32 ictrl;
|
|
|
|
u32 old_IMASK;
|
|
|
|
u32 low_irq;
|
|
|
|
u32 stat;
|
|
|
|
u32 ret;
|
|
|
|
|
|
|
|
low_irq = interrupt & 0xFF;
|
|
|
|
|
|
|
|
CpuSuspendIntr(&ictrl);
|
|
|
|
|
|
|
|
ret = -101;
|
|
|
|
stat = -103;
|
|
|
|
|
|
|
|
if (low_irq<0) goto end;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
if (low_irq<0x20)
|
|
|
|
{
|
|
|
|
old_IMASK=IMASK;
|
|
|
|
IMASK&=~(1<<low_irq);
|
|
|
|
|
|
|
|
if (old_IMASK&(1<<low_irq))
|
|
|
|
{
|
|
|
|
stat = low_irq;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = -103;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (low_irq<0x27)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (DMA_ICR & 0xFFFFFF & (1<<(low_irq-0x10)))
|
|
|
|
{
|
|
|
|
if (((DMA_ICR & 0xFFFFFF)>>(low_irq-0x20)) & 0x01) stat = low_irq | 0x100;
|
|
|
|
|
|
|
|
if (DMA_ICR2 & (1<<(low_irq-0x20))) stat |= 0x200;
|
|
|
|
|
|
|
|
DMA_ICR2 &= ~(1<<(low_irq-0x20)) & 0xFFFFFF;
|
|
|
|
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = -103;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (low_irq<0x2E)
|
|
|
|
{
|
|
|
|
if (DMA_ICR2 & 0xFFFFFF & (1<<(low_irq-0x18)))
|
|
|
|
{
|
|
|
|
stat = low_irq;
|
|
|
|
|
|
|
|
if (((DMA_ICR2 & 0xFFFFFF)>>(low_irq-0x21))&0x01) stat |= 0x200;
|
|
|
|
|
|
|
|
DMA_ICR2 &= ~(1<<(low_irq-0x18)) & 0xFFFFFF;
|
|
|
|
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = -103;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (oldstat) *(volatile int*)oldstat = stat;
|
|
|
|
CpuResumeIntr(ictrl);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
// Enable
|
|
|
|
void intrman_call16(int interrupt)
|
|
|
|
{
|
|
|
|
u32 ictrl;
|
|
|
|
CpuSuspendIntr(&ictrl);
|
2010-04-25 00:31:27 +00:00
|
|
|
|
2008-11-06 23:27:06 +00:00
|
|
|
interrupt &= 0xFF;
|
2010-04-25 00:31:27 +00:00
|
|
|
|
2008-11-06 23:27:06 +00:00
|
|
|
if (interrupt < 0x20){
|
|
|
|
soft_hw_intr_mask |= (1 << interrupt);
|
|
|
|
} else if (interrupt < 0x28){
|
|
|
|
unknown2[1] |= 1 << (interrupt-0x08);
|
|
|
|
} else if (interrupt < 0x2E){
|
|
|
|
unknown2[2] |= 1 << (interrupt-0x10);
|
|
|
|
}
|
2010-04-25 00:31:27 +00:00
|
|
|
|
2008-11-06 23:27:06 +00:00
|
|
|
CpuResumeIntr(ictrl);
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
// Disable
|
|
|
|
void intrman_call15(int interrupt)
|
|
|
|
{
|
|
|
|
u32 ictrl;
|
|
|
|
CpuSuspendIntr(&ictrl);
|
2010-04-25 00:31:27 +00:00
|
|
|
|
2008-11-06 23:27:06 +00:00
|
|
|
interrupt &= 0xFF;
|
2010-04-25 00:31:27 +00:00
|
|
|
|
2008-11-06 23:27:06 +00:00
|
|
|
if (interrupt < 0x20){
|
|
|
|
soft_hw_intr_mask &= ~(1 << interrupt);
|
|
|
|
} else if (interrupt < 0x28){
|
|
|
|
unknown2[1] &= ~(1 << (interrupt-0x08));
|
|
|
|
} else if (interrupt < 0x2E){
|
|
|
|
unknown2[2] &= ~(1 << (interrupt-0x10));
|
|
|
|
}
|
2010-04-25 00:31:27 +00:00
|
|
|
|
2008-11-06 23:27:06 +00:00
|
|
|
CpuResumeIntr(ictrl);
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
void intrman_call27(int arg0)
|
|
|
|
{
|
|
|
|
unknown2[3]=arg0;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
int IntrHandler()
|
|
|
|
{
|
|
|
|
u32 masked_icr = DMA_ICR & unknown2[1];
|
|
|
|
|
|
|
|
_dprintf("%s\n", __FUNCTION__);
|
|
|
|
|
|
|
|
|
|
|
|
while (masked_icr & 0x7F008000){
|
2010-04-25 00:31:27 +00:00
|
|
|
int i;
|
2008-11-06 23:27:06 +00:00
|
|
|
if (masked_icr & 0x00008000){
|
|
|
|
// Int 0x25
|
|
|
|
func int_func = (func)(intrtable[0x25].handler & 0xFFFFFFFC);
|
|
|
|
DMA_ICR &= 0x00FF7FFF;
|
|
|
|
if (int_func){
|
|
|
|
int_func(intrtable[0x25].arg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Check each DMA interrupt
|
|
|
|
// The bits 24 - 30 are set for DMA channels 0 - 6 (ints 0x20 - 0x26 respectively)
|
2010-04-25 00:31:27 +00:00
|
|
|
// The bits 16 - 23 are the corresponding mask bits - the interrupt is only generated if the mask bit is set.
|
2008-11-06 23:27:06 +00:00
|
|
|
for (i=0; i < 7; ++i){
|
|
|
|
u32 ibit = 0x01000000 << i;
|
|
|
|
if (masked_icr & ibit){
|
|
|
|
func int_func = (func)(intrtable[0x20+i].handler & 0xFFFFFFFC);
|
|
|
|
DMA_ICR &= (ibit | 0x00FFFFFF);
|
|
|
|
if (int_func){
|
|
|
|
if (!int_func(intrtable[0x20+i].arg)){
|
|
|
|
// Disable / mask the interrupt if it was not handled
|
|
|
|
DMA_ICR &= (~(0x00010000 << i) & 0x00FFFFFF);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DMA_ICR &= 0x007FFFFF;
|
|
|
|
while (DMA_ICR & 0x00800000){
|
|
|
|
// do nothing
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
u32 temp_icr = DMA_ICR;
|
|
|
|
temp_icr &= 0x007FFFFF;
|
|
|
|
temp_icr |= 0x00800000;
|
|
|
|
DMA_ICR = temp_icr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Default context switch handler - does not switch context.
|
|
|
|
//
|
|
|
|
int default_ctx_switch_handler(u32 sp_in)
|
|
|
|
{
|
|
|
|
return sp_in;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Default routine to request a context switch. Does not request one.
|
|
|
|
//
|
|
|
|
int default_ctx_switch_required_handler()
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SetCtxSwitchHandler(func handler){
|
|
|
|
context_switch_handler = handler;
|
|
|
|
}
|
|
|
|
|
|
|
|
void* ResetCtxSwitchHandler()
|
|
|
|
{
|
|
|
|
context_switch_handler = default_ctx_switch_handler;
|
|
|
|
return &context_switch_handler;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetCtxSwitchReqHandler(func handler)
|
|
|
|
{
|
|
|
|
context_switch_required_handler = handler;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ResetCtxSwitchReqHandler()
|
|
|
|
{
|
|
|
|
context_switch_required_handler = default_ctx_switch_required_handler;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
// Return non-zero if sp is in an interrupt context
|
|
|
|
int QueryIntrStack(unsigned char* sp)
|
|
|
|
{
|
|
|
|
int retval = 0;
|
|
|
|
if ( (sp < tempstack + INTR_STACK_SIZE) && (sp > tempstack) ){
|
|
|
|
retval = 1;
|
|
|
|
}
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
// Return non-zero is we're currently in a interrupt context
|
|
|
|
int QueryIntrContext()
|
|
|
|
{
|
|
|
|
unsigned char* sp;
|
|
|
|
__asm__ ("move %0, $29\n" : "=r"(sp) :);
|
2010-04-25 00:31:27 +00:00
|
|
|
|
2008-11-06 23:27:06 +00:00
|
|
|
return QueryIntrStack(sp);
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
int iCatchMultiIntr()
|
|
|
|
{
|
|
|
|
unsigned char* sp;
|
|
|
|
__asm__ ("move %0, $29\n" : "=r"(sp) :);
|
|
|
|
|
|
|
|
if (QueryIntrStack(sp)){
|
|
|
|
if (sp >= tempstack + 0x160){
|
|
|
|
u32 SR;
|
|
|
|
__asm__ ("mfc0 %0, $12\n" : "=r"(SR));
|
|
|
|
if (SR & 1 == 0){
|
|
|
|
u32 set_SR = SR | 1;
|
|
|
|
__asm__ volatile (
|
|
|
|
"mtc0 %0, $12\n"
|
|
|
|
"nop\n"
|
|
|
|
"nop\n"
|
|
|
|
"mtc0 %1, $12\n" : : "r"(set_SR), "r" (SR)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return SR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
// called by EXCEP_Sys_handler
|
|
|
|
void EXCEP_Sys_8() {
|
|
|
|
_dprintf("%s\n", __FUNCTION__);
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
//not finished
|
|
|
|
void syscall_3_intrman_call14(){
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
//not finished
|
|
|
|
void syscall_4_intrman_call17_19(){
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
__inline void syscall_0(){
|
|
|
|
func funct;
|
|
|
|
funct=(func)((*(volatile int*)(0x404))+4);
|
|
|
|
__asm__ (
|
|
|
|
"jr %0\n"
|
|
|
|
"rfe\n"
|
|
|
|
: "=r" (funct)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
void retonly(){}
|
|
|
|
|
|
|
|
u32 callContextSwitchRequiredHandler()
|
|
|
|
{
|
|
|
|
if (NULL != context_switch_required_handler){
|
|
|
|
return context_switch_required_handler();
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////entrypoint///////////////////////////////
|
|
|
|
struct export export_stub={
|
|
|
|
0x41C00000,
|
|
|
|
0,
|
|
|
|
VER(1, 2), // 1.2 => 0x102
|
|
|
|
0,
|
|
|
|
"intrman",
|
|
|
|
(func)_start, // entrypoint
|
|
|
|
(func)intrmanDeinit,
|
|
|
|
(func)intrman_call2,
|
|
|
|
(func)intrman_call3,
|
|
|
|
(func)RegisterIntrHandler,
|
|
|
|
(func)ReleaseIntrHandler,
|
|
|
|
(func)EnableIntr,
|
|
|
|
(func)DisableIntr,
|
|
|
|
(func)CpuDisableIntr,
|
|
|
|
(func)CpuEnableIntr,
|
|
|
|
(func)intrman_syscall_04, // 0x0A
|
|
|
|
(func)intrman_syscall_08,
|
|
|
|
(func)CpuGetICTRL,
|
|
|
|
(func)CpuEnableICTRL,
|
|
|
|
(func)intrman_syscall_0C, // 0x0E
|
|
|
|
(func)intrman_call15,
|
|
|
|
(func)intrman_call16, // 0x10
|
|
|
|
(func)CpuSuspendIntr,
|
|
|
|
(func)CpuResumeIntr,
|
|
|
|
(func)CpuSuspendIntr,
|
|
|
|
(func)CpuResumeIntr,
|
|
|
|
(func)intrman_syscall_10,
|
|
|
|
(func)intrman_syscall_14,
|
|
|
|
(func)QueryIntrContext, // 0x17
|
|
|
|
(func)QueryIntrStack,
|
|
|
|
(func)iCatchMultiIntr,
|
|
|
|
(func)retonly,
|
|
|
|
(func)intrman_call27,
|
|
|
|
(func)SetCtxSwitchHandler, // 0x1C (called by threadman)
|
|
|
|
(func)ResetCtxSwitchHandler,
|
|
|
|
(func)SetCtxSwitchReqHandler, // 0x1E (called by threadman)
|
|
|
|
(func)ResetCtxSwitchReqHandler,
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
extern struct exHandler EXCEP_Int_priority_exception_handler;
|
|
|
|
extern struct exHandler EXCEP_Int_handler;
|
|
|
|
extern struct exHandler EXCEP_Sys_handler;
|
|
|
|
|
|
|
|
//////////////////////////////entrypoint///////////////////////////////
|
|
|
|
int _start(){
|
|
|
|
int i;
|
|
|
|
|
|
|
|
intrtable = (struct intrHandler*)(GetExHandlersTable() + 0x40);
|
|
|
|
|
|
|
|
IMASK = 0x00;
|
|
|
|
DMA_ICR = 0x00;
|
|
|
|
DMA_ICR2 = 0x00;
|
|
|
|
|
|
|
|
for (i=0; i < 0x2F; i++) {
|
|
|
|
intrtable[i].handler = 0;
|
|
|
|
intrtable[i].arg = 0;
|
|
|
|
}
|
2010-04-25 00:31:27 +00:00
|
|
|
|
2008-11-06 23:27:06 +00:00
|
|
|
soft_hw_intr_mask = 0xFFFFFFFF;
|
|
|
|
unknown2[1] = -1;
|
|
|
|
unknown2[2] = -1;
|
|
|
|
unknown2[0] = (int)intrtable;
|
|
|
|
|
|
|
|
RegisterExceptionHandler(0, &EXCEP_Int_handler);
|
|
|
|
RegisterPriorityExceptionHandler(0, 3, &EXCEP_Int_priority_exception_handler);
|
|
|
|
RegisterExceptionHandler(8, &EXCEP_Sys_handler);
|
|
|
|
RegisterIntrHandler(3, 1, &IntrHandler, 0);
|
|
|
|
RegisterLibraryEntries(&export_stub);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ijb_ping1()
|
|
|
|
{
|
|
|
|
_dprintf("%s\n", __FUNCTION__);
|
|
|
|
unsigned char* x = tempstack;
|
|
|
|
}
|
|
|
|
void ijb_trace3(u32 a0, u32 a1, u32 a2, u32 a3)
|
|
|
|
{
|
|
|
|
__printf("trace3: 0x%x, 0x%x, 0x%x\n", a0, a1, a2);
|
|
|
|
while (1){}
|
|
|
|
}
|