diff --git a/include/Dolphin/OS/OSExpansion.h b/include/Dolphin/OS/OSExpansion.h index d8186d627..2573ba1b6 100644 --- a/include/Dolphin/OS/OSExpansion.h +++ b/include/Dolphin/OS/OSExpansion.h @@ -19,6 +19,8 @@ s32 EXIProbeEx(s32 channel); s32 EXIGetType(s32 channel, u32 dev, u32* type); char* EXIGetTypeString(u32 type); +u32 __OSGetDIConfig(void); + ////////////////////////////////// /////////// EXI DEFINES ////////// diff --git a/include/Dolphin/OS/OSUtil.h b/include/Dolphin/OS/OSUtil.h index 783b192a3..b67f300f8 100644 --- a/include/Dolphin/OS/OSUtil.h +++ b/include/Dolphin/OS/OSUtil.h @@ -91,6 +91,9 @@ void OSTicksToCalendarTime(OSTime ticks, OSCalendarTime* timeDate); #define OSCachedToUncached(caddr) ((void*)((u8*)(caddr) + (OS_BASE_UNCACHED - OS_BASE_CACHED))) #define OSUncachedToCached(ucaddr) ((void*)((u8*)(ucaddr) - (OS_BASE_UNCACHED - OS_BASE_CACHED))) +// Other useful addresses. +vu16 __OSDeviceCode AT_ADDRESS(OS_BASE_CACHED | 0x30E6); + ////////////////////////////////// #ifdef __cplusplus diff --git a/include/Dolphin/exi.h b/include/Dolphin/exi.h index 38fe90385..bf4bdde4e 100644 --- a/include/Dolphin/exi.h +++ b/include/Dolphin/exi.h @@ -3,14 +3,54 @@ #include "types.h" #include "Dolphin/os.h" +#include "Dolphin/hw_regs.h" #ifdef __cplusplus extern "C" { #endif // ifdef __cplusplus -#define EXI_TX 0x800400u -#define EXI_MAGIC 0xa5ff005a +/////////// EXI DEFINES ////////// +// Useful numbers. +#define EXI_TX 0x800400u +#define EXI_MAGIC 0xa5ff005a +#define EXI_MAX_DEV 3 +#define EXI_MAX_CHAN 3 +#define EXI_REG_MAX 5 +// Useful macros. +#define EXI_0CR(tstart, dma, rw, tlen) ((((u32)(tstart)) << 0) | (((u32)(dma)) << 1) | (((u32)(rw)) << 2) | (((u32)(tlen)) << 4)) + +#define EXIREG(chan, idx) (__EXIRegs[((chan)*EXI_REG_MAX) + (idx)]) + +#define EXI_CPR_CS(x) ((1u << (x)) << 7) +#define EXI_CPR_CLK(x) ((x) << 4) + +s32 __EXIProbeStartTime[2] AT_ADDRESS(OS_BASE_CACHED | 0x30C0); + +////////////////////////////////// + +/////////// EXI STRUCTS ////////// +// Struct for handling expansion information (size 0x40). +typedef struct EXIControl { + EXICallback exiCallback; // _00 + EXICallback tcCallback; // _04 + EXICallback extCallback; // _08 + vu32 state; // _0C + int immLen; // _10 + u8* immBuf; // _14 + u32 dev; // _18 + u32 id; // _1C + s32 idTime; // _20 + int items; // _24 + struct { + u32 dev; + EXICallback callback; + } queue[EXI_MAX_DEV]; // _28 +} EXIControl; + +////////////////////////////////// + +////////// EXI FUNCTIONS ///////// void EXIInit(); BOOL EXIImm(s32 channel, void* buffer, s32 length, u32 type, EXICallback callback); @@ -23,13 +63,15 @@ BOOL EXIAttach(s32 channel, EXICallback callback); BOOL EXIDetach(s32 channel); BOOL EXISelect(s32 channel, u32 device, u32 frequency); BOOL EXIDeselect(s32 channel); -// sic + void EXIIntrruptHandler(__OSInterrupt interrupt, OSContext* context); BOOL EXILock(s32 channel, u32 device, EXICallback callback); BOOL EXIUnlock(s32 channel); u32 EXIGetState(s32 channel); s32 EXIGetID(s32 channel, u32 device, u32* id); +////////////////////////////////// + #ifdef __cplusplus }; #endif // ifdef __cplusplus diff --git a/src/Dolphin/exi/EXIBios.c b/src/Dolphin/exi/EXIBios.c index 89524fb17..39df7f118 100644 --- a/src/Dolphin/exi/EXIBios.c +++ b/src/Dolphin/exi/EXIBios.c @@ -1,100 +1,45 @@ +#include "Dolphin/exi.h" +#pragma scheduling off + +char* __EXIVersion = "<< Dolphin SDK - EXI\trelease build: Apr 17 2003 12:33:17 (0x2301) >>"; + +static EXIControl Ecb[EXI_MAX_CHAN]; +static u32 IDSerialPort1; /* * --INFO-- * Address: 800DFB54 * Size: 0000F4 */ -void SetExiInterruptMask(void) +static void SetExiInterruptMask(s32 chan, EXIControl* exi) { - /* - .loc_0x0: - mflr r0 - stw r0, 0x4(r1) - stwu r1, -0x18(r1) - stw r31, 0x14(r1) - addi r31, r4, 0 - lis r4, 0x804F - addi r4, r4, 0x5F28 - addi r4, r4, 0x80 - cmpwi r3, 0x1 - beq- .loc_0x80 - bge- .loc_0x38 - cmpwi r3, 0 - bge- .loc_0x44 - b .loc_0xE0 - - .loc_0x38: - cmpwi r3, 0x3 - bge- .loc_0xE0 - b .loc_0xB0 - - .loc_0x44: - lwz r0, 0x0(r31) - cmplwi r0, 0 - bne- .loc_0x5C - lwz r0, 0x0(r4) - cmplwi r0, 0 - beq- .loc_0x68 - - .loc_0x5C: - lwz r0, 0xC(r31) - rlwinm. r0,r0,0,27,27 - beq- .loc_0x74 - - .loc_0x68: - lis r3, 0x41 - bl 0xF440 - b .loc_0xE0 - - .loc_0x74: - lis r3, 0x41 - bl 0xF4BC - b .loc_0xE0 - - .loc_0x80: - lwz r0, 0x0(r31) - cmplwi r0, 0 - beq- .loc_0x98 - lwz r0, 0xC(r31) - rlwinm. r0,r0,0,27,27 - beq- .loc_0xA4 - - .loc_0x98: - lis r3, 0x8 - bl 0xF410 - b .loc_0xE0 - - .loc_0xA4: - lis r3, 0x8 - bl 0xF48C - b .loc_0xE0 - - .loc_0xB0: - li r3, 0x19 - bl 0xF098 - cmplwi r3, 0 - beq- .loc_0xCC - lwz r0, 0xC(r31) - rlwinm. r0,r0,0,27,27 - beq- .loc_0xD8 - - .loc_0xCC: - li r3, 0x40 - bl 0xF3DC - b .loc_0xE0 - - .loc_0xD8: - li r3, 0x40 - bl 0xF458 - - .loc_0xE0: - lwz r0, 0x1C(r1) - lwz r31, 0x14(r1) - addi r1, r1, 0x18 - mtlr r0 - blr - */ + EXIControl* exi2; + + exi2 = &Ecb[2]; + switch (chan) { + case 0: + if ((exi->exiCallback == 0 && exi2->exiCallback == 0) || (exi->state & EXI_STATE_LOCKED)) { + __OSMaskInterrupts(OS_INTERRUPTMASK_EXI_0_EXI | OS_INTERRUPTMASK_EXI_2_EXI); + } else { + __OSUnmaskInterrupts(OS_INTERRUPTMASK_EXI_0_EXI | OS_INTERRUPTMASK_EXI_2_EXI); + } + break; + case 1: + if (exi->exiCallback == 0 || (exi->state & EXI_STATE_LOCKED)) { + __OSMaskInterrupts(OS_INTERRUPTMASK_EXI_1_EXI); + } else { + __OSUnmaskInterrupts(OS_INTERRUPTMASK_EXI_1_EXI); + } + break; + case 2: + if (__OSGetInterruptHandler(__OS_INTERRUPT_PI_DEBUG) == 0 || (exi->state & EXI_STATE_LOCKED)) { + __OSMaskInterrupts(OS_INTERRUPTMASK_PI_DEBUG); + } else { + __OSUnmaskInterrupts(OS_INTERRUPTMASK_PI_DEBUG); + } + break; + } } /* @@ -102,9 +47,24 @@ void SetExiInterruptMask(void) * Address: ........ * Size: 000154 */ -void CompleteTransfer(void) +static void CompleteTransfer(s32 chan) { - // UNUSED FUNCTION + EXIControl* exi = &Ecb[chan]; + u8* buf; + u32 data; + int i; + int len; + + if (exi->state & EXI_STATE_BUSY) { + if ((exi->state & EXI_STATE_IMM) && (len = exi->immLen)) { + buf = exi->immBuf; + data = EXIREG(chan, 4); + for (i = 0; i < len; i++) { + *buf++ = (u8)((data >> ((3 - i) * 8)) & 0xff); + } + } + exi->state &= ~EXI_STATE_BUSY; + } } /* @@ -112,186 +72,44 @@ void CompleteTransfer(void) * Address: 800DFC48 * Size: 00025C */ -void EXIImm(void) +BOOL EXIImm(s32 chan, void* buf, s32 len, u32 type, EXICallback callback) { - /* - .loc_0x0: - mflr r0 - stw r0, 0x4(r1) - stwu r1, -0x40(r1) - stmw r25, 0x24(r1) - addi r26, r3, 0 - addi r27, r4, 0 - addi r28, r5, 0 - addi r29, r6, 0 - addi r25, r7, 0 - rlwinm r4,r3,6,0,25 - lis r3, 0x804F - addi r0, r3, 0x5F28 - add r31, r0, r4 - bl 0xEFBC - mr r30, r3 - lwz r0, 0xC(r31) - rlwinm. r0,r0,0,30,31 - bne- .loc_0x54 - lwz r0, 0xC(r31) - rlwinm. r0,r0,0,29,29 - bne- .loc_0x64 + EXIControl* exi = &Ecb[chan]; + BOOL enabled; - .loc_0x54: - mr r3, r30 - bl 0xEFC0 - li r3, 0 - b .loc_0x248 + enabled = OSDisableInterrupts(); + if ((exi->state & EXI_STATE_BUSY) || !(exi->state & EXI_STATE_SELECTED)) { + OSRestoreInterrupts(enabled); + return FALSE; + } - .loc_0x64: - stw r25, 0x4(r31) - lwz r0, 0x4(r31) - cmplwi r0, 0 - beq- .loc_0x98 - addi r3, r26, 0 - li r4, 0 - li r5, 0x1 - li r6, 0 - bl 0x5B0 - lis r3, 0x20 - mulli r0, r26, 0x3 - srw r3, r3, r0 - bl 0xF3AC + exi->tcCallback = callback; + if (exi->tcCallback) { + EXIClearInterrupts(chan, FALSE, TRUE, FALSE); + __OSUnmaskInterrupts(OS_INTERRUPTMASK_EXI_0_TC >> (3 * chan)); + } - .loc_0x98: - lwz r0, 0xC(r31) - ori r0, r0, 0x2 - stw r0, 0xC(r31) - cmplwi r29, 0 - beq- .loc_0x1EC - li r0, 0 - li r4, 0 - cmpw r4, r28 - bge- .loc_0x1D8 - subi r6, r28, 0x8 - cmpwi r28, 0x8 - ble- .loc_0x240 - addi r3, r27, 0 - addi r5, r6, 0x7 - rlwinm r5,r5,29,3,31 - mtctr r5 - cmpwi r6, 0 - ble- .loc_0x240 - - .loc_0xE0: - lbz r6, 0x0(r3) - subfic r5, r4, 0x3 - rlwinm r5,r5,3,0,28 - slw r5, r6, r5 - or r0, r0, r5 - lbz r6, 0x1(r3) - addi r5, r4, 0x1 - subfic r5, r5, 0x3 - rlwinm r5,r5,3,0,28 - slw r5, r6, r5 - or r0, r0, r5 - lbz r6, 0x2(r3) - addi r5, r4, 0x2 - subfic r5, r5, 0x3 - rlwinm r5,r5,3,0,28 - slw r5, r6, r5 - or r0, r0, r5 - lbz r6, 0x3(r3) - neg r5, r4 - rlwinm r5,r5,3,0,28 - slw r5, r6, r5 - or r0, r0, r5 - lbz r6, 0x4(r3) - addi r5, r4, 0x4 - subfic r5, r5, 0x3 - rlwinm r5,r5,3,0,28 - slw r5, r6, r5 - or r0, r0, r5 - lbz r6, 0x5(r3) - addi r5, r4, 0x5 - subfic r5, r5, 0x3 - rlwinm r5,r5,3,0,28 - slw r5, r6, r5 - or r0, r0, r5 - lbz r6, 0x6(r3) - addi r5, r4, 0x6 - subfic r5, r5, 0x3 - rlwinm r5,r5,3,0,28 - slw r5, r6, r5 - or r0, r0, r5 - lbz r6, 0x7(r3) - addi r5, r4, 0x7 - subfic r5, r5, 0x3 - rlwinm r5,r5,3,0,28 - slw r5, r6, r5 - or r0, r0, r5 - addi r3, r3, 0x8 - addi r4, r4, 0x8 - bdnz+ .loc_0xE0 - b .loc_0x240 - - .loc_0x1A8: - sub r3, r28, r4 - mtctr r3 - cmpw r4, r28 - bge- .loc_0x1D8 - - .loc_0x1B8: - lbz r5, 0x0(r6) - subfic r3, r4, 0x3 - rlwinm r3,r3,3,0,28 - slw r3, r5, r3 - or r0, r0, r3 - addi r6, r6, 0x1 - addi r4, r4, 0x1 - bdnz+ .loc_0x1B8 - - .loc_0x1D8: - lis r3, 0xCC00 - addi r4, r3, 0x6800 - mulli r3, r26, 0x14 - add r3, r4, r3 - stw r0, 0x10(r3) - - .loc_0x1EC: - stw r27, 0x14(r31) - cmplwi r29, 0x1 - beq- .loc_0x200 - mr r0, r28 - b .loc_0x204 - - .loc_0x200: - li r0, 0 + exi->state |= EXI_STATE_IMM; - .loc_0x204: - stw r0, 0x10(r31) - rlwinm r0,r29,2,0,29 - ori r3, r0, 0x1 - subi r0, r28, 0x1 - rlwinm r0,r0,4,0,27 - or r4, r3, r0 - lis r3, 0xCC00 - addi r3, r3, 0x6800 - mulli r0, r26, 0x14 - add r3, r3, r0 - stw r4, 0xC(r3) - mr r3, r30 - bl 0xEDE4 - li r3, 0x1 - b .loc_0x248 + if (type != EXI_READ) { + u32 data; + int i; - .loc_0x240: - add r6, r27, r4 - b .loc_0x1A8 + data = 0; + for (i = 0; i < len; i++) { + data |= ((u8*)buf)[i] << ((3 - i) * 8); + } + EXIREG(chan, 4) = data; + } - .loc_0x248: - lwz r0, 0x44(r1) - lmw r25, 0x24(r1) - addi r1, r1, 0x40 - mtlr r0 - blr - */ + exi->immBuf = buf; + exi->immLen = (type != EXI_WRITE) ? len : 0; + + EXIREG(chan, 3) = EXI_0CR(1, 0, type, len - 1); + + OSRestoreInterrupts(enabled); + + return TRUE; } /* @@ -299,65 +117,24 @@ void EXIImm(void) * Address: 800DFEA4 * Size: 0000A0 */ -void EXIImmEx(void) +BOOL EXIImmEx(s32 chan, void* buf, s32 len, u32 mode) { - /* - .loc_0x0: - mflr r0 - stw r0, 0x4(r1) - stwu r1, -0x30(r1) - stmw r27, 0x1C(r1) - addi r27, r3, 0 - addi r28, r4, 0 - addi r29, r5, 0 - addi r30, r6, 0 - b .loc_0x80 - - .loc_0x24: - cmpwi r29, 0x4 - bge- .loc_0x34 - mr r31, r29 - b .loc_0x38 - - .loc_0x34: - li r31, 0x4 - - .loc_0x38: - addi r5, r31, 0 - addi r3, r27, 0 - addi r4, r28, 0 - addi r6, r30, 0 - li r7, 0 - bl -0x2A8 - cmpwi r3, 0 - bne- .loc_0x60 - li r3, 0 - b .loc_0x8C - - .loc_0x60: - mr r3, r27 - bl 0x128 - cmpwi r3, 0 - bne- .loc_0x78 - li r3, 0 - b .loc_0x8C - - .loc_0x78: - add r28, r28, r31 - sub r29, r29, r31 - - .loc_0x80: - cmpwi r29, 0 - bne+ .loc_0x24 - li r3, 0x1 - - .loc_0x8C: - lwz r0, 0x34(r1) - lmw r27, 0x1C(r1) - addi r1, r1, 0x30 - mtlr r0 - blr - */ + s32 xLen; + + while (len) { + xLen = (len < 4) ? len : 4; + if (!EXIImm(chan, buf, xLen, mode, NULL)) { + return FALSE; + } + + if (!EXISync(chan)) { + return FALSE; + } + + (u8*)buf += xLen; + len -= xLen; + } + return TRUE; } /* @@ -365,78 +142,32 @@ void EXIImmEx(void) * Address: 800DFF44 * Size: 0000EC */ -void EXIDma(void) +BOOL EXIDma(s32 chan, void* buf, s32 len, u32 type, EXICallback callback) { - /* - .loc_0x0: - mflr r0 - stw r0, 0x4(r1) - stwu r1, -0x40(r1) - stmw r25, 0x24(r1) - addi r27, r3, 0 - addi r28, r4, 0 - addi r29, r5, 0 - addi r30, r6, 0 - addi r25, r7, 0 - rlwinm r4,r3,6,0,25 - lis r3, 0x804F - addi r0, r3, 0x5F28 - add r26, r0, r4 - bl 0xECC0 - mr r31, r3 - lwz r0, 0xC(r26) - rlwinm. r0,r0,0,30,31 - bne- .loc_0x54 - lwz r0, 0xC(r26) - rlwinm. r0,r0,0,29,29 - bne- .loc_0x64 - - .loc_0x54: - mr r3, r31 - bl 0xECC4 - li r3, 0 - b .loc_0xD8 + EXIControl* exi = &Ecb[chan]; + BOOL enabled; - .loc_0x64: - stw r25, 0x4(r26) - lwz r0, 0x4(r26) - cmplwi r0, 0 - beq- .loc_0x98 - addi r3, r27, 0 - li r4, 0 - li r5, 0x1 - li r6, 0 - bl 0x2B4 - lis r3, 0x20 - mulli r0, r27, 0x3 - srw r3, r3, r0 - bl 0xF0B0 + enabled = OSDisableInterrupts(); + if ((exi->state & EXI_STATE_BUSY) || !(exi->state & EXI_STATE_SELECTED)) { + OSRestoreInterrupts(enabled); + return FALSE; + } - .loc_0x98: - lwz r0, 0xC(r26) - ori r0, r0, 0x1 - stw r0, 0xC(r26) - rlwinm r4,r28,0,6,26 - lis r3, 0xCC00 - addi r0, r3, 0x6800 - mulli r3, r27, 0x14 - add r3, r0, r3 - stw r4, 0x4(r3) - stw r29, 0x8(r3) - rlwinm r0,r30,2,0,29 - ori r0, r0, 0x3 - stw r0, 0xC(r3) - mr r3, r31 - bl 0xEC4C - li r3, 0x1 + exi->tcCallback = callback; + if (exi->tcCallback) { + EXIClearInterrupts(chan, FALSE, TRUE, FALSE); + __OSUnmaskInterrupts(OS_INTERRUPTMASK_EXI_0_TC >> (3 * chan)); + } - .loc_0xD8: - lwz r0, 0x44(r1) - lmw r25, 0x24(r1) - addi r1, r1, 0x40 - mtlr r0 - blr - */ + exi->state |= EXI_STATE_DMA; + + EXIREG(chan, 1) = (u32)buf & 0x3ffffe0; + EXIREG(chan, 2) = (u32)len; + EXIREG(chan, 3) = EXI_0CR(1, 1, type, 0); + + OSRestoreInterrupts(enabled); + + return TRUE; } /* @@ -444,180 +175,29 @@ void EXIDma(void) * Address: 800E0030 * Size: 00024C */ -void EXISync(void) +BOOL EXISync(s32 chan) { - /* - .loc_0x0: - mflr r0 - stw r0, 0x4(r1) - stwu r1, -0x30(r1) - stmw r27, 0x1C(r1) - rlwinm r5,r3,6,0,25 - lis r4, 0x804F - addi r0, r4, 0x5F28 - add r31, r0, r5 - li r28, 0 - mulli r30, r3, 0x14 - lis r3, 0xCC00 - addi r29, r3, 0x6800 - add r29, r29, r30 - b .loc_0x228 - - .loc_0x38: - lwz r0, 0xC(r29) - rlwinm. r0,r0,0,31,31 - bne- .loc_0x228 - bl 0xEBC4 - mr r27, r3 - lwz r0, 0xC(r31) - rlwinm. r0,r0,0,29,29 - beq- .loc_0x21C - lwz r0, 0xC(r31) - rlwinm. r0,r0,0,30,31 - beq- .loc_0x194 - lwz r0, 0xC(r31) - rlwinm. r0,r0,0,30,30 - beq- .loc_0x188 - lwz r3, 0x10(r31) - cmpwi r3, 0 - beq- .loc_0x188 - lwz r5, 0x14(r31) - lis r4, 0xCC00 - addi r0, r4, 0x6800 - add r4, r0, r30 - lwz r0, 0x10(r4) - li r4, 0 - ble- .loc_0x188 - subi r7, r3, 0x8 - cmpwi r3, 0x8 - ble- .loc_0x15C - addi r6, r7, 0x7 - rlwinm r6,r6,29,3,31 - mtctr r6 - cmpwi r7, 0 - ble- .loc_0x15C - - .loc_0xB8: - subfic r6, r4, 0x3 - rlwinm r6,r6,3,0,28 - srw r6, r0, r6 - stb r6, 0x0(r5) - addi r6, r4, 0x1 - subfic r6, r6, 0x3 - rlwinm r6,r6,3,0,28 - srw r6, r0, r6 - stb r6, 0x1(r5) - addi r6, r4, 0x2 - subfic r6, r6, 0x3 - rlwinm r6,r6,3,0,28 - srw r6, r0, r6 - stb r6, 0x2(r5) - neg r6, r4 - rlwinm r6,r6,3,0,28 - srw r6, r0, r6 - stb r6, 0x3(r5) - addi r6, r4, 0x4 - subfic r6, r6, 0x3 - rlwinm r6,r6,3,0,28 - srw r6, r0, r6 - stb r6, 0x4(r5) - addi r6, r4, 0x5 - subfic r6, r6, 0x3 - rlwinm r6,r6,3,0,28 - srw r6, r0, r6 - stb r6, 0x5(r5) - addi r6, r4, 0x6 - subfic r6, r6, 0x3 - rlwinm r6,r6,3,0,28 - srw r6, r0, r6 - stb r6, 0x6(r5) - addi r6, r4, 0x7 - subfic r6, r6, 0x3 - rlwinm r6,r6,3,0,28 - srw r6, r0, r6 - stb r6, 0x7(r5) - addi r5, r5, 0x8 - addi r4, r4, 0x8 - bdnz+ .loc_0xB8 - - .loc_0x15C: - sub r6, r3, r4 - mtctr r6 - cmpw r4, r3 - bge- .loc_0x188 - - .loc_0x16C: - subfic r3, r4, 0x3 - rlwinm r3,r3,3,0,28 - srw r3, r0, r3 - stb r3, 0x0(r5) - addi r5, r5, 0x1 - addi r4, r4, 0x1 - bdnz+ .loc_0x16C - - .loc_0x188: - lwz r0, 0xC(r31) - rlwinm r0,r0,0,0,29 - stw r0, 0xC(r31) - - .loc_0x194: - bl 0xB8B0 - cmplwi r3, 0xFF - bne- .loc_0x218 - bl 0xAF20 - rlwinm r3,r3,0,0,3 - subis r0, r3, 0x2000 - cmplwi r0, 0 - beq- .loc_0x218 - lwz r0, 0x10(r31) - cmpwi r0, 0x4 - bne- .loc_0x218 - lwz r0, 0x0(r29) - rlwinm. r0,r0,0,25,27 - bne- .loc_0x218 - lis r3, 0xCC00 - addi r0, r3, 0x6800 - add r4, r0, r30 - lwzu r3, 0x10(r4) - subis r0, r3, 0x101 - cmplwi r0, 0 - beq- .loc_0x208 - lwz r3, 0x0(r4) - subis r0, r3, 0x507 - cmplwi r0, 0 - beq- .loc_0x208 - lwz r3, 0x0(r4) - subis r0, r3, 0x422 - cmplwi r0, 0x1 - bne- .loc_0x218 - - .loc_0x208: - lis r3, 0x8000 - lhz r0, 0x30E6(r3) - cmplwi r0, 0x8200 - bne- .loc_0x21C - - .loc_0x218: - li r28, 0x1 - - .loc_0x21C: - mr r3, r27 - bl 0xEA10 - b .loc_0x234 - - .loc_0x228: - lwz r0, 0xC(r31) - rlwinm. r0,r0,0,29,29 - bne+ .loc_0x38 - - .loc_0x234: - mr r3, r28 - lwz r0, 0x34(r1) - lmw r27, 0x1C(r1) - addi r1, r1, 0x30 - mtlr r0 - blr - */ + EXIControl* exi = &Ecb[chan]; + BOOL rc = FALSE; + BOOL enabled; + + while (exi->state & EXI_STATE_SELECTED) { + if (((EXIREG(chan, 3) & 1) >> 0) == 0) { + enabled = OSDisableInterrupts(); + if (exi->state & EXI_STATE_SELECTED) { + CompleteTransfer(chan); + if (__OSGetDIConfig() != 0xff || ((OSGetConsoleType() & 0xF0000000) == OS_CONSOLE_TDEVKIT) || exi->immLen != 4 + || (EXIREG(chan, 0) & 0x00000070) != (EXI_FREQ_1M << 4) + || (EXIREG(chan, 4) != EXI_USB_ADAPTER && EXIREG(chan, 4) != EXI_IS_VIEWER && EXIREG(chan, 4) != 0x04220001) + || __OSDeviceCode == 0x8200) { + rc = TRUE; + } + } + OSRestoreInterrupts(enabled); + break; + } + } + return rc; } /* @@ -625,35 +205,21 @@ void EXISync(void) * Address: 800E027C * Size: 000048 */ -void EXIClearInterrupts(void) +int EXIClearInterrupts(s32 chan, BOOL exi, BOOL tc, BOOL ext) { - /* - .loc_0x0: - mulli r0, r3, 0x14 - lis r3, 0xCC00 - addi r7, r3, 0x6800 - add r7, r7, r0 - lwz r0, 0x0(r7) - mr r3, r0 - andi. r0, r0, 0x7F5 - cmpwi r4, 0 - beq- .loc_0x28 - ori r0, r0, 0x2 - - .loc_0x28: - cmpwi r5, 0 - beq- .loc_0x34 - ori r0, r0, 0x8 - - .loc_0x34: - cmpwi r6, 0 - beq- .loc_0x40 - ori r0, r0, 0x800 - - .loc_0x40: - stw r0, 0x0(r7) - blr - */ + u32 cpr; + u32 prev; + + prev = cpr = EXIREG(chan, 0); + cpr &= 0x7f5; + if (exi) + cpr |= 2; + if (tc) + cpr |= 8; + if (ext) + cpr |= 0x800; + EXIREG(chan, 0) = cpr; + return prev; } /* @@ -661,46 +227,24 @@ void EXIClearInterrupts(void) * Address: 800E02C4 * Size: 00007C */ -void EXISetExiCallback(void) +EXICallback EXISetExiCallback(s32 chan, EXICallback exiCallback) { - /* - .loc_0x0: - mflr r0 - stw r0, 0x4(r1) - stwu r1, -0x28(r1) - stmw r26, 0x10(r1) - addi r26, r3, 0 - addi r27, r4, 0 - rlwinm r0,r3,6,0,25 - lis r3, 0x804F - addi r31, r3, 0x5F28 - add r30, r31, r0 - bl 0xE94C - mr r28, r3 - lwz r29, 0x0(r30) - stw r27, 0x0(r30) - cmpwi r26, 0x2 - beq- .loc_0x50 - addi r3, r26, 0 - addi r4, r30, 0 - bl -0x7B8 - b .loc_0x5C - - .loc_0x50: - li r3, 0 - addi r4, r31, 0 - bl -0x7C8 - - .loc_0x5C: - mr r3, r28 - bl 0xE93C - mr r3, r29 - lwz r0, 0x2C(r1) - lmw r26, 0x10(r1) - addi r1, r1, 0x28 - mtlr r0 - blr - */ + EXIControl* exi = &Ecb[chan]; + EXICallback prev; + BOOL enabled; + + enabled = OSDisableInterrupts(); + prev = exi->exiCallback; + exi->exiCallback = exiCallback; + + if (chan != 2) { + SetExiInterruptMask(chan, exi); + } else { + SetExiInterruptMask(0, &Ecb[0]); + } + + OSRestoreInterrupts(enabled); + return prev; } /* @@ -710,7 +254,10 @@ void EXISetExiCallback(void) */ void EXIProbeReset(void) { - // UNUSED FUNCTION + __EXIProbeStartTime[0] = __EXIProbeStartTime[1] = 0; + Ecb[0].idTime = Ecb[1].idTime = 0; + __EXIProbe(0); + __EXIProbe(1); } /* @@ -718,596 +265,236 @@ void EXIProbeReset(void) * Address: 800E0340 * Size: 000174 */ -void __EXIProbe(void) +static BOOL __EXIProbe(s32 chan) { - /* - .loc_0x0: - mflr r0 - stw r0, 0x4(r1) - stwu r1, -0x28(r1) - stmw r27, 0x14(r1) - addi r28, r3, 0 - rlwinm r4,r3,6,0,25 - lis r3, 0x804F - addi r0, r3, 0x5F28 - add r31, r0, r4 - cmpwi r28, 0x2 - bne- .loc_0x34 - li r3, 0x1 - b .loc_0x160 - - .loc_0x34: - li r29, 0x1 - bl 0xE8C0 - addi r30, r3, 0 - mulli r0, r28, 0x14 - lis r3, 0xCC00 - addi r3, r3, 0x6800 - add r3, r3, r0 - lwz r5, 0x0(r3) - lwz r0, 0xC(r31) - rlwinm. r0,r0,0,28,28 - bne- .loc_0x128 - rlwinm. r0,r5,0,20,20 - beq- .loc_0x90 - lwz r0, 0x0(r3) - andi. r0, r0, 0x7F5 - ori r0, r0, 0x800 - stw r0, 0x0(r3) - li r4, 0 - stw r4, 0x20(r31) - rlwinm r0,r28,2,0,29 - lis r3, 0x8000 - addi r3, r3, 0x30C0 - stwx r4, r3, r0 - - .loc_0x90: - rlwinm. r0,r5,0,19,19 - beq- .loc_0x108 - lis r31, 0x8000 - lwz r0, 0xF8(r31) - rlwinm r0,r0,30,2,31 - lis r3, 0x1062 - addi r3, r3, 0x4DD3 - mulhwu r0, r3, r0 - rlwinm r27,r0,26,6,31 - bl 0x1279C - li r5, 0 - addi r6, r27, 0 - bl -0x1E63C - li r5, 0 - li r6, 0x64 - bl -0x1E648 - addi r4, r4, 0x1 - rlwinm r0,r28,2,0,29 - addi r3, r31, 0x30C0 - add r3, r3, r0 - lwz r0, 0x0(r3) - cmpwi r0, 0 - bne- .loc_0xF0 - stw r4, 0x0(r3) - - .loc_0xF0: - lwz r0, 0x0(r3) - sub r0, r4, r0 - cmpwi r0, 0x3 - bge- .loc_0x154 - li r29, 0 - b .loc_0x154 - - .loc_0x108: - li r4, 0 - stw r4, 0x20(r31) - rlwinm r0,r28,2,0,29 - lis r3, 0x8000 - addi r3, r3, 0x30C0 - stwx r4, r3, r0 - li r29, 0 - b .loc_0x154 - - .loc_0x128: - rlwinm. r0,r5,0,19,19 - beq- .loc_0x138 - rlwinm. r0,r5,0,20,20 - beq- .loc_0x154 - - .loc_0x138: - li r4, 0 - stw r4, 0x20(r31) - rlwinm r0,r28,2,0,29 - lis r3, 0x8000 - addi r3, r3, 0x30C0 - stwx r4, r3, r0 - li r29, 0 - - .loc_0x154: - mr r3, r30 - bl 0xE7C8 - mr r3, r29 - - .loc_0x160: - lwz r0, 0x2C(r1) - lmw r27, 0x14(r1) - addi r1, r1, 0x28 - mtlr r0 - blr - */ + EXIControl* exi = &Ecb[chan]; + BOOL enabled; + BOOL rc; + u32 cpr; + s32 t; + + if (chan == 2) { + return TRUE; + } + + rc = TRUE; + enabled = OSDisableInterrupts(); + cpr = EXIREG(chan, 0); + if (!(exi->state & EXI_STATE_ATTACHED)) { + if (cpr & 0x00000800) { + EXIClearInterrupts(chan, FALSE, FALSE, TRUE); + __EXIProbeStartTime[chan] = exi->idTime = 0; + } + + if (cpr & 0x00001000) { + t = (s32)(OSTicksToMilliseconds(OSGetTime()) / 100) + 1; + if (__EXIProbeStartTime[chan] == 0) { + __EXIProbeStartTime[chan] = t; + } + if (t - __EXIProbeStartTime[chan] < 300 / 100) { + rc = FALSE; + } + } else { + __EXIProbeStartTime[chan] = exi->idTime = 0; + rc = FALSE; + } + } else if (!(cpr & 0x00001000) || (cpr & 0x00000800)) { + __EXIProbeStartTime[chan] = exi->idTime = 0; + rc = FALSE; + } + OSRestoreInterrupts(enabled); + + return rc; } /* - * --INFO-- - * Address: 800E04B4 - * Size: 000080 - */ -void EXIProbe(void) -{ - /* - .loc_0x0: - mflr r0 - stw r0, 0x4(r1) - stwu r1, -0x18(r1) - stw r31, 0x14(r1) - stw r30, 0x10(r1) - addi r30, r3, 0 - rlwinm r4,r3,6,0,25 - lis r3, 0x804F - addi r0, r3, 0x5F28 - add r31, r0, r4 - addi r3, r30, 0 - bl -0x1A0 - cmpwi r3, 0 - beq- .loc_0x68 - lwz r0, 0x20(r31) - cmpwi r0, 0 - bne- .loc_0x68 - addi r3, r30, 0 - li r4, 0 - addi r5, r1, 0xC - bl 0xC7C - cmpwi r3, 0 - beq- .loc_0x64 - li r3, 0x1 - b .loc_0x68 - - .loc_0x64: - li r3, 0 - - .loc_0x68: - lwz r0, 0x1C(r1) - lwz r31, 0x14(r1) - lwz r30, 0x10(r1) - addi r1, r1, 0x18 - mtlr r0 - blr - */ -} - -/* - * --INFO-- - * Address: 800E0534 - * Size: 0000B4 - */ -void EXIProbeEx(void) -{ - /* - .loc_0x0: - mflr r0 - stw r0, 0x4(r1) - stwu r1, -0x18(r1) - stw r31, 0x14(r1) - stw r30, 0x10(r1) - addi r30, r3, 0 - rlwinm r4,r3,6,0,25 - lis r3, 0x804F - addi r0, r3, 0x5F28 - add r31, r0, r4 - addi r3, r30, 0 - bl -0x220 - cmpwi r3, 0 - beq- .loc_0x68 - lwz r0, 0x20(r31) - cmpwi r0, 0 - bne- .loc_0x68 - addi r3, r30, 0 - li r4, 0 - addi r5, r1, 0xC - bl 0xBFC - cmpwi r3, 0 - beq- .loc_0x64 - li r3, 0x1 - b .loc_0x68 - - .loc_0x64: - li r3, 0 - - .loc_0x68: - cmpwi r3, 0 - beq- .loc_0x78 - li r3, 0x1 - b .loc_0x9C - - .loc_0x78: - rlwinm r0,r30,2,0,29 - lis r3, 0x8000 - addi r3, r3, 0x30C0 - lwzx r0, r3, r0 - cmpwi r0, 0 - beq- .loc_0x98 - li r3, 0 - b .loc_0x9C - - .loc_0x98: - li r3, -0x1 - - .loc_0x9C: - lwz r0, 0x1C(r1) - lwz r31, 0x14(r1) - lwz r30, 0x10(r1) - addi r1, r1, 0x18 - mtlr r0 - blr - */ -} - -/* - * --INFO-- - * Address: ........ - * Size: 0000D4 - */ -void __EXIAttach(void) -{ - // UNUSED FUNCTION -} - -/* - * --INFO-- - * Address: 800E05E8 - * Size: 00010C - */ -void EXIAttach(void) -{ - /* - .loc_0x0: - mflr r0 - stw r0, 0x4(r1) - stwu r1, -0x40(r1) - stmw r27, 0x2C(r1) - addi r27, r3, 0 - addi r28, r4, 0 - rlwinm r4,r3,6,0,25 - lis r3, 0x804F - addi r0, r3, 0x5F28 - add r30, r0, r4 - addi r3, r27, 0 - bl -0x2D4 - cmpwi r3, 0 - beq- .loc_0x54 - lwz r0, 0x20(r30) - cmpwi r0, 0 - bne- .loc_0x54 - addi r3, r27, 0 - li r4, 0 - addi r5, r1, 0x1C - bl 0xB48 - - .loc_0x54: - bl 0xE5FC - mr r29, r3 - lwz r0, 0x20(r30) - cmpwi r0, 0 - bne- .loc_0x78 - mr r3, r29 - bl 0xE60C - li r3, 0 - b .loc_0xF8 - - .loc_0x78: - bl 0xE5D8 - mr r31, r3 - lwz r0, 0xC(r30) - rlwinm. r0,r0,0,28,28 - bne- .loc_0x9C - mr r3, r27 - bl -0x338 - cmpwi r3, 0 - bne- .loc_0xAC - - .loc_0x9C: - mr r3, r31 - bl 0xE5D8 - li r31, 0 - b .loc_0xEC - - .loc_0xAC: - addi r3, r27, 0 - li r4, 0x1 - li r5, 0 - li r6, 0 - bl -0x428 - stw r28, 0x8(r30) - lis r3, 0x10 - mulli r0, r27, 0x3 - srw r3, r3, r0 - bl 0xE9D0 - lwz r0, 0xC(r30) - ori r0, r0, 0x8 - stw r0, 0xC(r30) - mr r3, r31 - bl 0xE594 - li r31, 0x1 - - .loc_0xEC: - mr r3, r29 - bl 0xE588 - mr r3, r31 - - .loc_0xF8: - lwz r0, 0x44(r1) - lmw r27, 0x2C(r1) - addi r1, r1, 0x40 - mtlr r0 - blr - */ -} - -/* - * --INFO-- - * Address: 800E06F4 - * Size: 0000BC - */ -void EXIDetach(void) -{ - /* - .loc_0x0: - mflr r0 - stw r0, 0x4(r1) - stwu r1, -0x20(r1) - stw r31, 0x1C(r1) - stw r30, 0x18(r1) - stw r29, 0x14(r1) - addi r29, r3, 0 - rlwinm r4,r3,6,0,25 - lis r3, 0x804F - addi r0, r3, 0x5F28 - add r31, r0, r4 - bl 0xE518 - mr r30, r3 - lwz r0, 0xC(r31) - rlwinm. r0,r0,0,28,28 - bne- .loc_0x50 - mr r3, r30 - bl 0xE528 - li r3, 0x1 - b .loc_0xA0 - - .loc_0x50: - lwz r0, 0xC(r31) - rlwinm. r0,r0,0,27,27 - beq- .loc_0x78 - lwz r0, 0x18(r31) - cmplwi r0, 0 - bne- .loc_0x78 - mr r3, r30 - bl 0xE500 - li r3, 0 - b .loc_0xA0 - - .loc_0x78: - lwz r0, 0xC(r31) - rlwinm r0,r0,0,29,27 - stw r0, 0xC(r31) - lis r3, 0x50 - mulli r0, r29, 0x3 - srw r3, r3, r0 - bl 0xE87C - mr r3, r30 - bl 0xE4D4 - li r3, 0x1 - - .loc_0xA0: - lwz r0, 0x24(r1) - lwz r31, 0x1C(r1) - lwz r30, 0x18(r1) - lwz r29, 0x14(r1) - addi r1, r1, 0x20 - mtlr r0 - blr - */ + * --INFO-- + * Address: 800E04B4 + * Size: 000080 + */ +BOOL EXIProbe(s32 chan) +{ + EXIControl* exi = &Ecb[chan]; + BOOL rc; + u32 id; + + rc = __EXIProbe(chan); + if (rc && exi->idTime == 0) { + rc = EXIGetID(chan, 0, &id) ? TRUE : FALSE; + } + return rc; } /* * --INFO-- - * Address: 800E07B0 - * Size: 00012C + * Address: 800E0534 + * Size: 0000B4 */ -void EXISelect(void) +s32 EXIProbeEx(s32 chan) { - /* - .loc_0x0: - mflr r0 - stw r0, 0x4(r1) - stwu r1, -0x30(r1) - stmw r27, 0x1C(r1) - addi r27, r3, 0 - addi r28, r4, 0 - addi r29, r5, 0 - rlwinm r4,r3,6,0,25 - lis r3, 0x804F - addi r0, r3, 0x5F28 - add r31, r0, r4 - bl 0xE45C - mr r30, r3 - lwz r0, 0xC(r31) - rlwinm. r0,r0,0,29,29 - bne- .loc_0x84 - cmpwi r27, 0x2 - beq- .loc_0x94 - cmplwi r28, 0 - bne- .loc_0x6C - lwz r0, 0xC(r31) - rlwinm. r0,r0,0,28,28 - bne- .loc_0x6C - mr r3, r27 - bl -0x4D0 - cmpwi r3, 0 - beq- .loc_0x84 - - .loc_0x6C: - lwz r0, 0xC(r31) - rlwinm. r0,r0,0,27,27 - beq- .loc_0x84 - lwz r0, 0x18(r31) - cmplw r0, r28 - beq- .loc_0x94 + if (EXIProbe(chan)) { + return 1; + } else if (__EXIProbeStartTime[chan] != 0) { + return 0; + } else { + return -1; + } +} - .loc_0x84: - mr r3, r30 - bl 0xE428 - li r3, 0 - b .loc_0x118 +/* + * --INFO-- + * Address: ........ + * Size: 0000D4 + */ +static BOOL __EXIAttach(s32 chan, EXICallback extCallback) +{ + EXIControl* exi = &Ecb[chan]; + BOOL enabled; - .loc_0x94: - lwz r0, 0xC(r31) - ori r0, r0, 0x4 - stw r0, 0xC(r31) - mulli r0, r27, 0x14 - lis r3, 0xCC00 - addi r4, r3, 0x6800 - add r4, r4, r0 - lwz r5, 0x0(r4) - andi. r5, r5, 0x405 - li r0, 0x1 - slw r0, r0, r28 - rlwinm r3,r0,7,0,24 - rlwinm r0,r29,4,0,27 - or r0, r3, r0 - or r5, r5, r0 - stw r5, 0x0(r4) - lwz r0, 0xC(r31) - rlwinm. r0,r0,0,28,28 - beq- .loc_0x10C - cmpwi r27, 0x1 - beq- .loc_0x104 - bge- .loc_0x10C - cmpwi r27, 0 - bge- .loc_0xF8 - b .loc_0x10C - - .loc_0xF8: - lis r3, 0x10 - bl 0xE754 - b .loc_0x10C + enabled = OSDisableInterrupts(); + if ((exi->state & EXI_STATE_ATTACHED) || __EXIProbe(chan) == FALSE) { + OSRestoreInterrupts(enabled); + return FALSE; + } - .loc_0x104: - lis r3, 0x2 - bl 0xE748 + EXIClearInterrupts(chan, TRUE, FALSE, FALSE); - .loc_0x10C: - mr r3, r30 - bl 0xE3A0 - li r3, 0x1 + exi->extCallback = extCallback; + __OSUnmaskInterrupts(OS_INTERRUPTMASK_EXI_0_EXT >> (3 * chan)); + exi->state |= EXI_STATE_ATTACHED; + OSRestoreInterrupts(enabled); - .loc_0x118: - lwz r0, 0x34(r1) - lmw r27, 0x1C(r1) - addi r1, r1, 0x30 - mtlr r0 - blr - */ + return TRUE; } /* * --INFO-- - * Address: 800E08DC - * Size: 000110 + * Address: 800E05E8 + * Size: 00010C */ -void EXIDeselect(void) +BOOL EXIAttach(s32 chan, EXICallback extCallback) { - /* - .loc_0x0: - mflr r0 - stw r0, 0x4(r1) - stwu r1, -0x20(r1) - stw r31, 0x1C(r1) - stw r30, 0x18(r1) - stw r29, 0x14(r1) - stw r28, 0x10(r1) - addi r31, r3, 0 - rlwinm r4,r3,6,0,25 - lis r3, 0x804F - addi r0, r3, 0x5F28 - add r30, r0, r4 - bl 0xE32C - mr r28, r3 - lwz r0, 0xC(r30) - rlwinm. r0,r0,0,29,29 - bne- .loc_0x54 - mr r3, r28 - bl 0xE33C - li r3, 0 - b .loc_0xF0 - - .loc_0x54: - lwz r0, 0xC(r30) - rlwinm r0,r0,0,30,28 - stw r0, 0xC(r30) - mulli r0, r31, 0x14 - lis r3, 0xCC00 - addi r3, r3, 0x6800 - add r3, r3, r0 - lwz r29, 0x0(r3) - andi. r0, r29, 0x405 - stw r0, 0x0(r3) - lwz r0, 0xC(r30) - rlwinm. r0,r0,0,28,28 - beq- .loc_0xB4 - cmpwi r31, 0x1 - beq- .loc_0xAC - bge- .loc_0xB4 - cmpwi r31, 0 - bge- .loc_0xA0 - b .loc_0xB4 - - .loc_0xA0: - lis r3, 0x10 - bl 0xE708 - b .loc_0xB4 - - .loc_0xAC: - lis r3, 0x2 - bl 0xE6FC - - .loc_0xB4: - mr r3, r28 - bl 0xE2CC - cmpwi r31, 0x2 - beq- .loc_0xEC - rlwinm. r0,r29,0,24,24 - beq- .loc_0xEC - mr r3, r31 - bl -0x66C - cmpwi r3, 0 - beq- .loc_0xE4 - li r3, 0x1 - b .loc_0xF0 + EXIControl* exi = &Ecb[chan]; + BOOL enabled; + BOOL rc; + + EXIProbe(chan); + + enabled = OSDisableInterrupts(); + if (exi->idTime == 0) { + OSRestoreInterrupts(enabled); + return FALSE; + } + rc = __EXIAttach(chan, extCallback); + OSRestoreInterrupts(enabled); + return rc; +} - .loc_0xE4: - li r3, 0 - b .loc_0xF0 +/* + * --INFO-- + * Address: 800E06F4 + * Size: 0000BC + */ +BOOL EXIDetach(s32 chan) +{ + EXIControl* exi = &Ecb[chan]; + BOOL enabled; + + enabled = OSDisableInterrupts(); + if (!(exi->state & EXI_STATE_ATTACHED)) { + OSRestoreInterrupts(enabled); + return TRUE; + } + if ((exi->state & EXI_STATE_LOCKED) && exi->dev == 0) { + OSRestoreInterrupts(enabled); + return FALSE; + } + + exi->state &= ~EXI_STATE_ATTACHED; + __OSMaskInterrupts((OS_INTERRUPTMASK_EXI_0_EXT | OS_INTERRUPTMASK_EXI_0_EXI) >> (3 * chan)); + OSRestoreInterrupts(enabled); + return TRUE; +} - .loc_0xEC: - li r3, 0x1 +/* + * --INFO-- + * Address: 800E07B0 + * Size: 00012C + */ +BOOL EXISelect(s32 chan, u32 dev, u32 freq) +{ + EXIControl* exi = &Ecb[chan]; + u32 cpr; + BOOL enabled; + + enabled = OSDisableInterrupts(); + if ((exi->state & EXI_STATE_SELECTED) + || chan != 2 + && (dev == 0 && !(exi->state & EXI_STATE_ATTACHED) && !__EXIProbe(chan) || !(exi->state & EXI_STATE_LOCKED) + || (exi->dev != dev))) { + OSRestoreInterrupts(enabled); + return FALSE; + } + + exi->state |= EXI_STATE_SELECTED; + cpr = EXIREG(chan, 0); + cpr &= 0x405; + cpr |= EXI_CPR_CS(dev) | EXI_CPR_CLK(freq); + EXIREG(chan, 0) = cpr; + + if (exi->state & EXI_STATE_ATTACHED) { + switch (chan) { + case 0: + __OSMaskInterrupts(OS_INTERRUPTMASK_EXI_0_EXT); + break; + case 1: + __OSMaskInterrupts(OS_INTERRUPTMASK_EXI_1_EXT); + break; + } + } + + OSRestoreInterrupts(enabled); + return TRUE; +} - .loc_0xF0: - lwz r0, 0x24(r1) - lwz r31, 0x1C(r1) - lwz r30, 0x18(r1) - lwz r29, 0x14(r1) - lwz r28, 0x10(r1) - addi r1, r1, 0x20 - mtlr r0 - blr - */ +/* + * --INFO-- + * Address: 800E08DC + * Size: 000110 + */ +BOOL EXIDeselect(s32 chan) +{ + EXIControl* exi = &Ecb[chan]; + u32 cpr; + BOOL enabled; + + enabled = OSDisableInterrupts(); + if (!(exi->state & EXI_STATE_SELECTED)) { + OSRestoreInterrupts(enabled); + return FALSE; + } + exi->state &= ~EXI_STATE_SELECTED; + cpr = EXIREG(chan, 0); + EXIREG(chan, 0) = cpr & 0x405; + + if (exi->state & EXI_STATE_ATTACHED) { + switch (chan) { + case 0: + __OSUnmaskInterrupts(OS_INTERRUPTMASK_EXI_0_EXT); + break; + case 1: + __OSUnmaskInterrupts(OS_INTERRUPTMASK_EXI_1_EXT); + break; + } + } + + OSRestoreInterrupts(enabled); + + if (chan != 2 && (cpr & EXI_CPR_CS(0))) { + return __EXIProbe(chan) ? TRUE : FALSE; + } + + return TRUE; } /* @@ -1315,63 +502,34 @@ void EXIDeselect(void) * Address: 800E09EC * Size: 0000C8 */ -void EXIIntrruptHandler(void) +static void EXIIntrruptHandler(__OSInterrupt interrupt, OSContext* context) { - /* - .loc_0x0: - mflr r0 - stw r0, 0x4(r1) - stwu r1, -0x2F8(r1) - stw r31, 0x2F4(r1) - stw r30, 0x2F0(r1) - stw r29, 0x2EC(r1) - addi r31, r4, 0 - extsh r3, r3 - subi r0, r3, 0x9 - lis r3, 0x5555 - addi r3, r3, 0x5556 - mulhw r3, r3, r0 - rlwinm r0,r3,1,31,31 - add r30, r3, r0 - mulli r0, r30, 0x14 - lis r3, 0xCC00 - addi r3, r3, 0x6800 - add r3, r3, r0 - lwz r0, 0x0(r3) - andi. r0, r0, 0x7F5 - ori r0, r0, 0x2 - stw r0, 0x0(r3) - rlwinm r4,r30,6,0,25 - lis r3, 0x804F - addi r0, r3, 0x5F28 - add r3, r0, r4 - lwz r0, 0x0(r3) - mr r29, r0 - cmplwi r0, 0 - beq- .loc_0xAC - addi r3, r1, 0x18 - bl 0xC704 - addi r3, r1, 0x18 - bl 0xC534 - addi r3, r30, 0 - addi r4, r31, 0 - addi r12, r29, 0 - mtlr r12 - blrl - addi r3, r1, 0x18 - bl 0xC6E0 - mr r3, r31 - bl 0xC510 - - .loc_0xAC: - lwz r0, 0x2FC(r1) - lwz r31, 0x2F4(r1) - lwz r30, 0x2F0(r1) - lwz r29, 0x2EC(r1) - addi r1, r1, 0x2F8 - mtlr r0 - blr - */ + + s32 chan; + EXIControl* exi; + EXICallback callback; + + chan = (interrupt - __OS_INTERRUPT_EXI_0_EXI) / 3; + exi = &Ecb[chan]; + EXIClearInterrupts(chan, TRUE, FALSE, FALSE); + callback = exi->exiCallback; + if (callback) { + OSContext exceptionContext; + + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + + callback(chan, context); + + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); + } + + // needed for stack fixing + { + s32 dummy1; + s32 dummy2; + } } /* @@ -1379,157 +537,36 @@ void EXIIntrruptHandler(void) * Address: 800E0AB4 * Size: 000218 */ -void TCIntrruptHandler(void) +static void TCIntrruptHandler(__OSInterrupt interrupt, OSContext* context) { - /* - .loc_0x0: - mflr r0 - stw r0, 0x4(r1) - stwu r1, -0x2F8(r1) - stw r31, 0x2F4(r1) - stw r30, 0x2F0(r1) - stw r29, 0x2EC(r1) - stw r28, 0x2E8(r1) - addi r28, r4, 0 - extsh r5, r3 - subi r0, r5, 0xA - lis r3, 0x5555 - addi r3, r3, 0x5556 - mulhw r3, r3, r0 - rlwinm r0,r3,1,31,31 - add r30, r3, r0 - rlwinm r4,r30,6,0,25 - lis r3, 0x804F - addi r0, r3, 0x5F28 - add r31, r0, r4 - lis r0, 0x8000 - srw r3, r0, r5 - bl 0xE4F8 - mulli r7, r30, 0x14 - lis r6, 0xCC00 - addi r3, r6, 0x6800 - add r3, r3, r7 - lwz r0, 0x0(r3) - andi. r0, r0, 0x7F5 - ori r0, r0, 0x8 - stw r0, 0x0(r3) - lwz r0, 0x4(r31) - mr r29, r0 - cmplwi r0, 0 - beq- .loc_0x1F8 - li r4, 0 - stw r4, 0x4(r31) - lwz r0, 0xC(r31) - rlwinm. r0,r0,0,30,31 - beq- .loc_0x1C4 - lwz r0, 0xC(r31) - rlwinm. r0,r0,0,30,30 - beq- .loc_0x1B8 - lwz r3, 0x10(r31) - cmpwi r3, 0 - beq- .loc_0x1B8 - lwz r5, 0x14(r31) - addi r0, r6, 0x6800 - add r6, r0, r7 - lwz r0, 0x10(r6) - ble- .loc_0x1B8 - subi r7, r3, 0x8 - cmpwi r3, 0x8 - ble- .loc_0x18C - addi r6, r7, 0x7 - rlwinm r6,r6,29,3,31 - mtctr r6 - cmpwi r7, 0 - ble- .loc_0x18C - - .loc_0xE8: - subfic r6, r4, 0x3 - rlwinm r6,r6,3,0,28 - srw r6, r0, r6 - stb r6, 0x0(r5) - addi r6, r4, 0x1 - subfic r6, r6, 0x3 - rlwinm r6,r6,3,0,28 - srw r6, r0, r6 - stb r6, 0x1(r5) - addi r6, r4, 0x2 - subfic r6, r6, 0x3 - rlwinm r6,r6,3,0,28 - srw r6, r0, r6 - stb r6, 0x2(r5) - neg r6, r4 - rlwinm r6,r6,3,0,28 - srw r6, r0, r6 - stb r6, 0x3(r5) - addi r6, r4, 0x4 - subfic r6, r6, 0x3 - rlwinm r6,r6,3,0,28 - srw r6, r0, r6 - stb r6, 0x4(r5) - addi r6, r4, 0x5 - subfic r6, r6, 0x3 - rlwinm r6,r6,3,0,28 - srw r6, r0, r6 - stb r6, 0x5(r5) - addi r6, r4, 0x6 - subfic r6, r6, 0x3 - rlwinm r6,r6,3,0,28 - srw r6, r0, r6 - stb r6, 0x6(r5) - addi r6, r4, 0x7 - subfic r6, r6, 0x3 - rlwinm r6,r6,3,0,28 - srw r6, r0, r6 - stb r6, 0x7(r5) - addi r5, r5, 0x8 - addi r4, r4, 0x8 - bdnz+ .loc_0xE8 - - .loc_0x18C: - sub r6, r3, r4 - mtctr r6 - cmpw r4, r3 - bge- .loc_0x1B8 - - .loc_0x19C: - subfic r3, r4, 0x3 - rlwinm r3,r3,3,0,28 - srw r3, r0, r3 - stb r3, 0x0(r5) - addi r5, r5, 0x1 - addi r4, r4, 0x1 - bdnz+ .loc_0x19C - - .loc_0x1B8: - lwz r0, 0xC(r31) - rlwinm r0,r0,0,0,29 - stw r0, 0xC(r31) - - .loc_0x1C4: - addi r3, r1, 0x20 - bl 0xC4F0 - addi r3, r1, 0x20 - bl 0xC320 - addi r3, r30, 0 - addi r4, r28, 0 - addi r12, r29, 0 - mtlr r12 - blrl - addi r3, r1, 0x20 - bl 0xC4CC - mr r3, r28 - bl 0xC2FC - - .loc_0x1F8: - lwz r0, 0x2FC(r1) - lwz r31, 0x2F4(r1) - lwz r30, 0x2F0(r1) - lwz r29, 0x2EC(r1) - lwz r28, 0x2E8(r1) - addi r1, r1, 0x2F8 - mtlr r0 - blr - */ + OSContext exceptionContext; + s32 chan; + EXIControl* exi; + EXICallback callback; + + chan = (interrupt - __OS_INTERRUPT_EXI_0_TC) / 3; + exi = &Ecb[chan]; + __OSMaskInterrupts(OS_INTERRUPTMASK(interrupt)); + EXIClearInterrupts(chan, FALSE, TRUE, FALSE); + callback = exi->tcCallback; + if (callback) { + exi->tcCallback = 0; + CompleteTransfer(chan); + + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + + callback(chan, context); + + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); + } + + // needed for stack fixing + { + s32 dummy1; + s32 dummy2; + } } /* @@ -1537,65 +574,29 @@ void TCIntrruptHandler(void) * Address: 800E0CCC * Size: 0000D0 */ -void EXTIntrruptHandler(void) +static void EXTIntrruptHandler(__OSInterrupt interrupt, OSContext* context) { - /* - .loc_0x0: - mflr r0 - stw r0, 0x4(r1) - stwu r1, -0x2E8(r1) - stw r31, 0x2E4(r1) - stw r30, 0x2E0(r1) - stw r29, 0x2DC(r1) - stw r28, 0x2D8(r1) - addi r31, r4, 0 - extsh r3, r3 - subi r0, r3, 0xB - lis r3, 0x5555 - addi r3, r3, 0x5556 - mulhw r3, r3, r0 - rlwinm r0,r3,1,31,31 - add r30, r3, r0 - lis r3, 0x50 - mulli r0, r30, 0x3 - srw r3, r3, r0 - bl 0xE2EC - rlwinm r4,r30,6,0,25 - lis r3, 0x804F - addi r0, r3, 0x5F28 - add r29, r0, r4 - lwz r28, 0x8(r29) - lwz r0, 0xC(r29) - rlwinm r0,r0,0,29,27 - stw r0, 0xC(r29) - cmplwi r28, 0 - beq- .loc_0xB0 - addi r3, r1, 0x10 - bl 0xC428 - addi r3, r1, 0x10 - bl 0xC258 - li r0, 0 - stw r0, 0x8(r29) - addi r3, r30, 0 - addi r4, r31, 0 - addi r12, r28, 0 - mtlr r12 - blrl - addi r3, r1, 0x10 - bl 0xC3FC - mr r3, r31 - bl 0xC22C - - .loc_0xB0: - lwz r0, 0x2EC(r1) - lwz r31, 0x2E4(r1) - lwz r30, 0x2E0(r1) - lwz r29, 0x2DC(r1) - lwz r28, 0x2D8(r1) - addi r1, r1, 0x2E8 - mtlr r0 - blr - */ + s32 chan; + EXIControl* exi; + EXICallback callback; + + chan = (interrupt - __OS_INTERRUPT_EXI_0_EXT) / 3; + __OSMaskInterrupts((OS_INTERRUPTMASK_EXI_0_EXT | OS_INTERRUPTMASK_EXI_0_EXI) >> (3 * chan)); + exi = &Ecb[chan]; + callback = exi->extCallback; + exi->state &= ~EXI_STATE_ATTACHED; + if (callback) { + OSContext exceptionContext; + + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + + exi->extCallback = 0; + callback(chan, context); + + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); + } } /* @@ -1605,6 +606,36 @@ void EXTIntrruptHandler(void) */ void EXIInit(void) { + while (((EXIREG(0, 3) & 0x1) == 1) || ((EXIREG(1, 3) & 0x1) == 1) || ((EXIREG(2, 3) & 0x1) == 1)) { + continue; + } + + __OSMaskInterrupts(OS_INTERRUPTMASK_EXI_0_EXI | OS_INTERRUPTMASK_EXI_0_TC | OS_INTERRUPTMASK_EXI_0_EXT | OS_INTERRUPTMASK_EXI_1_EXI + | OS_INTERRUPTMASK_EXI_1_TC | OS_INTERRUPTMASK_EXI_1_EXT | OS_INTERRUPTMASK_EXI_2_EXI | OS_INTERRUPTMASK_EXI_2_TC); + + EXIREG(0, 0) = 0; + EXIREG(1, 0) = 0; + EXIREG(2, 0) = 0; + + EXIREG(0, 0) = 0x00002000; + + __OSSetInterruptHandler(__OS_INTERRUPT_EXI_0_EXI, EXIIntrruptHandler); + __OSSetInterruptHandler(__OS_INTERRUPT_EXI_0_TC, TCIntrruptHandler); + __OSSetInterruptHandler(__OS_INTERRUPT_EXI_0_EXT, EXTIntrruptHandler); + __OSSetInterruptHandler(__OS_INTERRUPT_EXI_1_EXI, EXIIntrruptHandler); + __OSSetInterruptHandler(__OS_INTERRUPT_EXI_1_TC, TCIntrruptHandler); + __OSSetInterruptHandler(__OS_INTERRUPT_EXI_1_EXT, EXTIntrruptHandler); + __OSSetInterruptHandler(__OS_INTERRUPT_EXI_2_EXI, EXIIntrruptHandler); + __OSSetInterruptHandler(__OS_INTERRUPT_EXI_2_TC, TCIntrruptHandler); + + EXIGetID(0, 2, &IDSerialPort1); + + if ((OSGetConsoleType() & 0x10000000) != 0) { + __EXIProbeStartTime[0] = __EXIProbeStartTime[1] = 0; + Ecb[0].idTime = Ecb[1].idTime = 0; + __EXIProbe(0); + __EXIProbe(1); + } /* .loc_0x0: mflr r0 @@ -1740,84 +771,35 @@ void EXIInit(void) * Address: 800E0F70 * Size: 0000F4 */ -void EXILock(void) +BOOL EXILock(s32 chan, u32 dev, EXICallback unlockedCallback) { - /* - .loc_0x0: - mflr r0 - stw r0, 0x4(r1) - stwu r1, -0x30(r1) - stmw r27, 0x1C(r1) - addi r27, r3, 0 - addi r31, r4, 0 - addi r28, r5, 0 - rlwinm r4,r3,6,0,25 - lis r3, 0x804F - addi r0, r3, 0x5F28 - add r30, r0, r4 - bl 0xDC9C - mr r29, r3 - lwz r0, 0xC(r30) - rlwinm. r0,r0,0,27,27 - beq- .loc_0xB8 - cmplwi r28, 0 - beq- .loc_0xA8 - mr r3, r30 - lwz r4, 0x24(r30) - mtctr r4 - cmpwi r4, 0 - ble- .loc_0x80 - - .loc_0x5C: - lwz r0, 0x28(r3) - cmplw r0, r31 - bne- .loc_0x78 - mr r3, r29 - bl 0xDC84 - li r3, 0 - b .loc_0xE0 - - .loc_0x78: - addi r3, r3, 0x8 - bdnz+ .loc_0x5C - - .loc_0x80: - rlwinm r0,r4,3,0,28 - add r3, r30, r0 - stw r28, 0x2C(r3) - lwz r0, 0x24(r30) - rlwinm r0,r0,3,0,28 - add r3, r30, r0 - stw r31, 0x28(r3) - lwz r3, 0x24(r30) - addi r0, r3, 0x1 - stw r0, 0x24(r30) - - .loc_0xA8: - mr r3, r29 - bl 0xDC44 - li r3, 0 - b .loc_0xE0 - - .loc_0xB8: - lwz r0, 0xC(r30) - ori r0, r0, 0x10 - stw r0, 0xC(r30) - stw r31, 0x18(r30) - addi r3, r27, 0 - addi r4, r30, 0 - bl -0x14EC - mr r3, r29 - bl 0xDC18 - li r3, 0x1 - - .loc_0xE0: - lwz r0, 0x34(r1) - lmw r27, 0x1C(r1) - addi r1, r1, 0x30 - mtlr r0 - blr - */ + EXIControl* exi = &Ecb[chan]; + BOOL enabled; + int i; + + enabled = OSDisableInterrupts(); + if (exi->state & EXI_STATE_LOCKED) { + if (unlockedCallback) { + for (i = 0; i < exi->items; i++) { + if (exi->queue[i].dev == dev) { + OSRestoreInterrupts(enabled); + return FALSE; + } + } + exi->queue[exi->items].callback = unlockedCallback; + exi->queue[exi->items].dev = dev; + exi->items++; + } + OSRestoreInterrupts(enabled); + return FALSE; + } + + exi->state |= EXI_STATE_LOCKED; + exi->dev = dev; + SetExiInterruptMask(chan, exi); + + OSRestoreInterrupts(enabled); + return TRUE; } /* @@ -1825,74 +807,30 @@ void EXILock(void) * Address: 800E1064 * Size: 0000DC */ -void EXIUnlock(void) +BOOL EXIUnlock(s32 chan) { - /* - .loc_0x0: - mflr r0 - stw r0, 0x4(r1) - stwu r1, -0x20(r1) - stw r31, 0x1C(r1) - stw r30, 0x18(r1) - stw r29, 0x14(r1) - stw r28, 0x10(r1) - addi r28, r3, 0 - rlwinm r4,r3,6,0,25 - lis r3, 0x804F - addi r0, r3, 0x5F28 - add r31, r0, r4 - bl 0xDBA4 - mr r30, r3 - lwz r0, 0xC(r31) - rlwinm. r0,r0,0,27,27 - bne- .loc_0x54 - mr r3, r30 - bl 0xDBB4 - li r3, 0 - b .loc_0xBC - - .loc_0x54: - lwz r0, 0xC(r31) - rlwinm r0,r0,0,28,26 - stw r0, 0xC(r31) - addi r3, r28, 0 - addi r4, r31, 0 - bl -0x1578 - lwz r3, 0x24(r31) - cmpwi r3, 0 - ble- .loc_0xB0 - lwz r29, 0x2C(r31) - subic. r0, r3, 0x1 - stw r0, 0x24(r31) - ble- .loc_0x9C - addi r3, r31, 0x28 - addi r4, r31, 0x30 - lwz r0, 0x24(r31) - rlwinm r5,r0,3,0,28 - bl -0x1A070 - - .loc_0x9C: - addi r3, r28, 0 - li r4, 0 - addi r12, r29, 0 - mtlr r12 - blrl - - .loc_0xB0: - mr r3, r30 - bl 0xDB48 - li r3, 0x1 - - .loc_0xBC: - lwz r0, 0x24(r1) - lwz r31, 0x1C(r1) - lwz r30, 0x18(r1) - lwz r29, 0x14(r1) - lwz r28, 0x10(r1) - addi r1, r1, 0x20 - mtlr r0 - blr - */ + EXIControl* exi = &Ecb[chan]; + BOOL enabled; + EXICallback unlockedCallback; + + enabled = OSDisableInterrupts(); + if (!(exi->state & EXI_STATE_LOCKED)) { + OSRestoreInterrupts(enabled); + return FALSE; + } + exi->state &= ~EXI_STATE_LOCKED; + SetExiInterruptMask(chan, exi); + + if (0 < exi->items) { + unlockedCallback = exi->queue[0].callback; + if (0 < --exi->items) { + memmove(&exi->queue[0], &exi->queue[1], sizeof(exi->queue[0]) * exi->items); + } + unlockedCallback(chan, 0); + } + + OSRestoreInterrupts(enabled); + return TRUE; } /* @@ -1900,17 +838,11 @@ void EXIUnlock(void) * Address: 800E1140 * Size: 000018 */ -void EXIGetState(void) +u32 EXIGetState(s32 chan) { - /* - .loc_0x0: - rlwinm r4,r3,6,0,25 - lis r3, 0x804F - addi r0, r3, 0x5F28 - add r3, r0, r4 - lwz r3, 0xC(r3) - blr - */ + EXIControl* exi = &Ecb[chan]; + + return (u32)exi->state; } /* @@ -1918,23 +850,11 @@ void EXIGetState(void) * Address: 800E1158 * Size: 000028 */ -void UnlockedHandler(void) +static void UnlockedHandler(s32 chan, OSContext* context) { - /* - .loc_0x0: - mflr r0 - stw r0, 0x4(r1) - stwu r1, -0x18(r1) - li r4, 0 - addi r5, r1, 0x10 - bl .loc_0x28 - lwz r0, 0x1C(r1) - addi r1, r1, 0x18 - mtlr r0 - blr + u32 id; - .loc_0x28: - */ + EXIGetID(chan, 0, &id); } /* @@ -1942,8 +862,59 @@ void UnlockedHandler(void) * Address: 800E1180 * Size: 0003B0 */ -void EXIGetID(void) +s32 EXIGetID(s32 chan, u32 dev, u32* id) { + EXIControl* exi = &Ecb[chan]; + BOOL err; + u32 cmd; + s32 startTime; + BOOL enabled; + + if (chan < 2 && dev == 0) { + if (!__EXIProbe(chan)) { + return 0; + } + + if (exi->idTime == __EXIProbeStartTime[chan]) { + *id = exi->id; + return exi->idTime; + } + + if (!__EXIAttach(chan, NULL)) { + return 0; + } + + startTime = __EXIProbeStartTime[chan]; + } + + err = !EXILock(chan, dev, (chan < 2 && dev == 0) ? UnlockedHandler : NULL); + if (!err) { + err = !EXISelect(chan, dev, EXI_FREQ_1M); + if (!err) { + cmd = 0; + err |= !EXIImm(chan, &cmd, 2, EXI_WRITE, NULL); + err |= !EXISync(chan); + err |= !EXIImm(chan, id, 4, EXI_READ, NULL); + err |= !EXISync(chan); + err |= !EXIDeselect(chan); + } + EXIUnlock(chan); + } + + if (chan < 2 && dev == 0) { + EXIDetach(chan); + enabled = OSDisableInterrupts(); + err |= (startTime != __EXIProbeStartTime[chan]); + if (!err) { + exi->id = *id; + exi->idTime = startTime; + } + OSRestoreInterrupts(enabled); + + return err ? 0 : exi->idTime; + } + + return err ? 0 : !0; /* .loc_0x0: mflr r0 @@ -2233,22 +1204,42 @@ void EXIGetID(void) */ } -/* - * --INFO-- - * Address: ........ - * Size: 000118 - */ -void EXIGetType(void) -{ - // UNUSED FUNCTION -} - /* * --INFO-- * Address: ........ * Size: 000234 */ -void EXIGetTypeString(void) +char* EXIGetTypeString(u32 type) { - // UNUSED FUNCTION + switch (type) { + case EXI_MEMORY_CARD_59: + return "Memory Card 59"; + case EXI_MEMORY_CARD_123: + return "Memory Card 123"; + case EXI_MEMORY_CARD_251: + return "Memory Card 251"; + case EXI_MEMORY_CARD_507: + return "Memory Card 507"; + case EXI_MEMORY_CARD_1019: + return "Memory Card 1019"; + case EXI_MEMORY_CARD_2043: + return "Memory Card 2043"; + case EXI_USB_ADAPTER: + return "USB Adapter"; + case 0x80000000 | EXI_MEMORY_CARD_59: + case 0x80000000 | EXI_MEMORY_CARD_123: + case 0x80000000 | EXI_MEMORY_CARD_251: + case 0x80000000 | EXI_MEMORY_CARD_507: + return "Net Card"; + case EXI_ETHER_VIEWER: + return "Artist Ether"; + case EXI_MODEM: + return "Broadband Adapter"; + case EXI_STREAM_HANGER: + return "Stream Hanger"; + case EXI_IS_VIEWER: + return "IS-DOL-VIEWER"; + } } + +#pragma scheduling reset