mirror of https://github.com/PCSX2/pcsx2.git
509 lines
10 KiB
C
509 lines
10 KiB
C
//[module] SIO2MAN
|
|
//[processor] IOP
|
|
//[type] ELF-IRX
|
|
//[size] ?(0x?)
|
|
//[bios] ?(0x?-0x?)
|
|
//[iopboot2] 21
|
|
//[loaded @] ?
|
|
//[name] sio2man
|
|
//[version] 0x101
|
|
//[memory map] 0xBF808200,0xBF808204,0xBF808208,0xBF80820C,
|
|
// 0xBF808210,0xBF808214,0xBF808218,0xBF80821C, 16 entries
|
|
// 0xBF808220,0xBF808224,0xBF808228,0xBF80822C, array
|
|
// 0xBF808230,0xBF808234,0xBF808238,0xBF80823C,
|
|
// 0xBF808240,0xBF808244,0xBF808248,0xBF80824C,
|
|
// 0xBF808250,0xBF808254,0xBF808258,0xBF80825C,
|
|
// 0xBF808260, 0xBF808268,0xBF80826C,
|
|
// 0xBF808270,0xBF808274,0xBF808278,0xBF80827C,
|
|
// 0xBF808280
|
|
//[handlers] -
|
|
//[entry point] _start, (export_stub)
|
|
//[made by] Herben
|
|
|
|
#include <tamtypes.h>
|
|
#include <stdio.h>
|
|
|
|
#include "kdmacman.h"
|
|
#include "kloadcore.h"
|
|
#include "kintrman.h"
|
|
#include <thbase.h>
|
|
#include <thevent.h>
|
|
|
|
struct sio2_packet {
|
|
u32 recvVal1; // 0x00
|
|
u32 sendArray1[4]; // 0x04-0x10
|
|
u32 sendArray2[4]; // 0x14-0x20
|
|
|
|
u32 recvVal2; // 0x24
|
|
|
|
u32 sendArray3[16]; // 0x28-0x64
|
|
|
|
u32 recvVal3; // 0x68
|
|
|
|
int sendSize; // 0x6C
|
|
int recvSize; // 0x70
|
|
|
|
u8 *sendBuf; // 0x74
|
|
u8 *recvBuf; // 0x78
|
|
|
|
u32 dmacAddress1;
|
|
u32 dmacSize1;
|
|
u32 dmacCount1;
|
|
u32 dmacAddress2;
|
|
u32 dmacSize2;
|
|
u32 dmacCount2;
|
|
};
|
|
|
|
struct sio2common {
|
|
int evid;
|
|
int thid;
|
|
};
|
|
|
|
struct sio2common common;
|
|
int sio2_initialized = 0;
|
|
struct sio2_packet *packetAddr;
|
|
int debug = 1;
|
|
|
|
#define _dprintf(fmt, args...) if (debug > 0) printf(fmt, ## args)
|
|
|
|
// if (debug > 0) printf("\033[0;32m" "sio2man: " "\033[0m" fmt, ## args)
|
|
|
|
int _start(void);
|
|
void nullSub(void);
|
|
int sio2_init(void);
|
|
void sio2_deInit(void);
|
|
void sio2_setCtrl(u32 arg0);
|
|
u32 sio2_getCtrl(void);
|
|
u32 sio2_getRecv1(void);
|
|
void sio2_setSend1(int entryNum, u32 val);
|
|
u32 sio2_getSend1(int entryNum);
|
|
void sio2_setSend2(int entryNum, u32 val);
|
|
u32 sio2_getSend2(int entryNum);
|
|
u32 sio2_getRecv2(void);
|
|
void sio2_setSend3(int entryNum, u32 val);
|
|
u32 sio2_getSend3(int entryNum);
|
|
u32 sio2_getRecv3(void);
|
|
void sio2_set8278(u32 arg0);
|
|
u32 sio2_get8278(void);
|
|
void sio2_set827C(u32 arg0);
|
|
u32 sio2_get827C(void);
|
|
void sio2_datain(u8 arg0);
|
|
u8 sio2_dataout(void);
|
|
void sio2_setIntr(u32 arg0);
|
|
u32 sio2_getIntr(void);
|
|
void sio2_signalExchange1(void);
|
|
void sio2_signalExchange2(void);
|
|
int sio2_packetExchange(struct sio2_packet *packet);
|
|
|
|
struct export sio2man_stub={
|
|
0x41C00000,
|
|
0,
|
|
VER(1, 2), // 1.2 => 0x102
|
|
0,
|
|
"sio2man",
|
|
(func)_start, // 0
|
|
(func)nullSub,
|
|
(func)sio2_deInit,
|
|
(func)nullSub,
|
|
(func)sio2_setCtrl, // 4
|
|
(func)sio2_getCtrl,
|
|
(func)sio2_getRecv1,
|
|
(func)sio2_setSend1,
|
|
(func)sio2_getSend1, // 8
|
|
(func)sio2_setSend2,
|
|
(func)sio2_getSend2,
|
|
(func)sio2_getRecv2,
|
|
(func)sio2_setSend3, // 12
|
|
(func)sio2_getSend3,
|
|
(func)sio2_getRecv3,
|
|
(func)sio2_set8278,
|
|
(func)sio2_get8278, // 16
|
|
(func)sio2_set827C,
|
|
(func)sio2_get827C,
|
|
(func)sio2_datain,
|
|
(func)sio2_dataout, // 20
|
|
(func)sio2_setIntr,
|
|
(func)sio2_getIntr,
|
|
(func)sio2_signalExchange1,
|
|
(func)sio2_signalExchange2, // 24
|
|
(func)sio2_packetExchange,
|
|
0
|
|
};
|
|
|
|
#define INUM_sio2 17
|
|
#define HTYPE_C 1
|
|
|
|
|
|
int _start(void) {
|
|
return sio2_init();
|
|
}
|
|
|
|
void nullSub(void) { return; }
|
|
|
|
void sio2_setCtrl(u32 arg0) {
|
|
*(u32 *) (0xBF808268) = arg0;
|
|
}
|
|
|
|
u32 sio2_getCtrl(void) {
|
|
return(*(u32 *) (0xBF808268));
|
|
}
|
|
|
|
u32 sio2_getRecv1(void) {
|
|
return(*(u32 *) (0xBF80826C));
|
|
}
|
|
|
|
void sio2_setSend1(int entryNum, u32 val) {
|
|
switch(entryNum) {
|
|
case 0:
|
|
*(u32 *) (0xBF808240) = val;
|
|
break;
|
|
case 1:
|
|
*(u32 *) (0xBF808248) = val;
|
|
break;
|
|
case 2:
|
|
*(u32 *) (0xBF808250) = val;
|
|
break;
|
|
case 3:
|
|
*(u32 *) (0xBF808258) = val;
|
|
break;
|
|
}
|
|
}
|
|
|
|
u32 sio2_getSend1(int entryNum) {
|
|
switch(entryNum) {
|
|
case 0:
|
|
return(*(u32 *) (0xBF808240));
|
|
case 1:
|
|
return(*(u32 *) (0xBF808248));
|
|
case 2:
|
|
return(*(u32 *) (0xBF808250));
|
|
case 3:
|
|
return(*(u32 *) (0xBF808258));
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
void sio2_setSend2(int entryNum, u32 val) {
|
|
switch(entryNum) {
|
|
case 0:
|
|
*(u32 *) (0xBF808244) = val;
|
|
break;
|
|
case 1:
|
|
*(u32 *) (0xBF80824C) = val;
|
|
break;
|
|
case 2:
|
|
*(u32 *) (0xBF808254) = val;
|
|
break;
|
|
case 3:
|
|
*(u32 *) (0xBF80825C) = val;
|
|
break;
|
|
}
|
|
}
|
|
|
|
u32 sio2_getSend2(int entryNum) {
|
|
switch(entryNum) {
|
|
case 0:
|
|
return(*(u32 *) (0xBF808244));
|
|
case 1:
|
|
return(*(u32 *) (0xBF80824C));
|
|
case 2:
|
|
return(*(u32 *) (0xBF808254));
|
|
case 3:
|
|
return(*(u32 *) (0xBF80825C));
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
u32 sio2_getRecv2(void) {
|
|
return(*(u32 *) (0xBF808270));
|
|
}
|
|
|
|
void sio2_setSend3(int entryNum, u32 val) {
|
|
if(entryNum < 16)
|
|
*(u32 *) (0xBF808200 + (entryNum * 4)) = val;
|
|
}
|
|
|
|
u32 sio2_getSend3(int entryNum) {
|
|
if(entryNum < 16)
|
|
return(*(u32 *) (0xBF808200 + (entryNum * 4)));
|
|
|
|
return(-1);
|
|
}
|
|
|
|
u32 sio2_getRecv3(void) {
|
|
return(*(u32 *) (0xBF808274));
|
|
}
|
|
|
|
void sio2_set8278(u32 arg0) {
|
|
*(u32 *) (0xBF808278) = arg0;
|
|
}
|
|
|
|
u32 sio2_get8278(void) {
|
|
return(*(u32 *) (0xBF808278));
|
|
}
|
|
|
|
void sio2_set827C(u32 arg0) {
|
|
*(u32 *) (0xBF80827C) = arg0;
|
|
}
|
|
|
|
u32 sio2_get827C(void) {
|
|
return(*(u32 *) (0xBF80827C));
|
|
}
|
|
|
|
void sio2_datain(u8 arg0) {
|
|
*(u8 *) (0xBF808260) = arg0;
|
|
}
|
|
|
|
u8 sio2_dataout(void) {
|
|
return(*(u8 *) (0xBF808264));
|
|
}
|
|
|
|
void sio2_setIntr(u32 arg0) {
|
|
*(u32 *) (0xBF808280) = arg0;
|
|
}
|
|
|
|
u32 sio2_getIntr(void) {
|
|
return(*(u32 *) (0xBF808280));
|
|
}
|
|
|
|
int sio2_createEventFlag(void) {
|
|
iop_event_t param;
|
|
|
|
param.attr = 2;
|
|
param.option = 0;
|
|
param.bits = 0;
|
|
return(CreateEventFlag(¶m));
|
|
}
|
|
|
|
void dumpbuf(u8 *buf, int size) {
|
|
/* char str[1024];
|
|
char tmp[256];
|
|
int i;
|
|
|
|
str[0] = 0;
|
|
for(i = 0; i < size; i++) {
|
|
sprintf(tmp, "%x, ", buf[i]);
|
|
strcat(str, tmp);
|
|
}
|
|
printf("%s\n", str);
|
|
*/
|
|
}
|
|
|
|
void sio2_sendPacket(struct sio2_packet *p) {
|
|
int i;
|
|
|
|
// _dprintf("%s: sendSize=%d\n", __FUNCTION__, p->sendSize);
|
|
|
|
for(i = 0; i < 4; i++) {
|
|
sio2_setSend1(i, p->sendArray1[i]);
|
|
sio2_setSend2(i, p->sendArray2[i]);
|
|
}
|
|
|
|
for(i = 0; i < 16; i++)
|
|
sio2_setSend3(i, p->sendArray3[i]);
|
|
|
|
if (p->sendSize) {
|
|
_dprintf("sendBuf: ");
|
|
dumpbuf(p->sendBuf, p->sendSize);
|
|
|
|
for(i = 0; i < p->sendSize; i++) {
|
|
*(u8 *) (0xBF808260) = p->sendBuf[i];
|
|
}
|
|
}
|
|
|
|
if(p->dmacAddress1 != 0) {
|
|
_dprintf("dmaAddress1=%x, dmacSize1=%x, dmacCount1=%x\n", p->dmacAddress1, p->dmacSize1, p->dmacCount1);
|
|
dumpbuf((u8*)p->dmacAddress1, p->dmacSize1*p->dmacCount1);
|
|
dmacSetDMA(DMAch_SIO2in, p->dmacAddress1, p->dmacSize1, p->dmacCount1, 1); // from memory
|
|
dmacStartTransfer(DMAch_SIO2in);
|
|
}
|
|
|
|
if(p->dmacAddress2 != 0) {
|
|
dmacSetDMA(DMAch_SIO2out, p->dmacAddress2, p->dmacSize2, p->dmacCount2, 0); // to memory
|
|
dmacStartTransfer(DMAch_SIO2out);
|
|
}
|
|
}
|
|
|
|
void sio2_recvPacket(struct sio2_packet *p) {
|
|
int i;
|
|
|
|
// _dprintf("%s: recvSize=%d\n", __FUNCTION__, p->recvSize);
|
|
|
|
p->recvVal1 = *(u32 *) (0xBF80826C);
|
|
p->recvVal2 = *(u32 *) (0xBF808270);
|
|
p->recvVal3 = *(u32 *) (0xBF808274);
|
|
|
|
if (p->recvSize) {
|
|
_dprintf("recvBuf: ");
|
|
for(i = 0; i < p->recvSize; i++) {
|
|
p->recvBuf[i] = *(u8 *) (0xBF808264);
|
|
printf("%x, ", p->recvBuf[i]);
|
|
}
|
|
// printf("\n");
|
|
}
|
|
|
|
if (p->dmacAddress2 != 0) {
|
|
dumpbuf((u8*)p->dmacAddress2, p->dmacSize2*p->dmacCount2);
|
|
}
|
|
}
|
|
|
|
void sio2_basicThread(void* data) {
|
|
unsigned long result[4];
|
|
|
|
//_dprintf("%s\n", __FUNCTION__);
|
|
|
|
while(1) {
|
|
WaitEventFlag(common.evid, 0x5, 0x01, result);
|
|
|
|
if (result[0] & 0x01) {
|
|
ClearEventFlag(common.evid, ~0x1);
|
|
SetEventFlag(common.evid, 0x02);
|
|
} else
|
|
if (result[0] & 0x04) {
|
|
ClearEventFlag(common.evid, ~0x4);
|
|
SetEventFlag(common.evid, 0x08);
|
|
} else {
|
|
printf("sio2MAN: Woke up for unknown event(%08X)!\n", result[0]);
|
|
return;
|
|
}
|
|
|
|
// Wait for application to call our export 25
|
|
WaitEventFlag(common.evid, 0x10, 0, NULL);
|
|
ClearEventFlag(common.evid, ~0x10);
|
|
|
|
*(u32 *) (0xBF808268) = (*(u32 *) (0xBF808268)) | 0x0C;
|
|
sio2_sendPacket(packetAddr);
|
|
*(u32 *) (0xBF808268) = (*(u32 *) (0xBF808268)) | 0x01;
|
|
|
|
// Wait for the sio2 interrupt to occur
|
|
WaitEventFlag(common.evid, 0x80, 0, NULL);
|
|
ClearEventFlag(common.evid, ~0x80);
|
|
|
|
// Recieve the reply packet
|
|
sio2_recvPacket(packetAddr);
|
|
|
|
SetEventFlag(common.evid, 0x20);
|
|
|
|
WaitEventFlag(common.evid, 0x40, 0, NULL);
|
|
ClearEventFlag(common.evid, ~0x40);
|
|
}
|
|
}
|
|
|
|
int sio2_createBasicThread(void) {
|
|
iop_thread_t param;
|
|
|
|
param.attr = TH_C;
|
|
param.option = 0;
|
|
param.thread = &sio2_basicThread;
|
|
param.stacksize = 0x2000;
|
|
param.priority = 0x18;
|
|
|
|
return(CreateThread(¶m));
|
|
}
|
|
|
|
|
|
int sio2_interruptHandler(struct sio2common *c) {
|
|
sio2_setIntr(sio2_getIntr());
|
|
|
|
iSetEventFlag(c->evid, 0x80);
|
|
|
|
return(1);
|
|
}
|
|
|
|
// Export 0
|
|
int sio2_init(void) {
|
|
u32 oldStat;
|
|
|
|
// _dprintf("%s\n", __FUNCTION__);
|
|
|
|
if(RegisterLibraryEntries(&sio2man_stub) != 0) {
|
|
//printf("sio2MAN: Unable to register library entries!\n");
|
|
return(MODULE_NO_RESIDENT_END);//==1
|
|
}
|
|
|
|
if(sio2_initialized != 0) {
|
|
//printf("sio2MAN: Already initialized!\n");
|
|
return(MODULE_NO_RESIDENT_END);
|
|
}
|
|
|
|
sio2_initialized = 1;
|
|
|
|
*(u32 *) (0xBF808268) = 0x3BC;
|
|
|
|
common.evid = sio2_createEventFlag();
|
|
common.thid = sio2_createBasicThread();
|
|
|
|
CpuSuspendIntr(&oldStat);
|
|
|
|
RegisterIntrHandler(INUM_sio2, HTYPE_C, &sio2_interruptHandler, &common);
|
|
EnableIntr(INUM_sio2);
|
|
|
|
CpuResumeIntr(oldStat);
|
|
|
|
dmacSetVal(DMAch_SIO2in, 0x03);
|
|
dmacSetVal(DMAch_SIO2out, 0x03);
|
|
dmacEnableDMAch(DMAch_SIO2in);
|
|
dmacEnableDMAch(DMAch_SIO2out);
|
|
|
|
StartThread(common.thid, 0); // Start the "basicThread"
|
|
|
|
return MODULE_RESIDENT_END;
|
|
}
|
|
|
|
void sio2_deInit(void) {
|
|
u32 oldStat;
|
|
|
|
// _dprintf("%s\n", __FUNCTION__);
|
|
|
|
CpuSuspendIntr(&oldStat);
|
|
|
|
DisableIntr(INUM_sio2, 0);
|
|
ReleaseIntrHandler(INUM_sio2);
|
|
|
|
CpuResumeIntr(oldStat);
|
|
|
|
dmacDisableDMAch(DMAch_SIO2in);
|
|
dmacDisableDMAch(DMAch_SIO2out);
|
|
}
|
|
|
|
void sio2_signalExchange1(void) {
|
|
// _dprintf("%s\n", __FUNCTION__);
|
|
|
|
// Signal the basic thread to let it know we want to do an exchange.
|
|
SetEventFlag(common.evid, 0x01);
|
|
// Wait for basic thread to acknowledge then clear the flag.
|
|
WaitEventFlag(common.evid, 0x02, 0, NULL);
|
|
ClearEventFlag(common.evid, ~0x2);
|
|
}
|
|
|
|
void sio2_signalExchange2(void) {
|
|
// _dprintf("%s\n", __FUNCTION__);
|
|
|
|
// Signal the basic thread to let it know we want to do an exchange.
|
|
SetEventFlag(common.evid, 0x04);
|
|
// Wait for basic thread to acknowledge then clear the flag.
|
|
WaitEventFlag(common.evid, 0x08, 0, NULL);
|
|
ClearEventFlag(common.evid, ~0x8);
|
|
}
|
|
|
|
int sio2_packetExchange(struct sio2_packet *packet) {
|
|
// _dprintf("%s: %x\n", __FUNCTION__, packet);
|
|
|
|
// Set the address of the packet.
|
|
packetAddr = packet;
|
|
|
|
// Let the basic thread know we have the address set for the exchange.
|
|
SetEventFlag(common.evid, 0x10);
|
|
|
|
// Wait for the basic thread to finish it's stuff.
|
|
WaitEventFlag(common.evid, 0x20, 0, NULL);
|
|
ClearEventFlag(common.evid, ~0x20);
|
|
|
|
SetEventFlag(common.evid, 0x40);
|
|
|
|
return 1;
|
|
}
|
|
|