SparrowOSTS_121127.ISO

This commit is contained in:
Terry A. Davis authored and minexew committed 2018-09-08 21:45:28 +02:00
1 parent 0e9364ff4c
commit e57428affb
1218 files changed
+247142 -165507

No files matched your search

+12
View File
@@ -0,0 +1,12 @@
//This is executed by Adam at boot.
//See $LK,"Adam1 Start-up","FF:::/SparrowOS/OSMain/OSEnd.CPP.Z,Adam1:2"$
extern I8i OptEqu(I64i num,I8i val);
OptEqu(0,0); //(0,0)=EchoOff (0,1)=EchoOn
#include "/SparrowOS/OSMain/BootDefs.HPP.Z"
#include "/SparrowOS/OSMain/Adam1a.HPP.Z"
#include "/SparrowOS/Compiler/CmpDefs.HPP.Z"
#include "/SparrowOS/OSMain/Adam1b.HPP.Z"
#include "/SparrowOS/OSMain/Adam1c.HPP.Z"
#include "/SparrowOS/Compiler/Compiler.HPP.Z"
Cd("/SparrowOS/Adam");;
#include "Adam2.CPP.Z"
File diff suppressed because it is too large. Load diff
+301
View File
@@ -0,0 +1,301 @@
/*
In this file, syms defined OSMain assembly
files are given C+ definitions. This file
is included when you compile the kernel, after
the assembly files have been assembled, making
the C+ definitions available for the C+ OSMain
files. It is also included as part of booting.
The assembly global labels are stored as HTT_EXPORT_SYS_SYM
entries in the hash table. These symols are placed
into the OSMain binary module and added to the
sym hash table at boot before this file
gets #included during boot.
See
$LK,"Adam1b","FF:::/SparrowOS/OSMain/OSMain.PRJ.Z,Adam1b"$ for where it is included during compiling the kernel.
$LK,"Adam1b","FF:::/SparrowOS/OSMain/Adam1.CPP.Z,Adam1b"$ for where it is included during boots.
$LK,"LoadOSMain","FF:::/SparrowOS/OSMain/OSEnd.CPP.Z,LoadOSMain"$ for where the OSMain syms are added to the hash tables.
*/
#help_index "Misc;Messages"
public _extern SYS_FOCUS_TASK CTask *sys_focus_task;
#help_index "Graphics/Screen"
//This is the INT 0x10 mode number.
public _extern SYS_BIOS_GR_MODE U16 bios_gr_mode;
#help_index "PCI"
public _extern SYS_PCI_BUSSES U16 sys_pci_busses;
#help_index "Misc"
public _extern SYS_CTRL_ALT_FLAGS I64 sys_ctrl_alt_flags[1];
public _extern SYS_COMPILE_TIME CDate sys_compile_time;
#help_index "Boot"
_extern SYS_BOOT_BASE U32 sys_boot_base;
_extern SYS_BOOT_CODE U32 sys_boot_code;
_extern SYS_RUN_LEVEL U32 sys_run_level;
_extern SYS_BOOT_PATCH_TABLE_BASE U32 sys_boot_patch_table_base;
#help_index "Misc/Progress Bars"
public _extern SYS_PROGRESSES CProgress sys_progresses[NUM_PROGRESS_BARS];
public _extern SYS_PROGRESS1 I64 progress1;
public _extern SYS_PROGRESS1_MAX I64 progress1_max;
public _extern SYS_PROGRESS1_DESC U8 progress1_desc[PROGRESS_DESC_LEN+1];
public _extern SYS_PROGRESS2 I64 progress2;
public _extern SYS_PROGRESS2_MAX I64 progress2_max;
public _extern SYS_PROGRESS2_DESC U8 progress2_desc[PROGRESS_DESC_LEN+1];
public _extern SYS_PROGRESS3 I64 progress3;
public _extern SYS_PROGRESS3_MAX I64 progress3_max;
public _extern SYS_PROGRESS3_DESC U8 progress3_desc[PROGRESS_DESC_LEN+1];
public _extern SYS_PROGRESS4 I64 progress4;
public _extern SYS_PROGRESS4_MAX I64 progress4_max;
public _extern SYS_PROGRESS4_DESC U8 progress4_desc[PROGRESS_DESC_LEN+1];
#help_index "Bit"
#help_file "::/SparrowOS/Doc/Bit"
public _intern IC_BT Bool Bt(U8 *bit_field,I64 bit);
public _intern IC_BTS Bool Bts(U8 *bit_field,I64 bit);
public _intern IC_BTR Bool Btr(U8 *bit_field,I64 bit);
public _intern IC_BTC Bool Btc(U8 *bit_field,I64 bit);
public _intern IC_BEQU Bool BEqu(U8 *bit_field,I64 bit,Bool val);
//Locked for (for multitple CPU's)
public _intern IC_LBTS Bool LBts(U8 *bit_field,I64 bit);
public _intern IC_LBTR Bool LBtr(U8 *bit_field,I64 bit);
public _intern IC_LBTC Bool LBtc(U8 *bit_field,I64 bit);
public _intern IC_LBEQU Bool LBEqu(U8 *bit_field,I64 bit,Bool val);
//Scan I64 sized item fwd for first set bit, starting at lowest.
//Return -1 if not found.
public _intern IC_BSF I64 Bsf(I64 bit_field_val);
//Scan I64 sized item reverse for first set bit, starting at highest.
//Return -1 if not found.
public _intern IC_BSR I64 Bsr(I64 bit_field_val);
public _extern _BIT_FIELD_OR_U32 U0 BFieldOrU32(
U8 *bit_field,I64 bit,U32 pattern);
public _extern _BIT_FIELD_EXTRACT_U32 U32 BFieldExtU32(
U8 *bit_field,I64 bit,I64 size);
#help_index "Circular Queue"
#help_file "::/SparrowOS/Doc/Que"
public _intern IC_QUE_INIT U0 QueInit(CQue *root);
//Ins item into que after predicessor.
public _intern IC_QUE_INS U0 QueIns(CQue *entry,CQue *pred);
//Reversed insert into que. Ins
//item into que before successor.
public _intern IC_QUE_INS_REV U0 QueInsRev(CQue *entry,CQue *succ);
//Remove item from que.
public _intern IC_QUE_REM U0 QueRem(CQue *entry);
#help_index "Task"
public _intern IC_PREEMPT Bool Preempt(Bool val);
#help_index "I/O;Processor/IO Port"
public _intern IC_INU8 I64 InU8(I64 port);
public _intern IC_INU16 I64 InU16(I64 port);
public _intern IC_INU32 I64 InU32(I64 port);
public _intern IC_OUTU8 U0 OutU8(I64 port, I64 val);
public _intern IC_OUTU16 U0 OutU16(I64 port, I64 val);
public _intern IC_OUTU32 U0 OutU32(I64 port, I64 val);
public _extern _REP_IN_U8 U0 RepInU8(U8 *buf,I64 cnt,I64 port);
public _extern _REP_IN_U16 U0 RepInU16(U8 *buf,I64 cnt,I64 port);
public _extern _REP_IN_U32 U0 RepInU32(U8 *buf,I64 cnt,I64 port);
public _extern _REP_OUT_U8 U0 RepOutU8(U8 *buf,I64 cnt,I64 port);
public _extern _REP_OUT_U16 U0 RepOutU16(U8 *buf,I64 cnt,I64 port);
public _extern _REP_OUT_U32 U0 RepOutU32(U8 *buf,I64 cnt,I64 port);
#help_index "Memory"
//Only goes fwd.
public _intern IC_MEMCPY U0 MemCpy(U8 *dst,U8 *src,I64 cnt);
public _intern IC_MEMSET U8 *MemSet(U8 *dst,I64 val,I64 cnt);
public _intern IC_MEMSET U8 *MemSetU8(U8 *dst,I64 val,I64 U8cnt);
public _intern IC_MEMSET_U16 U16 *MemSetU16(U8 *dst,I64 val,I64 U16cnt);
public _intern IC_MEMSET_U32 U32 *MemSetU32(U8 *dst,I64 val,I64 U32cnt);
public _intern IC_MEMSET_U64 U64 *MemSetU64(U8 *dst,I64 val,I64 U64cnt);
public _extern SYS_CODE_BP CBlkPool *sys_code_bp;
public _extern SYS_DATA_BP CBlkPool *sys_data_bp;
public _extern SYS_HEAP_BASE U32 sys_heap_base;
public _extern SYS_HEAP_LIMIT U32 sys_heap_limit;
_extern SYS_HEAP_INIT_FLAG U8 sys_heap_init_flag;
_extern SYS_HEAP_INIT_VAL U8 sys_heap_init_val;
_extern SYS_MEM_INIT_FLAG U8 sys_mem_init_flag;
_extern SYS_MEM_INIT_VAL U8 sys_mem_init_val;
_extern SYS_VAR_INIT_FLAG U8 sys_var_init_flag;
_extern SYS_VAR_INIT_VAL U8 sys_var_init_val;
_extern SYS_HEAP_DBG_FLAG U8 sys_heap_dbg;
#help_index "Char/Conversion"
public _intern IC_TOUPPER I64 ToUpper(U8 ch);
#help_index "Char/Operations"
public _intern IC_STRLEN I64 StrLen(U8 *st);
#help_index "Processor"
public _extern _CPUID U0 CPUId(U32 rax,CRAXRBCRCXRDX *result);
public _intern IC_SET_RAX U0 SetRAX(I64 d);
public _intern IC_GET_RAX I64 GetRAX();
public _intern IC_CLI U0 Cli();
public _intern IC_STI U0 Sti();
public _intern IC_PUSHFD U0 PushFD();
public _intern IC_POPFD U0 PopFD();
public _intern IC_HLT U0 Hlt();
public _extern _SYS_HLT U0 SysHlt(); //Loops
//This instruction hints to the processor
//that a spin-loop is taking place.
public _intern IC_PAUSE U0 Pause();
public _intern IC_POP I64 Pop();
public _intern IC_PUSH U0 Push(I64 d);
public _intern IC_CLD U0 Cld();
public _intern IC_STD U0 Std();
public _intern IC_GET_FLAGS I64 GetFlags();
public _intern IC_SET_FLAGS U0 SetFlags(I64 d);
public _intern IC_GET_STK_PTR U8 *GetStkPtr();
public _intern IC_SET_STK_PTR U0 SetStkPtr(U8 *d);
public _intern IC_GET_BASE_PTR U8 *GetBasePtr();
public _intern IC_SET_BASE_PTR U0 SetBasePtr(U8 *d);
public _extern SYS_CACHE_LINE_WIDTH I64 sys_cache_line_width;
_extern SYS_GDTTAB U8 sys_gdttab[GDT_SIZE];
public _extern _XCHG_U64 U64 XchgU64(U64 *dst,U64 d);
public _extern _XCHG_U32 U64 XchgU32(U32 *dst,U32 d);
public _extern _XCHG_U16 U64 XchgU16(U16 *dst,U16 d);
public _extern _XCHG_U8 U64 XchgU8 (U8 *dst,U8 d);
public _extern _LXCHG_U64 U64 LXchgU64(U64 *dst,U64 d);
public _extern _LXCHG_U32 U64 LXchgU32(U32 *dst,U32 d);
public _extern _LXCHG_U16 U64 LXchgU16(U16 *dst,U16 d);
public _extern _LXCHG_U8 U64 LXchgU8(U8 *dst,U8 d);
//Model Specific REgisters
//See $LK,"MSRs","MN:IA32_EFER"$
public _extern _SET_MSR U0 SetMSR(I64 model_specific_reg,I64 val);
#help_index "Processor/Cache;Memory/Cache"
public _intern IC_INVLPG U0 InvlPg(U8 *a);
//Flush cache line.
public _intern IC_CLFLUSH U0 CLFlush(U8 *a);
#help_index "MultiCore"
#help_file "::/SparrowOS/Doc/MultiCore"
_extern _SET_GS_BASE U0 SetGs(CCPU *c);
public _extern SYS_MP_CNT I64 mp_cnt;
_extern SYS_MP_CNT_INITIAL I64 mp_cnt_initial; //only used during $LK,"MPStart","MN:MPStart"$
_extern SYS_MP_CNT_LOCK I64 mp_cnt_lock;
_extern SYS_TEMP_CPU0_STRUCT CCPU sys_temp_cpu0_struct;
public _extern SYS_CPU_STRUCTS CCPU *cpu_structs;
_extern SYS_SEMAS CSema sys_semas[NUM_SYS_SEMAS];
#help_index "MultiCore;Processor"
//This pts to the current CPU structure.
//It returns the val in the GS segment register.
public _intern IC_GS CCPU *Gs();
#help_index "Time/CPU Cycles"
public _intern IC_RDTSC I64 GetTimeStamp();
#help_index "Time/HPET"
public _intern IC_HPET I64 HPET();
#help_index "Time/Jiffies"
#help_file "::/SparrowOS/Doc/TimeJiffy"
_extern SYS_TIMER I64 sys_timer;
public _extern SYS_JIFFIES I64 sys_jiffies;
#help_index "Math"
public _intern IC_TO_I64 I64 ToI64(F64 d); //This truncates
public _intern IC_TO_F64 F64 ToF64(I64 i);
public _intern IC_TO_BOOL Bool ToBool(I64 i);
public _intern IC_ABS_I64 I64 AbsI64(I64 i);
public _intern IC_LIMIT_I64 I64 LimitI64(I64 p,I64 lo,I64 hi);
public _intern IC_LIMIT_U64 U64 LimitU64(U64 p,U64 lo,U64 hi);
public _intern IC_SIGN_I64 I64 SignI64(I64 i);
public _intern IC_SQR_I64 I64 SqrI64(I64 i);
public _intern IC_SQR_U64 U64 SqrU64(U64 i);
public _intern IC_SWAP_U8 U0 SwapU8(U8 *n1,U8 *n2);
public _intern IC_SWAP_U16 U0 SwapU16(U16 *n1,U16 *n2);
public _intern IC_SWAP_U32 U0 SwapU32(U32 *n1,U32 *n2);
public _intern IC_SWAP_U64 U0 SwapU64(U64 *n1,U64 *n2);
public _intern IC_MIN_I64 I64 MinI64(I64 n1,I64 n2);
public _intern IC_MAX_I64 I64 MaxI64(I64 n1,I64 n2);
public _intern IC_MIN_U64 U64 MinU64(U64 n1,U64 n2);
public _intern IC_MAX_U64 U64 MaxU64(U64 n1,U64 n2);
public _intern IC_MOD_U64 U64 ModU64(U64 *q,U64 d);
public _intern IC_SQR F64 Sqr(F64 d);
public _intern IC_ABS F64 Abs(F64 d);
public _intern IC_SQRT F64 Sqrt(F64 d);
public _intern IC_SIN F64 Sin(F64 d);
public _intern IC_COS F64 Cos(F64 d);
public _intern IC_TAN F64 Tan(F64 d);
public _intern IC_ATAN F64 ATan(F64 d);
public _extern _SIGN F64 Sign(F64 d);
public _extern _ARG F64 Arg(F64 x,F64 y);
public _extern _ROUND F64 Round(F64 d);
public _extern _TRUNC F64 Trunc(F64 d);
public _extern _FLOOR F64 Floor(F64 d);
public _extern _CEIL F64 Ceil(F64 d);
public _extern _POW F64 Pow(F64 base,F64 power);
public _extern _POW10 F64 Pow10(F64 d);
public _extern _LOG2 F64 Log2(F64 d);
public _extern _LOG10 F64 Log10(F64 d);
public _extern _LN F64 Ln(F64 d);
public _extern _EXP F64 Exp(F64 d);
_extern _FLDCW U0 Fldcw(U16 w);
_extern _FCLEX U0 Fclex();
_extern _FSTCW U16 Fstcw();
_extern _FSTSW U16 Fstsw();
_extern _FXSAVE U0 Fxsave(CFPU *fpu_mmx);
_extern _FXRSTOR U0 Fxrstor(CFPU *fpu_mmx);
_extern SYS_INIT_FPU_MMX CFPU sys_init_fpu_mmx;
#help_index "Math/CD3;ODE/CD3"
#help_file "::/SparrowOS/Doc/D3"
public _extern _D3_EQU CD3 *D3Equ(CD3 *dst,F64 x,F64 y,F64 z);
public _extern _D3_ZERO CD3 *D3Zero(CD3 *dst);
public _extern _D3_COPY CD3 *D3Copy(CD3 *dst,CD3 *src);
public _extern _D3_NORM F64 D3Norm(CD3 *d);
public _extern _D3_SQR_NORM F64 D3SqrNorm(CD3 *d);
public _extern _D3_ADD CD3 *D3Add(CD3 *d1,CD3 *d2,CD3 *sum);
public _extern _D3_SUB CD3 *D3Sub(CD3 *d1,CD3 *d2,CD3 *diff);
public _extern _D3_MUL CD3 *D3Mul(F64 c,CD3 *d,CD3 *prod);
public _extern _D3_DIV CD3 *D3Div(F64 c,CD3 *d,CD3 *quot);
public _extern _D3_ADD_EQU CD3 *D3AddEqu(CD3 *sum,CD3 *d);
public _extern _D3_SUB_EQU CD3 *D3SubEqu(CD3 *diff,CD3 *d);
public _extern _D3_MUL_EQU CD3 *D3MulEqu(CD3 *prod,F64 c);
public _extern _D3_DIV_EQU CD3 *D3DivEqu(CD3 *quot,F64 c);
public _extern _D3_DIST F64 D3Dist(CD3 *d1,CD3 *d2);
public _extern _D3_SQR_DIST F64 D3SqrDist(CD3 *d1,CD3 *d2);
//Dot Product
public _extern _D3_DOT F64 D3Dot(CD3 *d1,CD3 *d2);
//Cross Product
public _extern _D3_CROSS CD3 *D3Cross(CD3 *d1,CD3 *d2,CD3 *prod);
//Convert to unit vect
public _extern _D3_UNIT CD3 *D3Unit(CD3 *d);
#help_index "Task;Processor"
//This pts to the current task record.
//It returns the val in the FS segment register.
public _intern IC_FS CTask *Fs();
#help_index "Call"
public _extern _CALL I64 Call(U8 *s);
//fp_add can have any fixed number of arguments.
public _extern _CALLIND I64 CallInd(/*argpop*/I64 (*fp_add)(...),...);
//This is just an array of ptrs to funs.
//See $LK,"Extern Num Definitions","MN:EXT_TABLE_SIZE"$
public _extern SYS_EXTERN_TABLE /*argpop*/ I64 (**ext)(...);
//Can have any fixed number of arguments.
public _extern _CALLEXTNUM I64 CallExtNum(I64 num,...);
//Search sym table for fun name and pass it args.
//Can have any fixed number of arguments.
public _extern _CALLEXTSTR I64 CallExtStr(/*argpop*/ U8 *name,...);
#help_index ""
+808
View File
@@ -0,0 +1,808 @@
#help_index "Time/CDate"
#help_file "::/SparrowOS/Doc/TimeCDate"
public extern CDate local_time_offset;
#help_index "Time/Jiffies"
//18.33333*65536Hz (SYS_TIMER_FREQ)
public extern I64 SysTimerRead();
#help_index "Task"
extern U8 *sys_acct;
extern CTask *sys_winmgr_task,*sys_task_being_screen_updated;
public extern CTask *adam_task;
public extern I64 sys_num_spawned_users;
extern U0 TaskFinishOffDying();
public _extern SYS_SAVE_CONTEXT_YIELD U0 Yield();
public extern U0 TSSBusy(I64 tr,Bool val=OFF);
_extern SYS_IDLE_START U8 sys_idle_start;
_extern SYS_IDLE_END U8 sys_idle_end;
_extern SYS_TASK_END_NOW U0 TaskEndNow();
#help_index "Time/CPU Cycles"
#help_file "::/SparrowOS/Doc/TimeCycles"
public extern I64 time_stamp_freq,time_stamp_kHz_freq;
public extern I64 TaskTotalTime();
//This is sampled once at boot time
public extern I64 time_stamp_freq_initial;
#help_index "Time/HPET"
#help_file "::/SparrowOS/Doc/TimeHPET"
public extern I64 HPET_freq,HPET_kHz_freq;
#help_index "Time/Seconds"
public extern F64 tNP(); //High freq. No accounting for task Pause.
public extern F64 tJ(); //From Jiffies.
public extern F64 tS(); //From SysTimerFreq.
public extern F64 tP(CTask *task=NULL); //High freq. Accounts for task pause.
public extern Bool Blink(F64 Hz=2.5,F64 t=0);
#help_index "Snd"
#help_file "::/SparrowOS/Doc/Snd"
public extern I64 snd_dev;
public extern F64 snd_vol,snd_reverb_intensity,snd_reverb_delay;
public extern U0 Snd(F64 freq,I64 waveform=WF_SQUARE,F64 amp=1.0);
public extern Bool Mute(Bool val);
public extern Bool IsMute();
public extern F64 snd_freq;
public extern U0 Beep(I64 freq=500,Bool busy=FALSE);
public extern Bool IOSnd(Bool val);
#help_index "Snd/Snd Files"
public extern Bool snd_record;
extern U0 (*fp_snd_record)(F64 freq,I64 waveform,F64 amp);
#help_index "Snd/HDAudio"
public extern U0 (*fp_snd)(F64 freq,I64 waveform,F64 amp);
public extern U0 (*fp_snd_fill_buf)(SND_OUT_CONTAINER *buf,I64 buf_num);
public extern U0 (*fp_snd_copy_buf)(SND_IN_CONTAINER *buf,I64 buf_num);
#help_index "Processor"
extern U8 *sys_fault_handlers_code;
public extern U8 *IntEntryGet(I64 irq,I64 cpu_num=-1);
public extern U8 *IntEntrySet(I64 irq,U0 (*fp_new_handler)(),I64 cpu_num=-1,I64 type=IDTET_IRQ,I64 dpl=0);
extern CPCIDev sys_pci_dev_root;
extern CMemRange sys_mem32_dev_root;
#help_index "Task/Delay;Time/CPU Cycles"
public extern I64 TimeStampFreqCal();
public extern U0 BusyWait(I64 æS); //Loosely timed
public extern U0 SleepUntil(I64 wake_jiffy);
public extern U0 Sleep(I64 mS);
public extern U0 PortNop(); //On the order of 1uS
#help_index "Task"
public extern Bool IsPreempt();
#help_index "Debugging"
#help_file "::/SparrowOS/Doc/Dbg"
extern CTask *sys_dbg_focus_task;
public extern U0 D(U8 *buf,I64 cnt=0x80,Bool show_offset=TRUE);
public extern U0 Dm(U8 *buf,I64 cnt=0x80);
public extern U0 Da(U8 **b,I64 cnt=0x10);
extern I64 *TaskRegAdd(CTask *task,I64 reg_num);
public extern U0 Dr(CTask *task=NULL);
public extern Bool IsDbgTask();
public extern Bool IsSysDbg();
public extern Bool IsSysDeterministic();
public extern Bool SysDbg(Bool val);
public extern Bool SysDeterministic(Bool val);
public extern Bool ChkPtr(U8 *ptr);
public extern Bool ChkOnStk(U8 *ptr,CTask *task=NULL);
public extern I64 UnusedStk(CTask *task=NULL);
public extern U0 StkRep(CTask *task=NULL);
public extern U0 CallerRep(U8 **rbp=NULL,CTask *task=NULL);
public extern U8 *Caller(I64 num=1);
public extern U8 *TaskCaller(CTask *task=NULL,I64 num=0,Bool saved_context=FALSE);
public extern U0 Dbg(U8 *msg=NULL,I64 num=0,Bool fault=FALSE);
public extern U0 Go1();
public extern I64 sys_dbg_fault_num;
public extern U8 *sys_dbg_fault_rip;
#help_index "Debugging/Raw Output"
public extern U0 RawDrawChar(I64 ch);
public extern U0 VGAFlush();
public extern Bool Raw(Bool val);
public extern Bool IsRaw();
public extern Bool SingleUser(Bool val);
public extern Bool IsSingleUser();
public extern Bool InDbg(Bool val);
public extern Bool IsInDbg();
public extern U0 DbgStr(U8 *st,I64 mS=100);
public extern U0 DbgNum(I64 num,I64 mS=100);
public extern U0 DbgF(F64 d,I64 mS=100);
public extern U0 DbgAdd(U8 *add,I64 mS=100);
public extern U0 DbgD(U8 *add,I64 cnt=0x80,I64 mS=100);
public extern U0 DbgDm(U8 *add,I64 cnt=0x80,I64 mS=100);
#help_index "Graphics/Color"
extern U0 (*fp_set_std_palette)();
public extern U8 *Color2Text(U8 *buf,CColorROPU32 c);
#help_index "Char"
#help_file "::/SparrowOS/Doc/Char"
extern U0 (**fp_ctrl_alt_let_cbs)(I64 sc);
extern I64 ctrl_alt_let_in_irq_flags;
extern U8 **ctrl_alt_let_descs;
extern I64 **ctrl_alt_let_ret_addr; //addr of ret add on stack in kbd irq
extern CTaskCmd sys_macro_root;
extern CKeyDev sys_put_key_root;
extern CTask *sys_macro_util_task;
extern I64 sys_raw_dc_col,sys_raw_dc_flags;
extern U8 *sys_dc_screen_image;
public extern Bool text_mode;
//Constants are defined for these to
//optimize. See $LK,"::/SparrowOS/Adam/Gr/GrCfg.CPP.Z","FI:::/SparrowOS/Adam/Gr/GrCfg.CPP.Z"$.
public extern I64 text_rows,text_cols,gr_width,gr_height;
public extern U8 *gr_font;
public extern CKeyDev *KeyDevAdd(Bool (*fp_put_key)(I64 ch,I64 sc),Bool (*fp_puts)(U8 *st),I64 priority,Bool key_descs=FALSE);
public extern U0 KeyDevRem(CKeyDev *tempp);
public extern U0 SetKeyDesc(U8 *fmt,...);
public extern U0 SetCtrlAltLetCB(U8 ch,U0 (*fp_handler)(I64 sc),U8 *desc,Bool in_irq=FALSE);
extern U8 key_desc[128];
extern U8 *key_handler;
#help_index "Char/Output;Char/Define"
public extern U0 PutDefineErr(U8 *st);
public extern U0 PutDefineWarn(U8 *st);
#help_index "Char/Output"
public extern U0 PrintF(U8 *fmt,...);
public extern U0 PrintFErr(U8 *fmt,...);
public extern U0 PrintFWarn(U8 *fmt,...);
public extern U0 NewLine(I64 cnt=1);
public extern U0 Spaces(I64 cnt=1);
public extern U0 PutErr(U8 *st=NULL);
public extern U0 PutWarn(U8 *st=NULL);
public extern U0 PutKey(I64 ch,I64 scancode);
public extern U0 PutChar(I64 ch);
public extern U0 PutS(U8 *st);
public extern U8 *Bin2Hex(U8 *dst,I64 n;I64 width);
public extern U0 PutHex(I64 n,I64 width);
public extern Bool Silent(Bool val);
public extern Bool IsSilent();
public extern U0 GetOutOfDollar();
#help_index "Char/Conversion"
public extern I64 A2I(U8 *st,I64 radix=10,U8 **_end_ptr=NULL);
#help_index "Input Pointer/Mouse"
public extern I64 mouse_evt_time;
extern I64 mouse_pkt_size;
#help_index "Char/Input"
public extern I64 kbd_evt_time;
extern Bool kbd_irqs_working;
public extern Bool PressAKey();
public extern Bool ExitAllApplications();
public extern Bool AreYouSure();
public extern I64 GetKey(I64 *_scancode=NULL,Bool echo=FALSE,Bool raw_cursor=FALSE);
public extern I64 GetChar(I64 *_scancode=NULL,Bool echo=TRUE,Bool raw_cursor=FALSE);
public extern Bool ScanKey(I64 *_ch=NULL,I64 *_scancode=NULL,Bool echo=FALSE);
public extern Bool YorN();
public extern I64 GetS(U8 *buf,I64 size,Bool allow_ext=TRUE);
public extern I64 KbdMouseEvtTime();
//Gets $LK,"Flags","MN:GETSF_SHIFT_ESC_EXIT"$
public extern U8 *MGetS(I64 flags=0);
extern U8 *(*fp_mgets)(I64 flags=0);
extern U8 *GetFJoin(U8 *src,U8 *fmt,I64 argc,I64 *argv);
public extern U8 *GetF(U8 *src,U8 *fmt,...);
#help_index "Char/Lists"
public extern U8 *ListEntryPt(I64 entry_num, U8 *lst);
public extern I64 ListEntryMatch(U8 *src, U8 *lst,I64 flags=0,I64 *_ambiguity_overkill=NULL);
#help_index "Char/Operations"
public extern I64 StrOcc(U8 *src, U8 ch);
public extern U8 *StrFirstOcc(U8 *src,U8 *marker);
public extern U8 *StrLastOcc(U8 *src,U8 *marker);
public extern I64 Spaces2Tabs(U8 *dst,U8 *src);
public extern U8 *Tabs2Spaces(U8 *src);
public extern U8 *ScaleIndent(U8 *src,F64 indent_scale_factor);
public extern U8 *StrUtil(U8 *_src,I64 flags);
public extern U8 *MStrUtil(U8 *src,I64 flags,F64 indent_scale_factor=0);
public extern U8 *StrFirstRem(U8 *src,U8 *marker,U8 *dst=NULL);
public extern U8 *StrLastRem(U8 *src,U8 *marker,U8 *dst=NULL);
public extern Bool WildCardMatch(U8 *wild_st,U8 *src_st);
public extern U8 *StrAdd(U8 *base,U8 *addition); //frees base arg
public extern U8 *SearchStr(U8 *src,U8 *pattern,I64 flags=0);
extern U8 *SPrintFJoin(U8 *dst,U8 *fmt,I64 argc,I64 *argv);
public extern U8 *SPrintF(U8 *dst,U8 *fmt,...);
public extern U8 *MSPrintF(U8 *fmt,...);
#help_index "Char/Define"
#help_file "::/SparrowOS/Doc/Define"
public extern CHashDefineStr *DefineLoad(U8 *name,U8 *st,Bool replace=FALSE);
public extern CHashDefineStr *DefineListLoad(U8 *name,U8 *st,Bool replace=FALSE);
public extern U0 DefinePrintF(U8 *name,U8 *src,...);
public extern U8 *Define(U8 *name);
public extern U8 *DefineSub(I64 sub,U8 *name);
public extern I64 DefineSubCnt(U8 *name);
public extern U0 PutDefine(U8 *name);
#help_index "Char/Define;Char/Lists"
public extern I64 DefineMatch(U8 *src,U8 *lst_name,I64 flags=0,I64 *_ambiguity_overkill=NULL);
#help_index "Memory"
#help_file "::/SparrowOS/Doc/Mem"
public _extern _MEMCMP I64 MemCmp(U8 *ptr1,U8 *ptr2,I64 cnt);
public extern I64 MemPageSize(U8 *a)
public extern Bool MemPagePresentMark(U8 *a,Bool val);
public extern Bool MemLowPagesProtect(Bool val);
public extern U8 *MemBlks2MegAlloc(I64 *_pages2Meg,CBlkPool *bp=NULL);
public extern U8 *MemBlksUncachedAlloc(I64 *_pages2Meg,CBlkPool *bp=NULL);
public extern U8 *MemBlksWriteThroughAlloc(I64 *_pages2Meg,CBlkPool *bp=NULL);
public extern U0 MemBlks2MegFree(CMemBlk *m,I64 pages2Meg,CBlkPool *bp=NULL);
public extern U8 *MemBlksNonTaskAlloc(I64 *_pages512,CBlkPool *bp=NULL);
public extern I64 *MemPtAtPageTableEntry(U8 *a);
public extern U0 MemBlksNonTaskFree(CMemBlk *m,I64 pages512,CBlkPool *bp=NULL);
public _extern _MALLOC U8 *MAlloc(I64 size,CTask *mem_task=NULL);
public _extern _FREE U0 Free(U8 *add);
public _extern _MSIZE I64 MSize(U8 *src); //size of heap object
public _extern _MSIZE2 I64 MSize2(U8 *src); //Internal size
public _extern _MHEAP_CTRL CHeapCtrl *MHeapCtrl(U8 *src);
public extern U8 *CAlloc(I64 size,CTask *mem_task=NULL);
public extern U8 *MAllocIdentical(U8 *src,CTask *mem_task=NULL);
public extern U8 *MAllocAligned(I64 size,I64 alignment,CTask *mem_task=NULL,I64 misalignment=0);
public extern U8 *CAllocAligned(I64 size,I64 alignment,CTask *mem_task=NULL,I64 misalignment=0);
public extern U0 LinkedListDel(U8 **_list);
public extern U8 *LinkedListCopy(U8 **_list,CTask *mem_task=NULL);
public extern I64 LinkedListCnt(U8 **_list);
public extern I64 LinkedListSize(U8 **_list);
public extern I64 Scale2Mem(I64 min,I64 max,I64 limit=2*1024*1024*1024);
#help_index "Memory;Circular Queue"
public extern U0 QueDel(CQue *root,Bool querem=FALSE);
public extern CQue *QueCopy(CQue *root,CTask *mem_task=NULL);
public extern I64 QueCnt(CQue *root);
public extern I64 QueSize(CQue *root);
#help_index "Memory/Heap Ctrl"
public extern U0 BlkPoolAdd(CBlkPool *bp,CMemBlk *m,I64 pages512);
public extern U0 BlkPoolInit(CBlkPool *bp,I64 pages512);
extern CHeapCtrl *TaskHeapCtrlNew(CTask *task,CBlkPool *bp);
extern U0 TaskHeapCtrlDel(CHeapCtrl *hc);
public extern CHeapCtrl *HeapCtrlIndependentInit(CBlkPool *bp,I64 pages512);
#help_index "Memory/Adam Heap"
public extern U8 *AMAlloc(I64 size);
public extern U8 *AMAllocIdentical(U8 *src);
public extern U8 *ACAlloc(I64 size);
#help_index "Char/Operations;Memory"
public extern U8 *StrNew(U8 *buf,CTask *mem_task=NULL);
#help_index "Char/Operations;Memory/Adam Heap"
public extern U8 *AStrNew(U8 *buf);
#help_index "Device"
public extern U8 *Mem32DevAlloc(I64 size,I64 alignment);
public extern U8 *Mem64DevAlloc(I64 *_pages2Meg);
public extern U0 Mem32DevFree(U8 *base);
public extern U0 Mem64DevFree(U8 *base,I64 pages2Meg);
public extern CHeapCtrl *sys_uncached_heap;
#help_index "Task"
public extern U0 Exit();
public extern U0 Kill(CTask *task,Bool wait=TRUE);
public extern Bool Suspend(CTask *task=NULL,Bool state=TRUE);
public extern Bool IsSuspended(CTask *task=NULL);
public extern Bool TaskValidate(CTask *task);
public extern CTask *Spawn(U0 (*fp_add)(U8 *data),U8 *data=NULL,
U8 *task_name=NULL,
CTask *parent=NULL, //NULL means adam
I64 stk_size=0,I64 flags=SPAWNF_ADD_TO_QUE);
public extern U0 TaskPause(CTask *task,Bool state);
public extern U0 TaskQueIns(CTask *task,CTask *pred=NULL);
public extern U0 TaskQueRem(CTask *task);
public extern U0 TaskWait(CTask *task=NULL);
public extern U0 TaskInitExt();
public extern U0 UserCmdLine();
public extern U0 WinDerivedValsUpdate(CTask *task=NULL);
public extern U0 TaskDerivedValsUpdate(CTask *task=NULL,Bool update_z_buf=TRUE);
extern U0 (*fp_update_ctrls)(CTask *task);
public extern CTask *SpawnUser(U8 *fmt=NULL,...);
extern U0 TaskFinishOff(CTask *task);
public extern U0 OverRideSingleUserSwap();
#help_index "Task/Requests"
public extern U0 TaskRstAwaitingMsg(CTask *task=NULL);
public extern CTaskCmd *
TaskRqstQue(CTask *servant,CTask *master,
U8 *data,I64 flags);
public extern I64 ServantCmdsHandler(CTask *task=NULL);
public extern I64 ServantUser(U8 *fmt,...);
extern U0 ServantUserCmdLine();
public extern Bool GetRqstResult(CTaskCmd *rqst=NULL,I64 *_result=NULL);
public extern U0 ServantTaskCont();
public extern I64 Adam(U8 *fmt,...);
public extern U0 AdamLogExcept(I64 argc,I64 *argv);
public extern U0 AdamLog(U8 *fmt,...);
public extern U0 AdamErr(U8 *fmt,...);
#help_index "Task/Text Input"
public extern CTaskCmd *
TextInputQue(CTask *servant,CTask *master,
U8 *data,I64 flags);
#help_index "Task/Text Input;Messages"
public extern CTaskCmd *QueMsg(CTask *servant,CTask *master,
I64 msg_code,I64 p1,I64 p2,I64 flags);
public extern U0 PostMsg(CTask *task,I64 msg_code,I64 p1,I64 p2,I64 flags=0);
public extern U0 SendMsg(CTask *task,I64 msg_code,I64 p1,I64 p2,I64 flags=0);
public extern U0 Msg(I64 msg_code,I64 p1,I64 p2,I64 flags=0);
#help_index "Exceptions"
//Exceptions are thrown through the following funcation call.
//by convention, the first arg should be a type code.
public extern U0 PutExcept();
public extern U0 throw(...);
public extern U0 throw_no_log(...);
public extern I64 ExceptDepth(CTask *task=NULL);
//The following are used internally and should not be called directly
extern U0 SysTry(U8 *start_label,U8 *skip_label);
extern U0 SysUntry();
public extern U0 ThrowBreak(CTask *task=NULL);
public extern Bool BreakLock(CTask *task=NULL);
public extern Bool BreakUnlock(CTask *task=NULL);
#help_index "Compression/Piece by Piece"
public extern U0 ArcCompressBuf(CArcCtrl *c);
public extern U0 ArcFinishCompression(CArcCtrl *c);
public extern U0 ArcExpandBuf(CArcCtrl *c);
public extern CArcCtrl *ArcCtrlNew(Bool expand,Bool text_only);
public extern U0 ArcCtrlDel(CArcCtrl *c);
#help_index "Compression"
public extern CArcCompress *
CompressBuf(U8 *src,I64 size,I64 flags=0,CTask *mem_task=NULL);
public extern U8 *ExpandBuf(CArcCompress *r,CTask *mem_task=NULL);
//This is just an XOR checksum.
extern I64 ArcXSum(U32 *buf,I64 size);
#help_index "AutoFile"
#help_file "::/SparrowOS/Doc/AutoFile"
#help_index "Task/Text Input;AutoFile"
public extern U0 Auto(U8 *fmt,...);
public extern U0 AutoStr(U8 *fmt,...);
public extern U0 AutoFile(U8 *filename);
public extern U0 XTalk(CTask *task,U8 *fmt,...);
public extern U0 XTalkWait(CTask *task,U8 *fmt,...);
public extern U0 XTalkStr(CTask *task,U8 *fmt,...);
public extern U0 XTalkStrWait(CTask *task,U8 *fmt,...);
#help_index "Misc/Progress Bars"
public extern U0 ProgressBarsRst();
#help_index "Math"
public extern U16 RandU16(); //With timestamp
public extern U32 RandU32();
public extern U64 RandU64();
public extern I16 RandI16();
public extern I32 RandI32();
public extern I64 RandI64();
public extern F64 Rand();
public extern U16 Rand2U16(); //Without timestamp
public extern U32 Rand2U32();
public extern U64 Rand2U64();
public extern I16 Rand2I16();
public extern I32 Rand2I32();
public extern I64 Rand2I64();
public extern F64 Rand2();
public extern U0 Randomize(I64 seed=0);
public extern U64 FloorU64(U64 num,U64 to);
public extern U64 CeilU64(U64 num,U64 to);
public extern I64 RoundI64(I64 num,I64 to);
public extern I64 FloorI64(I64 num,I64 to);
public extern I64 CeilI64(I64 num,I64 to);
#help_index "Misc"
public extern U0 QSortI64(I64 *base,I64 num, I64 (*fp_compare)(I64 e1,I64 e2));
public extern U0 QSort(U8 *base,I64 num, I64 width,I64 (*fp_compare)(U8 *e1,U8 *e2));
public extern U16 EndianU16(U16 d);
public extern U32 EndianU32(U32 d);
public extern U64 EndianU64(U64 d);
extern I64 sys_rnd_seed;
#help_index "Bit"
public extern I64 BCnt(I64 d);
public extern U8 *reverse_bits_table,*set_bits_table;
#help_index "Doc/Clipboard"
public extern CDoc *sys_clipboard_doc;
#help_index "Time/CDate"
public extern U16 mon_start_days1[12];
public extern U16 mon_start_days2[12];
public extern I64 YearStartDate(I64 year);
public extern CDate CDateStruct2CDate(CDateStruct *_ds);
public extern U0 CDate2CDateStruct(CDateStruct *_ds,CDate ltdt);
public extern I64 FirstDayOfMon(I64 i);
public extern I64 LastDayOfMon(I64 i);
public extern I64 FirstDayOfYear(I64 i);
public extern I64 LastDayOfYear(I64 i);
public extern I64 DayOfWeek(I64 i);
public extern CDate GetCurTimeCDate();
public extern U0 CDate2ISO1(CISO1Date *dst,CDate ltdt);
#help_index "File/System"
extern U8 sys_temp_filename[136];
extern I64 sys_dsk_reads,sys_dsk_writes;
#help_index "File/System/Cache"
extern CCacheBlk *sys_dsk_cache_base,*sys_dsk_cache_ctrl;
extern CCacheBlk **sys_dsk_cache_hash_table;
extern I64 sys_dsk_cache_size;
extern U0 DskCacheInit(I64 size_in_U8s);
public extern U0 DskCacheInvalidate(CPrt *p);
#help_index "File/System/BlkDev"
public extern I64 num_blkdevs;
public extern CBlkDev *sys_blkdevs;
#help_index "File/System/Partitions"
public extern CPrt *sys_prts,*dft_prt;
extern CPrt *drv_to_prt[32];
#help_index "File/System/Hardware"
extern I64 ATAProbe(I64 base0,I64 base1,I64 unit);
extern U0 BlkDevAdd(CBlkDev *bdev,Bool one_prt);
extern U0 ATAReadBlks(CBlkDev *bdev,U8 *buf, I64 blk, I64 cnt);
extern U0 ATAWriteBlks(CBlkDev *bdev,U8 *buf, I64 blk, I64 cnt);
#help_index "File/Cmd Line (Typically);Cmd Line (Typically)"
#help_file "::/SparrowOS/Doc/CmdLine"
public extern U0 ChgDsk(U8 drv_let=0);
public extern Bool Drv(U8 drv_let);
public extern Bool Cd(U8 *dirname,Bool make_dirs=FALSE);
public extern Bool MapDrv(U8 drv_let,CPrt *p);
public extern U0 Dir(U8 *wild="*",Bool full=FALSE);
public extern U0 Del(U8 *wild,Bool print_msg=TRUE);
public extern Bool MkDir(U8 *filename);
#help_index "Info;File/Cmd Line (Typically);Cmd Line (Typically);File/Install Related;Install"
public extern U0 PrtRep();
#help_index "File/Program Routines/Low Level"
extern CDirEntry *SysFilesFind(U8 *files_find_mask,I64 fuf_flags);
extern U0 SysDel(U8 *wild,Bool make_mask); //this is dangerous
extern Bool CopySingle(U8 *f1,U8 *f2); //Just one file
extern U0 CleanMAPBuf(CPrt *p);
extern U0 FAT32FreeClusters(CPrt *p,I64 c);
extern U0 NativeFSFreeClusters(CPrt *p,I64 c,I64 cnt);
public extern Bool BlkDevLock(CBlkDev *bdev);
public extern Bool PrtLock(CPrt *p);
public extern Bool BlkDevUnlock(CBlkDev *bdev,Bool rst=FALSE);
public extern Bool PrtUnlock(CPrt *p,Bool rst=FALSE);
public extern U0 BlkDevsRelease();
public extern U0 PrtsRelease();
public extern I64 ClusterNumNext(CPrt *p,I64 c,I64 cnt=1);
public extern I64 Cluster2Blk(CPrt *p,I64 c);
public extern I64 RClustersBlks(CPrt *p,U8 *buf,I64 c,I64 blks);
public extern I64 RClusters(CPrt *p,U8 *buf,I64 c,I64 cnt);
public extern I64 WClustersBlks(CPrt *p,U8 *buf,I64 c,I64 blks);
public extern I64 WClusters(CPrt *p,U8 *buf,I64 c,I64 cnt);
public extern I64 ClusersAlloc(CPrt *p,I64 c=0,I64 cnt=1,Bool contiguous=FALSE);
public extern Bool RBlks(CPrt *p,U8 *buf, I64 blk, I64 cnt);
public extern Bool WBlks(CPrt *p,U8 *buf, I64 blk, I64 cnt);
public extern U0 WZeroBlks(CPrt *p,I64 blk,I64 cnt);
public extern U0 PrtChk(CPrt *p);
public extern U0 BlkDevChk(CBlkDev *bdev);
public extern U8 Prt2Drv(CPrt *p=NULL);
public extern CPrt *Drv2Prt(U8 drv_let=0);
public extern CBlkDev *Drv2BlkDev(U8 drv_let=0);
public extern CBlkDev *Drv2BlkDevFwded(U8 drv_let=0);
extern I64 Name2DirCluster(CPrt *p,U8 *dirname);
extern I64 Name2ParentDirCluster(CPrt *p,U8 *dirname);
#help_index "File/Program Routines/CFile"
public extern CFile *FOpen(U8 *filename,U8 *flags,I64 cnt=0);
public extern I64 FSize(CFile *f);
public extern U0 FSync(CFile *f);
public extern U0 FClose(CFile *f);
public extern Bool FRBlks(CFile *f,U8 *buf,I64 blk=FFB_NEXT_BLK,I64 cnt=1);
public extern Bool FWBlks(CFile *f,U8 *buf,I64 blk=FFB_NEXT_BLK,I64 cnt=1);
#help_index "File/CD DVD"
public extern U0 CDImageRead(U8 cd_drv_let,U8 *out_name);
public extern U0 CDImageWrite(U8 cd_drv_let,U8 *in_name=NULL,I64 media_type=MT_CD);
public extern U8 *sys_dft_iso_name;
#help_index "File/FileNames"
public extern Bool FilesFindMatch(U8 *files_find_mask,U8 *filename,I64 fuf_flags=0);
public extern Bool IsDotZ(U8 *filename);
public extern Bool IsDotC(U8 *filename);
public extern Bool IsTextFile(U8 *filename);
public extern Bool IsSrcFile(U8 *filename);
public extern U8 *FileExtDot(U8 *src);
public extern U8 *FileExtRem(U8 *src,U8 *dst=NULL);
public extern U0 PutFileLink(U8 *filename,I64 line=0,Bool plain_text=FALSE);
public extern U0 PutDirLink(U8 *dirname);
public extern U8 *CurDir(CTask *task=NULL,CTask *mem_task=NULL);
public extern U8 *DirNameAbs(U8 *dirname);
public extern U8 *DirFile(U8 *dirname,U8 *name=NULL,U8 *_extension=NULL);
public extern U8 *ZorNotZ(U8 *name);
public extern U8 *FileNameAbs(U8 *filename);
public extern Bool FileNameChk(U8 *filename);
public extern U8 *ChgExt(U8 *filename,U8 *extension);
public extern U8 *DftExt(U8 *filename,U8 *extension);
public extern Bool IsDir(U8 *dir_name);
public extern Bool IsDrvWritable(U8 drv_let=0);
extern CDirEntry *CdDir(CDirEntry *tempm,U8 *abs_name);
#help_index "File/Program Routines/Utils"
public extern U0 GetFFlags(U8 *f,U8 *list,U8 *st);
public extern U8 *SPrintFFlags(U8 *dst,U8 *list,I64 flags);
public extern U0 FileAccessDel(CFileAccess *fa);
public extern CFileAccess *FileAccessNew(U8 *mask,Bool make_mask=FALSE,Bool make_dirs=FALSE);
extern I64 FileAttr(U8 *name,I64 old_attr=0);
public extern U0 CDirEntryDel(CDirEntry *tempm);
public extern U0 CDirEntryDel2(CDirEntry *tempm);
public extern U0 CDirListDel(CDirEntry *tempm);
public extern U0 CDirListDel2(CDirEntry *tempm);
public extern Bool CDirNew(CPrt *p,U8 *cur_dir,CDirEntry *tempm,Bool free_old_chain=TRUE);
#help_index "File/Program Routines"
public extern CDirEntry *FilesFind(U8 *files_find_mask,I64 fuf_flags=0);
public extern I64 FileSize(U8 *filename);
public extern I64 FileSizeExpanded(U8 *filename);
public extern Bool FileFind(U8 *filename,CDirEntry *de=NULL,
Bool dir_only=FALSE,Bool file_only=FALSE,Bool scan_parents=FALSE);
public extern U8 *FileRead(U8 *filename,I64 *_size=NULL,I64 *_attr=NULL,Bool raw=FALSE);
public extern U8 *TextFileRead(U8 *filename,I64 *_attr=NULL);
public extern I64 FileWrite(U8 *filename,U8 *fbuf,
I64 size,CDate ltdt=0,I64 attr=0,Bool raw=FALSE);
public extern U0 TextFileWrite(U8 *filename,U8 *st,I64 attr=0);
#help_index "Install;File/Install Related;File/Cmd Line (Typically);Cmd Line (Typically);"
public extern U0 Mount(Bool repartition=FALSE);
#help_index "Install;File/Install Related"
extern CATARep *ATARepFind(CATARep *root,I64 num);
public extern Bool DrvEnable(U8 drv_let,Bool val);
public extern U0 Fmt(U8 drv_let,Bool quick=TRUE,Bool confirm=TRUE,I64 type=PT_FAT32);
extern U0 DrvDftSelect();
public extern U8 dft_drv;
extern Bool boot_drv_pmt;
#help_index "Hash"
#help_file "::/SparrowOS/Doc/Hash"
public _extern _HASH_STR I64 HashStr(U8 *st);
public _extern _HASH_FIND CHash *
HashFind(U8 *st,CHashTable *table,I64 mask,I64 instance=1);
public _extern _HASH_SINGLE_TABLE_FIND CHash *
HashSingleTableFind(U8 *st,CHashTable *table,I64 mask,I64 instance=1);
public _extern _HASH_BUCKET_FIND CHash **
HashBucketFind(U8 *st,CHashTable *table);
public _extern _HASH_ADD U0 HashAdd(CHash *temph,CHashTable *table);
public _extern _HASH_ADD_AFTER U0 HashAddAfter(CHash *temph,CHash *pred,CHashTable *table);
public _extern _HASH_REPLACE U0 HashReplace(CHash *temph,CHashTable *table,
I64 instance=1);//instance must match temph's
public _extern _HASH_REM_DEL Bool HashRemDel(CHash *temph,CHashTable *table,
I64 instance=1);//instance must match temph's
public _extern _EXT_FIND U8 *ExtFind(U8 *st,I64 instance=1);
public extern CHashGeneric *HashGenericAdd(U8 *name,I64 type,I64 u0=0,I64 u8=0,I64 u16=0,CTask *task=NULL);
public extern I64 HashTypeNum(CHash *temph);
public extern CHashTable *HashTableNew(I64 size,CTask *mem_task=NULL);
public extern U0 HashDel(CHashSrcSym *temph);
public extern U0 HashTableDel(CHashTable *table);
extern U0 SysSymImportsResolve(U8 *sptr,I64 ld_flags=0);
#help_index "Hash/Named Frame"
#help_file "::/SparrowOS/Doc/NamedFrame"
public extern I64 NamedFramePtr(U8 *name,CTask *task=NULL);
public extern CHashGeneric *NamedFramePtrAdd(U8 *name,I64 u0,CTask *task=NULL);
public extern I64 NamedFramePtrSet(U8 *name,I64 u0,CTask *task=NULL);
public extern I64 NamedFramePtrDel(U8 *name,CTask *task=NULL);
#help_index "Compiler;Cmd Line (Typically)"
public extern U8 *Load(U8 *filename,I64 ld_flags=0,
CBinFile *bfh_addr=-1); //-1 means don't care what load addr.
extern I64 sys_num_installed_compilers;
#help_index "Compiler"
extern U0 (*fp_prs_stream_blk)(CLex *lx);
#help_index "Boot"
public extern U0 Reboot();
#help_index "MultiCore"
extern CMPCmdCtrl *mp_ctrl;
extern U8 mp_apic_ids[MP_MAX_PROCESSORS];
extern CMPCrash *mp_crash;
public extern U0 MPInt(U8 num,I64 cpu_num=1);
public extern U0 IntEOI(); //signal end of interrupt
public extern U0 MPIntAll(U8 num);
public extern U0 MPWake(I64 target_cpu_mask);
extern U0 MPSethServerTask();
extern CMPCmd *MPQueJob(I64 (*fp_add)(U8 *data),U8 *data=NULL,
U8 *desc=NULL,
I64 flags=1<<MPCf_FREE_ON_COMPLETE,
Bool spawn=FALSE,I64 target_cpu_mask=ALL_MASK);
public extern CMPCmd *MPJob(I64 (*fp_add)(U8 *data),U8 *data=NULL,
I64 target_cpu=1,I64 flags=1<<MPCf_FREE_ON_COMPLETE);
public extern I64 MPJobResult(CMPCmd *tempm);
public extern CTask *MPSpawn(U0 (*fp_add)(U8 *data),U8 *data=NULL,U8 *name=NULL,I64 target_cpu=1);
public extern U0 MPNMInt();
public extern U0 MPStart();
#help_index "MultiCore;Boot"
public extern U0 MPHalt();
#help_index "Math"
public extern F64 Limit(F64 p,F64 lo,F64 hi);
public extern F64 Min(F64 n1,F64 n2);
public extern F64 Max(F64 n1,F64 n2);
public extern F64 Pow10I64(I64 i);
#help_index "PCI"
public extern U8 PCIReadU8(I64 bus,I64 dev,I64 fun,I64 rg);
public extern U16 PCIReadU16(I64 bus,I64 dev,I64 fun,I64 rg);
public extern U32 PCIReadU32(I64 bus,I64 dev,I64 fun,I64 rg);
public extern U0 PCIWriteU8(I64 bus,I64 dev,I64 fun,I64 rg,I64 val);
public extern U0 PCIWriteU16(I64 bus,I64 dev,I64 fun,I64 rg,I64 val);
public extern U0 PCIWriteU32(I64 bus,I64 dev,I64 fun,I64 rg,I64 val);
public extern I64 PCIClassFind(I64 class_code,I64 n);
//These are far call routines in the BIOS
public _extern SYS_BIOS32_SERVICE_DIR U32 sys_BIOS32_service_dir;
public _extern SYS_PCI_SERVICES U32 sys_pci_services;
#help_index "PCI;Call"
public _extern C32_EAX U32 c32_eax;
public _extern C32_EBX U32 c32_ebx;
public _extern C32_ECX U32 c32_ecx;
public _extern C32_EDX U32 c32_edx;
public _extern C32_ESI U32 c32_esi;
public _extern C32_EDI U32 c32_edi;
//Not reentrant
public _extern _FAR_CALL32 Bool FarCall32(U0 (*fp_add)());
#help_index "Call"
//fp_add can have any fixed number of arguments.
public argpop extern I64 CallStkGrow(I64 stk_size_threshold,I64 stk_size,/*argpop*/I64 (*fp_add)(...),...);
#help_index "Fifo"
public extern CFifoU8 *FifoU8New(I64 size,CTask *mem_task=NULL);
public extern U0 FifoU8Del(CFifoU8 *f);
public extern Bool FifoU8Ins(CFifoU8 *f,U8 b);
public extern Bool FifoU8Rem(CFifoU8 *f,U8 *_b);
public extern Bool FifoU8Peek(CFifoU8 *f,U8 *_b);
public extern U0 FifoU8Flush(CFifoU8 *f);
public extern I64 FifoU8Cnt(CFifoU8 *f);
public extern CFifoI64 *FifoI64New(I64 size,CTask *mem_task=NULL);
public extern U0 FifoI64Del(CFifoI64 *f);
public extern Bool FifoI64Ins(CFifoI64 *f,I64 q);
public extern Bool FifoI64Rem(CFifoI64 *f,I64 *_q);
public extern Bool FifoI64Peek(CFifoI64 *f,I64 *_q);
public extern U0 FifoI64Flush(CFifoI64 *f);
public extern I64 FifoI64Cnt(CFifoI64 *f);
#help_index "Char/Operations"
public _extern _STRCMP I64 StrCmp(U8 *st1,U8 *st2);
public _extern _STRICMP I64 StrICmp(U8 *st1,U8 *st2);
public _extern _STRNCMP I64 StrNCmp(U8 *st1,U8 *st2,I64 n);
public _extern _STRNICMP I64 StrNICmp(U8 *st1,U8 *st2,I64 n);
public _extern _STRSTR U8 *StrStr(U8 *st,U8 *pattern);
public _extern _STRISTR U8 *StrIStr(U8 *st,U8 *pattern);
public _extern _STRCPY U0 StrCpy(U8 *dest,U8 *src);
public _extern _STRCAT U0 StrCat(U8 *dest,U8 *src);
#help_index "Char/Input"
public extern I64 sys_key_cnt;
public extern U0 SetTypeMatic(U8 delay);
extern U0 KbdInit();
extern I64 KbdQueMsgs();
extern U0 KbdMouseVarsInit();
extern Bool MouseDriverInstall();
extern U0 KbdMouseHandler(Bool poll_kbd,Bool poll_mouse);
public extern U32 key_down_bitmap[8],key_down_bitmap2[8];
#help_index "Char/BitMaps"
public extern U32 alpha_bitmap[16];
public extern U32 alpha_numeric_bitmap[16];
public extern U32 alpha_numeric_no_at_bitmap[16];
public extern U32 word_bitmap[16];
public extern U32 dec_numeric_bitmap[16];
public extern U32 hex_numeric_bitmap[16];
public extern U32 white_space_bitmap[16];
public extern U32 non_eol_white_space_bitmap[16];
public extern U32 zero_cr_nl_cursor_bitmap[16];
public extern U32 zero_tab_ff_cr_nl_cursor_bitmap[16];
public extern U32 zero_tab_ff_cr_nl_cursor_dollar_bitmap[16];
public extern U32 getkey_chars_bitmap[16];
public extern U32 printable_chars_bitmap[16];
public extern U32 displayable_chars_bitmap[16];
public extern U32 safe_dollar_chars_bitmap[16];
public extern U32 filename_chars_bitmap[16];
public extern U32 non_eol_chars_bitmap[16];
#help_index "Char/Conversion"
public extern I64 A2ScanCode(I64 ch,I64 sc_flags=0);
public extern U8 ScanCode2A(I64 sc);
public extern U8 *A2KeyName(I64 ch,Bool include_ctrl=TRUE);
public extern U8 *ScanCode2KeyName(I64 sc);
#help_index "Input Pointer/Mouse"
public extern F64 mxx_scale,myy_scale,mzz_scale;
//These are the coordinates before
//they get scaled.
public extern I64 mxx_prescale,myy_prescale,mzz_prescale;
public extern I64 mxx,myy,mzz;
public extern F64 mouse_speed;
extern I64 old_mxx,old_myy,old_mzz;
public extern Bool mouse_buttons[5];
extern Bool mouse_installed;
extern I64 mouse_install_attempts,
mouse_last_evt_time;
extern Bool mouse_has_wheel;
extern Bool mouse_has_ext_buttons;
extern Bool mouse_evt;
extern Bool mouse_install_attempt_in_progress;
extern CFifoI64 *scan_code_fifo;
extern I64 sys_last_down_scan_code;
extern Bool kbdmouse_rst;
extern Bool mouse_irqs_working;
#help_index "Input Pointer"
#help_file "::/SparrowOS/Doc/InputPointer"
public extern I64 ipx,ipy,ipz,ip_throttle;
public extern I64 ipx_offset,ipy_offset,ipz_offset;
public extern F64 ipx_scale,ipy_scale,ipz_scale;
public extern F64 ip_speed;
public extern I64 ip_dev;
public extern I64 iptx,ipty;
public extern Bool ip_lb,ip_cb,ip_rb;
extern Bool ip_lb_last,ip_cb_last,ip_rb_last;
public extern Bool ip_has_wheel;
extern F64 ip_last_move_time;
extern CSnap ip_snap_last;
public extern U0 SetIP(I64 x=MAX_I64,I64 y=MAX_I64,I64 z=MAX_I64,I64 l=MAX_I64,I64 r=MAX_I64,I64 c=MAX_I64);
#help_index "Input Pointer/Displayed Image"
public extern Bool ip_on; //Show or hide cursor
extern U0 IPVarsUpdate(I64 x,I64 y,I64 z,Bool l,Bool c,Bool r);
extern U0 IPVarsInit();
#help_index "Input Pointer/Snap"
public extern I64 ipx_presnap,ipy_presnap,ipz_presnap;
extern CSnap *SnapCur();
public extern U0 GetSnap(CSnap *s);
public extern U0 SetSnap(CSnap *s,I64 i=0,F64 d=0);
#help_index "Messages"
extern U0 InputFilterTask();
public extern I64 ScanMsg(I64 *_p1=NULL,I64 *_p2=NULL,I64 mask=~1,CTask *task=NULL);
public extern I64 FlushMsgs(CTask *task=NULL);
public extern I64 GetMsg(I64 *_p1=NULL,I64 *_p2=NULL,I64 mask=~1,CTask *task=NULL);
public extern I64 ScanChar();
#help_index "Misc;Messages"
public extern I64 sys_cur_scan_code;
#help_index "Doc/Task"
extern CDoc *(*fp_doc_cur)(CTask *task=NULL);
#help_index "Char/Conversion"
public extern F64 A2F64(U8 *src,U8 **_end_ptr=NULL);
#help_index "Time/CDate"
public extern U8 *date_fmt_map,*time_fmt_map;
public extern U0 DateTimeFmtMapsRst();
#help_index "Char/Conversion;Time/CDate"
public extern CDate A2CDate(U8 *src);
#help_index "Debugging;Hash"
public extern CHash *PSectFind(U8 *add,I64 *_offset);
extern CPSectCache *psect_cache;
extern I64 psect_cache_index;
#help_index "Debugging"
public extern U0 EdLite(U8 *filename);
public extern I64 SrcLineNum(U8 *add,I64 cnt=1);
public extern U8 *SrcFileName(U8 *add,I64 cnt=1,CTask *mem_task=NULL);
public extern U8 *SrcEdLink(U8 *add,I64 cnt=1,CTask *mem_task=NULL);
public extern Bool PutSrcLink(U8 *add,I64 cnt=1,U8 *buf=NULL);
public extern U0 EdAddSrc(U8 *add,I64 cnt=1,I64 ed_flags=0);
#help_index "Exceptions"
public extern U0 CatchAll();
#help_index "Task/Requests;Compiler"
public extern U0 UserTaskCont();
public extern I64 ExeCmdLine(CLex *lx);
#help_index "Training"
public extern U0 Help();
#help_index ""
+400
View File
@@ -0,0 +1,400 @@
asm {
USE32
SYS_BIOS32_SERVICE_DIR:: DU32 0;
SYS_PCI_SERVICES:: DU32 0;
SYS_FIND_BIOS32_SERVICE_DIR::
MOV ESI,0xE0000
MOV ECX,(0x100000-0xE0000)/4
@@05: CMP U32 [ESI],'_32_'
JNE @@20
PUSH ECX
XOR ECX,ECX
MOV CL,U8 9[ESI]
SHL ECX,4
@@10: MOV EDI,ESI
XOR EAX,EAX
XOR EDX,EDX
@@15: MOV DL,U8 [EDI]
ADD EAX,EDX
INC EDI
DEC ECX
JNZ @@15
POP ECX
OR AL,AL
JNZ @@20
MOV U32 [SYS_BIOS32_SERVICE_DIR],ESI
MOV ESI,U32 4[ESI]
MOV U32 [SYS_BIOS32_SERVICE_CALL],ESI
RET
@@20: ADD ESI,4
LOOP @@05
MOV U32 [SYS_BIOS32_SERVICE_DIR],0
RET
SYS_FIND_PCI_SERVICES::
MOV ESI,U32 [SYS_BIOS32_SERVICE_DIR]
OR ESI,ESI
JNZ @@05
MOV U32 [SYS_PCI_SERVICES],0
RET
@@05: MOV EAX,'$$PCI'
XOR EBX,EBX
DU8 0x9A; //CALL GDT_CS_SEL:BIOS32_SERVICE
SYS_BIOS32_SERVICE_CALL:: DU32 0;
DU16 GDT_CS_SEL;
OR AL,AL
JNZ @@05
LEA ESI,U32 [EBX+EDX]
MOV U32 [SYS_PCI_SERVICES],ESI
RET
@@05: MOV U32 [SYS_PCI_SERVICES],0
RET
USE64
C32_EAX:: DU32 0;
C32_EBX:: DU32 0;
C32_ECX:: DU32 0;
C32_EDX:: DU32 0;
C32_ESI:: DU32 0;
C32_EDI:: DU32 0;
C32_RSP:: DU64 0;
_FAR_CALL32::
//This calls a 32-bit mode routine.
//(We must switch from 64-bit mode to do it.)
//
//NON REENTRANT
//
ENTER 0
MOV RAX,U64 SF_ARG1[RBP]
OR RAX,RAX
JNZ @@05
LEAVE
RET1 8 //return FALSE
@@05: MOV U32 [C32_ADD],EAX
PUSH_REGS
PUSHFD
XOR RAX,RAX
PUSH U64 FS:CTask.addr[RAX]
PUSH U64 GS:CCPU.addr[RAX]
MOV U64 [C32_RSP],RSP
PUSH U32 GDT_ZERO_DS_SEL //STKSEG
PUSH U32 0x9C000 //STK
PUSH U32 0 //FLAGS--interrupts off
PUSH U32 GDT_CS_SEL
LEA RAX,[@@15]
PUSH RAX
IRET
USE32
@@15:
WBINVD
//disable paging
MOV_EAX_CR0
BTR EAX,31
MOV_CR0_EAX
MOV ECX,IA32_EFER
XOR EDX,EDX
XOR EAX,EAX
WRMSR
MOV AX,GDT_ZERO_DS_SEL
MOV FS,AX
MOV GS,AX
//SS already set
MOV EAX,U32 [C32_EAX]
MOV EBX,U32 [C32_EBX]
MOV ECX,U32 [C32_ECX]
MOV EDX,U32 [C32_EDX]
MOV ESI,U32 [C32_ESI]
MOV EDI,U32 [C32_EDI]
DU8 0x9A; //CALL GDT_CS_SEL:[C32_ADD]
C32_ADD:: DU32 0;
DU16 GDT_CS_SEL;
MOV U32 [C32_EAX],EAX
MOV U32 [C32_EBX],EBX
MOV U32 [C32_ECX],ECX
MOV U32 [C32_EDX],EDX
MOV U32 [C32_ESI],ESI
MOV U32 [C32_EDI],EDI
CALL INIT_EM64T
USE64
MOV AX,GDT_ZERO_DS_SEL
MOV DS,AX
MOV ES,AX
MOV SS,AX
MOV RSP,U64 [C32_RSP]
//GS ALREADY ON STK
CALL _SET_GS_BASE
POP RAX
CALL SET_FS_BASE
POPFD
POP_REGS
XOR RAX,RAX
MOV AL,TRUE
LEAVE
RET1 8
}
_extern C32_EAX U32 c32_eax;
_extern C32_EBX U32 c32_ebx;
_extern C32_ECX U32 c32_ecx;
_extern C32_EDX U32 c32_edx;
_extern C32_ESI U32 c32_esi;
_extern C32_EDI U32 c32_edi;
_extern SYS_PCI_SERVICES U32 sys_pci_services;
//Not reentrant--used to call BIOS32
//Takes like, 250uS.
_extern _FAR_CALL32 Bool FarCall32(U0 (*fp_add)());
U8 PCIReadU8(I64 bus,I64 dev,I64 fun,I64 rg)
{
I64 result;
PushFD;
Cli;
while (LBts(&sys_semas[SYS_SEMA_FAR_CALL32],0))
Yield;
c32_eax=0xB108;
c32_ebx=bus<<8+dev<<3+fun;
c32_edi=rg;
if (FarCall32(sys_pci_services))
result=c32_ecx.u8[0];
else
result=0xFF;
LBtr(&sys_semas[SYS_SEMA_FAR_CALL32],0);
PopFD;
return result;
}
U16 PCIReadU16(I64 bus,I64 dev,I64 fun,I64 rg)
{
I64 result;
PushFD;
Cli;
while (LBts(&sys_semas[SYS_SEMA_FAR_CALL32],0))
Yield;
c32_eax=0xB109;
c32_ebx=bus<<8+dev<<3+fun;
c32_edi=rg;
if (FarCall32(sys_pci_services))
result=c32_ecx.u16[0];
else
result=0xFFFF;
LBtr(&sys_semas[SYS_SEMA_FAR_CALL32],0);
PopFD;
return result;
}
U32 PCIReadU32(I64 bus,I64 dev,I64 fun,I64 rg)
{
I64 result;
PushFD;
Cli;
while (LBts(&sys_semas[SYS_SEMA_FAR_CALL32],0))
Yield;
c32_eax=0xB10A;
c32_ebx=bus<<8+dev<<3+fun;
c32_edi=rg;
if (FarCall32(sys_pci_services))
result=c32_ecx;
else
result=0xFFFFFFFF;
LBtr(&sys_semas[SYS_SEMA_FAR_CALL32],0);
PopFD;
return result;
}
U0 PCIWriteU8(I64 bus,I64 dev,I64 fun,I64 rg,I64 val)
{
PushFD;
Cli;
while (LBts(&sys_semas[SYS_SEMA_FAR_CALL32],0))
Yield;
c32_eax=0xB10B;
c32_ebx=bus<<8+dev<<3+fun;
c32_edi=rg;
c32_ecx=val;
FarCall32(sys_pci_services);
LBtr(&sys_semas[SYS_SEMA_FAR_CALL32],0);
PopFD;
}
U0 PCIWriteU16(I64 bus,I64 dev,I64 fun,I64 rg,I64 val)
{
PushFD;
Cli;
while (LBts(&sys_semas[SYS_SEMA_FAR_CALL32],0))
Yield;
c32_eax=0xB10C;
c32_ebx=bus<<8+dev<<3+fun;
c32_edi=rg;
c32_ecx=val;
FarCall32(sys_pci_services);
LBtr(&sys_semas[SYS_SEMA_FAR_CALL32],0);
PopFD;
}
U0 PCIWriteU32(I64 bus,I64 dev,I64 fun,I64 rg,I64 val)
{
PushFD;
Cli;
while (LBts(&sys_semas[SYS_SEMA_FAR_CALL32],0))
Yield;
c32_eax=0xB10D;
c32_ebx=bus<<8+dev<<3+fun;
c32_edi=rg;
c32_ecx=val;
FarCall32(sys_pci_services);
LBtr(&sys_semas[SYS_SEMA_FAR_CALL32],0);
PopFD;
}
I64 PCIClassFind(I64 class_code,I64 n)
{
//class_code is low three bytes
//n is index starting at zero
//Returns: -1 not found
// else bus,dev,fun.
I64 result;
PushFD;
Cli;
while (LBts(&sys_semas[SYS_SEMA_FAR_CALL32],0))
Yield;
c32_eax=0xB103;
c32_esi=n;
c32_ecx=class_code;
if (FarCall32(sys_pci_services) && !c32_eax.u8[1])
result=c32_ebx.u8[1]<<16+(c32_ebx&0xF8)<<5+c32_ebx&7;
else
result=-1;
LBtr(&sys_semas[SYS_SEMA_FAR_CALL32],0);
PopFD;
return result;
}
Bool BootCdProbe(CBlkDev *bdev)
{
COSMain *img=CAlloc(CD_BLK_SIZE);
I64 i;
Bool result=FALSE;
"Port: %04X,%04X Unit: %02X ",bdev->base0,bdev->base1,bdev->unit;
if (ATAProbe(bdev->base0,bdev->base1,bdev->unit)==BDT_ATAPI) {
//After preboot + BootCD.BIN.Z comes OSMain.BIN.C
//See $LK,"CDBOOT","FA:::/SparrowOS/Adam/Dsk/DskCDDVD.CPP.Z,CDBOOT"$, See $LK,"CD Boot Blk","FF:::/SparrowOS/Adam/Boot/BootCD.CPP.Z,BOOT_CODE_CDROM"$
" ATAPI";
if (ATAPIStartStop(bdev,TRUE,tS+5.0)) {
" Started";
for (i=0;i<2;i++) { //Retry
if (ATAPIReadBlks2(bdev,img,sys_boot_code.u16[1],1,FALSE,tS+7.0)) {
if (img->compile_time==sys_compile_time) {
" Found";
return TRUE;
} else
" Read";
} else
" NoRead";
}
}
}
" Nope\n";
Free(img);
return result;
}
Bool BootCdProbeAll(CBlkDev *bdev)
{
U32 d1,d2;
bdev->base1=0;
if (PCIReadU16(0,31,1,0)==0x8086) {
d1=PCIReadU32(0,31,1,0x10);
d2=PCIReadU32(0,31,1,0x14);
if (d1&1 && d2&1) {
if (bdev->base0=d1&-8) {
bdev->unit=0;
if (BootCdProbe(bdev))
return TRUE;
bdev->unit=1;
if (BootCdProbe(bdev))
return TRUE;
}
}
d1=PCIReadU32(0,31,1,0x18);
d2=PCIReadU32(0,31,1,0x1C);
if (d1&1 && d2&1) {
if (bdev->base0=d1&-8) {
bdev->unit=0;
if (BootCdProbe(bdev))
return TRUE;
bdev->unit=1;
if (BootCdProbe(bdev))
return TRUE;
}
}
}
if (PCIReadU16(0,31,2,0)==0x8086) {
d1=PCIReadU32(0,31,2,0x10);
d2=PCIReadU32(0,31,2,0x14);
if (d1&1 && d2&1) {
if (bdev->base0=d1&-8) {
bdev->unit=0;
if (BootCdProbe(bdev))
return TRUE;
bdev->unit=1;
if (BootCdProbe(bdev))
return TRUE;
}
}
d1=PCIReadU32(0,31,2,0x18);
d2=PCIReadU32(0,31,2,0x1C);
if (d1&1 && d2&1) {
if (bdev->base0=d1&-8) {
bdev->unit=0;
if (BootCdProbe(bdev))
return TRUE;
bdev->unit=1;
if (BootCdProbe(bdev))
return TRUE;
}
}
}
d1=0x1F0;
d2=0x3F6;
if (bdev->base0=d1&-8) {
bdev->unit=0;
if (BootCdProbe(bdev))
return TRUE;
bdev->unit=1;
if (BootCdProbe(bdev))
return TRUE;
}
d1=0x170;
d2=0x376;
if (bdev->base0=d1&-8) {
bdev->unit=0;
if (BootCdProbe(bdev))
return TRUE;
bdev->unit=1;
if (BootCdProbe(bdev))
return TRUE;
}
}
+30
View File
@@ -0,0 +1,30 @@
//See $LK,"MP_VECT_ADDR","FF:::/SparrowOS/OSMain/Adam1a.HPP.Z,MP_VECT_ADDR"$ for something
//else used in low RAM.
//See $LK,"::/SparrowOS/Doc/Mem.TXT.Z","FI:::/SparrowOS/Doc/Mem.TXT.Z"$.
//At least $LK,"DFT_CACHE_LINE_WIDTH","MN:DFT_CACHE_LINE_WIDTH"$ alignment.
#define BOOT_RAM_BASE 0x07C00
#define BOOT_RAM_LIMIT 0x80000
//9FC00 is EBDA BIOS area
#define VGA_GRAPHIC_MEM_BASE 0xA0000
#define VGA_TEXT_MEM_BASE 0xB8000
#define BLK_SIZE_BITS 9
#define BLK_SIZE (1<<BLK_SIZE_BITS)
#define CD_BLK_SIZE (4*BLK_SIZE)
#define CD_FILE_OFFSET 80
#define CD_BOOT_LOADER_SIZE CD_BLK_SIZE*1 //Max 4 CDBlks, I think
//These are the cfguration settings
//for a standard production CD-Image
#define PROD_CDROM_CFG "b1Scale2Mem(2048,0x40000)\nt3 \n\n\n\n\n"
#define SAFE_CDROM_CFG "b1Scale2Mem(2048,0x40000)\nt3 \n\n\n\nDontProbe\n\n"
#define BOOT_STK_SIZE BLK_SIZE
#define BOOT_CODE_RAM 1
#define BOOT_CODE_HARDDRV 2
#define BOOT_CODE_CDROM 3
+324
View File
@@ -0,0 +1,324 @@
//See $LK,"::/SparrowOS/Doc/Acknowledgements.TXT.Z","FI:::/SparrowOS/Doc/Acknowledgements.TXT.Z"$ (4).
//See $LK,"CArcCompress","MN:CArcCompress"$, $LK,"CArcEntry","MN:CArcEntry"$, and $LK,"CArcCtrl","MN:CArcCtrl"$
asm {
USE64
/****
U0 ArcGetEntry(CArcCtrl *c)
{
I64 i;
CArcEntry *temp,*temp1;
if (c->entry_used) {
i=c->free_index;
c->entry_used=FALSE;
c->cur_entry=c->next_entry;
c->cur_bits_in_use=c->next_bits_in_use;
if (c->next_bits_in_use<ARC_MAX_BITS) {
c->next_entry = &c->compress[i++];
if (i==c->free_limit) {
c->next_bits_in_use++;
c->free_limit=1<<c->next_bits_in_use;
}
} else {
do if (++i==c->free_limit)
i=c->min_table_entry;
while (c->hash[i]);
temp=&c->compress[i];
c->next_entry=temp;
temp1=&c->hash[temp->basecode];
while (temp1) {
if (temp1->next==temp) {
temp1->next=temp->next;
break;
} else
temp1=temp1->next;
}
}
c->free_index=i;
}
}
****/
_ARC_GET_ENTRY::
ENTER 0
PUSH RSI
PUSH RDI
MOV RSI,U64 SF_ARG1[RBP]
BTR U64 CArcCtrl.entry_used[RSI],0
JNC I32 @@30
MOV RDX,U64 CArcCtrl.free_index[RSI]
MOV RAX,U64 CArcCtrl.next_entry[RSI]
MOV U64 CArcCtrl.cur_entry[RSI],RAX
MOV RCX,U64 CArcCtrl.next_bits_in_use[RSI]
MOV U64 CArcCtrl.cur_bits_in_use[RSI],RCX
CMP RCX,ARC_MAX_BITS
JAE @@05
MOV RAX,RDX
SHL RAX,4
LEA RAX,U64 CArcCtrl.compress[RSI+RAX]
MOV U64 CArcCtrl.next_entry[RSI],RAX
INC RDX
CMP U64 CArcCtrl.free_limit[RSI],RDX
JNE @@25
INC RCX
MOV U64 CArcCtrl.next_bits_in_use[RSI],RCX
MOV RAX,1
SHL RAX,CL
MOV U64 CArcCtrl.free_limit[RSI],RAX
JMP @@25
@@05: INC RDX
CMP U64 CArcCtrl.free_limit[RSI],RDX
JNE @@10
MOV RDX,U64 CArcCtrl.min_table_entry[RSI]
@@10: MOV RAX,U64 CArcCtrl.hash[RSI+RDX*8]
OR RAX,RAX
JNZ @@05
MOV RDI,RDX
SHL RDI,4
LEA RDI,U64 CArcCtrl.compress[RSI+RDI]
MOV U32 CArcCtrl.next_entry[RSI],EDI
MOVZX RBX,U16 CArcEntry.basecode[RDI]
LEA RCX,U64 CArcCtrl.hash[RSI+RBX*8]
@@15: OR RCX,RCX
JZ @@25
MOV RAX,U64 CArcEntry.next[RCX]
CMP RDI,RAX
JNE @@20
MOV RAX,U64 CArcEntry.next[RDI]
MOV U64 CArcEntry.next[RCX],RAX
JMP @@25
@@20: MOV RCX,RAX
JMP @@15
@@25: MOV U64 CArcCtrl.free_index[RSI],RDX
@@30: POP RDI
POP RSI
LEAVE
RET1 8
}
_extern _ARC_GET_ENTRY
U0 ArcGetEntry(CArcCtrl *c);
I64 ArcXSum(U32 *src,I64 size)
{
I64 result=0;
size>>=2;
while (size--)
result^=*src++;
return result;
}
I64 ArcDetermineCompressionType(U8 *src,I64 size)
{
while (size--)
if (*src++&0x80)
return CT_8_BIT;
return CT_7_BIT;
}
U0 ArcCompressBuf(CArcCtrl *c)
//Use $LK,"CompressBuf","MN:CompressBuf"$() unless you are doing
//more than one buffer.
{
CArcEntry *temp,*temp1;
I64 basecode;
U8 *src_ptr,*src_limit,ch;
src_ptr=c->src_buf+c->src_pos;
src_limit=c->src_buf+c->src_size;
if (c->saved_basecode==MAX_U32)
basecode=*src_ptr++;
else
basecode=c->saved_basecode;
while (src_ptr<src_limit &&
c->dst_pos+c->cur_bits_in_use<=c->dst_size) {
ArcGetEntry(c);
arc_start_loop1:
if (src_ptr>=src_limit) goto arc_done_compression;
ch=*src_ptr++;
if (temp=c->hash[basecode])
do {
if (temp->ch==ch) {
basecode=temp-&c->compress[0];
goto arc_start_loop1;
}
} while (temp=temp->next);
BFieldOrU32(c->dst_buf,c->dst_pos,basecode);
c->dst_pos+=c->cur_bits_in_use;
c->entry_used=TRUE;
temp=c->cur_entry;
temp->basecode=basecode;
temp->ch=ch;
temp1=&c->hash[basecode];
temp->next=temp1->next;
temp1->next=temp;
basecode=ch;
}
arc_done_compression:
c->saved_basecode=basecode;
c->src_pos=src_ptr-c->src_buf;
}
U0 ArcFinishCompression(CArcCtrl *c)
{
if (c->dst_pos+c->cur_bits_in_use<=c->dst_size) {
BFieldOrU32(c->dst_buf,c->dst_pos,c->saved_basecode);
c->dst_pos+=c->next_bits_in_use;
}
}
U0 ArcExpandBuf(CArcCtrl *c)
//Use $LK,"ExpandBuf","MN:ExpandBuf"$() unless you know what
//you're doing.
{
U8 *dst_ptr,*dst_limit;
I64 basecode,lastcode,code;
CArcEntry *temp,*temp1;
dst_ptr=c->dst_buf+c->dst_pos;
dst_limit=c->dst_buf+c->dst_size;
while (dst_ptr<dst_limit &&
c->stk_ptr!=c->stk_base)
*dst_ptr++ = * -- c->stk_ptr;
if (c->stk_ptr==c->stk_base && dst_ptr<dst_limit) {
if (c->saved_basecode==MAX_U32) {
lastcode=BFieldExtU32(c->src_buf,c->src_pos,
c->next_bits_in_use);
c->src_pos+=c->next_bits_in_use;
*dst_ptr++=lastcode;
ArcGetEntry(c);
c->last_ch=lastcode;
} else
lastcode=c->saved_basecode;
while (dst_ptr<dst_limit &&
c->src_pos+c->next_bits_in_use<=c->src_size) {
basecode=BFieldExtU32(c->src_buf,c->src_pos,
c->next_bits_in_use);
c->src_pos+=c->next_bits_in_use;
if (c->cur_entry==&c->compress[basecode]) {
*c->stk_ptr++=c->last_ch;
code=lastcode;
} else
code=basecode;
while (code>=c->min_table_entry) {
*c->stk_ptr++=c->compress[code].ch;
code=c->compress[code].basecode;
}
*c->stk_ptr++=code;
c->last_ch=code;
c->entry_used=TRUE;
temp=c->cur_entry;
temp->basecode=lastcode;
temp->ch=c->last_ch;
temp1=&c->hash[lastcode];
temp->next=temp1->next;
temp1->next=temp;
ArcGetEntry(c);
while (dst_ptr<dst_limit && c->stk_ptr!=c->stk_base)
*dst_ptr++ = * -- c->stk_ptr;
lastcode=basecode;
}
c->saved_basecode=lastcode;
}
c->dst_pos=dst_ptr-c->dst_buf;
}
CArcCtrl *ArcCtrlNew(Bool expand,Bool text_only)
{
CArcCtrl *c;
c=CAlloc(sizeof(CArcCtrl));
if (expand) {
c->stk_base=MAlloc(ARC_MAX_ENTRY+1);
c->stk_ptr=c->stk_base;
}
if (text_only)
c->min_bits=7;
else
c->min_bits=8;
c->min_table_entry=1<<c->min_bits;
c->free_index=c->min_table_entry;
c->next_bits_in_use=c->min_bits+1;
c->free_limit=1<<c->next_bits_in_use;
c->saved_basecode=MAX_U32;
c->entry_used=TRUE;
ArcGetEntry(c);
c->entry_used=TRUE;
return c;
}
U0 ArcCtrlDel(CArcCtrl *c)
{
Free(c->stk_base);
Free(c);
}
CArcCompress *CompressBuf(U8 *src,I64 size,
I64 flags=0,CTask *mem_task=NULL)
{
CArcCompress *result;
I64 size_out;
Bool text_only=ArcDetermineCompressionType(src,size)==CT_7_BIT;
CArcCtrl *c=ArcCtrlNew(FALSE,text_only);
c->src_size=size;
c->src_buf=src;
c->dst_size=(size+sizeof(CArcCompress))<<3;
c->dst_buf=CAlloc(c->dst_size>>3);
c->dst_pos=sizeof(CArcCompress)<<3;
ArcCompressBuf(c);
ArcFinishCompression(c);
if (c->src_pos==c->src_size) {
size_out=(c->dst_pos+7)>>3;
result=MAlloc(size_out,mem_task);
MemCpy(result,c->dst_buf,size_out);
result->compression_type=text_only ? CT_7_BIT:CT_8_BIT;
result->compressed_size=size_out;
} else {
result=MAlloc(size+sizeof(CArcCompress),mem_task);
MemCpy(&result->body,src,size);
result->compression_type=CT_NONE;
result->compressed_size=size+sizeof(CArcCompress);
}
result->expanded_size=size;
result->flags=flags;
Free(c->dst_buf);
ArcCtrlDel(c);
return result;
}
U8 *ExpandBuf(CArcCompress *r,CTask *mem_task=NULL)
{
CArcCtrl *c;
Bool text_only;
U8 *result=MAlloc(r->expanded_size+1,mem_task);
result[r->expanded_size]=0; //terminate
text_only= r->compression_type==CT_7_BIT;
if (r->compression_type==CT_NONE) {
MemCpy(result,&r->body,r->expanded_size);
goto expand_end;
}
c=ArcCtrlNew(TRUE,text_only);
c->src_size=r->compressed_size<<3;
c->src_pos=sizeof(CArcCompress)<<3;
c->src_buf=r;
c->dst_size=r->expanded_size;
c->dst_buf=result;
c->dst_pos=0;
ArcExpandBuf(c);
ArcCtrlDel(c);
expand_end:
return result;
}
+197
View File
@@ -0,0 +1,197 @@
//See $LK,"::/SparrowOS/Doc/TimeDate.TXT.Z","FI:::/SparrowOS/Doc/TimeDate.TXT.Z"$
U16 mon_start_days1[12]={
0,31,59,90,120,151,181,212,243,273,304,334};
U16 mon_start_days2[12]={
0,31,60,91,121,152,182,213,244,274,305,335};
I64 YearStartDate(I64 year)
{
I64 y1=year-1,yd4000=y1/4000,yd400=y1/400,yd100=y1/100,yd4=y1/4;
return year*365+yd4-yd100+yd400-yd4000;
}
CDate CDateStruct2CDate(CDateStruct *_ds)
{
CDate ltdt;
I64 i1,i2;
i1=YearStartDate(_ds->year);
i2=YearStartDate(_ds->year+1);
if (i2-i1==365)
i1+=mon_start_days1[_ds->mon-1];
else
i1+=mon_start_days2[_ds->mon-1];
ltdt.date=i1+_ds->day_of_mon-1;
ltdt.time=(_ds->sec10000+100*(_ds->sec100+100*(_ds->sec+60*(_ds->min+60*_ds->hour))))<<21/(15*15*3*625);
return ltdt;
}
I64 DayOfWeek(I64 i)
{
i+=CDATE_BASE_DAY_OF_WEEK;
if (i>=0)
return i % 7;
else
return 6-(6-i)%7;
}
U0 CDate2CDateStruct(CDateStruct *_ds,CDate ltdt)
{
I64 i,k,date=ltdt.date;
_ds->day_of_week=DayOfWeek(date);
_ds->year=(date+1)*100000/CDATE_YEAR_DAYS_INT;
i=YearStartDate(_ds->year);
while (i>date) {
_ds->year--;
i=YearStartDate(_ds->year);
}
date-=i;
if (YearStartDate(_ds->year+1)-i==365) {
k=0;
while (date>=mon_start_days1[k+1] && k<11)
k++;
date-=mon_start_days1[k];
} else {
k=0;
while (date>=mon_start_days2[k+1] && k<11)
k++;
date-=mon_start_days2[k];
}
_ds->mon=k+1;
_ds->day_of_mon=date+1;
k=(625*15*15*3*ltdt.time)>>21+1;
_ds->sec10000=ModU64(&k,100);
_ds->sec100=ModU64(&k,100);
_ds->sec=ModU64(&k,60);
_ds->min=ModU64(&k,60);
_ds->hour =k;
}
I64 FirstDayOfMon(I64 i)
{
CDateStruct ds;
CDate ltdt=0;
ltdt.date=i;
CDate2CDateStruct(&ds,ltdt);
ds.day_of_mon=1;
ltdt=CDateStruct2CDate(&ds);
return ltdt.date;
}
I64 LastDayOfMon(I64 i)
{
CDateStruct ds;
CDate ltdt=0;
ltdt.date=i;
CDate2CDateStruct(&ds,ltdt);
ds.mon++;
if (ds.mon==13) {
ds.mon=0;
ds.year++;
}
ds.day_of_mon=1;
ltdt=CDateStruct2CDate(&ds);
return ltdt.date-1;
}
I64 FirstDayOfYear(I64 i)
{
CDateStruct ds;
CDate ltdt=0;
ltdt.date=i;
CDate2CDateStruct(&ds,ltdt);
ds.day_of_mon=1;
ds.mon=1;
ltdt=CDateStruct2CDate(&ds);
return ltdt.date;
}
I64 LastDayOfYear(I64 i)
{
CDateStruct ds;
CDate ltdt=0;
ltdt.date=i;
CDate2CDateStruct(&ds,ltdt);
ds.day_of_mon=1;
ds.mon=1;
ds.year++;
ltdt=CDateStruct2CDate(&ds);
return ltdt.date-1;
}
I64 Bcd2Bin(I64 b)
{
I64 i,result=0;
for (i=0;i<16;i++) {
result=result*10+b>>60;
b<<=4;
}
return result;
}
U0 GetCurTimeCDateStruct(CDateStruct *_ds)
{
I64 i;
U8 *b=_ds;
Bool is_bcd;
MemSet(_ds,0,sizeof(CDateStruct));
PushFD;
Cli;
while (LBts(&sys_semas[SYS_SEMA_SYS_DATE],0))
Pause;
OutU8(0x70,0x0A);
do {
while (InU8(0x71) & 0x80)
Pause;
OutU8(0x70,0);
b[2]=InU8(0x71);
OutU8(0x70,2);
b[3]=InU8(0x71);
OutU8(0x70,4);
b[4]=InU8(0x71);
OutU8(0x70,6);
b[5]=InU8(0x71);
OutU8(0x70,7);
b[6]=InU8(0x71);
OutU8(0x70,8);
b[7]=InU8(0x71);
OutU8(0x70,9);
b[8]=InU8(0x71);
OutU8(0x70,0x0A);
} while (InU8(0x71) & 0x80);
OutU8(0x70,0x0B);
if (InU8(0x71) & 4)
is_bcd=FALSE;
else
is_bcd=TRUE;
LBtr(&sys_semas[SYS_SEMA_SYS_DATE],0);
PopFD;
if (is_bcd)
for (i=2;i<9;i++)
b[i]=Bcd2Bin(b[i]);
if (_ds->year>255) _ds->year=255;
_ds->year+=2000;
if (_ds->mon>12) _ds->mon=12;
if (_ds->day_of_mon>31) _ds->day_of_mon=31;
if (_ds->day_of_week>6) _ds->day_of_week=6;
if (_ds->hour>23) _ds->hour=23;
if (_ds->min>59) _ds->min=59;
if (_ds->sec>59) _ds->sec=59;
}
CDate GetCurTimeCDate()
{
CDateStruct ds;
GetCurTimeCDateStruct(&ds);
return CDateStruct2CDate(&ds)-local_time_offset;
}
+558
View File
@@ -0,0 +1,558 @@
Bool IsDbgTask()
{
CTask *task=Fs->parent_task;
if (TaskValidate(task) && task->dbg_task==Fs)
return TRUE;
else
return FALSE;
}
Bool ChkPtr(U8 *ptr)
{
if (sys_heap_base<=ptr<=MAPPED_MEM_SPACE) {
if (*MemPtAtPageTableEntry(ptr)&1)
return TRUE;
else
return FALSE;
} else if (ptr<sys_boot_base)
return FALSE;
else if (ptr<VGA_GRAPHIC_MEM_BASE)
return TRUE;
else
return FALSE;
}
Bool ChkOnStk(U8 *ptr,CTask *task=NULL)
{
Bool result=FALSE;
PushFD;
Cli;
if (task) {
if (&task->stk->stk_base<=ptr<=(&task->stk->stk_base)(U8 *)+task->stk->stk_size)
result=TRUE;
} else if (sys_heap_base<=ptr<=sys_heap_limit)
result=TRUE;
PopFD;
return result;
}
I64 UnusedStk(CTask *task=NULL)
{
I64 result;
if (!task) task=Fs;
PushFD;
Cli;
if (task==Fs)
result=GetStkPtr()(U8 *)-(&task->stk->stk_base)(U8 *);
else
result=task->rsp(U8 *)-(&task->stk->stk_base)(U8 *);
PopFD;
return result;
}
U8 *Caller(I64 num=1)
//Returns the addr of the fun
//which called this one, or the caller
//of the caller, etc.
{
U8 **rbp=GetBasePtr,**ptr;
while (num--) {
if (rbp>=*rbp)
return NULL;
rbp=*rbp;
if (!ChkOnStk(rbp,Fs))
return NULL;
}
ptr=rbp+1;
return *ptr;
}
U8 *TaskCaller(CTask *task=NULL,I64 num=0,Bool saved_context=FALSE)
{
U8 **ptr,**rbp,**rsp;
if (!task) task=Fs;
if (!saved_context && task==Fs)
return Caller(num+1);
if (!TaskValidate(task))
return NULL;
rbp=task->rbp;
rsp=task->rsp;
if (num) {
while (ChkOnStk(rbp,task)) {
ptr=rbp+1;
if (! --num)
return *ptr;
if (rbp>=*rbp)
break;
rbp=*rbp;
}
return NULL;
} else {
if (task->rip==SYS_IDLE_PT)
return *rsp;
else
return task->rip;
}
}
#define STK_REP_LEN 32
U0 StkRep(CTask *task=NULL)
//Reports whats on the stk
{
I64 i,j,add,
**rbp,**rsp,*my_rsp[STK_REP_LEN];
CHashTable *old_hash=Fs->hash_table;
if (!task) task=Fs;
if (!TaskValidate(task))
return;
PushFD;
Cli;
if (task==Fs) {
rbp=GetBasePtr;
rsp=rbp+3;
rbp=*rbp;
} else {
rsp=task->rsp;
rbp=task->rbp;
}
if (task->rip==SYS_IDLE_PT)
add=*rsp;
else
add=task->rip;
MemCpy(my_rsp,rsp,STK_REP_LEN*sizeof(U8 *));
PopFD;
Fs->hash_table=task->hash_table;
for (i=0;i<STK_REP_LEN;i++) {
"%08X [RSP+%04X]: %016X ",rsp+i,
i*sizeof(U8 *),my_rsp[i];
while (TRUE) {
if (!(&task->stk->stk_base<=rbp<(&task->stk->stk_base)(U8 *)+task->stk->stk_size))
break;
j=rbp-rsp;
if (j>=i)
break;
add=my_rsp[j+1];
if (rbp>=my_rsp[j])
break;
rbp=my_rsp[j];
}
if (my_rsp[i]==add)
"$$FG,RED$$";
"%P$$FG$$\n",my_rsp[i];
}
NewLine;
Fs->hash_table=old_hash;
}
U0 CallerRep(U8 **rbp=NULL,CTask *task=NULL)
//Prints a report of calling routines
{
I64 **ptr;
if (!task) task=Fs;
if (!rbp) rbp=GetBasePtr;
"CallerRep:\n";
while (ChkOnStk(rbp,task)) {
ptr=rbp+1;
"%08X:%08tX:%P\n",ptr,*ptr,*ptr;
if (rbp>=*rbp)
break;
rbp=*rbp;
}
}
U0 DbgStr(U8 *st,I64 mS=100)
//Shows a string using
//$LK,"Raw","MN:Raw"$ screen output for a fixed length
//of time.
{
Bool old_raw,old_input_filter;
PushFD;
Cli;
old_raw=Raw(ON);
old_input_filter=LBtr(&Fs->task_flags,TASKf_INPUT_FILTER_TASK);
"DbgStr(";
"" st;
')';
BusyWait(mS<<10);
PopFD;
LBEqu(&Fs->task_flags,TASKf_INPUT_FILTER_TASK,old_input_filter);
Raw(old_raw);
}
U0 DbgNum(I64 num,I64 mS=100)
//Shows a hex num using
//$LK,"Raw","MN:Raw"$ screen output for a fixed length
//of time.
{
Bool old_raw,old_input_filter;
PushFD;
Cli;
old_raw=Raw(ON);
old_input_filter=LBtr(&Fs->task_flags,TASKf_INPUT_FILTER_TASK);
"DbgNum(%016X)",num;
BusyWait(mS<<10);
PopFD;
LBEqu(&Fs->task_flags,TASKf_INPUT_FILTER_TASK,old_input_filter);
Raw(old_raw);
}
U0 DbgF(F64 d,I64 mS=100)
//Shows a floating-point val using
//$LK,"Raw","MN:Raw"$ screen output for a fixed length
//of time.
{
Bool old_raw,old_input_filter;
PushFD;
Cli;
old_raw=Raw(ON);
old_input_filter=LBtr(&Fs->task_flags,TASKf_INPUT_FILTER_TASK);
"DbgF(%15e)",d;
BusyWait(mS<<10);
PopFD;
LBEqu(&Fs->task_flags,TASKf_INPUT_FILTER_TASK,old_input_filter);
Raw(old_raw);
}
U0 DbgAdd(U8 *add,I64 mS=100)
//Shows an addr using $LK,"Raw","MN:Raw"$ screen
//output for a length of time.
{
Bool old_raw,old_input_filter;
PushFD;
Cli;
old_raw=Raw(ON);
old_input_filter=LBtr(&Fs->task_flags,TASKf_INPUT_FILTER_TASK);
"DbgAdd(%P)",add;
BusyWait(mS<<10);
PopFD;
LBEqu(&Fs->task_flags,TASKf_INPUT_FILTER_TASK,old_input_filter);
Raw(old_raw);
}
U0 DbgD(U8 *add,I64 cnt=0x80,I64 mS=100)
//Dumps a block of mem using $LK,"Raw","MN:Raw"$
//screen output for a fixed length
//of time.
{
Bool old_raw,old_input_filter;
PushFD;
Cli;
old_raw=Raw(ON);
old_input_filter=LBtr(&Fs->task_flags,TASKf_INPUT_FILTER_TASK);
D(add,cnt);
BusyWait(mS<<10);
PopFD;
LBEqu(&Fs->task_flags,TASKf_INPUT_FILTER_TASK,old_input_filter);
Raw(old_raw);
}
U0 DbgDm(U8 *add,I64 cnt=0x80,I64 mS=100)
//Dumps a block of mem using $LK,"Raw","MN:Raw"$
//screen output for a fixed length
//of time.
{
Bool old_raw,old_input_filter;
PushFD;
Cli;
old_raw=Raw(ON);
old_input_filter=LBtr(&Fs->task_flags,TASKf_INPUT_FILTER_TASK);
Dm(add,cnt);
BusyWait(mS<<10);
PopFD;
LBEqu(&Fs->task_flags,TASKf_INPUT_FILTER_TASK,old_input_filter);
Raw(old_raw);
}
U0 D(U8 *buf,I64 cnt=0x80,Bool show_offset=TRUE)
//Dump mem, showing offsets.
//See $LK,"DocD","MN:DocD"$() for a live dump.
{
I64 i,j,ch;
U8 *b=buf;
while (cnt) {
if (show_offset)
"%08X ",b-buf;
else
"%010X ",b;
j= cnt>16 ? 16:cnt;
for (i=0;i<j;i++)
"%02X ",b[i];
for (;i<16;i++)
" ";
for (i=0;i<j;i++) {
ch=b[i];
if (ch<CH_SHIFT_SPACE || ch==CH_BACKSPACE)
ch='.';
'' ch;
if (ch=='$$')
'' ch;
}
NewLine;
cnt-=j;
b+=j;
}
}
U0 Dm(U8 *buf,I64 cnt=0x80)
//Show mem addr, not offsets
{
D(buf,cnt,FALSE);
}
U0 Da(U8 **b,I64 cnt=0x10)
//Dump mem, showing symbolic addresses
{
while (cnt-->0) {
"%08X:%08X,%P\n",b,*b,*b;
b++;
}
}
I64 *TaskRegAdd(CTask *task,I64 reg_num)
{
switch (reg_num) {
case CREG_RAX: return &task->rax;
case CREG_RCX: return &task->rcx;
case CREG_RDX: return &task->rdx;
case CREG_RBX: return &task->rbx;
case CREG_RSP: return &task->rsp;
case CREG_RBP: return &task->rbp;
case CREG_RSI: return &task->rsi;
case CREG_RDI: return &task->rdi;
case 8 : return &task->r8;
case 9 : return &task->r9;
case 10: return &task->r10;
case 11: return &task->r11;
case 12: return &task->r12;
case 13: return &task->r13;
case 14: return &task->r14;
case 15: return &task->r15;
}
return NULL;
}
U0 Dr(CTask *task=NULL)
{//Dump registers
I64 i;
if (!task) task=Fs;
for (i=0;i<16;i++)
"%3Z:%016X\n",i,"ST_U64_REGS",*TaskRegAdd(task,i);
"RIP:%016X\n",task->rip;
}
U0 OverRideSingleUserSwap()
{
Bool old_single=SingleUser(OFF);
Yield;
SingleUser(old_single);
}
U0 DefineRegs() //A courtesy for dbgging
{
DefineLoad("RAX","Fs->rax");
DefineLoad("RBX","Fs->rbx");
DefineLoad("RCX","Fs->rcx");
DefineLoad("RDX","Fs->rdx");
DefineLoad("RSI","Fs->rsi");
DefineLoad("RDI","Fs->rdi");
DefineLoad("RBP","Fs->rbp");
DefineLoad("RSP","Fs->rsp");
DefineLoad("RIP","Fs->rip");
DefineLoad("R8" ,"Fs->r8");
DefineLoad("R9" ,"Fs->r9");
DefineLoad("R10","Fs->r10");
DefineLoad("R11","Fs->r11");
DefineLoad("R12","Fs->r12");
DefineLoad("R13","Fs->r13");
DefineLoad("R14","Fs->r14");
DefineLoad("R15","Fs->r15");
}
U8 *SysMGetS(I64)
{
U8 buf[512];
GetS(buf,512,FALSE);
return StrNew(buf);
}
U0 SysDbgExit()
{
if (IsInDbg) {
"Exit Dbg\n";
Btr(&Fs->last_lex->flags,Lf_PROMPT);
}
}
U0 Go1()
{
if (IsInDbg && ext[EXT_EXIT_DEBUGGER])
CallExtNum(EXT_EXIT_DEBUGGER);
}
U0 SysDbgEnter(Bool was_in_debugger)
{
Bool old_user_task,old_waiting_msg;
I64 i,old_dbg_mgets;
U8 buf[200];
CHashTable *tempht;
if (IsRaw) {
i=Fs->rip;
Ui(buf,&i,64);
PutS(buf);
} else
U(Fs->rip,1);
if (!was_in_debugger) {
old_waiting_msg=LBtr(&Fs->task_flags,TASKf_AWAITING_MSG);
old_user_task =LBts(&Fs->task_flags,TASKf_USER);
TaskInitExt;
sys_focus_task=Fs;
sys_cur_scan_code=0;
old_dbg_mgets=fp_mgets;
fp_mgets=&SysMGetS;
while (!mouse_install_attempts)
OverRideSingleUserSwap;
tempht=HashTableNew(STD_HASH_SIZE);
tempht->next=Fs->hash_table;
Fs->hash_table=tempht;
DefineRegs;
UserTaskCont;
Fs->hash_table=tempht->next;
HashTableDel(tempht);
fp_mgets=old_dbg_mgets;
LBEqu(&Fs->task_flags,TASKf_USER,old_user_task);
LBEqu(&Fs->task_flags,TASKf_AWAITING_MSG,old_waiting_msg);
}
}
U0 DbgHelp()
{
"\n"
"The cmd line is basically the same as normal. Here are some common\n"
"debugging commands.\n\n"
">EdLite(\"FileName\");\t\t//Edit file.\n"
">D(0x100000);\t\t\t//Dump page tables.\n"
">Dm(0x100000);\t\t\t//Dump page tables.\n"
">Dm(Fs,sizeof(CTask));\t\t//Dump current task record.\n"
">ClassRep(\"CTask\",Fs,1);\t//Dump current task record.\n"
">CallerRep;\t\t\t//Stack trace report.\n"
">Da(RSP);\t\t\t//Dump stk.\n"
">Dr;\t\t\t\t//Dump Registers.\n"
">1+2*3+&PutS;\t\t\t//Show calculation result.\n"
">*(0x70000)(I64 *)=0x123456789;\t//Assign value to 0x70000-0x70007.\n"
">RAX=0x1234;\t\t\t//Set RAX to 0x1234.\n"
">RIP=&SysThrowBreak;\t\t//Set RIP.\n"
">I64 i;\t\t\t\t//Declare variable.\n"
">i=RCX+RDX;\t\t\t//Assign to variable.\n"
">U(&PrintF+0x8);\t\t//Unassemble PrintF.\n"
">Uf(\"PutS\");\t\t\t//Unassembler function \"PutS\".\n"
">BptS(&Main+0x20);\t\t//Set break point.\n"
">BptR(&Main+0x20);\t\t//Reset (clear) break point.\n"
">BptsR;\t\t\t\t//Reset (clear) all break points.\n"
">Step;\t\t\t\t//Single step.\n"
">Go1;\t\t\t\t//Resume execution.\n"
">Go2;\t\t\t\t//Better resume execution.\n"
">Go3;\t\t\t\t//BptsR;VGAFlush;WinFocus;Go2;\n"
">Exit;\t\t\t\t//Exit (kill) task.\n\n"
"After resuming, <CTRL-ALT-T> changes focus task.\n"
"After resuming, <CTRL-ALT-F> flushes screen VGA cache.\n\n";
}
U0 Dbg(U8 *msg=NULL,I64 num=0,Bool fault=FALSE)
//Enters the debugger.
//This can be used as a kernel panic.
{
Bool was_in_dbg,was_single_user,was_raw;
I64 old_dc_flags=sys_raw_dc_flags;
PushFD;
Cli;
if (Gs->num && mp_crash) {
mp_cnt=1;
mp_crash->cpu_num=Gs->num;
mp_crash->task=Fs;
mp_crash->msg=msg;
mp_crash->msg_num=num;
MPInt(I_MP_CRASH,0);
SysHlt;
}
was_single_user=SingleUser(ON);
was_raw=Raw(ON);
was_in_dbg=InDbg(ON);
sys_raw_dc_flags|=RDCF_SHOW_DOLLAR|RDCF_SCROLL;
if (!fault && !was_in_dbg)
sys_dbg_focus_task=sys_focus_task;
"\n\tSparrowOS Debugger\n\n"
">Help;\t//For help.\n\n";
Beep(500,TRUE);
if (msg) {
"\n!!! %s",msg;
if (num)
"%016X",num;
" !!!\n\n";
}
CallerRep;
if (ext[EXT_DEBUGGER])
CallExtNum(EXT_DEBUGGER,was_in_dbg);
else {
"No Debugger\n";
SysHlt;
}
InDbg(was_in_dbg);
SingleUser(was_single_user);
Raw(was_raw);
sys_raw_dc_flags=old_dc_flags;
PopFD;
if (!fault && LBtr(&Fs->task_flags,TASKf_KILL_AFTER_DBG))
Exit;
}
U0 Fault2() //Called from $LK,"Fault2","FF:::/SparrowOS/OSMain/Interrupts.CPP.Z,Fault2"$
{
//$BK,1$Be careful not to swap-out and ruin the saved context$BK,0$
Bool was_raw,was_single_user;
I64 i,old_fault_num=sys_dbg_fault_num,
old_dc_flags=sys_raw_dc_flags;
U8 *old_fault_rip=sys_dbg_fault_rip;
if (Fs->fault_num==I_DIVIDE_BY_ZERO)
throw(EXCEPT_DIVIDE_BY_ZERO,Fs->rip);
was_single_user=SingleUser(ON);
if (!IsInDbg)
sys_dbg_focus_task=sys_focus_task;
sys_focus_task=NULL;
sys_dbg_fault_num=Fs->fault_num;
if (Fs->fault_num==I_BPT)
Fs->rip--;
sys_dbg_fault_rip=Fs->rip;
if (Fs->dbg_task)
CallExtNum(EXT_RESUME_DBG); //See $LK,"IDEResumeDbg","FF:::/SparrowOS/Adam/Doc/DocIDE.CPP.Z,IDEResumeDbg"$
else {
was_raw=Raw(ON);
sys_raw_dc_flags|=RDCF_SHOW_DOLLAR|RDCF_SCROLL;
"Task \"";
"" Fs->task_title;
"\"\n";
"Fault:0x%02X %Z\t\tErr Code:%08X\n",Fs->fault_num,Fs->fault_num,"ST_INT_NAMES",Fs->fault_err_code;
"RIP:%08X",Fs->rip; //Sometimes crashes on %P, so do this first
":%P RSP:%08X\n",Fs->rip,Fs->rsp;
if (Fs->fault_num==I_PAGE_FAULT) {
asm { MOV_RAX_CR2 }
i=GetRAX;
"Fault Addr:%08X:%P\n",i,i;
}
Dbg(NULL,0,TRUE);
Raw(was_raw);
sys_raw_dc_flags=old_dc_flags;
}
sys_dbg_fault_num=old_fault_num;
sys_dbg_fault_rip=old_fault_rip;
SingleUser(was_single_user);
if (LBtr(&Fs->task_flags,TASKf_KILL_AFTER_DBG))
Exit;
}
+129
View File
@@ -0,0 +1,129 @@
//These provide an option for different
//languages. Not all strings are done this way
//See $LK,"Char/Define","HI:Char/Define"$.
U0 LoadSysStrs()
{
DefineLoad("ST_UNDEFINED_EXTERN","Undefined Extern\n");
DefineLoad("ST_FILE_NOT_FOUND","File not found.\n");
DefineLoad("ST_INVALID_FILENAME","Invalid File Name.\n");
DefineLoad("ST_PRESS_A_KEY","$$BK,1$$PRESS A KEY$$BK,0$$\n");
DefineLoad("ST_EXIT_ALL_APPLICATIONS","$$FG,RED$$Exit all other applications.$$FG$$\n");
DefineLoad("ST_GOING_TO_PROBE_HARDWARE","\nWe're going to probe hardware.\n");
DefineLoad("ST_ARE_YOU_SURE","ARE YOU SURE ");
DefineLoad("ST_NOT_NATIVE","Not Native Partition\n");
DefineLoad("ST_NOT_FAT32","Not FAT32 Partition\n");
DefineLoad("ST_NOT_ISO9660","Not ISO9660 Partition\n");
DefineLoad("ST_NOT_ISO13346","Not ISO13346 Partition\n");
DefineLoad("ST_UNSUPPORTED_FILE_SYSTEM","File System Not Supported\n");
DefineLoad("ST_NOT_WRITABLE","Not Writable\n");
DefineLoad("ST_DELETE","Del ");
DefineLoad("ST_INVALID_DRV","Invalid Drive\n");
DefineLoad("ST_NO_MATCHING_ENTRIES","No matching entries\n");
DefineListLoad("ST_OFF_ON","Off\0On\0");
DefineListLoad("ST_HTT_TYPES","ExportSysSym\0ImportSysSym\0DefineStr\0GlbVar\0Class\0"
"IntType\0Funct\0Word\0DictWord\0KeyWord\0AsmKeyWord\0OpCode\0Reg\0"
"File\0Module\0HelpFile\0Frame Ptr\0Private\0"
"Public\0Export\0Import\0Lit\0Unres\0Local\0");
DefineListLoad("ST_DAYS_OF_WEEK","Sunday\0Monday\0Tuesday\0Wednesday\0"
"Thursday\0Friday\0Saturday\0");
DefineListLoad("ST_MONTHS","January\0February\0March\0April\0May\0"
"June\0July\0August\0September\0October\0November\0December\0");
DefineListLoad("ST_EXCEPT_TYPES","Local\0Break\0Out of Mem\0Divide by Zero\0"
"Floating\0Compiler\0Undefined Define\0"
"Undefined Extern\0File\0File Xsum\0"
"Partition error\0Blk Dev error\0"
"Graphics\0SPrintF\0GetF\0Bin Module\0"
"MultiCore\0");
DefineListLoad("ST_FILE_ATTRS","R\0H\0S\0V\0D\0A\0 \0 \0X\0Y\0T\0Z\0C\0F\0");
DefineListLoad("ST_FILE_UTIL_FLAGS","r\0d\0i\0l\0?\0a\0c\0R\0p\0m\0D\0F\0t\0s\0f\0lf\0lb\0");
DefineListLoad("ST_BLKDEV_TYPES","NULL\0RAM\0ATA\0ATAPI\0NonNative\0");
DefineListLoad("ST_PRT_TYPES","NULL\0NATIVE\0FAT32\0ISO9660\0ISO13490\0ISO13346\0NTFS\0UNKNOWN\0");
DefineLoad("ST_MOUNT_INTRO",
"\n\n\n$$BK,1$$$$FG,PURPLE$$Mount drives so they will "
"be present when you boot.$$FG$$$$BK,0$$\n");
DefineLoad("ST_MOUNT_BASE_LET",
"\n****** Mount Drives ******\n"
"The base drive letter is the letter\n"
"of the first partition. If adding\n"
"a hard drive, you should pick 'C'.\n"
"If more than one partition is present\n"
"they will be lettered in sequence.\n"
"\n"
"Base Drive Letter($$FG,PURPLE$$<ENTER>$$FG$$ to exit):");
DefineLoad("ST_MOUNT_DRV_TYPE",
"\t$$FG,PURPLE$$1$$FG$$=RAM\n\t$$FG,PURPLE$$2$$FG$$=ATA(Harddisk)\n"
"\t$$FG,PURPLE$$3$$FG$$=ATAPI(CD-ROM)\n"
"\t$$FG,PURPLE$$4$$FG$$=Non Native File (Run TSZ first)\n"
"Type:");
DefineLoad("ST_MOUNT_BLKS",
"Blks of 512 bytes:");
DefineLoad("ST_MOUNT_UNIT",
"\t$$FG,PURPLE$$0$$FG$$=Master\n\t$$FG,PURPLE$$1$$FG$$=Slave\nUnit:");
DefineLoad("ST_MOUNT_FMT_WHOLE_DRV",
"\nReformat WHOLE drive!");
DefineLoad("ST_MOUNT_BOOTED_CDROM",
"<ENTER> to use booted CD-ROM\n");
DefineLoad("ST_INCLUDE_0X",
"Include $$FG,PURPLE$$0x$$FG$$ prefix\n");
DefineLoad("ST_MOUNT_BASE0",
"Include $$FG,PURPLE$$0x$$FG$$ prefix.\n"
"I/O Port Base0:\n");
DefineLoad("ST_MOUNT_BASE0_HINT",
"Enter dev number or\n"
"port with $$FG,PURPLE$$0x$$FG$$ prefix.\n"
"I/O Port Base0:\n");
DefineLoad("ST_MOUNT_BASE1",
"I/O Port Base1:\n");
DefineLoad("ST_MOUNT_NON_NATIVE_LET",
"Non Native Drive Letter:");
DefineLoad("ST_MOUNT_NON_NATIVE_BLK",
"File blk num:");
DefineLoad("ST_CDROM_PORTS_PMT",
"\n\nTry again with different port numbers if\n"
"it hangs for more than 2 minutes.\n\n");
DefineLoad("ST_FAILED","\n\n$$BK,1$$$$FG,RED$$Operation Failed$$BK,0$$$$FG$$\n\n");
DefineListLoad("ST_COLORS","BLACK\0BLUE\0GREEN\0CYAN\0"
"RED\0PURPLE\0BROWN\0LTGRAY\0DKGRAY\0LTBLUE\0LTGREEN\0"
"LTSCYAN\0LTRED\0LTPURPLE\0YELLOW\0WHITE\0");
DefineListLoad("ST_INT_NAMES",
"Divide Error\0Debug\0NMI\0Breakpoint\0Overflow\0BOUND Range Exceeded\0Invalid Opcode\0No Math Coprocessor\0"
"Double Fault\0Coprocessor Segment Fault\0Invalid TASK\0Segment Not Present\0Stk Segment Fault\0General Protection\0Page Fault\0 \0"
"Math Fault\0Alignment Check\0Machine Check\0SIMD Exception\0 \0 \0 \0 \0"
" \0 \0 \0 \0 \0 \0 \0 \0"
" \0 \0 \0 \0 \0 \0 \0 \0"
" \0 \0 \0 \0 \0 \0 \0 \0"
"MP Crash\0Wake\0");
$AN,"Anchor for inserting OS Define","OS_DEFINE"$
}
U8 *Color2Text(U8 *buf,CColorROPU32 c)
{
if (0<=c.c0.color<16)
StrCpy(buf,DefineSub(c.c0.color,"ST_COLORS"));
else if (c.c0.color==COLOR_TRANSPARENT)
StrCpy(buf,"TRANSPARENT");
else
StrCpy(buf,"INVALID");
if (c&ROPF_DITHER) {
StrCat(buf,"/");
if (0<=c.c1.color<16)
StrCat(buf,DefineSub(c.c1.color,"ST_COLORS"));
else if (c.c1.color==COLOR_TRANSPARENT)
StrCat(buf,"TRANSPARENT");
else
StrCat(buf,"INVALID");
}
return buf;
}
+279
View File
@@ -0,0 +1,279 @@
U0 RawDrawChar(I64 ch)
{
/* This is for RAW output during boot
before the window mgr is running
and for the debugger.
See $LK,"GrUpdateForegroundOfText","MN:GrUpdateForegroundOfText"$ for
the normal screen text output routine.
See also $LK,"GrUpdateScreen","MN:GrUpdateScreen"$().
*/
Bool old_preempt=Preempt(OFF);
I64 i,row,col;
U8 *ptr,*ptr1,*ptr2;
if (!(sys_raw_dc_flags&RDCF_SHOW_DOLLAR)) {
if (ch=='$$') {
if (sys_raw_dc_flags&RDCF_IN_DOLLAR) {
sys_raw_dc_flags&=~RDCF_IN_DOLLAR;
if (!(sys_raw_dc_flags & RDCF_LAST_DOLLAR)) {
sys_raw_dc_flags&=~RDCF_LAST_DOLLAR;
Preempt(old_preempt);
return;
}
} else {
sys_raw_dc_flags|=RDCF_IN_DOLLAR|RDCF_LAST_DOLLAR;
Preempt(old_preempt);
return;
}
}
sys_raw_dc_flags&=~RDCF_LAST_DOLLAR;
if (sys_raw_dc_flags&RDCF_IN_DOLLAR) {
Preempt(old_preempt);
return;
}
}
if (ch==CH_TAB) {
RawDrawChar(CH_SPACE);
while (sys_raw_dc_col & 7)
RawDrawChar(CH_SPACE);
} else if (ch==CH_BACKSPACE) {
sys_raw_dc_col--;
RawDrawChar(CH_SPACE);
sys_raw_dc_col--;
} else if (ch==CH_NEW_LINE) {
RawDrawChar(CH_SPACE);
while (sys_raw_dc_col % text_cols)
RawDrawChar(CH_SPACE);
} else if (Bt(displayable_chars_bitmap,ch)) {
row=sys_raw_dc_col/text_cols%text_rows;
col=sys_raw_dc_col%text_cols;
if (text_mode) {
if (sys_raw_dc_flags&RDCF_SCROLL && sys_raw_dc_col && !row && !col) {
MemCpy(VGA_TEXT_MEM_BASE,VGA_TEXT_MEM_BASE+text_cols,
text_cols*(text_rows-1)*2);
MemSet(VGA_TEXT_MEM_BASE+text_cols*(text_rows-1)*2,0,text_cols*2);
sys_raw_dc_col-=text_cols;
row=text_rows-1;
}
ptr=VGA_TEXT_MEM_BASE+(row*text_cols+col)*2;
ptr[0]=ch;
ptr[1]=BLACK<<4+WHITE;
} else {
OutU8(VGA_SC_INDEX,VGA_MAP_MASK);
OutU8(VGA_SC_DATA,0x0F); //All planes -- WHITE
if (sys_raw_dc_flags&RDCF_SCROLL && sys_raw_dc_col && !row && !col) {
//Scroll cached image
MemCpy(sys_dc_screen_image,sys_dc_screen_image+gr_width*FONT_HEIGHT>>3,
gr_width*(gr_height-FONT_HEIGHT)>>3);
MemSet(sys_dc_screen_image+gr_width*(gr_height-FONT_HEIGHT)>>3,0,gr_width*FONT_HEIGHT>>3);
MemCpy(VGA_GRAPHIC_MEM_BASE,sys_dc_screen_image,gr_width*gr_height>>3);
sys_raw_dc_col-=text_cols;
row=text_rows-1;
}
PushFD;
Cli;
ptr=ptr1=col+row*gr_width;
ptr+=VGA_GRAPHIC_MEM_BASE;
ptr1+=sys_dc_screen_image; //Write to cached image as well
ptr2=&gr_font[ch.u8[0]*FONT_HEIGHT];
for (i=0;i<FONT_HEIGHT;i++) {
*ptr=*ptr1=reverse_bits_table[*ptr2++];
ptr+=gr_width>>3;
ptr1+=gr_width>>3;
}
PopFD;
}
sys_raw_dc_col++;
}
Preempt(old_preempt);
}
U0 VGAFlush()
{
LBts(&sys_semas[SYS_SEMA_FLUSH_VGA_IMAGE],0);
}
U0 WinDerivedValsUpdate(CTask *task=NULL)
{
if (!task) task=Fs;
//Assert: This is called with TASKLf_TASK_LOCK set
PushFD;
Cli;
task->win_width =task->win_right-task->win_left+1;
task->win_height=task->win_bottom-task->win_top+1;
//Inside the Border
task->win_pixel_left =FONT_WIDTH*task->win_left;
task->win_pixel_right =FONT_WIDTH*(task->win_right+1)-1;
task->win_pixel_width =task->win_pixel_right-task->win_pixel_left+1;
task->win_pixel_top =FONT_HEIGHT*task->win_top;
task->win_pixel_bottom=FONT_HEIGHT*(task->win_bottom+1)-1;
task->win_pixel_height=task->win_pixel_bottom-task->win_pixel_top+1;
//Outside the border
if (Bt(&task->display_flags,DISPLAYf_NO_BORDER)) {
task->win_border_pixel_left =task->win_pixel_left;
task->win_border_pixel_right =task->win_pixel_right;
task->win_border_pixel_top =task->win_pixel_top;
task->win_border_pixel_bottom=task->win_pixel_bottom;
} else {
task->win_border_pixel_left =task->win_pixel_left-FONT_WIDTH;
task->win_border_pixel_right =task->win_pixel_right+FONT_WIDTH;
task->win_border_pixel_top =task->win_pixel_top-FONT_HEIGHT;
task->win_border_pixel_bottom=task->win_pixel_bottom+FONT_HEIGHT;
}
PopFD;
}
Bool AKDRawDisplayPutKey(I64 ch,I64)
{
if (IsRaw) {
RawDrawChar(ch);
return TRUE;
} else
return FALSE;
}
Bool AKDRawDisplayPutS(U8 *st)
{
U8 ch;
if (IsRaw) {
while (ch=*st++)
RawDrawChar(ch);
return TRUE;
} else
return FALSE;
}
Bool AKDInputFilterPutKey(I64 ch,I64 scancode)
{
Bool old_preempt;
if (Bt(&Fs->task_flags,TASKf_INPUT_FILTER_TASK)) {
old_preempt=Preempt(OFF);
Msg(MSG_KEY_DOWN,ch,scancode);
Preempt(old_preempt);
return TRUE;
} else
return FALSE;
}
Bool AKDInputFilterPutS(U8 *st)
{
U8 ch;
Bool old_preempt;
if (Bt(&Fs->task_flags,TASKf_INPUT_FILTER_TASK)) {
old_preempt=Preempt(OFF);
while (ch=*st++)
Msg(MSG_KEY_DOWN,ch,0);
Preempt(old_preempt);
return TRUE;
} else
return FALSE;
}
U0 PutKey(I64 ch,I64 sc)
{ //See $LK,"PutKeyHandling","FA:::/SparrowOS/Doc/KeyBoard.TXT.Z,PutKeyHandling"$
CKeyDev *tempp=sys_put_key_root.next;
if (!Bt(&Fs->display_flags,DISPLAYf_SILENT)) {
if (sys_cur_scan_code & SCF_SCROLL) {
if (sys_focus_task==Fs) {
while (sys_cur_scan_code & SCF_SCROLL)
Yield;
}
}
while (tempp!=&sys_put_key_root) {
if (!(sc & SCF_KEY_DESC) || tempp->flags & KDF_HAS_DESCS) {
if ((*tempp->put_key)(ch,sc))
break;
}
tempp=tempp->next;
}
}
}
U0 PutChar(I64 ch)
{
PutKey(ch,0);
}
U0 PutS(U8 *st)
{ //See $LK,"PutKeyHandling","FA:::/SparrowOS/Doc/KeyBoard.TXT.Z,PutKeyHandling"$
U8 ch,*ptr;
Bool cont=TRUE;
if (!st) return;
CKeyDev *tempp=sys_put_key_root.next;
if (!Bt(&Fs->display_flags,DISPLAYf_SILENT)) {
if (sys_cur_scan_code & SCF_SCROLL) {
if (sys_focus_task==Fs) {
while (sys_cur_scan_code & SCF_SCROLL)
Yield;
}
}
while (cont && tempp!=&sys_put_key_root) {
if (tempp->put_s) {
if ((*tempp->put_s)(st))
break;
} else {
ptr=st;
while (ch=*ptr++)
if ((*tempp->put_key)(ch,0))
cont=FALSE;
}
tempp=tempp->next;
}
}
}
U0 SetKeyDesc(U8 *fmt,...)
{
I64 i;
U8 *buf=SPrintFJoin(NULL,fmt,argc,argv);
StrCpy(key_desc,buf);
key_handler=Caller;
Free(buf);
for (i=0;i<5;i++)
Yield; //This makes KeyMap work better
}
U0 SetCtrlAltLetCB(U8 ch,U0 (*fp_handler)(I64 sc),U8 *desc,Bool in_irq=FALSE)
{
ch=ToUpper(ch)-'A';
if (ch<26) {
fp_ctrl_alt_let_cbs[ch]=fp_handler;
Free(ctrl_alt_let_descs[ch]);
ctrl_alt_let_descs[ch]=AStrNew(desc);
BEqu(&ctrl_alt_let_in_irq_flags,ch,in_irq);
}
}
CKeyDev *KeyDevAdd(Bool (*fp_put_key)(I64 ch,I64 sc),Bool (*fp_puts)(U8 *st),I64 priority,Bool key_descs=FALSE)
//Places hook in StdOut chain
{ //See $LK,"PutKeyHandling","FA:::/SparrowOS/Doc/KeyBoard.TXT.Z,PutKeyHandling"$
Bool old_preempt=Preempt(OFF);
CKeyDev *tempp,*tempp1=sys_put_key_root.last;
tempp=ACAlloc(sizeof(CKeyDev));
tempp->put_key=fp_put_key;
tempp->put_s=fp_puts;
tempp->priority=priority;
if (key_descs)
tempp->flags|=KDF_HAS_DESCS;
while (tempp1->priority>priority)
tempp1=tempp1->last;
QueIns(tempp,tempp1);
Preempt(old_preempt);
return tempp;
}
U0 KeyDevRem(CKeyDev *tempp)
{
Bool old_preempt=Preempt(OFF);
QueRem(tempp);
Preempt(old_preempt);
Free(tempp);
}
+31
View File
@@ -0,0 +1,31 @@
//See $LK,"::/SparrowOS/Doc/Acknowledgements.TXT.Z","FI:::/SparrowOS/Doc/Acknowledgements.TXT.Z"$ (2).
#define ATA_NOP 0x00
#define ATA_DEV_RST 0x08
#define ATA_PACKET 0xA0
#define ATA_READ_NATIVE_MAX 0xF8
#define ATA_READ_NATIVE_MAX_EXT 0x27
#define ATA_SET_MAX 0xF9
#define ATA_SET_MAX_EXT 0x37
#define ATA_READ_MULTI 0xC4
#define ATA_READ_MULTI_EXT 0x29
#define ATA_WRITE_MULTI 0xC5
#define ATA_WRITE_MULTI_EXT 0x39
#define ATA_ID_DEV 0xEC
#define ATAS_ERR 0x01
#define ATAS_DRQ 0x08
#define ATAS_DF 0x20
#define ATAS_DRDY 0x40
#define ATAS_BSY 0x80
#define ATAR0_DATA 0
#define ATAR0_FEAT 1
#define ATAR0_NSECT 2
#define ATAR0_SECT 3
#define ATAR0_LCYL 4
#define ATAR0_HCYL 5
#define ATAR0_SELECT 6
#define ATAR0_STAT 7
#define ATAR0_CMD 7
#define ATAR1_CTRL 2
+652
View File
@@ -0,0 +1,652 @@
Bool BlkDevLock(CBlkDev *bdev)
{
BlkDevChk(bdev);
while (bdev->lock_fwding)
bdev=bdev->lock_fwding;
if (!Bt(&bdev->locked_flags,BDlf_LOCKED) || bdev->owning_task!=Fs) {
while (LBts(&bdev->locked_flags,BDlf_LOCKED))
Yield;
bdev->owning_task=Fs;
return TRUE;
} else
return FALSE;
}
Bool PrtLock(CPrt *p)
{
PrtChk(p);
BlkDevLock(p->bdev);
if (!Bt(&p->locked_flags,Plf_LOCKED) || p->owning_task!=Fs) {
while (LBts(&p->locked_flags,Plf_LOCKED))
Yield;
p->owning_task=Fs;
return TRUE;
} else
return FALSE;
}
Bool BlkDevUnlock(CBlkDev *bdev,Bool rst=FALSE)
{
BlkDevChk(bdev);
while (bdev->lock_fwding)
bdev=bdev->lock_fwding;
if (Bt(&bdev->locked_flags,BDlf_LOCKED) && bdev->owning_task==Fs) {
if (rst) {
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SND],0))
Snd(0);
bdev->flags&=~(BDF_INITIALIZED|BDF_INIT_IN_PROGRESS);
}
bdev->owning_task=0;
LBtr(&bdev->locked_flags,BDlf_LOCKED);
Yield; //Prevent deadlock
return TRUE;
} else
return FALSE;
}
Bool PrtUnlock(CPrt *p,Bool rst=FALSE)
{
PrtChk(p);
if (Bt(&p->locked_flags,Plf_LOCKED) && p->owning_task==Fs) {
BlkDevUnlock(p->bdev,rst);
p->owning_task=0;
LBtr(&p->locked_flags,Plf_LOCKED);
Yield; //Prevent deadlock
return TRUE;
} else
return FALSE;
}
Bool BlkDevInit(CBlkDev *bdev)
{
CPrt *p=Drv2Prt(bdev->drv_let_base),*p2;
Bool old_preempt=Preempt(OFF),result=FALSE;
if (!(bdev->flags & BDF_INITIALIZED)) {
bdev->flags|=BDF_INITIALIZED |
BDF_INIT_IN_PROGRESS;
switch(bdev->type) {
case BDT_RAM:
bdev->RAM_dsk=AMAlloc((bdev->max_blk+1)<<BLK_SIZE_BITS);
bdev->max_blk=MSize(bdev->RAM_dsk)>>BLK_SIZE_BITS-1;
p->type=PT_NATIVE;
if (sys_boot_code.u8[0]!=BOOT_CODE_RAM ||
!NativeFSDrvValidate(bdev->drv_let_base))
NativeFSFmt(bdev->drv_let_base);
else {
p->size=bdev->max_blk+1;
NativeFSPrtInit(p);
}
break;
case BDT_ATA:
bdev->max_reads=128;
bdev->max_writes=1;
bdev->read_freq=2000;
bdev->write_freq=500;
ATAInit(bdev);
break;
case BDT_ATAPI:
//0xFFFF*4 is too big for my taste
bdev->max_reads=0x800*4;
//max of maybe a quarter of disk cache
if (bdev->max_reads>sys_dsk_cache_size/BLK_SIZE/4)
bdev->max_reads=sys_dsk_cache_size/BLK_SIZE/4 & ~3;
if (bdev->max_reads<128)
bdev->max_reads=128;
bdev->max_writes=0xFFFF*4;
bdev->read_freq=1000;
bdev->write_freq=250;
ATAInit(bdev);
p->size=bdev->max_blk+1;
break;
case BDT_NON_NATIVE_FILE:
bdev->max_reads=128;
bdev->max_writes=128;
bdev->read_freq=2000;
bdev->write_freq=500;
if (bdev->flags & BDF_FMT)
NativeFSFmt(bdev->drv_let_base,TRUE);
else {
p2=Drv2Prt(bdev->non_native_drv);
bdev->min_blk=p->offset;
bdev->max_blk=p2->offset+p2->size-1; //temp
p->size=p2->size-(p->offset-p2->offset); //temp
NativeFSPrtInit(p);
bdev->max_blk=p->offset+p->size-1;
}
break;
}
if (bdev->flags & BDF_READ_CACHE)
DskCacheInvalidate(p);
bdev->flags&=~BDF_INIT_IN_PROGRESS;
result=TRUE;
}
Preempt(old_preempt);
return result;
}
U0 BlkDevsRelease()
{
I64 i;
CBlkDev *bdev;
for (i=0;i<NUM_BLKDEVS;i++) {
bdev=&sys_blkdevs[i];
if (Bt(&bdev->locked_flags,BDlf_LOCKED) && bdev->owning_task==Fs)
BlkDevUnlock(bdev,TRUE);
}
}
U0 PrtsRelease()
{
I64 i;
CPrt *p;
for (i=0;i<NUM_PRTS;i++) {
p=&sys_prts[i];
if (Bt(&p->locked_flags,Plf_LOCKED) && p->owning_task==Fs)
PrtUnlock(p,TRUE);
}
}
U0 MapBufAlloc(CPrt *p,I64 num_blks)
{
PrtChk(p);
Free(p->cur_map_blk);
Free(p->buffered_map_dirty_bits);
p->num_buffered_map_blks=num_blks;
p->cur_map_blk=AMAlloc(num_blks<<BLK_SIZE_BITS);
p->buffered_map_dirty_bits=ACAlloc((num_blks+7)>>3);
p->cur_map_blk_num=0;
RBlks(p,p->cur_map_blk,p->map1,p->num_buffered_map_blks);
}
U0 CleanMAPBuf(CPrt *p,I64 MAP_select=-1)
{
I64 i;
if ((MAP_select==-1 || !MAP_select) && p->map1!=p->map2)
for (i=0;i<p->num_buffered_map_blks;i++)
if (Bt(p->buffered_map_dirty_bits,i))
WBlks(p,p->cur_map_blk(I64)+i<<BLK_SIZE_BITS,p->map1+i+p->cur_map_blk_num,1);
if (MAP_select==-1 || MAP_select==1 || p->map1==p->map2)
for (i=0;i<p->num_buffered_map_blks;i++)
if (LBtr(p->buffered_map_dirty_bits,i))
WBlks(p,p->cur_map_blk(I64)+i<<BLK_SIZE_BITS,p->map2+i+p->cur_map_blk_num,1);
}
U0 SetNativeBuf(CPrt *p,I64 c,I64 map_select=-1)
{
I64 MAP_blk_num;
if (c==INVALID_CLUSTER)
throw(EXCEPT_PRT,1);
if (p->type==PT_FAT32)
MAP_blk_num=c/(BLK_SIZE>>2);
else
MAP_blk_num=c>>(BLK_SIZE_BITS+3);
if (MAP_blk_num!=p->cur_map_blk_num) {
CleanMAPBuf(p,map_select);
p->cur_map_blk_num=MAP_blk_num;
if (map_select==-1 || !map_select)
RBlks(p,p->cur_map_blk,p->map1+p->cur_map_blk_num,1);
else
RBlks(p,p->cur_map_blk,p->map2+p->cur_map_blk_num,1);
}
}
#define ZERO_BUF_SIZE 2048
U0 WZeroBlks(CPrt *p,I64 blk,I64 cnt)
{
I64 n;
U8 *z=CAlloc(ZERO_BUF_SIZE<<BLK_SIZE_BITS);
Bool show_progress;
if (cnt>ZERO_BUF_SIZE && p->bdev->type!=BDT_RAM) {
progress1=0; progress1_max=cnt;
StrCpy(progress1_desc,"Zeroing");
show_progress=TRUE;
} else
show_progress=FALSE;
while (cnt>0) {
n=cnt;
if (n>ZERO_BUF_SIZE)
n=ZERO_BUF_SIZE;
WBlks(p,z,blk,n);
blk+=n;
cnt-=n;
if (show_progress)
progress1+=n;
Yield; //Prevent locking
}
Free(z);
if (show_progress) {
*progress1_desc=0;
progress1=progress1_max=0;
}
}
//Very dangerous
Bool SetDrvType(U8 drv_let,I64 type=PT_NATIVE)
{
I64 i,j,ext_base,num_prt,offset,cur_type;
CMasterBoot mbr;
CBlkDev *bdev=Drv2BlkDev(drv_let);
num_prt=bdev->drv_let_base-'A';
switch (bdev->type) {
case BDT_ATA:
offset=0;
ext_base=INVALID_CLUSTER;
while (TRUE) {
ATAReadBlks(bdev,&mbr,offset,1);
j=-1;
for (i=0;i<4;i++) {
cur_type=mbr.p[i].type;
if (cur_type) {
if (cur_type==5 || cur_type==15)
j=i;
else {
if (num_prt+'A'==ToUpper(drv_let)) {
switch (type) {
case PT_NATIVE:
mbr.p[i].type=MBR_PT_NATIVE;
break;
case PT_FAT32:
mbr.p[i].type=MBR_PT_FAT32a;
break;
default:
Dbg;
}
mbr.p[i].active=0x80;
ATAWriteBlks(bdev,&mbr,offset,1);
return TRUE;
}
num_prt++;
}
}
}
if (j<0)
break;
if (!mbr.p[j].offset)
break;
if (ext_base==INVALID_CLUSTER) {
offset=mbr.p[j].offset;
ext_base=offset;
} else
offset=mbr.p[j].offset+ext_base;
}
break;
}
}
Bool RBlks(CPrt *p,U8 *buf, I64 blk, I64 cnt)
{
Bool result=TRUE,unlock;
CBlkDev *bdev=p->bdev;
PrtChk(p);
if (cnt<=0) return result;
try {
unlock=PrtLock(p);
BlkDevInit(bdev);
if (p->offset && blk<p->offset || blk+cnt>p->offset+p->size)
throw(EXCEPT_PRT,2);
blk+=bdev->offset;
if (bdev->flags & BDF_READ_CACHE)
RCache(p,&buf,&blk,&cnt);
if (cnt>0) {
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SND],0))
Snd(bdev->read_freq);
result=(*p->rblks)(p,buf,blk,cnt);
bdev->last_time=tS;
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SND],0))
Snd(0);
if (bdev->flags & BDF_READ_CACHE)
DskCacheAdd(p,buf,blk,cnt);
}
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
return result;
}
Bool WBlks(CPrt *p,U8 *buf, I64 blk, I64 cnt)
{
Bool result=TRUE,unlock;
CBlkDev *bdev=p->bdev;
PrtChk(p);
if (cnt<=0) return result;
try {
unlock=PrtLock(p);
BlkDevInit(bdev);
if (bdev->flags&BDF_READ_ONLY &&
!(bdev->flags & BDF_READ_ONLY_OVERRIDE))
throw(EXCEPT_BLKDEV,0);
if (p->offset && blk<p->offset || blk+cnt>p->offset+p->size)
throw(EXCEPT_PRT,3);
blk+=bdev->offset;
if (cnt>0) {
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SND],0))
Snd(bdev->write_freq);
result=(*p->wblks)(p,buf,blk,cnt);
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SND],0))
Snd(0);
bdev->last_time=tS;
if (bdev->flags & BDF_READ_CACHE)
DskCacheAdd(p,buf,blk,cnt);
}
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
return result;
}
U0 DskCacheInvalidate(CPrt *p)
{
Bool unlock;
CBlkDev *bdev=p->bdev;
PrtChk(p);
try {
unlock=PrtLock(p);
BlkDevInit(bdev);
if (bdev->flags & BDF_READ_CACHE)
DskCacheInvalidate2(p);
if (p->type==PT_ISO9660) {
if (!(bdev->flags & BDF_READ_ONLY_OVERRIDE))
ISOPrtInit(p,(32767/bdev->blk_size+1)*
bdev->blk_size>>BLK_SIZE_BITS);
}
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
}
U0 ChgDsk(U8 drv_let=0)
{ //This is needed for removable media
CPrt *p=Drv2Prt(drv_let);
CBlkDev *bdev=p->bdev;
Bool old_preempt=Preempt(OFF);
if (!BlkDevInit(bdev) && bdev->flags & BDF_REMOVABLE)
DskCacheInvalidate(p);
Drv(drv_let);
NativeFSFreeFreeList(p);
Preempt(old_preempt);
}
U0 PrtRep()
{ //Partition report
CPrt *p;
CBlkDev *bdev;
U16 type_u16;
I64 i;
"\nDefined Partitions:\n\n";
p=sys_prts;
for (i=0;i<NUM_PRTS;i++,p++) {
bdev=p->bdev;
if (type_u16=p->type.u16[0]) {
"$$FG,PURPLE$$";
if (p==dft_prt)
'*';
else
'' CH_SPACE;
if (Bt(&p->type,PTf_DISABLE))
"Disabled ";
"%C %-8Z %-9Z %04X %04X %02X$$FG$$\n%016X-%016X\n",
Prt2Drv(p),type_u16,"ST_PRT_TYPES",
bdev->type,"ST_BLKDEV_TYPES",bdev->base0,bdev->base1,bdev->unit,
p->offset,p->offset+p->size-1;
}
}
}
I64 ClusterNumNext(CPrt *p,I64 c,I64 cnt=1)
{
Bool unlock;
PrtChk(p);
if (cnt<=0) return c;
try {
unlock=PrtLock(p);
switch (p->type) {
case PT_ISO9660:
case PT_NATIVE:
c+=cnt;
break;
case PT_FAT32:
while (cnt-->0 && 0<c<0x0FFFFFF8) {
SetNativeBuf(p,c);
c=p->cur_map_blk[c & (BLK_SIZE/4-1)];
}
if (!(0<c<0x0FFFFFF8))
c=INVALID_CLUSTER;
break;
default:
Dbg;
}
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
return c;
}
I64 Cluster2Blk(CPrt *p,I64 c)
{
PrtChk(p);
return p->data+c*p->spc;
}
I64 RClustersBlks(CPrt *p,U8 *buf,I64 c,I64 blks)
{ //This accepts blk count, so padding on last cluster is not read.
I64 i;
Bool unlock;
PrtChk(p);
if (blks<=0) return c;
try {
unlock=PrtLock(p);
switch (p->type) {
case PT_ISO9660:
case PT_NATIVE:
RBlks(p,buf,p->data+c*p->spc,blks);
c+=(blks+p->spc-1)/p->spc;
break;
case PT_FAT32:
while (blks && 0<c<0x0FFFFFF8) {
i=blks;
if (i>p->spc)
i=p->spc;
RBlks(p,buf,p->data+c*p->spc,i);
buf+=i<<BLK_SIZE_BITS;
c=ClusterNumNext(p,c,1);
blks-=i;
}
if (blks)
Dbg;
break;
default:
Dbg;
}
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
return c;
}
I64 RClusters(CPrt *p,U8 *buf,I64 c,I64 cnt)
{
return RClustersBlks(p,buf,c,cnt*p->spc);
}
Bool CFileNameTo(U8 *dst,U8 *src)
{
MemSet(dst,0,CDIR_FILENAME_LEN);
if (!FileNameChk(src))
return FALSE;
StrCpy(dst,src);
return TRUE;
}
I64 Name2DirCluster(CPrt *p,U8 *dirname)
{
Bool cont=TRUE,unlock;
I64 cur_dir_cluster;
CDirEntry de;
U8 *buf=StrNew(dirname),*buf2=StrNew(dirname);
PrtChk(p);
try {
unlock=PrtLock(p);
cur_dir_cluster=p->root_cluster;
while (*buf && cont) {
StrFirstRem(buf,"/",buf2);
if (*buf2) {
switch (p->type) {
case PT_NATIVE:
cont=NativeFSFileFind(p,cur_dir_cluster,
buf2,&de,TRUE,FALSE);
break;
case PT_FAT32:
cont=FAT32FileFind(p,cur_dir_cluster,
buf2,&de,TRUE,FALSE);
break;
case PT_ISO9660:
cont=ISO1FileFind(p,cur_dir_cluster,
buf2,&de,TRUE,FALSE);
break;
default:
Dbg;
}
cur_dir_cluster=de.cluster;
}
}
if (!cont) {
"%s ",dirname;
PutDefineErr("ST_FILE_NOT_FOUND");
cur_dir_cluster=0;
}
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
Free(buf);
Free(buf2);
return cur_dir_cluster;
}
I64 Name2ParentDirCluster(CPrt *p,U8 *dirname)
{
Bool cont=TRUE,unlock;
I64 cur_dir_cluster,cur_dir_cluster2;
CDirEntry de;
U8 *buf=StrNew(dirname),*buf2=StrNew(dirname);
PrtChk(p);
try {
unlock=PrtLock(p);
cur_dir_cluster=p->root_cluster;
cur_dir_cluster2=p->root_cluster;
while (*buf && cont) {
cur_dir_cluster2=cur_dir_cluster;
StrFirstRem(buf,"/",buf2);
if (*buf2) {
switch (p->type) {
case PT_NATIVE:
cont=NativeFSFileFind(p,cur_dir_cluster,
buf2,&de,TRUE,FALSE);
break;
case PT_FAT32:
cont=FAT32FileFind(p,cur_dir_cluster,
buf2,&de,TRUE,FALSE);
break;
case PT_ISO9660:
cont=ISO1FileFind(p,cur_dir_cluster,
buf2,&de,TRUE,FALSE);
break;
default:
Dbg;
}
cur_dir_cluster=de.cluster;
}
}
if (!cont) {
"%s ",dirname;
PutDefineErr("ST_FILE_NOT_FOUND");
cur_dir_cluster2=0;
}
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
Free(buf);
Free(buf2);
return cur_dir_cluster2;
}
I64 WClustersBlks(CPrt *p,U8 *buf,I64 c,I64 blks)
{ //This accepts blk count, so padding on last cluster is not written.
I64 i;
Bool unlock;
PrtChk(p);
if (blks<=0) return c;
try {
unlock=PrtLock(p);
switch (p->type) {
case PT_NATIVE:
WBlks(p,buf,p->data+c*p->spc,blks);
c=0;
break;
case PT_FAT32:
while (blks) {
if (!(0<c<0x0FFFFFF8))
Dbg;
i=blks;
if (i>p->spc)
i=p->spc;
WBlks(p,buf,p->data+c*p->spc,i);
buf+=i<<BLK_SIZE_BITS;
c=ClusterNumNext(p,c);
blks-=i;
}
break;
default:
Dbg;
}
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
return c;
}
I64 WClusters(CPrt *p,U8 *buf,I64 c,I64 cnt)
{
return WClustersBlks(p,buf,c,cnt*p->spc);
}
//c=0 means first cluster in chain
I64 ClusersAlloc(CPrt *p,I64 c=0,I64 cnt=1,Bool contiguous=FALSE)
{
PrtChk(p);
if (cnt<=0) return c;
switch (p->type) {
case PT_NATIVE:
return NativeFSAllocClusters(p,cnt);
case PT_FAT32:
if (contiguous) {
if (c) throw(EXCEPT_FILE,3);
return FAT32AllocContiguousClusters(p,cnt);
} else
return FAT32AllocClusters(p,c,cnt);
default:
Dbg;
}
}
+468
View File
@@ -0,0 +1,468 @@
Bool MapDrv(U8 drv_let,CPrt *p)
{
drv_let=ToUpper(drv_let);
if ('A'<=drv_let<='Z') {
drv_to_prt[drv_let-'A']=p;
p->drv_let=drv_let;
return TRUE;
} else
return FALSE;
}
Bool Drv(U8 drv_let)
{
CPrt *p=Drv2Prt(drv_let);
CBlkDev *bdev=p->bdev;
BlkDevChk(bdev);
if (p!=Fs->cur_prt) {
if ( bdev->flags & BDF_REMOVABLE &&
!(bdev->flags & BDF_INITIALIZED) )
ChgDsk(Prt2Drv(p));
if (bdev->type==BDT_RAM ||
bdev->type==BDT_NON_NATIVE_FILE)
BlkDevInit(bdev);
}
Fs->cur_prt=p;
Free(Fs->cur_dir);
Fs->cur_dir=StrNew("/");
switch (p->type) {
case PT_NATIVE:
case PT_FAT32:
case PT_ISO9660:
return TRUE;
default:
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
return FALSE;
}
}
Bool Cd(U8 *dirname,Bool make_dirs=FALSE)
{//Optionally, will create the directories if they don't exist.
I64 maxlen,cur_dir_cluster=0;
U8 *chg_to_buf,*new_cur_dir,*buf;
CPrt *p;
Bool result=TRUE;
if (!*dirname) return TRUE;
if (dirname[1]==':') {
if (*dirname==':') {
if (Fs->cur_prt!=dft_prt)
if (!Drv(*dirname)) return FALSE;
} else {
if (Fs->cur_prt!=
Drv2Prt(*dirname))
if (!Drv(*dirname)) return FALSE;
}
dirname+=2;
}
if (*dirname=='/' || !*dirname || !Fs->cur_dir) {
Free(Fs->cur_dir);
Fs->cur_dir=StrNew("/");
if (*dirname=='/')
dirname++;
}
chg_to_buf=MStrUtil(dirname,
SUF_REM_LEADING|SUF_REM_TRAILING|SUF_REM_CTRL_CHARS);
maxlen=StrLen(Fs->cur_dir)+1+StrLen(chg_to_buf)+1;
new_cur_dir=MAlloc(maxlen);
buf=MAlloc(maxlen);
StrCpy(new_cur_dir,Fs->cur_dir);
while (*chg_to_buf && result) {
StrFirstRem(chg_to_buf,"/",buf);
if (!*buf)
StrCpy(new_cur_dir,"/");
else if (!StrCmp(buf,"..")) {
StrLastRem(new_cur_dir,"/");
if (!*new_cur_dir)
StrCpy(new_cur_dir,"/");
} else if (!StrCmp(buf,".")) {
;
} else if (*buf) {
if (!StrCmp(buf,"HOME")) {
result=Cd(sys_acct);
Free(new_cur_dir);
new_cur_dir=MAlloc(maxlen+StrLen(sys_acct));
StrCpy(new_cur_dir,sys_acct+2);
} else {
p=Fs->cur_prt;
cur_dir_cluster=Name2DirCluster(p,new_cur_dir);
switch (p->type) {
case PT_NATIVE:
result=NativeFSCd(buf,cur_dir_cluster);
break;
case PT_FAT32:
result=FAT32Cd(buf,cur_dir_cluster);
break;
case PT_ISO9660:
result=ISO1Cd(buf,cur_dir_cluster);
break;
default:
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
result=FALSE;
}
if (!result && make_dirs) {
Free(Fs->cur_dir);
Fs->cur_dir=StrNew(new_cur_dir);
result=MkDir(buf);
}
if (result) {
if (StrCmp(new_cur_dir,"/"))
StrCat(new_cur_dir,"/");
StrCat(new_cur_dir,buf);
}
}
}
}
Free(Fs->cur_dir);
Fs->cur_dir=StrNew(new_cur_dir);
Free(buf);
Free(chg_to_buf);
Free(new_cur_dir);
return result;
}
U0 FileAccessDel(CFileAccess *fa)
{
CBlkDev *bdev;
if (!fa) return;
bdev=fa->old_prt->bdev;
if (!(bdev->flags & BDF_INIT_IN_PROGRESS)) {
if (fa->old_dir) {
Drv(Prt2Drv(fa->old_prt));
Cd(fa->old_dir);
}
} else {
Fs->cur_prt=fa->old_prt;
Free(Fs->cur_dir);
Fs->cur_dir=StrNew("/");
}
Free(fa->old_dir);
Free(fa->mask);
Free(fa);
}
CFileAccess *FileAccessNew(U8 *_mask,Bool make_mask=FALSE,Bool make_dirs=FALSE)
{
Bool valid=TRUE,old_silent;
U8 *buf,*mask,*temp_mask;
CFileAccess *fa=CAlloc(sizeof(CFileAccess));
mask=MStrUtil(_mask,
SUF_REM_LEADING|SUF_REM_TRAILING|SUF_REM_CTRL_CHARS);
temp_mask=mask;
fa->old_dir=StrNew(Fs->cur_dir);
fa->old_prt=Fs->cur_prt;
if (*mask && mask[1]==':') {
if (Fs->cur_prt!=Drv2Prt(*mask))
if (!Drv(*mask)) valid=FALSE;
mask+=2;
}
if (StrStr(mask,"HOME") && Fs->cur_prt!=Drv2Prt(*sys_acct))
Drv(*sys_acct);
fa->p=Fs->cur_prt;
PrtChk(fa->p);
buf=MAlloc(StrLen(mask)+2);
StrCpy(buf,mask);
fa->mask=MAlloc(StrLen(mask)+2);
StrLastRem(buf,"/",fa->mask);
if (*mask=='/' && !*buf)
StrCpy(buf,"/");
if (*buf)
if (!Cd(buf,make_dirs))
valid=FALSE;
if (valid && make_mask) {
if (!*fa->mask) {
Free(fa->mask);
fa->mask=StrNew("*");
} else {
if (!make_dirs || FileNameChk(fa->mask)) {
old_silent=Silent(ON);
if (Cd(fa->mask,make_dirs)) {
Free(fa->mask);
fa->mask=StrNew("*");
}
Silent(old_silent);
}
}
}
Free(buf);
Free(temp_mask);
if (!valid) {
FileAccessDel(fa);
fa=NULL;
// throw(EXCEPT_FILE);
}
return fa;
}
CDirEntry *FilesFind(U8 *files_find_mask,I64 fuf_flags=0)
{
/*
Flags:
$LK,"FUF_RECURSE","MN:FUF_RECURSE"$ +r Recurse
$LK,"FUF_FLATTEN_TREE","MN:FUF_FLATTEN_TREE"$ +f $BK,1$be sure to use this along with '+F'$BK,0$.
$LK,"FUF_JUST_DIRS","MN:FUF_JUST_DIRS"$ +D just directories
$LK,"FUF_JUST_FILES","MN:FUF_JUST_FILES"$ +F just files
$LK,"FUF_JUST_TEXT_FILES","MN:FUF_JUST_TEXT_FILES"$ +t just text files: $LK,"TEXT_FILE_MASK","MN:TEXT_FILE_MASK"$
$LK,"FUF_JUST_SRC_FILES","MN:FUF_JUST_SRC_FILES"$ +s just src files : $LK,"SRC_FILE_MASK","MN:SRC_FILE_MASK"$
See $LK,"ST_FILE_UTIL_FLAGS","MN:ST_FILE_UTIL_FLAGS"$ when used in calling program taking text flags.
*/
CDirEntry *result;
CFileAccess *fa=FileAccessNew(files_find_mask,TRUE);
if (fa) {
result=SysFilesFind(fa->mask,fuf_flags);
FileAccessDel(fa);
} else
result=NULL;
return result;
}
Bool IsDir(U8 *dir_name)
{
U8 *mask=MSPrintF("%s/*",dir_name);
Bool result,old_silent=Silent(ON);
CFileAccess *fa=FileAccessNew(mask);
if (fa) {
FileAccessDel(fa);
result=TRUE;
} else
result=FALSE;
Free(mask);
Silent(old_silent);
return result;
}
U0 Dir(U8 *files_find_mask="*",Bool full=FALSE)
{
CFileAccess *fa;
fa=FileAccessNew(files_find_mask,TRUE);
if (fa) {
Dir2(fa->mask,0,full);
FileAccessDel(fa);
}
}
U0 Del(U8 *files_find_mask,Bool print_msg=TRUE)
{
CFileAccess *fa=FileAccessNew(files_find_mask);
if (fa) {
switch (fa->p->type) {
case PT_NATIVE:
NativeFSFilesDel(fa->p,Fs->cur_dir,fa->mask,0,FALSE,print_msg);
break;
case PT_FAT32:
FAT32FilesDel(fa->p,Fs->cur_dir,fa->mask,0,FALSE,print_msg);
break;
case PT_ISO9660:
PutDefineErr("ST_NOT_WRITABLE");
break;
default:
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
}
FileAccessDel(fa);
}
}
U8 *FileRead(U8 *filename,I64 *_size=NULL,I64 *_attr=NULL,Bool raw=FALSE)
{
CHashGeneric *temph;
U8 *absname,*result=NULL;
I64 size=0,attr=0;
CFileAccess *fa;
CArcCompress *ac=NULL;
if (_attr) *_attr=0;
absname=FileNameAbs(filename);
if (!raw && (temph=HashFind(absname,adam_task->hash_table,HTT_FILE))) {
if (FileAttr(absname) & _ATTR_COMPRESSED) {
ac=temph->user_data0;
if (_size) *_size=ac->expanded_size;
if (_attr) *_attr=FileAttr(absname,*_attr);
result=ExpandBuf(ac);
} else {
result=MAlloc(temph->user_data1+1);
MemCpy(result,temph->user_data0,temph->user_data1);
result[temph->user_data1]=0; //Terminate
if (_size) *_size=temph->user_data1;
}
} else {
fa=FileAccessNew(absname);
if (fa) {
switch (fa->p->type) {
case PT_NATIVE:
result=NativeFSFileRead(fa->p,Fs->cur_dir,fa->mask,&size,&attr,raw,&ac);
break;
case PT_FAT32:
result=FAT32FileRead(fa->p,Fs->cur_dir,fa->mask,&size,&attr,raw,&ac);
break;
case PT_ISO9660:
result=ISO1FileRead(fa->p,Fs->cur_dir,fa->mask,&size,&attr,raw,&ac);
break;
default:
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
}
while (!result && StrCmp(Fs->cur_dir,"/")) {
Cd("..");
switch (Fs->cur_prt->type) {
case PT_NATIVE:
result=NativeFSFileRead(fa->p,Fs->cur_dir,fa->mask,&size,&attr,raw,&ac);
break;
case PT_FAT32:
result=FAT32FileRead(fa->p,Fs->cur_dir,fa->mask,&size,&attr,raw,&ac);
break;
case PT_ISO9660:
result=ISO1FileRead(fa->p,Fs->cur_dir,fa->mask,&size,&attr,raw,&ac);
break;
default:
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
}
}
if (!result) {
"%s ",filename;
PutDefineErr("ST_FILE_NOT_FOUND");
}
FileAccessDel(fa);
}
if (_size) *_size=size;
if (_attr) *_attr=attr;
if (!raw && attr & _ATTR_RESIDENT)
HashGenericAdd(absname,HTT_FILE,AMAllocIdentical(ac),size,0,adam_task);
Free(ac);
}
Free(absname);
return result;
}
U8 *TextFileRead(U8 *filename,I64 *_attr=NULL)
{
return FileRead(filename,NULL,_attr);
}
Bool FileFind(U8 *filename,CDirEntry *rde=NULL,
Bool dir_only=FALSE,Bool file_only=FALSE,Bool scan_parents=FALSE)
{
I64 cur_dir_cluster;
CDirEntry de;
CFileAccess *fa=FileAccessNew(filename);
Bool result=FALSE;
if (fa) {
cur_dir_cluster=Name2DirCluster(fa->p,Fs->cur_dir);
switch (fa->p->type) {
case PT_NATIVE:
result=NativeFSFileFind(fa->p,cur_dir_cluster,fa->mask,
&de,dir_only,file_only);
break;
case PT_FAT32:
result=FAT32FileFind(fa->p,cur_dir_cluster,fa->mask,
&de,dir_only,file_only);
break;
case PT_ISO9660:
result=ISO1FileFind(fa->p,cur_dir_cluster,fa->mask,
&de,dir_only,file_only);
break;
default:
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
}
if (scan_parents) {
while (!result && StrCmp(Fs->cur_dir,"/")) {
Cd("..");
cur_dir_cluster=Name2DirCluster(fa->p,Fs->cur_dir);
switch (fa->p->type) {
case PT_NATIVE:
result=NativeFSFileFind(fa->p,cur_dir_cluster,fa->mask,
&de,dir_only,file_only);
break;
case PT_FAT32:
result=FAT32FileFind(fa->p,cur_dir_cluster,fa->mask,
&de,dir_only,file_only);
break;
case PT_ISO9660:
result=ISO1FileFind(fa->p,cur_dir_cluster,fa->mask,
&de,dir_only,file_only);
break;
default:
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
}
}
}
FileAccessDel(fa);
}
if (result && rde)
MemCpy(rde,&de,sizeof(CDirEntry));
return result;
}
I64 FileSize(U8 *filename)
{
CDirEntry de;
if (FileFind(filename,&de))
return de.size;
else
return 0;
}
I64 FileSizeExpanded(U8 *filename)
{
U8 buf[BLK_SIZE],*full_name;
CPrt *p;
CDirEntry de;
if (FileFind(filename,&de)) {
full_name=FileNameAbs(filename);
p=Drv2Prt(*full_name);
Free(full_name);
if (p->type==PT_NATIVE && de.expanded_size)
return de.expanded_size;
else {
if (de.size && FileAttr(de.name) & _ATTR_COMPRESSED) {
RBlks(p,buf,Cluster2Blk(p,de.cluster),1);
return (&buf)(CArcCompress *)->expanded_size;
} else
return de.size;
}
} else
return 0;
}
I64 FileWrite(U8 *filename,U8 *fbuf,
I64 size,CDate ltdt=0,I64 attr=0,Bool raw=FALSE)
{
I64 c=0;
CHashGeneric *temph;
CFileAccess *fa=FileAccessNew(filename,FALSE,TRUE);
CArcCompress *ac=NULL;
U8 *absname=FileNameAbs(filename);
if (fa) {
switch (fa->p->type) {
case PT_NATIVE:
c=NativeFSFileWrite(fa->p,Fs->cur_dir,fa->mask,
fbuf,size,ltdt,attr,raw,&ac);
break;
case PT_FAT32:
c=FAT32FileWrite(fa->p,Fs->cur_dir,fa->mask,
fbuf,size,ltdt,attr,raw,&ac);
break;
case PT_ISO9660:
PutDefineErr("ST_NOT_WRITABLE");
break;
default:
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
}
if (temph=HashFind(absname,adam_task->hash_table,HTT_FILE)) {
if (!raw && ac && attr & _ATTR_RESIDENT) {
Free(temph->user_data0);
temph->user_data0=AMAllocIdentical(ac);
temph->user_data1=size;
} else
HashRemDel(temph,adam_task->hash_table);
} else if (!raw && ac && attr & _ATTR_RESIDENT)
HashGenericAdd(absname,HTT_FILE,AMAllocIdentical(ac),size,0,adam_task);
Free(ac);
FileAccessDel(fa);
}
Free(absname);
return c;
}
U0 TextFileWrite(U8 *filename,U8 *st,I64 attr=0)
{
FileWrite(filename,st,StrLen(st),0,attr);
}
+386
View File
@@ -0,0 +1,386 @@
U0 DrvDftSelect()
{
dft_prt=Drv2Prt(dft_drv);
Fs->cur_prt=INVALID_PTR; //Null screws-up cache
Fs->cur_dir=StrNew("/");
ChgDsk(':');
}
Bool CopySingleZ(U8 *f1,U8 *f2) //Just one file
{
U8 *file_buf=NULL;
I64 size,attr=0,c;
CDirEntry de;
if (FileFind(f1,&de,FALSE,TRUE)) {
file_buf=FileRead(f1,&size,&attr);
attr=FileAttr(f2,attr);
if (file_buf) {
"Copying %s to %s\n",f1,f2;
c=FileWrite(f2,file_buf,size,de.datetime,attr);
Free(file_buf);
return ToBool(c);
} else PutDefineErr("ST_FILE_NOT_FOUND");
} else PutDefineErr("ST_FILE_NOT_FOUND");
return FALSE;
}
#define COPY_BUF_BLKS 0x80
Bool CopySingle(U8 *f1,U8 *f2) //Just one file
{
U8 *absf1=FileNameAbs(f1),*absf2=FileNameAbs(f2),*buf;
I64 cnt,n,size,attr1=FileAttr(f1),attr2=FileAttr(f2),
xsum=NATIVE_XSUM,i,j;
CFile *in_file=NULL,*out_file=NULL;
if (!StrCmp(absf1,absf2)) { //onto self?
Free(absf1);
Free(absf2);
return FALSE;
}
Free(absf1);
Free(absf2);
if (attr1!=attr2)
return CopySingleZ(f1,f2);
buf=MAlloc(COPY_BUF_BLKS<<BLK_SIZE_BITS);
if (attr1 & _ATTR_CONTIGUOUS)
in_file=FOpen(f1,"rc");
else
in_file=FOpen(f1,"r");
if (in_file) {
size=FSize(in_file);
cnt=(size+BLK_SIZE-1)>>BLK_SIZE_BITS;
if (attr2 & _ATTR_CONTIGUOUS)
out_file=FOpen(f2,"wc",cnt);
else
out_file=FOpen(f2,"w",cnt);
if (out_file) {
"Copying %s to %s\n",f1,f2;
j=size;
while (cnt>0) {
if (cnt>COPY_BUF_BLKS) {
n=COPY_BUF_BLKS;
i=n<<BLK_SIZE_BITS;
} else {
n=cnt;
i=j;
}
FRBlks(in_file, buf,FFB_NEXT_BLK,n);
xsum^=ArcXSum(buf,i);
FWBlks(out_file,buf,FFB_NEXT_BLK,n);
cnt-=n;
j-=n<<BLK_SIZE_BITS;
}
if (in_file->de.xsum &&
in_file->de.xsum!=xsum)
throw(EXCEPT_ARC_XSUM);
out_file->de.xsum=xsum;
out_file->flags|=FF_USE_OLD_DATETIME;
out_file->de.datetime=in_file->de.datetime;
out_file->de.size=size;
out_file->de.expanded_size=in_file->de.expanded_size;
out_file->de.attr=FileAttr(f2,in_file->de.attr);
FClose(out_file);
FClose(in_file);
Free(buf);
return TRUE;
} else PutDefineErr("ST_FILE_NOT_FOUND");
FClose(in_file);
} else PutDefineErr("ST_FILE_NOT_FOUND");
Free(buf);
return FALSE;
}
Bool MkDir(U8 *filename)
{
U8 *name;
if (FileFind(filename,NULL,TRUE))
return FALSE;
CFileAccess *fa=FileAccessNew(filename);
Bool result=FALSE;
if (fa) {
if (*fa->mask) {
if (!FileNameChk(fa->mask))
PutDefineErr("ST_INVALID_FILENAME");
else {
"Make Directory:";
"" filename;
NewLine;
name=MStrUtil(fa->mask,
SUF_REM_LEADING|SUF_REM_TRAILING|SUF_REM_CTRL_CHARS);
switch (fa->p->type) {
case PT_NATIVE:
result=NativeFSMkDir(fa->p,Fs->cur_dir,name);
break;
case PT_FAT32:
result=FAT32MkDir(fa->p,Fs->cur_dir,name);
break;
case PT_ISO9660:
PutDefineErr("ST_NOT_WRITABLE");
break;
default:
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
}
Free(name);
}
}
FileAccessDel(fa);
}
return result;
}
U0 SysDel(U8 *wild,Bool make_mask) //this is dangerous
{
CFileAccess *fa=FileAccessNew(wild,make_mask);
if (fa) {
switch (fa->p->type) {
case PT_NATIVE:
NativeFSFilesDel(fa->p,Fs->cur_dir,fa->mask,0,TRUE,TRUE);
break;
case PT_FAT32:
FAT32FilesDel(fa->p,Fs->cur_dir,fa->mask,0,TRUE,TRUE);
break;
case PT_ISO9660:
PutDefineErr("ST_NOT_WRITABLE");
break;
default:
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
}
FileAccessDel(fa);
}
}
U0 Fmt(I64 drv_let,Bool quick=TRUE,Bool confirm=TRUE,I64 type=PT_FAT32)
{//See $LK,"PT_FAT32","MN:PT_FAT32"$ for a list of supported file system types.
CPrt *p=Drv2Prt(drv_let);
Bool old_silent=IsSilent;
if (confirm) {
if (!AreYouSure)
return;
}
if (!p) {
PutDefineErr("ST_INVALID_DRV");
return;
}
switch (type) {
case PT_NATIVE:
Silent(ON);
Drv(drv_let);
Silent(old_silent);
NativeFSFmt(drv_let,quick);
DskCacheInvalidate(Drv2Prt(drv_let));
Drv(drv_let);
break;
case PT_FAT32:
Silent(ON);
Drv(drv_let);
Silent(old_silent);
FAT32Fmt(drv_let,quick);
DskCacheInvalidate(Drv2Prt(drv_let));
Drv(drv_let);
break;
case PT_ISO9660:
PutDefineErr("ST_NOT_WRITABLE");
break;
default:
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
}
}
U0 CDImageRead(U8 cd_drv_let,U8 *out_name)
{
CBlkDev *bdev=Drv2BlkDev(cd_drv_let);
CPrt *p=Drv2Prt(cd_drv_let);
U8 *buf=MAlloc(COPY_BUF_BLKS<<BLK_SIZE_BITS),
*out_name2=DftExt(out_name,"ISO");
CFile *f=FOpen(out_name2,"w");
I64 n,spc=bdev->blk_size>>BLK_SIZE_BITS,blk=0,cnt,retry;
BlkDevInit(bdev);
if (bdev->type!=BDT_ATAPI)
throw(EXCEPT_BLKDEV,3);
if (!out_name)
out_name=sys_dft_iso_name;
cnt=CeilU64(p->size,spc);
while (cnt>0) {
if (cnt>COPY_BUF_BLKS)
n=COPY_BUF_BLKS;
else
n=cnt;
if (n>bdev->max_reads)
n=bdev->max_reads;
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SND],0))
Snd(bdev->read_freq);
retry=4;
while (--retry)
if (ATAPIReadBlks2(bdev,buf,blk/spc,n/spc,TRUE,
//n is 0x800 if max_reads. Up to 8 additional seconds
tS+7.0+0.004*n/spc))
break;
if (!retry)
ATAPIReadBlks2(bdev,buf,blk/spc,n/spc,TRUE,0);
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SND],0))
Snd(0);
FWBlks(f,buf,blk,n);
cnt-=n;
blk+=n;
}
FClose(f);
Free(buf);
Free(out_name2);
}
class CDualBuf
{
U8 *buf0,*buf1;
I64 in_buf,out_buf,cnt;
U8 *filename;
CBlkDev *CD_bdev;
};
U0 CDImageWriteTask(CDualBuf *d)
{
U8 *buf;
I64 n,blk=0,cnt=d->cnt;
CFile *f;
if (!IsSysDeterministic)
Preempt(ON);
TaskInitExt; //needed for disk access
if (FileAttr(d->filename)&_ATTR_CONTIGUOUS)
f=FOpen(d->filename,"rc");
else
f=FOpen(d->filename,"r");
while (cnt>0) {
if (cnt>COPY_BUF_BLKS)
n=COPY_BUF_BLKS;
else
n=cnt;
if (n>d->CD_bdev->max_writes)
n=d->CD_bdev->max_writes;
buf=d->in_buf&1 ? d->buf1:d->buf0;
while (d->in_buf>d->out_buf+1)
Yield;
FRBlks(f,buf,blk,n);
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SND],0))
Snd(d->CD_bdev->write_freq);
d->in_buf++;
cnt-=n;
blk+=n;
}
FClose(f);
}
U0 CDImageWrite(U8 cd_drv_let,U8 *in_name=NULL,I64 media_type=MT_CD)
{
CDualBuf *d=CAlloc(sizeof(CDualBuf));
U8 *buf,*in_name2,*in_name3;
I64 i,n,spc,blk=0,cnt;
CPrt *p=Drv2Prt(cd_drv_let);
CBlkDev *bdev=p->bdev,*bdev2;
CTask *task;
Bool old_preempt;
CFile *f;
if (!in_name)
in_name=sys_dft_iso_name;
in_name3=DftExt(in_name,"ISO");
in_name2=FileNameAbs(in_name3);
f=FOpen(in_name2,"r");
if (!f) {
Free(d);
return;
}
cnt=(FSize(f)+BLK_SIZE-1)>>BLK_SIZE_BITS;
FClose(f);
if (bdev->type!=BDT_ATAPI)
throw(EXCEPT_BLKDEV,4);
bdev2=Drv2BlkDev(*in_name2);
while (bdev2->lock_fwding)
bdev2=bdev2->lock_fwding;
if ((bdev2->type==BDT_ATA || bdev2->type==BDT_ATAPI) &&
bdev2->base0==bdev->base0) {
"Can't Burn CD on same ATA ctrller as File.\n\n";
throw(EXCEPT_BLKDEV,5);
}
bdev->flags|=BDF_READ_ONLY_OVERRIDE;
BlkDevInit(bdev);
spc=bdev->blk_size>>BLK_SIZE_BITS;
if (p->size<cnt)
p->size=cnt;
d->filename=in_name2;
d->CD_bdev=bdev;
d->buf0=MAlloc(COPY_BUF_BLKS<<BLK_SIZE_BITS);
d->buf1=MAlloc(COPY_BUF_BLKS<<BLK_SIZE_BITS);
d->cnt=cnt;
old_preempt=Preempt(OFF);
task=Spawn(&CDImageWriteTask,d,"Write CD");
while (d->in_buf<=d->out_buf)
Yield;
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SND],0))
Snd(bdev->write_freq);
BlkDevLock(bdev);
ATAPIWaitReady(bdev,0);
progress1=0; progress1_max=cnt;
StrCpy(progress1_desc,"Writing");
while (cnt>0) {
if (cnt>COPY_BUF_BLKS)
n=COPY_BUF_BLKS;
else
n=cnt;
if (n>bdev->max_writes)
n=bdev->max_writes;
buf=d->out_buf&1 ? d->buf1:d->buf0;
while (d->in_buf<=d->out_buf)
Yield;
ATAPIWriteBlks(bdev,buf,blk/spc,(n+spc-1)/spc);
d->out_buf++;
cnt-=n;
blk+=n;
progress1+=n;
}
ATAPISync(bdev);
progress1=0; progress1_max=2;
StrCpy(progress1_desc,"Closing");
for (i=0;i<2;i++) {
ATAPIClose(bdev,0x100,i); //Close tracks
progress1++;
}
ATAPISync(bdev);
ATAPIClose(bdev,0x200); //close disk
ATAPISync(bdev);
if (media_type==MT_DVD) {
ATAPIClose(bdev,0x300);
ATAPISync(bdev);
}
*progress1_desc=0;
progress1=progress1_max=0;
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SND],0))
Snd(0);
bdev->flags&=~BDF_READ_ONLY_OVERRIDE;
BlkDevUnlock(bdev);
Free(d->buf0);
Free(d->buf1);
Free(in_name2);
Free(in_name3);
Preempt(old_preempt);
Free(d);
}
+655
View File
@@ -0,0 +1,655 @@
U0 ATABlkSelect(CBlkDev *bdev,I64 blk,I64 cnt)
{
if (bdev->type!=BDT_ATAPI && bdev->base1)
OutU8(bdev->base1+ATAR1_CTRL,0x8);
if (bdev->flags & BDF_EXT_SIZE) {
OutU8(bdev->base0+ATAR0_NSECT,cnt.u8[1]);
OutU8(bdev->base0+ATAR0_SECT,blk.u8[3]);
OutU8(bdev->base0+ATAR0_LCYL,blk.u8[4]);
OutU8(bdev->base0+ATAR0_HCYL,blk.u8[5]);
OutU8(bdev->base0+ATAR0_NSECT,cnt);
OutU8(bdev->base0+ATAR0_SECT,blk);
OutU8(bdev->base0+ATAR0_LCYL,blk.u8[1]);
OutU8(bdev->base0+ATAR0_HCYL,blk.u8[2]);
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
} else {
OutU8(bdev->base0+ATAR0_NSECT,cnt);
OutU8(bdev->base0+ATAR0_SECT,blk);
OutU8(bdev->base0+ATAR0_LCYL,blk.u8[1]);
OutU8(bdev->base0+ATAR0_HCYL,blk.u8[2]);
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4|blk.u8[3]);
}
}
Bool ATAWaitNotBUSY(CBlkDev *bdev,F64 timeout)
{
while (TRUE) {
if (timeout && tS>timeout)
return FALSE;
if (InU8(bdev->base0+ATAR0_STAT)&ATAS_BSY)
Yield;
else
return TRUE;
}
}
Bool ATAWaitDRQ(CBlkDev *bdev,F64 timeout)
{
while (TRUE) {
if (timeout && tS>timeout)
return FALSE;
if (!(InU8(bdev->base0+ATAR0_STAT)&ATAS_DRQ))
Yield;
else
return TRUE;
}
}
Bool ATANop(CBlkDev *bdev,F64 timeout)
{
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_FEAT,0);
OutU8(bdev->base0+ATAR0_CMD,ATA_NOP);
return ATAWaitNotBUSY(bdev,timeout);
}
U0 ATACmd(CBlkDev *bdev,U8 cmd)
{
OutU8(bdev->base0+ATAR0_FEAT,0);
OutU8(bdev->base0+ATAR0_CMD,cmd);
bdev->last_time=tS;
PortNop;
}
Bool ATAGetResult(CBlkDev *bdev,U8 *buf,I64 cnt,I64 _avail,Bool one_read,F64 timeout=0)
{
I64 avail,overflow;
bdev->flags&=~BDF_LAST_WAS_WRITE;
MemSet(buf,0,cnt);
while (cnt>0) {
if (!ATAWaitDRQ(bdev,timeout))
return FALSE;
if (_avail)
avail=_avail;
else
avail=InU8(bdev->base0+ATAR0_HCYL)<<8+InU8(bdev->base0+ATAR0_LCYL);
if (avail) {
if (avail>cnt) {
overflow=avail-cnt;
avail=cnt;
} else
overflow=0;
if (avail&2)
RepInU16(buf,avail>>1,bdev->base0+ATAR0_DATA);
else
RepInU32(buf,avail>>2,bdev->base0+ATAR0_DATA);
cnt-=avail;
buf+=avail;
while (overflow>0) {
if (timeout && tS>timeout)
return FALSE;
InU16(bdev->base0+ATAR0_DATA);
overflow-=2;
}
if (one_read)
break;
} else
Yield;
}
return ATAWaitNotBUSY(bdev,timeout);
}
Bool ATAPIWritePktWord(CBlkDev *bdev,U16 w,F64 timeout=0)
{
if (!ATAWaitDRQ(bdev,timeout))
return FALSE;
OutU16(bdev->base0+ATAR0_DATA,EndianU16(w));
bdev->last_time=tS;
return TRUE;
}
Bool ATAPISetMaxSpeed(CBlkDev *bdev)
{
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_LCYL,0);
OutU8(bdev->base0+ATAR0_HCYL,0);
ATACmd(bdev,ATA_PACKET);
ATAPIWritePktWord(bdev,0xBB00); //Set speed
ATAPIWritePktWord(bdev,0xFFFF); //read at max
ATAPIWritePktWord(bdev,0xFFFF); //write at max
ATAPIWritePktWord(bdev,0);
ATAPIWritePktWord(bdev,0);
ATAPIWritePktWord(bdev,0);
return ATAWaitNotBUSY(bdev,0);
}
Bool ATAPISeek(CBlkDev *bdev,I64 native_blk)
{
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_LCYL,0);
OutU8(bdev->base0+ATAR0_HCYL,0);
ATACmd(bdev,ATA_PACKET);
ATAPIWritePktWord(bdev,0x2B00); //Seek
ATAPIWritePktWord(bdev,native_blk>>16);
ATAPIWritePktWord(bdev,native_blk);
ATAPIWritePktWord(bdev,0);
ATAPIWritePktWord(bdev,0);
ATAPIWritePktWord(bdev,0x0000);
return ATAWaitNotBUSY(bdev,0);
}
Bool ATAPIStartStop(CBlkDev *bdev,Bool start,F64 timeout)
{
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
ATACmd(bdev,ATA_PACKET);
//Start/Stop
if (!ATAPIWritePktWord(bdev,0x1B00,timeout)) return FALSE;
if (!ATAPIWritePktWord(bdev,0x0000,timeout)) return FALSE;
if (start) {
if (!ATAPIWritePktWord(bdev,0x0100,timeout)) return FALSE;
} else {
if (!ATAPIWritePktWord(bdev,0x0000,timeout)) return FALSE;
}
if (!ATAPIWritePktWord(bdev,0x0000,timeout)) return FALSE;
if (!ATAPIWritePktWord(bdev,0x0000,timeout)) return FALSE;
if (!ATAPIWritePktWord(bdev,0x0000,timeout)) return FALSE;
return ATAWaitNotBUSY(bdev,timeout);
}
I64 ATAGetDevId(CBlkDev *bdev,U16 **_id_record,F64 timeout)
{
U16 *id_record;
if (_id_record) *_id_record=NULL;
if (bdev->type!=BDT_ATAPI && bdev->base1)
OutU8(bdev->base1+ATAR1_CTRL,0x8);
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
ATACmd(bdev,ATA_ID_DEV);
if (!ATAWaitNotBUSY(bdev,timeout))
return BDT_NULL;
if (InU8(bdev->base0+ATAR0_STAT)&ATAS_ERR)
return BDT_ATAPI;
id_record=ACAlloc(512);
if (!ATAGetResult(bdev,id_record,512,512,FALSE,timeout)) {
Free(id_record);
return BDT_NULL;
}
if (_id_record) *_id_record=id_record;
return BDT_ATA;
}
I64 ATAReadNativeMax(CBlkDev *bdev)
{ //returns zero on err
I64 blk=0;
Bool okay=TRUE;
if (bdev->type==BDT_ATAPI) {
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
ATACmd(bdev,ATA_DEV_RST);
if (!ATAWaitNotBUSY(bdev,0))
okay=FALSE;
} else {
while (InU8(bdev->base0+ATAR0_STAT) & ATAS_BSY) {
if (bdev->flags&BDF_LAST_WAS_WRITE)
OutU16(bdev->base0+ATAR0_DATA,0);
else
InU16(bdev->base0+ATAR0_DATA);
Yield;
}
Free(bdev->dev_id_record);
if (ATAGetDevId(bdev,&bdev->dev_id_record,0)==BDT_NULL)
okay=FALSE;
else
BEqu(&bdev->flags,BDf_EXT_SIZE,Bt(&bdev->dev_id_record[86],10));
}
if (okay) {
if (bdev->flags & BDF_EXT_SIZE && bdev->base1) {
OutU8(bdev->base1+ATAR1_CTRL,0x8);
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
ATACmd(bdev,ATA_READ_NATIVE_MAX_EXT);
if (ATAWaitNotBUSY(bdev,0)) {
blk.u8[0]=InU8(bdev->base0+ATAR0_SECT);
blk.u8[1]=InU8(bdev->base0+ATAR0_LCYL);
blk.u8[2]=InU8(bdev->base0+ATAR0_HCYL);
OutU8(bdev->base1+ATAR1_CTRL,0x80);
blk.u8[3]=InU8(bdev->base0+ATAR0_SECT);
blk.u8[4]=InU8(bdev->base0+ATAR0_LCYL);
blk.u8[5]=InU8(bdev->base0+ATAR0_HCYL);
if (blk>>24==blk&0xFFFFFF) {//Kludge to make qemu-kvm work
Btr(&bdev->flags,BDf_EXT_SIZE);
blk&=0xFFFFFF;
}
}
} else {
if (bdev->type!=BDT_ATAPI && bdev->base1)
OutU8(bdev->base1+ATAR1_CTRL,0x8);
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
ATACmd(bdev,ATA_READ_NATIVE_MAX);
if (ATAWaitNotBUSY(bdev,0)) {
blk.u8[0]=InU8(bdev->base0+ATAR0_SECT);
blk.u8[1]=InU8(bdev->base0+ATAR0_LCYL);
blk.u8[2]=InU8(bdev->base0+ATAR0_HCYL);
blk.u8[3]=InU8(bdev->base0+ATAR0_SELECT) & 0xF;
}
}
}
return bdev->max_blk=blk;
}
I64 ATAPIReadCapacity(CBlkDev *bdev,I64 *_blk_size=NULL)
{ //Supposedly this can return a result +/- 75 sects.
//Error might just be for music.
Bool unlock=BlkDevLock(bdev);
U32 buf[2];
if (ATAWaitNotBUSY(bdev,0)) {
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_LCYL,8);
OutU8(bdev->base0+ATAR0_HCYL,0);
ATACmd(bdev,ATA_PACKET);
ATAPIWritePktWord(bdev,0x2500); //Read Capacity
ATAPIWritePktWord(bdev,0x0000);
ATAPIWritePktWord(bdev,0x0000);
ATAPIWritePktWord(bdev,0x0000);
ATAPIWritePktWord(bdev,0x0000);
ATAPIWritePktWord(bdev,0x0000);
if (!ATAGetResult(bdev,buf,8,0,TRUE))
buf[0]=buf[1]=0;
} else
buf[0]=buf[1]=0;
if (unlock) BlkDevUnlock(bdev);
if (_blk_size) *_blk_size=EndianU32(buf[1]);
return EndianU32(buf[0]);
}
CATAPITrack *ATAPIReadTrackInfo(CBlkDev *bdev,I64 blk)
{
CATAPITrack *result=CAlloc(sizeof(CATAPITrack));
Bool unlock=BlkDevLock(bdev);
if (ATAWaitNotBUSY(bdev,0)) {
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_LCYL,sizeof(CATAPITrack)&0xFF);
OutU8(bdev->base0+ATAR0_HCYL,sizeof(CATAPITrack)>>8);
ATACmd(bdev,ATA_PACKET);
ATAPIWritePktWord(bdev,0x5200); //Read Track Info
ATAPIWritePktWord(bdev,blk.u16[1]);
ATAPIWritePktWord(bdev,blk.u16[0]);
ATAPIWritePktWord(bdev,(sizeof(CATAPITrack)&0xFF00)>>8);
ATAPIWritePktWord(bdev,(sizeof(CATAPITrack)&0x00FF)<<8);
ATAPIWritePktWord(bdev,0x0000);
if (!ATAGetResult(bdev,result,sizeof(CATAPITrack),0,TRUE)) {
Free(result);
result=NULL;
}
} else {
Free(result);
result=NULL;
}
if (unlock) BlkDevUnlock(bdev);
return result;
}
Bool ATAInit(CBlkDev *bdev)
{
Bool unlock=BlkDevLock(bdev),okay=FALSE;
if (bdev->type==BDT_ATAPI)
bdev->flags&=~BDF_EXT_SIZE;
else
bdev->flags|=BDF_EXT_SIZE;
if (ATAReadNativeMax(bdev)) {
ATABlkSelect(bdev,bdev->max_blk,0);
if (bdev->flags&BDF_EXT_SIZE)
ATACmd(bdev,ATA_SET_MAX_EXT);
else
ATACmd(bdev,ATA_SET_MAX);
if (ATAWaitNotBUSY(bdev,0)) {
okay=TRUE;
if (bdev->type==BDT_ATAPI) {
if (ATAPIStartStop(bdev,TRUE,0)) {
if(!ATAPISetMaxSpeed(bdev))
okay=FALSE;
} else
okay=FALSE;
}
}
}
if (unlock) BlkDevUnlock(bdev);
return okay;
}
Bool ATAPIWaitReady(CBlkDev *bdev,F64 timeout)
{
while (TRUE) {
if (!ATAWaitNotBUSY(bdev,timeout) ||
!ATANop(bdev,timeout) ||
!ATAPIStartStop(bdev,TRUE,timeout))
return FALSE;
if (InU8(bdev->base0+ATAR0_STAT) & ATAS_DRDY &&
!InU8(bdev->base0+ATAR0_FEAT));
return TRUE;
if (timeout && tS>timeout)
return FALSE;
ATAInit(bdev);
Yield;
}
}
U0 ATAReadBlks(CBlkDev *bdev,U8 *buf, I64 blk, I64 cnt)
{
I64 retries=3;
Bool unlock=BlkDevLock(bdev);
retry:
ATABlkSelect(bdev,blk,cnt);
if (bdev->flags & BDF_EXT_SIZE)
ATACmd(bdev,ATA_READ_MULTI_EXT);
else
ATACmd(bdev,ATA_READ_MULTI);
if (!ATAGetResult(bdev,buf,cnt*bdev->blk_size,BLK_SIZE,FALSE,tS+1.0)) {
if (retries--) {
ATAWaitNotBUSY(bdev,0);
goto retry;
} else
throw(EXCEPT_BLKDEV,6);
}
sys_dsk_reads+=(cnt*bdev->blk_size)>>BLK_SIZE_BITS;
if (unlock) BlkDevUnlock(bdev);
}
I64 ATAProbe(I64 base0,I64 base1,I64 unit)
{
CBlkDev bdev;
MemSet(&bdev,0,sizeof(CBlkDev));
bdev.type=BDT_ATAPI;
bdev.base0=base0;
bdev.base1=base1;
bdev.unit=unit;
bdev.blk_size=CD_BLK_SIZE;
return ATAGetDevId(&bdev,NULL,tS+0.1);
}
Bool ATAPIReadBlks2(CBlkDev *bdev,U8 *buf, I64 native_blk, I64 cnt,Bool lock,F64 timeout)
{
Bool result,unlock;
if (cnt<=0)
return FALSE;
if (lock)
unlock=BlkDevLock(bdev);
if (!ATAPIWaitReady(bdev,timeout)) goto arb_false_done;
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_LCYL,bdev->blk_size);
OutU8(bdev->base0+ATAR0_HCYL,bdev->blk_size.u8[1]);
ATACmd(bdev,ATA_PACKET);
if (!ATAPIWritePktWord(bdev,0xA800,timeout)) goto arb_false_done;
if (!ATAPIWritePktWord(bdev,native_blk.u16[1],timeout)) goto arb_false_done;
if (!ATAPIWritePktWord(bdev,native_blk,timeout)) goto arb_false_done;
if (!ATAPIWritePktWord(bdev,cnt.u16[1],timeout)) goto arb_false_done;
if (!ATAPIWritePktWord(bdev,cnt,timeout)) goto arb_false_done;
if (!ATAPIWritePktWord(bdev,0x0000,timeout)) goto arb_false_done;
if (!ATAGetResult(bdev,buf,cnt*bdev->blk_size,0,FALSE,timeout)) {
arb_false_done:
result=FALSE;
} else {
sys_dsk_reads+=(cnt*bdev->blk_size)>>BLK_SIZE_BITS;
result=TRUE;
}
// ATAPIStartStop(bdev,FALSE,0);
if (lock && unlock) BlkDevUnlock(bdev);
return result;
}
U0 ATAPIReadBlks(CBlkDev *bdev,U8 *buf, I64 blk, I64 cnt)
{
CPrt *p=Drv2Prt(bdev->drv_let_base);
I64 retry,spc=bdev->blk_size>>BLK_SIZE_BITS,n,blk2,
l2=bdev->max_reads<<1+spc<<1;
U8 *cd_buf=MAlloc(l2<<BLK_SIZE_BITS);
if (cnt>0) {
if (blk<=bdev->max_reads)
blk2=0;
else
blk2=FloorU64(blk-bdev->max_reads,spc);
if (blk2+l2>p->size)
l2=p->size-blk2;
n=(l2+spc-1)/spc;
retry=4;
while (--retry)
if (ATAPIReadBlks2(bdev,cd_buf,blk2/spc,n,TRUE,
//n is 0x800 if max_reads. Up to 8 additional seconds
tS+7.0+0.004*n))
break;
if (!retry)
ATAPIReadBlks2(bdev,cd_buf,blk2/spc,n,TRUE,0);
if (bdev->flags & BDF_READ_CACHE)
DskCacheAdd(p,cd_buf,blk2,n*spc);
MemCpy(buf,cd_buf+(blk-blk2)<<BLK_SIZE_BITS,cnt<<BLK_SIZE_BITS);
}
Free(cd_buf);
}
U0 ATARBlks(CPrt *p,U8 *buf, I64 blk, I64 cnt)
{
I64 n;
CBlkDev *bdev=p->bdev;
BlkDevChk(bdev);
while (cnt>0) {
n=cnt;
if (n>bdev->max_reads)
n=bdev->max_reads;
if (bdev->type==BDT_ATAPI)
ATAPIReadBlks(bdev,buf,blk,n);
else
ATAReadBlks(bdev,buf,blk,n);
buf+=n<<BLK_SIZE_BITS;
blk+=n;
cnt-=n;
}
}
//This is for low level disk access
//Call WBlks() instead
U0 ATAWriteBlks(CBlkDev *bdev,U8 *buf, I64 blk, I64 cnt)
{
I64 i,U32s_avail,sects_avail,retries=3;
F64 timeout;
Bool unlock=BlkDevLock(bdev);
retry:
ATABlkSelect(bdev,blk,cnt);
if (bdev->flags&BDF_EXT_SIZE)
ATACmd(bdev,ATA_WRITE_MULTI_EXT);
else
ATACmd(bdev,ATA_WRITE_MULTI);
bdev->flags|=BDF_LAST_WAS_WRITE;
while (cnt>0) {
timeout=tS+1.0;
while (TRUE) {
i=InU8(bdev->base0+ATAR0_STAT);
if (!(i & ATAS_DRDY)||!(i & ATAS_DRQ)) {
Yield;
} else
break;
if (/* i&ATAS_ERR||*/ tS>timeout) {
if (retries--) {
ATAWaitNotBUSY(bdev,0);
goto retry;
} else
throw(EXCEPT_BLKDEV,7);
}
}
sects_avail=1;
U32s_avail=sects_avail<<BLK_SIZE_BITS>>2;
RepOutU32(buf,U32s_avail,bdev->base0+ATAR0_DATA);
buf+=U32s_avail<<2;
cnt-=sects_avail;
retries=3;
}
ATAWaitNotBUSY(bdev,0);
if (unlock) BlkDevUnlock(bdev);
}
Bool ATAPISync(CBlkDev *bdev)
{
Bool okay=TRUE;
if (!ATAWaitNotBUSY(bdev,0))
okay=FALSE;
else {
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_LCYL,0);
OutU8(bdev->base0+ATAR0_HCYL,0);
ATACmd(bdev,ATA_PACKET);
ATAPIWritePktWord(bdev,0x3500); //Sync
ATAPIWritePktWord(bdev,0x0000);
ATAPIWritePktWord(bdev,0x0000);
ATAPIWritePktWord(bdev,0x0000);
ATAPIWritePktWord(bdev,0x0000);
ATAPIWritePktWord(bdev,0x0000);
if (!ATAWaitNotBUSY(bdev,0))
okay=FALSE;
}
return okay;
}
U0 ATAPIClose(CBlkDev *bdev,I64 close_field=0x200,I64 track=0)
{
//0x200 CD/DVD part 1
//0x300 DVD part 2
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_LCYL,0);
OutU8(bdev->base0+ATAR0_HCYL,0);
ATACmd(bdev,ATA_PACKET);
ATAPIWritePktWord(bdev,0x5B00); //Close
ATAPIWritePktWord(bdev,close_field);
ATAPIWritePktWord(bdev,track);
ATAPIWritePktWord(bdev,0x0000);
ATAPIWritePktWord(bdev,0x0000);
ATAPIWritePktWord(bdev,0x0000);
ATAWaitNotBUSY(bdev,0);
}
U0 ATAPIWriteBlks(CBlkDev *bdev,U8 *buf, I64 native_blk, I64 cnt)
{
I64 U32s_avail;
U8 *buf2;
ATAWaitNotBUSY(bdev,0);
ATAPISeek(bdev,native_blk);
OutU8(bdev->base0+ATAR0_FEAT,0);
OutU8(bdev->base0+ATAR0_LCYL,bdev->blk_size);
OutU8(bdev->base0+ATAR0_HCYL,bdev->blk_size.u8[1]);
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_CMD,ATA_PACKET);
ATAPIWritePktWord(bdev,0x0400); //FMT
ATAPIWritePktWord(bdev,native_blk.u16[1]);
ATAPIWritePktWord(bdev,native_blk);
ATAPIWritePktWord(bdev,cnt.u16[1]);
ATAPIWritePktWord(bdev,cnt);
ATAPIWritePktWord(bdev,0x0000);
bdev->flags|=BDF_LAST_WAS_WRITE;
ATAWaitNotBUSY(bdev,0);
ATAPISeek(bdev,native_blk);
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_LCYL,bdev->blk_size);
OutU8(bdev->base0+ATAR0_HCYL,bdev->blk_size.u8[1]);
ATACmd(bdev,ATA_PACKET);
ATAPIWritePktWord(bdev,0xAA00); //Write
ATAPIWritePktWord(bdev,native_blk.u16[1]);
ATAPIWritePktWord(bdev,native_blk);
ATAPIWritePktWord(bdev,cnt.u16[1]);
ATAPIWritePktWord(bdev,cnt);
ATAPIWritePktWord(bdev,0x0000);
buf2=buf+bdev->blk_size*cnt;
while (buf<buf2) {
ATAWaitDRQ(bdev,0);
U32s_avail=(InU8(bdev->base0+ATAR0_HCYL)<<8+InU8(bdev->base0+ATAR0_LCYL))>>2;
if (buf+U32s_avail<<2>buf2)
U32s_avail=(buf2-buf)>>2;
if (U32s_avail) {
RepOutU32(buf,U32s_avail,bdev->base0+ATAR0_DATA);
buf+=U32s_avail<<2;
sys_dsk_writes+=U32s_avail>>(BLK_SIZE_BITS-2);
}
}
ATAWaitNotBUSY(bdev,0);
}
U0 ATAWBlks(CPrt *p,U8 *buf, I64 blk, I64 cnt)
{
I64 n,spc;
CBlkDev *bdev=p->bdev;
Bool unlock;
BlkDevChk(bdev);
spc=bdev->blk_size>>BLK_SIZE_BITS;
if (bdev->type==BDT_ATAPI) {
unlock=BlkDevLock(bdev);
ATAPIWaitReady(bdev,0);
}
while (cnt>0) {
n=cnt;
if (n>bdev->max_writes)
n=bdev->max_writes;
if (bdev->type==BDT_ATAPI)
ATAPIWriteBlks(bdev,buf,blk/spc,(n+spc-1)/spc);
else
ATAWriteBlks(bdev,buf,blk,n);
buf+=n<<BLK_SIZE_BITS;
blk+=n;
cnt-=n;
sys_dsk_writes+=n;
}
if (bdev->type==BDT_ATAPI) {
ATAPISync(bdev);
// ATAPIStartStop(bdev,FALSE,0);
if (unlock) BlkDevUnlock(bdev);
}
}
+361
View File
@@ -0,0 +1,361 @@
U0 SetBlkDevLockFwding(CBlkDev *bdev)
{
CBlkDev *bd1;
I64 i;
switch (bdev->type) {
case BDT_RAM:
break;
case BDT_ATA:
case BDT_ATAPI:
for (i=0;i<num_blkdevs;i++) {
bd1=&sys_blkdevs[i];
if (bdev!=bd1 && (bd1->type==BDT_ATAPI || bd1->type==BDT_ATA) &&
bd1->base0==bdev->base0) {
bdev->lock_fwding=bd1;
break;
}
}
break;
case BDT_NON_NATIVE_FILE:
bdev->lock_fwding=Drv2BlkDev(bdev->non_native_drv);
break;
}
}
I64 BlkDevAdd(CBlkDev *bdev,Bool one_prt)
{
I64 i,j,ext_base,num_prt,offset;
CPrt *p;
CBootStruct br;
CMasterBoot mbr;
bdev->bd_signature=BD_SIGNATURE_VAL;
num_prt=bdev->drv_let_base-'A';
p=&sys_prts[num_prt];
MemSet(p,0,sizeof(CPrt));
p->drv_let=num_prt+'A';
p->pt_signature=PRT_SIGNATURE_VAL;
p->bdev=bdev;
p->size=bdev->max_blk+1;
switch (bdev->type) {
case BDT_RAM:
p->type=PT_NATIVE;
p->rblks=&RAMRBlks;
p->wblks=&RAMWBlks;
num_prt++;
//This is to force creation of a RAM
//drive during boot, so it is probably
//MAlloced to the same addr and can
//be assumed to be already formatted.
//If this line is removed, RAM Drives
//will be allocated on a just-in-time
//basis.
BlkDevInit(bdev);
break;
case BDT_ATA:
BlkDevInit(bdev);
if (one_prt) {
p->type=PT_NATIVE;
p->rblks=&ATARBlks;
p->wblks=&ATAWBlks;
p->size=bdev->max_blk+1;
num_prt++;
//The following read is a test read.
//if it hangs, the drive is not supported.
ATAReadBlks(bdev,&mbr,0,1);
break;
}
offset=0;
ext_base=INVALID_CLUSTER;
while (TRUE) {
ATAReadBlks(bdev,&mbr,offset,1);
if (mbr.signature!=0xAA55)
break;
j=-1;
for (i=0;i<4;i++) {
if (mbr.p[i].type) {
p=&sys_prts[num_prt];
MemSet(p,0,sizeof(CPrt));
p->drv_let=num_prt+'A';
p->pt_signature=PRT_SIGNATURE_VAL;
p->bdev=bdev;
p->rblks=&ATARBlks;
p->wblks=&ATAWBlks;
p->offset=mbr.p[i].offset+offset;
p->size =mbr.p[i].size;
p->type=PT_NULL;
switch (mbr.p[i].type) {
case MBR_PT_NATIVE:
p->type=PT_NATIVE;
NativeFSPrtInit(p);
num_prt++;
break;
case MBR_PT_FAT32a:
case MBR_PT_FAT32b:
case MBR_PT_FAT32c:
case MBR_PT_FAT32d:
case MBR_PT_FAT32e:
case MBR_PT_FAT32f:
ATAReadBlks(bdev,&br,p->offset,1);
if (br.signature==MBR_PT_NATIVE) {
p->type=PT_NATIVE;
NativeFSPrtInit(p);
} else {
p->type=PT_FAT32;
FAT32PrtInit(p);
}
num_prt++;
break;
case MBR_PT_NTFS:
p->type=PT_NTFS;
num_prt++;
break;
case 5:
case 15:
j=i;
break;
default:
p->type=PT_UNKNOWN;
num_prt++;
}
}
}
if (j<0)
break;
if (!mbr.p[j].offset)
break;
if (ext_base==INVALID_CLUSTER) {
offset=mbr.p[j].offset;
ext_base=offset;
} else
offset=mbr.p[j].offset+ext_base;
}
break;
case BDT_ATAPI:
p->type=PT_ISO9660; //Start with this
p->rblks=&ATARBlks;
p->wblks=&ATAWBlks;
p->size =0;
num_prt++;
break;
case BDT_NON_NATIVE_FILE:
p->type=PT_NATIVE;
p->offset=bdev->non_native_offset;
p->rblks=&NonNativeFileRBlks;
p->wblks=&NonNativeFileWBlks;
if (bdev->flags & BDF_FMT)
p->size=bdev->max_blk-bdev->min_blk+1;
num_prt++;
break;
}
SetBlkDevLockFwding(bdev);
return num_prt-(bdev->drv_let_base-'A');
}
Bool DrvEnable(U8 drv_let,Bool val)
{//This can be used to unmount a drive or remount,
//but not mount the first time.
CPrt *p;
Bool result=FALSE;
try {
p=Drv2Prt(drv_let);
result=!LBEqu(&p->type,PTf_DISABLE,!val);
} catch {
Fs->ignore_except=TRUE;
}
return result;
}
CATARep *ATARepFind(CATARep *root,I64 num)
{
CATARep *tempha=root;
while (tempha) {
if (tempha->num==num)
return tempha;
tempha=tempha->next;
}
return tempha;
}
U0 Mount(Bool repartition=FALSE)
{
CBlkDev *bdev;
I64 drv_let_base,drv_let,type,k,num_hints;
U8 buf[32],buf2[128],buf3[128];
Bool add;
CATARep *root,*tempha;
do {
PrtRep;
PutDefine("ST_MOUNT_BASE_LET");
drv_let_base=ToUpper(GetChar)-'A';
NewLine;
if (0<=drv_let_base<NUM_PRTS) {
PutDefine("ST_MOUNT_DRV_TYPE");
type=GetChar-'0';
NewLine;
k=0;
if (type==BDT_ATA || type==BDT_ATAPI) {
num_hints=CallExtStr("ATARep",TRUE,&root);
do {
if (num_hints)
PutDefine("ST_MOUNT_BASE0_HINT");
else
PutDefine("ST_MOUNT_BASE0");
GetS(buf2,128);
} while (!A2I(buf2));
if (1<=A2I(buf2)<=num_hints) {
tempha=ATARepFind(root,A2I(buf2));
SPrintF(buf2,"0x%X",tempha->base0);
SPrintF(buf3,"0x%X",tempha->base1);
k=tempha->unit;
} else {
if (type==BDT_ATAPI)
StrCpy(buf3,"0");
else
do {
PutDefine("ST_MOUNT_BASE1");
GetS(buf3,128);
} while (!A2I(buf3));
do {
PutDefine("ST_MOUNT_UNIT");
k=GetChar-'0';
} while (!(0<=k<=1));
NewLine;
}
LinkedListDel(root);
}
if (type==BDT_NON_NATIVE_FILE) {
PutDefine("ST_MOUNT_NON_NATIVE_LET");
drv_let=GetChar;
NewLine;
PutDefine("ST_INCLUDE_0X");
PutDefine("ST_MOUNT_NON_NATIVE_BLK");
GetS(buf2,128);
}
if (type==BDT_RAM) {
PutDefine("ST_MOUNT_BLKS");
GetS(buf,32);
}
if (BDT_NULL<type<=BDT_NON_NATIVE_FILE &&
0<=k<=1) {
bdev=&sys_blkdevs[num_blkdevs++];
bdev->drv_let_base=drv_let_base+'A';
bdev->unit=k;
bdev->type=type;
if (type==BDT_ATAPI)
bdev->flags=BDF_REMOVABLE;
else
bdev->flags=0;
if (type!=BDT_RAM)
bdev->flags|=BDF_READ_CACHE;
if (type==BDT_ATAPI) {
bdev->blk_size=CD_BLK_SIZE;
bdev->flags|=BDF_READ_ONLY;
} else
bdev->blk_size=BLK_SIZE;
if (type==BDT_RAM)
bdev->max_blk=A2I(buf)-1;
else
bdev->max_blk=0xEFFFFFFF;
if (type==BDT_NON_NATIVE_FILE) {
bdev->non_native_drv=drv_let;
bdev->non_native_offset=A2I(buf2);
} else {
bdev->non_native_drv=0;
bdev->non_native_offset=0;
}
if (type==BDT_ATA ||
type==BDT_ATAPI) {
bdev->base0=A2I(buf2);
bdev->base1=A2I(buf3);
}
add=TRUE;
if (type==BDT_ATA && repartition) {
PutDefine("ST_MOUNT_FMT_WHOLE_DRV");
if (YorN) {
if (!BlkDevAdd(bdev,TRUE))
PutDefine("ST_FAILED");
else
CallExtStr("PrtDsk",bdev->drv_let_base);
add=FALSE;
}
}
if (add && !BlkDevAdd(bdev,FALSE))
PutDefine("ST_FAILED");
} else
PutDefine("ST_FAILED");
}
} while (0<=drv_let_base<NUM_PRTS);
}
I64 SysPmtI64()
{
U8 st[136];
StrCpy(st,"0x");
GetS(st+2,134,FALSE);
return A2I(st);
}
Bool PmtBaseUnit(CBlkDev *bdev)
{
I64 ch;
Bool probe;
" SparrowOS\n\n\n";
#exe {
if (osmain_cfg->opts[CFG_DONT_PROBE])
StreamPutS("probe=FALSE;");
else
StreamPutS("probe=TRUE;");
};
if (!probe || !BootCdProbeAll(bdev)) {
"\nThis is not a product registration. SparrowOS\n"
"needs the I/O port numbers for the CD-ROM.\n"
"Retry the ports above or check Windows\n"
"system information under I/O ports for\n"
"'IDE', 'ATA' or 'SATA'.\n\n"
"\nEnter 4-digit hex I/O Port number.\n"
"CD-ROM I/O Port Base0: 0x";
bdev->base0=SysPmtI64;
bdev->base1=0;
"\nUnit (0 or 1): ";
do ch=GetChar(NULL,FALSE);
while (!('0'<=ch<='1'));
'' ch;
bdev->unit=ch-'0';
return TRUE;
}
return FALSE;
}
U0 BlkDevsInitAll()
{
CBlkDev *bdev;
I64 i;
num_blkdevs=0;
sys_blkdevs=ACAlloc(sizeof(CBlkDev)*NUM_BLKDEVS);
sys_prts=ACAlloc(sizeof(CPrt)*NUM_PRTS);
for (i=0;i<NUM_PRTS;i++)
drv_to_prt[i]=&sys_prts[i];
sys_raw_dc_col=0;
#exe {
StreamPutS("#exe {OptOff(OPTf_WARN_PAREN);}");
StreamDoc(osmain_cfg->add_dev);
StreamPutS("#exe {OptOn(OPTf_WARN_PAREN);}");
};
PrtRep;
}
+281
View File
@@ -0,0 +1,281 @@
U0 FAllocFile(CFile *f,I64 cnt,Bool contiguous)
{
CPrt *fp=f->p;
CFileAccess *fa=FileAccessNew(f->de.full_name);
f->de.cluster=ClusersAlloc(fp,0,(cnt+fp->spc-1)/fp->spc,contiguous);
f->de.size=cnt<<BLK_SIZE_BITS;
f->de.expanded_size=f->de.size;
if (fa) {
CDirNew(fa->p,Fs->cur_dir,&f->de,TRUE);
FileAccessDel(fa);
}
f->flags&=~FF_NEW_FILE;
}
I64 FSize(CFile *f)
{
if (f)
return f->de.size;
else
return 0;
}
U0 FSync(CFile *f)
{
if (f->flags & FF_BUF_DIRTY) {
WClusters(f->p,f->cluster_buf,f->cluster,1);
f->flags&=~FF_BUF_DIRTY;
}
}
CFile *FOpen(U8 *filename,U8 *flags,I64 cnt=0)
{ //allows flags "r","w","w+" and "c" (contiguous)
CFile *f=CAlloc(sizeof(CFile));
CFileAccess *fa;
U8 *full_name,*full_name2;
Bool contiguous=StrOcc(flags,'c');
f->cluster=INVALID_CLUSTER;
f->fblk_num=0;
if (cnt>0)
f->max_blk=cnt-1;
else
f->max_blk=MAX_I64;
f->file_cluster_num=INVALID_CLUSTER;
full_name2=FileNameAbs(filename);
full_name=AStrNew(full_name2);
Free(full_name2);
f->p=Drv2Prt(*full_name);
if (f->p->type==PT_NATIVE)
contiguous=TRUE;
if (contiguous) {
f->flags|=FF_CONTIGUOUS;
if (f->p->type!=PT_NATIVE) {
if (!(FileAttr(filename) & _ATTR_CONTIGUOUS))
throw(EXCEPT_FILE,2);
}
}
f->cluster_buf=CAlloc(f->p->spc<<BLK_SIZE_BITS);
if (StrOcc(flags,'w')) {
f->flags=f->flags|FF_WRITE|FF_NEEDS_WRITE;
if (StrOcc(flags,'+')) {
if (FileFind(full_name,&f->de,FALSE,TRUE)) {
f->de.full_name=full_name;
if (contiguous)
f->max_blk=(FSize(f)+BLK_SIZE-1)>>BLK_SIZE_BITS-1;
return f;
}
} else
Del(full_name,FALSE);
f->de.full_name=full_name;
f->flags|=FF_NEW_FILE;
fa=FileAccessNew(full_name);
if (fa) {
StrCpy(f->de.name,fa->mask);
FileAccessDel(fa);
if (cnt>0)
FAllocFile(f,cnt,contiguous);
if (!contiguous || cnt>0)
return f;
}
} else {
if (FileFind(full_name,&f->de,FALSE,TRUE)) {
f->de.full_name=full_name;
f->max_blk=(FSize(f)+BLK_SIZE-1)>>BLK_SIZE_BITS-1;
return f;
}
}
Free(f->cluster_buf);
Free(full_name);
Free(f);
return NULL;
}
U0 FClose(CFile *f)
{
CFileAccess *fa;
if (f) {
FSync(f);
if (f->flags & FF_NEEDS_WRITE) {
fa=FileAccessNew(f->de.full_name);
if (fa) {
if (!(f->flags & FF_USE_OLD_DATETIME))
f->de.datetime=GetCurTimeCDate;
if (f->flags & FF_NEW_FILE)
CDirNew(fa->p,Fs->cur_dir,&f->de,TRUE);
else
CDirNew(fa->p,Fs->cur_dir,&f->de,FALSE);
FileAccessDel(fa);
} else
throw(EXCEPT_FILE,1);
}
Free(f->cluster_buf);
Free(f->de.full_name);
Free(f);
}
}
I64 FSetCluster(CFile *f,I64 c,I64 blk,Bool read)
{
CPrt *p=f->p;
I64 i;
if (f->cluster!=c) {
if (f->flags & FF_BUF_DIRTY) {
i=p->spc;
if (f->max_blk!=MAX_I64) {
i=f->max_blk+1-f->file_cluster_num*p->spc;
if (i>p->spc)
i=p->spc;
}
WClustersBlks(p,f->cluster_buf,f->cluster,i);
f->flags=f->flags & ~FF_BUF_DIRTY;
}
f->cluster=c;
f->file_cluster_num=blk/p->spc;
if (read) {
i=p->spc;
if (f->max_blk!=MAX_I64) {
i=f->max_blk+1-f->file_cluster_num*p->spc;
if (i>p->spc)
i=p->spc;
}
c=RClustersBlks(p,f->cluster_buf,c,i);
}
}
return c;
}
Bool FRBlks(CFile *f,U8 *buf,I64 blk=FFB_NEXT_BLK,I64 cnt=1)
{
CPrt *p=f->p;
I64 spc=p->spc,i,j,c=f->de.cluster;
if (!f || !p) return FALSE;
if (blk==FFB_NEXT_BLK)
blk=f->fblk_num;
if (blk+cnt-1>f->max_blk)
return FALSE;
if (cnt<=0) return TRUE;
if (f->flags & FF_CONTIGUOUS) {
RBlks(p,buf,Cluster2Blk(p,c)+blk,cnt);
blk+=cnt;
} else {
i=blk/spc;
if (0<=f->file_cluster_num<=i) {
c=f->cluster;
i-=f->file_cluster_num;
}
if (i>0)
c=ClusterNumNext(p,c,i);
if (i=blk%spc) {
c=FSetCluster(f,c,blk,TRUE);
j= cnt<spc-i ? cnt:spc-i;
MemCpy(buf,f->cluster_buf+i<<BLK_SIZE_BITS,j<<BLK_SIZE_BITS);
buf+=j<<BLK_SIZE_BITS;
cnt-=j;
blk+=j;
}
while (cnt>=spc) {
c=FSetCluster(f,c,blk,TRUE);
MemCpy(buf,f->cluster_buf,spc<<BLK_SIZE_BITS);
buf+=spc<<BLK_SIZE_BITS;
cnt-=spc;
blk+=spc;
}
if (cnt>0) {
c=FSetCluster(f,c,blk,TRUE);
MemCpy(buf,f->cluster_buf,cnt<<BLK_SIZE_BITS);
buf+=cnt<<BLK_SIZE_BITS;
blk+=cnt;
}
}
f->fblk_num=blk;
return TRUE;
}
Bool FWBlks(CFile *f,U8 *buf,I64 blk=FFB_NEXT_BLK,I64 cnt=1)
{
CPrt *p=f->p;
I64 spc=p->spc,i,j,c=f->de.cluster,c1;
if (!f || !p) return FALSE;
if (blk==FFB_NEXT_BLK)
blk=f->fblk_num;
if (blk+cnt-1>f->max_blk)
return FALSE;
if (!(f->flags & FF_WRITE))
return FALSE;
if (cnt<=0) return TRUE;
if (f->flags & FF_CONTIGUOUS) {
WBlks(p,buf,Cluster2Blk(p,c)+blk,cnt);
blk+=cnt;
} else {
if (!c) {
c=ClusersAlloc(p,0,1,FALSE);
f->file_cluster_num=0;
f->cluster=c;
f->de.cluster=c;
f->flags|=FF_NEEDS_WRITE|FF_NEW_FILE;
}
i=blk/spc;
if (0<=f->file_cluster_num<=i) {
c=f->cluster;
i-=f->file_cluster_num;
}
while (i>0) {
c1=c;
c=ClusterNumNext(p,c1,1);
if (c==INVALID_CLUSTER) {
c=ClusersAlloc(p,c1,i,FALSE);
if (i>1)
c=ClusterNumNext(p,c,i-1);
break;
} else
i--;
}
if (i=blk%spc) {
FSetCluster(f,c,blk,TRUE);
j=cnt<spc-i ? cnt:spc-i;
MemCpy(f->cluster_buf+BLK_SIZE*i,buf,j<<BLK_SIZE_BITS);
f->flags|=FF_BUF_DIRTY;
buf+=j<<BLK_SIZE_BITS;
cnt-=j;
blk+=j;
if (cnt>0) {
c1=c;
c=ClusterNumNext(p,c1,1);
if (c==INVALID_CLUSTER)
c=ClusersAlloc(p,c1,1,FALSE);
}
}
while (cnt>=spc) {
FSetCluster(f,c,blk,FALSE);
MemCpy(f->cluster_buf,buf,spc<<BLK_SIZE_BITS);
f->flags|=FF_BUF_DIRTY;
buf+=spc<<BLK_SIZE_BITS;
cnt-=spc;
blk+=spc;
if (cnt>0) {
c1=c;
c=ClusterNumNext(p,c1,1);
if (c==INVALID_CLUSTER)
c=ClusersAlloc(p,c1,1,FALSE);
}
}
if (cnt>0) {
FSetCluster(f,c,blk,TRUE);
MemCpy(f->cluster_buf,buf,cnt<<BLK_SIZE_BITS);
f->flags|=FF_BUF_DIRTY;
buf+=cnt<<BLK_SIZE_BITS;
blk+=cnt;
}
if (f->de.size<blk<<BLK_SIZE_BITS)
f->de.size=blk<<BLK_SIZE_BITS;
if (f->de.expanded_size<blk<<BLK_SIZE_BITS)
f->de.expanded_size=blk<<BLK_SIZE_BITS;
}
f->fblk_num=blk;
return TRUE;
}
+177
View File
@@ -0,0 +1,177 @@
U0 DskCacheInit(I64 size_in_U8s)
{
CCacheBlk *tempc;
I64 i,cnt;
while (LBts(&sys_semas[SYS_SEMA_DSK_CACHE],0))
Yield;
Free(sys_dsk_cache_ctrl);
Free(sys_dsk_cache_base);
Free(sys_dsk_cache_hash_table);
if (size_in_U8s<0x2000) {
sys_dsk_cache_ctrl=NULL;
sys_dsk_cache_base=NULL;
sys_dsk_cache_hash_table=NULL;
} else {
sys_dsk_cache_ctrl=ACAlloc(offset(CCacheBlk.body));
sys_dsk_cache_base=AMAlloc(size_in_U8s);
QueInit(sys_dsk_cache_ctrl);
cnt=MSize(sys_dsk_cache_base)/sizeof(CCacheBlk);
sys_dsk_cache_size=cnt*BLK_SIZE;
for (i=0;i<cnt;i++) {
tempc=sys_dsk_cache_base+i;
QueIns(tempc,sys_dsk_cache_ctrl->last_lru);
tempc->next_hash=tempc->last_hash=tempc;
tempc->p=NULL;
tempc->blk=0;
}
sys_dsk_cache_hash_table=AMAlloc(DSK_CACHE_HASH_SIZE*sizeof(U8 *)*2);
for (i=0;i<DSK_CACHE_HASH_SIZE;i++) {
tempc=sys_dsk_cache_hash_table(U8 *)+i*sizeof(U8 *)*2-offset(CCacheBlk.next_hash);
tempc->next_hash=tempc->last_hash=tempc;
}
}
LBtr(&sys_semas[SYS_SEMA_DSK_CACHE],0);
}
I64 DskCacheHash(I64 blk)
{
I64 i=blk & (DSK_CACHE_HASH_SIZE-1);
return sys_dsk_cache_hash_table(U8 *)+i<<4-offset(CCacheBlk.next_hash);
}
U0 DskCacheQueRem(CCacheBlk *tempc)
{
QueRem(tempc);
tempc->next_hash->last_hash=tempc->last_hash;
tempc->last_hash->next_hash=tempc->next_hash;
}
U0 DskCacheQueIns(CCacheBlk *tempc)
{
CCacheBlk *temp_n,*temp_l;
QueIns(tempc,sys_dsk_cache_ctrl->last_lru);
temp_l=DskCacheHash(tempc->blk);
temp_n=temp_l->next_hash;
tempc->last_hash=temp_l;
tempc->next_hash=temp_n;
temp_l->next_hash=temp_n->last_hash=tempc;
}
CCacheBlk *DskCacheFind(CPrt *p,I64 blk)
{
CCacheBlk *tempc,*tempc1=DskCacheHash(blk);
tempc=tempc1->next_hash;
while (tempc!=tempc1) {
if (tempc->p==p && tempc->blk==blk)
return tempc;
tempc=tempc->next_hash;
}
return NULL;
}
U0 DskCacheAdd(CPrt *p,U8 *buf, I64 blk, I64 cnt)
{
CCacheBlk *tempc;
if (sys_dsk_cache_base) {
while (LBts(&sys_semas[SYS_SEMA_DSK_CACHE],0))
Yield;
while (cnt-->0) {
if (!(tempc=DskCacheFind(p,blk)))
tempc=sys_dsk_cache_ctrl->next_lru;
DskCacheQueRem(tempc);
MemCpy(&tempc->body,buf,BLK_SIZE);
tempc->p=p;
tempc->blk=blk;
DskCacheQueIns(tempc);
blk++;
buf+=BLK_SIZE;
}
LBtr(&sys_semas[SYS_SEMA_DSK_CACHE],0);
}
}
U0 DskCacheInvalidate2(CPrt *p)
{
CCacheBlk *tempc,*tempc1;
if (sys_dsk_cache_base) {
while (LBts(&sys_semas[SYS_SEMA_DSK_CACHE],0))
Yield;
tempc=sys_dsk_cache_ctrl->last_lru;
while (tempc!=sys_dsk_cache_ctrl) {
tempc1=tempc->last_lru;
if (tempc->p==p) {
DskCacheQueRem(tempc);
tempc->p=NULL;
tempc->blk=0;
tempc->next_hash=tempc->last_hash=tempc;
QueIns(tempc,sys_dsk_cache_ctrl->last_lru);
}
tempc=tempc1;
}
LBtr(&sys_semas[SYS_SEMA_DSK_CACHE],0);
}
}
U0 RCache(CPrt *p,U8 **_buf, I64 *_blk, I64 *_cnt)
{
CCacheBlk *tempc;
if (sys_dsk_cache_base) {
while (LBts(&sys_semas[SYS_SEMA_DSK_CACHE],0))
Yield;
//fetch leading blks from cache
while (*_cnt>0) {
if (tempc=DskCacheFind(p,*_blk)) {
MemCpy(*_buf,&tempc->body,BLK_SIZE);
*_cnt-=1;
*_buf+=BLK_SIZE;
*_blk+=1;
} else
break;
}
//fetch trailing blks from cache
while (*_cnt>0) {
if (tempc=DskCacheFind(p,*_blk+*_cnt-1)) {
MemCpy(*_buf+(*_cnt-1)<<BLK_SIZE_BITS,&tempc->body,BLK_SIZE);
*_cnt-=1;
} else
break;
}
LBtr(&sys_semas[SYS_SEMA_DSK_CACHE],0);
}
}
Bool RAMRBlks(CPrt *p,U8 *buf,I64 blk,I64 cnt)
{
CBlkDev *bdev=p->bdev;
BlkDevChk(bdev);
MemCpy(buf,bdev->RAM_dsk+blk<<BLK_SIZE_BITS,cnt<<BLK_SIZE_BITS);
return TRUE;
}
Bool RAMWBlks(CPrt *p,U8 *buf,I64 blk,I64 cnt)
{
CBlkDev *bdev=p->bdev;
BlkDevChk(bdev);
MemCpy(bdev->RAM_dsk+blk<<BLK_SIZE_BITS,buf,cnt<<BLK_SIZE_BITS);
return TRUE;
}
Bool NonNativeFileRBlks(CPrt *p,U8 *buf,I64 blk,I64 cnt)
{
CBlkDev *bdev=p->bdev;
CPrt *bp=Drv2Prt(bdev->non_native_drv);
BlkDevChk(bdev);
return (*bp->rblks)(bp,buf,blk,cnt);
}
Bool NonNativeFileWBlks(CPrt *p,U8 *buf,I64 blk,I64 cnt)
{
CBlkDev *bdev=p->bdev;
CPrt *bp=Drv2Prt(bdev->non_native_drv);
BlkDevChk(bdev);
return (*bp->wblks)(bp,buf,blk,cnt);
}
+268
View File
@@ -0,0 +1,268 @@
Bool CDirNew(CPrt *p,U8 *cur_dir,CDirEntry *tempm,Bool free_old_chain=TRUE)
{
switch (p->type) {
case PT_NATIVE:
return NativeFSDirNew(p,cur_dir,tempm,free_old_chain);
case PT_FAT32:
return FAT32DirNew(p,cur_dir,tempm,free_old_chain);
case PT_ISO9660:
PutDefineErr("ST_NOT_WRITABLE");
return FALSE;
default:
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
return FALSE;
}
}
U0 CDirEntryDel(CDirEntry *tempm)
{ //Doesn't Free user_data
if (tempm) {
Free(tempm->full_name);
Free(tempm);
}
}
U0 CDirEntryDel2(CDirEntry *tempm)
{ //Frees user_data
if (tempm) {
Free(tempm->full_name);
Free(tempm->user_data);
Free(tempm);
}
}
U0 CDirListDel(CDirEntry *tempm)
{ //Doesn't Free user_data
CDirEntry *tempm2;
while (tempm) {
tempm2=tempm->next;
if (tempm->sub)
CDirListDel(tempm->sub);
CDirEntryDel(tempm);
tempm=tempm2;
}
}
U0 CDirListDel2(CDirEntry *tempm)
{ //Frees user_data
CDirEntry *tempm2;
while (tempm) {
tempm2=tempm->next;
if (tempm->sub)
CDirListDel2(tempm->sub);
CDirEntryDel2(tempm);
tempm=tempm2;
}
}
I64 CDirEntryCompare(CDirEntry *e1,CDirEntry *e2)
{
U8 buf1[CDIR_FILENAME_LEN],buf2[CDIR_FILENAME_LEN],
buf3[CDIR_FILENAME_LEN],buf4[CDIR_FILENAME_LEN];
I64 d1=0,d2=0;
if (e1->attr & _ATTR_DIR)
d1=1;
if (e2->attr & _ATTR_DIR)
d2=1;
if (d1!=d2)
return d2-d1;
else {
StrCpy(buf1,e1->name);
StrCpy(buf2,e2->name);
FileExtRem(buf1,buf3);
FileExtRem(buf2,buf4);
if (d1=StrCmp(buf3,buf4))
return d1;
return StrCmp(buf1,buf2);
}
}
U0 CDirFilesSort(CDirEntry **_tempm)
{
I64 i,cnt=0;
CDirEntry *tempm=*_tempm,*tempm1,**sort_buf;
if (tempm) {
tempm1=tempm;
while (tempm1) {
cnt++;
tempm1=tempm1->next;
}
if (cnt>1) {
sort_buf=MAlloc(cnt*sizeof(U8 *));
i=0;
tempm1=tempm;
while (tempm1) {
sort_buf[i++]=tempm1;
tempm1=tempm1->next;
}
QSortI64(sort_buf,cnt,&CDirEntryCompare);
tempm=sort_buf[0];
*_tempm=tempm;
for (i=0;i<cnt-1;i++) {
tempm1=sort_buf[i];
tempm1->next=sort_buf[i+1];
}
tempm1=sort_buf[i];
tempm1->next=NULL;
Free(sort_buf);
tempm1=tempm;
while (tempm1) {
if (tempm1->sub)
CDirFilesSort(&tempm1->sub);
tempm1=tempm1->next;
}
} else
if (tempm->sub)
CDirFilesSort(&tempm->sub);
}
}
CDirEntry *CDirFilesFlatten(CDirEntry *tempm,CDirEntry **_result,I64 fuf_flags)
{ //returns last node
CDirEntry *tempm1;
Bool del;
if (tempm)
while (TRUE) {
tempm1=tempm->next;
if (!(tempm->attr&_ATTR_DIR)||!(fuf_flags&FUF_JUST_FILES)) {
_result=*_result=tempm;
del=FALSE;
} else
del=TRUE;
if (tempm->sub) {
_result=CDirFilesFlatten(tempm->sub,_result,fuf_flags);
tempm->sub=NULL;
}
if (del)
CDirEntryDel(tempm);
if (tempm1)
tempm=tempm1;
else
break;
}
*_result=NULL;
return _result;
}
CDirEntry *SysFilesFind(U8 *files_find_mask,I64 fuf_flags)
{
CPrt *p=Fs->cur_prt;
CDirEntry *result=NULL;
PrtChk(p);
switch (p->type) {
case PT_NATIVE:
result=NativeFSFilesFind(files_find_mask,fuf_flags);
break;
case PT_FAT32:
result=FAT32FilesFind(files_find_mask,fuf_flags);
break;
case PT_ISO9660:
result=ISO1FilesFind(files_find_mask,fuf_flags);
break;
default:
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
result=NULL;
}
if (result) {
CDirFilesSort(&result);
if (fuf_flags&(FUF_FLATTEN_TREE|FUF_JUST_FILES))
CDirFilesFlatten(result,&result,fuf_flags);
}
return result;
}
U0 PutFileLink(U8 *filename,I64 line=0,Bool plain_text=FALSE)
{
U8 *buf;
if (!filename) return;
if (IsRaw) {
if (line)
"%s,%04d",filename,line;
else
"" filename;
} else {
buf=FileNameAbs(filename);
if (plain_text) {
if (line)
"$$LK,\"%s,%04d\",\"PL:%s,%d\"$$",filename,line,buf,line;
else
"$$LK,\"%s\",\"PI:%s\"$$",filename,buf;
} else {
if (line)
"$$LK,\"%s,%04d\",\"FL:%s,%d\"$$",filename,line,buf,line;
else
"$$LK,\"%s\",\"FI:%s\"$$",filename,buf;
}
Free(buf);
}
}
U0 PutDirLink(U8 *dirname)
{
U8 *buf;
if (!dirname) return;
if (IsRaw)
"" dirname;
else {
buf=DirNameAbs(dirname);
"$$MA+A,\"%s\",\"Cd(\\\"%s\\\");Dir;\n\"$$",dirname,buf;
Free(buf);
}
}
U0 Dir2(U8 *files_find_mask,I64 fuf_flags,Bool full)
{
CDirEntry *tempm1=NULL,*tempm2;
U8 *st;
I64 csize=0xFFFF,esize=0xFFFF,c=0xFFFF;
tempm1=SysFilesFind(files_find_mask,fuf_flags);
if (!(st=CurDir))
PutDefine("ST_INVALID_DRV");
else {
if (tempm1) {
//Find max columns
tempm2=tempm1;
while (tempm2) {
if (tempm2->size>csize)
csize=tempm2->size;
if (tempm2->expanded_size>esize)
esize=tempm2->expanded_size;
if (tempm2->cluster>c)
c=tempm2->cluster;
tempm2=tempm2->next;
}
csize=Bsr(csize)/4+1;
esize=Bsr(esize)/4+1;
c=Bsr(c)/4+1;
"$$MA+A,\"Directory \",\"PopUpCd;Dir;\n\"$$ of %s\n",st;
if (full)
"__DATE__ __TIME__ %*ts %*ts %*ts\n",
csize,"SIZE",esize,"UNCMPSIZE",c,"CLUSTER";
else
"DATE_ TIME_ %*ts\n",csize,"SIZE";
while (tempm1) {
tempm2=tempm1->next;
if (full)
"%D %T %0*tX %0*tX %0*tX ",tempm1->datetime,tempm1->datetime,
csize,tempm1->size,esize,tempm1->expanded_size,
c, tempm1->cluster;
else
"%h1D %h1T %0*tX ",tempm1->datetime,tempm1->datetime,
csize,tempm1->size;
if (tempm1->attr & _ATTR_DIR)
PutDirLink(tempm1->name);
else
PutFileLink(tempm1->name);
NewLine;
CDirEntryDel(tempm1);
tempm1=tempm2;
}
} else
PutDefine("ST_NO_MATCHING_ENTRIES");
Free(st);
}
}
+379
View File
@@ -0,0 +1,379 @@
U8 *FileExtDot(U8 *src)
{
U8 ch;
while (ch=*src++)
if (ch=='.' && *src!='/' && *src!='.')
return src-1;
return NULL;
}
U8 *FileExtRem(U8 *src,U8 *dst=NULL)
{
U8 *ptr;
if (ptr=FileExtDot(src)) {
if (dst)
StrCpy(dst,ptr+1);
*ptr=0;
} else if (dst)
*dst=0;
return dst;
}
Bool IsDotZ(U8 *filename)
{
I64 i=StrLen(filename);
if (i>6 && filename[i-1]=='Z' && filename[i-2]=='.' && filename[i-6]=='.')
return TRUE;
else
return FALSE;
}
Bool IsDotC(U8 *filename)
{
I64 i=StrLen(filename);
if (i>6 && filename[i-1]=='C' && filename[i-2]=='.' && filename[i-6]=='.')
return TRUE;
else
return FALSE;
}
Bool IsTextFile(U8 *filename)
{
return FilesFindMatch(TEXT_FILE_MASK,filename);
}
Bool IsSrcFile(U8 *filename)
{
return FilesFindMatch(SRC_FILE_MASK,filename);
}
Bool FilesFindMatch(U8 *files_find_mask,U8 *filename,I64 fuf_flags=0)
{
U8 *st1=StrNew(files_find_mask),
*st2=MAlloc(StrLen(files_find_mask)+1);
Bool result=FALSE;
while (TRUE) {
StrFirstRem(st1,";",st2);
if (*st2) {
if (*st2=='~') {
if (WildCardMatch(st2+1,filename)) {
result=FALSE;
break;
}
} else {
if (WildCardMatch(st2,filename)) {
if (Bt(&fuf_flags,FUf_JUST_TEXT_FILES) && !IsTextFile(filename)) {
result=FALSE;
break;
} else if (Bt(&fuf_flags,FUf_JUST_SRC_FILES) && !IsSrcFile(filename)) {
result=FALSE;
break;
} else
result=TRUE;
}
}
} else
break;
}
Free(st1);
Free(st2);
return result;
}
U0 PrtChk(CPrt *p)
{
if (!p || p->pt_signature!=PRT_SIGNATURE_VAL)
throw(EXCEPT_PRT,4);
}
U8 Prt2Drv(CPrt *p=NULL)
{
if (!p)
p=Fs->cur_prt;
PrtChk(p);
return p->drv_let;
}
CPrt *Drv2Prt(U8 drv_let=0)
{
CPrt *p;
if (!drv_let)
p=Fs->cur_prt;
else if (drv_let==':')
p=dft_prt;
else
p=drv_to_prt[ToUpper(drv_let)-'A'];
PrtChk(p);
return p;
}
U0 BlkDevChk(CBlkDev *bdev)
{
if (!bdev || bdev->bd_signature!=BD_SIGNATURE_VAL)
throw(EXCEPT_BLKDEV,1);
if (bdev->type<=BDT_NULL || bdev->type>BDT_NON_NATIVE_FILE)
throw(EXCEPT_BLKDEV,2);
}
CBlkDev *Drv2BlkDev(U8 drv_let=0)
{
CPrt *p=Drv2Prt(drv_let);
CBlkDev *bdev=p->bdev;
BlkDevChk(bdev);
return bdev;
}
CBlkDev *Drv2BlkDevFwded(U8 drv_let=0)
{
CBlkDev *bdev=Drv2BlkDev(drv_let);
while (bdev && bdev->non_native_drv)
bdev=Drv2BlkDev(bdev->non_native_drv);
return bdev;
}
Bool IsDrvWritable(U8 drv_let=0)
{
CBlkDev *bdev=Drv2BlkDev(drv_let);
if (bdev->flags & BDF_READ_ONLY)
return FALSE;
else
return TRUE;
}
U8 *CurDir(CTask *task=NULL,CTask *mem_task=NULL)
{
U8 *st;
if (!task) task=Fs;
if (!task->cur_dir)
return NULL;
st=MAlloc(StrLen(task->cur_dir)+3,mem_task);
*st=Prt2Drv;
st[1]=':';
StrCpy(st+2,task->cur_dir);
return st;
}
U8 *DirNameAbs(U8 *_dirname)
{
I64 maxlen;
U8 drv[3],*cur_dir,*buf2,*buf3,*buf,*dirname,*temp_name;
if (!Fs->cur_dir || !*Fs->cur_dir)
return StrNew(_dirname);
dirname=MStrUtil(_dirname,
SUF_REM_LEADING|SUF_REM_TRAILING|SUF_REM_CTRL_CHARS);
temp_name=dirname;
*drv=Prt2Drv;
drv[1]=':';
drv[2]=0;
if (*dirname && dirname[1]==':') {
if (*dirname==':')
*drv=dft_drv;
else
*drv=*dirname;
dirname=dirname+2;
cur_dir=StrNew("/");
} else
cur_dir=StrNew(Fs->cur_dir);
if (*dirname=='/') {
Free(cur_dir);
cur_dir=StrNew("/");
dirname++;
}
buf2=StrNew(dirname);
maxlen=StrLen(cur_dir)+1+StrLen(buf2)+1;
buf3=MAlloc(maxlen);
buf =MAlloc(maxlen);
StrCpy(buf3,cur_dir);
while (*buf2) {
StrFirstRem(buf2,"/",buf);
if (!*buf)
StrCpy(buf3,"/");
else if (!StrCmp(buf,"..")) {
StrLastRem(buf3,"/");
if (!*buf3)
StrCpy(buf3,"/");
} else if (!StrCmp(buf,".")) {
;
} else if (*buf) {
if (!StrCmp(buf,"HOME")) {
Free(buf3);
buf3=MAlloc(maxlen+StrLen(sys_acct));
StrCpy(buf3,sys_acct+2);
*drv=*sys_acct;
} else {
if (StrCmp(buf3,"/"))
StrCat(buf3,"/");
StrCat(buf3,buf);
}
}
}
Free(cur_dir);
cur_dir=MAlloc(StrLen(buf3)+3);
StrCpy(cur_dir,drv);
StrCpy(cur_dir+2,buf3);
Free(buf);
Free(buf2);
Free(buf3);
Free(temp_name);
return cur_dir;
}
U8 *FileNameAbs(U8 *_filename)
{
U8 *buf,*buf2,*buf3,*filename,*temp_name,*temp_buf;
filename=MStrUtil(_filename,
SUF_REM_LEADING|SUF_REM_TRAILING|SUF_REM_CTRL_CHARS);
temp_name=filename;
buf=StrNew(filename);
temp_buf=buf;
if (*buf && buf[1]==':') {
buf+=2;
filename+=2;
}
buf2=MAlloc(StrLen(temp_name)+1);
StrLastRem(buf,"/",buf2);
if (*filename=='/' && !*buf)
StrCpy(buf,"/");
buf3=DirNameAbs(temp_buf);
Free(temp_buf);
buf=MAlloc(StrLen(buf3)+1+StrLen(buf2)+1);
StrCpy(buf,buf3);
if (buf[StrLen(buf)-1]!='/')
StrCat(buf,"/");
StrCat(buf,buf2);
Free(buf2);
Free(buf3);
Free(temp_name);
return buf;
}
U8 *ChgExt(U8 *filename,U8 *extension)
{//Change file name extension
U8 *result=MAlloc(StrLen(filename)+1+StrLen(extension)+1);
StrCpy(result,filename);
if (FileExtDot(filename))
FileExtRem(result);
StrCat(result,".");
StrCat(result,extension);
return result;
}
U8 *DftExt(U8 *filename,U8 *extension)
{//Give extension if has none.
U8 *result=MAlloc(StrLen(filename)+1+StrLen(extension)+1);
StrCpy(result,filename);
if (!FileExtDot(filename)) {
StrCat(result,".");
StrCat(result,extension);
}
return result;
}
CDirEntry *CdDir(CDirEntry *tempm,U8 *abs_name)
{
I64 i;
while (tempm) {
i=StrLen(tempm->full_name);
if (StrNCmp(tempm->full_name,abs_name,i))
tempm=tempm->next;
else
if (StrLen(abs_name)==i)
return tempm;
else
return CdDir(tempm->sub,abs_name);
}
return NULL;
}
I64 FileAttr(U8 *name,I64 attr=0)
{
if (IsDotZ(name))
attr|=_ATTR_COMPRESSED;
else
attr&=~_ATTR_COMPRESSED;
if (IsDotC(name))
attr|=_ATTR_CONTIGUOUS;
return attr;
}
Bool FileNameChk(U8 *filename)
{
U8 *ptr=filename;
if (!filename) return FALSE;
if (!*ptr) return FALSE;
if (*ptr=='.') {
if (!ptr[1]) return TRUE;
if (ptr[1]=='.' && !ptr[2]) return TRUE;
}
if (StrLen(filename)>=CDIR_FILENAME_LEN) return FALSE;
while (*ptr)
if (!Bt(filename_chars_bitmap,*ptr++))
return FALSE;
return TRUE;
}
U8 *DirFile(U8 *dirname,U8 *name=NULL,U8 *_extension=NULL)
{/*
Strips file from dirname, scans for file upward until found or returns default.
("/SparrowOS/OSMain/Hash1a.CPP.Z",NULL,NULL) returns "D:/SparrowOS/OSMain"
("/SparrowOS/OSMain",NULL,"PRJ.Z") returns "D:/SparrowOS/OSMain/OSMain.PRJ.Z"
("/SparrowOS/OSMain/Dsk",NULL,"PRJ.Z") returns "D:/SparrowOS/OSMain/OSMain.PRJ.Z"
("/SparrowOS/Apps/MusicOrgan","Load","CPP.Z") returns "D:/SparrowOS/Apps/MusicOrgan/Load.CPP.Z"
*/
U8 *st=DirNameAbs(dirname),*st2,*st3,*result,*dft=NULL,*ext;
if (_extension && *_extension) {
if (*_extension=='.')
ext=StrNew(_extension);
else
ext=MSPrintF(".%s",_extension);
} else
ext=StrNew("");
while (StrOcc(st,'/')&&!IsDir(st))
StrLastRem(st,"/");
while (StrOcc(st,'/')) {
st2=StrNew(st);
st3=StrNew(st);
StrLastRem(st2,"/",st3);
if (name)
result=MSPrintF("%s/%s%s",st,name,ext);
else {
if (*ext)
result=MSPrintF("%s/%s%s",st,st3,ext);
else
result=StrNew(st);
}
if (!dft)
dft=StrNew(result);
if (!*ext&&(!name||!*name)||FileFind(result)) {
Free(st3);
Free(st2);
Free(st);
Free(dft);
Free(ext);
return result;
}
Free(st);
st=st2;
Free(st3);
}
Free(st);
Free(ext);
return dft;
}
U8 *ZorNotZ(U8 *name)
{ //Compressed file name unless only uncompressed is available
I64 i;
U8 *result=StrNew(name);
if (!*result||FileFind(result)||!IsDotZ(name))
return result;
i=StrLen(name)-2;
result[i]=0;
if (FileFind(result))
return result;
result[i]='.';
return result;
}
File diff suppressed because it is too large. Load diff
+312
View File
@@ -0,0 +1,312 @@
//ISO1 is ISO9660
//ISO2 is ISO13490
//ISO3 is ISO13346
Bool ISOPrtInit(CPrt *p,I64 blk)
{
CBlkDev *bdev=p->bdev;
I64 spc=bdev->blk_size>>BLK_SIZE_BITS,i=blk/spc;
CISO1PriDesc *iso=MAlloc(bdev->blk_size);
CISO1DirEntry *de;
Bool unlock,result=FALSE;
U8 buf[8];
try {
unlock=PrtLock(p);
p->type=PT_ISO9660; //default
p->spc=spc;
p->offset=p->data=p->root_cluster=p->size=0;
while (TRUE) {
p->size=MaxI64(p->size,(i+1)*spc);
RBlks(p,iso,i*spc,spc);
buf[0](U32)=iso->id[0](U32);
buf[4](U16)=iso->id[4](U8);
switch (ListEntryMatch(buf,"CD001\0CDW02\0BEA01\0BOOT2\0NSR02\0NSR03\0TEA01\0",LEF_EXACT)) {
case 0:
p->type=PT_ISO9660;
switch (iso->type) {
case ISO1T_SUPPLEMENTARY_DESC:
p->data=0;
de=&iso->root_dir_record;
p->root_cluster=de->loc.little;
p->size=iso->vol_space_size.little*bdev->blk_size>>BLK_SIZE_BITS;
result=TRUE;
goto ipi_done;
case ISO1T_TERMINATOR:
throw(EXCEPT_PRT,5);
}
break;
default: //Its normal for ISO13346 to read NULL blk as terminator
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
throw(EXCEPT_PRT,6);
}
i++;
}
ipi_done:
Free(iso);
if (unlock)
PrtUnlock(p);
} catch {
p->type=PT_ISO9660;
p->spc=spc;
p->offset=p->data=p->root_cluster=0;
Free(iso);
if (unlock)
PrtUnlock(p);
}
return result;
}
U0 CDate2ISO1(CISO1Date *dst,CDate ltdt)
{
CDateStruct ds;
CDate2CDateStruct(&ds,ltdt);
dst->year=ds.year-ISO1_BASE_YEAR;
dst->mon=ds.mon;
dst->day=ds.day_of_mon;
dst->hour=ds.hour;
dst->min=ds.min;
dst->sec=ds.sec;
dst->sec100=ds.sec100;
}
CDate ISO1DateStruct2CDate(CISO1Date *dt)
{
CDateStruct ds;
MemSet(&ds,0,sizeof(CDateStruct));
ds.day_of_mon=dt->day;
ds.mon=dt->mon;
ds.year=dt->year+ISO1_BASE_YEAR;
ds.sec100=dt->sec100;
ds.sec=dt->sec;
ds.min=dt->min;
ds.hour=dt->hour;
return CDateStruct2CDate(&ds);
}
Bool ISO1FromName(U8 *dst,U8 *src)
{
I64 i,j,n;
MemSet(dst,0,CDIR_FILENAME_LEN);
n=*src++;
if (n==1 && !*src) {
*dst='.';
} else if (n==1 && *src==1) {
*dst='.';
dst[1]='.';
} else {
n>>=1;
j=0;
for (i=0;i<n;i++) {
src++;
if (*src==';')
break;
if (Bt(filename_chars_bitmap,*src)) {
if (j>=CDIR_FILENAME_LEN-1)
return FALSE;
dst[j++]=*src++;
} else
return FALSE;
}
}
return FileNameChk(dst);
}
Bool ISO1CDirFill(CPrt *p,CDirEntry *tempm,CISO1DirEntry *de)
{
Bool result;
CArcCompress *buf;
MemSet(tempm,0,sizeof(CDirEntry));
result=ISO1FromName(tempm->name,&de->name_len);
tempm->cluster=de->loc.little;
tempm->size=de->size.little;
tempm->attr=FileAttr(tempm->name);
if (de->flags & ISO1_ATTR_DIR)
tempm->attr|=_ATTR_DIR;
tempm->datetime=ISO1DateStruct2CDate(&de->date);
if (tempm->attr & _ATTR_COMPRESSED) {
buf=MAlloc(BLK_SIZE);
RClustersBlks(p,buf,tempm->cluster,1);
tempm->expanded_size=buf->expanded_size;
Free(buf);
} else
tempm->expanded_size=tempm->size;
return result;
}
Bool ISO1FileFind(CPrt *p,I64 cur_dir_cluster,U8 *name,CDirEntry *_result,
Bool dir_only,Bool file_only)
{
CISO1DirEntry *isoptr,*buf;
U8 dname[CDIR_FILENAME_LEN];
Bool result=FALSE,unlock;
I64 i;
PrtChk(p);
if (p->type!=PT_ISO9660)
PutDefineErr("ST_NOT_ISO9660");
else {
try {
unlock=PrtLock(p);
isoptr=MAlloc(p->spc<<BLK_SIZE_BITS);
RClusters(Fs->cur_prt,isoptr,cur_dir_cluster,1);
if (isoptr->name_len==1 && !isoptr->name) { //curdir
i=(isoptr->size.little+p->spc<<BLK_SIZE_BITS-1)/p->spc<<BLK_SIZE_BITS;
buf=MAlloc(p->spc<<BLK_SIZE_BITS*i);
RClusters(Fs->cur_prt,buf,cur_dir_cluster,i);
Free(isoptr);
} else {
buf=isoptr;
i=1;
}
i*=p->spc<<BLK_SIZE_BITS;
isoptr=buf;
while (i>0) {
if (!isoptr->len) {
isoptr(U8 *)++;
i--;
} else {
ISO1FromName(dname,&isoptr->name_len);
if (*dname) {
if (!StrCmp(name,dname)) {
result=ISO1CDirFill(p,_result,isoptr);
if (result &&
!(dir_only && !(_result->attr & _ATTR_DIR)) &&
!(file_only && _result->attr & _ATTR_DIR) )
goto exit_this;
else
result=FALSE;
}
}
i-=isoptr->len;
isoptr(U8 *)+=isoptr->len;
}
}
exit_this:
Free(buf);
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
}
return result;
}
U8 *ISO1FileRead(CPrt *p,U8 *cur_dir,U8 *filename,I64 *_size,
I64 *_attr,Bool raw,CArcCompress **_ac2)
{
U8 *buf=NULL;
CDirEntry de;
I64 c,blk_cnt,cur_dir_cluster;
CArcCompress *ac;
PrtChk(p);
if (_size) *_size=0;
if (_ac2) *_ac2=NULL;
if (_attr) *_attr=0;
if (p->type!=PT_ISO9660)
PutDefineErr("ST_NOT_ISO9660");
else {
try {
PrtLock(p);
cur_dir_cluster=Name2DirCluster(p,cur_dir);
if (ISO1FileFind(p,cur_dir_cluster,filename,&de,FALSE,TRUE)) {
if (_attr) *_attr=de.attr;
blk_cnt=(de.size+BLK_SIZE-1)>>BLK_SIZE_BITS;
buf=MAlloc(blk_cnt<<BLK_SIZE_BITS+1);
c=de.cluster;
c=RClustersBlks(p,buf,c,blk_cnt);
if (FileAttr(de.name)&_ATTR_COMPRESSED && !raw) {
ac=buf;
if (_attr) *_attr=FileAttr(de.name,*_attr);
if (_size) *_size=ac->expanded_size;
if (_ac2) {
*_ac2=ac;
buf=ExpandBuf(ac);
} else {
buf=ExpandBuf(ac);
Free(ac);
}
} else {
buf[de.size]=0; //Terminate
if (_size) *_size=de.size;
}
if (_attr) *_attr=FileAttr(de.name,*_attr);
}
PrtUnlock(p);
} catch
PrtUnlock(p);
}
return buf;
}
Bool ISO1Cd(U8 *name,I64 cur_dir_cluster)
{
CDirEntry de;
if (Fs->cur_prt->type!=PT_ISO9660)
PutDefineErr("ST_NOT_ISO9660");
else {
if (ISO1FileFind(Fs->cur_prt,cur_dir_cluster,name,&de,TRUE,FALSE))
return TRUE;
else {
"%s ",name;
PutDefineErr("ST_FILE_NOT_FOUND");
}
}
return FALSE;
}
CDirEntry *ISO1FilesFind(U8 *files_find_mask,I64 fuf_flags,CDirEntry *parent=NULL)
{
CPrt *p=Fs->cur_prt;
CISO1DirEntry *buf,*buf2,*isoptr;
I64 i,cur_dir_cluster=Name2DirCluster(p,Fs->cur_dir);
CDirEntry *result=NULL,*tempm;
isoptr=MAlloc(p->spc<<BLK_SIZE_BITS);
RClusters(Fs->cur_prt,isoptr,cur_dir_cluster,1);
if (isoptr->name_len==1 && !isoptr->name) { //curdir
i=(isoptr->size.little+p->spc<<BLK_SIZE_BITS-1)/p->spc<<BLK_SIZE_BITS;
buf=MAlloc(p->spc<<BLK_SIZE_BITS*i);
RClusters(Fs->cur_prt,buf,cur_dir_cluster,i);
Free(isoptr);
} else {
buf=isoptr;
i=1;
}
buf2=buf;
i*=p->spc<<BLK_SIZE_BITS;
while (i>0) {
if (!buf->len) {
buf(U8 *)++;
i--;
} else {
tempm=MAlloc(sizeof(CDirEntry));
if (ISO1CDirFill(Fs->cur_prt,tempm,buf)) {
tempm->parent=parent;
if (Bt(&fuf_flags,FUf_RECURSE) && tempm->attr&_ATTR_DIR && *tempm->name!='.') {
tempm->next=result;
result=tempm;
tempm->full_name=DirNameAbs(tempm->name);
if (Cd(tempm->name)) {
tempm->sub=ISO1FilesFind(files_find_mask,fuf_flags,tempm);
Cd("..");
}
} else if ((tempm->attr & _ATTR_DIR || !Bt(&fuf_flags,FUf_JUST_DIRS)) &&
!(Bt(&fuf_flags,FUf_RECURSE) && *tempm->name=='.' && tempm->attr&_ATTR_DIR) &&
FilesFindMatch(files_find_mask,tempm->name,fuf_flags)) {
tempm->next=result;
result=tempm;
tempm->full_name=FileNameAbs(tempm->name);
} else
CDirEntryDel(tempm);
} else
CDirEntryDel(tempm);
i-=buf->len;
buf(U8 *)+=buf->len;
}
}
Free(buf2);
return result;
}
+715
View File
@@ -0,0 +1,715 @@
U0 NativeFSFreeFreeList(CPrt *p)
{
CFreeList *tempf,*tempf1;
Bool unlock;
try {
unlock=PrtLock(p);
if (tempf=p->next_free) {
while (tempf!=&p->next_free) {
tempf1=tempf->next;
Free(tempf);
tempf=tempf1;
}
}
p->next_free=NULL;
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
}
U0 NativeFSFreeListBuild(CPrt *p)
{
Bool unlock;
CFreeList *tempf;
I64 i,first=0,
max_cluster=(p->size+p->offset-p->data)/p->spc;
try {
unlock=PrtLock(p);
if (p->next_free)
NativeFSFreeFreeList(p);
p->next_free=&p->next_free;
p->last_free=&p->next_free;
while (first<max_cluster) {
i=0; //count free clusters
while (first+i<max_cluster) {
SetNativeBuf(p,first+i);
if (Bt(p->cur_map_blk,(first+i)&(BLK_SIZE<<3-1)))
break;
else
i++;
}
if (i) {
tempf=AMAlloc(sizeof(CFreeList));
tempf->size=i;
tempf->start=first;
QueIns(tempf,p->last_free);
}
first+=i+1;
}
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
}
U0 NativeFSPrtInit(CPrt *p)
{
CBootStruct br;
Bool unlock;
try {
unlock=PrtLock(p);
RBlks(p,&br,p->offset,1);
if (br.signature!=MBR_PT_NATIVE ||
br.signature2!=0xAA55)
throw(EXCEPT_PRT,7);
p->type=PT_NATIVE;
NativeFSFreeFreeList(p);
p->spc=br.sects_per_cluster;
p->size=br.sects;
p->data=p->offset+1+br.bitmap_sects-p->spc;
p->root_cluster=br.root_cluster;
p->map1=p->offset+1;
p->map2=p->offset+1;
MapBufAlloc(p,1);
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
}
Bool NativeFSDrvValidate(U8 drv_let)
{
CPrt *p;
CBootStruct br;
Bool result=FALSE;
try {
p=Drv2Prt(drv_let);
if (p->type==PT_NATIVE &&
RBlks(p,&br,p->offset,1) &&
br.signature==MBR_PT_NATIVE &&
br.signature2==0xAA55 &&
br.sects==p->size)
result=TRUE;
} catch
Fs->catch_except=TRUE;
return result;
}
U0 NativeFSFmt(U8 drv_let,Bool quick=TRUE)
{
U8 *root_dir;
CDirEntry *d_native;
CBootStruct *br=CAlloc(BLK_SIZE);
CPrt *p=Drv2Prt(drv_let);
I64 i,n;
try {
PrtLock(p);
// SetDrvType(drv_let,PT_NATIVE);
SetDrvType(drv_let,PT_FAT32);
p->type=PT_NATIVE;
br->U8s_per_sect=BLK_SIZE;
if (p->size<0x20000)
br->sects_per_cluster=1;
else if (p->size<0x200000)
br->sects_per_cluster=2;
else if (p->size<0x2000000)
br->sects_per_cluster=4;
else if (p->size<0x20000000)
br->sects_per_cluster=8;
else if (p->size<0x200000000)
br->sects_per_cluster=16;
else
br->sects_per_cluster=32;
br->signature=MBR_PT_NATIVE;
br->signature2=0xAA55;
br->sects=p->size;
n=br->sects_per_cluster*(BLK_SIZE<<3);
n=(br->sects+n-1)/n;
br->bitmap_sects=n;
br->unique_id=GetTimeStamp>>4;
br->root_cluster=0;
if (quick)
i=n+1;
else
i=p->size;
WZeroBlks(p,p->offset,i);
WBlks(p,br,p->offset,1);
NativeFSPrtInit(p);
ClusersAlloc(p,0,1,FALSE); //Alloc #1
br->root_cluster=ClusersAlloc(p,0,1,FALSE);
WBlks(p,br,p->offset,1);
root_dir=CAlloc(p->spc<<BLK_SIZE_BITS);
d_native=root_dir-offset(CDirEntry.start);
d_native->attr=_ATTR_DIR|_ATTR_CONTIGUOUS;
*d_native->name='.';
d_native->cluster=br->root_cluster;
d_native->size=p->spc<<BLK_SIZE_BITS;
d_native->expanded_size=d_native->size;
d_native->datetime=GetCurTimeCDate;
d_native(U8 *)+=CDIR_SIZE;
*d_native->name='.';
d_native->name[1]='.';
d_native->attr=_ATTR_DIR|_ATTR_CONTIGUOUS;
d_native->cluster=br->root_cluster;
d_native->datetime=GetCurTimeCDate;
WBlks(p,root_dir,p->data+br->root_cluster*p->spc,p->spc);
NativeFSPrtInit(p);
PrtUnlock(p);
} catch
PrtUnlock(p);
Free(br);
Free(root_dir);
}
Bool NativeFSFileFind(CPrt *p,I64 cur_dir_cluster,U8 *name,CDirEntry *_result,
Bool dir_only,Bool file_only)
{
CDirEntry *buf,*buf2,*ptr;
U8 dname[CDIR_FILENAME_LEN];
I64 ch;
Bool result=FALSE,unlock;
MemSet(_result,0,sizeof(CDirEntry));
PrtChk(p);
if (p->type!=PT_NATIVE)
PutDefineErr("ST_NOT_NATIVE");
else if (!CFileNameTo(dname,name))
PutDefineErr("ST_INVALID_FILENAME");
else {
try {
unlock=PrtLock(p);
buf2=MAlloc(p->spc<<BLK_SIZE_BITS);
RClusters(p,buf2,cur_dir_cluster,1);
ptr=buf2(U8 *)-offset(CDirEntry.start);
buf=MAlloc(ptr->size);
RClustersBlks(p,buf,cur_dir_cluster,ptr->size>>BLK_SIZE_BITS);
Free(buf2);
ptr=buf(U8 *)-offset(CDirEntry.start);
*ptr->name='.';
ptr->name[1]=0;
while (TRUE) {
if (!(ch=*ptr->name))
break;
else if (!(ptr->attr & _ATTR_DELETED) &&
!(dir_only && !(ptr->attr & _ATTR_DIR)) &&
!(file_only && ptr->attr & _ATTR_DIR) &&
!StrCmp(dname,ptr->name)) {
MemCpy(&_result->attr,&ptr->attr,CDIR_SIZE);
result=TRUE;
goto exit_this;
}
ptr(U8 *)+=CDIR_SIZE;
}
exit_this:
Free(buf);
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
}
return result;
}
U8 *NativeFSFileRead(CPrt *p,U8 *cur_dir,U8 *filename,I64 *_size,
I64 *_attr,Bool raw,CArcCompress **_ac2)
{
U8 *buf=NULL;
CDirEntry de;
I64 c,blk_cnt,cur_dir_cluster;
CArcCompress *ac;
PrtChk(p);
if (_size) *_size=0;
if (_ac2) *_ac2=NULL;
if (_attr) *_attr=0;
if (p->type!=PT_NATIVE)
PutDefineErr("ST_NOT_NATIVE");
else {
try {
PrtLock(p);
cur_dir_cluster=Name2DirCluster(p,cur_dir);
if (NativeFSFileFind(p,cur_dir_cluster,filename,&de,FALSE,TRUE)) {
if (_attr) *_attr=de.attr;
blk_cnt=(de.size+BLK_SIZE-1)>>BLK_SIZE_BITS;
buf=MAlloc(blk_cnt<<BLK_SIZE_BITS+1);
c=de.cluster;
c=RClustersBlks(p,buf,c,blk_cnt);
if (de.xsum) {
if (de.xsum^ArcXSum(buf,de.size) !=NATIVE_XSUM)
throw(EXCEPT_ARC_XSUM);
}
if (FileAttr(de.name) & _ATTR_COMPRESSED && !raw) {
ac=buf;
if (_attr) *_attr=FileAttr(de.name,*_attr);
if (_size) *_size=ac->expanded_size;
if (_ac2) {
*_ac2=ac;
buf=ExpandBuf(ac);
} else {
buf=ExpandBuf(ac);
Free(ac);
}
} else {
buf[de.size]=0; //Terminate
if (_size) *_size=de.size;
}
if (_attr) *_attr=FileAttr(de.name,*_attr);
}
PrtUnlock(p);
} catch
PrtUnlock(p);
}
return buf;
}
Bool NativeFSCd(U8 *name,I64 cur_dir_cluster)
{
CDirEntry de;
if (Fs->cur_prt->type!=PT_NATIVE)
PutDefineErr("ST_NOT_NATIVE");
else {
if (NativeFSFileFind(Fs->cur_prt,cur_dir_cluster,
name,&de,TRUE,FALSE))
return TRUE;
else {
"%s ",name;
PutDefineErr("ST_FILE_NOT_FOUND");
}
}
return FALSE;
}
U0 NativeFSFreeClusters(CPrt *p,I64 c,I64 cnt)
{
CFreeList *tempf;
Bool found=FALSE,unlock,unlock_break;
PrtChk(p);
if (!c) return;
if (p->type!=PT_NATIVE)
PutDefineErr("ST_NOT_NATIVE");
else {
try {
unlock_break=BreakLock;
unlock=PrtLock(p);
if (!p->next_free)
NativeFSFreeListBuild(p);
tempf=p->next_free;
while (!found && tempf!=&p->next_free) {
if (tempf->start+tempf->size==c) {
tempf->size+=cnt;
found=TRUE;
} else if (c+cnt==tempf->start) {
tempf->size+=cnt;
tempf->start=c;
found=TRUE;
}
tempf=tempf->next;
}
if (!found) {
tempf=AMAlloc(sizeof(CFreeList));
tempf->size=cnt;
tempf->start=c;
QueIns(tempf,p->last_free);
}
while (cnt-->0) {
SetNativeBuf(p,c);
LBtr(p->cur_map_blk,c&(BLK_SIZE<<3-1));
LBts(p->buffered_map_dirty_bits,0);
c++;
}
CleanMAPBuf(p);
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
} catch {
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
}
}
}
I64 NativeFSAllocClusters(CPrt *p,I64 cnt)
{
CFreeList *tempf,*best_free=NULL;
I64 i,first,best_size=MAX_I64;
Bool unlock,unlock_break;
if (cnt<=0)
Dbg;
try {
unlock_break=BreakLock;
unlock=PrtLock(p);
if (!p->next_free)
NativeFSFreeListBuild(p);
tempf=p->next_free;
while (tempf!=&p->next_free) {
if (tempf->size>=cnt && tempf->size<best_size) {
best_free=tempf;
best_size=tempf->size;
if (tempf->size==cnt)
break;
}
tempf=tempf->next;
}
if (!best_free)
Dbg;
first=best_free->start;
for (i=0;i<cnt;i++) {
SetNativeBuf(p,first+i);
LBts(p->cur_map_blk,(first+i)&(BLK_SIZE<<3-1));
LBts(p->buffered_map_dirty_bits,0);
}
CleanMAPBuf(p);
if (best_free->size-=cnt)
best_free->start+=cnt;
else {
QueRem(best_free);
Free(best_free);
}
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
} catch {
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
}
return first;
}
Bool NativeFSDirNew(CPrt *p,U8 *cur_dir,CDirEntry *de,Bool free_old_chain)
{
CDirEntry *buf,*buf2,*ptr,de2;
CBootStruct *br;
I64 c,ch,i=1,j=0,n=BLK_SIZE/CDIR_SIZE,dir_size,cur_dir_cluster;
Bool written=FALSE,unlock,unlock_break;
U8 *temp,*parent_dir;
try {
unlock_break=BreakLock;
de->attr|=_ATTR_CONTIGUOUS;
unlock=PrtLock(p);
cur_dir_cluster=Name2DirCluster(p,cur_dir);
buf2=MAlloc(p->spc<<BLK_SIZE_BITS);
RClusters(p,buf2,cur_dir_cluster,1);
ptr=buf2(U8 *)-offset(CDirEntry.start);
buf=MAlloc(ptr->size);
RClustersBlks(p,buf,cur_dir_cluster,ptr->size>>BLK_SIZE_BITS);
dir_size=ptr->size;
ptr=buf(U8 *)-offset(CDirEntry.start)+CDIR_SIZE;
Free(buf2);
while (TRUE) {
if (!(ch=*ptr->name)) {
if (!written)
MemCpy(&ptr->start,&de->start,CDIR_SIZE);
if ((i+1)*CDIR_SIZE+j<<BLK_SIZE_BITS<dir_size)
WBlks(p,buf(U8 *)+j<<BLK_SIZE_BITS,
p->data+cur_dir_cluster*p->spc+j,1);
else {
buf2=CAlloc(dir_size+p->spc<<BLK_SIZE_BITS);
MemCpy(buf2,buf,dir_size);
NativeFSFreeClusters(p,cur_dir_cluster,
(dir_size>>BLK_SIZE_BITS+p->spc-1)/p->spc);
dir_size+=p->spc<<BLK_SIZE_BITS;
c=ClusersAlloc(p,0,(dir_size>>BLK_SIZE_BITS+p->spc-1)/p->spc,TRUE);
Free(buf);
buf=buf2;
ptr=buf(U8 *)-offset(CDirEntry.start);
ptr->size=dir_size;
ptr->expanded_size=dir_size;
ptr->cluster=c;
WClustersBlks(p,buf,c,dir_size>>BLK_SIZE_BITS);
if (cur_dir_cluster==p->root_cluster) {
br=CAlloc(BLK_SIZE);
RBlks(p,br,p->offset,1);
br->root_cluster=c;
WBlks(p,br,p->offset,1);
Free(br);
p->root_cluster=c;
} else {
temp=StrNew(cur_dir);
parent_dir=StrNew(cur_dir);
StrLastRem(parent_dir,"/",temp);
if (!*parent_dir) {
Free(parent_dir);
parent_dir=StrNew("/");
}
if (NativeFSFileFind(p,Name2DirCluster(p,parent_dir),
temp,&de2,TRUE,FALSE)) {
de2.cluster=c;
de2.size=dir_size;
de2.expanded_size=dir_size;
NativeFSDirNew(p,parent_dir,&de2,FALSE);
} else
Dbg;
Free(temp);
Free(parent_dir);
}
}
break;
} else if (ptr->attr & _ATTR_DELETED) {
if (!written) {
MemCpy(&ptr->start,&de->start,CDIR_SIZE);
WBlks(p,buf(U8 *)+j<<BLK_SIZE_BITS,
p->data+cur_dir_cluster*p->spc+j,1);
written=TRUE;
}
} else {
if (!StrCmp(de->name,ptr->name)) {
if (free_old_chain)
NativeFSFreeClusters(p,ptr->cluster,
(ptr->size+p->spc<<BLK_SIZE_BITS-1)/p->spc<<BLK_SIZE_BITS);
if (!written)
MemCpy(&ptr->start,&de->start,CDIR_SIZE);
else
ptr->attr|=_ATTR_DELETED;
WBlks(p,buf(U8 *)+j<<BLK_SIZE_BITS,
p->data+cur_dir_cluster*p->spc+j,1);
break;
}
}
ptr(U8 *)+=CDIR_SIZE;
if (++i>=n) {
j++;
i=0;
}
}
Free(buf);
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
} catch {
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
}
return FALSE;
}
Bool NativeFSFilesDel(CPrt *p,U8 *cur_dir,U8 *files_find_mask,I64 fuf_flags,
Bool del_dir,Bool print_msg)
{
CDirEntry *buf,*buf2,*ptr;
I64 i=0,ch,j=0,n=BLK_SIZE/CDIR_SIZE,cur_dir_cluster;
Bool unlock_break;
try {
unlock_break=BreakLock;
PrtLock(p);
cur_dir_cluster=Name2DirCluster(p,cur_dir);
buf2=MAlloc(p->spc<<BLK_SIZE_BITS);
RClusters(p,buf2,cur_dir_cluster,1);
ptr=buf2(U8 *)-offset(CDirEntry.start);
buf=MAlloc(ptr->size);
RClustersBlks(p,buf,cur_dir_cluster,ptr->size>>BLK_SIZE_BITS);
Free(buf2);
ptr=buf(U8 *)-offset(CDirEntry.start);
*ptr->name='.';
ptr->name[1]=0;
while (TRUE) {
if (!(ch=*ptr->name))
break;
else if (!(ptr->attr & _ATTR_DELETED) && ch!='.' && (del_dir ||
!(ptr->attr & _ATTR_DIR)) &&
FilesFindMatch(files_find_mask,ptr->name,fuf_flags)) {
if (print_msg) {
PutDefine("ST_DELETE");
"" ptr->name;
NewLine;
}
ptr->attr|=_ATTR_DELETED;
WBlks(p,buf(U8 *)+j<<BLK_SIZE_BITS,
p->data+cur_dir_cluster*p->spc+j,1);
NativeFSFreeClusters(p,ptr->cluster,
(ptr->size+p->spc<<BLK_SIZE_BITS-1)/p->spc<<BLK_SIZE_BITS);
}
ptr(U8 *)+=CDIR_SIZE;
if (++i>=n) {
j++;
i=0;
}
}
Free(buf);
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
} catch {
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
}
return FALSE;
}
I64 NativeFSFileWrite(CPrt *p,U8 *cur_dir,U8 *name,U8 *buf,I64 size,
CDate ltdt,I64 attr,Bool raw,
CArcCompress **_ac2)
{
CDirEntry de;
I64 c=0,flags=0,blk_cnt;
CArcCompress *ac=NULL;
Bool contiguous;
MemSet(&de,0,sizeof(CDirEntry));
if (_ac2) *_ac2=NULL;
if (size<0) size=0;
if (!ltdt)
ltdt=GetCurTimeCDate;
if (p->type!=PT_NATIVE)
PutDefineErr("ST_NOT_NATIVE");
else if (!CFileNameTo(de.name,name))
PutDefineErr("ST_INVALID_FILENAME");
else {
NativeFSFilesDel(p,cur_dir,de.name,0,FALSE,FALSE);
attr=FileAttr(name,attr);
attr|=_ATTR_CONTIGUOUS;
contiguous=TRUE;
de.expanded_size=size;
if (attr&_ATTR_COMPRESSED && !raw) {
ac=CompressBuf(buf,size,flags);
size=ac->compressed_size;
buf=ac;
}
de.size=size;
de.xsum=ArcXSum(buf,size)^NATIVE_XSUM;
if (blk_cnt=(size+BLK_SIZE-1)>>BLK_SIZE_BITS)
c=ClusersAlloc(p,0,(blk_cnt+p->spc-1)/p->spc,contiguous);
else
c=INVALID_CLUSTER;
de.cluster=c;
de.attr=attr;
de.datetime=ltdt;
if (blk_cnt)
WClustersBlks(p,buf,c,blk_cnt);
NativeFSDirNew(p,cur_dir,&de,TRUE);
if (_ac2)
*_ac2=ac;
else
Free(ac);
}
return c;
}
CDirEntry *NativeFSFilesFind(U8 *files_find_mask,I64 fuf_flags,CDirEntry *parent=NULL)
{
CPrt *p=Fs->cur_prt;
CDirEntry *buf,*buf2,*ptr,*result=NULL,*tempm;
I64 ch,cur_dir_cluster;
try {
PrtLock(p);
cur_dir_cluster=Name2DirCluster(p,Fs->cur_dir);
buf2=MAlloc(p->spc<<BLK_SIZE_BITS);
RClusters(p,buf2,cur_dir_cluster,1);
ptr=buf2(U8 *)-offset(CDirEntry.start);
buf=MAlloc(ptr->size);
RClustersBlks(p,buf,cur_dir_cluster,ptr->size>>BLK_SIZE_BITS);
Free(buf2);
ptr=buf(U8 *)-offset(CDirEntry.start);
*ptr->name='.';
ptr->name[1]=0;
ptr(U8 *)+=CDIR_SIZE;
ptr->cluster=Name2ParentDirCluster(p,Fs->cur_dir);
ptr(U8 *)-=CDIR_SIZE;
while (TRUE) {
if (!(ch=*ptr->name))
break;
else if (!(ptr->attr & _ATTR_DELETED)) {
tempm=CAlloc(sizeof(CDirEntry));
MemCpy(&tempm->start,&ptr->start,CDIR_SIZE);
tempm->parent=parent;
if (Bt(&fuf_flags,FUf_RECURSE) && tempm->attr&_ATTR_DIR && *tempm->name!='.') {
tempm->next=result;
result=tempm;
tempm->full_name=DirNameAbs(tempm->name);
PrtUnlock(p);
if (Cd(tempm->name)) {
tempm->sub=NativeFSFilesFind(files_find_mask,fuf_flags,tempm);
Cd("..");
}
PrtLock(p);
} else if ((tempm->attr&_ATTR_DIR || !Bt(&fuf_flags,FUf_JUST_DIRS)) &&
!(Bt(&fuf_flags,FUf_RECURSE) && *tempm->name=='.' && tempm->attr&_ATTR_DIR) &&
FilesFindMatch(files_find_mask,tempm->name,fuf_flags)) {
tempm->next=result;
result=tempm;
tempm->full_name=FileNameAbs(tempm->name);
} else
CDirEntryDel(tempm);
}
ptr(U8 *)+=CDIR_SIZE;
}
Free(buf);
PrtUnlock(p);
} catch
PrtUnlock(p);
return result;
}
Bool NativeFSMkDir(CPrt *p,U8 *cur_dir,U8 *name)
{
I64 size=p->spc<<BLK_SIZE_BITS,c,
cur_dir_cluster=Name2DirCluster(p,cur_dir);
U8 *buf=CAlloc(size);
CDirEntry *d_native=buf-offset(CDirEntry.start);
Bool unlock_break;
try {
unlock_break=BreakLock;
c=FileWrite(name,buf,size,0,_ATTR_DIR,FALSE);
d_native->attr=_ATTR_DIR|_ATTR_CONTIGUOUS;
StrCpy(d_native->name,name);
d_native->cluster=c;
d_native->size=size;
d_native->expanded_size=size;
d_native->datetime=GetCurTimeCDate;
d_native(U8 *)+=CDIR_SIZE;
d_native->attr=_ATTR_DIR|_ATTR_CONTIGUOUS;
*d_native->name='.';
d_native->name[1]='.';
d_native->name[2]=0;
d_native->cluster=cur_dir_cluster;
d_native->size=0;
d_native->expanded_size=0;
d_native->datetime=GetCurTimeCDate;
WClusters(p,buf,c,1);
Free(buf);
if (unlock_break)
BreakUnlock;
} catch
if (unlock_break)
BreakUnlock;
return TRUE;
}
+286
View File
@@ -0,0 +1,286 @@
class CLine
{
CLine *next,*last;
U8 *line;
};
U0 EdLiteUpdate(CLine *root,CLine *cur_line,I64 cur_col,I64 line_start_col)
{
I64 ch,i,j,k,k2,cursor_col,cursor_row=-1;
U8 *st;
CLine *templ=cur_line;
Bool done_eof=FALSE;
sys_raw_dc_col=0;
for (i=0;i<text_rows/2;i++)
if (templ->last!=root)
templ=templ->last;
for (i=0;i<text_rows;i++) {
if (cursor_row<0 && templ==cur_line) {
k=0;
for (j=0;j<cur_col;j++)
if (templ->line[j]==CH_TAB)
k=(k+8)&~7;
else
k++;
cursor_col=k;
cursor_row=i;
}
if (templ!=root) {
st=templ->line;
k=0;
j=0;
while (ch=*st++) {
if (ch==CH_TAB)
k2=(k+8)&~7;
else
k2=k+1;
if (line_start_col<=k<line_start_col+text_cols) {
'' ch;
j=k2-line_start_col;
}
k=k2;
}
if (j<text_cols)
NewLine;
templ=templ->next;
} else {
if (!done_eof) {
"<EOF>";
done_eof=TRUE;
}
NewLine;
}
}
sys_raw_dc_col=text_cols*cursor_row+cursor_col-line_start_col;
RawDrawChar(0x7F);
}
U0 EdLite(U8 *filename)
{
//Light weight text editor for debugging
U8 *src,*src2,*src3,*dst,*buf,*bin_data=NULL;
I64 i,ch,sc,size,bin_size=0,line_start_col=0,cur_col=0,
old_dc_flags=sys_raw_dc_flags;
CLine root,*templ,*templ1,*cur_line;
Bool old_raw=Raw(ON),
old_debug=InDbg(ON),
old_single=SingleUser(ON);
if (!filename) filename=sys_temp_filename;
buf=FileRead(filename,&size);
PushFD;
Cli;
sys_raw_dc_flags=sys_raw_dc_flags&~RDCF_SCROLL|RDCF_SHOW_DOLLAR;
sys_cur_scan_code=0;
QueInit(&root);
root.line=StrNew("");
if (buf) {
src=buf;
while (*src) {
src2=src;
while ((ch=*src++) && ch!=CH_CARRIAGE_RETURN && ch!=CH_NEW_LINE);
src--;
*src++=0;
if (!ch)
src--;
while (ch==CH_CARRIAGE_RETURN && *src==CH_NEW_LINE || *src==CH_CURSOR)
src++;
dst=src3=src2;
while (ch=*src3++)
if (ch!=CH_NEW_LINE && ch!=CH_CURSOR)
*dst++=ch;
*dst=0;
templ=MAlloc(sizeof(CLine));
templ->line=StrNew(src2);
QueIns(templ,root.last);
}
if (src+1-buf<size) {
bin_data=MAlloc(bin_size=size-(src-buf));
MemCpy(bin_data,src,bin_size);
}
Free(buf);
}
cur_line=root.next;
do {
if (cur_line==&root)
cur_col=0;
while (cur_col-line_start_col<0)
line_start_col-=8;
while (cur_col-line_start_col>=text_cols)
line_start_col+=8;
EdLiteUpdate(&root,cur_line,cur_col,line_start_col);
switch (ch=GetKey(&sc,FALSE,TRUE)) {
case 0:
switch (sc.u8[0]) {
case SC_CURSOR_UP:
if (cur_line->last!=&root)
cur_line=cur_line->last;
if (cur_col>StrLen(cur_line->line))
cur_col=StrLen(cur_line->line);
break;
case SC_CURSOR_DOWN:
if (cur_line!=&root)
cur_line=cur_line->next;
if (cur_col>StrLen(cur_line->line))
cur_col=StrLen(cur_line->line);
break;
case SC_CURSOR_RIGHT:
cur_col++;
if (cur_col>StrLen(cur_line->line)) {
templ=cur_line->next;
if (templ!=&root) {
cur_col=0;
cur_line=templ;
} else
cur_col=StrLen(cur_line->line);
}
break;
case SC_CURSOR_LEFT:
if (cur_col)
cur_col--;
else {
templ=cur_line->last;
if (templ!=&root) {
cur_line=templ;
cur_col=StrLen(templ->line);
}
}
break;
case SC_PAGE_UP:
for (i=1;i<text_rows;i++) {
if (cur_line->last!=&root)
cur_line=cur_line->last;
if (cur_col>StrLen(cur_line->line))
cur_col=StrLen(cur_line->line);
}
break;
case SC_PAGE_DOWN:
for (i=1;i<text_rows;i++) {
if (cur_line!=&root)
cur_line=cur_line->next;
if (cur_col>StrLen(cur_line->line))
cur_col=StrLen(cur_line->line);
}
break;
case SC_DELETE:
if (cur_col==StrLen(cur_line->line)) {
templ=cur_line->next;
if (cur_line!=&root && templ!=&root) {
src=MAlloc(StrLen(cur_line->line)+StrLen(templ->line)+1);
StrCpy(src,cur_line->line);
StrCat(src,templ->line);
Free(cur_line->line);
Free(templ->line);
cur_line->line=src;
QueRem(templ);
Free(templ);
}
} else
StrCpy(cur_line->line+cur_col,cur_line->line+cur_col+1);
break;
}
break;
case CH_NEW_LINE:
templ=MAlloc(sizeof(CLine));
templ->line=StrNew(cur_line->line+cur_col);
cur_line->line[cur_col]=0;
QueIns(templ,cur_line);
cur_line=templ;
cur_col=0;
break;
case CH_BACKSPACE:
if (cur_col) {
StrCpy(cur_line->line+cur_col-1,cur_line->line+cur_col);
cur_col--;
} else if (cur_line!=&root && cur_line->last!=&root) {
templ=cur_line->last;
src=MAlloc(StrLen(cur_line->line)+StrLen(templ->line)+1);
StrCpy(src,templ->line);
StrCat(src,cur_line->line);
cur_col=StrLen(templ->line);
Free(cur_line->line);
Free(templ->line);
templ->line=src;
QueRem(cur_line);
Free(cur_line);
cur_line=templ;
}
break;
case CH_CTRLY:
if (cur_line!=&root) {
templ=cur_line;
cur_line=cur_line->next;
QueRem(templ);
Free(templ->line);
Free(templ);
cur_col=0;
}
break;
default:
if (CH_SHIFT_SPACE<=ch<=0x7E || ch==CH_TAB || 0x80<=ch<=0xFF) {
if (cur_line==&root) {
cur_line=MAlloc(sizeof(CLine));
cur_line->line=StrNew("");
QueIns(cur_line,root.last);
}
src=MAlloc(StrLen(cur_line->line)+2);
MemCpy(src,cur_line->line,cur_col);
src[cur_col]=ch;
if (cur_col<StrLen(cur_line->line))
StrCpy(src+cur_col+1,cur_line->line+cur_col);
else
src[cur_col+1]=0;
Free(cur_line->line);
cur_line->line=src;
cur_col++;
}
break;
}
} while (ch!=CH_SHIFT_ESC && ch!=CH_ESC);
if (ch==CH_ESC) {
size=bin_size;
templ=root.next;
while (templ!=&root) {
size+=StrLen(templ->line)+1;
templ=templ->next;
}
buf=dst=MAlloc(size);
templ=root.next;
while (templ!=&root) {
i=StrLen(templ->line);
MemCpy(dst,templ->line,i);
dst+=i;
*dst++=CH_NEW_LINE;
templ=templ->next;
}
if (bin_data)
MemCpy(dst,bin_data,bin_size);
FileWrite(filename,buf,size);
Free(buf);
}
templ=root.next;
while (templ!=&root) {
templ1=templ->next;
QueRem(templ);
Free(templ->line);
Free(templ);
templ=templ1;
}
Free(root.line);
Free(bin_data);
Raw(old_raw);
InDbg(old_debug);
SingleUser(old_single);
sys_raw_dc_flags=sys_raw_dc_flags&~RDCF_SHOW_DOLLAR|old_dc_flags&RDCF_SHOW_DOLLAR;
PopFD;
}
+230
View File
@@ -0,0 +1,230 @@
I64 ExceptDepth(CTask *task=NULL)
{
CExcept *tempt;
I64 result=0;
if (!task) task=Fs;
tempt=task->next_except;
while (tempt!=&task->next_except) {
result++;
tempt=tempt->next;
}
return result;
}
asm {
USE64
#assert !((CREG_NON_PTR_MASK|CREG_VARS_MASK)&~0xFCC0)
_TEST_EXCEPT::
XOR RAX,RAX
MOV RAX,FS:U64 CTask.last_except[RAX]
MOV RBP,U64 CExcept.rbp[RAX]
MOV RSI,U64 CExcept.rsi[RAX]
MOV RDI,U64 CExcept.rdi[RAX]
MOV R10,U64 CExcept.r10[RAX]
MOV R11,U64 CExcept.r11[RAX]
MOV R12,U64 CExcept.r12[RAX]
MOV R13,U64 CExcept.r13[RAX]
MOV R14,U64 CExcept.r14[RAX]
MOV R15,U64 CExcept.r15[RAX]
PUSH U64 CExcept.rflags[RAX]
POPFD
JMP U64 CExcept.handler_catch[RAX]
_TAKE_EXCEPT::
XOR RAX,RAX
MOV RAX,FS:U64 CTask.last_except[RAX]
MOV RSP,U64 CExcept.rsp[RAX]
JMP U64 CExcept.handler_untry[RAX]
_SAVE_EXCEPT_REGS::
ENTER 0
MOV RAX,U64 SF_ARG1[RBP]
MOV U64 CExcept.rsi[RAX],RSI
MOV U64 CExcept.rdi[RAX],RDI
MOV U64 CExcept.r10[RAX],R10
MOV U64 CExcept.r11[RAX],R11
MOV U64 CExcept.r12[RAX],R12
MOV U64 CExcept.r13[RAX],R13
MOV U64 CExcept.r14[RAX],R14
MOV U64 CExcept.r15[RAX],R15
LEAVE
RET1 8
}
_extern _TEST_EXCEPT U0 TestExcept();
_extern _TAKE_EXCEPT U0 TakeExcept();
_extern _SAVE_EXCEPT_REGS U0 SaveExceptRegs(CExcept *t);
#exe {OptOn(OPTf_NO_REG_VAR);};
class CTryStk
{
I64 var_tempt;
I64 var_old_flags;
I64 var_rbp;
I64 var_rsp;
I64 rbp;
I64 ret_rip;
I64 arg1;
I64 arg2;
};
U0 SysTry(U8 *catch_start,U8 *untry_start)
{
I64 *rsp=GetStkPtr,*rbp=GetBasePtr,old_flags=GetFlags;
CExcept *tempt=MAlloc(sizeof(CExcept));
tempt->handler_catch=catch_start;
tempt->handler_untry=untry_start;
tempt->rsp=rsp(U8 *)+sizeof(CTryStk);
tempt->rbp=*rbp;
tempt->rflags=old_flags;
SaveExceptRegs(tempt);
Cli;
QueIns(tempt,Fs->last_except);
SetFlags(old_flags);
}
U0 SysUntry()
{
CExcept *tempt=Fs->last_except;
PushFD;
//The adam task sometimes probes except depth,
//so we lock it out. A probe from a multicore
//would fail, but who'd want to do that?
Cli;
QueRem(tempt);
PopFD;
Free(tempt);
}
U0 AdamLogExcept(I64 argc,I64 *argv)
{
I64 i;
if (!Gs->num) { //TODO: Other cores
AdamLog("Depth:%02X Task:%08X throw(",
ExceptDepth(Fs),Fs);
for (i=0;i<argc;i++) {
AdamLog("%X",argv[i]);
if (i<argc-1)
AdamLog(",");
}
AdamLog(");\n");
}
}
U0 PutExcept()
{
I64 i;
if (Fs->except_argc>0) {
if (Fs->except_argv[0]<DefineSubCnt("ST_EXCEPT_TYPES")) {
"Exception Type :%Z\n",Fs->except_argv[0],"ST_EXCEPT_TYPES";
if (Fs->except_argv[0]==EXCEPT_UNDEF_DEFINE)
"Name:'%s'\n",Fs->except_argv[1];
else if (Fs->except_argv[0]==EXCEPT_DIVIDE_BY_ZERO)
"Addr:%P\n",Fs->except_argv[1];
else {
for (i=1;i<Fs->except_argc;i++)
"%016X ",Fs->except_argv[i];
NewLine;
}
} else {
"Exception:";
for (i=0;i<Fs->except_argc;i++)
"%016X ",Fs->except_argv[i];
NewLine;
}
} else
"Generic Exception\n";
}
U0 throw_join(I64 argc,I64 *argv)
{
CExcept *tempt=Fs->last_except;
Bool was_raw;
Fs->except_argc=argc;
Fs->except_argv=argv;
Fs->except_rbp=GetBasePtr;
Fs->catch_except=FALSE;
Fs->ignore_except=FALSE;
while (Fs->next_except!=&Fs->next_except) {
TestExcept;
if (Fs->catch_except)
TakeExcept;
if (Fs->ignore_except)
return;
SetBasePtr(Fs->except_rbp);
tempt=Fs->last_except;
QueRem(tempt);
Free(tempt);
}
was_raw=Raw(ON);
PutExcept;
Dbg("Unhandled Exception");
Raw(was_raw);
}
U0 throw_no_log(...)
{
throw_join(argc,argv);
}
U0 throw(...)
{
AdamLogExcept(argc,argv);
throw_join(argc,argv);
}
#exe {OptOff(OPTf_NO_REG_VAR);};
U0 SysThrowBreak()
{
if (Bt(&Fs->task_flags,TASKf_BREAK_TO_SHIFT_ESC))
Msg(MSG_KEY_DOWN,CH_SHIFT_ESC,0x20100000201);
else { //TODO: Might want lock
Fs->wake_jiffy=0;
TaskRstAwaitingMsg;
PrtsRelease();
BlkDevsRelease();
FlushMsgs;
throw(EXCEPT_BREAK);
}
}
//This can be used to exit an app, but not a task.
U0 ThrowBreak(CTask *task=NULL)
{
if (task && task!=Fs) {
if (!TaskValidate(task)) return;
//TODO: Might want lock
sys_focus_task=task;
LBts(sys_ctrl_alt_flags,SYSf_CTRL_ALT_C);
} else
SysThrowBreak;
}
Bool BreakLock(CTask *task=NULL)
{
if (!task) task=Fs;
return !LBts(&task->task_flags,TASKf_BREAK_LOCKED);
}
Bool BreakUnlock(CTask *task=NULL)
{
Bool result;
if (!task) task=Fs;
result=LBtr(&task->task_flags,TASKf_BREAK_LOCKED);
if (LBtr(&task->task_flags,TASKf_PENDING_BREAK)) {
if (task==Fs)
ThrowBreak;
else
task->rip=&ThrowBreak;
}
return result;
}
U0 CatchAll()
{
PutExcept;
Fs->catch_except=TRUE;
}
+169
View File
@@ -0,0 +1,169 @@
CFifoU8 *FifoU8New(I64 size,CTask *mem_task=NULL)
{
CFifoU8 *f;
if (!mem_task) mem_task=Fs;
f=MAlloc(sizeof(CFifoU8),mem_task);
f->buf=MAlloc(size,mem_task);
f->mask=size-1;
f->in_ptr=0;
f->out_ptr=0;
return f;
}
U0 FifoU8Del(CFifoU8 *f)
{
Free(f->buf);
Free(f);
}
Bool FifoU8Ins(CFifoU8 *f,U8 b)
{
I64 new_in_ptr;
PushFD;
Cli;
new_in_ptr=(f->in_ptr+1)&f->mask;
if (new_in_ptr==f->out_ptr) {
PopFD;
return FALSE;
} else {
f->buf[f->in_ptr]=b;
f->in_ptr=new_in_ptr;
PopFD;
return TRUE;
}
}
Bool FifoU8Rem(CFifoU8 *f,U8 *_b)
{
PushFD;
Cli;
if (f->in_ptr==f->out_ptr) {
PopFD;
return FALSE;
} else {
*_b=f->buf[f->out_ptr];
f->out_ptr=(f->out_ptr+1)&f->mask;
PopFD;
return TRUE;
}
}
Bool FifoU8Peek(CFifoU8 *f,U8 *_b)
{
PushFD;
Cli;
if (f->in_ptr==f->out_ptr) {
PopFD;
return FALSE;
} else {
*_b=f->buf[f->out_ptr];
PopFD;
return TRUE;
}
}
U0 FifoU8Flush(CFifoU8 *f)
{
PushFD;
Cli;
f->out_ptr=f->in_ptr;
PopFD;
}
I64 FifoU8Cnt(CFifoU8 *f)
{
I64 result;
PushFD;
Cli;
if (f->out_ptr>f->in_ptr)
result=f->mask+1-(f->out_ptr-f->in_ptr);
else
result=f->in_ptr-f->out_ptr;
PopFD;
return result;
}
CFifoI64 *FifoI64New(I64 size,CTask *mem_task=NULL)
{
CFifoI64 *f;
if (!mem_task) mem_task=Fs;
f=MAlloc(sizeof(CFifoI64),mem_task);
f->buf=MAlloc(size*sizeof(I64),mem_task);
f->mask=size-1;
f->in_ptr=0;
f->out_ptr=0;
return f;
}
U0 FifoI64Del(CFifoI64 *f)
{
Free(f->buf);
Free(f);
}
Bool FifoI64Ins(CFifoI64 *f,I64 q)
{
I64 new_in_ptr;
PushFD;
Cli;
new_in_ptr=(f->in_ptr+1)&f->mask;
if (new_in_ptr==f->out_ptr) {
PopFD;
return FALSE;
} else {
f->buf[f->in_ptr]=q;
f->in_ptr=new_in_ptr;
PopFD;
return TRUE;
}
}
Bool FifoI64Rem(CFifoI64 *f,I64 *_q)
{
PushFD;
Cli;
if (f->in_ptr==f->out_ptr) {
PopFD;
return FALSE;
} else {
*_q=f->buf[f->out_ptr];
f->out_ptr=(f->out_ptr+1)&f->mask;
PopFD;
return TRUE;
}
}
Bool FifoI64Peek(CFifoI64 *f,I64 *_q)
{
PushFD;
Cli;
if (f->in_ptr==f->out_ptr) {
PopFD;
return FALSE;
} else {
*_q=f->buf[f->out_ptr];
PopFD;
return TRUE;
}
}
U0 FifoI64Flush(CFifoI64 *f)
{
PushFD;
Cli;
f->out_ptr=f->in_ptr;
PopFD;
}
I64 FifoI64Cnt(CFifoI64 *f)
{
I64 result;
PushFD;
Cli;
if (f->out_ptr>f->in_ptr)
result=f->mask+1-(f->out_ptr-f->in_ptr);
else
result=f->in_ptr-f->out_ptr;
PopFD;
return result;
}
+261
View File
@@ -0,0 +1,261 @@
//See $LK,"::/SparrowOS/Doc/Acknowledgements.TXT.Z","FI:::/SparrowOS/Doc/Acknowledgements.TXT.Z"$ (1).
U8 sys_font_8x8[256*8]= {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x18,0x3C,0x3C,0x18,0x18,0x00,0x18,0x00,
0x36,0x36,0x36,0x00,0x00,0x00,0x00,0x00,
0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00,
0x30,0xFC,0x16,0x7C,0xD0,0x7E,0x18,0x00,
0x06,0x66,0x30,0x18,0x0C,0x66,0x60,0x00,
0x1C,0x36,0x36,0x1C,0xB6,0x66,0xDC,0x00,
0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00,
0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00,
0x00,0x18,0x7E,0x3C,0x7E,0x18,0x00,0x00,
0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x0C,
0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,
0x00,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,
0x3C,0x66,0x76,0x7E,0x6E,0x66,0x3C,0x00,
0x18,0x1C,0x18,0x18,0x18,0x18,0x7E,0x00,
0x3C,0x66,0x60,0x30,0x18,0x0C,0x7E,0x00,
0x3C,0x66,0x60,0x38,0x60,0x66,0x3C,0x00,
0x30,0x38,0x3C,0x36,0x7E,0x30,0x30,0x00,
0x7E,0x06,0x3E,0x60,0x60,0x66,0x3C,0x00,
0x38,0x0C,0x06,0x3E,0x66,0x66,0x3C,0x00,
0x7E,0x60,0x30,0x18,0x0C,0x0C,0x0C,0x00,
0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00,
0x3C,0x66,0x66,0x7C,0x60,0x30,0x1C,0x00,
0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x00,
0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x0C,
0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00,
0x00,0x00,0x7E,0x00,0x7E,0x00,0x00,0x00,
0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00,
0x3C,0x66,0x30,0x18,0x18,0x00,0x18,0x00,
0x3C,0x66,0x76,0x56,0x76,0x06,0x3C,0x00,
0x3C,0x66,0x66,0x7E,0x66,0x66,0x66,0x00,
0x3E,0x66,0x66,0x3E,0x66,0x66,0x3E,0x00,
0x3C,0x66,0x06,0x06,0x06,0x66,0x3C,0x00,
0x1E,0x36,0x66,0x66,0x66,0x36,0x1E,0x00,
0x7E,0x06,0x06,0x3E,0x06,0x06,0x7E,0x00,
0x7E,0x06,0x06,0x3E,0x06,0x06,0x06,0x00,
0x3C,0x66,0x06,0x76,0x66,0x66,0x3C,0x00,
0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00,
0x7E,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,
0x7C,0x30,0x30,0x30,0x30,0x36,0x1C,0x00,
0x66,0x36,0x1E,0x0E,0x1E,0x36,0x66,0x00,
0x06,0x06,0x06,0x06,0x06,0x06,0x7E,0x00,
0xC6,0xEE,0xFE,0xD6,0xD6,0xC6,0xC6,0x00,
0x66,0x66,0x6E,0x7E,0x76,0x66,0x66,0x00,
0x3C,0x66,0x66,0x66,0x66,0x66,0x3C,0x00,
0x3E,0x66,0x66,0x3E,0x06,0x06,0x06,0x00,
0x3C,0x66,0x66,0x66,0x56,0x36,0x6C,0x00,
0x3E,0x66,0x66,0x3E,0x36,0x66,0x66,0x00,
0x3C,0x66,0x06,0x3C,0x60,0x66,0x3C,0x00,
0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x00,
0x66,0x66,0x66,0x66,0x66,0x66,0x3C,0x00,
0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,
0xC6,0xC6,0xD6,0xD6,0xFE,0xEE,0xC6,0x00,
0x66,0x66,0x3C,0x18,0x3C,0x66,0x66,0x00,
0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x00,
0x7E,0x60,0x30,0x18,0x0C,0x06,0x7E,0x00,
0x3E,0x06,0x06,0x06,0x06,0x06,0x3E,0x00,
0x00,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,
0x7C,0x60,0x60,0x60,0x60,0x60,0x7C,0x00,
0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,
0x0C,0x18,0x30,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x3C,0x60,0x7C,0x66,0x7C,0x00,
0x06,0x06,0x3E,0x66,0x66,0x66,0x3E,0x00,
0x00,0x00,0x3C,0x66,0x06,0x66,0x3C,0x00,
0x60,0x60,0x7C,0x66,0x66,0x66,0x7C,0x00,
0x00,0x00,0x3C,0x66,0x7E,0x06,0x3C,0x00,
0x38,0x0C,0x0C,0x3E,0x0C,0x0C,0x0C,0x00,
0x00,0x00,0x7C,0x66,0x66,0x7C,0x60,0x3C,
0x06,0x06,0x3E,0x66,0x66,0x66,0x66,0x00,
0x18,0x00,0x1C,0x18,0x18,0x18,0x3C,0x00,
0x18,0x00,0x1C,0x18,0x18,0x18,0x18,0x0E,
0x06,0x06,0x66,0x36,0x1E,0x36,0x66,0x00,
0x1C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,
0x00,0x00,0x6C,0xFE,0xD6,0xD6,0xC6,0x00,
0x00,0x00,0x3E,0x66,0x66,0x66,0x66,0x00,
0x00,0x00,0x3C,0x66,0x66,0x66,0x3C,0x00,
0x00,0x00,0x3E,0x66,0x66,0x3E,0x06,0x06,
0x00,0x00,0x7C,0x66,0x66,0x7C,0x60,0xE0,
0x00,0x00,0x36,0x6E,0x06,0x06,0x06,0x00,
0x00,0x00,0x7C,0x06,0x3C,0x60,0x3E,0x00,
0x0C,0x0C,0x3E,0x0C,0x0C,0x0C,0x38,0x00,
0x00,0x00,0x66,0x66,0x66,0x66,0x7C,0x00,
0x00,0x00,0x66,0x66,0x66,0x3C,0x18,0x00,
0x00,0x00,0xC6,0xD6,0xD6,0xFE,0x6C,0x00,
0x00,0x00,0x66,0x3C,0x18,0x3C,0x66,0x00,
0x00,0x00,0x66,0x66,0x66,0x7C,0x60,0x3C,
0x00,0x00,0x7E,0x30,0x18,0x0C,0x7E,0x00,
0x30,0x18,0x18,0x0E,0x18,0x18,0x30,0x00,
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,
0x0C,0x18,0x18,0x70,0x18,0x18,0x0C,0x00,
0x8C,0xD6,0x62,0x00,0x00,0x00,0x00,0x00,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x1E,0x33,0x03,0x33,0x1E,0x18,0x30,0x1E,
0x00,0x33,0x00,0x33,0x33,0x33,0x7E,0x00,
0x38,0x00,0x1E,0x33,0x3F,0x03,0x1E,0x00,
0x7E,0xC3,0x3C,0x60,0x7C,0x66,0xFC,0x00,
0x33,0x00,0x1E,0x30,0x3E,0x33,0x7E,0x00,
0x07,0x00,0x1E,0x30,0x3E,0x33,0x7E,0x00,
0x0C,0x0C,0x1E,0x30,0x3E,0x33,0x7E,0x00,
0x00,0x00,0x3E,0x03,0x03,0x3E,0x60,0x3C,
0x7E,0xC3,0x3C,0x66,0x7E,0x06,0x3C,0x00,
0x33,0x00,0x1E,0x33,0x3F,0x03,0x1E,0x00,
0x07,0x00,0x1E,0x33,0x3F,0x03,0x1E,0x00,
0x33,0x00,0x0E,0x0C,0x0C,0x0C,0x1E,0x00,
0x3E,0x63,0x1C,0x18,0x18,0x18,0x3C,0x00,
0x07,0x00,0x0E,0x0C,0x0C,0x0C,0x1E,0x00,
0x33,0x0C,0x1E,0x33,0x33,0x3F,0x33,0x00,
0x0C,0x0C,0x00,0x1E,0x33,0x3F,0x33,0x00,
0x38,0x00,0x3F,0x06,0x1E,0x06,0x3F,0x00,
0x00,0x00,0xFE,0x30,0xFE,0x33,0xFE,0x00,
0x7C,0x36,0x33,0x7F,0x33,0x33,0x73,0x00,
0x1E,0x33,0x00,0x1E,0x33,0x33,0x1E,0x00,
0x00,0x33,0x00,0x1E,0x33,0x33,0x1E,0x00,
0x00,0x07,0x00,0x1E,0x33,0x33,0x1E,0x00,
0x1E,0x33,0x00,0x33,0x33,0x33,0x7E,0x00,
0x00,0x07,0x00,0x33,0x33,0x33,0x7E,0x00,
0x00,0x33,0x00,0x33,0x33,0x3F,0x30,0x1F,
0x63,0x1C,0x3E,0x63,0x63,0x3E,0x1C,0x00,
0x33,0x00,0x33,0x33,0x33,0x33,0x1E,0x00,
0x18,0x18,0x7E,0x03,0x03,0x7E,0x18,0x18,
0x1C,0x36,0x26,0x0F,0x06,0x67,0x3F,0x00,
0x33,0x33,0x1E,0x3F,0x0C,0x3F,0x0C,0x00,
0x0F,0x1B,0x1B,0x2F,0x33,0x7B,0x33,0x70,
0x70,0xD8,0x18,0x7E,0x18,0x18,0x1B,0x0E,
0x38,0x00,0x1E,0x30,0x3E,0x33,0x7E,0x00,
0x1C,0x00,0x0E,0x0C,0x0C,0x0C,0x1E,0x00,
0x00,0x38,0x00,0x1E,0x33,0x33,0x1E,0x00,
0x00,0x38,0x00,0x33,0x33,0x33,0x7E,0x00,
0x00,0x1F,0x00,0x1F,0x33,0x33,0x33,0x00,
0x3F,0x00,0x33,0x37,0x3F,0x3B,0x33,0x00,
0x3C,0x36,0x36,0x7C,0x00,0x7E,0x00,0x00,
0x3C,0x66,0x66,0x3C,0x00,0x7E,0x00,0x00,
0x0C,0x00,0x0C,0x06,0x03,0x33,0x1E,0x00,
0x00,0x00,0x00,0x3F,0x03,0x03,0x00,0x00,
0x00,0x00,0x00,0x3F,0x30,0x30,0x00,0x00,
0x63,0x33,0x1B,0x7C,0xC6,0x73,0x19,0xF8,
0x63,0x33,0x1B,0xCF,0xE6,0xF3,0xF9,0xC0,
0x00,0x18,0x00,0x18,0x18,0x3C,0x3C,0x18,
0x00,0xCC,0x66,0x33,0x66,0xCC,0x00,0x00,
0x00,0x33,0x66,0xCC,0x66,0x33,0x00,0x00,
0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,
0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,
0xBB,0xEE,0xBB,0xEE,0xBB,0xEE,0xBB,0xEE,
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18,
0x18,0x18,0x1F,0x18,0x1F,0x18,0x18,0x18,
0x6C,0x6C,0x6C,0x6C,0x6F,0x6C,0x6C,0x6C,
0x00,0x00,0x00,0x00,0x7F,0x6C,0x6C,0x6C,
0x00,0x00,0x1F,0x18,0x1F,0x18,0x18,0x18,
0x6C,0x6C,0x6F,0x60,0x6F,0x6C,0x6C,0x6C,
0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,
0x00,0x00,0x7F,0x60,0x6F,0x6C,0x6C,0x6C,
0x6C,0x6C,0x6F,0x60,0x7F,0x00,0x00,0x00,
0x6C,0x6C,0x6C,0x6C,0x7F,0x00,0x00,0x00,
0x18,0x18,0x1F,0x18,0x1F,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x1F,0x18,0x18,0x18,
0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00,
0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,
0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18,
0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,
0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,
0x18,0x18,0xF8,0x18,0xF8,0x18,0x18,0x18,
0x6C,0x6C,0x6C,0x6C,0xEC,0x6C,0x6C,0x6C,
0x6C,0x6C,0xEC,0x0C,0xFC,0x00,0x00,0x00,
0x00,0x00,0xFC,0x0C,0xEC,0x6C,0x6C,0x6C,
0x6C,0x6C,0xEF,0x00,0xFF,0x00,0x00,0x00,
0x00,0x00,0xFF,0x00,0xEF,0x6C,0x6C,0x6C,
0x6C,0x6C,0xEC,0x0C,0xEC,0x6C,0x6C,0x6C,
0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,
0x6C,0x6C,0xEF,0x00,0xEF,0x6C,0x6C,0x6C,
0x18,0x18,0xFF,0x00,0xFF,0x00,0x00,0x00,
0x6C,0x6C,0x6C,0x6C,0xFF,0x00,0x00,0x00,
0x00,0x00,0xFF,0x00,0xFF,0x18,0x18,0x18,
0x00,0x00,0x00,0x00,0xFF,0x6C,0x6C,0x6C,
0x6C,0x6C,0x6C,0x6C,0xFC,0x00,0x00,0x00,
0x18,0x18,0xF8,0x18,0xF8,0x00,0x00,0x00,
0x00,0x00,0xF8,0x18,0xF8,0x18,0x18,0x18,
0x00,0x00,0x00,0x00,0xFC,0x6C,0x6C,0x6C,
0x6C,0x6C,0x6C,0x6C,0xEF,0x6C,0x6C,0x6C,
0x18,0x18,0xFF,0x00,0xFF,0x18,0x18,0x18,
0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,
0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,
0x00,0x00,0x6E,0x3B,0x13,0x3B,0x6E,0x00,
0x00,0x1E,0x33,0x1F,0x33,0x1F,0x03,0x03,
0x00,0x7F,0x63,0x03,0x03,0x03,0x03,0x00,
0x00,0x7F,0x36,0x36,0x36,0x36,0x36,0x00,
0x7F,0x66,0x0C,0x18,0x0C,0x66,0x7F,0x00,
0x00,0x00,0x7E,0x33,0x33,0x33,0x1E,0x00,
0x00,0x66,0x66,0x66,0x66,0x3E,0x06,0x03,
0x00,0x6E,0x3B,0x18,0x18,0x18,0x18,0x00,
0x3F,0x0C,0x1E,0x33,0x33,0x1E,0x0C,0x3F,
0x1C,0x36,0x63,0x7F,0x63,0x36,0x1C,0x00,
0x1C,0x36,0x63,0x63,0x36,0x36,0x77,0x00,
0x38,0x0C,0x18,0x3E,0x33,0x33,0x1E,0x00,
0x00,0x00,0x7E,0xDB,0xDB,0x7E,0x00,0x00,
0x60,0x30,0x7E,0xDB,0xDB,0x7E,0x06,0x03,
0x3C,0x06,0x03,0x3F,0x03,0x06,0x3C,0x00,
0x1E,0x33,0x33,0x33,0x33,0x33,0x33,0x00,
0x00,0x3F,0x00,0x3F,0x00,0x3F,0x00,0x00,
0x0C,0x0C,0x3F,0x0C,0x0C,0x00,0x3F,0x00,
0x06,0x0C,0x18,0x0C,0x06,0x00,0x3F,0x00,
0x18,0x0C,0x06,0x0C,0x18,0x00,0x3F,0x00,
0x70,0xD8,0xD8,0x18,0x18,0x18,0x18,0x18,
0x18,0x18,0x18,0x18,0x18,0x1B,0x1B,0x0E,
0x0C,0x0C,0x00,0x3F,0x00,0x0C,0x0C,0x00,
0x00,0x4E,0x39,0x00,0x4E,0x39,0x00,0x00,
0x1C,0x36,0x36,0x1C,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,
0xF0,0x30,0x30,0x30,0x37,0x36,0x3C,0x38,
0x1E,0x36,0x36,0x36,0x36,0x00,0x00,0x00,
0x1E,0x30,0x1C,0x06,0x3E,0x00,0x00,0x00,
0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
+802
View File
@@ -0,0 +1,802 @@
/****
$SP,"<1>",1$
Tasks have symbol tables. If symbol not found, parent task's table
is searched. Adam task has system-wide symbols.
SYMBOL LOOK-UP (Especially, used by JIT compiler and Loader)
1) Symbol text name is hashed -- Adding the ASCII values of all
chars with shifts.
2) Hash body array is indexed.
3) Linked-list is traversed until match of text and type-of-entry
4) If not found, next hash table is searched.
Duplicate entries are allowed--they overshadow old entries.
ADDRESS-TO-SYMBOL LOOK-UP (Slow because not important--could add tree)
1)PSect Cache is scanned.
2)"next_added,last_added" que links are traversed. This speeds look-up
instead of scanning hash table because hash table is so sparce.
See $LK,"PSectFind","MN:PSectFind"$().
****/
asm {
USE64
// ************************************
// IN: RSI=Addr of string
// OUT: RAX
SYS_HASH_STR::
XOR RAX,RAX
OR RSI,RSI
JZ @@15
PUSH RSI
PUSH RBX
XOR RBX,RBX
JMP @@10
@@05: SHL1 RBX
ADC RBX,RAX
@@10: LODSB
OR AL,AL
JNZ @@05
MOV RAX,RBX
SHR RBX,16
ADC RAX,RBX
POP RBX
POP RSI
@@15: RET
// ************************************
// IN: RAX=HASHED_STRING
// RSI=STR
// RBX=TYPE MASK
// RDI=TABLE
// RCX=INSTANCE, NOT ZERO
// OUT: RAX=ENTRY OR ZERO NOT FOUND
// RDX=POINTER TO POINTER TO ENTRY
// RCX IF NOT FOUND ENOUGH, DECREMENTED BY NUM MATCHES
// ZERO FLAG SET NOT FOUND
SYS_HASH_SINGLE_TABLE_FIND1::
MOV RCX,1
SYS_HASH_SINGLE_TABLE_FIND::
OR RCX,RCX
JNZ @@05
XOR RAX,RAX
RET
@@05: AND RAX,U64 CHashTable.mask[RDI]
MOV RDX,U64 CHashTable.body[RDI]
LEA RDX,U64 [RDX+RAX*8]
@@10: MOV RAX,U64 [RDX]
OR RAX,RAX
JNZ @@15
RET
@@15: TEST U32 CHash.type[RAX],EBX
JZ @@30
PUSH RAX
PUSH RDI
PUSH RSI
MOV RDI,U64 CHash.str[RAX]
@@20: LODSB
CMP U8 [RDI],AL
JNE @@25
INC RDI
OR AL,AL
JNZ @@20
POP RSI
POP RDI
POP RAX
LOOP @@30
INC U32 CHash.use_cnt[RAX]
OR RAX,RAX
RET
@@25: POP RSI
POP RDI
POP RAX
@@30: LEA RDX,U64 CHash.next[RAX]
JMP @@10
// ************************************
// IN: RSI=STR
// RBX=TYPE MASK
// RDI=TABLE
// RCX=INSTANCE NUM
// OUT: RAX=ENTRY OR ZERO NOT FOUND
// ZERO FLAG SET NOT FOUND
SYS_HASH_FIND1::
MOV RCX,1
SYS_HASH_FIND::
PUSH RDI
CALL SYS_HASH_STR
@@05: PUSH RAX
CALL SYS_HASH_SINGLE_TABLE_FIND
JNZ @@15
POP RAX
@@10: MOV RDI,U64 CHashTable.next[RDI]
OR RDI,RDI
JNZ @@05
POP RDI
XOR RAX,RAX
RET
@@15: ADD RSP,8
POP RDI
OR RAX,RAX
RET
// ************************************
// IN: RSI=STR
// RDI=TABLE
// OUT: RAX=BUCKET
SYS_HASH_BUCKET_FIND::
PUSH RDX
CALL SYS_HASH_STR
AND RAX,U64 CHashTable.mask[RDI]
MOV RDX,U64 CHashTable.body[RDI]
LEA RAX,U64 [RDX+RAX*8]
POP RDX
RET
// ************************************
//IN: RSI
// RCX=INSTANCE
//OUT: RAX
// ZERO FLAG SET NOT FOUND
SYS_EXT_FIND1::
MOV RCX,1
SYS_EXT_FIND::
PUSH RDI
PUSH RBX
XOR RAX,RAX
MOV RDI,U64 FS:CTask.hash_table[RAX]
MOV RBX,HTT_FUN|HTT_EXPORT_SYS_SYM
CALL SYS_HASH_FIND
JZ @@15
@@05: TEST U32 CHash.type[RAX],HTT_FUN
JZ @@10
MOV RAX,U64 CHashFun.executable_addr[RAX]
JMP @@15
@@10: MOV RAX,U64 CHashExport.val[RAX]
@@15: POP RBX
POP RDI
OR RAX,RAX
RET
_EXT_FIND::
ENTER 0
PUSH RSI
PUSH RDI
XOR RAX,RAX
MOV RDI,U64 FS:CTask.hash_table[RAX]
MOV RSI,U64 SF_ARG1[RBP]
MOV RCX,U64 SF_ARG2[RBP]
MOV RBX,HTT_FUN|HTT_EXPORT_SYS_SYM
CALL SYS_HASH_FIND
JZ @@15
@@05: TEST U32 CHash.type[RAX],HTT_FUN
JZ @@10
MOV RAX,U64 CHashFun.executable_addr[RAX]
JMP @@15
@@10: MOV RAX,U64 CHashExport.val[RAX]
@@15: POP RDI
POP RSI
LEAVE
RET1 16
// ************************************
_HASH_STR::
ENTER 0
PUSH RSI
MOV RSI,U64 SF_ARG1[RBP]
CALL SYS_HASH_STR
POP RSI
LEAVE
RET1 8
// ************************************
_HASH_FIND::
ENTER 0
PUSH RSI
PUSH RDI
MOV RSI,U64 SF_ARG1[RBP]
MOV RDI,U64 SF_ARG2[RBP]
MOV RBX,U64 SF_ARG3[RBP]
MOV RCX,U64 SF_ARG4[RBP]
CALL SYS_HASH_FIND
POP RDI
POP RSI
LEAVE
RET1 32
// ************************************
_HASH_SINGLE_TABLE_FIND::
ENTER 0
PUSH RSI
PUSH RDI
MOV RSI,U64 SF_ARG1[RBP]
MOV RDI,U64 SF_ARG2[RBP]
MOV RBX,U64 SF_ARG3[RBP]
MOV RCX,U64 SF_ARG4[RBP]
CALL SYS_HASH_STR
CALL SYS_HASH_SINGLE_TABLE_FIND
POP RDI
POP RSI
LEAVE
RET1 32
// ************************************
_HASH_BUCKET_FIND::
ENTER 0
PUSH RSI
PUSH RDI
MOV RSI,U64 SF_ARG1[RBP]
MOV RDI,U64 SF_ARG2[RBP]
CALL SYS_HASH_BUCKET_FIND
POP RDI
POP RSI
LEAVE
RET1 16
// ************************************
_HASH_ADD::
ENTER 0
PUSH RSI
PUSH RDI
MOV RCX,U64 SF_ARG1[RBP]
MOV RSI,U64 CHash.str[RCX]
MOV RDI,U64 SF_ARG2[RBP]
CALL SYS_HASH_BUCKET_FIND
MOV RCX,U64 SF_ARG1[RBP]
PUSHFD
CLI
MOV RBX,U64 [RAX]
MOV U64 CHash.next[RCX],RBX
MOV U64 [RAX],RCX
//Queins
MOV RBX,U64 CHashTable.last_added[RDI]
MOV U64 CHash.last_added[RCX],RBX
MOV U64 CHash.next_added[RBX],RCX
MOV U64 CHashTable.last_added[RDI],RCX
MOV U64 CHash.next_added[RCX],RDI
POPFD
POP RDI
POP RSI
LEAVE
RET1 16
// ************************************
_HASH_ADD_AFTER::
ENTER 0
PUSH RDI
MOV RCX,U64 SF_ARG1[RBP]
MOV RDI,U64 SF_ARG3[RBP]
PUSHFD
CLI
MOV RAX,SF_ARG2[RBP]
MOV RBX,U64 [RAX]
MOV U64 CHash.next[RCX],RBX
MOV U64 [RAX],RCX
//QueIns
MOV RBX,U64 CHashTable.last_added[RDI]
MOV U64 CHash.last_added[RCX],RBX
MOV U64 CHash.next_added[RBX],RCX
MOV U64 CHashTable.last_added[RDI],RCX
MOV U64 CHash.next_added[RCX],RDI
POPFD
POP RDI
LEAVE
RET1 24
// ************************************
_HASH_REPLACE::
ENTER 0
PUSH RSI
PUSH RDI
MOV RCX,U64 SF_ARG1[RBP]
OR RCX,RCX
JZ @@15
MOV RSI,U64 CHash.str[RCX]
XOR RBX,RBX
MOV EBX,U32 CHash.type[RCX]
AND EBX,~HTF_FLAGS_MASK&0xFFFFFFFF
MOV RDI,U64 SF_ARG2[RBP]
MOV RCX,U64 SF_ARG3[RBP]
CALL SYS_HASH_STR
PUSHFD
CLI
CALL SYS_HASH_SINGLE_TABLE_FIND
MOV RCX,U64 SF_ARG1[RBP]
JZ @@05 //Z set by find
//QueRem/QueIns
MOV RBX,U64 CHash.next_added[RAX]
MOV U64 CHash.next_added[RCX],RBX
MOV U64 CHash.last_added[RBX],RCX
MOV RBX,U64 CHash.last_added[RAX]
MOV U64 CHash.last_added[RCX],RBX
MOV U64 CHash.next_added[RBX],RCX
MOV RBX,U64 CHash.next[RAX]
JMP @@10
//QueIns
@@05: MOV RBX,U64 CHashTable.last_added[RDI]
MOV U64 CHash.last_added[RCX],RBX
MOV U64 CHash.next_added[RBX],RCX
MOV U64 CHashTable.last_added[RDI],RCX
MOV U64 CHash.next_added[RCX],RDI
MOV RBX,RAX
@@10: MOV U64 CHash.next[RCX],RBX
MOV U64 [RDX],RCX
POPFD
OR RAX,RAX
JZ @@15
PUSH_C_REGS
PUSH RAX
CALL &HashDel
POP_C_REGS
@@15: POP RDI
POP RSI
LEAVE
RET1 24
// ************************************
_HASH_REM_DEL::
ENTER 0
PUSH RSI
PUSH RDI
MOV RCX,U64 SF_ARG1[RBP]
OR RCX,RCX
JZ @@10
MOV RSI,U64 CHash.str[RCX]
XOR RBX,RBX
MOV EBX,U32 CHash.type[RCX]
AND EBX,~HTF_FLAGS_MASK&0xFFFFFFFF
MOV RDI,U64 SF_ARG2[RBP]
MOV RCX,U64 SF_ARG3[RBP]
CALL SYS_HASH_STR
PUSHFD
CLI
CALL SYS_HASH_SINGLE_TABLE_FIND
JZ @@05
CMP RAX,U64 SF_ARG1[RBP]
JNE @@05
MOV RBX,U64 CHash.next[RAX]
MOV U64 [RDX],RBX
//QueRem
MOV RBX,U64 CHash.next_added[RAX]
MOV RDX,U64 CHash.last_added[RAX]
MOV U64 CHash.next_added[RDX],RBX
MOV U64 CHash.last_added[RBX],RDX
POPFD
PUSH_C_REGS
PUSH RAX
CALL &HashDel
POP_C_REGS
POP RDI
POP RSI
MOV RAX,1
LEAVE
RET1 24
@@05: POPFD
@@10: POP RDI
POP RSI
XOR RAX,RAX
LEAVE
RET1 24
}
_extern _HASH_STR I64 HashStr(U8 *st);
_extern _HASH_FIND CHash *
HashFind(U8 *st,CHashTable *table,I64 mask,I64 instance=1);
_extern _HASH_SINGLE_TABLE_FIND CHash *
HashSingleTableFind(U8 *st,CHashTable *table,I64 mask,I64 instance=1);
_extern _HASH_BUCKET_FIND CHash **
HashBucketFind(U8 *st,CHashTable *table);
_extern _HASH_ADD U0 HashAdd(CHash *temph,CHashTable *table);
_extern _HASH_REPLACE U0 HashReplace(CHash *temph,CHashTable *table,
I64 instance=1);//instance must match temph's
_extern _HASH_REM_DEL Bool HashRemDel(CHash *temph,CHashTable *table,
I64 instance=1);//instance must match temph's
I64 HashTypeNum(CHash *temph)
{
if (temph)
return Bsf(temph->type&HTT_TYPE_MASK);
else
return -1;
}
CHashTable *HashTableNew(I64 size,CTask *mem_task=NULL)
{
CHashTable *tempht;
tempht=CAlloc(sizeof(CHashTable),mem_task);
tempht->body=CAlloc(size<<3,mem_task);
tempht->mask=size-1;
tempht->next_added=tempht->last_added=tempht;
return tempht;
}
U0 HashDel(CHashSrcSym *temph)
{
if (!temph) return;
if (!(temph->type&HTT_DICT_WORD))
Free(temph->str);
if (temph->type & HTG_SRC_SYM) {
Free(temph->src_link);
Free(temph->index);
Free(temph->import_name);
LinkedListDel(temph->list);
if (temph->type & (HTT_FUN | HTT_EXPORT_SYS_SYM)) {
Free(temph->debug);
Free(temph->indent);
}
if (temph->type & (HTT_FUN | HTT_CLASS))
//Assumes code not on heap, so doesn't Free.
//$LK,"MemberListDel","MN:MemberListDel"$() is an import to the OSMain module
MemberListDel(temph);
else if (temph->type&HTT_DEFINE_STR)
Free(temph(CHashDefineStr *)->data);
else if (temph->type & HTT_GLBL_VAR) {
if (!(temph(CHashGlblVar *)->flags&GVAF_ALIAS))
Free(temph(CHashGlblVar *)->data_addr);
LinkedListDel(temph(CHashGlblVar *)->dim.next);
if (temph(CHashGlblVar *)->fun_ptr)
HashDel(temph(CHashGlblVar *)->fun_ptr-temph(CHashGlblVar *)->fun_ptr->ptr_cnt);
}
} else if (temph->type & HTT_FILE)
Free(temph(CHashGeneric *)->user_data0);
Free(temph);
}
U0 HashTableDel(CHashTable *tempht)
{
CHashSrcSym *temph,*temph1;
if (!tempht) return;
temph=tempht->next_added;
while (temph!=tempht) {
temph1=temph->next_added;
HashDel(temph);
temph=temph1;
}
Free(tempht->body);
Free(tempht);
}
CHashGeneric *HashGenericAdd(U8 *name,I64 type,I64 u0=0,I64 u1=0,I64 u2=0,CTask *task=NULL)
{
if (!task) task=Fs;
CHashGeneric *result=CAlloc(sizeof(CHashGeneric),task);
result->type=type;
result->user_data0=u0;
result->user_data1=u1;
result->user_data2=u2;
result->str=StrNew(name,task);
HashAdd(result,task->hash_table);
return result;
}
I64 NamedFramePtr(U8 *name,CTask *task=NULL)
{
CHashGeneric *temph;
if (!task) task=Fs;
if (temph=HashFind(name,task->hash_table,HTT_NAMED_FRAME_PTR))
return temph->user_data0;
else
return 0;
}
CHashGeneric *NamedFramePtrAdd(U8 *name,I64 u0,CTask *task=NULL)
{
return HashGenericAdd(name,HTT_NAMED_FRAME_PTR,u0,0,0,task);
}
I64 NamedFramePtrSet(U8 *name,I64 u0,CTask *task=NULL)
{
CHashGeneric *temph;
if (!task) task=Fs;
if (temph=HashFind(name,task->hash_table,HTT_NAMED_FRAME_PTR))
return LXchgU64(&temph->user_data0,u0);
else
return 0;
}
I64 NamedFramePtrDel(U8 *name,CTask *task=NULL)
{
CHashGeneric *temph;
I64 result=0;
if (!task) task=Fs;
if (temph=HashFind(name,task->hash_table,HTT_NAMED_FRAME_PTR)) {
result=temph->user_data0;
HashRemDel(temph,task->hash_table);
}
return result;
}
U0 LoadOneImport(U8 **_src,U8 *module_base,I64 ld_flags)
{
U8 *src=*_src,*ptr2,*st_ptr;
I64 i,etype;
CHashExport *tempess=NULL;
CHashImport *tempiss;
Bool first=TRUE;
CHashFun *tempf;
CHashGlblVar *tempg;
while (etype=*src++) {
i=*src(U32 *)++;
st_ptr=src;
src+=StrLen(st_ptr)+1;
if (*st_ptr) {
if (!first) {
*_src=st_ptr-5;
return;
} else {
first=FALSE;
if (!(tempess=HashFind(st_ptr,Fs->hash_table,HTG_ALL-HTT_IMPORT_SYS_SYM))) {
if (!(ld_flags & LDF_SILENT)) {
PutDefine("ST_UNRESOLVED_REFERENCE");
"" st_ptr;
NewLine;
}
tempiss=CAlloc(sizeof(CHashImport));
tempiss->str=StrNew(st_ptr);
tempiss->type=HTT_IMPORT_SYS_SYM;
tempiss->module_header_entry=st_ptr-5;
tempiss->module_base=module_base;
HashAdd(tempiss,Fs->hash_table);
}
}
}
if (tempess) {
ptr2=module_base+i;
if (tempess->type & HTT_FUN) {
tempf=tempess;
if (etype & 1)
i=tempf->executable_addr;
else
i=tempf->executable_addr-module_base;
} else if (tempess->type & HTT_GLBL_VAR) {
tempg=tempess;
if (etype & 1)
i=tempg->data_addr;
else
i=tempg->data_addr-module_base;
} else {
if (etype & 1)
i=tempess->val;
else
i=tempess->val(U8 *)-module_base;
}
if (etype<=EIE_LIT_U8)
*ptr2(U8 *)+=i;
else if (etype<=EIE_LIT_U16)
*ptr2(U16 *)+=i;
else if (etype<=EIE_LIT_U32)
*ptr2(U32 *)+=i;
else if (etype<=EIE_LIT_U64)
*ptr2(I64 *)+=i;
}
}
*_src=src-1;
}
U0 SysSymImportsResolve(U8 *st_ptr,I64 ld_flags)
{
CHashImport *tempiss;
U8 *ptr;
while (tempiss=HashSingleTableFind(st_ptr,Fs->hash_table,HTT_IMPORT_SYS_SYM)) {
ptr=tempiss->module_header_entry;
LoadOneImport(&ptr,tempiss->module_base,ld_flags);
tempiss->type=HTT_INVALID;
}
}
U0 LoadPass1(U8 *src,U8 *module_base,I64 ld_flags)
{
U8 *ptr2,*ptr3,*st_ptr;
I64 i,j,cnt,etype;
CHashExport *tempess=NULL;
while (etype=*src++) {
i=*src(U32 *)++;
st_ptr=src;
src+=StrLen(st_ptr)+1;
switch (etype) {
case EIE_REL_EXPORT:
case EIE_LIT_EXPORT:
tempess=CAlloc(sizeof(CHashExport));
tempess->str=StrNew(st_ptr);
tempess->type=HTT_EXPORT_SYS_SYM|HTF_LIT;
if (etype==EIE_LIT_EXPORT)
tempess->val=i;
else
tempess->val=i+module_base;
HashAdd(tempess,Fs->hash_table);
SysSymImportsResolve(st_ptr,ld_flags);
break;
case EIE_REL_U8...EIE_LIT_U64:
src=st_ptr-5;
LoadOneImport(&src,module_base,ld_flags);
break;
case EIE_ABS_ADDR:
if (ld_flags & LDF_NO_ABSS)
src+=i*sizeof(U32);
else {
cnt=i;
for (j=0;j<cnt;j++) {
ptr2=module_base+*src(U32 *)++;
*ptr2(U32 *)+=module_base;
}
}
break;
case EIE_HEAP_GLBL:
ptr3=MAlloc(*src(I64 *)++);
if (*st_ptr) {
tempess=CAlloc(sizeof(CHashExport));
tempess->str=StrNew(st_ptr);
tempess->type=HTT_EXPORT_SYS_SYM|HTF_LIT;
tempess->val=ptr3;
HashAdd(tempess,Fs->hash_table);
}
cnt=i;
for (j=0;j<cnt;j++) {
ptr2=module_base+*src(U32 *)++;
*ptr2(I64 *)+=ptr3;
}
break;
}
}
}
U0 LoadPass2(U8 *src,U8 *module_base,I64)
{
U8 *st_ptr;
I64 i,etype;
while (etype=*src++) {
i=*src(U32 *)++;
st_ptr=src;
src+=StrLen(st_ptr)+1;
switch (etype) {
case EIE_MAIN:
Call(i+module_base);
break;
case EIE_ABS_ADDR:
src+=sizeof(U32)*i;
break;
case EIE_HEAP_GLBL:
src+=8+sizeof(U32)*i;
break;
}
}
}
U8 *Load(U8 *filename,I64 ld_flags=0,CBinFile *bfh_addr=-1)
{ //See $LK,"BinRep","MN:BinRep"$().
//bfh_addr==-1 means don't care what load addr.
U8 *fbuf,*module_base,*absname;
I64 size,module_alignment;
CBinFile *bfh2;
fbuf=DftExt(filename,"BIN.Z");
if (!(bfh2=FileRead(fbuf,&size))) {
Free(fbuf);
return NULL;
}
//See $LK,"Loader Patch Table Generation","FF:::/SparrowOS/Compiler/CmpMain.CPP.Z,EIE_MODULE_ALIGNMENT"$
module_alignment=*(bfh2(U8 *)+bfh2->loader_patch_table_offset+1)(U32 *);
if (!module_alignment || Bsf(module_alignment)!=Bsr(module_alignment))
throw(EXCEPT_BIN_MODULE);
#assert sizeof(CBinFile)==16
if (bfh_addr==-1) {
if (Fs->code_heap!=Fs->data_heap) {
if (module_alignment<16)
module_alignment=16;
bfh_addr=MAllocAligned(size,module_alignment,Fs->code_heap,module_alignment-sizeof(CBinFile));
} else if (module_alignment>8)
bfh_addr=MAllocAligned(size,module_alignment,NULL,module_alignment-sizeof(CBinFile));
else {
bfh_addr=bfh2;
goto lo_skip;
}
}
MemCpy(bfh_addr,bfh2,size);
Free(bfh2);
lo_skip:
module_base=bfh_addr(U8 *)+sizeof(CBinFile);
if (ArcXSum(bfh_addr,bfh_addr->file_size)!=NATIVE_XSUM)
throw(EXCEPT_ARC_XSUM);
absname=FileNameAbs(fbuf);
Free(fbuf);
fbuf=StrNew(absname);
FileExtRem(fbuf);
if (fbuf[1]==':' && StrLen(fbuf)>2)
HashGenericAdd(fbuf+2,HTT_MODULE|HTF_PUBLIC,bfh_addr);
Free(fbuf);
LoadPass1(bfh_addr(U8 *)+bfh_addr->loader_patch_table_offset,module_base,ld_flags);
if (!(ld_flags&LDF_JUST_LOAD))
LoadPass2(bfh_addr(U8 *)+bfh_addr->loader_patch_table_offset,module_base,ld_flags);
Free(absname);
return bfh_addr;
}
U0 LoadOSMain()
{
HashGenericAdd(OSMAIN_MODULE_NAME,HTT_MODULE|HTF_PUBLIC,sys_boot_base-sizeof(CBinFile));
//Abs patches done here $LK,"EIE_ABS_ADDR","FF:D:/SparrowOS/OSMain/OSStart.CPP.Z,EIE_ABS_ADDR"$.
LoadPass1(sys_boot_patch_table_base,sys_boot_base,LDF_NO_ABSS|LDF_SILENT);
//No main routines
// LoadPass2(sys_boot_patch_table_base,sys_boot_base,0);
}
Í"  Cat"8äCbs"X Dog"täDog"À Bird!D\`!h€ô!´\Ì!(\,!0@ôXHX`X`T`T`THTHXHlHl`ªxª\ÀxÀ\€H€`HHH`\H\`pHp`4H4`xðxðxð\ð\\\x$\$x8\8xL\Lx`\`x\x0\0xD\Dx\xx88ìÿÿÿ8ìÿÿÿ8ìÿÿÿxìÿÿÿxxH`H,H,4,4,4`4`H`!hh!HTXT!üÿÿÿ8@d
!P\Ì!\Ì4è!Tèdè!dèd!d�è!pè`è!\è\ô!\ô¼!ä!<L!LL(!L(Œ(!Œ(t!T\ !\ÐT!4ì`Ð!`T!tŒ0!Œ0H,!H,H!H<!ä!¼`ø!`ø`ì!`ìpì!�ìd!d`ì!`ìTì
+241
View File
@@ -0,0 +1,241 @@
asm {
USE64
SYS_MP_CRASH_HANDLER_ADDR:: //forward reference to work around compiler
DU32 &MPCrash;
SYS_WAKE_HANDLER::
PUSH RAX
MOV EAX,U32 LAPIC_EOI
MOV U32 [RAX],0
POP RAX
IRET
//I_TIMER
SYS_TIMER_HANDLER::
CALL SYS_SAVE_CONTEXT //PREEMPTIVE
CLD
MOV RBP,RSP
MOV RBX,U64 [RBP]
MOV U64 CTask.rip[RSI],RBX
MOV RAX,U64 16[RBP]
MOV U64 CTask.rflags[RSI],RAX
MOV RAX,U64 24[RBP]
MOV U64 CTask.rsp[RSI],RAX
XOR RAX,RAX
MOV RDI,U64 GS:CCPU.addr[RAX]
LOCK
INC U64 CCPU.total_jiffies[RDI]
BT U64 CTask.task_flags[RSI],TASKf_IDLE
JC @@05
CMP RBX,U32 SYS_IDLE_START
JB @@10
CMP RBX,U32 SYS_IDLE_END
JA @@10
@@05: LOCK
INC U64 CCPU.idle_pt_hits[RDI]
@@10: MOV RAX,U64 CCPU.timer_irq_chain[RDI]
OR RAX,RAX
JZ @@15
PUSH RSI
CALL RAX
JMP @@20
@@15: ADD RSP,8
@@20: CLI
MOV RAX,U64 CCPU.num[RDI]
OR RAX,RAX
JZ @@25
MOV EAX,U32 LAPIC_EOI
MOV U32 [RAX],0
JMP @@30
@@25: MOV AL,0x20 //ACKNOWLEDGE INTERRUPT
OUT 0x20,AL
@@30: MOV RAX,SYS_SEMAS
BT U32 SYS_SEMA_SINGLE_USER*SEMA_STRUCT_SIZE[RAX],0
JC @@35
BT U64 CTask.task_flags[RSI],TASKf_PREEMPT
JC I32 RESTORE_NEXT_RSI_TASK
@@35: JMP I32 RESTORE_RSI_NO_PREEMPT_TASK
// ************************************
SYS_IRQ_FAULT::
PUSH RBX
MOV RBX,U64 8[RSP]
PUSH RAX
XOR RAX,RAX
MOV FS:U32 CTask.fault_num[RAX],EBX
POP RAX
POP RBX
ADD RSP,8
CALL SYS_SAVE_CONTEXT
XOR RDX,RDX
MOV U64 CTask.fault_err_code[RSI],RDX
MOV EDX,U32 CTask.fault_num[RSI]
BT U64 [SYS_FAULT_ERR_CODE_BITMAP],RDX
JNC @@1
POP U64 CTask.fault_err_code[RSI]
@@1: MOV RBP,RSP
MOV RAX,U64 [RBP]
MOV U64 CTask.rip[RSI],RAX
MOV RAX,U64 16[RBP]
MOV U64 CTask.rflags[RSI],RAX
MOV RAX,U64 24[RBP]
MOV U64 CTask.rsp[RSI],RAX
MOV RSP,RAX
MOV RBP,CTask.rbp[RSI]
MOV RSI,CTask.rsi[RSI]
CALL &Fault2 //See $LK,"Fault2","FF:::/SparrowOS/OSMain/Dbg1a.CPP.Z,Fault2"$
JMP I32 RESTORE_FS_TASK_WITH_KEY_CHECK
SYS_FAULT_ERR_CODE_BITMAP::
DU32 0x00027D00,0,0,0,0,0,0,0;
}
U8 *IntEntryGet(I64 irq,I64 cpu_num=-1)
{
U8 *result;
I64 *src;
if (cpu_num<0) cpu_num=Gs->num;
if (cpu_num>=mp_cnt&&cpu_num>Gs->num)
throw(EXCEPT_MULTICORE,3);
src=cpu_structs[cpu_num].idt(U8 *)+irq*16;
result(I64).u16[0]=*src(U16 *);
src(U8 *)+=6;
result(I64).u16[1]=*src(U16 *)++;
result(I64).u32[1]=*src(U32 *);
return result;
}
U8 *IntEntrySet(I64 irq,U0 (*fp_new_handler)(),I64 cpu_num=-1,
I64 type=IDTET_IRQ,I64 dpl=0)
{
//See $LK,"IDTET_IRQ","MN:IDTET_IRQ"$
//See $LK,"::/SparrowOS/Demo/Lectures/InterruptDemo.CPP.Z","FI:::/SparrowOS/Demo/Lectures/InterruptDemo.CPP.Z"$
//See $LK,"::/SparrowOS/Demo/MultiCore/Interrupts.CPP.Z","FI:::/SparrowOS/Demo/MultiCore/Interrupts.CPP.Z"$
I64 fp=fp_new_handler;
U8 *result,*dst;
if (cpu_num<0) cpu_num=Gs->num;
result=IntEntryGet(irq,cpu_num);
dst=cpu_structs[cpu_num].idt(U8 *)+irq*16;
PushFD;
Cli;
*dst(U16 *)++=fp.u16[0];
*dst(U16 *)++=GDT_CS64_SEL;
*dst(U16 *)++=0x8000+type<<8+dpl<<13;
*dst(U16 *)++=fp.u16[1];
*dst(U32 *)++=fp.u32[1];
*dst(U32 *)++=0;
PopFD;
return result;
}
U0 IntsInit()
{
//Init 8259
OutU8(0x20,0x11); //IW1
OutU8(0xA0,0x11); //IW1
OutU8(0x21,0x20); //IW2
OutU8(0xA1,0x28); //IW2
OutU8(0x21,0x04); //IW3
OutU8(0xA1,0x02); //IW3
OutU8(0x21,0x0D); //IW4
OutU8(0xA1,0x09); //IW4
OutU8(0x21,0xFA); //Mask all but IRQ0 (timer) and IRQ2 Cascade
OutU8(0xA1,0xFF);
}
U0 IntEOI()
{
*LAPIC_EOI(U32 *)=0;
}
interrupt U0 IntNop1()
{ //Make unplanned IRQs stop!
//IRQs on cores other than zero are APIC, I'm pretty sure.
//I think the PIC only generates core 0 IRQs.
IntEOI;
}
interrupt U0 IntNop2()
{ //Make unplanned IRQs stop by all means!
OutU8(0xA0,0x20);
OutU8(0x20,0x20);
IntEOI;
}
U8 *IntFaultHandlersNew()
{
I64 i;
U8 *result=MAlloc(256*10,Fs->code_heap),*dst=result;
for (i=0;i<256;i++) {
*dst++=0x68; //PUSH I32 xxxxxxxx
*dst(I32 *)++=i;
*dst++=0xE9; //JMP I32 xxxxxxxx
*dst(I32 *)=SYS_IRQ_FAULT-dst-4;
dst+=4;
}
return result;
}
U0 IntInit1()
{ //Interrupt descriptor table part1
I64 i,temp_ptr[2];
U32 *ptr;
Gs->idt=CAlloc(16*256);
/*
During boot, we don't know what hardware PIC IRQ's were set to.
When we unmask for the first time, after initializing the PIC, I'm
not sure of old pending IRQs will be issued.
After boot, we might get a APIC IRQ because we never initialize that.
Acknowledging unplanned IRQs seems safest to me, even
if we accidentally turn-off a valid IRQ and miss it.
We only support keyboard, mouse and timer, anyway.
*/
for (i=0;i<256;i++)
if (!Gs->num)
IntEntrySet(i,&IntNop2);
else
IntEntrySet(i,&IntNop1);
ptr=temp_ptr;
*ptr(U16 *)++=256*16-1;
*ptr(U32 *)++=Gs->idt(I64).u32[0];
*ptr(U32 *)++=Gs->idt(I64).u32[1];
*ptr(U16 *)++=0;
SetRAX(temp_ptr);
asm { LIDT U64 [RAX] }
}
U0 IntInit2()
{ //Interrupt descriptor table part2
I64 i;
PushFD;
Cli;
for (i=0;i<0x20;i++)
IntEntrySet(i,&sys_fault_handlers_code[10*i]);
/*
In theory, we use the PIC mask register to insure we don't get
anything but keyboard, mouse and timer IRQs. In practice, I've
gotten IRQ 0x27, perhaps because I didn't initialize the APIC.
I go ahead and ACK PIC in $LK,"IntNop2","MN:IntNop2"$().
I have no idea why I got a IRQ 0x27.
*/
IntEntrySet(I_NMI,_SYS_HLT);
IntEntrySet(I_TIMER,SYS_TIMER_HANDLER);
IntEntrySet(I_MP_CRASH,*SYS_MP_CRASH_HANDLER_ADDR(U32 *));
IntEntrySet(I_WAKE,SYS_WAKE_HANDLER);
PopFD;
}
+128
View File
@@ -0,0 +1,128 @@
U0 SetSnap(CSnap *s,I64 i=0,F64 d=0)
{
if (i) {
s->x=i;
s->y=i;
s->z=i;
}
if (d) {
s->dx=d;
s->dy=d;
s->dz=d;
}
}
CSnap *SnapCur()
{
static CSnap s;
Bool old_preempt=Preempt(OFF);
if (sys_focus_task && TaskValidate(sys_focus_task) &&
sys_focus_task->win_pixel_left<=ipx_presnap<=sys_focus_task->win_pixel_right &&
sys_focus_task->win_pixel_top <=ipy_presnap<=sys_focus_task->win_pixel_bottom)
MemCpy(&s,&sys_focus_task->snap,sizeof(CSnap));
else
SetSnap(&s,1,1.0);
Preempt(old_preempt);
return &s;
}
U0 GetSnap(CSnap *_s)
{
CSnap *s=SnapCur;
MemCpy(_s,s,sizeof(CSnap));
}
U0 IPVarsUpdate(I64 x,I64 y,I64 z,Bool l,Bool c,Bool r)
{
CSnap s;
GetSnap(&s);
ipx_presnap=ToI64(ipx_scale*x)+ipx_offset;
ipx=RoundI64(ipx_presnap,s.x);
if (sys_focus_task)
ipx+=(sys_focus_task->win_pixel_left+sys_focus_task->win_scroll_x)%s.x;
ipy_presnap=ToI64(ipy_scale*y)+ipy_offset;
ipy=RoundI64(ipy_presnap,s.y);
if (sys_focus_task)
ipy+=(sys_focus_task->win_pixel_top+sys_focus_task->win_scroll_y)%s.y;
ipz_presnap=ToI64(ipz_scale*z)+ipz_offset;
ipz=RoundI64(ipz_presnap,s.z);
if (sys_focus_task)
ipz+=sys_focus_task->win_scroll_y%s.z;
ipx=LimitI64(ipx,0,gr_width-1);
ipy=LimitI64(ipy,0,gr_height-1);
ip_throttle=LimitI64(ip_throttle,MIN_I32,MAX_I32);
iptx=ipx/FONT_WIDTH;
if (iptx>=text_cols) {
iptx=text_cols-1;
ipx=text_cols*FONT_WIDTH-1;
}
ipty=ipy/FONT_HEIGHT;
if (ipty>=text_rows) {
ipty=text_rows-1;
ipy=text_rows*FONT_HEIGHT-1;
}
ip_lb=l;
ip_cb=c;
ip_rb=r;
LBEqu(&sys_cur_scan_code,SCf_IP_L_DOWN,ip_lb);
LBEqu(&sys_cur_scan_code,SCf_IP_R_DOWN,ip_rb);
}
U0 SetIP(I64 x=MAX_I64,I64 y=MAX_I64,I64 z=MAX_I64,I64 l=MAX_I64,I64 r=MAX_I64,I64 c=MAX_I64)
{ //Note: Generates a message.
Bool old_preempt=Preempt(OFF);
if (!(0<=x<gr_width))
x=ipx;
if (!(0<=y<gr_height))
y=ipy;
if (z==MAX_I64)
z=ipz;
if (!(FALSE<=l<=TRUE))
l=ip_lb;
if (!(FALSE<=c<=TRUE))
c=ip_cb;
if (!(FALSE<=r<=TRUE))
r=ip_rb;
x=(x-ipx_offset)/ipx_scale;
y=(y-ipy_offset)/ipy_scale;
z=(z-ipz_offset)/ipz_scale;
IPVarsUpdate(x,y,z,l,c,r);
switch (ip_dev) {
case IP_MOUSE:
SetMouseIP(x,y,z,l,c,r);
break;
}
Preempt(old_preempt);
}
U0 IPVarsInit()
{
ipx=0;
ipy=0;
ipz=0;
ip_throttle=0;
ipx_offset=0;
ipy_offset=0;
ipz_offset=0;
ipx_scale=1.0;
ipy_scale=1.0;
ipz_scale=1.0;
ip_speed=0;
ip_dev=IP_NULL;
iptx=ipx/FONT_WIDTH;
ipty=ipy/FONT_HEIGHT;
ip_on=TRUE;
ip_lb_last=FALSE;
ip_rb_last=FALSE;
ip_lb=FALSE;
ip_cb=FALSE;
ip_rb=FALSE;
ip_has_wheel=FALSE;
ip_last_move_time=tS;
SetSnap(&ip_snap_last,1,1.0);
}
+546
View File
@@ -0,0 +1,546 @@
asm {
NORMAL_KEY_SCAN_DECODE_TABLE::
DU8 0,CH_ESC,"1234567890-=",CH_BACKSPACE,CH_TAB;
DU8 "qwertyuiop[]",CH_NEW_LINE,0,"as";
DU8 "dfghjkl;'\`",0,"\\zxcv";
DU8 "bnm,./",0,'*',0,CH_SPACE,0,0,0,0,0,0;
DU8 0,0,0,0,0,0,0,0,0,0,'-',0,0,0,'+',0;
SHIFT_KEY_SCAN_DECODE_TABLE::
DU8 0,CH_SHIFT_ESC,"!@#$$%^&*()_+",CH_BACKSPACE,CH_TAB;
DU8 "QWERTYUIOP{}",CH_NEW_LINE,0,"AS";
DU8 "DFGHJKL:\"~",0,"|ZXCV";
DU8 "BNM<>?",0,'*',0,CH_SHIFT_SPACE,0,0,0,0,0,0;
DU8 0,0,0,0,0,0,0,0,0,0,'-',0,0,0,'+',0;
CTRL_KEY_SCAN_DECODE_TABLE::
DU8 0,CH_ESC,"1234567890-=",CH_BACKSPACE,CH_TAB;
DU8 CH_CTRLQ,CH_CTRLW,CH_CTRLE,CH_CTRLR,CH_CTRLT,CH_CTRLY,CH_CTRLU,CH_CTRLI,CH_CTRLO,CH_CTRLP,"[]",CH_NEW_LINE,0,CH_CTRLA,CH_CTRLS;
DU8 CH_CTRLD,CH_CTRLF,CH_CTRLG,CH_CTRLH,CH_CTRLJ,CH_CTRLK,CH_CTRLL,";'\`",0,"\\",CH_CTRLZ,CH_CTRLX,CH_CTRLC,CH_CTRLV;
DU8 CH_CTRLB,CH_CTRLN,CH_CTRLM,",./",0,'*',0,CH_SPACE,0,0,0,0,0,0;
DU8 0,0,0,0,0,0,0,0,0,0,'-',0,0,0,'+',0;
}
U0 KbdCmdSend(I64 port, U8 val)
{
F64 timeout=tS+0.125;
while (tS<timeout) {
if (!(InU8(KBD_CTRL)&2)) {
OutU8(port,val);
return;
}
}
throw (EXCEPT_LOCAL);
}
I64 KbdCmdRead()
{
F64 timeout=tS+0.125;
while (tS<timeout)
if (InU8(KBD_CTRL)&1)
return InU8(KBD_PORT);
throw (EXCEPT_LOCAL);
}
U0 KbdCmdFlush()
{
F64 timeout=tS+0.03;
while (tS<timeout)
InU8(KBD_PORT);
}
U0 KbdSetLEDs(I64 sc)
{
Bool old_preempt=Preempt(OFF);
U8 v=0;
BEqu(&v,0,Bt(&sc,SCf_SCROLL));
BEqu(&v,1,Bt(&sc,SCf_NUM));
BEqu(&v,2,Bt(&sc,SCf_CAPS));
try {
KbdCmdSend(KBD_PORT,0xED);
KbdCmdSend(KBD_PORT,v);
} catch
Fs->catch_except=TRUE;
Preempt(old_preempt);
}
U0 KbdMouseCmdAck(U8 val)
{
I64 ack,timeout=5;
do {
ack=0;
try {
KbdCmdSend(KBD_CTRL,0xD4);
KbdCmdSend(KBD_PORT,val);
ack=KbdCmdRead;
} catch {
KbdCmdFlush;
Fs->catch_except=TRUE;
}
} while (ack!=0xFA && --timeout);
if (!timeout)
throw (EXCEPT_LOCAL);
}
U0 SetTypeMatic(U8 delay)
{
try {
KbdCmdSend(KBD_CTRL,0xA7); //Disable Mouse
KbdCmdSend(KBD_CTRL,0xAE); //Enable Keyboard
KbdCmdSend(KBD_PORT,0xF3);
KbdCmdSend(KBD_PORT,delay); //Typematic rate
KbdCmdSend(KBD_CTRL,0xA8); //Enable Mouse
} catch {
KbdCmdFlush;
Fs->catch_except=TRUE;
}
}
I64 A2ScanCode(I64 ch,I64 sc_flags=0)
{ //ASCII val to scan code (Slow)
I64 i;
U8 *table;
if (sc_flags) {
table=NORMAL_KEY_SCAN_DECODE_TABLE;
if (sc_flags & SCF_CTRL || ch<26)
table=CTRL_KEY_SCAN_DECODE_TABLE;
else if (sc_flags & SCF_SHIFT || 'A'<=ch<='Z') {
if (!(sc_flags & SCF_CAPS))
table=SHIFT_KEY_SCAN_DECODE_TABLE;
} else {
if (sc_flags & SCF_CAPS)
table=SHIFT_KEY_SCAN_DECODE_TABLE;
}
for (i=0;i<0x50;i++)
if (table[i]==ch)
return i|sc_flags;
return sc_flags;
} else {
table=NORMAL_KEY_SCAN_DECODE_TABLE;
for (i=0;i<0x50;i++)
if (table[i]==ch)
return i;
table=SHIFT_KEY_SCAN_DECODE_TABLE;
for (i=0;i<0x50;i++)
if (table[i]==ch)
return i|SCF_SHIFT;
table=CTRL_KEY_SCAN_DECODE_TABLE;
for (i=0;i<0x50;i++)
if (table[i]==ch)
return i|SCF_CTRL;
return 0;
}
}
U8 ScanCode2A(I64 sc)
{//Scan Code to ASCII val
U8 *table=NORMAL_KEY_SCAN_DECODE_TABLE;
if (sc & SCF_E0_PREFIX)
return 0;
if (sc & SCF_CTRL)
table=CTRL_KEY_SCAN_DECODE_TABLE;
else if (sc & SCF_SHIFT) {
if (!(sc & SCF_CAPS))
table=SHIFT_KEY_SCAN_DECODE_TABLE;
} else {
if (sc & SCF_CAPS)
table=SHIFT_KEY_SCAN_DECODE_TABLE;
}
sc&=0x7F;
if (sc>=0x50)
return 0;
else
return table[sc];
}
U8 scan_code_map[0x100]={
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,SC_SHIFT,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,SC_CARRIAGE_RETURN,SC_CTRL,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0x35,0,0,SC_ALT,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,SC_HOME,SC_CURSOR_UP,SC_PAGE_UP,0,SC_CURSOR_LEFT,0,SC_CURSOR_RIGHT,0,SC_END,
SC_CURSOR_DOWN,SC_PAGE_DOWN,SC_INS,SC_DELETE,0,0,0,0,0,0,0,0,SC_GUI,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};
U8 num_lock_map[0x100]={
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,8,9,10,0,5,6,7,0,2,
3,4,11,0x34,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,SC_CARRIAGE_RETURN,SC_CTRL,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0x35,0,0,SC_ALT,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,SC_HOME,SC_CURSOR_UP,SC_PAGE_UP,0,SC_CURSOR_LEFT,0,SC_CURSOR_RIGHT,0,SC_END,
SC_CURSOR_DOWN,SC_PAGE_DOWN,SC_INS,SC_DELETE,0,0,0,0,0,0,0,0,SC_GUI,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};
U8 *A2KeyName(I64 ch,Bool include_ctrl=TRUE)
{//ASCII val to key name
I64 i;
U8 buf[136];
if (ch<=CH_SPACE) {
nobound_switch (ch) {
case CH_NEW_LINE:
StrCpy(buf,"ENTER");
break;
case CH_BACKSPACE:
StrCpy(buf,"BACKSPACE");
break;
case CH_TAB:
StrCpy(buf,"TAB");
break;
case CH_ESC:
StrCpy(buf,"ESC");
break;
case CH_SHIFT_ESC:
StrCpy(buf,"SHIFT_ESC");
break;
case 0: //nobound_switch
case 29:
case 30:
*buf=0;
break;
case CH_SHIFT_SPACE:
StrCpy(buf,"SHIFT_SPACE");
break;
case CH_SPACE:
StrCpy(buf,"SPACE");
break;
default:
if (include_ctrl)
StrCpy(buf,"CTRL ");
buf[i=StrLen(buf)]=ch-1+'a';
buf[i+1]=0;
break;
}
} else if (Bt(printable_chars_bitmap,ch)) {
*buf=ch;
buf[1]=0;
} else
*buf=0;
return StrNew(buf);
}
U8 *ScanCode2KeyName(I64 sc)
{
I64 ch;
U8 buf[136],*st;
*buf=0;
if (sc&SCF_CTRL)
StrCat(buf,"CTRL ");
if (sc&SCF_ALT)
StrCat(buf,"ALT ");
if (sc&SCF_SHIFT)
StrCat(buf,"SHIFT ");
if (ch=ScanCode2A(sc.u8[0])) {
st=A2KeyName(ch,FALSE);
StrCpy(buf+StrLen(buf),st);
Free(st);
} else {
switch (sc.u8[0]) {
case SC_BACKSPACE:StrCat(buf,"BACK"); break;
case SC_CAPS: StrCat(buf,"CAPS"); break;
case SC_NUM: StrCat(buf,"NUM"); break;
case SC_SCROLL: StrCat(buf,"SCROLL"); break;
case SC_CURSOR_UP:StrCat(buf,"UP"); break;
case SC_CURSOR_DOWN:StrCat(buf,"DOWN"); break;
case SC_CURSOR_LEFT:StrCat(buf,"LEFT"); break;
case SC_CURSOR_RIGHT:StrCat(buf,"RIGHT"); break;
case SC_PAGE_UP:StrCat(buf,"PAGE_UP"); break;
case SC_PAGE_DOWN:StrCat(buf,"PAGE_DOWN"); break;
case SC_HOME: StrCat(buf,"HOME"); break;
case SC_END: StrCat(buf,"END"); break;
case SC_INS: StrCat(buf,"INS"); break;
case SC_DELETE: StrCat(buf,"DELETE"); break;
case SC_F1: StrCat(buf,"F1"); break;
case SC_F2: StrCat(buf,"F2"); break;
case SC_F3: StrCat(buf,"F3"); break;
case SC_F4: StrCat(buf,"F4"); break;
case SC_F5: StrCat(buf,"F5"); break;
case SC_F6: StrCat(buf,"F6"); break;
case SC_F7: StrCat(buf,"F7"); break;
case SC_F8: StrCat(buf,"F8"); break;
case SC_F9: StrCat(buf,"F9"); break;
case SC_F10: StrCat(buf,"F10"); break;
case SC_F11: StrCat(buf,"F11"); break;
case SC_F12: StrCat(buf,"F12"); break;
case SC_GUI: StrCat(buf,"WINDOWS"); break;
case SC_PRTSCRN1: StrCat(buf,"PRTSCRN1"); break;
case SC_PRTSCRN2: StrCat(buf,"PRTSCRN2"); break;
}
}
return StrNew(buf);
}
I64 KbdBuildSC(U8 raw_byte,U8 *_last_raw_byte,I64 *_last_sc,
Bool *_set_LEDs,Bool *_ctrl_alt)
{
I64 sc_flags,sc,sc2,sc_raw;
*_set_LEDs=FALSE;
*_ctrl_alt=FALSE;
if (raw_byte==0xE0) {
*_last_raw_byte=raw_byte;
return 0;
} else {
sc=raw_byte;
BEqu(&sc,SCf_E0_PREFIX,*_last_raw_byte==0xE0);
BEqu(&sc,SCf_KEY_UP,raw_byte & 0x80);
*_last_raw_byte=raw_byte;
}
sc_flags=_last_sc->u32[0]&~0x1FF;
sc_raw=sc;
if (sc_flags & SCF_NUM) {
if (sc2=num_lock_map[sc.u8[0]])
sc.u8[0]=sc2;
} else {
if (sc2=scan_code_map[sc.u8[0]])
sc.u8[0]=sc2;
}
if (sc==SC_SHIFT) {
sc_flags|=SCF_SHIFT;
goto new_key_done;
}
if (sc==SC_SHIFT+SCF_KEY_UP) {
sc_flags&=~SCF_SHIFT;
goto new_key_done;
}
if (sc==SC_CTRL) {
sc_flags|=SCF_CTRL;
goto new_key_done;
}
if (sc==SC_CTRL+SCF_KEY_UP) {
sc_flags&=~SCF_CTRL;
goto new_key_done;
}
if (sc==SC_ALT) {
sc_flags|=SCF_ALT;
goto new_key_done;
}
if (sc==SC_ALT+SCF_KEY_UP) {
sc_flags&=~SCF_ALT;
goto new_key_done;
}
if (sc==SC_DELETE)
sc_flags|=SCF_DELETE;
else if (sc==SC_DELETE+SCF_KEY_UP)
sc_flags&=~SCF_DELETE;
if (sc==SC_INS)
sc_flags|=SCF_INS;
else if (sc==SC_INS+SCF_KEY_UP)
sc_flags&=~SCF_INS;
if (sc==SC_CAPS)
goto new_key_done;
if (sc==SC_CAPS+SCF_KEY_UP) {
sc_flags^=SCF_CAPS;
*_set_LEDs=TRUE;
goto new_key_done;
}
if (sc==SC_NUM)
goto new_key_done;
if (sc==SC_NUM+SCF_KEY_UP) {
sc_flags^=SCF_NUM;
*_set_LEDs=TRUE;
goto new_key_done;
}
if (sc==SC_SCROLL)
goto new_key_done;
if (sc==SC_SCROLL+SCF_KEY_UP) {
sc_flags^=SCF_SCROLL;
*_set_LEDs=TRUE;
goto new_key_done;
}
if (sc_flags & SCF_CTRL && sc_flags & SCF_ALT) {
sc_flags&=~SCF_NEW_KEY;
*_ctrl_alt=TRUE;
} else {
new_key_done:
sc_flags|=SCF_NEW_KEY;
}
return *_last_sc=sc_flags|sc|(sc_flags|sc_raw)<<32;
}
U0 KbdPktRead()
{
static U8 last_raw_byte=0;
static I64 last_sc=0;
U8 raw_byte;
I64 ch,sc;
Bool set_LEDs,ctrl_alt;
if (GetTimeStamp>kbd_evt_time+time_stamp_freq>>3)
FifoU8Flush(kbd_fifo);
kbd_evt_time=GetTimeStamp;
raw_byte=InU8(KBD_PORT);
sc=KbdBuildSC(raw_byte,&last_raw_byte,&last_sc,&set_LEDs,&ctrl_alt);
if (ctrl_alt && sc) {
if (!(sc & SCF_KEY_UP)) {
if (sc.u8[0]==SC_DELETE)
CtrlAltDel(last_sc);
else {
if (sc.u8[0]==SC_ESC)
ch='e';
else if (sc.u8[0]==SC_TAB)
ch='t';
else
ch=ScanCode2A(sc.u8[0]);
if ('a'<=ch<='z' && fp_ctrl_alt_let_cbs[ch-'a'] &&
Bt(&ctrl_alt_let_in_irq_flags,ch-'a')) {
(*fp_ctrl_alt_let_cbs[ch-'a'])(last_sc);
return;
}
}
}
}
if (!FifoU8Cnt(kbd_fifo)) {
FifoU8Ins(kbd_fifo,raw_byte);
if (raw_byte!=0xE0) {
while (FifoU8Rem(kbd_fifo,&raw_byte))
FifoU8Ins(kbd2_fifo,raw_byte);
}
} else {
FifoU8Ins(kbd_fifo,raw_byte);
while (FifoU8Rem(kbd_fifo,&raw_byte))
FifoU8Ins(kbd2_fifo,raw_byte);
}
}
interrupt U0 KbdIntHandler()
{
Cld;
OutU8(0x20,0x20);
kbd_irqs_working=TRUE;
if (mouse_install_attempt_in_progress) {
kbdmouse_rst=TRUE;
return;
}
ctrl_alt_let_ret_addr=GetBasePtr()(I64)+8;
KbdPktRead;
}
U0 KbdInit()
{
try {
KbdCmdFlush;
KbdCmdSend(KBD_CTRL,0xA7); //Disable Mouse
KbdCmdSend(KBD_CTRL,0xAE); //Enable Keyboard
KbdCmdSend(KBD_PORT,0xF0);
KbdCmdSend(KBD_PORT,0x02);
KbdSetLEDs(sys_cur_scan_code);
} catch {
KbdCmdFlush;
Fs->catch_except=TRUE;
}
IntEntrySet(0x21,&KbdIntHandler,0);
OutU8(0x21,InU8(0x21)&~2);
SetCtrlAltLetCB('C',&CtrlAltC,"Sys/Break Execution",TRUE);
SetCtrlAltLetCB('E',&CtrlAltE,"Sys/Spawn New User Task");
SetCtrlAltLetCB('F',&CtrlAltF,"Sys/VGA Flush",TRUE);
SetCtrlAltLetCB('M',&CtrlAltM,"Sys/Toggle Mute");
SetCtrlAltLetCB('P',&CtrlAltP,"Sys/Toggle Pause Focused Task");
SetCtrlAltLetCB('T',&CtrlAltT,"Sys/Switch Focus to Next Task",TRUE);
SetCtrlAltLetCB('X',&CtrlAltX,"Sys/Kill Focused Task",TRUE);
}
U0 KbdHandler()
{
static U8 last_raw_byte=0;
U8 raw_byte;
Bool set_LEDs,ctrl_alt;
I64 ch,sc;
FifoU8Rem(kbd2_fifo,&raw_byte);
sc=KbdBuildSC(raw_byte,&last_raw_byte,&sys_cur_scan_code,&set_LEDs,&ctrl_alt);
if (set_LEDs)
KbdSetLEDs(sc);
if (raw_byte==0xE0) {
FifoU8Rem(kbd2_fifo,&raw_byte);
sc=KbdBuildSC(raw_byte,&last_raw_byte,&sys_cur_scan_code,&set_LEDs,&ctrl_alt);
if (set_LEDs)
KbdSetLEDs(sc);
}
if (ctrl_alt) {
if (!(sc & SCF_KEY_UP)) {
if (sc.u8[0]==SC_ESC)
ch='e';
else if (sc.u8[0]==SC_TAB)
ch='t';
else
ch=ScanCode2A(sc.u8[0]);
if ('a'<=ch<='z' && fp_ctrl_alt_let_cbs[ch-'a'] &&
!Bt(&ctrl_alt_let_in_irq_flags,ch-'a'))
(*fp_ctrl_alt_let_cbs[ch-'a'])(sys_cur_scan_code);
}
return;
}
if (Btr(&sys_cur_scan_code,SCf_NEW_KEY)) {
Btr(&sys_cur_scan_code,32+SCf_NEW_KEY);
FifoI64Ins(scan_code_fifo,sys_cur_scan_code);
sys_key_cnt++;
if (!(sys_cur_scan_code&SCF_KEY_UP)) {
sys_last_down_scan_code=sys_cur_scan_code;
Bts(key_down_bitmap,sys_cur_scan_code.u8[0]);
Bts(key_down_bitmap2,sys_cur_scan_code.u8[4]);
} else {
Btr(key_down_bitmap,sys_cur_scan_code.u8[0]);
Btr(key_down_bitmap2,sys_cur_scan_code.u8[4]);
}
}
}
I64 KbdQueMsgs()
{
I64 p1,p2,msg_code=MSG_NULL;
CTask *task_focus;
if (task_focus=sys_focus_task) {
while (FifoI64Rem(scan_code_fifo,&p2)) {
p1=ScanCode2A(p2);
if (p2 & SCF_KEY_UP) {
QueMsg(task_focus,0,
MSG_KEY_UP,p1,p2,0);
msg_code=MSG_KEY_UP;
} else {
QueMsg(task_focus,0,
MSG_KEY_DOWN,p1,p2,0);
msg_code=MSG_KEY_DOWN;
}
}
}
return msg_code;
}
I64 KbdMouseEvtTime()
{
if (mouse_evt_time>kbd_evt_time)
return mouse_evt_time;
else
return kbd_evt_time;
}
+233
View File
@@ -0,0 +1,233 @@
U0 InputFilterTask()
{
U8 *st;
CTaskCmd *tempc,*tempc1;
Bool old_filter;
I64 old_flags=GetFlags;
LBts(&Fs->task_flags,TASKf_USER);
TaskInitExt;
LBts(&Fs->task_flags,TASKf_INPUT_FILTER_TASK);
old_filter=LBts(&Fs->last_input_filter_task->task_flags,TASKf_FILTER_INPUT);
LBEqu(&Fs->task_flags,TASKf_FILTER_INPUT,old_filter);
while (TRUE) {
ServantCmdsHandler;
Cli;
tempc1=&Fs->next_servant_cmd;
tempc=tempc1->next;
if (tempc==tempc1)
break;
else {
if (tempc->cmd_code==TASKCT_TEXT_INPUT) {
QueRem(tempc);
SetFlags(old_flags);
st=tempc->data;
Free(tempc);
if (!IsSysDeterministic)
Preempt(ON);
try
ExePutS(st);
catch
Fs->catch_except=TRUE;
Preempt(OFF);
Free(st);
} else
break;
}
}
Fs->next_input_filter_task->last_input_filter_task=Fs->last_input_filter_task;
Fs->last_input_filter_task->next_input_filter_task=Fs->next_input_filter_task;
if (!old_filter)
LBtr(&Fs->last_input_filter_task->task_flags,TASKf_FILTER_INPUT);
SetFlags(old_flags);
}
I64 ScanMsg(I64 *_p1=NULL,I64 *_p2=NULL,I64 mask=~1,CTask *task=NULL)
{
I64 result,old_flags;
CTaskCmd *tempc,*tempc1;
if (!task) task=Fs;
old_flags=GetFlags;
tempc1=&task->next_servant_cmd;
while (TRUE) {
if (task==Fs)
ServantCmdsHandler;
Cli;
tempc=tempc1->next;
if (tempc==tempc1)
break;
else {
if (tempc->cmd_code==TASKCT_MSG) {
QueRem(tempc);
SetFlags(old_flags);
result=tempc->msg_code;
if (_p1)
*_p1=tempc->p1;
if (_p2)
*_p2=tempc->p2;
Free(tempc);
if ((result!=MSG_KEY_DOWN || !(tempc->p2&SCF_KEY_DESC) ||
Bt(&mask,MSGF_ALLOW_KEY_DESC)) && Bt(&mask,result))
goto sm_done;
}
}
SetFlags(old_flags);
}
result=MSG_NULL;
if (_p1)
*_p1=0;
if (_p2)
*_p2=0;
if (task->parent_task&&task->parent_task->popup_task==task) {
SetFlags(old_flags);
return ScanMsg(_p1,_p2,mask,task->parent_task);
}
sm_done:
SetFlags(old_flags);
return result;
}
I64 FlushMsgs(CTask *task=NULL)
{
I64 result=0,p1,p2;
while (ScanMsg(&p1,&p2,~1,task))
result++;
return result;
}
I64 GetMsg(I64 *_p1=NULL,I64 *_p2=NULL,I64 mask=~1,CTask *task=NULL)
{
I64 result;
Bool old_preempt=Preempt(OFF);
if (!task) task=Fs;
LBtr(&task->task_flags,TASKf_IDLE);
while (!(result=ScanMsg(_p1,_p2,mask,task))) {
LBts(&task->task_flags,TASKf_IDLE);
Yield;
}
LBtr(&task->task_flags,TASKf_IDLE);
Preempt(old_preempt);
return result;
}
I64 ScanChar()
{
I64 p1a,p2a,p1b,p2b;
if (!ScanMsg(&p1a,&p2a,1<<MSG_KEY_DOWN)||!p1a)
return 0;
else
do GetMsg(&p1b,&p2b,1<<MSG_KEY_UP);
while (!p1b);
return p1a;
}
Bool ScanKey(I64 *_ch=NULL,I64 *_scancode=NULL,Bool echo=FALSE)
{
I64 ch=0,sc=0;
if (ScanMsg(&ch,&sc,1<<MSG_KEY_DOWN)) {
if (_ch) *_ch=ch;
if (_scancode) *_scancode=sc;
if (echo)
PutKey(ch,sc);
return TRUE;
} else {
if (_ch) *_ch=0;
if (_scancode) *_scancode=0;
return FALSE;
}
}
I64 GetKey(I64 *_scancode=NULL,Bool echo=FALSE,Bool raw_cursor=FALSE)
{
I64 ch,sc;
Bool old_preempt=Preempt(OFF),cursor_on=FALSE;
while (!ScanKey(&ch,&sc,FALSE)) {
if (IsRaw && raw_cursor) {
if (!cursor_on && Blink(,tNP)) {
'' CH_SOLID;
cursor_on=TRUE;
} else if (cursor_on && !Blink(,tNP)) {
'' CH_BACKSPACE;
cursor_on=FALSE;
}
}
LBts(&Fs->task_flags,TASKf_IDLE);
if (IsInDbg) {
//We don't want interrupt-driven keyboard when in debugger
//because that could have side-effects or crash, so we poll
//keyboard when in debugger with interrupts off.
PushFD;
Cli;
KbdMouseHandler(TRUE,FALSE);
KbdQueMsgs;
PopFD;
if (old_preempt && GetFlags&1<<RFLAGS_INTERRUPTS)
Yield;
} else {
LBts(&Fs->task_flags,TASKf_AWAITING_MSG);
Yield;
}
LBtr(&Fs->task_flags,TASKf_IDLE);
}
if (IsRaw && raw_cursor && cursor_on)
'' CH_BACKSPACE;
Preempt(old_preempt);
if (echo)
PutKey(ch,sc);
if (_scancode) *_scancode=sc;
return ch;
}
I64 GetChar(I64 *_scancode=NULL,Bool echo=TRUE,Bool raw_cursor=FALSE)
{
I64 ch1;
do ch1=GetKey(_scancode,FALSE,raw_cursor);
while (!ch1);
if (echo)
"$$FU$$%c$$FG$$",ch1;
return ch1;
}
U8 *MGetS(I64 flags=0)
//$LK,"Flags","MN:GETSF_SHIFT_ESC_EXIT"$
{
//Returns a $LK,"MAlloc","MN:MAlloc"$()ed prompted string.
return (*fp_mgets)(flags);
}
I64 GetS(U8 *buf,I64 size,Bool allow_ext=TRUE)
{
U8 *st;
I64 ch,i=0;
if (!size || !buf) return 0;
if (allow_ext) {
st=MGetS;
if (StrLen(st)>size-1) {
MemCpy(buf,st,size-1);
buf[size-1]=0;
} else
StrCpy(buf,st);
i=StrLen(buf);
Free(st);
} else {
while (TRUE) {
ch=GetChar(NULL,FALSE,IsInDbg);
if (ch==CH_NEW_LINE) {
'' ch;
break;
} else if (ch==CH_BACKSPACE) {
if (i>0) {
i--;
'' ch;
}
} else {
if (i<size-1) {
buf[i++]=ch;
'' ch;
}
}
}
buf[i]=0;
}
return i;
}
+352
View File
@@ -0,0 +1,352 @@
U0 MousePktRead()
{
U8 j;
if (GetTimeStamp>mouse_evt_time+time_stamp_freq>>3)
FifoU8Flush(mouse_fifo);
mouse_evt_time=GetTimeStamp;
FifoU8Ins(mouse_fifo,InU8(KBD_PORT));
if (FifoU8Cnt(mouse_fifo)==mouse_pkt_size)
while (FifoU8Rem(mouse_fifo,&j))
FifoU8Ins(mouse2_fifo,j);
}
interrupt U0 MouseIntHandler()
{
Cld;
OutU8(0xA0,0x20);
OutU8(0x20,0x20);
mouse_irqs_working=TRUE;
if (mouse_install_attempt_in_progress || !mouse_installed) {
kbdmouse_rst=TRUE;
return;
}
MousePktRead;
}
U0 MouseGetDevType()
{
U8 b;
KbdMouseCmdAck(0xF2);
b=KbdCmdRead;
if (b==3)
mouse_has_wheel=TRUE;
else if (b==4)
mouse_has_ext_buttons=TRUE;
}
Bool MouseRst()
{
U8 b,*_b;
U16 *_w;
I64 i;
Bool result=FALSE,timeout,present;
mouse_has_wheel=FALSE;
mouse_has_ext_buttons=FALSE;
_w=0x40E;
present=MemPagePresentMark(_w,TRUE);
if (*_w==0x9FC0) {
_b=0x9FC00+0x30;
*_b=1; //This enables my mouse. It might be for one machine.
//USB DMA packets, set-up by BIOS to make legacy PS/2?
}
if (!present)
MemPagePresentMark(_w,FALSE);
try {
KbdCmdFlush;
KbdCmdSend(KBD_CTRL,0xAD); //Disable Kbd
KbdCmdSend(KBD_CTRL,0xA8); //Enable Mouse
KbdMouseCmdAck(0xFF); //Rst
for (i=0;i<250;i++) {
try {
KbdCmdRead;
timeout=FALSE;
} catch {
Fs->catch_except=TRUE;
timeout=TRUE;
}
if (!timeout) break;
}
try
KbdCmdRead;
catch
Fs->catch_except=TRUE;
KbdMouseCmdAck(0xF3);
KbdMouseCmdAck(200);
KbdMouseCmdAck(0xF3); // enable Mouse
KbdMouseCmdAck(100); // Set Rate
KbdMouseCmdAck(0xF3);
KbdMouseCmdAck(80); //Resolution
MouseGetDevType; // enable Mouse
KbdMouseCmdAck(0xF3);
KbdMouseCmdAck(10);
MouseGetDevType; // enable Mouse
KbdMouseCmdAck(0xE8); //Resolution
KbdMouseCmdAck(0x03);
KbdMouseCmdAck(0xE6);
KbdMouseCmdAck(0xF3); // Set Rate
KbdMouseCmdAck(100);
KbdMouseCmdAck(0xF4); // enable Mouse
result=TRUE;
//Enable IRQ 12
KbdCmdSend(KBD_CTRL,0x20);
b=KbdCmdRead;
KbdCmdSend(KBD_CTRL,0x60);
KbdCmdSend(KBD_PORT,(b|2)&~0x20);
} catch
Fs->catch_except=TRUE;
//This is been added to override failure
//because the mouse sometimes still works.
result=TRUE;
try
KbdCmdSend(KBD_CTRL,0xAE); //Enable Keyboard
catch
Fs->catch_except=TRUE;
if (mouse_has_wheel || mouse_has_ext_buttons)
mouse_pkt_size=4;
else
mouse_pkt_size=3;
if (!result)
try
KbdCmdSend(KBD_CTRL,0xA7); //Disable Mouse
catch
Fs->catch_except=TRUE;
return result;
}
U0 SetMouseSpeed()
{
I64 dd,temp;
if (dd=(old_mxx-mxx)*(old_mxx-mxx)+
(old_myy-myy)*(old_myy-myy))
if (temp=mouse_evt_time-mouse_last_evt_time)
mouse_speed=Sqrt(dd)*time_stamp_freq/temp;
mouse_last_evt_time=mouse_evt_time;
}
U0 MouseUpdatePre(Bool *old_buttons)
{
I64 i;
old_mxx=mxx; old_myy=myy; old_mzz=mzz;
for (i=0;i<5;i++)
old_buttons[i]=mouse_buttons[i];
}
U0 MouseUpdatePost(Bool *old_buttons)
{
I64 i;
CSnap s;
GetSnap(&s);
if (ip_snap_last.dx!=s.dx)
mxx_prescale*=ip_snap_last.dx/s.dx;
if (ip_snap_last.dy!=s.dy)
myy_prescale*=ip_snap_last.dy/s.dy;
if (ip_snap_last.dz!=s.dz)
mzz_prescale*=ip_snap_last.dz/s.dz;
mxx=mxx_prescale*mxx_scale*s.dx;
myy=myy_prescale*myy_scale*s.dy;
mzz=mzz_prescale*mzz_scale*s.dz;
MemCpy(&ip_snap_last,&s,sizeof(CSnap));
i=ToI64(ipx_scale*mxx/s.x)*s.x+ipx_offset;
if (i<0)
ipx_offset-=i;
else if (i>=gr_width)
ipx_offset+=gr_width-1-i;
i=ToI64(ipy_scale*myy/s.y)*s.y+ipy_offset;
if (i<0)
ipy_offset-=i;
else if (i>=gr_height)
ipy_offset+=gr_height-1-i;
if (mxx!=old_mxx||myy!=old_myy||mzz!=old_mzz) {
mouse_evt=TRUE;
SetMouseSpeed;
} else
for (i=0;i<5;i++)
if (mouse_buttons[i]!=old_buttons[i]) {
mouse_evt=TRUE;
break;
}
}
U0 MouseHandler()
{
I64 i,dx,dy,dz;
U8 mouse_buf[4];
Bool old_buttons[5];
MouseUpdatePre(old_buttons);
for (i=0;i<4;i++)
mouse_buf[i]=0;
for (i=0;i<mouse_pkt_size;i++)
if (!FifoU8Rem(mouse2_fifo,&mouse_buf[i]))
mouse_buf[i]=0;
mouse_buttons[0] = mouse_buf[0] & 1;
mouse_buttons[1] = (mouse_buf[0] & 2) >> 1;
mouse_buttons[2] = (mouse_buf[0] & 4) >> 2;
mouse_buttons[3] = (mouse_buf[3] & 0x10) >> 4;
mouse_buttons[4] = (mouse_buf[3] & 0x20) >> 5;
if (mouse_buf[0] & 0x10)
dx=mouse_buf[1]-256;
else
dx=mouse_buf[1];
if (mouse_buf[0] & 0x20)
dy=256-mouse_buf[2];
else
dy=-mouse_buf[2];
if (mouse_buf[3] & 0x08)
dz=mouse_buf[3]&7-8;
else
dz=mouse_buf[3]&7;
mxx_prescale+=dx;
myy_prescale+=dy;
mzz_prescale+=dz;
MouseUpdatePost(old_buttons);
}
U0 SetMouseIP(I64 x,I64 y,I64 z,I64 l,I64 r,I64 c)
{
Bool old_buttons[5];
CSnap s;
GetSnap(&s);
mouse_evt_time=GetTimeStamp;
MouseUpdatePre(old_buttons);
mxx_prescale=x/mxx_scale/s.dx;
myy_prescale=y/myy_scale/s.dy;
mzz_prescale=z/mzz_scale/s.dz;
mouse_buttons[0]=l;
mouse_buttons[1]=r;
mouse_buttons[2]=c; //unsure which one
MouseUpdatePost(old_buttons);
}
U0 KbdMouseRst()
{
KbdCmdFlush;
FifoU8Flush(kbd2_fifo);
FifoU8Flush(mouse2_fifo);
FifoI64Flush(scan_code_fifo);
sys_cur_scan_code=0;
kbdmouse_rst=FALSE;
}
Bool MouseDriverInstall(I64 dummy=0) //can be spawned
{
nounusedwarn dummy;
I64 i;
Bool old_preempt=IsPreempt;
if (!IsSysDeterministic)
Preempt(ON);
mouse_install_attempt_in_progress=TRUE;
OutU8(0xA1,InU8(0xA1)|0x10);
mouse_installed=mouse_irqs_working=FALSE;
IntEntrySet(0x2C,&MouseIntHandler,0);
for(i=0;i<5;i++)
mouse_buttons[i]=0;
if (i=MouseRst)
OutU8(0xA1,InU8(0xA1)&~0x10);
KbdMouseRst;
mouse_install_attempts++;
mouse_installed=mouse_evt=i;
mouse_install_attempt_in_progress=FALSE;
Preempt(old_preempt);
return mouse_installed;
}
U0 KbdMouseHandler(Bool poll_kbd,Bool poll_mouse)
{
if (mouse_install_attempt_in_progress) {
Yield;
return;
}
if (kbdmouse_rst)
KbdMouseRst;
else {
if (poll_mouse &&
mouse_installed &&
!mouse_irqs_working) {
PushFD;
Cli;
while (InU8(KBD_CTRL)&1)
MousePktRead;
PopFD;
}
if (poll_kbd)
while (InU8(KBD_CTRL)&1)
KbdPktRead;
if (kbdmouse_rst)
KbdMouseRst;
else {
while (FifoU8Cnt(kbd2_fifo))
KbdHandler;
while (FifoU8Cnt(mouse2_fifo))
if (mouse_installed)
MouseHandler;
else
KbdMouseRst;
}
}
}
U0 KbdMouseVarsInit()
{
sys_key_cnt=0;
scan_code_fifo=FifoI64New(128);
kbd_fifo=FifoU8New(8);
kbd2_fifo=FifoU8New(64);
mouse_fifo=FifoU8New(8);
mouse2_fifo=FifoU8New(64);
MemSet(key_down_bitmap,0,256/8);
MemSet(key_down_bitmap2,0,256/8);
sys_last_down_scan_code=0;
sys_cur_scan_code=0;
kbdmouse_rst=FALSE;
kbd_irqs_working=FALSE;
mouse_irqs_working=FALSE;
mxx_scale=0.5;
myy_scale=0.5;
mzz_scale=1.0;
mxx_prescale=gr_width/mxx_scale/2.0;
myy_prescale=gr_height/myy_scale/2.0;
mzz_prescale=0/mzz_scale;
mxx=gr_width>>1;
myy=gr_height>>1;
mzz=0;
mouse_speed=0.0;
old_mxx=mxx;
old_myy=myy;
old_mzz=mzz;
mouse_installed=FALSE;
mouse_install_attempts=0;
mouse_last_evt_time=0;
mouse_has_wheel=FALSE;
mouse_has_ext_buttons=FALSE;
mouse_evt=FALSE;
}
+621
View File
@@ -0,0 +1,621 @@
asm {
USE64
// ************************************
_D3_NORM::
ENTER 0
MOV RDX,U64 SF_ARG1[RBP]
FLD U64 [RDX]
FMUL ST0,ST0
FLD U64 8[RDX]
FMUL ST0,ST0
FADDP ST1,ST0
FLD U64 16[RDX]
FMUL ST0,ST0
FADDP ST1,ST0
FSQRT
FSTP U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG1[RBP]
LEAVE
RET1 8
// ************************************
_D3_SQR_NORM::
ENTER 0
MOV RDX,U64 SF_ARG1[RBP]
FLD U64 [RDX]
FMUL ST0,ST0
FLD U64 8[RDX]
FMUL ST0,ST0
FADDP ST1,ST0
FLD U64 16[RDX]
FMUL ST0,ST0
FADDP ST1,ST0
FSTP U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG1[RBP]
LEAVE
RET1 8
// ************************************
_D3_DIST::
ENTER 0
MOV RDX,U64 SF_ARG1[RBP]
MOV RBX,U64 SF_ARG2[RBP]
FLD U64 [RDX]
FSUB ST0,U64 [RBX]
FMUL ST0,ST0
FLD U64 8[RDX]
FSUB ST0,U64 8[RBX]
FMUL ST0,ST0
FADDP ST1,ST0
FLD U64 16[RDX]
FSUB ST0,U64 16[RBX]
FMUL ST0,ST0
FADDP ST1,ST0
FSQRT
FSTP U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG1[RBP]
LEAVE
RET1 16
// ************************************
_D3_SQR_DIST::
ENTER 0
MOV RDX,U64 SF_ARG1[RBP]
MOV RBX,U64 SF_ARG2[RBP]
FLD U64 [RDX]
FSUB ST0,U64 [RBX]
FMUL ST0,ST0
FLD U64 8[RDX]
FSUB ST0,U64 8[RBX]
FMUL ST0,ST0
FADDP ST1,ST0
FLD U64 16[RDX]
FSUB ST0,U64 16[RBX]
FMUL ST0,ST0
FADDP ST1,ST0
FSTP U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG1[RBP]
LEAVE
RET1 16
// ************************************
_D3_CROSS::
ENTER 0
MOV RDX,U64 SF_ARG1[RBP]
MOV RBX,U64 SF_ARG2[RBP]
MOV RAX,U64 SF_ARG3[RBP]
FLD U64 8[RDX]
FMUL ST0,U64 16[RBX]
FLD U64 16[RDX]
FMUL ST0,U64 8[RBX]
FSUBP ST1,ST0
FSTP U64 [RAX]
FLD U64 [RDX]
FMUL ST0,U64 16[RBX]
FLD U64 16[RDX]
FMUL ST0,U64 [RBX]
FSUBRP ST1,ST0
FSTP U64 8[RAX]
FLD U64 [RDX]
FMUL ST0,U64 8[RBX]
FLD U64 8[RDX]
FMUL ST0,U64 [RBX]
FSUBP ST1,ST0
FSTP U64 16[RAX]
LEAVE
RET1 24
// ************************************
_D3_DOT::
ENTER 0
MOV RDX,U64 SF_ARG1[RBP]
MOV RBX,U64 SF_ARG2[RBP]
FLD U64 [RDX]
FMUL ST0,U64 [RBX]
FLD U64 8[RDX]
FMUL ST0,U64 8[RBX]
FADDP ST1,ST0
FLD U64 16[RDX]
FMUL ST0,U64 16[RBX]
FADDP ST1,ST0
FSTP U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG1[RBP]
LEAVE
RET1 16
// ************************************
_D3_ADD::
ENTER 0
MOV RDX,U64 SF_ARG1[RBP]
MOV RBX,U64 SF_ARG2[RBP]
MOV RAX,U64 SF_ARG3[RBP]
FLD U64 [RDX]
FADD ST0,U64 [RBX]
FSTP U64 [RAX]
FLD U64 8[RDX]
FADD ST0,U64 8[RBX]
FSTP U64 8[RAX]
FLD U64 16[RDX]
FADD ST0,U64 16[RBX]
FSTP U64 16[RAX]
LEAVE
RET1 24
// ************************************
_D3_SUB::
ENTER 0
MOV RDX,U64 SF_ARG1[RBP]
MOV RBX,U64 SF_ARG2[RBP]
MOV RAX,U64 SF_ARG3[RBP]
FLD U64 [RDX]
FSUB ST0,U64 [RBX]
FSTP U64 [RAX]
FLD U64 8[RDX]
FSUB ST0,U64 8[RBX]
FSTP U64 8[RAX]
FLD U64 16[RDX]
FSUB ST0,U64 16[RBX]
FSTP U64 16[RAX]
LEAVE
RET1 24
// ************************************
_D3_MUL::
ENTER 0
MOV RBX,U64 SF_ARG2[RBP]
MOV RAX,U64 SF_ARG3[RBP]
FLD U64 SF_ARG1[RBP]
FLD ST0
FMUL ST0,U64 [RBX]
FSTP U64 [RAX]
FLD ST0
FMUL ST0,U64 8[RBX]
FSTP U64 8[RAX]
FMUL ST0,U64 16[RBX]
FSTP U64 16[RAX]
LEAVE
RET1 24
// ************************************
_D3_DIV::
ENTER 0
MOV RBX,U64 SF_ARG2[RBP]
MOV RAX,U64 SF_ARG3[RBP]
FLD U64 SF_ARG1[RBP]
FLD ST0
FDIVR ST0,U64 [RBX]
FSTP U64 [RAX]
FLD ST0
FDIVR ST0,U64 8[RBX]
FSTP U64 8[RAX]
FDIVR ST0,U64 16[RBX]
FSTP U64 16[RAX]
LEAVE
RET1 24
// ************************************
_D3_ZERO::
ENTER 0
MOV RAX,U64 SF_ARG1[RBP]
XOR RDX,RDX
MOV U64 [RAX],RDX
MOV U64 8[RAX],RDX
MOV U64 16[RAX],RDX
LEAVE
RET1 8
// ************************************
_D3_COPY::
ENTER 0
MOV RAX,U64 SF_ARG1[RBP]
MOV RBX,U64 SF_ARG2[RBP]
MOV RDX,U64 [RBX]
MOV U64 [RAX],RDX
MOV RDX,U64 8[RBX]
MOV U64 8[RAX],RDX
MOV RDX,U64 16[RBX]
MOV U64 16[RAX],RDX
LEAVE
RET1 16
// ************************************
_D3_EQU::
ENTER 0
MOV RAX,U64 SF_ARG1[RBP]
MOV RDX,U64 SF_ARG2[RBP]
MOV U64 [RAX],RDX
MOV RDX,U64 SF_ARG3[RBP]
MOV U64 8[RAX],RDX
MOV RDX,U64 SF_ARG4[RBP]
MOV U64 16[RAX],RDX
LEAVE
RET1 32
// ************************************
_D3_ADD_EQU::
ENTER 0
MOV RAX,U64 SF_ARG1[RBP]
MOV RBX,U64 SF_ARG2[RBP]
FLD U64 [RAX]
FADD ST0,U64 [RBX]
FSTP U64 [RAX]
FLD U64 8[RAX]
FADD ST0,U64 8[RBX]
FSTP U64 8[RAX]
FLD U64 16[RAX]
FADD ST0,U64 16[RBX]
FSTP U64 16[RAX]
LEAVE
RET1 16
// ************************************
_D3_SUB_EQU::
ENTER 0
MOV RAX,U64 SF_ARG1[RBP]
MOV RBX,U64 SF_ARG2[RBP]
FLD U64 [RAX]
FSUB ST0,U64 [RBX]
FSTP U64 [RAX]
FLD U64 8[RAX]
FSUB ST0,U64 8[RBX]
FSTP U64 8[RAX]
FLD U64 16[RAX]
FSUB ST0,U64 16[RBX]
FSTP U64 16[RAX]
LEAVE
RET1 16
// ************************************
_D3_MUL_EQU::
ENTER 0
MOV RAX,U64 SF_ARG1[RBP]
FLD U64 SF_ARG2[RBP]
FLD ST0
FMUL ST0,U64 [RAX]
FSTP U64 [RAX]
FLD ST0
FMUL ST0,U64 8[RAX]
FSTP U64 8[RAX]
FMUL ST0,U64 16[RAX]
FSTP U64 16[RAX]
LEAVE
RET1 16
// ************************************
_D3_DIV_EQU::
ENTER 0
MOV RAX,U64 SF_ARG1[RBP]
FLD U64 SF_ARG2[RBP]
FLD ST0
FDIVR ST0,U64 [RAX]
FSTP U64 [RAX]
FLD ST0
FDIVR ST0,U64 8[RAX]
FSTP U64 8[RAX]
FDIVR ST0,U64 16[RAX]
FSTP U64 16[RAX]
LEAVE
RET1 16
// ************************************
_D3_UNIT::
ENTER 0
MOV RDX,U64 SF_ARG1[RBP]
FLD U64 [RDX]
FMUL ST0,ST0
FLD U64 8[RDX]
FMUL ST0,ST0
FADDP ST1,ST0
FLD U64 16[RDX]
FMUL ST0,ST0
FADDP ST1,ST0
FSQRT
FST U64 SF_ARG1[RBP]
MOV RBX,SF_ARG1[RBP]
OR RBX,RBX
JZ @@05
FLD ST0
FDIVR ST0,U64 [RAX]
FSTP U64 [RAX]
FLD ST0
FDIVR ST0,U64 8[RAX]
FSTP U64 8[RAX]
FDIVR ST0,U64 16[RAX]
FSTP U64 16[RAX]
LEAVE
RET1 8
@@05: FFREE ST0
FINCSTP
LEAVE
RET1 8
// ************************************
_SQR::
ENTER 0
FLD U64 SF_ARG1[RBP]
FMUL ST0,ST0
FSTP U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG1[RBP]
LEAVE
RET1 8
// ************************************
_SIGN::
ENTER 0
FLD U64 SF_ARG1[RBP]
FTST
FSTSW
FFREE ST0
FINCSTP
MOV RDX,RAX
XOR RAX,RAX
BT RDX,14
JC @@05
MOV RAX,1.0
BT RDX,8
JNC @@05
MOV RAX,-1.0
@@05: LEAVE
RET1 8
// ************************************
_ARG::
ENTER 0
FLD U64 SF_ARG2[RBP]
FLD U64 SF_ARG1[RBP]
@@05: FPATAN
FSTSW
TEST AX,0x400
JNZ @@05
FSTP U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG1[RBP]
LEAVE
RET1 16
// ************************************
_ROUND::
ENTER 8
FSTCW U16 -8[RBP]
MOV AX,U16 -8[RBP]
MOV U16 -6[RBP],AX
AND AX,~0x0C00
MOV U16 -8[RBP],AX
FLDCW U16 -8[RBP]
FLD U64 SF_ARG1[RBP]
FRNDINT
FSTP U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG1[RBP]
FLDCW U16 -6[RBP]
LEAVE
RET1 8
// ************************************
_TRUNC::
ENTER 8
FSTCW U16 -8[RBP]
MOV AX,U16 -8[RBP]
MOV U16 -6[RBP],AX
OR AX,0x0C00
MOV U16 -8[RBP],AX
FLDCW U16 -8[RBP]
FLD U64 SF_ARG1[RBP]
FRNDINT
FSTP U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG1[RBP]
FLDCW U16 -6[RBP]
LEAVE
RET1 8
// ************************************
_FLOOR::
ENTER 8
FSTCW U16 -8[RBP]
MOV AX,U16 -8[RBP]
MOV U16 -6[RBP],AX
AND AX,~0x0C00
OR AX,0x0400
MOV U16 -8[RBP],AX
FLDCW U16 -8[RBP]
FLD U64 SF_ARG1[RBP]
FRNDINT
FSTP U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG1[RBP]
FLDCW U16 -6[RBP]
LEAVE
RET1 8
// ************************************
_CEIL::
ENTER 8
FSTCW U16 -8[RBP]
MOV AX,U16 -8[RBP]
MOV U16 -6[RBP],AX
AND AX,~0x0C00
OR AX,0x0800
MOV U16 -8[RBP],AX
FLDCW U16 -8[RBP]
FLD U64 SF_ARG1[RBP]
FRNDINT
FSTP U64 SF_ARG1[RBP]
MOV RAX,SF_ARG1[RBP]
FLDCW U16 -6[RBP]
LEAVE
RET1 8
// ************************************
SYS_POW::
// RAX=RDX`RAX
ENTER 24
OR RAX,RAX //To power of zero?
JNZ @@05
MOV RAX,1.0
JMP @@20
@@05: OR RDX,RDX //zero to a power?
JNZ @@10
XOR RAX,RAX
JMP @@20
@@10: MOV RCX,RAX //RCX=pow
MOV U64 -8[RBP],RDX
MOV U64 -16[RBP],RAX
FSTCW U16 -24[RBP]
MOV AX,U16 -24[RBP]
MOV U16 -22[RBP],AX
OR AX,0x0C00
MOV U16 -24[RBP],AX
FLDCW U16 -24[RBP]
FLD U64 -16[RBP]
FLD U64 -8[RBP]
FABS //base should be pos
FYL2X // y*log2(x)
FST U64 -8[RBP]
FRNDINT
FLD U64 -8[RBP]
FSUBRP ST1,ST0
F2XM1
FLD1
FADDP ST1,ST0
FSTP U64 -16[RBP]
FLD U64 -8[RBP]
FLD U64 -16[RBP]
FSCALE // ST0<<ST1
OR RDX,RDX //was base neg?
JGE @@15
MOV U64 -16[RBP],RCX
FLD U64 -16[RBP]
FISTTP U64 -16[RBP]
TEST U64 -16[RBP],1
JZ @@15 //was pow odd?
FCHS
@@15: FSTP U64 -8[RBP]
FFREE ST0
FINCSTP
FLDCW U16 -22[RBP]
MOV RAX,U64 -8[RBP]
@@20: LEAVE
RET
// ************************************
_POW::
ENTER 0
MOV RAX,U64 SF_ARG2[RBP]
MOV RDX,U64 SF_ARG1[RBP]
CALL SYS_POW
LEAVE
RET1 16
// ************************************
_POW10::
ENTER 16
FSTCW U16 -8[RBP]
MOV AX,U16 -8[RBP]
MOV U16 -6[RBP],AX
OR AX,0x0C00
MOV U16 -8[RBP],AX
FLDCW U16 -8[RBP]
FLDL2T
FLD U64 SF_ARG1[RBP]
FMULP ST1,ST0
FST U64 SF_ARG1[RBP]
FRNDINT
FLD U64 SF_ARG1[RBP]
FSUBRP ST1,ST0
F2XM1
FLD1
FADDP ST1,ST0
FSTP U64 -16[RBP]
FLD U64 SF_ARG1[RBP]
FLD U64 -16[RBP]
FSCALE // ST0<<ST1
FSTP U64 -16[RBP]
FFREE ST0
FINCSTP
FLDCW U16 -6[RBP]
MOV RAX,U64 -16[RBP]
LEAVE
RET1 8
// ************************************
_EXP::
ENTER 16
FSTCW U16 -8[RBP]
MOV AX,U16 -8[RBP]
MOV U16 -6[RBP],AX
OR AX,0x0C00
MOV U16 -8[RBP],AX
FLDCW U16 -8[RBP]
FLDL2E
FLD U64 SF_ARG1[RBP]
FMULP ST1,ST0
FST U64 SF_ARG1[RBP]
FRNDINT
FLD U64 SF_ARG1[RBP]
FSUBRP ST1,ST0
F2XM1
FLD1
FADDP ST1,ST0
FSTP U64 -16[RBP]
FLD U64 SF_ARG1[RBP]
FLD U64 -16[RBP]
FSCALE // ST0<<ST1
FSTP U64 -16[RBP]
FFREE ST0
FINCSTP
FLDCW U16 -6[RBP]
MOV RAX,U64 -16[RBP]
LEAVE
RET1 8
// ************************************
_LOG10::
ENTER 8
FLDLG2
FLD U64 SF_ARG1[RBP]
FYL2X // y*log2(x)
FSTP U64 -8[RBP]
MOV RAX,U64 -8[RBP]
LEAVE
RET1 8
// ************************************
_LOG2::
ENTER 8
FLD1
FLD U64 SF_ARG1[RBP]
FYL2X // y*log2(x)
FSTP U64 -8[RBP]
MOV RAX,U64 -8[RBP]
LEAVE
RET1 8
// ************************************
_LN::
ENTER 8
FLDLN2
FLD U64 SF_ARG1[RBP]
FYL2X // y*log2(x)
FSTP U64 -8[RBP]
MOV RAX,U64 -8[RBP]
LEAVE
RET1 8
// ************************************
_FLDCW::
ENTER 0
FLDCW U16 SF_ARG1[RBP]
LEAVE
RET1 8
// ************************************
_FSTCW::
ENTER 8
FSTCW U16 -8[RBP]
MOVZX RAX,U16 -8[RBP]
LEAVE
RET
// ************************************
_FSTSW::
XOR RAX,RAX
FSTSW
RET
// ************************************
_FCLEX::
FCLEX
RET
// ************************************
_FXSAVE::
ENTER 0
MOV RAX,U64 SF_ARG1[RBP]
FXSAVE U64 [RAX]
LEAVE
RET1 8
// ************************************
_FXRSTOR::
ENTER 0
MOV RAX,U64 SF_ARG1[RBP]
FXRSTOR U64 [RAX]
LEAVE
RET1 8
}
+226
View File
@@ -0,0 +1,226 @@
F64 Limit(F64 p,F64 lo,F64 hi)
{
if (p<lo)
return lo;
if (p>hi)
return hi;
return p;
}
F64 Min(F64 n1,F64 n2)
{
if (n1<=n2)
return n1;
else
return n2;
}
F64 Max(F64 n1,F64 n2)
{
if (n1>=n2)
return n1;
else
return n2;
}
F64 Pow10I64(I64 i)
{
if (i>308)
return ì;
else if (i<-308)
return 0.0;
else
return pow10_I64[i+309];
}
U64 FloorU64(U64 num,U64 to)
{
return num-num%to;
}
U64 CeilU64(U64 num,U64 to)
{
num+=to-1;
return num-num%to;
}
I64 RoundI64(I64 num,I64 to)
{
return num-num%to;
}
I64 FloorI64(I64 num,I64 to)
{
if (num>=0)
return num-num%to;
else {
num++;
return num-num%to-to;
}
}
I64 CeilI64(I64 num,I64 to)
{
if (num>=0) {
num+=to-1;
return num-num%to;
} else {
num+=to-1;
return num-num%to-to;
}
}
//See $LK,"::/SparrowOS/Doc/Acknowledgements.TXT.Z","FI:::/SparrowOS/Doc/Acknowledgements.TXT.Z"$ (6).
#ifdef SYS_DETERMINISTIC
$FG,6$U16 RandU16()
{
Fs->rnd_seed.i32[0]=1664525*Fs->rnd_seed.i32[0]+1013904223;
return Fs->rnd_seed.u16[0];
}
I16 RandI16()
{
Fs->rnd_seed.i32[0]=1664525*Fs->rnd_seed.i32[0]+1013904223;
return Fs->rnd_seed.i16[0];
}
U32 RandU32()
{
Fs->rnd_seed.i32[0]=1664525*Fs->rnd_seed.i32[0]+1013904223;
return Fs->rnd_seed.u32[0];
}
I32 RandI32()
{
Fs->rnd_seed.i32[0]=1664525*Fs->rnd_seed.i32[0]+1013904223;
return Fs->rnd_seed.i32[0];
}
U64 RandU64()
{
U64 result;
result.u32[0]=Fs->rnd_seed.i32[0]= 1664525*Fs->rnd_seed.i32[0]+1013904223;
result.u32[1]=Fs->rnd_seed.i32[0]= 1664525*Fs->rnd_seed.i32[0]+1013904223;
return result;
}
I64 RandI64()
{
I64 result;
result.u32[0]=Fs->rnd_seed.i32[0]= 1664525*Fs->rnd_seed.i32[0]+1013904223;
result.u32[1]=Fs->rnd_seed.i32[0]= 1664525*Fs->rnd_seed.i32[0]+1013904223;
return result;
}
F64 Rand()
{ //0.0<=x<1.0
I64 result;
result.u32[0]=Fs->rnd_seed.i32[0]= 1664525*Fs->rnd_seed.i32[0]+1013904223;
result.u32[1]=Fs->rnd_seed.i32[0]= 1664525*Fs->rnd_seed.i32[0]+1013904223;
result&=0x3FFFFFFFFFFFFFFF;
return result/ToF64(0x4000000000000000);
}
#else
$FG,5$U16 RandU16()
{
sys_rnd_seed.i32[0]=(1664525*sys_rnd_seed.i32[0]+1013904223)^GetTimeStamp>>4;
return sys_rnd_seed.u16[0];
}
I16 RandI16()
{
sys_rnd_seed.i32[0]=(1664525*sys_rnd_seed.i32[0]+1013904223)^GetTimeStamp>>4;
return sys_rnd_seed.i16[0];
}
U32 RandU32()
{
sys_rnd_seed.i32[0]=(1664525*sys_rnd_seed.i32[0]+1013904223)^GetTimeStamp>>4;
return sys_rnd_seed.u32[0];
}
I32 RandI32()
{
sys_rnd_seed.i32[0]=(1664525*sys_rnd_seed.i32[0]+1013904223)^GetTimeStamp>>4;
return sys_rnd_seed.i32[0];
}
U64 RandU64()
{
U64 result;
result.u32[0]=sys_rnd_seed.i32[0]=(1664525*sys_rnd_seed.i32[0]+1013904223)^GetTimeStamp>>4;
result.u32[1]=sys_rnd_seed.i32[0]= 1664525*sys_rnd_seed.i32[0]+1013904223;
return result;
}
I64 RandI64()
{
I64 result;
result.u32[0]=sys_rnd_seed.i32[0]=(1664525*sys_rnd_seed.i32[0]+1013904223)^GetTimeStamp>>4;
result.u32[1]=sys_rnd_seed.i32[0]= 1664525*sys_rnd_seed.i32[0]+1013904223;
return result;
}
F64 Rand()
{ //0.0<=x<1.0
I64 result;
result.u32[0]=sys_rnd_seed.i32[0]=(1664525*sys_rnd_seed.i32[0]+1013904223)^GetTimeStamp>>4;
result.u32[1]=sys_rnd_seed.i32[0]= 1664525*sys_rnd_seed.i32[0]+1013904223;
result&=0x3FFFFFFFFFFFFFFF;
return result/ToF64(0x4000000000000000);
}
$FD$#endif
U16 Rand2U16()
{
Fs->rnd_seed.i32[0]=1664525*Fs->rnd_seed.i32[0]+1013904223;
return Fs->rnd_seed.u16[0];
}
I16 Rand2I16()
{
Fs->rnd_seed.i32[0]=1664525*Fs->rnd_seed.i32[0]+1013904223;
return Fs->rnd_seed.i16[0];
}
U32 Rand2U32()
{
Fs->rnd_seed.i32[0]=1664525*Fs->rnd_seed.i32[0]+1013904223;
return Fs->rnd_seed.u32[0];
}
I32 Rand2I32()
{
Fs->rnd_seed.i32[0]=1664525*Fs->rnd_seed.i32[0]+1013904223;
return Fs->rnd_seed.i32[0];
}
U64 Rand2U64()
{
U64 result;
result.u32[0]=Fs->rnd_seed.i32[0]= 1664525*Fs->rnd_seed.i32[0]+1013904223;
result.u32[1]=Fs->rnd_seed.i32[0]= 1664525*Fs->rnd_seed.i32[0]+1013904223;
return result;
}
I64 Rand2I64()
{
I64 result;
result.u32[0]=Fs->rnd_seed.i32[0]= 1664525*Fs->rnd_seed.i32[0]+1013904223;
result.u32[1]=Fs->rnd_seed.i32[0]= 1664525*Fs->rnd_seed.i32[0]+1013904223;
return result;
}
F64 Rand2()
{ //0.0<=x<1.0
I64 result;
result.u32[0]=Fs->rnd_seed.i32[0]= 1664525*Fs->rnd_seed.i32[0]+1013904223;
result.u32[1]=Fs->rnd_seed.i32[0]= 1664525*Fs->rnd_seed.i32[0]+1013904223;
result&=0x3FFFFFFFFFFFFFFF;
return result/ToF64(0x4000000000000000);
}
U0 Randomize(I64 seed=0)
{ //Randomizes seed.
Fs->rnd_seed=seed;
}
File diff suppressed because it is too large. Load diff
+384
View File
@@ -0,0 +1,384 @@
U0 PortNop()
{
InU8(0x21); //This is an innoculous (reads IRQ Mask)
//access which should take
//fixed time because it's an ISA-bus standard.
//It takes 1.0uS-2.0uS
}
U16 EndianU16(U16 d)
{
I64 result=0;
result.u8[1]=d.u8[0];
result.u8[0]=d.u8[1];
return result;
}
U32 EndianU32(U32 d)
{
I64 result=0;
result.u8[3]=d.u8[0];
result.u8[2]=d.u8[1];
result.u8[1]=d.u8[2];
result.u8[0]=d.u8[3];
return result;
}
U64 EndianU64(U64 d)
{
U64 result;
result.u8[7]=d.u8[0];
result.u8[6]=d.u8[1];
result.u8[5]=d.u8[2];
result.u8[4]=d.u8[3];
result.u8[3]=d.u8[4];
result.u8[2]=d.u8[5];
result.u8[1]=d.u8[6];
result.u8[0]=d.u8[7];
return result;
}
I64 BCnt(I64 d)
{
I64 result=0,i;
for (i=0;i<8;i++)
result+=set_bits_table[d.u8[i]];
return result;
}
U0 IntSimpleTimer(CTask *)
{
I64 i;
if (mp_cnt>1)
while (LBts(&sys_semas[SYS_SEMA_SYS_TIMER],0))
Pause;
lock sys_jiffies++;
sys_timer+=SYS_TIMER0_PERIOD+1;
LBtr(&sys_semas[SYS_SEMA_SYS_TIMER],0);
for (i=1;i<mp_cnt;i++)
MPInt(I_TIMER,i);
}
I64 SysTimerRead()
{
I64 i,result;
PushFD;
Cli;
if (mp_cnt>1)
while (LBts(&sys_semas[SYS_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;
}
result=sys_timer+SYS_TIMER0_PERIOD-i;
LBtr(&sys_semas[SYS_SEMA_SYS_TIMER],0);
PopFD;
return result;
}
I64 TaskTotalTime()
{
return GetTimeStamp-Fs->time_slice_start+Fs->total_time;
}
I64 TimeStampFreqCal()
{
static I64 time_stamp_start=0,timer_start=0,HPET_start=0;
I64 i;
if (time_stamp_start) {
PushFD;
Cli;
if (HPET_start) {
time_stamp_freq=HPET_freq*(GetTimeStamp-time_stamp_start);
i=HPET-HPET_start;
} else {
time_stamp_freq=SYS_TIMER_FREQ*(GetTimeStamp-time_stamp_start);
i=SysTimerRead-timer_start;
}
if (!i)
Dbg("Timer Cal Error");
time_stamp_freq/=i;
time_stamp_kHz_freq=time_stamp_freq/1000;
PopFD;
time_stamp_freq_calibrated=TRUE;
}
PushFD;
Cli;
if (HPET_freq) {
timer_start=0;
HPET_start=HPET;
} else {
HPET_start=0;
timer_start=SysTimerRead;
}
time_stamp_start=GetTimeStamp;
PopFD;
return time_stamp_freq;
}
F64 tNP()
//Time since boot in seconds as a float
{
static I64 last_time_stamp=0;
static F64 last_result=0;
I64 time_stamp;
if (HPET_freq)
return ToF64(HPET)/HPET_freq;
else { //Monotonically incresing,calibrated.
PushFD;
Cli;
if (mp_cnt>1)
while (LBts(&sys_semas[SYS_SEMA_TNP],0))
Pause;
time_stamp=GetTimeStamp;
last_result+=ToF64(time_stamp-last_time_stamp)/time_stamp_freq;
last_time_stamp=time_stamp;
LBtr(&sys_semas[SYS_SEMA_TNP],0);
PopFD;
return last_result;
}
}
F64 tP(CTask *task=NULL)
{ //Time in seconds, stopped during pauses
F64 result;
Bool old_preempt=Preempt(OFF);
if (!task) task=Fs;
if (TaskValidate(task)) {
if (Bt(&task->task_flags,TASKf_PAUSED))
result=task->pause_start-task->pause_total;
else
result=tNP-task->pause_total;
Preempt(old_preempt);
return result;
}
Preempt(old_preempt);
return tNP;
}
F64 tJ()
{
return sys_jiffies/ToF64(JIFFY_FREQ);
}
F64 tS()
{
return SysTimerRead/ToF64(SYS_TIMER_FREQ);
}
Bool Blink(F64 Hz=2.5,F64 t=0)
{
if (!Hz) return 0;
if (t)
return ToI64(t*2*Hz)&1;
else
return ToI64(sys_jiffies*2*Hz/JIFFY_FREQ)&1;
}
U0 BusyWait(I64 æS) //Loosely timed
{
I64 i;
for (i=0;i<æS;i++)
PortNop;
}
U0 SleepUntil(I64 wake_jiffy)
//This routine is not for power-saving
//it is to make a program pause without
//hogging the CCPU.
{
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)
//This routine is not for power-saving
//it is to make a program pause without
//hogging the CCPU.
{
if (!mS)
Yield;
else
SleepUntil(sys_jiffies+mS*JIFFY_FREQ/1000);
}
U0 Snd(F64 freq,I64 waveform=WF_SQUARE,F64 amp=1.0)
// The internal PC speaker only does square waves.
// waveform and amp are for HDAudio.
// Use $LK,"SndFilePlay","MN:SndFilePlay"$() or $LK,"::/SparrowOS/Demo/Snd/PolyPhonic.CPP.Z","FI:::/SparrowOS/Demo/Snd/PolyPhonic.CPP.Z"$ as a template for
// doing polyphonic or fancy HD Audio snd.
{
I64 p;
if (!Bt(&sys_semas[SYS_SEMA_MUTE],0) && snd_vol &&
!LBts(&sys_semas[SYS_SEMA_SND],0)) {
if (!IsInDbg && snd_dev!=SD_PC_SPEAKER) {
snd_freq=freq;
if (fp_snd) {
if (0<freq<=20000 && amp>0)
(*fp_snd)(freq,waveform,amp);
else
(*fp_snd)(0,waveform,0);
}
} else {
if (freq!=snd_freq) {
snd_freq=freq;
if (0<freq<=20000 && amp>0) {
p=SYS_TIMER_FREQ/freq;
OutU8(0x43,0xB6);
OutU8(0x42,p);
OutU8(0x42,p.u8[1]);
OutU8(0x61,3|InU8(0x61));
} else
OutU8(0x61,InU8(0x61)&~3);
}
}
if (!IsInDbg && snd_record && fp_snd_record)
(*fp_snd_record)(freq,waveform,amp);
LBtr(&sys_semas[SYS_SEMA_SND],0);
}
}
U0 Beep(I64 freq=500,Bool busy=FALSE)
{
Snd(freq);
if (busy) BusyWait(500000);
else Sleep(500);
Snd(0);
if (busy) BusyWait(200000);
else Sleep(200);
}
Bool Mute(Bool val)
{
Bool result;
if (val) {
PushFD;
Cli;
Snd(0);
result=LBts(&sys_semas[SYS_SEMA_MUTE],0);
PopFD;
} else
result=LBtr(&sys_semas[SYS_SEMA_MUTE],0);
return result;
}
Bool IsMute() {
return Bt(&sys_semas[SYS_SEMA_MUTE],0);
}
Bool Silent(Bool val) {
//This turns-off console output, not sound.
return LBEqu(&Fs->display_flags,DISPLAYf_SILENT,val);
}
Bool IsSilent() {
return Bt(&Fs->display_flags,DISPLAYf_SILENT);
}
Bool IOSnd(Bool val) {
Bool result=!LBEqu(&sys_semas[SYS_SEMA_NO_IO_SND],0,!val);
Snd(0);
return result;
}
Bool IsPreempt() {
return Bt(&Fs->task_flags,TASKf_PREEMPT);
}
Bool SysDbg(Bool val) {
//Sets or rsts a bit which you can
//use while debugging.
return LBEqu(&sys_semas[SYS_SEMA_DEBUG],0,val);
}
Bool IsSysDbg() {
return Bt(&sys_semas[SYS_SEMA_DEBUG],0);
}
Bool SysDeterministic(Bool val) {
//Sets or rsts a bit which tries to keep the system deterministic, for debugging.
return LBEqu(&sys_semas[SYS_SEMA_DETERMINISTIC],0,val);
}
Bool IsSysDeterministic() {
return Bt(&sys_semas[SYS_SEMA_DETERMINISTIC],0);
}
Bool Raw(Bool val) {
//Switches to direct screen output
//mode for when you don't have
//a working window.
if (!val)
VGAFlush;
return !LBEqu(&Fs->task_flags,TASKf_NOT_RAW,!val);
}
Bool IsRaw() {
return !Bt(&Fs->task_flags,TASKf_NOT_RAW);
}
Bool SingleUser(Bool val) {
return LBEqu(&sys_semas[SYS_SEMA_SINGLE_USER],0,val);
}
Bool IsSingleUser() {
return Bt(&sys_semas[SYS_SEMA_SINGLE_USER],0);
}
Bool InDbg(Bool val) {
return LBEqu(&sys_semas[SYS_SEMA_IN_DEBUGGER],0,val);
}
Bool IsInDbg() {
return Bt(&sys_semas[SYS_SEMA_IN_DEBUGGER],0);
}
U0 ProgressBarsRst()
{
MemSet(sys_progresses,0,sizeof(sys_progresses));
}
U0 CtrlAltDel(I64)
{
LBts(sys_ctrl_alt_flags,SYSf_CTRL_ALT_DEL);
}
U0 CtrlAltC(I64)
{
LBts(sys_ctrl_alt_flags,SYSf_CTRL_ALT_C);
}
U0 CtrlAltE(I64)
{
SpawnUser;
}
U0 CtrlAltF(I64)
{
VGAFlush;
}
U0 CtrlAltM(I64)
{
Mute(!IsMute);
}
U0 CtrlAltP(I64)
{
if (sys_focus_task)
TaskPause(sys_focus_task,!Bt(&sys_focus_task->task_flags,TASKf_PAUSED));
}
U0 CtrlAltT(I64)
{
LBts(sys_ctrl_alt_flags,SYSf_CTRL_ALT_TAB);
}
U0 CtrlAltX(I64)
{
LBts(sys_ctrl_alt_flags,SYSf_CTRL_ALT_X);
}
+521
View File
@@ -0,0 +1,521 @@
asm {
ALIGN 16,OC_NOP
USE16
//See $LK,"SparrowOS MultiCore","FI:::/SparrowOS/Doc/MultiCore.TXT.Z"$.
//This code gets copied to $LK,"MP_VECT_ADDR","MN:MP_VECT_ADDR"$.
//See $LK,"MemCpy(MP_VECT_ADDR","FF:::/SparrowOS/OSMain/MultiProc.CPP.Z,MemCpy(mp:2"$.
SYS_MP_INIT_START::
JMP MP2_START2
ALIGN 4,OC_NOP
MP2_SYS_TEMP_PTR: DU32 0,0;
MP2_START2:
CLI
WBINVD
MOV AX,MP_VECT_ADDR/16
MOV DS,AX
//See $LK,"mp->sys_temp_ptr","FF:::/SparrowOS/OSMain/MultiProc.CPP.Z,mp->sys_temp_ptr:2"$
#assert MP2_SYS_TEMP_PTR-SYS_MP_INIT_START==CMPMain.sys_temp_ptr
LGDT U32 [CMPMain.sys_temp_ptr]
MOV EAX,SYS_START_CR0
MOV_CR0_EAX
DU8 0x66,0xEA; //JMP GDT_CS_SEL:MP_INIT_OS
DU32 MP_INIT_OS;
DU16 GDT_CS_SEL;
SYS_MP_INIT_END::
USE32
MP_INIT_OS:
MOV AX,GDT_ZERO_DS_SEL
MOV DS,AX
MOV ES,AX
MOV FS,AX
MOV GS,AX
MOV SS,AX
@@05: LOCK
BTS U32 [SYS_MP_CNT_LOCK],0
JC @@05
MOV ESI,U32 [SYS_MP_CNT_INITIAL]
LOCK
INC U32 [SYS_MP_CNT_INITIAL]
LOCK
BTR U32 [SYS_MP_CNT_LOCK],0
CMP ESI,MP_MAX_PROCESSORS
JAE I32 _SYS_HLT
IMUL2 ESI,sizeof(CCPU)
ADD ESI,U32 [SYS_CPU_STRUCTS]
LEA EAX,U32 CCPU.start_stk+sizeof(CCPU.start_stk)[ESI]
MOV ESP,EAX
PUSH U32 SYS_START_RFLAGS
POPFD
PUSH U32 0
CALL INIT_EM64T
USE64
FNINIT
PUSH RSI
PUSH RSI
CALL _SET_GS_BASE
POP RSI
@@10: MOV RBX,U64 CCPU.seth_task[RSI]
OR RBX,RBX
JZ @@10
MOV U64 CTask.gs[RBX],RSI
MOV RAX,RBX
CALL SET_FS_BASE
JMP I32 SYS_RESTORE_CONTEXT
}
U0 TSSBusy(I64 tr,Bool val=OFF)
{
LBEqu((&sys_gdttab)(U8 *)+tr+4,9,val);
}
CTSS *TSSNew(I64 cpu_num)
{
U32 *d,*d1;
CTSS *tss=CAlloc(sizeof(CTSS));
tss->io_map_offset=offset(CTSS.io_map);
MemSet(tss->io_map,0xFF,0x10000/8);
tss->st0=MAlloc(INTERRUPT_STK);
tss->rsp0=tss->st0(U8 *)+MSize(tss->st0);
tss->st1=MAlloc(INTERRUPT_STK);
tss->rsp1=tss->st1(U8 *)+MSize(tss->st1);
tss->st2=MAlloc(INTERRUPT_STK);
tss->rsp2=tss->st2(U8 *)+MSize(tss->st2);
tss->tr =GDT_CPU_TR_SELS+cpu_num*16;
tss->tr_ring3=GDT_CPU_TR_RING3_SELS+cpu_num*16;
d=(&sys_gdttab)(U8 *)+tss->tr;
d1=d(U8 *)+4;
*d =0x0000FFFF;
*d1=0x008F8900;
d(U8 *)+=2;
*d|=tss & 0x00FFFFFF;
*d1++|=tss & 0xFF000000;
*d1++=tss>>32;
*d1=0;
d=(&sys_gdttab)(U8 *)+tss->tr_ring3;
d1=d(U8 *)+4;
*d =0x0000FFFF;
*d1=0x008FE900;
d(U8 *)+=2;
*d|=tss & 0x00FFFFFF;
*d1++|=tss & 0xFF000000;
*d1++=tss>>32;
*d1=0;
return tss;
}
U0 MPCmdCtrlInit(CMPCmdCtrl *ctrl)
{
MemSet(ctrl,0,sizeof(CMPCmdCtrl));
QueInit(ctrl);
ctrl->next_done=ctrl->last_done=&ctrl->next_done;
}
CCPU *CPUStructInit(I64 num,CCPU *c)
{
MemSet(c,0,sizeof(CCPU));
c->addr=c;
c->num=num;
c->idle_factor=0.01;
MPCmdCtrlInit(&c->cmd_ctrl);
if (num)
c->idle_task=Spawn(0,NULL,"Idle Task",Fs,,0);
else
c->timer_irq_chain=&IntSimpleTimer;
return c;
}
U0 MPInt(U8 num,I64 cpu_num=1)
{
if (cpu_num>=mp_cnt) {
if (!Bt(&sys_run_level,RLf_MP))
return;
else
throw(EXCEPT_MULTICORE,0);
}
PushFD;
Cli; //multitasking safe because each core has a local apic and IRQ's are off
while (*LAPIC_ICR_LOW(U32 *)&0x1000)
Pause;
*LAPIC_ICR_HIGH(U32 *)=mp_apic_ids[cpu_num]<<24;
*LAPIC_ICR_LOW(U32 *)=0x4000+num;
PopFD;
}
U0 MPIntAll(U8 num)
{ //(All but self)
PushFD;
Cli; //multitasking safe because each core has a local apic and IRQ's are off
while (*LAPIC_ICR_LOW(U32 *)&0x1000)
Pause;
*LAPIC_ICR_LOW(U32 *)=0xC4800+num;
PopFD;
}
U0 MPNMInt()
{
*LAPIC_ICR_LOW(U32 *)=0xC4400;
}
U0 MPHalt()
{
mp_cnt=1;
MPNMInt; //Hlt All other processors
BusyWait(10000);
}
U0 MPWake(I64 target_cpu_mask)
{
I64 i;
target_cpu_mask&=1<<mp_cnt-1;
Btr(&target_cpu_mask,Gs->num);
PushFD;
Cli;
for (i=Bsf(target_cpu_mask);target_cpu_mask;i++)
if (Btr(&target_cpu_mask,i)) {
if (Bt(&cpu_structs[i].cpu_flags,CPUf_SETH_SLEEP))
cpu_structs[i].seth_task->wake_jiffy=0;
MPInt(I_WAKE,i);
if (Bt(&cpu_structs[i].cpu_flags,CPUf_SETH_SLEEP)) //In case went back to sleep
cpu_structs[i].seth_task->wake_jiffy=0;
}
PopFD;
}
U0 MPAPICInit()
{ //Called by adam during start-up
//and other cores during initialization
//after $LK,"MPStart","MN:MPStart"$().
*LAPIC_SVR(U32 *)|=LAPICF_APIC_ENABLED;
mp_apic_ids[Gs->num]=*LAPIC_APIC_ID(U32 *)>>24;
*LAPIC_LDR(U32 *)=mp_apic_ids[Gs->num]<<24;
*LAPIC_DFR(U32 *)=0xF0000000;
/*
MemSet(LAPIC_IRR,0,0x20);
MemSet(LAPIC_ISR,0,0x20);
MemSet(LAPIC_TMR,0,0x20);
*/
SetRAX(Gs->tss->tr);
asm { LTR AX }
if (Gs->num) {
IntInit1;
SetFlags(SYS_NORMAL_RFLAGS);
BusyWait(2000);
IntInit2;
}
}
#assert !offset(CMPCmdCtrl.next_waiting)
Bool MPCmdCtrlDo(CMPCmdCtrl *ctrl)
{ //Called while locked
CMPCmd *tempm=ctrl->next_waiting;
while (tempm!=ctrl && !Bt(&tempm->target_cpu_mask,Gs->num))
tempm=tempm->next;
if (tempm!=ctrl) {
QueRem(tempm);
LBts(&tempm->flags,MPCf_DISPATCHED);
tempm->handler_cpu=Gs->num;
LBtr(&ctrl->flags,MPCCf_LOCKED);
switch (tempm->cmd_code) {
case MPCT_CALL:
tempm->result=(*tempm->add)(tempm->data);
Preempt(OFF);
Sti;
break;
case MPCT_SPAWN_TASK:
if (tempm->desc)
tempm->task=Spawn(tempm->add,tempm->data,tempm->desc);
else
tempm->task=Spawn(tempm->add,tempm->data,"MP Job");
break;
}
if (Bt(&tempm->flags,MPCf_FREE_ON_COMPLETE)) {
Free(tempm->desc);
Free(tempm);
} else {
while (LBts(&ctrl->flags,MPCCf_LOCKED))
Yield;
QueIns(tempm,ctrl->last_done);
LBts(&tempm->flags,MPCf_DONE);
LBtr(&ctrl->flags,MPCCf_LOCKED);
}
return TRUE;
} else {
LBtr(&ctrl->flags,MPCCf_LOCKED);
return FALSE;
}
}
U0 MPSethServerTask()
{
CMPCmdCtrl *my_ctrl=&Gs->cmd_ctrl;
Sti;
while (TRUE) {
TaskFinishOffDying;
if (!LBts(&my_ctrl->flags,MPCCf_LOCKED) &&
!MPCmdCtrlDo(my_ctrl) && //Jobs for this core are highest priority.
!LBts(&mp_ctrl->flags,MPCCf_LOCKED))
MPCmdCtrlDo(mp_ctrl);
if (my_ctrl->next_waiting==my_ctrl &&
mp_ctrl->next_waiting==mp_ctrl) {
LBts(&Gs->cpu_flags,CPUf_SETH_SLEEP);
Sleep(20); //We don't want this too long because of need for $LK,"TaskFinishOffDying","MN:TaskFinishOffDying"$().
LBtr(&Gs->cpu_flags,CPUf_SETH_SLEEP);
}
}
}
CMPCmd *MPQueJob(I64 (*fp_add)(U8 *data),U8 *data=NULL,
U8 *desc=NULL,
I64 flags=1<<MPCf_FREE_ON_COMPLETE,
Bool spawn=FALSE,I64 target_cpu_mask=ALL_MASK)
{
I64 i=Bsf(target_cpu_mask);
CMPCmdCtrl *ctrl;
CMPCmd *tempm;
if (mp_cnt<2 || i<0) throw(EXCEPT_MULTICORE,1);
tempm=ACAlloc(sizeof(CMPCmd));
if (desc)
tempm->desc=AStrNew(desc);
if (spawn)
tempm->cmd_code=MPCT_SPAWN_TASK;
else
tempm->cmd_code=MPCT_CALL;
tempm->add=fp_add;
tempm->data=data;
tempm->target_cpu_mask=target_cpu_mask;
tempm->flags=flags;
if (i==Bsr(target_cpu_mask))
tempm->ctrl=ctrl=&cpu_structs[i].cmd_ctrl;
else
tempm->ctrl=ctrl=mp_ctrl;
PushFD;
Cli;
while (LBts(&ctrl->flags,MPCCf_LOCKED))
Yield;
QueIns(tempm,ctrl->last_waiting);
LBtr(&ctrl->flags,MPCCf_LOCKED);
PopFD;
MPWake(target_cpu_mask);
return tempm;
}
CMPCmd *MPJob(I64 (*fp_add)(U8 *data),U8 *data=NULL,
I64 target_cpu=1,I64 flags=1<<MPCf_FREE_ON_COMPLETE)
//Set flags to zero if you wish to
//get the result.
{
return MPQueJob(fp_add,data,NULL,flags,FALSE,1<<target_cpu);
}
I64 MPJobResult(CMPCmd *tempm)
{
I64 result;
CMPCmdCtrl *ctrl=tempm->ctrl;
if (mp_cnt<2) throw(EXCEPT_MULTICORE,2);
while (!Bt(&tempm->flags,MPCf_DONE))
Yield;
PushFD;
Cli;
while (LBts(&ctrl->flags,MPCCf_LOCKED))
Yield;
QueRem(tempm);
LBtr(&ctrl->flags,MPCCf_LOCKED);
PopFD;
result=tempm->result;
Free(tempm->desc);
Free(tempm);
return result;
}
CTask *MPSpawn(U0 (*fp_add)(U8 *data),U8 *data=NULL,U8 *name=NULL,I64 target_cpu=1)
{
CTask *result;
CMPCmd *tempm=MPQueJob(fp_add,data,name,0,TRUE,1<<target_cpu);
CMPCmdCtrl *ctrl;
while (!Bt(&tempm->flags,MPCf_DONE))
Yield;
result=tempm->task;
ctrl=tempm->ctrl;
PushFD;
Cli;
while (LBts(&ctrl->flags,MPCCf_LOCKED))
Yield;
QueRem(tempm);
LBtr(&ctrl->flags,MPCCf_LOCKED);
PopFD;
Free(tempm->desc);
Free(tempm);
return result;
}
U0 MPCPUTaskInit()
{ //Called by multicore's seth task after $LK,"MPStart","MN:MPStart"$()
//as the first thing a CPU does before waiting for jobs
MPAPICInit;
Fs->rip=&MPSethServerTask;
Fs->time_slice_start=GetTimeStamp;
RestoreContext;
}
U0 MPCmdQueDel(CMPCmd *root)
{
CMPCmd *tempm=root->next,*tempm1;
while (tempm!=root) {
tempm1=tempm->next;
QueRem(tempm);
Free(tempm->desc);
Free(tempm);
tempm=tempm1;
}
}
U0 MPStart()
{ //Called by adam during start-up
//and can be called again to rst multicores.
//Doesn't always work when rstting. Kill all tasks, first.
//Must be called from core#0.
CTask *task;
U8 buf[128];
CMPMain *mp=MP_VECT_ADDR;
CCPU *c;
I64 i,my_mp_cnt;
CRAXRBCRCXRDX ee;
CPUId(0x1,&ee);
if (!Bt(&ee.rdx,9))
return;
PushFD;
Cli;
if (mp_cnt>1) {
my_mp_cnt=mp_cnt;
MPHalt; //sets mp_cnt to 1
for (i=1;i<my_mp_cnt;i++) {
c=&cpu_structs[i];
MPCmdQueDel(&c->cmd_ctrl.next_waiting);
MPCmdQueDel(&c->cmd_ctrl.next_done);
}
MPCmdQueDel(&mp_ctrl->next_waiting);
MPCmdQueDel(&mp_ctrl->next_done);
}
MemSet(&cpu_structs[1],0,sizeof(CCPU)*(MP_MAX_PROCESSORS-1));
//When you start-up other cores, they jump to an addr
//specified by a byte vect number, $LK,"MPN_VECT","MN:MPN_VECT"$ which corresponds
//to a location 4096*vect number, $LK,"MP_VECT_ADDR","MN:MP_VECT_ADDR"$$WW,0$.
MemCpy(mp,SYS_MP_INIT_START,SYS_MP_INIT_END-SYS_MP_INIT_START);
mp->sys_temp_ptr=GDT_SIZE-1+(&sys_gdttab)(U8 *)<<16;
mp_cnt_initial=mp_cnt=1;
mp_cnt_lock=0;
*LAPIC_LVT_ERR(U32 *)=*LAPIC_LVT_ERR(U32 *)&0xFFFFFF00+MPN_VECT;
asm {WBINVD}; //Not sure why this is needed. Might just need delay. $LK,"MemCpy","MN:MemCpy"$ above?
*LAPIC_ICR_LOW(U32 *)=0xC4500; //assert init IPI
BusyWait(10000);
*LAPIC_ICR_LOW(U32 *)=0xC4600+MPN_VECT; //start-up
BusyWait(200);
*LAPIC_ICR_LOW(U32 *)=0xC4600+MPN_VECT;
BusyWait(100000);
for (i=0;i<10000;i++)
LBts(&mp_cnt_lock,0); //Don't let more through
my_mp_cnt=mp_cnt_initial;
if (my_mp_cnt>MP_MAX_PROCESSORS)
my_mp_cnt=MP_MAX_PROCESSORS;
for (i=1;i<my_mp_cnt;i++) {
c =&cpu_structs[i];
//SPrintF not available yet.
StrCpy(buf,"Seth Task CPU#0");
buf[14]+=i;
task=Spawn(&MPCPUTaskInit,NULL,buf,NULL,SETH_STK,0);
task->rflags=SYS_START_RFLAGS;
//$LK,"CTask","MN:CTask"$ allocated off this core's seth_task's heap (Which is Adam)
task->task_in_que_signature=TASK_IN_QUE_SIGNATURE_VAL;
CPUStructInit(i,c);
c->tss=TSSNew(i);
c->seth_task=task;
asm {WBINVD}; //Not sure why this is needed. Might just need delay.
}
//Make sure they're all up-and-running
for (i=1;i<my_mp_cnt;i++) {
c =&cpu_structs[i];
while (!Bt(&c->cpu_flags,CPUf_SETH_SLEEP))
Pause;
}
PopFD;
mp_cnt=my_mp_cnt; //Finalize cnt
}
U0 MPInit()
{ //Called by adam during start-up
CRAXRBCRCXRDX ee;
CCPU *c;
CPUId(0x1,&ee);
mp_cnt_initial=mp_cnt=1;
mp_cnt_lock=0;
mp_ctrl=AMAlloc(sizeof(CMPCmdCtrl));
MPCmdCtrlInit(mp_ctrl);
mp_crash=ACAlloc(sizeof(CMPCrash));
//Must be in code heap because init code uses 32 bit addr of cpu_struct
c=cpu_structs=CAlloc(sizeof(CCPU)*MP_MAX_PROCESSORS,Fs->code_heap);
MemCpy(c,&sys_temp_cpu0_struct,sizeof(CCPU));
c->addr=cpu_structs;
SetGs(c);
adam_task->gs=c;
adam_task->time_slice_start=GetTimeStamp;
c->seth_task=adam_task;
c->tss=TSSNew(0);
c->idle_task=Spawn(0,NULL,"Idle Task",Fs,,0);
if (Bt(&ee.rdx,9)) {
//Unnecessary?
// SetMSR(IA32_LAPIC_BASE,LAPIC_BASE+0x900);
MPAPICInit;
}
}
U0 MPCrash()
{ //Entering the debugger from another core causes an interrupt on core#0
//Which calls this routine.
IntEOI;
mp_cnt=1;
Raw(ON);
sys_raw_dc_flags|=RDCF_SHOW_DOLLAR;
"MP Crash CPU#%02X Task:%08X\n",mp_crash->cpu_num,mp_crash->task;
Dbg(mp_crash->msg,mp_crash->msg_num);
}
+233
View File
@@ -0,0 +1,233 @@
//This is run in a #exe{}.
U8 *osmain_cfg_options="ProtectLow\0Deterministic\0MemInit\0HeapInit\0VarInit\0NoMP\0TextMode\0GrMode\0DontProbe\0Help\0";
#define CFG_PROTECT_LOW 0
#define CFG_DETERMINISTIC 1
#define CFG_MEM_INIT 2
#define CFG_HEAP_INIT 3
#define CFG_VAR_INIT 4
#define CFG_NO_MP 5
#define CFG_TEXT_MODE 6
#define CFG_GR_MODE 7
#define CFG_DONT_PROBE 8
#define CFG_NUM_OPTIONS 9
#define CFG_HELP 9
class COSMainCfg
{
I64 bios_gr_mode;
U8 dft_drv,*acct_name;
U8 *dsk_cache_size_exp;
CDoc *add_dev;
Bool opts[CFG_NUM_OPTIONS];
U8 mem_init_val,heap_init_val,var_init_val;
Bool cdrom_ports_pmt;
};
CDoc *OSMainCfgAddDev(COSMainCfg *c)
{
I64 num_hints,drv_let_base,type,drv_let,k,n,num=0;
U8 buf[256],buf2[128],buf3[128];
CATARep *root=NULL,*tempha;
CDoc *doc=DocNew;
PutDefine("ST_MOUNT_INTRO");
do {
PutDefine("ST_MOUNT_BASE_LET");
drv_let_base=ToUpper(GetChar)-'A';
NewLine;
if (0<=drv_let_base<NUM_PRTS) {
PutDefine("ST_MOUNT_DRV_TYPE");
type=GetChar-'0';
NewLine;
k=0;
if (type==BDT_RAM) {
PutDefine("ST_MOUNT_BLKS");
GetS(buf,256);
} else if (type==BDT_ATA ||
type==BDT_ATAPI) {
num_hints=ATARep(TRUE,&root);
if (type==BDT_ATAPI) {
PutDefine("ST_MOUNT_BOOTED_CDROM");
if (num_hints)
PutDefine("ST_MOUNT_BASE0_HINT");
else
PutDefine("ST_MOUNT_BASE0");
GetS(buf2,128);
} else
do {
if (num_hints)
PutDefine("ST_MOUNT_BASE0_HINT");
else
PutDefine("ST_MOUNT_BASE0");
GetS(buf2,128);
} while (!A2I(buf2));
if (1<=A2I(buf2)<=num_hints) {
tempha=ATARepFind(root,A2I(buf2));
SPrintF(buf2,"0x%X",tempha->base0);
SPrintF(buf3,"0x%X",tempha->base1);
k=tempha->unit;
} else if (type!=BDT_ATAPI || *buf2) {
if (type==BDT_ATAPI)
StrCpy(buf3,"0");
else
do {
PutDefine("ST_MOUNT_BASE1");
GetS(buf3,128);
} while (!A2I(buf3));
do {
PutDefine("ST_MOUNT_UNIT");
k=GetChar-'0';
} while (!(0<=k<=1));
NewLine;
}
LinkedListDel(root);
}
if (type==BDT_NON_NATIVE_FILE) {
PutDefine("ST_MOUNT_NON_NATIVE_LET");
drv_let=GetChar;
NewLine;
PutDefine("ST_MOUNT_NON_NATIVE_BLK");
GetS(buf2,128);
}
if (BDT_NULL<type<=BDT_NON_NATIVE_FILE &&
0<=k<=1) {
DocPrintF(doc,"bdev=&sys_blkdevs[num_blkdevs++];");
DocPrintF(doc,"bdev->drv_let_base=%d;",
drv_let_base+'A');
DocPrintF(doc,"bdev->unit=%d;",k);
DocPrintF(doc,"bdev->type=%d;",type);
if (type==BDT_ATAPI)
DocPrintF(doc,"bdev->flags=BDF_REMOVABLE;");
else
DocPrintF(doc,"bdev->flags=0;");
if (type!=BDT_RAM)
DocPrintF(doc,"bdev->flags|=BDF_READ_CACHE;");
if (type==BDT_ATAPI) {
DocPrintF(doc,"bdev->blk_size=CD_BLK_SIZE;");
DocPrintF(doc,"bdev->flags|=BDF_READ_ONLY;");
} else
DocPrintF(doc,"bdev->blk_size=BLK_SIZE;");
if (type==BDT_RAM)
DocPrintF(doc,"bdev->max_blk=(%s)-1;",buf);
else
DocPrintF(doc,"bdev->max_blk=0xEFFFFFFF;");
if (type==BDT_NON_NATIVE_FILE) {
DocPrintF(doc,"bdev->non_native_drv=%d;",drv_let);
n=A2I(buf2);
DocPrintF(doc,"bdev->non_native_offset=%d;",n);
} else
DocPutS(doc,"bdev->non_native_drv=0;"
"bdev->non_native_offset=0;");
if (type==BDT_ATA || type==BDT_ATAPI) {
if (type==BDT_ATAPI && !*buf2) {
c->cdrom_ports_pmt=TRUE;
DocPrintF(doc,"boot_drv_pmt=PmtBaseUnit(bdev);");
} else
DocPrintF(doc,"bdev->base0=%s;bdev->base1=%s;",
buf2,buf3);
}
DocPrintF(doc,"BlkDevAdd(bdev,FALSE);");
num++;
} else
PutDefine("ST_FAILED");
}
} while (!num || 0<=drv_let_base<NUM_PRTS);
//See $LK,"InsBootDstDrv","FF:::/SparrowOS/Adam/Boot/InsBoot.CPP.Z,InsBootDstDrv"$
if (!(k=NamedFramePtr("InsBootDstDrv")))
k=Fs->cur_prt->drv_let;
DocPrintF(doc,"dft_drv=\'%C\';",k);
c->dft_drv=k;
return doc;
}
U0 OSMainCfgOptions(COSMainCfg *c)
{
I64 i;
U8 *st=NULL;
Bool state;
do {
Free(st);
for (i=0;i<CFG_NUM_OPTIONS;i++)
"$$FG,PURPLE$$%13tz$$FG$$:%Z\n",i,osmain_cfg_options,c->opts[i],"ST_OFF_ON";
"\nType '$$FG,PURPLE$$Help$$FG$$' for help.\n";
st=PmtStr("Option ($$FG,PURPLE$$<ENTER>$$FG$$ when done):","");
i=ListEntryMatch(st,osmain_cfg_options,LEF_IGNORE_CASE);
if (i==CFG_HELP)
"\n"
"$$FG,PURPLE$$ProtectLow$$FG$$ Marks memory below 0x%0X as not present.\n"
"$$FG,PURPLE$$Deterministic$$FG$$ Tries to keep deterministic.\n"
"$$FG,PURPLE$$MemInit$$FG$$ Initializes memory above 0x100000 to a val at boot.\n"
"$$FG,PURPLE$$HeapInit$$FG$$ Initializes MAlloc() memory to a val.\n"
"$$FG,PURPLE$$VarInit$$FG$$ Initializes glbl var memory to a val.\n"
"$$FG,PURPLE$$NoMP$$FG$$ No multicore.\n"
"$$FG,PURPLE$$TextMode$$FG$$ Text Mode (requires hard reboot).\n"
"$$FG,PURPLE$$GrMode$$FG$$ Graphics Mode (requires hard reboot).\n"
"$$FG,PURPLE$$DontProbe$$FG$$ Just prompt CD-ROM ports, don't probe.\n"
"\n",PROTECTED_LOW_PAGE_LIMIT; //Should be stream val of prot_low_limit
else
if (0<=i<CFG_NUM_OPTIONS) {
state=c->opts[i]=!c->opts[i];
switch (i) {
case CFG_MEM_INIT:
if (state)
c->mem_init_val=PmtI64("Val (0-255):",255,0,255);
break;
case CFG_HEAP_INIT:
if (state)
c->heap_init_val=PmtI64("Val (0-255):",255,0,255);
break;
case CFG_VAR_INIT:
if (state)
c->var_init_val=PmtI64("Val (0-255):",255,0,255);
break;
case CFG_GR_MODE:
if (state)
c->bios_gr_mode=PmtI64(
"0x12 640x480x4\n"
"0x6A 800x600x4\n\n"
"BIOS Graphic Mode (0x%0X):",c->bios_gr_mode);
break;
}
}
} while (*st);
Free(st);
}
COSMainCfg *OSMainCfgNew()
{
COSMainCfg *c=CAlloc(sizeof(COSMainCfg));
c->add_dev=OSMainCfgAddDev(c);
c->acct_name=PmtStr("Start-up Acct ($$FG,PURPLE$$<ENTER>$$FG$$ will prompt):");
c->dsk_cache_size_exp=PmtStr("Disk Cache Size in Bytes, gets rounded-up funny, ($$FG,PURPLE$$<ENTER>$$FG$$ will use default of $$FG,PURPLE$$%s$$FG$$ Bytes):",
"Scale2Mem(0x80000,0x8000000)");
c->bios_gr_mode=0x12; //0x12=640x480x4 0x6A=800x600x4
OSMainCfgOptions(c);
if (c->opts[CFG_DETERMINISTIC])
StreamPutS("#define SYS_DETERMINISTIC");
return c;
}
U0 OSMainCfgDel(COSMainCfg *c)
{
DocDel(c->add_dev);
Free(c->acct_name);
Free(c->dsk_cache_size_exp);
Free(c);
}
+257
View File
@@ -0,0 +1,257 @@
U0 DateTimeFmtMapsRst()
{
I64 i;
for (i=0;i<NUM_DATE_FMTS;i++)
date_fmt_map[i]=i;
for (i=0;i<NUM_TIME_FMTS;i++)
time_fmt_map[i]=i;
}
U0 SysGlblsInit()
{
I64 i,j;
U8 *m;
CRAXRBCRCXRDX ee;
CPUId(0x1,&ee);
sys_cache_line_width=ee.rbx.u8[1]*8;
QueInit(&sys_pci_dev_root);
sys_rnd_seed = 93186752^GetTimeStamp;
sys_focus_task=Fs;
QueInit(&sys_macro_root);
sys_dft_iso_name="::/Temp/CDDVD.ISO";
MemSet(mp_apic_ids,0,MP_MAX_PROCESSORS*sizeof(U8));
InDbg(ON);
reverse_bits_table=CAlloc(256);
for (i=0;i<256;i++)
for (j=0;j<8;j++)
if (Bt(&i,7-j))
LBts(reverse_bits_table+i,j);
set_bits_table=CAlloc(256);
for (i=0;i<256;i++)
for (j=0;j<8;j++)
if (Bt(&i,j))
set_bits_table[i]++;
ext=CAlloc(EXT_TABLE_SIZE*sizeof(U8 *));
ext[EXT_DEBUGGER]=&SysDbgEnter;
ext[EXT_EXIT_DEBUGGER]=&SysDbgExit;
fp_mgets=&SysMGetS;
fp_ctrl_alt_let_cbs=CAlloc(26*sizeof(U8 *));
ctrl_alt_let_descs=CAlloc(26*sizeof(U8 *));;
ctrl_alt_let_in_irq_flags=0;
psect_cache=CAlloc(PSECT_CACHE_SIZE*sizeof(CPSectCache));
psect_cache_index=0;
StrCpy(sys_temp_filename,"HOME/Temp.TXT.Z");
MemSet(&sys_put_key_root,0,sizeof(CKeyDev));
QueInit(&sys_put_key_root);
KeyDevAdd(&AKDInputFilterPutKey,&AKDInputFilterPutS,0x40000000,FALSE);
KeyDevAdd(&AKDRawDisplayPutKey,&AKDRawDisplayPutS,0x60000000,FALSE);
#exe {
if (*osmain_cfg->acct_name)
StreamPrintF("sys_acct=StrNew(\"%C:/SparrowOS/Accts/%s\");",osmain_cfg->dft_drv,osmain_cfg->acct_name);
else
StreamPrintF("sys_acct=StrNew(\"%C:/SparrowOS/Accts\");",osmain_cfg->dft_drv);
StreamPutS("#exe{OptOff(OPTf_WARN_PAREN);}");
StreamPrintF("DskCacheInit(%s);",osmain_cfg->dsk_cache_size_exp);
StreamPutS("#exe{OptOn(OPTf_WARN_PAREN);}");
};
pow10_I64=CAlloc(sizeof(F64)*(308+308+1));
for (i=-308;i<309;i++)
pow10_I64[i+309]=Pow10(i);
//$AN,"Independent Heap Ctrl Example","Independent Heap Ctrl Example"$
i=1; //Rqst 1 blk, we might get more.
m=MemBlksUncachedAlloc(&i,sys_code_bp);
sys_uncached_heap=HeapCtrlIndependentInit(m,i*0x200000/0x200);
ProgressBarsRst;
date_fmt_map=MAlloc(NUM_DATE_FMTS);
time_fmt_map=MAlloc(NUM_TIME_FMTS);
DateTimeFmtMapsRst;
sys_fault_handlers_code=IntFaultHandlersNew;
}
U0 SysGrInit()
{
//See $LK,"SYS_BIOS_GR_MODE","FF:D:/SparrowOS/OSMain/OSStart.CPP.Z,SYS_BIOS_GR_MODE:2"$
//See $LK,"::/SparrowOS/Adam/Gr/GrCfg.CPP.Z","FI:::/SparrowOS/Adam/Gr/GrCfg.CPP.Z"$
gr_font=sys_font_8x8;
if (bios_gr_mode==0x12 || bios_gr_mode==0x6A) {
text_mode=FALSE;
/*
Mode must be multiple of 32 wide
$LK,"GrUpdateLine32","MN:GrUpdateLine32"$().
*/
if (bios_gr_mode==0x6A) {
gr_width =800;
gr_height=600;
} else {
gr_width =640;
gr_height=480;
}
text_cols=gr_width/FONT_WIDTH;
text_rows=gr_height/FONT_HEIGHT;
OutU8(VGA_SC_INDEX,VGA_MAP_MASK);
OutU8(VGA_SC_DATA,0x0F);
MemSet(VGA_GRAPHIC_MEM_BASE,0,gr_width*gr_height>>3);
sys_dc_screen_image=CAlloc(gr_width*gr_height/8);
} else {
text_mode=TRUE;
gr_width =640;
gr_height=480;
text_cols=80;
text_rows=25;
MemSet(VGA_TEXT_MEM_BASE,0,text_rows*text_cols<<1);
}
}
U0 TimersInit()
{
I64 i,*qq;
U32 *_d;
OutU8(0x43,0x34);
OutU8(0x40,SYS_TIMER0_PERIOD);
OutU8(0x40,SYS_TIMER0_PERIOD>>8);
// High Precision Event Timer
if (PCIReadU16(0,31,0,0)==0x8086) { //Intel?
//D31 F0, cfg 0xF0=RCBA of PCI-LPC Bridge
_d=PCIReadU32(0,31,0,0xF0)(U8 *)&~0x3FFF+0x3404; //HPET cfg
//7 enable
//1:0 HPET is at 0xFED00000,0xFED01000, 0xFED02000 or 0xFED03000.
*_d=*_d&3|0x80;
}
qq=HPET_GCAP_ID;
i=*qq; //i.u32[1]= period in femtoS (10e-15)
if (100000<i.u32[1]<1000000000) {
HPET_freq =1000000000000000/i.u32[1];
HPET_kHz_freq=1000000000000/i.u32[1];
qq=HPET_GEN_CONF;
*qq|=1; //Enable counting
} else {
HPET_freq=0;
HPET_kHz_freq=0;
}
}
U0 Reboot()
{
U16 *d=0x472;
Cli;
if (mp_cnt>1)
MPHalt;
MemPagePresentMark(d,TRUE);
*d=0;
OutU8(0x70,0x8F);
OutU8(0x71,0x00);
OutU8(0x70,0x00);
OutU8(0x92,InU8(0x92)|1);
SysHlt;
}
U0 OSMain()
{ //Continued from $LK,"OSMain","FF:::/SparrowOS/OSMain/OSStart.CPP.Z,I32 &OSMain"$
adam_task=Fs;
HeapsInit;
LBts(&sys_run_level,RLf_FULL_HEAP);
Fs->hash_table=HashTableNew(ADAM_HASH_SIZE,Fs);
#exe {StreamPrintF("SysDeterministic(%d);",osmain_cfg->opts[CFG_DETERMINISTIC]);};
SysGlblsInit;
Mem32DevInit;
MemPagesNotPresentMark;
LoadOSMain;
SysGrInit;
StrCpy(Fs->task_name,"Adam Task CPU#0");
StrCpy(Fs->task_title,Fs->task_name);
Fs->text_attr=WHITE<<4+PURPLE;
Fs->border_attr=WHITE<<4+LTPURPLE;
Fs->win_right=text_cols-2;
Fs->win_top++;
TaskDerivedValsUpdate;
LoadSysStrs;
MPInit;
IntInit1;
//Before this point use $LK,"Snd","MN:Snd"$() and $LK,"BusyWait","MN:BusyWait"$()
//to debug. After this point, use $LK,"DbgNum","MN:DbgNum"$()
LBts(&sys_run_level,RLf_RAW);
if (BIOSTotalMem<250*0x100000)
Dbg("Requires 256 Meg of RAM Memory");
TimersInit;
IntsInit;
"Enable IRQ's\n";
SetFlags(SYS_NORMAL_RFLAGS);
BusyWait(2000);
IntInit2;
LBts(&sys_run_level,RLf_INTERRUPTS);
TimeStampFreqCal;
if (!IsSysDeterministic)
Preempt(ON);
#exe {
if (!osmain_cfg->opts[CFG_NO_MP])
StreamPutS("\"MultiCore Start\\n\\n\";"
"MPStart;");
};
LBts(&sys_run_level,RLf_MP);
KbdMouseVarsInit;
IPVarsInit;
KbdInit;
if (IsSysDeterministic)
MouseDriverInstall;
else if (mp_cnt<2)
Spawn(&MouseDriverInstall);
else
MPSpawn(&MouseDriverInstall);
"BlkDevsInitAll\n";
BlkDevsInitAll;
"BlkDevsInitAll Done\n";
#exe {
if (osmain_cfg->cdrom_ports_pmt)
StreamPutS("if (boot_drv_pmt) PutDefine(\"ST_CDROM_PORTS_PMT\");");
};
DrvDftSelect;
LBts(&sys_run_level,RLf_DSK);
"Loading Compiler\n";
Cd("/SparrowOS/Compiler");
Load("Compiler",LDF_SILENT);
time_stamp_freq_initial=TimeStampFreqCal;
InDbg(OFF);
LBts(&sys_run_level,RLf_COMPILER);
Cd("/SparrowOS/OSMain");
try
ExeFile("Adam1.CPP.Z"); //Continues $LK,"/SparrowOS/OSMain/Adam1.CPP.Z","FL:/SparrowOS/OSMain/Adam1.CPP.Z,1"$
catch {
CatchAll;
Dbg;
}
LBts(&sys_run_level,RLf_ADAM_SERVER);
ServantTaskCont; //Never to return
}
asm { ALIGN 16,OC_NOP
SYS_OSMAIN_END::}
+104
View File
@@ -0,0 +1,104 @@
/*
If you are sure a fun won't be called
before import is resolved, you can use
"import". Otherwise, use a fun pointer
var and check it before calling.
*/
import U0 MemberListDel(CHashClass *tempc);
import I64 ExePutS(U8 *buf,U8 *filename=NULL,Bool just_load=FALSE);
import I64 ExeFile(U8 *name,Bool just_load=FALSE);
import U0 DisplaySpecialKeys(I64 sc);
import Bool DocUnlock(CDoc *doc);
import Bool EdJoin(U8 *link_st,I64 ed_flags);
import I64 PopUp(U8 *msg,CTask *parent=NULL,CTask **_pu_task=NULL);
extern U0 throw(...);
extern U8 *FileNameAbs(U8 *name);
extern U8 *DftExt(U8 *name,U8 *extension);
extern Bool Cd(U8 *name,Bool make_dirs=FALSE);
extern Bool MkDir(U8 *filename);
extern U0 Msg(I64 code,I64 p1,I64 p2,I64 flags=0);
extern Bool BlkDevLock(CBlkDev *bdev);
extern Bool BlkDevUnlock(CBlkDev *bdev,Bool rst=FALSE);
extern Bool RBlks(CPrt *p,U8 *buf, I64 blk, I64 cnt);
extern Bool WBlks(CPrt *p,U8 *buf, I64 blk, I64 cnt);
extern U0 DskCacheInvalidate(CPrt *p);
extern Bool Drv(U8 drv_let);
extern U0 BlkDevsRelease();
extern U0 PrtsRelease();
extern Bool IsRaw();
extern U0 D(U8 *buf,I64 cnt=0x80,Bool show_offset=TRUE);
extern U0 Dm(U8 *buf,I64 cnt=0x80);
extern U0 MPInt(I64 num,I64 cpu_num=1);
extern U0 XTalk(CTask *task,U8 *fmt,...);
extern Bool TaskValidate(CTask *task);
extern U8 *FileExtRem(U8 *src,U8 *dst=NULL);
extern Bool IsDir(U8 *dir_name);
extern Bool FileFind(U8 *filename,CDirEntry *rde=NULL,
Bool dir_only=FALSE,Bool file_only=FALSE,Bool scan_parents=FALSE);
extern Bool FilesFindMatch(U8 *files_find_mask,U8 *filename,I64 fuf_flags=0);
extern Bool ISOPrtInit(CPrt *p,I64 blk);
extern Bool ISO1FileFind(CPrt *p,I64 cur_dir_cluster,U8 *name,CDirEntry *_result,
Bool dir_only,Bool file_only);
extern CDirEntry *ISO1FilesFind(U8 *files_find_mask,I64 fuf_flags,CDirEntry *parent=NULL);
extern U0 NativeFSFreeFreeList(CPrt *p);
extern U0 NativeFSPrtInit(CPrt *p);
extern U0 FAT32PrtInit(CPrt *p);
extern Bool NativeFSDrvValidate(U8 drv_let);
extern U0 NativeFSFmt(U8 drv_let,Bool quick=TRUE);
extern Bool NativeFSFileFind(CPrt *p,I64 cur_dir_cluster,U8 *name,CDirEntry *_result,
Bool dir_only,Bool file_only);
extern Bool FAT32FileFind(CPrt *p,I64 cur_dir_cluster,U8 *name,CDirEntry *_result,
Bool dir_only,Bool file_only);
extern U8 *FileRead(U8 *filename,I64 *_size=NULL,I64 *_attr=NULL,Bool raw=FALSE);
extern I64 NativeFSAllocClusters(CPrt *p,I64 cnt);
extern I64 FAT32AllocClusters(CPrt *p,I64 c,I64 cnt);
extern I64 FAT32AllocContiguousClusters(CPrt *p,I64 cnt);
extern Bool NativeFSDirNew(CPrt *p,U8 *cur_dir,CDirEntry *de,Bool free_old_chain);
extern Bool FAT32DirNew(CPrt *p,U8 *cur_dir,CDirEntry *de,Bool free_old_chain);
extern CDirEntry *NativeFSFilesFind (U8 *files_find_mask,I64 fuf_flags,CDirEntry *parent=NULL);
extern CDirEntry *FAT32FilesFind(U8 *files_find_mask,I64 fuf_flags,CDirEntry *parent=NULL,I64 *_dir_size=NULL);
extern I64 FileWrite(U8 *filename,U8 *fbuf,
I64 size,CDate ltdt=0,I64 attr=0,Bool raw=FALSE);
extern U0 Exit();
extern U0 AdamLog(U8 *fmt,...);
extern U0 Dbg(U8 *msg=NULL,I64 num=0,Bool fault=FALSE);
extern U0 DbgHelp();
extern U8 *Caller(I64 num=1);
extern Bool BootCdProbeAll(CBlkDev *bdev);
extern CTask *SpawnUser(U8 *fmt=NULL,...);
extern U0 TaskRstAwaitingMsg(CTask *task=NULL);
extern CTaskCmd *QueMsg(CTask *_servant,CTask *master,
I64 code,I64 p1,I64 p2,I64 flags);
extern U0 TaskWait(CTask *task=NULL);
extern U0 TaskInitExt();
extern U0 TaskPause(CTask *task,Bool state);
extern I64 ServantCmdsHandler(CTask *task=NULL);
extern U0 PrintF(U8 *fmt,...);
extern U0 PutS(U8 *st);
extern U0 PutChar(I64 ch);
extern U0 PutDefine(U8 *name);
extern U0 NewLine(I64 cnt=1);
extern I64 GetChar(I64 *scancode=NULL,Bool echo=TRUE,Bool raw_cursor=FALSE);
extern Bool IsInDbg();
extern I64 FlushMsgs(CTask *task=NULL);
extern U0 SetMouseIP(I64 x,I64 y,I64 z,I64 l,I64 r,I64 c);
extern U8 *MSPrintF(U8 *fmt,...);
extern U8 *TextFileRead(U8 *filename,I64 *_attr=NULL);
extern U0 SPrintFPSect(U8 *buf,I64 add,I64 field_len);
extern I64 GetS(U8 *buf,I64 size,Bool allow_ext=TRUE);
extern U0 UserTaskCont();
#exe {
OptOn(OPTf_KEEP_PRIVATE);
OptOn(OPTf_EXTERNS_TO_IMPORTS);
};
#include "/SparrowOS/Compiler/Compiler.HPP.Z"
#exe {
OptOff(OPTf_EXTERNS_TO_IMPORTS);
OptOff(OPTf_KEEP_PRIVATE);
};
+132
View File
@@ -0,0 +1,132 @@
U8 sys_temp_filename[136];
CTaskCmd sys_macro_root;
CKeyDev sys_put_key_root;
CTask *sys_macro_util_task=NULL,
*sys_dbg_focus_task=NULL;
CMPCmdCtrl *mp_ctrl=NULL;
CMPCrash *mp_crash=NULL;
U8 mp_apic_ids[MP_MAX_PROCESSORS];
CTask *adam_task;
I64 sys_num_spawned_users=0;
U8 *sys_fault_handlers_code;
CCacheBlk *sys_dsk_cache_base=NULL,*sys_dsk_cache_ctrl=NULL;
CCacheBlk **sys_dsk_cache_hash_table=NULL;
I64 sys_dsk_cache_size;
I64 sys_raw_dc_col=0,sys_raw_dc_flags=0;
U8 *sys_dc_screen_image;
Bool text_mode;
I64 text_rows,text_cols,gr_width,gr_height;
U8 *gr_font;
CTask *sys_winmgr_task=NULL,
*sys_task_being_screen_updated=NULL;
I64 sys_rnd_seed;
CDoc *sys_clipboard_doc;
U8 *sys_dft_iso_name;
I64 sys_dsk_reads,sys_dsk_writes;
CBlkDev *sys_blkdevs;
CPrt *sys_prts,*dft_prt;
U8 dft_drv;
Bool boot_drv_pmt=FALSE;
I64 num_blkdevs;
CPrt *drv_to_prt[32];
U8 *sys_acct;
U8 *reverse_bits_table,*set_bits_table;
U0 (**fp_ctrl_alt_let_cbs)(I64 sc);
I64 ctrl_alt_let_in_irq_flags;
I64 **ctrl_alt_let_ret_addr; //addr of ret add on stack in kbd irq
U8 **ctrl_alt_let_descs;
CDate local_time_offset=0;
Bool time_stamp_freq_calibrated=FALSE;
I64 HPET_freq=0,HPET_kHz_freq=0,
time_stamp_freq=2676302000,
time_stamp_kHz_freq=2676302,
time_stamp_freq_initial=2676302000,
mouse_evt_time=0,kbd_evt_time=0,mouse_pkt_size=3;
I64 sys_cur_scan_code=0;
U8 key_desc[128];
Bool kbd_irqs_working;
U8 *key_handler;
I64 sys_num_installed_compilers=0;
CPCIDev sys_pci_dev_root;
CMemRange sys_mem32_dev_root;
U8 *sys_mem64_dev_ptr=MAPPED_MEM_SPACE;
F64 snd_freq=0;
I64 snd_dev=SD_PC_SPEAKER;
Bool snd_record=FALSE;
F64 snd_vol=0.1,snd_reverb_intensity=0.2,snd_reverb_delay=0.3;
F64 *pow10_I64;
CHeapCtrl *sys_uncached_heap;
I64 ipx,ipy,ipz,ip_throttle;
I64 ipx_presnap,ipy_presnap,ipz_presnap;
I64 ipx_offset,ipy_offset,ipz_offset;
F64 ipx_scale,ipy_scale,ipz_scale;
F64 ip_speed;
I64 ip_dev;
I64 iptx,ipty;
Bool ip_on, //Show or hide cursor
ip_lb_last,ip_cb_last,ip_rb_last,
ip_lb,ip_cb,ip_rb;
Bool ip_has_wheel;
F64 ip_last_move_time;
CSnap ip_snap_last;
F64 mxx_scale,myy_scale,mzz_scale;
//These are the coordinates before
//they get scaled.
I64 mxx_prescale,myy_prescale,mzz_prescale;
I64 mxx,myy,mzz;
F64 mouse_speed;
I64 old_mxx,old_myy,old_mzz;
Bool mouse_buttons[5];
Bool mouse_has_wheel,
mouse_has_ext_buttons,
mouse_evt,
mouse_installed,
mouse_install_attempt_in_progress,
kbdmouse_rst,
mouse_irqs_working;
CFifoI64 *scan_code_fifo;
CFifoU8 *kbd_fifo,*kbd2_fifo,
*mouse_fifo,*mouse2_fifo;
I64 sys_key_cnt,
sys_last_down_scan_code,
mouse_install_attempts,
mouse_last_evt_time;
//BitTest, $LK,"Bt","MN:Bt"$(), with a merged scan code.
//(Left and right shift merged, for example.)
U32 key_down_bitmap[8];
//BitTest, $LK,"Bt","MN:Bt"$(), with an unmerged scan code.
U32 key_down_bitmap2[8];
U0 (*fp_snd)(F64 freq,I64 waveform,F64 amp)=NULL;
U0 (*fp_snd_record)(F64 freq,I64 waveform,F64 amp)=NULL;
U0 (*fp_snd_fill_buf)(SND_OUT_CONTAINER *buf,I64 buf_num)=NULL;
U0 (*fp_snd_copy_buf)(SND_IN_CONTAINER *buf,I64 buf_num)=NULL;
U8 *(*fp_mgets)(I64 flags=0)=NULL;
U0 (*fp_prs_stream_blk)(CLex *lx)=NULL;
U0 (*fp_update_ctrls)(CTask *task)=NULL;
CDoc *(*fp_doc_cur)(CTask *task=NULL)=NULL;
U0 (*fp_set_std_palette)()=NULL;
I64 sys_dbg_fault_num=-1;
U8 *sys_dbg_fault_rip=0;
CPSectCache *psect_cache;
I64 psect_cache_index;
//These are for $LK,"SPrintF","MN:SPrintFJoin"$()
U8 *date_fmt_map,*time_fmt_map;
File diff suppressed because it is too large. Load diff
+69
View File
@@ -0,0 +1,69 @@
//You should compile this by calling
//$LK,"InstallBoot","MN:InstallBoot"$(), not doing it directly.
//See $LK,"Cmp(\"OSMain\")","FF:::/SparrowOS/Adam/Boot/InsBoot.CPP.Z,Cmp(\"OSMain\""$.
#exe {
OptOn(OPTf_WARN_PAREN);
OptOn(OPTf_WARN_DUP_TYPES);
#include "OSCfg"
COSMainCfg *osmain_cfg;
osmain_cfg=OSMainCfgNew;
};
#include "BootDefs.HPP.Z"
#include "Adam1a.HPP.Z"
#include "OSStart"
#include "Utils1a"
#include "Math1a"
#include "/SparrowOS/Compiler/CmpDefs.HPP.Z"
#include "Adam1b.HPP.Z"
#include "OSExts"
#include "OSGlbls"
#include "Math1b"
#include "Scheduler"
#include "Font8x8"
#include "Memory"
#include "Interrupts"
#include "FIFO"
#include "Compress"
#include "Hash1a"
#include "Date"
#include "Str1a"
#include "Define1a"
#include "Display"
#include "Misc1a"
#include "Dbg1a"
#include "Except"
#include "KbdMouse/InputPointer"
#include "KbdMouse/Keyboard"
#include "KbdMouse/Mouse"
#include "KbdMouse/Message"
#include "QSort"
#include "Task1a"
#include "TaskCmd"
#exe {Cd("Dsk");};
#include "DskStr"
#include "DskCache"
#include "ATADef.HPP.Z"
#include "DskATA"
#include "Dsk1a"
#include "DskAddDev"
#include "DskDir"
#include "FileSysISO1"
#include "FileSysNative"
#include "FileSysFAT"
#include "Dsk1b"
#include "DskCFile"
#include "Dsk1c"
#exe {Cd("..");};
#include "MultiProc"
#include "BIOS32"
#include "EdLite"
#include "PSect"
#include "OSEnd"
#exe {OSMainCfgDel(osmain_cfg);};
+535
View File
@@ -0,0 +1,535 @@
asm {
/*
See $LK,"::/SparrowOS/Doc/Boot.TXT.Z","FI:::/SparrowOS/Doc/Boot.TXT.Z"$ for how booting works.
This file calls some BIOS routines before
switching to 32 bit, and then, 64 bit modes.
It continues here: $LK,"OSMain","FF:::/SparrowOS/OSMain/OSEnd.CPP.Z,U0 OSMain"$.
The boot loader jumps here, in real-mode (16-bit).
It actually jumps to the $LK,"CBinFile","MN:CBinFile"$ which is placed
just before this $LK,"generated by the compiler","FF:::/SparrowOS/Compiler/CmpMain.CPP.Z,NATIVE_XSUM"$.
The header begins with a short jmp to
the start of this file's code which begins
with the following small jump past some data.
This file is first in the OSMain image
because it is #included first. $LK,"OSMain.PRJ.Z","FF:::/SparrowOS/OSMain/OSMain.PRJ.Z,OSStart:1"$
*/
USE16
SYS_SPARROWOS_START1::
//This must match $LK,"COSMain","MN:COSMain"$.
JMP U16 SYS_SPARROWOS_START2
// ************************************
// ASM Global vars required for 16-bit start-up
ALIGN 4,OC_NOP
SYS_BOOT_BASE:: DU32 0; //Fixed offset from start used by reboot
SYS_BOOT_PATCH_TABLE_BASE:: DU32 0;
#exe {StreamPrintF("SYS_COMPILE_TIME:: DU64 0x%X;",GetCurTimeCDate);}
//See $LK,"BootCdProbe","MN:BootCdProbe"$
#assert SYS_COMPILE_TIME+8+16<CD_BLK_SIZE
SYS_OS_32START:: DU32 SYS_INIT_OS;
SYS_BOOT_CODE:: DU32 0xFF;
SYS_MEM_E801:: DU16 0,0;
SYS_MEM_E820:: DU8 NUM_MEM_E820_ENTRIES*MEM_E820_ENTRY_SIZE DUP (0);
ALIGN 16,OC_NOP
SYS_GDTTAB:: //See $LK,"SELECTORS","FF:::/SparrowOS/OSMain/Adam1a.HPP.Z,GDT_NULL_SEL"$
GDT_NULL: DU64 0,0;
GDT_BOOT_DS: DU64 0,0; //Gets filled-in
GDT_BOOT_CS: DU64 0,0; //Gets filled-in
GDT_CS: DU64 0x00CF9A000000FFFF,0;
GDT_CS64: DU64 0x00209A0000000000,0; //The $LK,"Constitution","FI:::/SparrowOS/Doc/Constitution.TXT.Z"$ says just ring0.
GDT_CS64_RING3: DU64 0x0020FA0000000000,0; //$LK,"Ring3","FI:::/SparrowOS/Demo/Lectures/Ring3.CPP.Z"$, in case you want to play around.
GDT_ZERO_DS: DU64 0x00CF92000000FFFF,0;
GDT_ZERO_DS_RING3: DU64 0x00CFF2000000FFFF,0;
GDT_CPU_TRS: DU8 MP_MAX_PROCESSORS*16 DUP(0); //Gets filled-in, $LK,"TSSNew","MN:TSSNew"$.
GDT_CPU_TRS_RING3: DU8 MP_MAX_PROCESSORS*16 DUP(0);;
#assert $$-SYS_GDTTAB==GDT_SIZE
SYS_BIOS_GR_MODE:: DU16 0;
SYS_PCI_BUSSES:: DU16 0;
#assert $$-SYS_SPARROWOS_START1==sizeof(COSMain)-sizeof(CBinFile)
ALIGN 8,OC_NOP
SYS_ADAM_TASK:: DU8 sizeof(CTask) DUP(0);
SYS_ADAM_HC:: DU8 sizeof(CHeapCtrl) DUP(0);
SYS_TEMP_PTR:: DU32 0,0,0;
SYS_RUN_LEVEL:: DU32 0;
// ************************************
//EBX is SYS_BOOT_CODE (val passed from boot blk)
SYS_SPARROWOS_START2::
MOV AX,(BOOT_RAM_LIMIT-BOOT_STK_SIZE)/16
MOV SS,AX
MOV SP,BOOT_STK_SIZE
PUSH EBX //will be SYS_BOOT_CODE
MOV AX,VGA_TEXT_MEM_BASE/16
MOV ES,AX
MOV U32 ES:[0],'L'+0x1000+('T'+0x2000)<<16
MOV U32 ES:[4],0
// MOV ECX,1000000
// CALL SYS_BUSY_WAIT
CALL U16 GET_IP
GET_IP:
POP BX
SUB BX,GET_IP
SHR BX,4
MOV AX,CS
ADD AX,BX
PUSH AX
PUSH U16 SYS_SPARROWOS_START3
RETF
SYS_SPARROWOS_START3::
//XSUM OSMain
MOV AX,CS
DEC AX
#assert sizeof(CBinFile)==16
MOV DS,AX
XOR ESI,ESI
MOV ECX,U32 CBinFile.file_size[ESI]
SHR ECX,4
MOV EBX,NATIVE_XSUM
@@05: LODSD
XOR EBX,EAX
LODSD
XOR EBX,EAX
LODSD
XOR EBX,EAX
LODSD
XOR EBX,EAX
XOR ESI,ESI
MOV AX,DS
INC AX
MOV DS,AX
LOOP @@05
//If you debug, use text video mem
MOV U32 ES:[4],'O'+65536*'K'+0xF000F000
// MOV ECX,1000000
// CALL SYS_BUSY_WAIT
OR EBX,EBX
JZ SPARROWOS_CONT_START
//XSUM Error
MOV U32 ES:[4],'X'+65536*'M'+0xF000F000
// MOV ECX,1000000
// CALL SYS_BUSY_WAIT
@@10: JMP @@10
SYS_BUSY_WAIT::
@@05: IN AL,0x21
DEC ECX
JNZ @@05
RET
// ************************************
SPARROWOS_CONT_START:
STI
MOV AX,CS
MOV DS,AX
MOV U32 [SYS_RUN_LEVEL],RLF_16BIT
#exe {StreamPrintF("MOV BX,%d\n",osmain_cfg->bios_gr_mode);};
MOV U16 [SYS_BIOS_GR_MODE],BX
MOV AX,0x4F02
#exe {
if (!osmain_cfg->opts[CFG_TEXT_MODE])
StreamPutS("INT 0x10"); //Enable VGA
};
CMP AX,0x004F
JE @@10
MOV U16 [SYS_BIOS_GR_MODE],0 //failed
@@10:
/**** This doesn't help
//Enable mouse
MOV AX,0xC200 //Enable
MOV BX,0x0100
INT 0x15
MOV AX,0xC201 //Rst
INT 0x15
MOV AX,0xC200 //Enable
MOV BX,0x0100
INT 0x15
MOV AX,0xC202 //Sample
MOV BX,0x0500 //100
INT 0x15
MOV AX,0xC203 //Resolution
MOV BX,0x0300 //8 per mm
INT 0x15
MOV AX,0xC205 //pkt size
MOV BX,0x0300
INT 0x15
MOV AX,0xC200 //Enable
MOV BX,0x0100
INT 0x15
****/
//Get mem maps
MOV AX,0xE801
INT 0x15
MOV U16 [SYS_MEM_E801],CX
MOV U16 [SYS_MEM_E801+2],DX
MOV CX,NUM_MEM_E820_ENTRIES-1 //Leave one to terminate
XOR EBX,EBX
MOV AX,DS
MOV ES,AX
MOV DI,SYS_MEM_E820
@@15: PUSH CX
MOV EAX,0xE820
MOV ECX,MEM_E820_ENTRY_SIZE
MOV EDX,'PAMS'
INT 0x15
JC @@20
CMP EAX,'PAMS'
JNE @@20
OR EBX,EBX
JZ @@20
ADD DI,MEM_E820_ENTRY_SIZE
POP CX
LOOP @@15
JMP @@25
@@20: ADD SP,2
//Get PCI Bus Info
@@25: MOV U16 [SYS_PCI_BUSSES],256
XOR DX,DX
MOV AX,0xB101
INT 0x1A
CMP DX,'PC'
JNE @@30
MOV CH,0
INC CX
MOV U16 [SYS_PCI_BUSSES],CX
@@30:
CLI
//Enable A20
IN AL,0x92
OR AL,2
OUT 0x92,AL
CLD //Start with known registers
MOV AX,CS
MOV DS,AX
MOV ES,AX
MOV FS,AX
MOV GS,AX
XOR EAX,EAX
XOR EBX,EBX
XOR ECX,ECX
XOR EDX,EDX
XOR ESI,ESI
XOR EDI,EDI
XOR EBP,EBP
XOR EAX,EAX
MOV AX,CS
SHL EAX,4
MOV U32 [SYS_BOOT_BASE],EAX
POP U32 [SYS_BOOT_CODE]
MOV BX,CS
DEC BX
#assert sizeof(CBinFile)==16
MOV GS,BX
MOV EBX,U32 GS:[CBinFile.loader_patch_table_offset]
ADD EAX,EBX
SUB EAX,16
MOV U32 [SYS_BOOT_PATCH_TABLE_BASE],EAX
MOV U32 [GDT_BOOT_DS],0x0000FFFF
MOV U32 [GDT_BOOT_DS+4],0x0CF9200
MOV U32 [GDT_BOOT_CS],0x0000FFFF
MOV U32 [GDT_BOOT_CS+4],0x0CF9A00
MOV EAX,U32 [SYS_BOOT_BASE]
ADD U32 [GDT_BOOT_DS+2],EAX
ADD U32 [GDT_BOOT_CS+2],EAX
// Set-up ptr to limit and base
//of GDT.
MOV U16 [SYS_TEMP_PTR],GDT_SIZE-1
MOV EAX,U32 [SYS_BOOT_BASE]
ADD EAX,SYS_GDTTAB
MOV U32 [SYS_TEMP_PTR+2],EAX
MOV U16 [SYS_TEMP_PTR+6],0
LGDT U32 [SYS_TEMP_PTR]
MOV EAX,SYS_START_CR0
MOV_CR0_EAX
/*
The assembler doesn't support far jumps so we hand code it.
16-bit code is not important enough for me to implement
16-bit mode in the assembler fully.
To complete the switch to 32-bit mode, we have to load
the code segment with a far jump.
*/
DU8 0x66,0xEA; //JMP GDT_CS_SEL:SYS_INIT_OS
DU32 SYS_INIT_OS;
DU16 GDT_BOOT_CS_SEL;
#assert $$+16<=0xFFFF
USE32
// ************************************
// ASM Global vars not required for 16-bit start-up
ALIGN 8,OC_NOP
SYS_HEAP_BASE:: DU64 0x100000+0x1000*(NUM_PML1+NUM_PML2+NUM_PML3+NUM_PML4);
SYS_HEAP_LIMIT:: DU64 0;
#exe {
StreamPrintF(
"SYS_MEM_INIT_FLAG:: DU8 %d;"
"SYS_MEM_INIT_VAL:: DU8 %d;"
"SYS_HEAP_INIT_FLAG:: DU8 %d;"
"SYS_HEAP_INIT_VAL:: DU8 %d;"
"SYS_VAR_INIT_FLAG:: DU8 %d;"
"SYS_VAR_INIT_VAL:: DU8 %d;",
osmain_cfg->opts[CFG_MEM_INIT], osmain_cfg->mem_init_val,
osmain_cfg->opts[CFG_HEAP_INIT],osmain_cfg->heap_init_val,
osmain_cfg->opts[CFG_VAR_INIT], osmain_cfg->var_init_val);
};
SYS_HEAP_DBG_FLAG:: DU8 _CFG_HEAP_DBG;
ALIGN 8,0
SYS_CTRL_ALT_FLAGS:: DU64 0;
SYS_EXTERN_TABLE:: DU64 0;
SYS_BP_START::
SYS_BP_LOCKED_FLAGS:: DU64 0;
SYS_BP_SIZE:: DU64 0;
SYS_BP_ALLOCATED_U8S:: DU64 0;
SYS_BP_MEM_FREE_LIST:: DU64 0;
SYS_BP_MEM_FREE_2MEG_LIST:: DU64 0;
SYS_BP_FREE_PAGE_HASH:: DU64 FREE_PAGE_HASH_SIZE DUP(0);
SYS_BP_FREE_PAGE_HASH2:: DU64 64-PAGE_BITS DUP(0);
#assert sizeof(CBlkPool)==$$-SYS_BP_START
SYS_CODE_BP:: DU64 0;
SYS_DATA_BP:: DU64 0;
SYS_PROGRESSES::
SYS_PROGRESS1:: DU64 0;
SYS_PROGRESS1_MAX:: DU64 0;
SYS_PROGRESS1_DESC:: DU8 PROGRESS_DESC_LEN+1 DUP(0);
SYS_PROGRESS2:: DU64 0;
SYS_PROGRESS2_MAX:: DU64 0;
SYS_PROGRESS2_DESC:: DU8 PROGRESS_DESC_LEN+1 DUP(0);
SYS_PROGRESS3:: DU64 0;
SYS_PROGRESS3_MAX:: DU64 0;
SYS_PROGRESS3_DESC:: DU8 PROGRESS_DESC_LEN+1 DUP(0);
SYS_PROGRESS4:: DU64 0;
SYS_PROGRESS4_MAX:: DU64 0;
SYS_PROGRESS4_DESC:: DU8 PROGRESS_DESC_LEN+1 DUP(0);
#assert $$-SYS_PROGRESSES==sizeof(CProgress)*4
SYS_FOCUS_TASK:: DU64 0;
SYS_TIMER:: DU64 0;
SYS_JIFFIES:: DU64 1;
SYS_CPU_STRUCTS:: DU64 0;
SYS_MP_CNT:: DU64 1;
SYS_MP_CNT_INITIAL:: DU64 1;
SYS_MP_CNT_LOCK:: DU64 1;
SYS_TEMP_CPU0_STRUCT:: DU8 sizeof(CCPU) DUP (0);
ALIGN DFT_CACHE_LINE_WIDTH,OC_NOP
SYS_CACHE_LINE_WIDTH:: DU64 DFT_CACHE_LINE_WIDTH;
DU8 DFT_CACHE_LINE_WIDTH-sizeof(CBinFile)-8 DUP(0);
SYS_SEMAS:: DU8 NUM_SYS_SEMAS*SEMA_STRUCT_SIZE DUP(0);
ALIGN 16,OC_NOP
SYS_INIT_FPU_MMX:: DU8 sizeof(CFPU) DUP(0);
// ************************************
ALIGN 16,OC_NOP
SYS_INIT_OS:: //Entry point for RAM reboots.
PUSH U32 SYS_START_RFLAGS
POPFD
MOV EAX,SYS_START_CR0
MOV_CR0_EAX
MOV AX,GDT_BOOT_DS_SEL //LOAD DS SELECTOR
MOV DS,AX
MOV ES,AX
MOV EAX,U32 [SYS_RUN_LEVEL]
AND EAX,RLF_16BIT
OR EAX,RLF_32BIT
MOV U32 [SYS_RUN_LEVEL],EAX
//Patch abs addresses
MOV ESI,U32 [SYS_BOOT_PATCH_TABLE_BASE]
MOV EDI,U32 [SYS_BOOT_BASE]
MOV AX,GDT_ZERO_DS_SEL
MOV DS,AX
MOV ES,AX
/* See $LK,"Loader Patch Table Generation","FF:::/SparrowOS/Compiler/CmpMain.CPP.Z,EIE_MODULE_ALIGNMENT"$
U8 EIE_MODULE_ALIGNMENT
U32 module alignment val
U8 0
U8 EIE_ABS_ADDR
U32 cnt of abs addr patch offsets
U8 0
U32 first abs addr offset
U32 second abs addr offset
...
*/
MOV ECX,U32 1+1+4+1[ESI] //Get count
LEA ESI,U32 1+4+1+1+4+1[ESI] //addr of first abs addr patch offset
@@05: LODSD
ADD EAX,EDI
ADD U32 [EAX],EDI
LOOP @@05
MOV AX,GDT_ZERO_DS_SEL
MOV DS,AX
MOV ES,AX
MOV FS,AX
MOV GS,AX
MOV SS,AX
MOV ESP,BOOT_RAM_LIMIT //Temp Stk
DU8 0xEA; //JMP GDT_CS_SEL:SYS_CONT_INIT_OS
DU32 SYS_CONT_INIT_OS;
DU16 GDT_CS_SEL;
SYS_CONT_INIT_OS::
LOCK
BTS U32 [SYS_RUN_LEVEL],RLf_PATCHED
CALL SYS_FIND_BIOS32_SERVICE_DIR
CALL SYS_FIND_PCI_SERVICES
MOV U32 [SYS_HEAP_BASE],0x100000+0x1000*(NUM_PML1+NUM_PML2+NUM_PML3+NUM_PML4)
CALL SYS_INIT_MEM
PUSH U32 0
CALL INIT_EM64T
USE64
LOCK
BTS U32 [SYS_RUN_LEVEL],RLf_64BIT
FNINIT
FXSAVE U64 [SYS_INIT_FPU_MMX]
//Init CPU0 Struct
PUSH U32 SYS_TEMP_CPU0_STRUCT
PUSH 0
CALL &CPUStructInit
PUSH RAX
CALL _SET_GS_BASE
//Init Adam Task
MOV EDI,U32 SYS_ADAM_TASK
MOV RCX,sizeof(CTask)
XOR RAX,RAX
REP_STOSB
//Init Adam heap ctrl
MOV EDI,U32 SYS_ADAM_HC
MOV RCX,sizeof(CHeapCtrl)
XOR RAX,RAX
REP_STOSB
MOV EDI,U32 SYS_ADAM_HC
MOV EAX,U32 SYS_BP_START
MOV U64 CHeapCtrl.bp[RDI],RAX
MOV U32 CHeapCtrl.hc_signature[RDI],HEAP_CTRL_SIGNATURE_VAL
LEA RAX,U64 CHeapCtrl.next_um-CMemUsedAllocated.next[RDI]
MOV U64 CHeapCtrl.next_um[RDI],RAX
MOV U64 CHeapCtrl.last_um[RDI],RAX
MOV EAX,U32 SYS_ADAM_TASK
MOV U64 CHeapCtrl.mem_task[RDI],RAX
MOV U64 CTask.code_heap[RAX],RDI
MOV U64 CTask.data_heap[RAX],RDI
MOV U32 CTask.task_signature[RAX],TASK_SIGNATURE_VAL
MOV U32 CTask.task_in_que_signature[RAX],TASK_IN_QUE_SIGNATURE_VAL
LOCK
BTS U32 [SYS_RUN_LEVEL],RLf_BOOT_HEAP
PUSH ADAM_STK
PUSH U32 SYS_ADAM_TASK
CALL &TaskInit
CALL SET_FS_BASE
MOV RSP,U64 CTask.rsp[RAX]
JMP I32 &OSMain
// ************************************
USE32
INIT_EM64T:
MOV_EAX_CR4
OR EAX,0xB0
MOV_CR4_EAX
MOV EAX,PAGE_TABLE_BASE+0x1000*(NUM_PML1+NUM_PML2+NUM_PML3)
MOV_CR3_EAX
MOV ECX,IA32_EFER
XOR EDX,EDX
MOV EAX,IA32F_LME
WRMSR
MOV_EAX_CR0
BTS EAX,31 //enable paging (required for 64-bit mode)
MOV_CR0_EAX
DU8 0xEA; //JMP GDT_CS64_SEL:EM64T_PART3
DU32 EM64T_PART3;
DU16 GDT_CS64_SEL;
USE64
EM64T_PART3:
RET
// ************************************
SYS_RESTART_OSMAIN::
XOR RDI,RDI
MOV EDI,U32 SYS_BOOT_BASE
MOV EDI,U32 [RDI]
XOR RSI,RSI
MOV ESI,U32 SYS_OS_32START
MOV ESI,U32 [RSI]
ADD ESI,EDI
PUSH U32 GDT_ZERO_DS_SEL //stk seg
PUSH U32 BOOT_RAM_LIMIT //stk
PUSH U32 0 //flags
PUSH U32 GDT_CS_SEL
LEA RAX,[@@10]
PUSH RAX
IRET
USE32
@@10:
WBINVD
//disable paging
MOV_EAX_CR0
BTR EAX,31
MOV_CR0_EAX
MOV ECX,IA32_EFER
XOR EDX,EDX
XOR EAX,EAX
WRMSR
MOV EBX,BOOT_CODE_RAM
JMP ESI
USE64
SYS_RESTART_OSMAIN_END::
}
+256
View File
@@ -0,0 +1,256 @@
I64 HasLower(U8 *src)
{
U8 ch;
while (ch=*src++)
if ('a'<=ch<='z')
return TRUE;
return FALSE;
}
CHash *PSectFind(U8 *add,I64 *_offset)
{ //See $LK,"::/SparrowOS/OSMain/Hash1a.CPP.Z","FL:::/SparrowOS/OSMain/Hash1a.CPP.Z,1"$
CHash *result=NULL;
CHashExport *tempess;
CHashTable *h=Fs->hash_table;
Bool has_lower=FALSE;
U64 best=0x8000,j;
if (!ChkPtr(add)) {
*_offset=best;
return NULL;
}
while (h) {
tempess=h->next_added;
while (tempess!=h) {
if (tempess->type&HTT_FUN)
j=tempess(CHashFun *)->executable_addr;
else if (tempess->type&HTT_EXPORT_SYS_SYM)
j=tempess->val;
else
j=0;
j=add(I64)-j;
if (tempess->type&HTT_EXPORT_SYS_SYM) {
if (j<best || j==best && !has_lower) {
has_lower=HasLower(tempess->str);
best=j;
result=tempess;
}
} else if (tempess->type&HTT_FUN) {
if (j<best || j==best &&
(result && result->type&HTT_EXPORT_SYS_SYM||!has_lower)) {
has_lower=HasLower(tempess->str);
best=j;
result=tempess;
}
}
tempess=tempess->next_added;
}
h=h->next;
}
*_offset=best;
return result;
}
U0 PSectCacheAdd(CHash *temps,U8 *add)
{
I64 i;
CDbgInfo *dbg;
Bool old_preempt;
CPSectCache *temppc;
if (temps && temps->type&HTT_FUN &&
(dbg=temps(CHashFun *)->debug)) {
old_preempt=Preempt(OFF);
lock {i=psect_cache_index++;}
temppc=&psect_cache[i&(PSECT_CACHE_SIZE-1)];
temppc->base=dbg->body[0];
if (add<temppc->base)
temppc->base=add;
temppc->limit=dbg->body[dbg->max_line-dbg->min_line];
if (add>=temppc->limit)
temppc->limit=add(I64)+1;
i=MinI64(StrLen(temps->str),PSECT_CACHE_STR_LEN-1);
MemCpy(temppc->str,temps->str,i);
temppc->str[i]=0;
temppc->time_stamp=tS;
Preempt(old_preempt);
}
}
U8 *PSectCacheFind(U8 *add,I64 *_offset)
{
I64 i;
F64 timeout;
CPSectCache *temppc=psect_cache;
if (&sys_idle_start<=add<&sys_idle_end) {
*_offset=add-&sys_idle_start;
return "SYS_IDLE_START";
} else {
timeout=tS+8.0;
for (i=0;i<PSECT_CACHE_SIZE;i++,temppc++)
if (temppc->base<=add<temppc->limit &&
temppc->time_stamp>timeout) {
*_offset=add-temppc->base;
return temppc->str;
}
return NULL;
}
}
U0 SPrintFPSect(U8 *buf,I64 add,I64 field_len)
{
I64 offset;
CHashExport *tempess;
U8 *str,*str2;
Bool is_fun=FALSE;
if (add) {
if (str=PSectCacheFind(add,&offset)) {
if (!(&sys_idle_start<=add<&sys_idle_end))
is_fun=TRUE;
} else {
if (tempess=PSectFind(add,&offset)) {
if (tempess->type&HTT_FUN)
is_fun=TRUE;
PSectCacheAdd(tempess,add);
str=tempess->str;
}
}
if (str) {
if (offset<=0xFFFF) {
if (is_fun) {
str2=MSPrintF("&%s",str);
if (field_len>7)
SPrintF(buf,"%*ts+0x%04X",field_len-7,str2,offset);
else
SPrintF(buf,"%s+0x%04X",str2,offset);
Free(str2);
} else {
if (field_len>7)
SPrintF(buf,"%*ts+0x%04X",field_len-7,str,offset);
else
SPrintF(buf,"%s+0x%04X",str,offset);
}
}
return;
}
}
if (field_len)
SPrintF(buf,"%*tX",field_len,add);
else
SPrintF(buf,"%X",add);
}
I64 SrcLineNum(U8 *add,I64 cnt=1)
{
CHashSrcSym *temph;
I64 i,ii,j,offset,best=-1,d,best_d;
CDbgInfo *dbg;
U8 **body,*src,*src2;
if (temph=PSectFind(add,&offset)) {
if (temph->type&(HTT_FUN|HTT_EXPORT_SYS_SYM)) {
if (dbg=temph->debug) {
j=dbg->max_line-dbg->min_line+1;
body=dbg->body;
best_d=MAX_I64;
for (i=0;i<j;i++) {
if (0<body[i]<=add<body[i]+cnt) {
ii=i+1;
while (!body[ii])
ii++;
if (add<body[ii]) {
d=add(I64)-body[i];
if (d<best_d) {
best_d=d;
best=i+dbg->min_line;
}
}
}
}
} else if (temph->src_link && !offset) {
src =StrNew(temph->src_link);
src2=StrNew(temph->src_link);
StrLastRem(src,",",src2);
best=A2I(src2);
Free(src);
Free(src2);
}
}
}
return best;
}
U8 *SrcFileName(U8 *add,I64 cnt=1,CTask *mem_task=NULL)
{
CHashSrcSym *temph;
I64 i,j,ii,offset,best=NULL,d,best_d;
CDbgInfo *dbg;
U8 **body,*src;
if (temph=PSectFind(add,&offset)) {
if (temph->type&(HTT_FUN|HTT_EXPORT_SYS_SYM)) {
if (dbg=temph->debug) {
j=dbg->max_line-dbg->min_line+1;
body=dbg->body;
best_d=MAX_I64;
for (i=0;i<j;i++) {
if (0<body[i]<=add<body[i]+cnt) {
ii=i+1;
while (!body[ii])
ii++;
if (add<body[ii]) {
d=add(I64)-body[i];
if (d<best_d) {
best_d=d;
best=temph->src_link;
}
}
}
}
} else
best=temph->src_link;
}
}
if (best) {
src=StrNew(best,mem_task);
StrFirstRem(src,":");
StrLastRem(src,",");
return src;
} else
return NULL;
}
U8 *SrcEdLink(U8 *add,I64 cnt=1,CTask *mem_task=NULL)
{
U8 *filename,buf[512];
I64 linenum=SrcLineNum(add,cnt);
if (linenum>=0) {
if (filename=SrcFileName(add,cnt)) {
SPrintF(buf,"FL:%s,%d",filename,linenum);
return StrNew(buf,mem_task);
}
}
return NULL;
}
Bool PutSrcLink(U8 *add,I64 cnt=1,U8 *buf=NULL)
{
U8 *src;
if (src=SrcEdLink(add,cnt)) {
if (buf)
SPrintF(buf,"$$LK,\"%P\",\"%s\"$$",add,src);
else
"$$LK,\"%P\",\"%s\"$$",add,src;
Free(src);
return TRUE;
} else if (buf)
*buf=0;
return FALSE;
}
U0 EdAddSrc(U8 *add,I64 cnt=1,I64 ed_flags=0)
{
U8 *src;
if (src=SrcEdLink(add,cnt)) {
EdJoin(src,ed_flags);
Free(src);
}
}
+247
View File
@@ -0,0 +1,247 @@
U0 QSortI64(I64 *base,I64 num, I64 (*fp_compare)(I64 e1,I64 e2))
{/*
For assending strings: Compare can return StrCmp(e1,e2);
For assending ints : Compare can return e1-e2;
Don't use e1-e2 if numbers can overflow, return -1,0 or 1 with if's.
Maybe, look at $LK,"::/SparrowOS/Demo/MultiCore/Sort.CPP.Z","FI:::/SparrowOS/Demo/MultiCore/Sort.CPP.Z"$ or
$LK,"::/SparrowOS/Demo/MultiCore/RadixSort.CPP.Z","FI:::/SparrowOS/Demo/MultiCore/RadixSort.CPP.Z"$.
*/
I64 i,*less,*greater,pivot;
if (num>1) {
do {
less=base;
greater=base+num;
pivot=base[num/2];
while (less<greater) {
if ((*fp_compare)(*less,pivot)<=0)
less++;
else {
greater--;
SwapU64(less,greater);
}
}
i=less-base;
if (i==num) { //All less or equal to pivot
//Point greater to first less
do greater--;
while (--i && !(*fp_compare)(*greater,pivot));
if (i) {
less=base+num/2; //Pivot was not moved, point to it
if (less<greater)
SwapU64(less,greater);
num=i;
} else //All equal
break;
} else if (i<num/2) {
QSortI64(base,i,fp_compare);
num-=i;
base=greater;
} else {
QSortI64(greater,num-i,fp_compare);
num=i;
}
} while (num>1);
}
}
U0 QSort2a(U8 **_base,I64 num,I64 (*fp_compare)(U8 **_e1,U8 **_e2))
{//Not public, for case of width=size(U8 *)
I64 i;
U8 **_less,**_greater,*pivot;
do {
_less=_base;
_greater=_base+num;
pivot=_base[num/2];
while (_less<_greater) {
if ((*fp_compare)(_less,&pivot)<=0)
_less++;
else {
_greater--;
SwapU64(_less,_greater);
}
}
i=_less-_base;
if (i==num) { //All less or equal to pivot
//Point greater to first less
do _greater--;
while (--i && !(*fp_compare)(_greater,&pivot));
if (i) {
_less=_base+num/2; //Pivot was not moved, point to it
if (_less<_greater)
SwapU64(_less,_greater);
num=i;
} else //All equal
break;
} else if (i<num/2) {
if (i>1)
QSort2a(_base,i,fp_compare);
num-=i;
_base=_greater;
} else {
if (num-i>1)
QSort2a(_greater,num-i,fp_compare);
num=i;
}
} while (num>1);
}
U0 QSort2b(U8 *base,I64 num, I64 width, I64 (*fp_compare)(U8 *e1,U8 *e2),U8 *temp)
{//Not public
I64 i;
U8 *less,*greater,*pivot;
pivot=temp+width;
do {
less=base;
greater=base+num*width;
MemCpy(pivot,base+num/2*width,width);
while (less<greater) {
if ((*fp_compare)(less,pivot)<=0)
less+=width;
else {
greater-=width;
MemCpy(temp,greater,width);
MemCpy(greater,less,width);
MemCpy(less,temp,width);
}
}
i=(less-base)/width;
if (i==num) { //All less or equal to pivot
//Point greater to first less
do greater-=width;
while (--i && !(*fp_compare)(greater,pivot));
if (i) {
less=base+num/2*width; //Pivot was not moved, point to it
if (less<greater) {
MemCpy(temp,greater,width);
MemCpy(greater,less,width);
MemCpy(less,temp,width);
}
num=i;
} else //All equal
break;
} else if (i<num/2) {
if (i>1)
QSort2b(base,i,width,fp_compare,temp);
num-=i;
base=greater;
} else {
if (num-i>1)
QSort2b(greater,num-i,width,fp_compare,temp);
num=i;
}
} while (num>1);
}
U0 QSort(U8 *base,I64 num, I64 width, I64 (*fp_compare)(U8 *e1,U8 *e2))
{/*
For assending strings: Compare can return StrCmp(*e1,*e2);
For assending ints : Compare can return *e1-*e2;
Don't use e1-e2 if numbers can overflow, return -1,0 or 1 with if's.
Maybe, look at $LK,"::/SparrowOS/Demo/MultiCore/Sort.CPP.Z","FI:::/SparrowOS/Demo/MultiCore/Sort.CPP.Z"$ or
$LK,"::/SparrowOS/Demo/MultiCore/RadixSort.CPP.Z","FI:::/SparrowOS/Demo/MultiCore/RadixSort.CPP.Z"$.
*/
I64 i;
U8 *less,*greater,*temp,*pivot;
if (width && num>1) {
if (width==sizeof(U8 *)) { //assign instead of MemCpy for width 8
do {
less=base;
greater=base+num*sizeof(U8 *);
pivot(U8 *)=base(U8 **)[num/2];
while (less<greater) {
if ((*fp_compare)(less,&pivot)<=0)
less+=sizeof(U8 *);
else {
greater-=sizeof(U8 *);
SwapU64(less,greater);
}
}
i=(less-base)/sizeof(U8 *);
if (i==num) { //All less or equal to pivot
//Point greater to first less
do greater-=sizeof(U8 *);
while (--i && !(*fp_compare)(greater,&pivot));
if (i) {
less=base+num/2*sizeof(U8 *); //Pivot was not moved, point to it
if (less<greater)
SwapU64(less,greater);
num=i;
} else //All equal
break;
} else if (i<num/2) {
if (i>1)
QSort2a(base,i,fp_compare);
num-=i;
base=greater;
} else {
if (num-i>1)
QSort2a(greater,num-i,fp_compare);
num=i;
}
} while (num>1);
} else {
temp=MAlloc(width*2);
pivot=temp+width;
do {
less=base;
greater=base+num*width;
MemCpy(pivot,base+num/2*width,width);
while (less<greater) {
if ((*fp_compare)(less,pivot)<=0)
less+=width;
else {
greater-=width;
MemCpy(temp,greater,width);
MemCpy(greater,less,width);
MemCpy(less,temp,width);
}
}
i=(less-base)/width;
if (i==num) { //All less or equal to pivot
//Point greater to first less
do greater-=width;
while (--i && !(*fp_compare)(greater,pivot));
if (i) {
less=base+num/2*width; //Pivot was not moved, point to it
if (less<greater) {
MemCpy(temp,greater,width);
MemCpy(greater,less,width);
MemCpy(less,temp,width);
}
num=i;
} else //All equal
break;
} else if (i<num/2) {
if (i>1)
QSort2b(base,i,width,fp_compare,temp);
num-=i;
base=greater;
} else {
if (num-i>1)
QSort2b(greater,num-i,width,fp_compare,temp);
num=i;
}
} while (num>1);
Free(temp);
}
}
}
+414
View File
@@ -0,0 +1,414 @@
/*
See $LK,"SparrowOS MultiTasking","FI:::/SparrowOS/Doc/MultiTasking.TXT.Z"$.
Tasks are ordered in a que based
on window front-to-back order with the
window mgr as the head, which
paints the wallpaper. The scheduler
goes in a circle, checking if a task is
ready and swapping-it-in if so.
Swapping just involves storing and
restoring registers -- no disk I/O for
virtual memory and no addr map
changes. Tasks can be switched in half
a microsecond.
The scheduler checks if a task is
waiting for a certain time or waiting
on a message and skips it if it's not
ready. A task runs until it
voluntarily yields ctrl with a call
to $LK,"Yield","MN:Yield"$ or gets preempted by the
timer interrupt. See $LK,"SYS_TIMER_HANDLER","MN:SYS_TIMER_HANDLER"$.
The timer freqency is $LK,"JIFFY_FREQ","MN:JIFFY_FREQ"$. Tasks
can ask not to be preempted with
$LK,"Preempt","MN:Preempt"$(ON/OFF). Tasks waiting on I/O
often loop, checking for a stat and
swapping-out. This does not really
degrade performance, though it pegs the
CPU Load.
The scheduler checks for a few critical
key-strokes such as <CTRL-ALT-X>, which
kills a task; <CTRL-ALT-DEL>, which reboots;
<CTRL-ALT-T>, which changes focus and <CTRL-ALT-C>,
which breaks execution of a program.
Each core has it's own circular task
que. For AP processors, they have a
"Seth" task which stays in a loop
waiting for jobs or requests to spawn
tasks. See $LK,"MPSethServerTask","MN:MPSethServerTask"$().
All cores have an idle task. If the
scheduler determined an IRQ opportunity
hasn't happened, the scheduler swaps in
the idle task(enabling IRQs).
$HL,1$*/
asm {
USE64
// ************************************
SYS_IDLE_START::
SYS_SAVE_CONTEXT::
//OUT: RSI=FS
PUSH RSI
PUSHFD
XOR RSI,RSI
MOV RSI,FS:CTask.addr[RSI]
POP U64 CTask.rflags[RSI]
POP U64 CTask.rsi[RSI]
MOV U64 CTask.rax[RSI],RAX
/*
We divert the stk to the Task memory
and push onto it and divert it back.
It's a little faster.
*/
MOV RAX,RSP
LEA RSP,U64 CTask.r15+8[RSI]
PUSH R15
PUSH R14
PUSH R13
PUSH R12
PUSH R11
PUSH R10
PUSH R9
PUSH R8
PUSH RDI
PUSH RBP
PUSH RBX
PUSH RDX
PUSH RCX
MOV RSP,RAX
RDTSC
SHL RDX,32
ADD RAX,RDX
SUB RAX,U64 CTask.time_slice_start[RSI]
ADD U64 CTask.total_time[RSI],RAX
MOV RAX,U64 CTask.fpu_mmx[RSI]
FXSAVE U64 [RAX]
MOV RDX,U64 CTask.bpt_list[RSI]
@@05: OR RDX,RDX
JZ @@10
MOV RDI,U64 CBpt.addr[RDX]
MOV AL,U8 CBpt.val[RDX]
MOV U8 [RDI],AL
MOV RDX,U64 CBpt.next[RDX]
JMP @@05
@@10: LOCK
BTR U64 CTask.task_flags[RSI],TASKf_CURRENTLY_RUNNING
RET
// ************************************
SYS_RESTORE_CONTEXT::
XOR RAX,RAX
INC U64 GS:CCPU.swap_cnter[RAX]
MOV RSI,FS:CTask.addr[RAX]
BT U32 CTask.rflags[RSI],RFLAGS_INTERRUPTS
JNC @@05
LOCK //We will be enabling IRQ's
BTS U32 GS:CCPU.cpu_flags[RAX],CPUf_HAD_IRQ_OPPORTUNITY
@@05: LOCK
BTS U64 CTask.task_flags[RSI],TASKf_CURRENTLY_RUNNING
BT U64 CTask.task_flags[RSI],TASKf_DISABLE_BPTS
JC @@15
MOV RDX,U64 CTask.bpt_list[RSI]
@@10: OR RDX,RDX
JZ @@15
MOV RDI,U64 CBpt.addr[RDX]
MOV U8 [RDI],OC_BPT
MOV RDX,U64 CBpt.next[RDX]
JMP @@10
@@15: INC U64 CTask.swap_cnter[RSI]
MOV RAX,U64 CTask.fpu_mmx[RSI]
FXRSTOR U64 [RAX]
RDTSC
SHL RDX,32
ADD RAX,RDX
MOV U64 CTask.time_slice_start[RSI],RAX
MOV RAX,RSP
LEA RSP,U64 CTask.rcx[RSI]
POP RCX
POP RDX
POP RBX
POP RBP
POP RDI
POP R8
POP R9
POP R10
POP R11
POP R12
POP R13
POP R14
POP R15
MOV RSP,RAX
MOV RAX,U64 CTask.rax[RSI]
PUSH GDT_ZERO_DS_SEL
PUSH U64 CTask.rsp[RSI]
PUSH U64 CTask.rflags[RSI]
PUSH GDT_CS64_SEL
PUSH U64 CTask.rip[RSI]
MOV RSI,U64 CTask.rsi[RSI]
IRET
// ************************************
END_RSI_TASK:
MOV RAX,RSI
CALL SET_FS_BASE
SYS_TASK_END_NOW::
CALL &TaskEnd
MOV RSI,RAX
CALL SET_FS_BASE
JMP I32 RESTORE_RSI_TASK_WITH_KEY_CHECK
RESTORE_RSI_NO_PREEMPT_TASK:
BT U32 [SYS_CTRL_ALT_FLAGS],SYSf_CTRL_ALT_DEL
JC I32 HANDLE_SWAP_KEY_EVENT
XOR RAX,RAX
CMP U64 GS:CCPU.idle_task[RAX],RSI //IDLE TASK HAS PREEMPT-OFF
JNE RESTORE_RSI_TASK_NO_KEY_CHECK
JMP I32 SWAP_IN_SETH_TASK
SYS_SAVE_CONTEXT_YIELD::
PUSHFD
PUSH RAX
MOV RAX,SYS_SEMAS
BT U32 SYS_SEMA_SINGLE_USER*SEMA_STRUCT_SIZE[RAX],0
JC @@05
POP RAX
CLI
PUSH RSI
XOR RSI,RSI
MOV RSI,FS:CTask.addr[RSI]
CMP U64 CTask.next_task[RSI],RSI
JNE @@15
PUSH RAX
MOV RAX,U64 [SYS_JIFFIES]
CMP U64 CTask.wake_jiffy[RSI],RAX
JA @@10
POP RAX
POP RSI
POPFD
RET
@@05: POP RAX
POPFD
RET
@@10: POP RAX
@@15: POP RSI
CALL SYS_SAVE_CONTEXT
MOV EBX,U32 SYS_IDLE_PT
MOV U64 CTask.rip[RSI],RBX
POP U64 CTask.rflags[RSI]
MOV U64 CTask.rsp[RSI],RSP
RESTORE_NEXT_RSI_TASK:
MOV RSI,U64 CTask.next_task[RSI]
RESTORE_RSI_TASK_WITH_KEY_CHECK:
TEST U64 [SYS_CTRL_ALT_FLAGS],1<<SYSf_CTRL_ALT_DEL|
1<<SYSf_CTRL_ALT_TAB|1<<SYSf_CTRL_ALT_X|1<<SYSf_CTRL_ALT_C
JNZ HANDLE_SWAP_KEY_EVENT
RESTORE_RSI_TASK_NO_KEY_CHECK:
@@20: BT U64 CTask.task_flags[RSI],TASKf_KILL_TASK
JC I32 END_RSI_TASK
TEST U64 CTask.task_flags[RSI],1<<TASKf_AWAITING_MSG|1<<TASKf_SUSPENDED|1<<TASKf_PAUSED
JNZ @@25
MOV RAX,U64 [SYS_JIFFIES]
CMP U64 CTask.wake_jiffy[RSI],RAX
JA @@25
CMP U32 CTask.task_in_que_signature[RSI],TASK_IN_QUE_SIGNATURE_VAL
JNE SWAP_IN_SETH_TASK
MOV RAX,RSI
CALL SET_FS_BASE
JMP I32 SYS_RESTORE_CONTEXT
@@25: MOV RSI,U64 CTask.next_task[RSI]
XOR RAX,RAX
CMP U64 GS:CCPU.seth_task[RAX],RSI
JNE @@20
LOCK
BTR U32 GS:CCPU.cpu_flags[RAX],CPUf_HAD_IRQ_OPPORTUNITY
JC @@20
MOV RAX,U64 GS:CCPU.idle_task[RAX]
MOV RSP,U64 CTask.stk[RAX]
ADD RSP,DFT_STK+CTaskStk.stk_base //Rst to top
CALL SET_FS_BASE
STI
HLT
CLI
SWAP_IN_SETH_TASK:
XOR RAX,RAX
MOV RSI,GS:CCPU.seth_task[RAX]
JMP I32 RESTORE_RSI_TASK_WITH_KEY_CHECK
SYS_IDLE_PT::
RET
SYS_IDLE_END::
HANDLE_SWAP_KEY_EVENT:
MOV RAX,RSI
CALL SET_FS_BASE
XOR RAX,RAX
MOV RAX,GS:CCPU.num[RAX]
OR RAX,RAX
JNZ I32 RESTORE_RSI_TASK_NO_KEY_CHECK
MOV EAX,U32 SYS_CTRL_ALT_FLAGS
LOCK
BTR U32 [RAX],SYSf_CTRL_ALT_DEL
JC I32 &Reboot
LOCK
BTR U32 [RAX],SYSf_CTRL_ALT_TAB
JNC @@05
PUSH RSI
MOV RSI,U64 [SYS_FOCUS_TASK]
MOV U64 [SYS_FOCUS_TASK],0
CALL FOCUS_RSI_NEXT_USER
POP RSI
JMP I32 RESTORE_FS_TASK_WITH_KEY_CHECK
@@05: LOCK
BTR U32 [RAX],SYSf_CTRL_ALT_X
JC END_FOCUS_USER
LOCK
BTR U32 [RAX],SYSf_CTRL_ALT_C
JNC I32 RESTORE_RSI_TASK_WITH_KEY_CHECK
BREAK_FOCUS_USER:
MOV RSI,U64 [SYS_FOCUS_TASK]
OR RSI,RSI
JZ SWAP_IN_SETH_TASK
BT U64 CTask.task_flags[RSI],TASKf_USER
JNC I32 RESTORE_RSI_TASK_NO_KEY_CHECK
LOCK
BTR U64 CTask.task_flags[RSI],TASKf_BREAK_LOCKED
JNC @@10
LOCK
BTS U64 CTask.task_flags[RSI],TASKf_PENDING_BREAK
JMP I32 RESTORE_RSI_TASK_NO_KEY_CHECK
@@10: MOV RAX,&SysThrowBreak
MOV U64 CTask.rip[RSI],RAX
BT U64 CTask.task_flags[RSI],TASKf_BREAK_TO_SHIFT_ESC
JC @@15
//We do these two now, in case interrupt happens
MOV U64 CTask.wake_jiffy[RSI],0
PUSH RSI
CALL &TaskRstAwaitingMsg
@@15: JMP I32 RESTORE_RSI_TASK_NO_KEY_CHECK
END_FOCUS_USER:
MOV RSI,U64 [SYS_FOCUS_TASK]
MOV U64 [SYS_FOCUS_TASK],0
PUSH RSI
CALL FOCUS_RSI_NEXT_USER
POP RSI
OR RSI,RSI
JZ I32 SWAP_IN_SETH_TASK
MOV RAX,RSI
CALL SET_FS_BASE
BT U64 CTask.task_flags[RSI],TASKf_USER
JNC I32 RESTORE_RSI_TASK_WITH_KEY_CHECK
LOCK
BTS U64 CTask.task_flags[RSI],TASKf_KILL_TASK
JMP I32 END_RSI_TASK
RESTORE_FS_TASK_WITH_KEY_CHECK:
XOR RSI,RSI
MOV RSI,FS:CTask.addr[RSI]
JMP I32 RESTORE_RSI_TASK_WITH_KEY_CHECK
FOCUS_RSI_NEXT_USER:
OR RSI,RSI
JNZ @@20
MOV ESI,U32 SYS_ADAM_TASK
@@20: MOV RDI,RSI
MOV RSI,U64 CTask.next_task[RSI]
@@25: BT U64 CTask.task_flags[ESI],TASKf_USER
JNC @@30
CMP U64 [SYS_FOCUS_TASK],RSI
JE @@30
MOV U64 [SYS_FOCUS_TASK],RSI
MOV RAX,U64 [SYS_EXTERN_TABLE]
MOV RAX,U64 EXT_WIN_TO_TOP*8[RAX]
OR RAX,RAX
JZ @@35
PUSH TRUE
PUSH RSI
CALL RAX
JMP @@35
@@30: MOV RSI,U64 CTask.next_task[RSI]
CMP RSI,RDI
JNE @@25
MOV U64 [SYS_FOCUS_TASK],0
@@35: RET
}
_extern SYS_RESTORE_CONTEXT U0 RestoreContext();
_extern SYS_SAVE_CONTEXT_YIELD U0 Yield();
_extern SYS_IDLE_START U8 sys_idle_start;
_extern SYS_IDLE_END U8 sys_idle_end;
_extern SYS_TASK_END_NOW U0 TaskEndNow();
U0 TaskQueIns(CTask *task,CTask *pred=NULL)
{
CTask *last;
PushFD;
Cli;
if (!pred) pred=Fs;
last=pred->last_task;
last->next_task=pred->last_task=task;
task->last_task=last;
task->next_task=pred;
task->task_in_que_signature=TASK_IN_QUE_SIGNATURE_VAL;
PopFD;
}
U0 TaskQueRem(CTask *task)
{
CTask *next,*last;
PushFD;
Cli;
task->task_in_que_signature=0;
next=task->next_task;
last=task->last_task;
last->next_task=next;
next->last_task=last;
PopFD;
}
U0 TaskQueInsChild(CTask *task)
{
CTask *last,*pred;
PushFD;
Cli;
pred=task->parent_task->last_child_task;
last=pred->last_sibling_task;
last->next_sibling_task=pred->last_sibling_task=task;
task->last_sibling_task=last;
task->next_sibling_task=pred;
PopFD;
}
+14
View File
@@ -0,0 +1,14 @@
#exe {OptOn(OPTf_KEEP_PRIVATE);};
#include "/SparrowOS/OSMain/BootDefs.HPP.Z"
#include "/SparrowOS/OSMain/Adam1a.HPP.Z"
#exe {OptOn(OPTf_EXTERNS_TO_IMPORTS);};
#include "/SparrowOS/Compiler/CmpDefs.HPP.Z"
#include "/SparrowOS/OSMain/Adam1b.HPP.Z"
#include "/SparrowOS/OSMain/Adam1c.HPP.Z"
#exe {
OptOff(OPTf_EXTERNS_TO_IMPORTS);
OptOff(OPTf_KEEP_PRIVATE);
};
+2
View File
@@ -0,0 +1,2 @@
#exe {ImportHashTable(adam_task->hash_table);};
File diff suppressed because it is too large. Load diff
+586
View File
@@ -0,0 +1,586 @@
U0 Exit()
{
if (Fs==sys_focus_task && IsInDbg) {
LBts(&Fs->task_flags,TASKf_KILL_AFTER_DBG);
Go1;
} else {
if (!Gs->num && !IsInDbg)
SingleUser(OFF);
Fs->rflags=GetFlags;
Fs->rsp=GetStkPtr;
Fs->rbp=GetBasePtr;
Fs->rip=$$;
Cli;
LBts(&Fs->task_flags,TASKf_KILL_TASK);
TaskEndNow;
}
}
Bool TaskValidate(CTask *task)
{
if (!(0<task<=MAX_I32) || task->addr!=task ||
task->task_signature(I64)!=TASK_COMBINED_SIGNATURE_VAL)
return FALSE;
else
return TRUE;
}
U0 Kill(CTask *task,Bool wait=TRUE)
{
I64 i;
CCPU *c;
Bool found,old_preempt=Preempt(OFF);
if (TaskValidate(task)) {
if (task==sys_winmgr_task)
found=TRUE;
else
found=FALSE;
for (i=0;i<mp_cnt;i++) {
c=&cpu_structs[i];
if (task==c->seth_task)
found=TRUE;
}
if (!found) {
LBts(&task->task_flags,TASKf_KILL_TASK);
if (wait) {
do Yield;
while (TaskValidate(task) && Bt(&task->task_flags,TASKf_KILL_TASK));
}
}
}
Preempt(old_preempt);
}
Bool Suspend(CTask *task=NULL,Bool state=TRUE)
{
Bool result;
if (!task) task=Fs;
PushFD;
Cli;
if (TaskValidate(task))
result=LBEqu(&task->task_flags,TASKf_SUSPENDED,state);
else
result=FALSE;
PopFD;
return result;
}
Bool IsSuspended(CTask *task=NULL)
{
if (!task) task=Fs;
if (TaskValidate(task))
return Bt(&task->task_flags,TASKf_SUSPENDED);
else
return FALSE;
}
CTaskStk *TaskStkNew(I64 stk_size,CTask *task)
{
CTaskStk *temps=MAlloc(stk_size+offset(CTaskStk.stk_base),task);
temps->next_stk=NULL;
temps->stk_ptr=NULL;
temps->stk_size=MSize(temps)-offset(CTaskStk.stk_base);
return temps;
}
#exe {OptOn(OPTf_NO_REG_VAR);};
//fp_add can have any fixed number of arguments.
argpop I64 CallStkGrow(I64 stk_size_threshold,I64 stk_size,/*argpop*/I64 (*fp_add)(...),...)
{
CTaskStk *temps,*temps2,**_stk;
I64 result,*rsp,*rsp2,*old_stk;
if (UnusedStk>=stk_size_threshold) {
asm {
LEAVE
POP RAX //return addr
ADD RSP,16 //pop threshold,stk_size
POP RBX // *f
ADD RSP,8 //pop ARGC
PUSH RAX
JMP RBX //CALL fp_add()
};
} else {
temps2=TaskStkNew(stk_size,Fs);
temps2->next_stk=temps=Fs->stk;
rsp2=(&temps2->stk_base)(U8 *)+temps2->stk_size;
old_stk=rsp=&argv[argc];
while (argc-->0)
*--rsp2=*--rsp;
_stk=&Fs->stk;
temps->stk_ptr=rsp=GetStkPtr;
asm {
IMPORT _FREE; //We are in a function, not at glbl scope.
//The compiler treats these in isolation.
PUSHFD
POP RDX //flags
CLI
MOV RBX,U64 &temps2[RBP]
MOV RAX,&_stk[RBP]
MOV U64 [RAX],RBX //Fs->stk=temps2
MOV RSP,U64 &rsp2[RBP]
PUSH RDX
POPFD
CALL U64 &fp_add[RBP]
MOV U64 &result[RBP],RAX
PUSHFD
POP RDX //flags
CLI
MOV RBX,U64 &temps[RBP]
MOV RAX,&_stk[RBP]
MOV U64 [RAX],RBX //Fs->stk=temps
MOV RSP,U64 &rsp[RBP]
PUSH RDX
POPFD
PUSH U64 &temps2[RBP]
CALL _FREE
MOV RDX,U64 &old_stk[RBP]
MOV RBX,U64 8[RBP]
MOV RAX,U64 &result[RBP]
MOV RBP,U64 [RBP]
MOV RSP,RDX
JMP RBX //return
};
}
return 0; //dummy to get rid of warning
}
;
#exe {OptOff(OPTf_NO_REG_VAR);};
I64 TaskInit(CTask *task,I64 stk_size)
{ //Returns Fs of task
CTaskStk *temps;
QueInit(&task->code_heap->next_mem_blk);
if (task->code_heap!=task->data_heap)
QueInit(&task->data_heap->next_mem_blk);
task->addr=
task->next_task=
task->last_task=
task->next_input_filter_task=
task->last_input_filter_task=
task;
task->rflags=SYS_NORMAL_RFLAGS;
task->win_max_refresh=WIN_DFT_MAX_REFRESH;
SetSnap(&task->snap,1,1.0);
task->next_child_task=
task->last_child_task=
(&task->next_child_task)(U8 *)-offset(CTask.next_sibling_task);
task->next_doc=
task->last_doc=
(&task->next_doc)(U8 *)-offset(CDoc.next_doc);
QueInit(&task->next_servant_cmd);
QueInit(&task->next_master_cmd);
QueInit(&task->next_lex);
QueInit(&task->next_except);
QueInit(&task->next_ctrl);
QueInit(&task->next_ode);
task->fpu_mmx=MAllocAligned(sizeof(CFPU),0x10,task);
MemCpy(task->fpu_mmx,&sys_init_fpu_mmx,sizeof(CFPU));
if (task==SYS_ADAM_TASK) {
// Delayed until heap expanded. See $LK,"Expand Heap","FA:::/SparrowOS/OSMain/Memory.CPP.Z,ExpandHeap"$
// task->hash_table=HashTableNew(ADAM_HASH_SIZE,task);
} else {
if (!Gs->num)
task->hash_table=HashTableNew(STD_HASH_SIZE,task);
else
task->hash_table=HashTableNew(MP_STD_HASH_SIZE,task);
}
if (!stk_size) {
if (!Gs->num)
stk_size=DFT_STK;
else
stk_size=MP_DFT_STK;
}
task->stk=temps=TaskStkNew(stk_size,task);
task->rsp=(&temps->stk_base)(U8 *)+temps->stk_size;
task->answers_displayed=1; //from 0-8
task->text_attr =WHITE<<4+BLUE;
task->border_attr=WHITE<<4+LTBLUE;
task->win_right =text_cols-2;
task->win_left =1;
task->win_top =1;
task->win_bottom =text_rows-2;
return task;
}
CTask *Spawn(U0 (*fp_start_add)(U8 *data),U8 *data=NULL,
U8 *task_name=NULL,
CTask *parent=NULL, //NULL means adam
I64 stk_size=0, //0=default
I64 flags=SPAWNF_ADD_TO_QUE)
{
//We alloc from code heap so addr will be short
//Could be allocated off of data heap
CTask *task=CAlloc(sizeof(CTask),adam_task->code_heap);
task->task_signature=TASK_SIGNATURE_VAL;
if (!task_name) task_name="Unnamed Task";
if (!parent) parent=Gs->seth_task;
task->parent_task=parent;
task->gs=parent->gs;
if (sys_code_bp)
task->code_heap=TaskHeapCtrlNew(task,sys_code_bp);
if (sys_data_bp)
task->data_heap=TaskHeapCtrlNew(task,sys_data_bp);
else
task->data_heap=task->code_heap;
TaskInit(task,stk_size);
task->rip=fp_start_add;
task->rsp(U8 *)-=8;
*task->rsp=data;
task->rsp(U8 *)-=8;
*task->rsp=&Exit;
task->hash_table->next=parent->hash_table;
MemCpy(task->task_title,task_name,TASK_TITLE_LEN+1);
MemCpy(task->task_name,task_name,TASK_NAME_LEN+1);
PushFD;
Cli;
if (flags&SPAWNF_ADD_TO_QUE) {
TaskQueInsChild(task);
TaskQueIns(task);
}
PopFD;
return task;
}
U0 ServantTaskCont()
{
FlushMsgs;
while (TRUE) {
if (ServantCmdsHandler)
if (!Bt(&Fs->task_flags,TASKf_LOCK_TITLE))
MemCpy(Fs->task_title,Fs->task_name,TASK_NAME_LEN+1);
FlushMsgs;
LBts(&Fs->task_flags,TASKf_IDLE);
LBts(&Fs->task_flags,TASKf_AWAITING_MSG);
Yield;
}
}
U0 TaskDerivedValsUpdate(CTask *task=NULL,Bool update_z_buf=TRUE)
{
if (!task) task=Fs;
PushFD;
Cli;
while (LBts(&task->locked_flags,TASKLf_TASK_LOCK))
Pause;
WinDerivedValsUpdate(task);
if (fp_update_ctrls)
(*fp_update_ctrls)(task);
if (update_z_buf && Bt(&task->display_flags,DISPLAYf_SHOW))
LBts(&sys_semas[SYS_SEMA_UPDATE_WIN_Z_BUF],0);
LBtr(&task->locked_flags,TASKLf_TASK_LOCK);
PopFD;
}
U0 TaskInitExt()
{
if (LBts(&Fs->task_flags,TASKf_INIT_EXT))
return;
TaskDerivedValsUpdate;
LBts(&Fs->display_flags,DISPLAYf_HAS_CLOSE_WIN);
Fs->text_attr =WHITE<<4+BLUE;
Fs->border_attr=WHITE<<4+LTBLUE;
Fs->win_top=13;
Cd("HOME");
CallExtNum(EXT_WIN_TO_TOP,Fs,Bt(&Fs->display_flags,DISPLAYf_SHOW));
}
I64 ExeCmdLine(CLex *lx)
{
I64 result=0,i,type;
U8 *ptr,*ptr2,*ptr3,*code;
CDocEntry *doc_e;
CDoc *doc;
while (lx->token &&
(lx->token!='}' || !(lx->flags & LF_EXE_BLK)) ) {
if (!Bt(&Fs->task_flags,TASKf_LOCK_TITLE)) {
ptr2=&Fs->task_title;
ptr3=ptr2+TASK_TITLE_LEN;
if (lx->cur_lfn->flags & LFSF_IS_DOC) {
doc_e=lx->cur_lfn->line_start;
doc=lx->cur_lfn->doc;
while (doc_e!=doc && ptr2<ptr3) {
switch (doc_e->type_u8 && ptr2<ptr3) {
case DOCT_TEXT:
ptr=doc_e->tag;
while (*ptr && ptr2<ptr3)
*ptr2++=*ptr++;
break;
case DOCT_TAB:
case DOCT_NEW_LINE:
*ptr2++='.';
break;
}
doc_e=doc_e->next;
}
} else
if (ptr=lx->cur_lfn->line_start)
MemCpy(ptr2,ptr,TASK_TITLE_LEN);
}
lx->flags&=~LF_HAS_MISC_DATA;
code=CmpStatement(lx,&type);
if (code!=INVALID_PTR) {
if (!(lx->flags&LF_JUST_LOAD)) {
result=Call(code);
for (i=2;i>=0;i--) {
Fs->answers[i+1]=Fs->answers[i];
Fs->answer_types[i+1]=Fs->answer_types[i];
}
Fs->answers[0]=result;
Fs->answer_types[0]=type;
}
if (!(lx->flags&LF_HAS_MISC_DATA))
Free(code);
}
}
if (lx->flags&LF_JUST_LOAD) {
if (lx->error_cnt)
return FALSE;
else
return TRUE;
} else
return result;
}
U0 UserTaskCont()
{
CLex *lx;
CDoc *doc;
Bool cont=TRUE;
do {
lx=LexNew(NULL,LF_PROMPT,NULL);
QueIns(lx,Fs->last_lex);
try {
Lex(lx);
ExeCmdLine(lx);
cont=Bt(&lx->flags,Lf_PROMPT);
QueRem(lx);
LexDel(lx);
} catch {
doc=Fs->last_doc;
if (doc!=(&Fs->next_doc)(U8 *)-offset(CDoc.next_doc) &&
doc->doc_in_que_signature==DOC_IN_QUE_SIGNATURE_VAL)
DocUnlock(doc);
CatchAll;
}
} while (cont);
}
U0 UserCmdLine(I64 dummy=0)
{
nounusedwarn dummy;
LBts(&Fs->task_flags,TASKf_USER);
TaskInitExt;
Fs->user_num=++sys_num_spawned_users;
if (HashFind("UserStartUp",adam_task->hash_table,HTT_FUN))
CallExtStr("UserStartUp");
if (!LBts(&Fs->display_flags,DISPLAYf_SHOW))
Dbg;
UserTaskCont;
}
U0 ServantUserCmdLine(I64 dummy=0)
{
nounusedwarn dummy;
LBts(&Fs->task_flags,TASKf_USER);
TaskInitExt;
if (HashFind("ServantStartUp",adam_task->hash_table,HTT_FUN))
CallExtStr("ServantStartUp");
ServantTaskCont;
}
CTask *SpawnUser(U8 *fmt=NULL,...)
{
U8 *st;
CTask *task=Spawn(&UserCmdLine);
TaskWait(task);
if (fmt) {
st=SPrintFJoin(NULL,fmt,argc,argv);
XTalk(task,st);
Free(st);
}
return task;
}
U0 TaskPause(CTask *task=NULL,Bool state=TRUE)
{
CTask *task1;
Bool old_preempt;
if (!task) task=Fs;
old_preempt=Preempt(OFF);
if (TaskValidate(task)) {
if (LBEqu(&task->task_flags,TASKf_PAUSED,state)) {
if (!state)
task->pause_total+=tNP-task->pause_start;
} else {
if (state)
task->pause_start=tNP;
}
task1=task->next_child_task;
while (task1!=&task->next_child_task) {
if (!TaskValidate(task1))
break;
TaskPause(task1,state);
task1=task1->next_sibling_task;
}
}
Preempt(old_preempt);
}
U0 TaskFinishOff(CTask *task)
{ //We delay freeing in case lingering
//references are made to task's.
TaskHeapCtrlDel(task->code_heap);
if (task->data_heap!=task->code_heap)
TaskHeapCtrlDel(task->data_heap);
Free(task);
}
I64 TaskEnd()
{ //called with irq's off
CTask *task=Fs,*tempt,*tempt1;
CTaskCmd *tempc,*tempc1,*tempc2;
if (task==sys_task_being_screen_updated) {
LBts(&task->task_flags,TASKf_KILL_TASK);
return task->next_task;
}
if (task->task_end_cb) {
task->wake_jiffy=0;
LBtr(&task->task_flags,TASKf_KILL_TASK);
TaskRstAwaitingMsg(task);
Suspend(task,FALSE);
task->rip=task->task_end_cb;
task->task_end_cb=NULL;
return task;
}
if (task->parent_task) {
if (task->parent_task->popup_task==task) {
task->parent_task->popup_task=NULL;
Kill(task->parent_task,FALSE);
return task->parent_task;
}
if (task->parent_task->dbg_task==task)
task->parent_task->dbg_task=NULL;
}
PrtsRelease;
BlkDevsRelease;
tempt1=(&task->next_child_task)(U8 *)-offset(CTask.next_sibling_task);
tempt=tempt1->next_sibling_task;
if (tempt!=tempt1) {
do {
LBts(&tempt->task_flags,TASKf_KILL_TASK);
tempt=tempt->next_sibling_task;
} while (tempt!=tempt1);
return task->next_task;
}
if (LBtr(&task->display_flags,DISPLAYf_SHOW))
LBts(&sys_semas[SYS_SEMA_UPDATE_WIN_Z_BUF],0);
while (LBts(&task->locked_flags,TASKLf_TASK_LOCK))
Pause;
tempc1=&task->next_servant_cmd;
tempc=tempc1->next;
while (tempc!=tempc1) {
tempc2=tempc->next;
Free(tempc->data);
Free(tempc);
tempc=tempc2;
}
tempc1=&task->next_master_cmd;
tempc=tempc1->next;
while (tempc!=tempc1) {
tempc2=tempc->next;
Free(tempc->data);
Free(tempc);
tempc=tempc2;
}
if (IsRaw)
VGAFlush;
if (sys_focus_task==task) {
if (!Gs->num)
SingleUser(OFF);
sys_focus_task=NULL;
if (fp_set_std_palette)
(*fp_set_std_palette)();
}
//QueRem
task->task_signature(I64)=0;
tempt =task->next_input_filter_task;
tempt1=task->last_input_filter_task;
tempt1->next_input_filter_task=tempt;
tempt ->last_input_filter_task=tempt1;
tempt =task->next_sibling_task;
tempt1=task->last_sibling_task;
tempt1->next_sibling_task=tempt;
tempt ->last_sibling_task=tempt1;
tempt =task->next_task; //save to return
TaskQueRem(task);
LBtr(&task->locked_flags,TASKLf_TASK_LOCK);
if (sys_winmgr_task) {
task->next_task=Gs->dying_task_list;
Gs->dying_task_list=task;
} else
TaskFinishOff(task); //dangerous (stk in use)
//Never happens--winmgr exists except during boot and no tasks die during boot
//currently, though this has been different and might be different in future.
//Would have to be multicore task getting this task's memory
//because IRQs are off, so no tasks on this core run.
return tempt;
}
U0 TaskFinishOffDying()
{ //Called by Seth tasks with preemption off.
/*
Delay freeing a task in case lingering
references are made. $LK,"::/SparrowOS/Adam/WallPaper.CPP.Z","FI:::/SparrowOS/Adam/WallPaper.CPP.Z"$,
for example, might be processing a task record.
A dead task fails $LK,"TaskValidate","MN:TaskValidate"$(), but
what if a task dies and is reincarnated
as another task with the same task record!
A slight delay in freeing the task record
is just a precaution, in case code somewhere
doesn't use $LK,"Preempt","MN:Preempt"$(OFF) and could get burned
by a task being reincarnated.
*/
CTask *task1,*task2;
if (task1=Gs->dying_task_list) {
do {
task2=task1->next_task;
TaskFinishOff(task1);
task1=task2;
} while (task1);
Gs->dying_task_list=NULL;
}
}
+422
View File
@@ -0,0 +1,422 @@
U0 TaskRstAwaitingMsg(CTask *task=NULL)
{ //Pop-ups get parent messages so wake-up our pop-ups if we got a msg.
Bool old_preempt=Preempt(OFF);
if (!task) task=Fs;
if (TaskValidate(task)) {
LBtr(&task->task_flags,TASKf_AWAITING_MSG);
while (task=task->popup_task)
if (TaskValidate(task))
LBtr(&task->task_flags,TASKf_AWAITING_MSG);
else
break;
}
Preempt(old_preempt);
}
CTaskCmd *TaskRqstQue(CTask *servant,CTask *master,
U8 *data,I64 flags)
{
CTaskCmd *result;
if (!data || !TaskValidate(servant) ||
master && !TaskValidate(master) ||
servant->popup_task && !Bt(&servant->task_flags,TASKf_FILTER_INPUT))
return NULL;
result=AMAlloc(sizeof(CTaskCmd));
result->master_task=master;
result->cmd_code=TASKCT_EXECUTE_STR;
result->flags=flags;
result->data=AStrNew(data);
result->result=NULL;
PushFD;
Cli;
while (LBts(&servant->locked_flags,TASKLf_TASK_LOCK))
Pause;
if (!TaskValidate(servant)) {
PopFD;
Free(result->data);
Free(result);
return NULL;
} else {
LBtr(&servant->task_flags,TASKf_IDLE);
TaskRstAwaitingMsg(servant);
QueIns(result,servant->last_servant_cmd);
LBtr(&servant->locked_flags,TASKLf_TASK_LOCK);
if (Bt(&flags,TASKCf_WAKE_MASTER)) {
Suspend(master);
Yield;
}
}
PopFD;
return result;
}
CTaskCmd *TextInputQue(CTask *servant,CTask *master,
U8 *data,I64 flags)
{
CTaskCmd *result;
Bool old_preempt=Preempt(OFF);
CTask *task;
if (!data || !TaskValidate(servant) ||
master && !TaskValidate(master) ||
servant->popup_task && !Bt(&servant->task_flags,TASKf_FILTER_INPUT)) {
Preempt(old_preempt);
return NULL;
}
result=AMAlloc(sizeof(CTaskCmd));
result->master_task=master; //in case somebody cares
result->cmd_code=TASKCT_TEXT_INPUT;
result->flags=flags;
result->data=AStrNew(data);
result->result=NULL;
PushFD;
if (flags&1<<TASKCf_HIGHEST_PRIORITY ||
servant->next_input_filter_task==servant) {
task=Spawn(&InputFilterTask,NULL,
"Input Filter",servant);
Cli;
task->next_input_filter_task=servant->next_input_filter_task;
task->last_input_filter_task=servant;
servant->next_input_filter_task=task;
task->next_input_filter_task->last_input_filter_task=task;
} else
task=servant->next_input_filter_task;
Cli;
while (LBts(&task->locked_flags,TASKLf_TASK_LOCK))
Pause;
if (!TaskValidate(task)) {
Free(result->data);
Free(result);
result=NULL;
} else {
LBtr(&task->task_flags,TASKf_IDLE);
TaskRstAwaitingMsg(task);
QueIns(result,task->last_servant_cmd);
LBtr(&task->locked_flags,TASKLf_TASK_LOCK);
}
PopFD;
Preempt(old_preempt);
return result;
}
CTaskCmd *QueMsg(CTask *_servant,CTask *master,
I64 msg_code,I64 p1,I64 p2,I64 flags)
{
CTaskCmd *tempc1,*tempc;
CTask *servant=_servant;
if (!TaskValidate(servant) ||
master && !TaskValidate(master)||
servant->popup_task && !Bt(&servant->task_flags,TASKf_FILTER_INPUT))
return NULL;
tempc=AMAlloc(sizeof(CTaskCmd));
tempc->master_task=master;
tempc->cmd_code=TASKCT_MSG;
tempc->msg_code=AbsI64(msg_code); //negative means do a down and up
tempc->p1=p1;
tempc->p2=p2;
tempc->flags=flags;
tempc->data=NULL;
tempc->result=NULL;
PushFD;
if (Bt(&sys_semas[SYS_SEMA_RECORD_MACRO],0) &&
servant!=sys_macro_util_task &&
msg_code==MSG_KEY_DOWN) {
tempc1=AMAllocIdentical(tempc);
Cli;
QueIns(tempc1,sys_macro_root.last);
}
Cli;
while (Bt(&servant->task_flags,TASKf_FILTER_INPUT) &&
!Bt(&flags,TASKCf_DONT_FILTER))
servant=servant->next_input_filter_task;
while (LBts(&servant->locked_flags,TASKLf_TASK_LOCK))
Pause;
if (!TaskValidate(servant)) {
Free(tempc);
tempc=NULL;
} else {
LBtr(&servant->task_flags,TASKf_IDLE);
TaskRstAwaitingMsg(servant);
QueIns(tempc,servant->last_servant_cmd);
LBtr(&servant->locked_flags,TASKLf_TASK_LOCK);
}
PopFD;
if (msg_code<0) //Down-Up
QueMsg(_servant,master,-msg_code+1,p1,p2,flags);
return tempc;
}
Bool GetRqstResult(CTaskCmd *rqst=NULL,I64 *_result=NULL)
{
CTaskCmd *tempc,*tempc1;
PushFD;
Cli;
while (LBts(&Fs->locked_flags,TASKLf_TASK_LOCK))
Pause;
tempc1=&Fs->next_master_cmd;
tempc=tempc1->next;
while (tempc!=tempc1) {
if (!rqst || rqst==tempc) {
QueRem(tempc);
LBtr(&Fs->locked_flags,TASKLf_TASK_LOCK);
PopFD;
if (_result)
*_result=tempc->result;
Free(tempc->data);
Free(tempc);
return TRUE;
}
tempc=tempc->next;
}
LBtr(&Fs->locked_flags,TASKLf_TASK_LOCK);
PopFD;
return FALSE;
}
U0 TaskWait(CTask *task=NULL)
{
CTask *task1;
CTaskCmd *tempc;
if (!task) task=Fs;
if (TaskValidate(task)) {
PushFD;
Cli;
while (TRUE) {
task1=task->last_input_filter_task;
tempc=&task1->next_servant_cmd;
if (TaskValidate(task1) && tempc==*tempc &&
(task1==Fs || Bt(&task1->task_flags,TASKf_IDLE)))
break;
Yield;
}
PopFD;
}
}
U0 PostMsg(CTask *task,I64 msg_code,I64 p1,I64 p2,I64 flags=0)
{
if (TaskValidate(task)) {
if (Bt(&task->task_flags,TASKf_INPUT_FILTER_TASK))
QueMsg(task->last_input_filter_task,NULL,msg_code,p1,p2,
flags| 1<<TASKCf_DONT_FILTER);
else
QueMsg(task,NULL,msg_code,p1,p2,flags);
}
}
U0 SendMsg(CTask *task,I64 msg_code,I64 p1,I64 p2,I64 flags=0)
{
PostMsg(task,msg_code,p1,p2,flags);
TaskWait(task);
}
U0 Msg(I64 msg_code,I64 p1,I64 p2,I64 flags=0)
{
PostMsg(Fs,msg_code,p1,p2,flags);
}
I64 ServantCmdsHandler(CTask *task=NULL)
{
I64 cnt=0,old_flags=GetFlags;
CTaskCmd *tempc,*tempc1;
CTask *master;
if (!task) task=Fs;
start_over:
Cli;
while (LBts(&task->locked_flags,TASKLf_TASK_LOCK))
Pause;
tempc1=&task->next_servant_cmd;
tempc=tempc1->next;
while (tempc!=tempc1) {
tempc=tempc1->next;
if (tempc->cmd_code==TASKCT_EXECUTE_STR ||
tempc->cmd_code==TASKCT_EXECUTE_FILE) {
cnt++;
QueRem(tempc);
LBtr(&task->locked_flags,TASKLf_TASK_LOCK);
SetFlags(old_flags);
try {
if (tempc->cmd_code==TASKCT_EXECUTE_STR)
tempc->result=ExePutS(tempc->data,sys_temp_filename);
else
tempc->result=ExeFile(tempc->data);
} catch
Fs->catch_except=TRUE;
if (master=tempc->master_task) {
if (!Bt(&tempc->flags,TASKCf_EXIT_ON_COMPLETE)) {
Cli;
while (LBts(&master->locked_flags,TASKLf_TASK_LOCK))
Pause;
QueIns(tempc,master->last_master_cmd);
LBtr(&master->locked_flags,TASKLf_TASK_LOCK);
SetFlags(old_flags);
}
if (Bt(&tempc->flags,TASKCf_FOCUS_MASTER) &&
Bt(&master->task_flags,TASKf_USER))
sys_focus_task=master;
if (Bt(&tempc->flags,TASKCf_WAKE_MASTER))
Suspend(master,FALSE);
if (!Bt(&tempc->flags,TASKCf_EXIT_ON_COMPLETE))
goto start_over;
else {
Free(tempc->data);
Free(tempc);
Exit;
}
} else {
if (!Bt(&tempc->flags,TASKCf_EXIT_ON_COMPLETE)) {
Free(tempc->data);
Free(tempc);
goto start_over;
} else {
Free(tempc->data);
Free(tempc);
Exit;
}
}
} else
break;
}
LBtr(&task->locked_flags,TASKLf_TASK_LOCK);
SetFlags(old_flags);
return cnt;
}
I64 Adam(U8 *fmt,...)
//Sends text to the adam task which gets
//compiled and run.
{
I64 result;
U8 *st=SPrintFJoin(NULL,fmt,argc,argv);
Bool old_preempt=Preempt(OFF);
CTaskCmd *tempc;
if (Fs==adam_task) {
tempc=TaskRqstQue(adam_task,Fs,st,0);
ServantCmdsHandler;
} else {
TaskWait(adam_task);
tempc=TaskRqstQue(adam_task,Fs,st,1<<TASKCf_WAKE_MASTER);
}
Preempt(old_preempt);
GetRqstResult(tempc,&result);
Free(st);
return result;
}
U0 AdamLog(U8 *fmt,...)
//Sends text to the adam task which gets
//displayed.
{
U8 *st=SPrintFJoin(NULL,fmt,argc,argv);
if (Fs==adam_task)
"" st;
else if (!IsSingleUser)
Adam("\"%Q\";",st);
Free(st);
}
U0 AdamErr(U8 *fmt,...)
//Sends text to the adam task which gets
//displayed as red and blinking.
{
U8 *st=SPrintFJoin(NULL,fmt,argc,argv),
*st2=MSPrintF("%S%s","ST_ERR",st);
if (Fs==adam_task)
"" st2;
else if (!IsSingleUser)
Adam("\"%Q\";",st2);
Free(st2);
Free(st);
}
U0 XTalk(CTask *task,U8 *fmt,...)
//Sends text to another task's input
//buffer.
{
U8 *st=SPrintFJoin(NULL,fmt,argc,argv),
*st2=MSPrintF("\"%Q\";",st);
TextInputQue(task,0,st2,0);
Free(st2);
Free(st);
}
U0 XTalkWait(CTask *task,U8 *fmt,...)
{
U8 *st=SPrintFJoin(NULL,fmt,argc,argv),
*st2=MSPrintF("\"%Q\";",st);
TextInputQue(task,0,st2,0);
Free(st2);
Free(st);
TaskWait(task);
}
U0 Auto(U8 *fmt,...)
//Sends text to one's own input buffer
{
U8 *st=SPrintFJoin(NULL,fmt,argc,argv),
*st2=MSPrintF("\"%Q\";",st);
if (Bt(&Fs->task_flags,TASKf_INPUT_FILTER_TASK))
ExePutS(st2);
else
TextInputQue(Fs,0,st2,1<<TASKCf_HIGHEST_PRIORITY);
Free(st2);
Free(st);
}
I64 ServantUser(U8 *fmt,...)
//Spawns a visible task and sends text
//which gets compiled and run.
{
U8 *st=SPrintFJoin(NULL,fmt,argc,argv);
I64 result=0;
CTaskCmd *tempc;
CTask *task=Spawn(&ServantUserCmdLine,NULL,"Servant",Fs);
Fs->popup_task=task;
tempc=TaskRqstQue(task,Fs,st,1<<TASKCf_WAKE_MASTER|1<<TASKCf_FOCUS_MASTER);
GetRqstResult(tempc,&result);
Fs->popup_task=NULL;
Kill(task,FALSE);
Free(st);
return result;
}
U0 AutoStr(U8 *fmt,...)
//Sends text in the nature of an AutoFile to one's
//own input buffer.
{
U8 *st=SPrintFJoin(NULL,fmt,argc,argv);
if (Bt(&Fs->task_flags,TASKf_INPUT_FILTER_TASK))
ExePutS(st);
else
TextInputQue(Fs,0,st,1<<TASKCf_HIGHEST_PRIORITY);
Free(st);
}
U0 AutoFile(U8 *filename)
{
U8 *name2=DftExt(filename,"AUT.Z");
if (Bt(&Fs->task_flags,TASKf_INPUT_FILTER_TASK))
ExeFile(name2);
else
AutoStr("%F",name2);
Free(name2);
}
//This sends text of an AutoFile nature to a
//task's input buffer.
U0 XTalkStr(CTask *task,U8 *fmt,...)
{
U8 *st=SPrintFJoin(NULL,fmt,argc,argv);
TextInputQue(task,0,st,0);
Free(st);
}
U0 XTalkStrWait(CTask *task,U8 *fmt,...)
{
U8 *st=SPrintFJoin(NULL,fmt,argc,argv);
TextInputQue(task,0,st,0);
Free(st);
TaskWait(task);
}
+330
View File
@@ -0,0 +1,330 @@
asm {
USE64
// ************************************
_MEMCMP::
ENTER 0
PUSH RSI
PUSH RDI
MOV RSI,U64 SF_ARG1[RBP]
MOV RDI,U64 SF_ARG2[RBP]
MOV RCX,U64 SF_ARG3[RBP]
XOR RAX,RAX
REPE_CMPSB
JZ @@05
MOV AL,1
JA @@05
MOV RAX,-1
@@05: POP RDI
POP RSI
LEAVE
RET1 24
// ************************************
_CALL::
ENTER 0
MOV RAX,U64 SF_ARG1[RBP]
OR RAX,RAX
JZ @@05
CALL RAX
@@05: LEAVE
RET1 8
// ************************************
_BIT_FIELD_OR_U32::
ENTER 0
MOV RBX,U64 SF_ARG2[RBP]
SHR RBX,3
ADD RBX,U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG3[RBP]
MOV RCX,U64 SF_ARG2[RBP]
AND CL,7
SHL RAX,CL
OR U64 [RBX],RAX
LEAVE
RET1 24
// ************************************
_BIT_FIELD_EXTRACT_U32::
ENTER 0
MOV RBX,U64 SF_ARG2[RBP]
MOV RCX,RBX
SHR RBX,3
ADD RBX,U64 SF_ARG1[RBP]
MOV RDX,U64 [RBX]
AND CL,7
SHR RDX,CL
MOV RCX,U64 SF_ARG3[RBP]
MOV RAX,1
SHL RAX,CL
DEC RAX
AND RAX,RDX
LEAVE
RET1 24
// ************************************
_XCHG_U64::
ENTER 0
MOV RDX,U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG2[RBP]
XCHG U64 [RDX],RAX
LEAVE
RET1 16
_XCHG_U32::
ENTER 0
MOV RDX,U64 SF_ARG1[RBP]
MOV EAX,U32 SF_ARG2[RBP]
XCHG U32 [RDX],EAX
LEAVE
RET1 16
_XCHG_U16::
ENTER 0
MOV RDX,U64 SF_ARG1[RBP]
MOVZX RAX,U16 SF_ARG2[RBP]
XCHG U16 [RDX],AX
LEAVE
RET1 16
_XCHG_U8::
ENTER 0
MOV RDX,U64 SF_ARG1[RBP]
MOVZX RAX,U8 SF_ARG2[RBP]
XCHG U8 [RDX],AL
LEAVE
RET1 16
_LXCHG_U64::
ENTER 0
MOV RDX,U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG2[RBP]
LOCK
XCHG U64 [RDX],RAX
LEAVE
RET1 16
_LXCHG_U32::
ENTER 0
MOV RDX,U64 SF_ARG1[RBP]
MOV EAX,U32 SF_ARG2[RBP]
LOCK
XCHG U32 [RDX],EAX
LEAVE
RET1 16
_LXCHG_U16::
ENTER 0
MOV RDX,U64 SF_ARG1[RBP]
MOVZX RAX,U16 SF_ARG2[RBP]
LOCK
XCHG U16 [RDX],AX
LEAVE
RET1 16
_LXCHG_U8::
ENTER 0
MOV RDX,U64 SF_ARG1[RBP]
MOVZX RAX,U8 SF_ARG2[RBP]
LOCK
XCHG U8 [RDX],AL
LEAVE
RET1 16
// ************************************
_REP_IN_U32::
ENTER 0
PUSH RDI
MOV RDI,U64 SF_ARG1[RBP]
MOV RDX,U64 SF_ARG3[RBP]
MOV RCX,U64 SF_ARG2[RBP]
REP_INSD
POP RDI
LEAVE
RET1 24
_REP_IN_U16::
ENTER 0
PUSH RDI
MOV RDI,U64 SF_ARG1[RBP]
MOV RDX,U64 SF_ARG3[RBP]
MOV RCX,U64 SF_ARG2[RBP]
REP_INSW
POP RDI
LEAVE
RET1 24
_REP_IN_U8::
ENTER 0
PUSH RDI
MOV RDI,U64 SF_ARG1[RBP]
MOV RDX,U64 SF_ARG3[RBP]
MOV RCX,U64 SF_ARG2[RBP]
REP_INSB
POP RDI
LEAVE
RET1 24
_REP_OUT_U32::
ENTER 0
PUSH RSI
MOV RSI,U64 SF_ARG1[RBP]
MOV RDX,U64 SF_ARG3[RBP]
MOV RCX,U64 SF_ARG2[RBP]
REP_OUTSD
POP RSI
LEAVE
RET1 24
_REP_OUT_U16::
ENTER 0
PUSH RSI
MOV RSI,U64 SF_ARG1[RBP]
MOV RDX,U64 SF_ARG3[RBP]
MOV RCX,U64 SF_ARG2[RBP]
REP_OUTSW
POP RSI
LEAVE
RET1 24
_REP_OUT_U8::
ENTER 0
PUSH RSI
MOV RSI,U64 SF_ARG1[RBP]
MOV RDX,U64 SF_ARG3[RBP]
MOV RCX,U64 SF_ARG2[RBP]
REP_OUTSB
POP RSI
LEAVE
RET1 24
// ************************************
_CPUID::
ENTER 0
PUSH RSI
MOV RAX,U64 SF_ARG1[RBP]
CPUID
MOV RSI,U64 SF_ARG2[RBP]
MOV U64 [RSI],RAX
MOV U64 8[RSI],RBX
MOV U64 16[RSI],RCX
MOV U64 24[RSI],RDX
POP RSI
LEAVE
RET1 16
// ************************************
_CALLIND::
ENTER 0
PUSH RSI
PUSH RDI
MOV RDX,U64 SF_ARG1[RBP]
MOV RCX,U64 SF_ARG2[RBP] //argc
LEA RSI,U64 SF_ARG3[RBP] //argv
SHL RCX,3
SUB RSP,RCX
MOV RDI,RSP
REP_MOVSB
@@05: OR RDX,RDX
JZ @@15
CALL RDX
@@10: POP RDI
POP RSI
LEAVE
RET
@@15: XOR RAX,RAX
MOV RCX,U64 SF_ARG2[RBP] //argc
SHL RCX,3
ADD RSP,RCX
POP RDI
POP RSI
LEAVE
RET
// ************************************
_CALLEXTNUM::
ENTER 0
PUSH RSI
PUSH RDI
MOV RDX,U64 SF_ARG1[RBP]
MOV RCX,U64 SF_ARG2[RBP] //argc
LEA RSI,U64 SF_ARG3[RBP] //argv
SHL RCX,3
SUB RSP,RCX
MOV RDI,RSP
REP_MOVSB
@@05: MOV RAX,U64 [SYS_EXTERN_TABLE]
MOV RAX,U64 [RAX+RDX*8]
OR RAX,RAX
JZ @@15
CALL RAX
@@10: POP RDI
POP RSI
LEAVE
RET
@@15: XOR RAX,RAX
MOV RCX,U64 SF_ARG2[RBP] //argc
SHL RCX,3
ADD RSP,RCX
POP RDI
POP RSI
LEAVE
RET
// ************************************
_CALLEXTSTR::
ENTER 0
PUSH RSI
PUSH RDI
MOV RCX,U64 SF_ARG2[RBP] //argc
LEA RSI,U64 SF_ARG3[RBP] //argv
SHL RCX,3
SUB RSP,RCX
MOV RDI,RSP
REP_MOVSB
@@05: MOV RSI,U64 SF_ARG1[RBP]
CALL SYS_EXT_FIND1
OR RAX,RAX
JZ @@15
CALL RAX
@@10: POP RDI
POP RSI
LEAVE
RET
@@15: MOV RCX,U64 SF_ARG2[RBP] //argc
SHL RCX,3
ADD RSP,RCX
POP RDI
POP RSI
LEAVE
RET
// ************************************
_SET_GS_BASE::
ENTER 0
MOV RAX,SF_ARG1[RBP]
PUSH RAX
PUSH RCX
PUSH RDX
MOV RDX,RAX
SHR RDX,32
MOV ECX,IA32_GS_BASE
WRMSR
POP RDX
POP RCX
POP RAX
LEAVE
RET1 8
SET_FS_BASE::
PUSH RAX
PUSH RCX
PUSH RDX
MOV RDX,RAX
SHR RDX,32
MOV ECX,IA32_FS_BASE
WRMSR
POP RDX
POP RCX
POP RAX
RET
_SET_MSR::
ENTER 0
MOV RAX,SF_ARG2[RBP]
MOV RDX,RAX
SHR RDX,32
MOV RCX,SF_ARG1[RBP]
WRMSR
LEAVE
RET1 16
_SYS_HLT::
CLI
@@05: HLT
JMP @@05
}