pcsx2/fps2bios/kernel/iopload/timrman/timrman.c

235 lines
5.9 KiB
C

//[module] TIMEMANI
//[processor] IOP
//[type] ELF-IRX
//[name] Timer_Manager
//[version] 0x101
//[memory map] 0xBF801100, 0xBF801110, 0xBF801120,
// 0xBF801450
// 0xBF801480, 0xBF801490, 0xBF8014A0,
// 0xBF8014B0, 0xBF8014C0
//[handlers] -
//[entry point] timrman_start, timrman_stub
//[made by] [RO]man (roman_ps2dev@hotmail.com) 13 October 2002
#include <tamtypes.h>
#include "iopdebug.h"
#include "kloadcore.h"
#include "kintrman.h"
#include "err.h"
#include "ktimrman.h"
#define CONFIG_1450 (*(volatile int*)0xBF801450)
struct TIMRMAN{
int hwreg;
char source, size;
short prescale;
int allocated;
} t[6]={
{RTC2, TC_SYSCLOCK, TIMER_SIZE_16, TIMER_PRESCALE_8, 0},
{RTC5, TC_SYSCLOCK, TIMER_SIZE_32, TIMER_PRESCALE_256, 0},
{RTC4, TC_SYSCLOCK, TIMER_SIZE_32, TIMER_PRESCALE_256, 0},
{RTC3, TC_SYSCLOCK|TC_HLINE, TIMER_SIZE_32, TIMER_PRESCALE_1, 0},
{RTC0, TC_SYSCLOCK|TC_PIXEL|TC_HOLD, TIMER_SIZE_16, TIMER_PRESCALE_1, 0},
{RTC1, TC_SYSCLOCK|TC_HLINE|TC_HOLD, TIMER_SIZE_16, TIMER_PRESCALE_1, 0}
};
int _start(int argc, char* argv[]);
///////////////////////////////////////////////////////////////////////[03]
void *GetTimersTable(){
return t; //address of the array
}
///////////////////////////////////////////////////////////////////////[04]
int AllocHardTimer(int source, int size, int prescale){
register int i;
int x;
if (QueryIntrContext()) return ERROR_INTR_CONTEXT; //intrman
CpuSuspendIntr(&x); //intrman
for (i=0; i<6; i++)
if (!t[i].allocated && (t[i].source & source) &&
(t[i].size==size) && (t[i].prescale>=prescale)){
t[i].allocated++; //u8
CpuResumeIntr(x); //intrman
return t[i].hwreg>>2;
}
CpuResumeIntr(x); //intrman
return ERROR_NO_TIMER;
}
///////////////////////////////////////////////////////////////////////[05]
int ReferHardTimer(int source, int size, int mode, int modemask){
register int i;
int x;
if (QueryIntrContext()) return ERROR_INTR_CONTEXT; //intrman
CpuSuspendIntr(&x); //intrman
for (i=0; i<6; i++)
if (t[i].allocated && (t[i].source & source) && (t[i].size==size) &&
(int)(GetTimerStatus(t[i].hwreg>>2) & modemask)==mode){
t[i].allocated++; //u8
CpuResumeIntr(x); //intrman
return t[i].hwreg>>2;
}
CpuResumeIntr(x); //intrman
return ERROR_NO_TIMER;
}
///////////////////////////////////////////////////////////////////////[10]
int GetHardTimerIntrCode(int timid){
switch(timid<<2){
case RTC2: return INT_RTC2;
case RTC0: return INT_RTC0;
case RTC1: return INT_RTC1;
case RTC4: return INT_RTC4;
case RTC3: return INT_RTC3;
case RTC5: return INT_RTC5;
}
return ERROR_UNK;
}
///////////////////////////////////////////////////////////////////////[06]
int FreeHardTimer(int timid){
register int i;
int x;
if (QueryIntrContext()) return ERROR_INTR_CONTEXT; //intrman
for (i=0; i<6; i++)
if (t[i].hwreg==(timid<<2))
break;
if ((i<6) && (t[i].allocated)){
CpuSuspendIntr(&x); //intrman
t[i].allocated--;
CpuResumeIntr(x); //intrman
return ERROR_OK;
}
return ERROR_NO_TIMER;
}
///////////////////////////////////////////////////////////////////////[07]
void SetTimerMode(int timid, int mode){
*(volatile short*)((timid<<2)+4) = mode;
}
///////////////////////////////////////////////////////////////////////[08]
unsigned int GetTimerStatus(int timid){
return *(volatile unsigned short*)((timid<<2)+4);
}
///////////////////////////////////////////////////////////////////////[09]
void SetTimerCounter(int timid, unsigned int count){
if ((timid<<2) < RTC3)
*(volatile short*)((timid<<2)+0)=count;
else
*(volatile int*)((timid<<2)+0)=count;
}
///////////////////////////////////////////////////////////////////////[0A]
unsigned int GetTimerCounter(int timid){
if ((timid<<2) < RTC3)
return *(volatile short*)((timid<<2)+0);
else
return *(volatile int*)((timid<<2)+0);
}
///////////////////////////////////////////////////////////////////////[0B]
void SetTimerCompare(int timid, unsigned int compare){
if ((timid<<2)+8 < RTC3)
*(volatile short*)((timid<<2)+8)=compare;
else
*(volatile int*)((timid<<2)+8)=compare;
}
///////////////////////////////////////////////////////////////////////[0C]
unsigned int GetTimerCompare(int timid){
if ((timid<<2)+8 < RTC3)
return *(volatile short*)((timid<<2)+8);
else
return *(volatile int*)((timid<<2)+8);
}
///////////////////////////////////////////////////////////////////////[0D]
void SetHoldMode(int holdnum, int mode){
RTC_HOLDMODE=(RTC_HOLDMODE &
( ~(0xF << (holdnum*4)))) |
((mode & 0xF) << (holdnum*4));
}
///////////////////////////////////////////////////////////////////////[0E]
unsigned long GetHoldMode(int holdnum){
return (RTC_HOLDMODE >> (holdnum*4)) & 0xF;
}
///////////////////////////////////////////////////////////////////////[0F]
unsigned long GetHoldReg(int holdnum){
return *(volatile unsigned int*)(RTC_HOLDREGS + (holdnum*4));
}
///////////////////////////////////////////////////////////////////////[01,02]
void _retonly(){}
//////////////////////////////entrypoint///////////////////////////////
struct export timrman_stub={
0x41C00000,
0,
VER(1, 1), // 1.1 => 0x101
0,
"timrman",
(func)_start, // entrypoint
(func)_retonly,
(func)_retonly,
(func)GetTimersTable,
(func)AllocHardTimer,
(func)ReferHardTimer,
(func)FreeHardTimer,
(func)SetTimerMode,
(func)GetTimerStatus,
(func)SetTimerCounter,
(func)GetTimerCounter,
(func)SetTimerCompare,
(func)GetTimerCompare,
(func)SetHoldMode,
(func)GetHoldMode,
(func)GetHoldReg,
(func)GetHardTimerIntrCode,
0
};
//////////////////////////////entrypoint///////////////////////////////[00]
int _start(int argc, char* argv[]){
int i;
u32 PRid;
__asm__ (
"mfc0 %0, $15\n"
: "=r"(PRid) :
);
if ((PRid<0x10) || (CONFIG_1450 & 8)) return 1;
for (i=5; i>=0; i--) t[i].allocated=0;
if( RegisterLibraryEntries(&timrman_stub) > 0 )
return 1;
EnableIntr(INT_RTC5);
return 0; //loadcore
}