diff --git a/docs/config.txt b/docs/config.txt index b1f6a4c..f018954 100644 --- a/docs/config.txt +++ b/docs/config.txt @@ -125,6 +125,23 @@ A good number is 20, though some programs suggest/require 30, 40, or even 255 e.g. files=20 +IDLEHALT +Usage: idlehalt=n +where n can be -1, 0, 1 or higher (default 0) +Activates built-in kernel energy saving functionality if n is +not 0. Value -1 enables all hooks, 1 enables only "safe" hooks, +CPU halted only if kernel is waiting for CON char device input. +Further hooks for n=-1 and n>0 depend on the kernel version: +In addition to the safe hooks, other hooks can get activated, +for example one for int 0x2f, ax=0x1680 "release time slice". +Note: In rare cases, entering or leaving HLT mode (which causes + big changes in CPU power consumption) can cause crashes if + cheap power supplies or mainboards cannot properly filter + the transients. Underclocking the whole system may help. + Linux always does a few HLT at boot time, to force a hang + on buggy systems early (boot with no-hlt to disable HLT). +P90 may have buggy HLT? www.tavi.co.uk/ps2pages/ohland/halt.html + INSTALL INSTALLHIGH Usage: install=[d:][path]file [options] @@ -135,6 +152,18 @@ to documentation that came with your particular software for supported options and usage. e.g. install=nansi.com +KEYBUF +Usage: keybuf=n[,m] +where n is in 0xac-0xde or 0x106-0x1de range and m is <= 0x200 +Relocate keyboard buffer from the default location at +0x40:0x1e-0x3e to 0x40:n-m. The buffer must be more +than 32 bytes and must not touch offsets 0x100-0x105. +Default for m is "next multiple of 0x100 after n". +Note: Some BIOSes store data in the 0xac-0xff area. BASICA will + use the 0x106-0x120 area. Other hardware, drivers or apps + can collide with KEYBUF, too, so use it at your own risk. +A reasonably safe choice should be "keybuf=0x140,0x1c0". + LASTDRIVE LASTDRIVEHIGH Usage: lastdrive=x diff --git a/kernel/config.c b/kernel/config.c index e469fe0..19bc6ff 100644 --- a/kernel/config.c +++ b/kernel/config.c @@ -180,6 +180,7 @@ STATIC VOID DeviceHigh(BYTE * pLine); STATIC VOID Files(BYTE * pLine); STATIC VOID FilesHigh(BYTE * pLine); STATIC VOID Fcbs(BYTE * pLine); +STATIC VOID CfgKeyBuf(BYTE * pLine); STATIC VOID CfgLastdrive(BYTE * pLine); STATIC VOID CfgLastdriveHigh(BYTE * pLine); STATIC BOOL LoadDevice(BYTE * pLine, char FAR *top, COUNT mode); @@ -218,6 +219,7 @@ STATIC VOID Stacks(BYTE * pLine); STATIC VOID StacksHigh(BYTE * pLine); STATIC VOID SetAnyDos(BYTE * pLine); +STATIC VOID SetIdleHalt(BYTE * pLine); STATIC VOID Numlock(BYTE * pLine); STATIC BYTE * GetNumArg(BYTE * pLine, COUNT * pnArg); BYTE *GetStringArg(BYTE * pLine, BYTE * pszString); @@ -274,6 +276,7 @@ STATIC struct table commands[] = { {"DOS", 1, Dosmem}, {"DOSDATA", 1, DosData}, {"FCBS", 1, Fcbs}, + {"KEYBUF", 1, CfgKeyBuf}, /* ea */ {"FILES", 1, Files}, {"FILESHIGH", 1, FilesHigh}, {"LASTDRIVE", 1, CfgLastdrive}, @@ -287,6 +290,7 @@ STATIC struct table commands[] = { {"SCREEN", 1, sysScreenMode}, /* JPP */ {"VERSION", 1, sysVersion}, /* JPP */ {"ANYDOS", 1, SetAnyDos}, /* tom */ + {"IDLEHALT", 1, SetIdleHalt}, /* ea */ {"DEVICE", 2, Device}, {"DEVICEHIGH", 2, DeviceHigh}, @@ -740,7 +744,6 @@ STATIC struct table * LookUp(struct table *p, BYTE * token) 0xHH.. : scancode in upper half 0x..LL : asciicode in lower half */ - #define GetBiosTime() peekl(0, 0x46c) UWORD GetBiosKey(int timeout) @@ -757,12 +760,17 @@ UWORD GetBiosKey(int timeout) init_call_intr(0x16, &r); if (!(r.flags & FLG_ZERO)) return r.a.x; - } - while ((unsigned)(GetBiosTime() - startTime) < timeout * 18u); + if (HaltCpuWhileIdle!=0) DosIdle_hlt(); /* not _int */ + } while ((unsigned)(GetBiosTime() - startTime) < timeout * 18u); return 0xffff; } /* blocking wait (timeout < 0): fetch it */ + do { + if (HaltCpuWhileIdle!=0) DosIdle_hlt(); /* not _int */ + r.a.x = 0x0100; + init_call_intr(0x16, &r); + } while (r.flags & FLG_ZERO); r.a.x = 0x0000; init_call_intr(0x16, &r); return r.a.x; @@ -1153,6 +1161,48 @@ STATIC VOID Fcbs(BYTE * pLine) Config.cfgProtFcbs = Config.cfgFcbs; } +/* + Keyboard buffer relocation: KEYBUF=start[,end] + Select a new location for the keyboard buffer at 0x40:xx, + for example 0x40:0xac-0xff, but 0x50:5-0xff ("basica" only?) + feels safer? 0x60:0-0xff is scratch, we use it as SHELL PSP. + (sys / boot sector load_segment / LOADSEG, exeflat call in + makefile, DOS_PSP in mcb.h, main.c P_0, task.c, kernel.asm) + (50:e0..ff used as early kernel boot drive / config buffer) +*/ +STATIC VOID CfgKeyBuf(BYTE * pLine) +{ + /* Format: KEYBUF = startoffset [,endoffset] */ + UWORD FAR *keyfill = (UWORD FAR *) MK_FP(0x40, 0x1a); + UWORD FAR *keyrange = (UWORD FAR *) MK_FP(0x40, 0x80); + COUNT startbuf, endbuf; + + if ((pLine = GetNumArg(pLine, &startbuf)) == 0) + return; + pLine = skipwh(pLine); + endbuf = (startbuf | 0xff)+1; /* default end: end of the same "page" */ + if (*pLine == ',') + { + if ((pLine = GetNumArg(++pLine, &endbuf)) == 0) + return; + } + startbuf &= 0xfffe; + endbuf &= 0xfffe; + if (endbuf=0x100 && startbuf<0x105) || startbuf>0x1de) + { /* 50:0 / 50:4 are for prtscr / A:/B: DJ */ + printf("Must start at 0xac..0x1de, not 0x100..0x104\n"); + return; + } + keyfill[0] = startbuf; + keyfill[1] = startbuf; + keyrange[0] = startbuf; + keyrange[1] = endbuf; + keycheck(); +} + /* LoadCountryInfo(): * Searches a file in the COUNTRY.SYS format for an entry * matching the specified code page and country code, and loads @@ -1161,7 +1211,6 @@ STATIC VOID Fcbs(BYTE * pLine) * * Returns TRUE if successful, FALSE if not. */ - #if 0 STATIC BOOL LoadCountryInfo(char *filename, UWORD ctryCode, UWORD codePage) { @@ -1744,29 +1793,36 @@ STATIC void config_init_fnodes(int f_nodes_cnt) } /* - Undocumented feature: - - ANYDOS + Undocumented feature: ANYDOS will report to MSDOS programs just the version number they expect. be careful with it! */ - STATIC VOID SetAnyDos(BYTE * pLine) { UNREFERENCED_PARAMETER(pLine); ReturnAnyDosVersionExpected = TRUE; } +/* + Kernel built-in energy saving: IDLEHALT=haltlevel + -1 max savings, 0 never HLT, 1 safe kernel only HLT, + 2 (3) also hooks int2f.1680 (and sets al=0) +*/ +STATIC VOID SetIdleHalt(BYTE * pLine) +{ + COUNT haltlevel; + if (GetNumArg(pLine, &haltlevel)) + HaltCpuWhileIdle = haltlevel; /* 0 for no HLT, 1..n more, -1 max */ +} + STATIC VOID CfgIgnore(BYTE * pLine) { UNREFERENCED_PARAMETER(pLine); } /* - 'MENU'ing stuff - - although it's worse then MSDOS's , its better then nothing - + 'MENU'ing stuff + although it's worse then MSDOS's , its better then nothing */ STATIC void ClearScreen(unsigned char attr); diff --git a/kernel/dosidle.asm b/kernel/dosidle.asm index aa5326d..f62014e 100644 --- a/kernel/dosidle.asm +++ b/kernel/dosidle.asm @@ -34,17 +34,32 @@ PSP_USERSS equ 30h segment HMA_TEXT global _DosIdle_int - + global _DosIdle_hlt extern _InDOS:wrt DGROUP extern _cu_psp:wrt DGROUP extern _MachineId:wrt DGROUP extern critical_sp:wrt DGROUP extern _user_r:wrt DGROUP + ; variables as the following are "part of" module inthndlr.c + ; because of the define MAIN before include globals.h there! + extern _HaltCpuWhileIdle:wrt DGROUP extern _DGROUP_:wrt HMA_TEXT ; +_DosIdle_hlt: + push ds + mov ds, [cs:_DGROUP_] + cmp byte [_HaltCpuWhileIdle],1 + jb DosId0 + pushf + sti + hlt ; save some energy :-) + popf +DosId0: pop ds + retn ; _DosIdle_int: + call _DosIdle_hlt push ds mov ds, [cs:_DGROUP_] cmp byte [_InDOS],1 @@ -76,3 +91,6 @@ Do_DosI: pop ax ret +; segment _DATA ; belongs to DGROUP +; whatever db whatever + diff --git a/kernel/globals.h b/kernel/globals.h index 5f2f8d1..6087deb 100644 --- a/kernel/globals.h +++ b/kernel/globals.h @@ -229,7 +229,7 @@ Freeman Publishing, Lawrence KS, USA (ISBN 0-87930-436-7).\n\ ; /* Globally referenced variables - WARNING: ORDER IS DEFINED IN */ -/* KERNAL.ASM AND MUST NOT BE CHANGED. DO NOT CHANGE ORDER BECAUSE THEY */ +/* KERNEL.ASM AND MUST NOT BE CHANGED. DO NOT CHANGE ORDER BECAUSE THEY */ /* ARE DOCUMENTED AS UNDOCUMENTED (?) AND HAVE MANY PROGRAMS AND TSRs */ /* ACCESSING THEM */ @@ -420,8 +420,10 @@ void setvec(unsigned char intno, intvec vector); #pragma aux (cdecl) spawn_int23 aborts; #endif void ASMCFUNC spawn_int23(void); /* procsupt.asm */ +void ASMCFUNC DosIdle_hlt(void); /* dosidle.asm */ GLOBAL BYTE ReturnAnyDosVersionExpected; +GLOBAL BYTE HaltCpuWhileIdle; GLOBAL struct f_node fnode[2]; GLOBAL int fnode_fd[2]; diff --git a/kernel/init-mod.h b/kernel/init-mod.h index 8256604..e97c0f0 100644 --- a/kernel/init-mod.h +++ b/kernel/init-mod.h @@ -155,6 +155,9 @@ unsigned init_oem(void); void movebda(size_t bytes, unsigned new_seg); unsigned ebdasize(void); +/* dosidle.asm */ +extern void ASM DosIdle_hlt(VOID); + /* intr.asm */ /* @@ -257,7 +260,8 @@ extern BYTE DOSFAR ASM _HMATextAvailable, /* first byte of available CODE are FAR ASM _HMATextStart[], /* first byte of HMAable CODE area */ FAR ASM _HMATextEnd[], DOSFAR ASM break_ena; /* break enabled flag */ extern BYTE DOSFAR _InitTextStart, /* first available byte of ram */ - DOSFAR ReturnAnyDosVersionExpected; + DOSFAR ReturnAnyDosVersionExpected, + DOSFAR HaltCpuWhileIdle; extern BYTE FAR ASM internal_data[]; extern unsigned char FAR ASM kbdType; diff --git a/kernel/int2f.asm b/kernel/int2f.asm index 42465a8..b84c972 100644 --- a/kernel/int2f.asm +++ b/kernel/int2f.asm @@ -28,11 +28,12 @@ ; $Id$ ; - %include "segs.inc" + %include "segs.inc" %include "stacks.inc" segment HMA_TEXT - extern _cu_psp:wrt DGROUP + extern _cu_psp:wrt DGROUP + extern _HaltCpuWhileIdle:wrt DGROUP extern _syscall_MUX14 extern _DGROUP_ @@ -53,9 +54,29 @@ Int2f2: stc FarTabRetn: retf 2 ; Return far -Int2f3: + +WinIdle: ; only HLT if at haltlevel 2+ + push ds + mov ds, [cs:_DGROUP_] + cmp byte [_HaltCpuWhileIdle],2 + pop ds + jb FarTabRetn + pushf + sti + hlt ; save some energy :-) + popf + push ds + mov ds, [cs:_DGROUP_] + cmp byte [_HaltCpuWhileIdle],3 + pop ds + jb FarTabRetn + mov al,0 ; even admit we HLTed ;-) + jmp short FarTabRetn + +Int2f3: cmp ax,1680h ; Win "release time slice" + je WinIdle cmp ah,16h - je FarTabRetn ; Win Hook return fast + je FarTabRetn ; other Win Hook return fast cmp ah,12h je IntDosCal ; Dos Internal calls diff --git a/kernel/proto.h b/kernel/proto.h index 639865e..029d879 100644 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -120,10 +120,12 @@ int get_sft_idx(UCOUNT hndl); struct cds FAR *get_cds(unsigned dsk); COUNT DosTruename(const char FAR * src, char FAR * dest); -/*dosidle.asm */ +/* dosidle.asm */ VOID ASMCFUNC DosIdle_int(void); +VOID ASMCFUNC DosIdle_hlt(void); #ifdef __WATCOMC__ #pragma aux (cdecl) DosIdle_int modify exact [] +#pragma aux (cdecl) DosIdle_hlt modify exact [] #endif /* dosnames.c */