diff --git a/arm11/source/gic.c b/arm11/source/gic.c index d7da669..034fbcc 100644 --- a/arm11/source/gic.c +++ b/arm11/source/gic.c @@ -2,54 +2,50 @@ #include #include +#include + #define IRQVECTOR_BASE ((vu32*)0x1FFFFFA0) -irq_handler handler_table[MAX_IRQ]; extern void (*main_irq_handler)(void); - -irq_handler GIC_AckIRQ(void) -{ - u32 xrq = *GIC_IRQACK; - irq_handler ret = NULL; - if (xrq < MAX_IRQ && handler_table[xrq]) { - ret = handler_table[xrq]; - } - *GIC_IRQEND = xrq; - return ret; -} - -void GIC_SetIRQ(u32 irq_id, irq_handler hndl) -{ - handler_table[irq_id] = hndl; - DIC_CLRENABLE[irq_id/32] |= BIT(irq_id & 0x1F); - DIC_SETENABLE[irq_id/32] |= BIT(irq_id & 0x1F); - DIC_PROCTGT[irq_id] = 1; - return; -} +irq_handler GIC_Handlers[128]; void GIC_Reset(void) { - *GIC_CONTROL = 1; - *DIC_CONTROL = 1; + u32 irq_s; - *GIC_PRIOMASK = ~0; - for (int i = 0; i < MAX_IRQ; i++) { - handler_table[i] = NULL; - *GIC_IRQEND = i; - } + REG_GIC_CONTROL = 0; + memset(GIC_Handlers, 0, sizeof(GIC_Handlers)); - for (int i = 0; i < (0x08); i++) { - DIC_CLRENABLE[i] = ~0; - DIC_PRIORITY[i] = 0; + REG_DIC_CONTROL = 0; + for (int i = 0; i < 4; i++) { + REG_DIC_CLRENABLE[i] = ~0; + REG_DIC_CLRPENDING[i] = ~0; } + for (int i = 0; i < 32; i++) REG_DIC_PRIORITY[i] = 0; + for (int i = 32; i < 128; i++) REG_DIC_TARGETPROC[i] = 0; + for (int i = 0; i < 8; i++) REG_DIC_CFGREG[i] = ~0; + REG_DIC_CONTROL = 1; - while(*GIC_PENDING != SPURIOUS_IRQ) { - for (int i=0; i < (0x08); i++) { - DIC_CLRPENDING[i] = ~0; - } - } + REG_DIC_CLRENABLE[0] = ~0; + for (int i = 0; i < 32; i++) REG_DIC_PRIORITY[i] = 0; + for (int i = 0; i < 2; i++) REG_DIC_CFGREG[i] = ~0; + REG_GIC_POI = 3; + REG_GIC_PRIOMASK = 0xF << 4; + REG_GIC_CONTROL = 1; + + do { + irq_s = REG_GIC_PENDING; + REG_GIC_IRQEND = irq_s; + } while(irq_s != 1023); IRQVECTOR_BASE[1] = (u32)&main_irq_handler; IRQVECTOR_BASE[0] = 0xE51FF004; - return; +} + +void GIC_SetIRQ(u32 irq, irq_handler handler) +{ + GIC_Handlers[irq] = handler; + REG_DIC_CLRPENDING[irq >> 5] |= BIT(irq & 0x1F); + REG_DIC_SETENABLE[irq >> 5] |= BIT(irq & 0x1F); + REG_DIC_TARGETPROC[irq] = 1; } diff --git a/arm11/source/gic.h b/arm11/source/gic.h index 8f7a974..5a573ea 100644 --- a/arm11/source/gic.h +++ b/arm11/source/gic.h @@ -3,27 +3,25 @@ typedef void (*irq_handler)(void); -#define MAX_IRQ (0x80) +#define REG_GIC_BASE (0x17E00100) // MPCore PMR +#define REG_DIC_BASE (0x17E01000) -#define SPURIOUS_IRQ (1023) +#define REG_GIC_CONTROL (*(vu32*)(REG_GIC_BASE + 0x00)) +#define REG_GIC_PRIOMASK (*(vu32*)(REG_GIC_BASE + 0x04)) +#define REG_GIC_POI (*(vu32*)(REG_GIC_BASE + 0x08)) +#define REG_GIC_IRQACK (*(vu32*)(REG_GIC_BASE + 0x0C)) +#define REG_GIC_IRQEND (*(vu32*)(REG_GIC_BASE + 0x10)) +#define REG_GIC_LASTPRIO (*(vu32*)(REG_GIC_BASE + 0x14)) +#define REG_GIC_PENDING (*(vu32*)(REG_GIC_BASE + 0x18)) -#define GIC_BASE (0x17E00100) -#define DIC_BASE (0x17E01000) - -#define GIC_CONTROL ((vu32*)(GIC_BASE + 0x00)) -#define GIC_PRIOMASK ((vu32*)(GIC_BASE + 0x04)) -#define GIC_IRQACK ((vu32*)(GIC_BASE + 0x0C)) -#define GIC_IRQEND ((vu32*)(GIC_BASE + 0x10)) -#define GIC_PENDING ((vu32*)(GIC_BASE + 0x18)) - -#define DIC_CONTROL ((vu32*)(DIC_BASE + 0x000)) -#define DIC_SETENABLE ((vu32*)(DIC_BASE + 0x100)) -#define DIC_CLRENABLE ((vu32*)(DIC_BASE + 0x180)) -#define DIC_SETPENDING ((vu32*)(DIC_BASE + 0x200)) -#define DIC_CLRPENDING ((vu32*)(DIC_BASE + 0x280)) -#define DIC_PRIORITY ((vu32*)(DIC_BASE + 0x400)) -#define DIC_PROCTGT ((vu8*) (DIC_BASE + 0x800)) -#define DIC_CFGREG ((vu32*)(DIC_BASE + 0xC00)) +#define REG_DIC_CONTROL (*(vu32*)(REG_DIC_BASE + 0x00)) +#define REG_DIC_SETENABLE ((vu32*)(REG_DIC_BASE + 0x100)) +#define REG_DIC_CLRENABLE ((vu32*)(REG_DIC_BASE + 0x180)) +#define REG_DIC_SETPENDING ((vu32*)(REG_DIC_BASE + 0x200)) +#define REG_DIC_CLRPENDING ((vu32*)(REG_DIC_BASE + 0x280)) +#define REG_DIC_PRIORITY ((vu32*)(REG_DIC_BASE + 0x400)) +#define REG_DIC_TARGETPROC ((vu8*) (REG_DIC_BASE + 0x800)) +#define REG_DIC_CFGREG ((vu32*)(REG_DIC_BASE + 0xC00)) void GIC_SetIRQ(u32 irq_id, irq_handler hndl); void GIC_Reset(void); diff --git a/arm11/source/irq.s b/arm11/source/irq.s index 22a452d..c3c02d0 100644 --- a/arm11/source/irq.s +++ b/arm11/source/irq.s @@ -3,25 +3,44 @@ #include +#define MPCORE_PMR (0x17E00000) +#define IRQ_SPURIOUS (1023) +#define IRQ_COUNT (128) + .global main_irq_handler .type main_irq_handler, %function main_irq_handler: sub lr, lr, #4 @ Fix return address - srsdb sp!, #(SR_SVC_MODE) @ Store IRQ mode LR and SPSR on the SVC stack - cpsid i, #(SR_SVC_MODE) @ Switch to SVC mode - push {r0-r3,r12} @ Preserve registers - and r1, sp, #4 - sub sp, sp, r1 @ Word-align stack - push {r1,lr} + srsfd sp!, #0x13 @ Store IRQ mode LR and SPSR on the SVC stack + cps #0x13 @ Switch to SVC mode + push {r0-r3, r12, lr} @ Preserve registers - bl GIC_AckIRQ @ Acknowledge interrupt, get handler address - cmp r0, #0 - beq .Lskip_irq + 1: + ldr lr, =MPCORE_PMR + ldr r0, [lr, #0x10C] @ Get pending interrupt - blx r0 @ Branch to interrupt handler + ldr r1, =IRQ_SPURIOUS + cmp r0, r1 + beq 3f @ Spurious interrupt, no interrupts pending - .Lskip_irq: - pop {r1,lr} - add sp, sp, r1 @ Restore stack pointer - pop {r0-r3,r12} @ Restore registers + cmp r0, #IRQ_COUNT + bhs 2f @ Invalid interrupt ID + + ldr r12, =GIC_Handlers + ldr r12, [r12, r0, lsl #2] + cmp r12, #0 + beq 2f + + push {r0, r12} + blx r12 + pop {r0, r12} + + 2: + ldr lr, =MPCORE_PMR + str r0, [lr, #0x110] @ End of interrupt + b 1b @ Check for any other pending interrupts + + 3: + pop {r0-r3, r12, lr} @ Restore registers rfeia sp! @ Return From Exception + diff --git a/arm11/source/main.c b/arm11/source/main.c index 7824595..43df690 100644 --- a/arm11/source/main.c +++ b/arm11/source/main.c @@ -59,11 +59,25 @@ void PXI_IRQHandler(void) return; } +vu16 *CFG11_MPCORE_CLKCNT = (vu16*)(0x10141300); +vu16 *CFG11_SOCINFO = (vu16*)(0x10140FFC); + void main(void) { u32 entry; - PXI_Reset(); + if ((*CFG11_SOCINFO & 2) && (!(*CFG11_MPCORE_CLKCNT & 1))) { + GIC_Reset(); + GIC_SetIRQ(88, NULL); + CPU_EnableIRQ(); + *CFG11_MPCORE_CLKCNT = 0x8001; + do { + asm("wfi\n\t"); + } while(!(*CFG11_MPCORE_CLKCNT & 0x8000)); + CPU_DisableIRQ(); + } + + PXI_Reset(); GIC_Reset(); GIC_SetIRQ(IRQ_PXI_SYNC, PXI_IRQHandler); PXI_EnableIRQ(); diff --git a/arm9/source/fatfs/ramdrive.c b/arm9/source/fatfs/ramdrive.c index c0c5135..faa3436 100644 --- a/arm9/source/fatfs/ramdrive.c +++ b/arm9/source/fatfs/ramdrive.c @@ -28,5 +28,5 @@ u64 GetRamDriveSize(void) { void InitRamDrive(void) { ramdrv_buffer = (u8*) __RAMDRV_ADDR; - ramdrv_size = ((IS_O3DS || IS_SIGHAX) ? __RAMDRV_END : __RAMDRV_END_N) - __RAMDRV_ADDR; + ramdrv_size = (IS_O3DS ? __RAMDRV_END : __RAMDRV_END_N) - __RAMDRV_ADDR; }