2009-02-09 21:15:56 +00:00
|
|
|
|
|
|
|
#include "kloadcore.h"
|
|
|
|
#include "kintrman.h"
|
|
|
|
#include "kdmacman.h"
|
|
|
|
#include "ksifman.h"
|
|
|
|
|
|
|
|
#define min(a, b) ((a)<(b)?(a):(b))
|
|
|
|
#define max(a, b) ((a)>(b)?(a):(b))
|
|
|
|
|
|
|
|
#define CONFIG_1450 (*(volatile int*)0xBF801450)
|
|
|
|
|
|
|
|
#define BD0 (*(volatile int*)0xBD000000) //mscom
|
|
|
|
#define BD1 (*(volatile int*)0xBD000010) //smcom
|
|
|
|
#define BD2 (*(volatile int*)0xBD000020) //msflag
|
|
|
|
#define BD3 (*(volatile int*)0xBD000030) //smflag
|
|
|
|
#define BD4 (*(volatile int*)0xBD000040)
|
|
|
|
#define BD5 (*(volatile int*)0xBD000050)
|
|
|
|
#define BD6 (*(volatile int*)0xBD000060)
|
|
|
|
#define BD7 (*(volatile int*)0xBD000070)
|
|
|
|
|
|
|
|
|
|
|
|
int debug=1;
|
|
|
|
|
|
|
|
#define _dprintf(fmt, args...) \
|
|
|
|
if (debug > 0) __printf("sifman: " fmt, ## args)
|
|
|
|
|
|
|
|
|
|
|
|
struct sifData{
|
|
|
|
int data,
|
|
|
|
words,
|
|
|
|
count,
|
|
|
|
addr;
|
|
|
|
};
|
|
|
|
|
|
|
|
int sifSIF2Init =0,
|
|
|
|
sifInit =0;
|
|
|
|
|
|
|
|
struct sm_internal{
|
|
|
|
short id, //+000 some id...?!?
|
|
|
|
res1; //+002 not used
|
|
|
|
int index; //+004 current position in dma buffer
|
|
|
|
struct sifData *crtbuf; //+008 address of current used buffer
|
|
|
|
struct sifData buf1[32]; //+00C first buffer
|
|
|
|
struct sifData buf2[32]; //+20C second buffer
|
|
|
|
int (*function)(int);//+40C a function ?!?
|
|
|
|
int param; //+410 a parameter for function
|
|
|
|
int res2; //+414 not used
|
|
|
|
} vars;
|
|
|
|
|
|
|
|
struct sifData one;
|
|
|
|
int res3, res4;
|
|
|
|
|
|
|
|
int _start(int argc, char* argv);
|
|
|
|
void RegisterSif0Handler();
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
int getBD2_loopchanging(){
|
|
|
|
register int a, b;
|
|
|
|
a=BD2;
|
|
|
|
b=BD2;
|
|
|
|
while (a!=b) {
|
|
|
|
a=b;
|
|
|
|
b=BD2;
|
|
|
|
}
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
int getBD3_loopchanging(){
|
|
|
|
register int a, b;
|
|
|
|
a=BD3;
|
|
|
|
b=BD3;
|
|
|
|
while (a!=b) {
|
|
|
|
a=b;
|
|
|
|
b=BD3;
|
|
|
|
}
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[04]
|
|
|
|
void SifSIF2Init(){
|
|
|
|
if (sifSIF2Init!=0) return;
|
|
|
|
|
|
|
|
DMAch_SIF2_CHCR = 0; //reset ch. 2
|
|
|
|
DMAch_DPCR|= 0x800; //enable dma ch. 2
|
|
|
|
DMAch_DPCR;
|
|
|
|
sifSIF2Init =1;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[05]
|
|
|
|
void SifInit(){
|
|
|
|
u32 x, y;
|
|
|
|
u32 msflag;
|
|
|
|
|
|
|
|
_dprintf("%s: sifInit=%d\n", __FUNCTION__, sifInit);
|
|
|
|
if (sifInit!=0) return;
|
|
|
|
|
|
|
|
DMAch_DPCR2 |=0x8800; //enable dma ch. 9 and 10
|
|
|
|
DMAch_SIF9_CHCR = 0;
|
|
|
|
DMAch_SIFA_CHCR = 0;
|
|
|
|
SifSIF2Init();
|
|
|
|
|
|
|
|
if (CONFIG_1450 & 0x10)
|
|
|
|
CONFIG_1450 |= 0x10;
|
|
|
|
CONFIG_1450 |= 0x1;
|
|
|
|
|
|
|
|
RegisterSif0Handler();
|
|
|
|
|
|
|
|
CpuSuspendIntr(&x); //intrman
|
|
|
|
CpuEnableIntr(); //intrman
|
|
|
|
|
|
|
|
_dprintf("%s: waiting EE...\n", __FUNCTION__);
|
|
|
|
do { //EE kernel sif ready
|
|
|
|
CpuSuspendIntr(&y); //intrman
|
|
|
|
msflag = getBD2_loopchanging();
|
|
|
|
CpuResumeIntr(y); //intrman
|
|
|
|
} while(!(msflag & 0x10000));
|
|
|
|
|
|
|
|
_dprintf("%s: EE ready\n", __FUNCTION__);
|
|
|
|
CpuResumeIntr(x); //intrman
|
|
|
|
SifSetDChain();
|
|
|
|
SifSetIOPrcvaddr(0); //sif1 receive buffer
|
|
|
|
BD3 = 0x10000; //IOPEE_sifman_init
|
|
|
|
BD3;
|
|
|
|
sifInit =1;
|
|
|
|
_dprintf("%s ok\n", __FUNCTION__);
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[02]
|
|
|
|
void SifDeinit(){
|
|
|
|
int x;
|
|
|
|
|
|
|
|
DisableIntr(INT_DMA9, &x);
|
|
|
|
ReleaseIntrHandler(INT_DMA9);
|
|
|
|
DMAch_SIF9_CHCR=0;
|
|
|
|
DMAch_SIFA_CHCR=0;
|
|
|
|
if (CONFIG_1450 & 0x10)
|
|
|
|
CONFIG_1450 |= 0x10;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[29]
|
|
|
|
int SifCheckInit(){
|
|
|
|
return sifInit;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[06]
|
|
|
|
void SifSetDChain(){
|
|
|
|
if ((BD4 & 0x40) == 0) BD4=0x40;
|
|
|
|
DMAch_SIFA_CHCR =0;
|
|
|
|
DMAch_SIFA_BCR_size =32;
|
|
|
|
DMAch_SIFA_CHCR =DMAf_08|DMAf_CO|DMAf_TR|DMAf_30;//EE->IOP (to memory)
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[30]
|
|
|
|
void SifSet0CB(int (*_function)(int), int _param){
|
|
|
|
vars.function=_function;
|
|
|
|
vars.param=_param;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[31]
|
|
|
|
void SifReset0CB(){
|
|
|
|
vars.function=NULL;
|
|
|
|
vars.param=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
int Sif0Handler(void *common) {
|
|
|
|
struct sm_internal *vars = (struct sm_internal *)common;
|
|
|
|
int var_10;
|
|
|
|
if (vars->function)
|
|
|
|
vars->function(vars->param);
|
|
|
|
|
|
|
|
if ((DMAch_SIF9_CHCR & DMAf_TR == 0) && (vars->index>0)) {
|
|
|
|
DMAch_SIF9_CHCR =0;
|
|
|
|
DMAch_SIF9_TADR =(int)vars->crtbuf;
|
|
|
|
DMAch_SIF9_BCR =32;
|
|
|
|
if (BD4 & 0x20 == 0) BD4 = 0x20;
|
|
|
|
vars->id++;
|
|
|
|
if (vars->crtbuf == vars->buf1){
|
|
|
|
vars->index=0;
|
|
|
|
vars->crtbuf=vars->buf2;
|
|
|
|
}else
|
|
|
|
vars->crtbuf=vars->buf1;
|
|
|
|
DMAch_SIF9_CHCR = DMAf_DR|DMAf_08|DMAf_CO|DMAf_LI|DMAf_TR;//IOP->EE (from memory)
|
|
|
|
var_10=DMAch_SIF9_CHCR;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
void RegisterSif0Handler(){
|
|
|
|
u32 x;
|
|
|
|
vars.index=0;
|
|
|
|
vars.crtbuf=vars.buf1;
|
|
|
|
vars.function=NULL;
|
|
|
|
vars.param=0;
|
|
|
|
CpuSuspendIntr(&x); //intrman
|
|
|
|
RegisterIntrHandler(INT_DMA9, 1, Sif0Handler, &vars); //intrman
|
|
|
|
EnableIntr(INT_DMA9); //intrman
|
|
|
|
CpuResumeIntr(x); //intrman
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
void enqueue(struct sifman_DMA *psd){
|
|
|
|
vars.crtbuf[vars.index].data=(u32)psd->data & 0xFFFFFF; //16MB addressability
|
|
|
|
if (psd->attr & SIF_DMA_INT_I)
|
|
|
|
vars.crtbuf[vars.index].data |= 0x40000000;
|
|
|
|
vars.crtbuf[vars.index].words=(psd->size + 3)/4 & 0xFFFFFF;
|
|
|
|
vars.crtbuf[vars.index].count = ((psd->size + 3)/16 + (((psd->size + 3)/4) & 3))
|
|
|
|
| 0x10000000;
|
|
|
|
if (psd->attr & SIF_DMA_INT_O)
|
|
|
|
vars.crtbuf[vars.index].count |=0x80000000;
|
|
|
|
vars.crtbuf[vars.index].addr = (u32)psd->addr & 0x1FFFFFFF; //512MB addresability
|
|
|
|
vars.index++;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[07]
|
|
|
|
u32 SifSetDma(struct sifman_DMA *psd, int len){
|
|
|
|
int var_20;
|
|
|
|
register unsigned int ret;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (32-vars.index < len) return 0; //no place
|
|
|
|
|
|
|
|
ret = vars.id;
|
|
|
|
ret = (ret << 16) | ((vars.index & 0xFF) << 8) | (len & 0xFF);
|
|
|
|
|
|
|
|
if (vars.index)
|
|
|
|
vars.crtbuf[vars.index-1].data &= 0x7FFFFFFF;
|
|
|
|
for (i=0; i<len; i++)
|
|
|
|
enqueue(&psd[i]);
|
|
|
|
vars.crtbuf[vars.index-1].data |= 0x80000000;
|
|
|
|
|
|
|
|
if ((DMAch_SIF9_CHCR & DMAf_TR) == 0) {
|
|
|
|
DMAch_SIF9_CHCR=0;
|
|
|
|
DMAch_SIF9_TADR=(int)vars.crtbuf;
|
|
|
|
|
|
|
|
if ((BD4 & 0x20) == 0) BD4=0x20;
|
|
|
|
|
|
|
|
DMAch_SIF9_BCR_size=32;
|
|
|
|
|
|
|
|
vars.index=0;
|
|
|
|
vars.id++;
|
|
|
|
if (vars.crtbuf==vars.buf1)vars.crtbuf=vars.buf2;
|
|
|
|
//stupid :D (why the if?)
|
|
|
|
|
|
|
|
DMAch_SIF9_CHCR=DMAf_DR|DMAf_08|DMAf_CO|DMAf_LI|DMAf_TR;//IOP->EE
|
|
|
|
var_20=DMAch_SIF9_CHCR; //?!?
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[08]
|
|
|
|
int SifDmaStat(u32 id){
|
|
|
|
if (DMAch_SIF9_CHCR & DMAf_TR){
|
|
|
|
if (id>>16 == vars.id) return 1; //waiting in queue
|
|
|
|
if (id>>16+1 == vars.id) return 0; //running
|
|
|
|
}
|
|
|
|
return -1; //terminated
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[09]
|
|
|
|
void SifSend(struct sifman_DMA sd){
|
|
|
|
sd.size = sd.size /4 + ((sd.size & 3) > 0);
|
|
|
|
one.data = ((u32)sd.data & 0xFFFFFF) | 0x80000000;
|
|
|
|
one.words= sd.size & 0xFFFFFF;
|
|
|
|
if (sd.attr & SIF_DMA_INT_I) one.data |= 0x40000000;
|
|
|
|
one.count = (sd.size/4 + ((sd.size & 3)>0)) | 0x10000000;
|
|
|
|
if (sd.attr & SIF_DMA_INT_O) one.count|= 0x80000000;
|
|
|
|
one.addr = (u32)sd.addr & 0xFFFFFFF;
|
|
|
|
|
|
|
|
if (BD4 & 0x20 == 0) BD4=0x20;
|
|
|
|
|
|
|
|
DMAch_SIF9_CHCR=0;
|
|
|
|
DMAch_SIF9_TADR=(u32)&one;
|
|
|
|
DMAch_SIF9_BCR_size=32;
|
|
|
|
DMAch_SIF9_CHCR=DMAf_DR|DMAf_08|DMAf_CO|DMAf_LI|DMAf_TR; //IOP->EE
|
|
|
|
DMAch_SIF9_CHCR;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[10]
|
|
|
|
void SifSendSync(){
|
|
|
|
while (DMAch_SIF9_CHCR & DMAf_TR);
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[11]
|
|
|
|
int SifIsSending(){
|
|
|
|
return (DMAch_SIF9_CHCR & DMAf_TR);
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[12]
|
|
|
|
void SifSetSIF0DMA(void *data, int size, int attr){
|
|
|
|
size=size/4 + ((size & 3)>0);
|
|
|
|
|
|
|
|
if (BD4 & 0x20 == 0) BD4=0x20;
|
|
|
|
|
|
|
|
DMAch_SIF9_CHCR=0;
|
|
|
|
DMAch_SIF9_MADR=(u32)data & 0xFFFFFF;
|
|
|
|
DMAch_SIF9_BCR_size=32;
|
|
|
|
DMAch_SIF9_BCR_count=size/32 + ((size & 0x1F)>0);
|
|
|
|
DMAch_SIF9_CHCR=DMAf_DR|DMAf_CO|DMAf_TR;
|
|
|
|
DMAch_SIF9_CHCR;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[13]
|
|
|
|
void SifSendSync0(){
|
|
|
|
while (DMAch_SIF9_CHCR & DMAf_TR);
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[14]
|
|
|
|
int SifIsSending0(){
|
|
|
|
return (DMAch_SIF9_CHCR & DMAf_TR);
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[15]
|
|
|
|
void SifSetSIF1DMA(void *data, int size, int attr){
|
|
|
|
size=size/4 + ((size & 3)>0);
|
|
|
|
|
|
|
|
if (BD4 & 0x40 == 0) BD4=0x40;
|
|
|
|
|
|
|
|
DMAch_SIFA_CHCR=0;
|
|
|
|
DMAch_SIFA_MADR=(u32)data & 0xFFFFFF;
|
|
|
|
DMAch_SIFA_BCR_size=32;
|
|
|
|
DMAch_SIFA_BCR_count=size/32 + ((size & 0x1F)>0);
|
|
|
|
DMAch_SIFA_CHCR=DMAf_CO|DMAf_TR|
|
|
|
|
(attr & SIF_DMA_BSN?DMAf_30:0);
|
|
|
|
DMAch_SIFA_CHCR;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[16]
|
|
|
|
void SifSendSync1(){
|
|
|
|
while (DMAch_SIFA_CHCR & DMAf_TR);
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[17]
|
|
|
|
int SifIsSending1(){
|
|
|
|
return (DMAch_SIFA_CHCR & DMAf_TR);
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[18]
|
|
|
|
void SifSetSIF2DMA(void *data, int size, int attr){
|
|
|
|
size=size/4 + ((size & 3)>0);
|
|
|
|
|
|
|
|
if (BD4 & 0x80 == 0) BD4=0x80;
|
|
|
|
|
|
|
|
DMAch_SIF2_CHCR=0;
|
|
|
|
DMAch_SIF2_MADR=(u32)data & 0xFFFFFF;
|
|
|
|
DMAch_SIF2_BCR_size=min(size, 32);
|
|
|
|
DMAch_SIF2_BCR_count=size/32 + ((size & 0x1F)>0);
|
|
|
|
DMAch_SIF2_CHCR=DMAf_CO |DMAf_TR|
|
|
|
|
((attr & SIF_TO_EE ?DMAf_DR:
|
|
|
|
(attr & SIF_DMA_BSN?DMAf_30:0)));
|
|
|
|
DMAch_SIF2_CHCR;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[19]
|
|
|
|
void SifSendSync2(){
|
|
|
|
while (DMAch_SIF2_CHCR & DMAf_TR);
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[20]
|
|
|
|
int SifIsSending2(){
|
|
|
|
return (DMAch_SIF2_CHCR & DMAf_TR);
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[21]
|
|
|
|
int SifGetEEIOPflags(){
|
|
|
|
return getBD2_loopchanging();
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[22]
|
|
|
|
int SifSetEEIOPflags(int val){
|
|
|
|
BD2=val;
|
|
|
|
return getBD2_loopchanging();
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[23]
|
|
|
|
int SifGetIOPEEflags(){
|
|
|
|
return getBD3_loopchanging();
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[24]
|
|
|
|
int SifSetIOPEEflags(int val){
|
|
|
|
BD3=val;
|
|
|
|
return getBD3_loopchanging();
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[25]
|
|
|
|
int SifGetEErcvaddr(){
|
|
|
|
return BD0;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[26]
|
|
|
|
int SifGetIOPrcvaddr(){
|
|
|
|
return BD1;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[27]
|
|
|
|
int SifSetIOPrcvaddr(int val){
|
|
|
|
BD1=val;
|
|
|
|
return BD1;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[28]
|
|
|
|
void SifSet1450_2(){
|
|
|
|
CONFIG_1450 |= 2;
|
|
|
|
CONFIG_1450 &= ~2;
|
|
|
|
CONFIG_1450;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////[01,03,32,33,34,35]
|
|
|
|
void _retonly(){}
|
|
|
|
|
|
|
|
//////////////////////////////entrypoint///////////////////////////////
|
|
|
|
struct export sifman_stub={
|
|
|
|
0x41C00000,
|
|
|
|
0,
|
|
|
|
VER(1, 1), // 1.1 => 0x101
|
|
|
|
0,
|
|
|
|
"sifman",
|
|
|
|
(func)_start, // entrypoint
|
|
|
|
(func)_retonly,
|
|
|
|
(func)SifDeinit,
|
|
|
|
(func)_retonly,
|
|
|
|
(func)SifSIF2Init,
|
|
|
|
(func)SifInit,
|
|
|
|
(func)SifSetDChain,
|
|
|
|
(func)SifSetDma,
|
|
|
|
(func)SifDmaStat,
|
|
|
|
(func)SifSend,
|
|
|
|
(func)SifSendSync,
|
|
|
|
(func)SifIsSending,
|
|
|
|
(func)SifSetSIF0DMA,
|
|
|
|
(func)SifSendSync0,
|
|
|
|
(func)SifIsSending0,
|
|
|
|
(func)SifSetSIF1DMA,
|
|
|
|
(func)SifSendSync1,
|
|
|
|
(func)SifIsSending1,
|
|
|
|
(func)SifSetSIF2DMA,
|
|
|
|
(func)SifSendSync2,
|
|
|
|
(func)SifIsSending2,
|
|
|
|
(func)SifGetEEIOPflags,
|
|
|
|
(func)SifSetEEIOPflags,
|
|
|
|
(func)SifGetIOPEEflags,
|
|
|
|
(func)SifSetIOPEEflags,
|
|
|
|
(func)SifGetEErcvaddr,
|
|
|
|
(func)SifGetIOPrcvaddr,
|
|
|
|
(func)SifSetIOPrcvaddr,
|
|
|
|
(func)SifSet1450_2,
|
|
|
|
(func)SifCheckInit,
|
|
|
|
(func)SifSet0CB,
|
|
|
|
(func)SifReset0CB,
|
|
|
|
(func)_retonly,
|
|
|
|
(func)_retonly,
|
|
|
|
(func)_retonly,
|
|
|
|
(func)_retonly,
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
//////////////////////////////entrypoint///////////////////////////////[00]
|
|
|
|
int _start(int argc, char* argv){
|
|
|
|
|
|
|
|
return RegisterLibraryEntries(&sifman_stub) > 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|