New config.sys (config.c, config.txt) options: IDLEHALT=n to activate

"HLT on idle" (dosidle.asm, int2f.asm) and KEYBUF=n[,m] to relocate
the keyboard buffer to another area in the 40:ac..40:1ff range. Global
functions and variables: proto.h DosIdle_hlt, init-mod.h and globals.h
DosIdle_hlt() and HaltCpuWhileIdle.


git-svn-id: https://svn.code.sf.net/p/freedos/svn/kernel/trunk@1339 6ac86273-5f31-0410-b378-82cca8765d1b
This commit is contained in:
Eric Auer 2007-07-21 03:37:53 +00:00
parent cf05259924
commit 1e5efe260e
7 changed files with 152 additions and 20 deletions

View File

@ -125,6 +125,23 @@ A good number is 20, though some programs suggest/require
30, 40, or even 255 30, 40, or even 255
e.g. files=20 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 INSTALL
INSTALLHIGH INSTALLHIGH
Usage: install=[d:][path]file [options] Usage: install=[d:][path]file [options]
@ -135,6 +152,18 @@ to documentation that came with your particular software for
supported options and usage. supported options and usage.
e.g. install=nansi.com 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 LASTDRIVE
LASTDRIVEHIGH LASTDRIVEHIGH
Usage: lastdrive=x Usage: lastdrive=x

View File

