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

480 lines
9.8 KiB
Text

typedef struct // 64 bytes
{
+0 - EXI callback
+4 - TC callback
+8 - EXT callback
+12
+16 - immediate length (used only for read imm)
+20 - immediate buffer (used only for read imm)
+24 - last locked device number
+28
+32
+36 - number of unlock callbacks
+40 dev \
+44 cb |
|
+48 dev | unlocked callbacks FIFO :
+52 cb | first goes device number,
| then callback address
+56 dev |
+60 cb /
} EXICHAN;
EXICHAN Ecb[3]; // 64 * 3 = 0xc0 bytes
// check for device, connected with specified chan
BOOL __EXIProbe(s32 chan)
{
BOOL level;
u32 status;
if(chan == 2) return 1;
level = OSDisableInterrupts();
r6 = 0xcc006800 + chan * 20; // EXI
status = EXI.status;
if(((u32)Ecb[chan][12] & 8) == 0)
{
if(status & 0x800)
{
EXI.status = (status & 0x07f5) | 0x0800;
(u32)Ecb[chan][32] = 0
0x800030c0 + chan * 4 = 0
}
if(status & bit19)
{
[0x800000f8] ..
.
.
OSGetTime()
div2i()
div2i()
[0x800030c0 + chan * 4] = 1
OSRestoreInterrupts(level);
return 0;
}
[0x80000020] = 0
[0x800030c0 + chan * 4] = 0
OSRestoreInterrupts(level);
return 0;
}
else
{
if((status & bit19) == 0)
{
if(status & bit20)
{
[0x80000020] = 0
[0x800030c0 + chan * 4] = 0
OSRestoreInterrupts(level);
return 0;
}
}
}
OSRestoreInterrupts(level);
return 1;
}
BOOL EXIProbe(s32 chan)
{
char id[...];
if(__EXIProbe(chan))
{
if(Ecb[chan][32] == NULL)
{
if(EXIGetID(chan, 0, id)) return 1;
}
}
return 0;
}
// maybe incorrect
void SetExiInterruptMask(s32 chan, u32 *exi)
{
switch(chan)
{
case 0:
if(((*exi != 0) && (*exi[12] & 0x10)) || (Ecb[2][0] == 0))
{
__OSMaskInterrupts(0x00410000);
}
else
{
__OSUnmaskInterrupts(0x00410000);
}
break;
case 1:
if((*exi == 0) || (*exi[12] & 0x10))
{
__OSMaskInterrupts(0x00080000);
return;
}
else
{
__OSUnmaskInterrupts(0x00080000);
return;
}
break;
case 2:
if(__OSGetInterruptHandler(25) && (*exi[12] & 0x10))
{
__OSMaskInterrupts(0x00400000);
}
else
{
__OSMaskInterrupts(0x00400000);
}
break;
}
}
void EXIInit()
{
// mask all EXI interrupts
__OSMaskInterrupts(0x007f8000);
[0xcc006800] = 0
[0xcc006814] = 0
[0xcc006828] = 0
[0xcc006800] = 0x2000
__OSSetInterruptHandler(9, EXIIntrruptHandler); // EXI0 EXI
__OSSetInterruptHandler(10, TCIntrruptHandler); // EXI0 TC
__OSSetInterruptHandler(11, EXTIntrruptHandler); // EXI0 EXT
__OSSetInterruptHandler(12, EXIIntrruptHandler); // EXI1 EXI
__OSSetInterruptHandler(14, EXTIntrruptHandler); // EXI1 EXT
__OSSetInterruptHandler(15, EXIIntrruptHandler); // EXI2 EXI
__OSSetInterruptHandler(16, TCIntrruptHandler); // EXI2 TC
if(OSGetConsoleType() & OS_CONSOLE_DEVELOPMENT)
{
(u32)[0x800030c0] = 0;
(u32)[0x800030c4] = 0;
(u32)Ecb[0].[32] = 0;
(u32)Ecb[1].[32] = 0;
__EXIProbe(0);
__EXIProbe(1);
}
}
int EXIDma(s32 chan, u32 *buf, s32 len, int type, void (*callback)())
{
BOOL level;
level = OSDisableInterrupts();
if(!(Ecb[chan][12] & 4) || (Ecb[chan][12] & 3))
{
OSRestoreInterrupts(level);
return 0;
}
if(Ecb[chan][4] = callback)
{
// unmask EXI TC interrupt
EXIClearInterrupts(chan, 0, 1, 0);
__OSUnmaskInterrupts(0x00200000 >> (chan * 3));
}
Ecb[chan][12] |= 1
r4 = 0xcc006800 + chan * 20; // EXI
EXI.dmabuf = buf & 0x03ffffe0;
EXI.dmalen = len;
EXI.control = (type << 2) | 3;
OSRestoreInterrupts(level)
return 1;
}
BOOL EXILock(s32 chan, s32 dev, void (*unlockedCallback)())
{
BOOL level = OSDisableInterrupts();
if(Ecb[chan][12] & 0x10)
{
// reinstall unlock callback
if(unlockedCallback)
{
for(i=0; i<Ecb[chan][36]; i++)
{
// already installed
if(Ecb[chan][40 + 8 * i] == dev)
{
OSRestoreInterrupts(level);
return 0;
}
}
Ecb[chan][44 + 8 * i] = unlockedCallback;
Ecb[chan][40 + 8 * i] = dev;
Ecb[chan][36]++;
}
OSRestoreInterrupts(level);
return 0;
}
SetExiInterruptMask(chan, &Ecb[chan]);
Ecb[chan][12] |= 0x10;
Ecb[chan][24] = dev;
OSRestoreInterrupts(level);
return 1;
}
BOOL EXIUnlock(s32 chan)
{
BOOL level = OSDisableInterrupts();
if(!(Ecb[chan][12] & 0x10))
{
OSRestoreInterrupts(level);
return 0;
}
Ecb[chan][12] &= ~0x10;
SetExiInterruptMask(chan, &Ecb[chan]);
// unlocked callbcak
if(Ecb[chan][36] > 0)
{
void (*callback)() = Ecb[chan][44];
if(--Ecb[chan][36])
{
memmove(&Ecb[chan][40], &Ecb[chan][48], Ecb[chan][36] * 8);
}
callback(chan, 0);
}
OSRestoreInterrupts(level);
return 1;
}
BOOL EXISelect(s32 chan, s32 dev, s32 freq)
{
BOOL level = OSDisableInterrupts();
// already selected ?
if(Ecb[chan][12] & 4)
{
OSRestoreInterrupts(level);
return 0;
}
if(chan != 2)
{
if(dev == 0)
{
if(!(Ecb[chan][12] & 8))
{
if(__EXIProbe(chan) == 0)
{
OSRestoreInterrupts(level);
return 0;
}
}
}
// check locked flag
if(Ecb[chan][12] & 0x10)
{
OSRestoreInterrupts(level);
return 0;
}
// check for last locked device
if(Ecb[chan][24] != dev)
{
OSRestoreInterrupts(level);
return 0;
}
}
// set selected flag
Ecb[chan][12] |= 4;
r5 = 0xcc006800 + chan * 20; // EXI
EXI.status = (EXI.status & 0x0405) | (0x80 << dev) | (freq << 4);
if(Ecb[chan][12] & 8)
{
switch(chan)
{
case 0:
__OSMaskInterrupts(0x00100000); // EXI0 EXT
break;
case 1:
__OSMaskInterrupts(0x00020000); // EXI1 EXT
break;
}
}
OSRestoreInterrupts(level);
return 1;
}
BOOL EXIDeselect(s32 chan)
{
BOOL level = OSDisableInterrupts();
u32 status;
// already deselected ?
if(!(Ecb[chan][12] & 4))
{
OSDisableInterrupts(level);
return 0;
}
// clear selected flag
Ecb[chan][12] &= ~4;
r3 = 0xcc006800 + chan * 20; // EXI
status = EXI.status;
EXI.status = status & 0x0405;
if(Ecb[chan][12] & 8)
{
switch(chan)
{
case 0:
__OSUnmaskInterrupts(0x00100000); // EXI0 EXT
break;
case 1:
__OSUnmaskInterrupts(0x00020000); // EXI1 EXT
break;
}
}
OSRestoreInterrupts(level);
if(chan != 2)
{
if(status & bit24)
{
if(__EXIProbe(chan) == 0) return 0;
}
}
return 1;
}
void EXIClearInterrupts(s32 chan, BOOL exi, BOOL tc, BOOL ext)
{
u32 status;
r7 = 0xcc006800 + chan * 20; // EXI
status = EXI.status & 0x07f5;
if(exi) status |= 2;
if(tc ) status |= 8;
if(ext) status |= 0x800;
EXI.status = status;
}
/// UNCOMPLETE STUFFFF !!!!!!!!!!!!!
u32 EXISync(s32 chan)
{
BOOL level;
r31 = &Ecb[chan]
r29 = 0xcc006800 + chan * 20;
do
{
if((Ecb[chan][12] & 1) == 0)
{
level = OSDisableInterrupts();
if((Ecb[chan][12] & 4) == 0)
{
OSRestoreInterrupts(level);
break;
}
if(if(Ecb[chan][12] & 3)
{
}
}
} while(Ecb[chan][12] & 4);
return 0;
}
00000640 <EXISync>:
BOOL EXIImm(s32 chan, u32 *buf, s32 len, BOOL type, void (*callback)())
{
BOOL level = OSDisableInterrupts();
s32 size;
r28 = chan
r29 = buf
r30 = len
r31 = type
r19 = callback
r27 = &Ecb[chan];
if(Ecb[chan][12] & 3)
{
OSRestoreInterrupts(level);
return 0;
}
if(Ecb[chan][4] = callback)
{
EXIClearInterrupts(chan, 0, 1, 0);
__OSUnmaskInterrupts(0x00200000 >> (chan * 3));
}
Ecb[chan][12] |= 2;
if(type)
{
}
else
{
Ecb[chan][20] = buf;
Ecb[chan][16] = (type) ? (0) : (len);
r3 = 0xcc006800 + chan * 20; // EXI
EXI.control = ((len - 1) << 4) | (type << 2) | 1;
OSRestoreInterrupts(level);
return 1;
}
}
<EXIImm>: