forked from Mirror/GodMode9
Enable the FCRAM extension on N3DS
... this means a larger RAM drive on N3DS
This commit is contained in:
parent
7a85615a42
commit
07e419f514
@ -2,54 +2,50 @@
|
||||
#include <cpu.h>
|
||||
#include <gic.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -3,25 +3,44 @@
|
||||
|
||||
#include <arm.h>
|
||||
|
||||
#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
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user