@ -180,6 +180,7 @@ STATIC VOID DeviceHigh(BYTE * pLine);
STATIC VOID Files(BYTE * pLine); STATIC VOID Files(BYTE * pLine);
STATIC VOID FilesHigh(BYTE * pLine); STATIC VOID FilesHigh(BYTE * pLine);
STATIC VOID Fcbs(BYTE * pLine); STATIC VOID Fcbs(BYTE * pLine);
STATIC VOID CfgKeyBuf(BYTE * pLine);
STATIC VOID CfgLastdrive(BYTE * pLine); STATIC VOID CfgLastdrive(BYTE * pLine);
STATIC VOID CfgLastdriveHigh(BYTE * pLine); STATIC VOID CfgLastdriveHigh(BYTE * pLine);
STATIC BOOL LoadDevice(BYTE * pLine, char FAR *top, COUNT mode); 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 StacksHigh(BYTE * pLine);
STATIC VOID SetAnyDos(BYTE * pLine); STATIC VOID SetAnyDos(BYTE * pLine);
STATIC VOID SetIdleHalt(BYTE * pLine);
STATIC VOID Numlock(BYTE * pLine); STATIC VOID Numlock(BYTE * pLine);
STATIC BYTE * GetNumArg(BYTE * pLine, COUNT * pnArg); STATIC BYTE * GetNumArg(BYTE * pLine, COUNT * pnArg);
BYTE *GetStringArg(BYTE * pLine, BYTE * pszString); BYTE *GetStringArg(BYTE * pLine, BYTE * pszString);
@ -274,6 +276,7 @@ STATIC struct table commands[] = {
{"DOS", 1, Dosmem}, {"DOS", 1, Dosmem},
{"DOSDATA", 1, DosData}, {"DOSDATA", 1, DosData},
{"FCBS", 1, Fcbs}, {"FCBS", 1, Fcbs},
{"KEYBUF", 1, CfgKeyBuf}, /* ea */
{"FILES", 1, Files}, {"FILES", 1, Files},
{"FILESHIGH", 1, FilesHigh}, {"FILESHIGH", 1, FilesHigh},
{"LASTDRIVE", 1, CfgLastdrive}, {"LASTDRIVE", 1, CfgLastdrive},
@ -287,6 +290,7 @@ STATIC struct table commands[] = {
{"SCREEN", 1, sysScreenMode}, /* JPP */ {"SCREEN", 1, sysScreenMode}, /* JPP */
{"VERSION", 1, sysVersion}, /* JPP */ {"VERSION", 1, sysVersion}, /* JPP */
{"ANYDOS", 1, SetAnyDos}, /* tom */ {"ANYDOS", 1, SetAnyDos}, /* tom */
{"IDLEHALT", 1, SetIdleHalt}, /* ea */
{"DEVICE", 2, Device}, {"DEVICE", 2, Device},
{"DEVICEHIGH", 2, DeviceHigh}, {"DEVICEHIGH", 2, DeviceHigh},
@ -740,7 +744,6 @@ STATIC struct table * LookUp(struct table *p, BYTE * token)
0xHH.. : scancode in upper half 0xHH.. : scancode in upper half
0x..LL : asciicode in lower half 0x..LL : asciicode in lower half
*/ */
#define GetBiosTime() peekl(0, 0x46c) #define GetBiosTime() peekl(0, 0x46c)
UWORD GetBiosKey(int timeout) UWORD GetBiosKey(int timeout)
@ -757,12 +760,17 @@ UWORD GetBiosKey(int timeout)
init_call_intr(0x16, &r); init_call_intr(0x16, &r);
if (!(r.flags & FLG_ZERO)) if (!(r.flags & FLG_ZERO))
return r.a.x; return r.a.x;
} if (HaltCpuWhileIdle!=0) DosIdle_hlt(); /* not _int */
while ((unsigned)(GetBiosTime() - startTime) < timeout * 18u); } while ((unsigned)(GetBiosTime() - startTime) < timeout * 18u);
return 0xffff; return 0xffff;
} }
/* blocking wait (timeout < 0): fetch it */ /* 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; r.a.x = 0x0000;
init_call_intr(0x16, &r); init_call_intr(0x16, &r);
return r.a.x; return r.a.x;
@ -1153,6 +1161,48 @@ STATIC VOID Fcbs(BYTE * pLine)
Config.cfgProtFcbs = Config.cfgFcbs; 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<startbuf || (endbuf-startbuf)<=0x20 ||
((startbuf & 0xff00) != ((endbuf-1) & 0xff00)) )
startbuf = 0; /* flag as bad: too small or page wrap */
if (startbuf<0xac || (startbuf>=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(): /* LoadCountryInfo():
* Searches a file in the COUNTRY.SYS format for an entry * Searches a file in the COUNTRY.SYS format for an entry
* matching the specified code page and country code, and loads * 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. * Returns TRUE if successful, FALSE if not.
*/ */
#if 0 #if 0
STATIC BOOL LoadCountryInfo(char *filename, UWORD ctryCode, UWORD codePage) STATIC BOOL LoadCountryInfo(char *filename, UWORD ctryCode, UWORD codePage)
{ {
@ -1744,29 +1793,36 @@ STATIC void config_init_fnodes(int f_nodes_cnt)
} }
/* /*
Undocumented feature: Undocumented feature: ANYDOS
ANYDOS
will report to MSDOS programs just the version number will report to MSDOS programs just the version number
they expect. be careful with it! they expect. be careful with it!
*/ */
STATIC VOID SetAnyDos(BYTE * pLine) STATIC VOID SetAnyDos(BYTE * pLine)
{ {
UNREFERENCED_PARAMETER(pLine); UNREFERENCED_PARAMETER(pLine);
ReturnAnyDosVersionExpected = TRUE; 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) STATIC VOID CfgIgnore(BYTE * pLine)
{ {
UNREFERENCED_PARAMETER(pLine); UNREFERENCED_PARAMETER(pLine);
} }
/* /*
'MENU'ing stuff 'MENU'ing stuff
although it's worse then MSDOS's , its better then nothing
although it's worse then MSDOS's , its better then nothing
*/ */
STATIC void ClearScreen(unsigned char attr); STATIC void ClearScreen(unsigned char attr);

View File

@ -34,17 +34,32 @@ PSP_USERSS equ 30h
segment HMA_TEXT segment HMA_TEXT
global _DosIdle_int global _DosIdle_int
global _DosIdle_hlt
extern _InDOS:wrt DGROUP extern _InDOS:wrt DGROUP
extern _cu_psp:wrt DGROUP extern _cu_psp:wrt DGROUP
extern _MachineId:wrt DGROUP extern _MachineId:wrt DGROUP
extern critical_sp:wrt DGROUP extern critical_sp:wrt DGROUP
extern _user_r: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 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: _DosIdle_int:
call _DosIdle_hlt
push ds push ds
mov ds, [cs:_DGROUP_] mov ds, [cs:_DGROUP_]
cmp byte [_InDOS],1 cmp byte [_InDOS],1
@ -76,3 +91,6 @@ Do_DosI:
pop ax pop ax
ret ret
; segment _DATA ; belongs to DGROUP
; whatever db whatever

View File

@ -229,7 +229,7 @@ Freeman Publishing, Lawrence KS, USA (ISBN 0-87930-436-7).\n\
; ;
/* Globally referenced variables - WARNING: ORDER IS DEFINED IN */ /* 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 */ /* ARE DOCUMENTED AS UNDOCUMENTED (?) AND HAVE MANY PROGRAMS AND TSRs */
/* ACCESSING THEM */ /* ACCESSING THEM */
@ -420,8 +420,10 @@ void setvec(unsigned char intno, intvec vector);
#pragma aux (cdecl) spawn_int23 aborts; #pragma aux (cdecl) spawn_int23 aborts;
#endif #endif
void ASMCFUNC spawn_int23(void); /* procsupt.asm */ void ASMCFUNC spawn_int23(void); /* procsupt.asm */
void ASMCFUNC DosIdle_hlt(void); /* dosidle.asm */
GLOBAL BYTE ReturnAnyDosVersionExpected; GLOBAL BYTE ReturnAnyDosVersionExpected;
GLOBAL BYTE HaltCpuWhileIdle;
GLOBAL struct f_node fnode[2]; GLOBAL struct f_node fnode[2];
GLOBAL int fnode_fd[2]; GLOBAL int fnode_fd[2];

View File

@ -155,6 +155,9 @@ unsigned init_oem(void);
void movebda(size_t bytes, unsigned new_seg); void movebda(size_t bytes, unsigned new_seg);
unsigned ebdasize(void); unsigned ebdasize(void);
/* dosidle.asm */
extern void ASM DosIdle_hlt(VOID);
/* intr.asm */ /* 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 _HMATextStart[], /* first byte of HMAable CODE area */
FAR ASM _HMATextEnd[], DOSFAR ASM break_ena; /* break enabled flag */ FAR ASM _HMATextEnd[], DOSFAR ASM break_ena; /* break enabled flag */
extern BYTE DOSFAR _InitTextStart, /* first available byte of ram */ extern BYTE DOSFAR _InitTextStart, /* first available byte of ram */
DOSFAR ReturnAnyDosVersionExpected; DOSFAR ReturnAnyDosVersionExpected,
DOSFAR HaltCpuWhileIdle;
extern BYTE FAR ASM internal_data[]; extern BYTE FAR ASM internal_data[];
extern unsigned char FAR ASM kbdType; extern unsigned char FAR ASM kbdType;

View File

@ -28,11 +28,12 @@
; $Id$ ; $Id$
; ;
%include "segs.inc" %include "segs.inc"
%include "stacks.inc" %include "stacks.inc"
segment HMA_TEXT segment HMA_TEXT
extern _cu_psp:wrt DGROUP extern _cu_psp:wrt DGROUP
extern _HaltCpuWhileIdle:wrt DGROUP
extern _syscall_MUX14 extern _syscall_MUX14
extern _DGROUP_ extern _DGROUP_
@ -53,9 +54,29 @@ Int2f2:
stc stc
FarTabRetn: FarTabRetn:
retf 2 ; Return far 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 cmp ah,16h
je FarTabRetn ; Win Hook return fast je FarTabRetn ; other Win Hook return fast
cmp ah,12h cmp ah,12h
je IntDosCal ; Dos Internal calls je IntDosCal ; Dos Internal calls

View File

@ -120,10 +120,12 @@ int get_sft_idx(UCOUNT hndl);
struct cds FAR *get_cds(unsigned dsk); struct cds FAR *get_cds(unsigned dsk);
COUNT DosTruename(const char FAR * src, char FAR * dest); COUNT DosTruename(const char FAR * src, char FAR * dest);
/*dosidle.asm */ /* dosidle.asm */
VOID ASMCFUNC DosIdle_int(void); VOID ASMCFUNC DosIdle_int(void);
VOID ASMCFUNC DosIdle_hlt(void);
#ifdef __WATCOMC__ #ifdef __WATCOMC__
#pragma aux (cdecl) DosIdle_int modify exact [] #pragma aux (cdecl) DosIdle_int modify exact []
#pragma aux (cdecl) DosIdle_hlt modify exact []
#endif #endif
/* dosnames.c */ /* dosnames.c */