templeos-info/public/Wb/Kernel/KMisc.HC

327 lines
6.7 KiB
HolyC
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

U0 PortNop()
{//Innoculous (reads IRQ Mask) which should take fixed time
//because it's an ISA-bus standard. It takes 1.0uS-2.0uS.
InU8(0x21);
}
U16 EndianU16(U16 d)
{//Swap big<-->little endian.
I64 res=0;
res.u8[1]=d.u8[0];
res.u8[0]=d.u8[1];
return res;
}
U32 EndianU32(U32 d)
{//Swap big<-->little endian.
I64 res=0;
res.u8[3]=d.u8[0];
res.u8[2]=d.u8[1];
res.u8[1]=d.u8[2];
res.u8[0]=d.u8[3];
return res;
}
I64 EndianI64(I64 d)
{//Swap big<-->little endian.
U64 res;
res.u8[7]=d.u8[0];
res.u8[6]=d.u8[1];
res.u8[5]=d.u8[2];
res.u8[4]=d.u8[3];
res.u8[3]=d.u8[4];
res.u8[2]=d.u8[5];
res.u8[1]=d.u8[6];
res.u8[0]=d.u8[7];
return res;
}
I64 BCnt(I64 d)
{//Count set bits in I64.
I64 res=0,i;
for (i=0;i<8;i++)
res+=set_bits_table[d.u8[i]];
return res;
}
U0 IntCore0TimerHndlr(CTask *)
{//Called from $LK,"IntCore0TimerHndlr",A="FF:::/Kernel/KInts.HC,IntCore0TimerHndlr"$
I64 i;
if (mp_cnt>1)
while (LBts(&sys_semas[SEMA_SYS_TIMER],0))
PAUSE
lock cnts.jiffies++;
cnts.timer+=SYS_TIMER0_PERIOD+1;
LBtr(&sys_semas[SEMA_SYS_TIMER],0);
for (i=1;i<mp_cnt;i++)
MPInt(I_TIMER,i);
OutU8(0x20,0x20); //Acknowledge PIC Interrupt
}
I64 SysTimerRead()
{//System timer count with overflow already handled.
I64 i,res;
PUSHFD
CLI
if (mp_cnt>1)
while (LBts(&sys_semas[SEMA_SYS_TIMER],0))
PAUSE
OutU8(0x43,0); //Latch Timer0
if ((i=InU8(0x40)+InU8(0x40)<<8)==SYS_TIMER0_PERIOD) {
if (InU8(0x20) & 1)
i=-1;
}
res=cnts.timer+SYS_TIMER0_PERIOD-i;
LBtr(&sys_semas[SEMA_SYS_TIMER],0);
POPFD
return res;
}
I64 HPET()
{ //Get high precision event timer.
return *(dev.uncached_alias+HPET_MAIN_CNT)(I64 *);
}
I64 TimeCal()
{
static I64 time_stamp_start=0,timer_start=0,HPET_start=0;
I64 i;
if (time_stamp_start) {
PUSHFD
CLI
if (HPET_start) {
cnts.time_stamp_freq=cnts.HPET_freq*(GetTSC-time_stamp_start);
i=HPET-HPET_start;
} else {
cnts.time_stamp_freq=SYS_TIMER_FREQ*(GetTSC-time_stamp_start);
i=SysTimerRead-timer_start;
}
if (!i)
AdamErr("Timer Cal Error");
else {
cnts.time_stamp_freq/=i;
cnts.time_stamp_kHz_freq=cnts.time_stamp_freq/1000;
cnts.time_stamp_calibrated=TRUE;
}
POPFD
}
PUSHFD
CLI
if (cnts.HPET_freq) {
timer_start=0;
HPET_start=HPET;
} else {
timer_start=SysTimerRead;
HPET_start=0;
}
time_stamp_start=GetTSC;
POPFD
return cnts.time_stamp_freq;
}
F64 tS()
{//Time since boot in seconds as a float.
if (cnts.HPET_freq)
return ToF64(HPET-cnts.HPET_initial)/cnts.HPET_freq;
else
return SysTimerRead/ToF64(SYS_TIMER_FREQ);
}
Bool Blink(F64 Hz=2.5)
{//Return TRUE, then FALSE, then TRUE at given frequency.
if (!Hz) return 0;
return ToI64(cnts.jiffies*2*Hz/JIFFY_FREQ)&1;
}
U0 Busy(I64 <EFBFBD>S)
{//Loosely timed.
I64 i;
if (cnts.HPET_freq) {
i=HPET+cnts.HPET_freq*<EFBFBD>S/1000000;
while (HPET<i);
} else
for (i=0;i<<EFBFBD>S;i++)
PortNop;
}
U0 SleepUntil(I64 wake_jiffy)
{//Not for power-saving.It is to make a program pause without hogging the CPU.
Bool old_idle=LBts(&Fs->task_flags,TASKf_IDLE);
Fs->wake_jiffy=wake_jiffy;
Yield;
LBEqu(&Fs->task_flags,TASKf_IDLE,old_idle);
}
U0 Sleep(I64 mS)
{//Not for power-saving.It is to make a program pause without hogging the CPU.
if (!mS)
Yield;
else
SleepUntil(cnts.jiffies+mS*JIFFY_FREQ/1000);
}
F64 Ona2Freq(I8 ona)
{//Ona to freq. Ona=60 is 440.0Hz.
if (!ona)
return 0;
else
return 440.0/32*2.0`(ona/12.0);
}
I8 Freq2Ona(F64 freq)
{//Freq to Ona. 440.0Hz is Ona=60.
if (freq>0)
return ClampI64(12*Log2(32.0/440.0*freq),1,I8_MAX);
else
return 0;
}
U0 Snd(I8 ona=0)
{//Play ona, a piano key num. 0 means rest.
I64 period;
CSndData *d;
if (!Bt(&sys_semas[SEMA_MUTE],0) &&
!LBts(&sys_semas[SEMA_SND],0)) { //Mutex. Just throw-out if in use
if (!ona) {
scrncast.ona=ona;
OutU8(0x61,InU8(0x61)&~3);
} else if (ona!=scrncast.ona) {
scrncast.ona=ona;
period=ClampI64(SYS_TIMER_FREQ/Ona2Freq(ona),1,U16_MAX);
OutU8(0x43,0xB6);
OutU8(0x42,period);
OutU8(0x42,period.u8[1]);
OutU8(0x61,3|InU8(0x61));
}
if (!IsDbgMode && scrncast.record) {
d=ACAlloc(sizeof(CSndData));
d->ona=ona;
d->tS=tS;
QueIns(d,scrncast.snd_head.last);
}
LBtr(&sys_semas[SEMA_SND],0);
}
}
Bool ScrnCast(Bool val=ON,Bool just_audio=FALSE,U8 *print_fmt="B:/Tmp/%X.GR")
{//WinMgr saves GR files to a dir.
Bool old_val;
scrncast.just_audio=just_audio;
if (val) {
if (!(old_val=LBtr(&scrncast.record,0))) {
Free(scrncast.print_fmt);
scrncast.print_fmt=AStrNew(print_fmt);
scrncast.t0_now=Now;
scrncast.snd_head.tS=scrncast.t0_tS=tS;
scrncast.snd_head.ona=scrncast.ona;
LBts(&scrncast.record,0);
}
} else
old_val=LBtr(&scrncast.record,0);
Snd;
return old_val;
}
U0 SndRst()
{//Fix stuck sound.
if (Bt(&sys_semas[SEMA_SND],0)) {
Sleep(1);
if (Bt(&sys_semas[SEMA_SND],0)) {
Sleep(1);
LBtr(&sys_semas[SEMA_SND],0);
}
}
Snd;
}
U0 Beep(I8 ona=62,Bool busy=FALSE)
{//Make beep at given ona freq.
Snd(ona);
if (busy)
Busy(500000);
else
Sleep(500);
Snd;
if (busy)
Busy(200000);
else
Sleep(200);
}
Bool Mute(Bool val)
{//Turn-off sound.
Bool res;
if (val) {
PUSHFD
CLI
Snd;
res=LBts(&sys_semas[SEMA_MUTE],0);
POPFD
} else
res=LBtr(&sys_semas[SEMA_MUTE],0);
return res;
}
Bool IsMute()
{//Return is-mute flag.
return Bt(&sys_semas[SEMA_MUTE],0);
}
Bool Silent(Bool val=ON)
{//Turn-off StdOut console text. (Not sound.)
return LBEqu(&Fs->display_flags,DISPLAYf_SILENT,val);
}
Bool IsSilent()
{//Return StdOut turned-off?
return Bt(&Fs->display_flags,DISPLAYf_SILENT);
}
Bool SysDbg(Bool val)
{//Set SysDbg bit you can use while debugging.
return LBEqu(&sys_semas[SEMA_DEBUG],0,val);
}
Bool IsSysDbg()
{//Return SysDbg bit.
return Bt(&sys_semas[SEMA_DEBUG],0);
}
Bool Raw(Bool val)
{//Set to direct scrn, BLACK & WHITE, non-windowed output mode.
if (!val)
VGAFlush;
return !LBEqu(&Fs->display_flags,DISPLAYf_NOT_RAW,!val);
}
Bool IsRaw()
{//Are we in BLACK & WHITE raw scrn mode?
return !Bt(&Fs->display_flags,DISPLAYf_NOT_RAW);
}
Bool SingleUser(Bool val)
{//Set single-user mode.
return LBEqu(&sys_semas[SEMA_SINGLE_USER],0,val);
}
Bool IsSingleUser()
{//Return single-user mode.
return Bt(&sys_semas[SEMA_SINGLE_USER],0);
}
Bool DbgMode(Bool val)
{//Set dbg-mode.
return LBEqu(&sys_semas[SEMA_DBG_MODE],0,val);
}
Bool IsDbgMode()
{//Return dbg-mode.
return Bt(&sys_semas[SEMA_DBG_MODE],0);
}
U0 ProgressBarsRst(U8 *path=NULL)
{//Reset all progress bars to zero.
CallExtStr("ProgressBarsRegTf",path);
MemSet(sys_progresses,0,sizeof(sys_progresses));
}