Index: hdr/debug.h =================================================================== RCS file: /cvsroot/freedos/kernel/hdr/Attic/debug.h,v retrieving revision 1.1.2.3 diff -u -3 -r1.1.2.3 debug.h --- hdr/debug.h 30 Jan 2005 14:05:44 -0000 1.1.2.3 +++ hdr/debug.h 13 Feb 2005 10:29:59 -0000 @@ -36,8 +36,14 @@ NOTE: this file included by INIT time code and normal resident code, so use care for all memory references */ - - + +/* allow output even in non-debug builds */ +#if 1 +#ifndef DEBUG_NEED_PRINTF +#define DEBUG_NEED_PRINTF +#endif +#endif + /* use to limit output to debug builds */ #ifdef DEBUG #define DebugPrintf(x) printf x @@ -92,9 +98,12 @@ #define FDirDbgPrintf(x) #endif -/* extra debug output marking sections */ +/* extra debug output when transferring I/O chunks of data */ /* #define DISPLAY_GETBLOCK */ +/* extra output during read/write operations */ +/* #define DSK_DEBUG */ + /* display info on various FAT handling functions (fatfs.c) */ /* #define DEBUGFATFS */ #ifdef DEBUGFATFS @@ -103,6 +112,14 @@ #define FatFSDbgPrintf(x) #endif +/* debug truename */ +/* #define DEBUG_TRUENAME */ +#ifdef DEBUG_TRUENAME +#define tn_printf(x) printf x +#else +#define tn_printf(x) +#endif + /* just to be sure printf is declared */ #if defined(DEBUG) || defined(DEBUGIRQ) || defined(DEBUGCFG) || \ @@ -110,8 +127,11 @@ defined(DEBUGFATDIR) || defined(DEBUGFATFS) #ifndef DEBUG_NEED_PRINTF #define DEBUG_NEED_PRINTF -VOID VA_CDECL printf(const char * fmt, ...); #endif #endif +#ifdef DEBUG_NEED_PRINTF +VOID VA_CDECL printf(const char * fmt, ...); +#endif + #endif /* __DEBUG_H */ Index: kernel/entry.asm =================================================================== RCS file: /cvsroot/freedos/kernel/kernel/entry.asm,v retrieving revision 1.27.2.3 diff -u -3 -r1.27.2.3 entry.asm --- kernel/entry.asm 11 Jan 2005 09:10:58 -0000 1.27.2.3 +++ kernel/entry.asm 18 Sep 2005 13:42:59 -0000 @@ -206,6 +206,35 @@ ; int21_handler(iregs UserRegs) ; reloc_call_int21_handler: +%define OEMHANDLER ; enable OEM hook, mostly OEM DOS 2.x, maybe through OEM 6.x +%ifdef OEMHANDLER + extern _OemHook21 + ; When defined and set (!= ffff:ffffh) invoke installed + ; int 21h handler for ah=f9h through ffh + ; with all registers preserved, callee must perform the iret + cmp ah, 0f9h ; if a normal int21 call, proceed + jb skip_oemhndlr ; as quickly as possible + ; we need all registers preserved but also + ; access to the hook address, so we copy locally + ; 1st (while performing check for valid address) + ; then do the jmp + push ds + push dx + mov dx,[cs:_DGROUP_] + mov ds,dx + cmp word [_OemHook21], -1 + je no_oemhndlr + cmp word [_OemHook21+2], -1 + je no_oemhndlr + pop dx + pop ds + jmp far [ds:_OemHook21] ; invoke OEM handler (no return) +;local_hookaddr dd 0 +no_oemhndlr: + pop dx + pop ds +skip_oemhndlr: +%endif ;OEMHANDLER ; ; Create the stack frame for C call. This is done to ; preserve machine state and provide a C structure for @@ -246,7 +275,9 @@ jne int21_1 int21_user: +%IFNDEF WIN31SUPPORT ; begin critical section call dos_crit_sect +%ENDIF ; NOT WIN31SUPPORT push ss push bp @@ -309,15 +340,30 @@ jmp short int21_exit_nodec -int21_2: inc byte [_InDOS] +int21_2: +%IFDEF WIN31SUPPORT ; begin critical section + ; should be called as needed, but we just + ; mark the whole int21 api as critical + push ax + mov ax, 8001h ; Enter Critical Section + int 2ah + pop ax +%ENDIF ; WIN31SUPPORT + inc byte [_InDOS] mov cx,_char_api_tos or ah,ah jz int21_3 +%IFDEF WIN31SUPPORT ; testing, this function call crashes + cmp ah,06h + je int21_3 +%ENDIF ; WIN31SUPPORT cmp ah,0ch jbe int21_normalentry int21_3: +%IFNDEF WIN31SUPPORT ; begin critical section call dos_crit_sect +%ENDIF ; NOT WIN31SUPPORT mov cx,_disk_api_tos int21_normalentry: @@ -337,6 +383,17 @@ call _int21_service int21_exit: dec byte [_InDOS] +%IFDEF WIN31SUPPORT ; end critical section + call dos_crit_sect ; release all critical sections +%if 0 + ; should be called as needed, but we just + ; mark the whole int21 api as critical + push ax + mov ax, 8101h ; Leave Critical Section + int 2ah + pop ax +%endif +%ENDIF ; WIN31SUPPORT ; ; Recover registers from system call. Registers and flags Index: kernel/fatfs.c =================================================================== RCS file: /cvsroot/freedos/kernel/kernel/fatfs.c,v retrieving revision 1.70.2.5 diff -u -3 -r1.70.2.5 fatfs.c --- kernel/fatfs.c 29 Jan 2005 20:33:11 -0000 1.70.2.5 +++ kernel/fatfs.c 17 Sep 2005 01:21:51 -0000 @@ -1833,11 +1833,11 @@ f_node_ptr get_near_f_node(void) { f_node_ptr fnp = fnode; - DebugPrintf(("get_near_f_node: fnp is %p\n", fnp)); + DDebugPrintf(("get_near_f_node: fnp is %p\n", fnp)); if (fnp->f_count && (++fnp)->f_count) panic("more than two near fnodes requested at the same time!\n"); fnp->f_count++; - DebugPrintf(("got near fnode, fnp->f_count=%i\n", fnp->f_count)); + DDebugPrintf(("got near fnode, fnp->f_count=%i\n", fnp->f_count)); return fnp; } Index: kernel/int2f.asm =================================================================== RCS file: /cvsroot/freedos/kernel/kernel/int2f.asm,v retrieving revision 1.34.2.3 diff -u -3 -r1.34.2.3 int2f.asm --- kernel/int2f.asm 31 Jan 2005 04:08:39 -0000 1.34.2.3 +++ kernel/int2f.asm 5 Feb 2005 11:28:34 -0000 @@ -69,6 +69,9 @@ cmp ax,4a33h ; Check DOS version 7 jne Check4Share xor ax,ax ; no undocumented shell strings + xor bx,bx ; RBIL undoc BX = ?? (0h) + ; " DS:DX ASCIIZ shell exe name + ; " DS:SI SHELL= line iret Check4Share: %endif @@ -134,6 +137,28 @@ cld +%IFDEF WIN31SUPPORT ; switch to local stack, no reentrancy support + extern mux2F_stk_top:wrt DGROUP + cli + ; setup, initialize copy + mov si, sp ; ds:si = ss:sp (user stack) + mov ax, ss + mov ds, ax + mov di, mux2F_stk_top-30 ; es:di = local stack-copied chunk + mov es, [cs:_DGROUP_] ; [-X == -(2*cx below+4) ] + mov cx, 13 ; how many words to copy over + ; setup, store original stack pointer + mov [es:di+28], si ; store ss:sp + mov [es:di+26], ds + ; actually switch to local stack + mov ax, es + mov ss, ax + mov sp, di + ; copy over stack data to local stack + rep movsw + sti +%ENDIF ; WIN31SUPPORT + %if XCPU >= 386 %ifdef WATCOM mov si,fs @@ -156,6 +181,24 @@ %endif %endif +%IFDEF WIN31SUPPORT ; switch back to user stack + cli + ; setup, initialize copy + mov si, sp ; ds:si = ss:sp (local stack) + mov ax, ss + mov ds, ax + mov di, [ds:si+28] ; restore original ss:sp + mov es, [ds:si+26] + mov cx, 13 ; how many words to copy over + ; actually switch to user stack + mov ax, es + mov ss, ax + mov sp, di + ; copy over stack data to user stack + rep movsw + sti +%ENDIF ; WIN31SUPPORT + pop es pop ds pop di @@ -165,7 +208,7 @@ pop dx pop cx pop ax - + iret global SHARE_CHECK Index: kernel/inthndlr.c =================================================================== RCS file: /cvsroot/freedos/kernel/kernel/inthndlr.c,v retrieving revision 1.87.2.18 diff -u -3 -r1.87.2.18 inthndlr.c --- kernel/inthndlr.c 31 Jan 2005 04:08:39 -0000 1.87.2.18 +++ kernel/inthndlr.c 18 Sep 2005 14:56:21 -0000 @@ -31,6 +31,8 @@ #include "portab.h" #include "globals.h" #include "nls.h" +#include "debug.h" + #ifdef VERSION_STRINGS BYTE *RcsId = @@ -409,11 +411,11 @@ dispatch: -#ifdef DEBUG +#ifdef DEBUG_0 if (bDumpRegs) { fmemcpy(&error_regs, user_r, sizeof(iregs)); - printf("System call (21h): %02x\n", user_r->AX); + printf("System call (21h): %04x\n", user_r->AX); dump_regs = TRUE; dump(); } @@ -762,6 +764,7 @@ case 0x31: DosMemChange(cu_psp, lr.DX < 6 ? 6 : lr.DX, 0); return_code = lr.AL | 0x300; + printf("ErrorLevel kernel returns is %x(==%x|0x300)\n", (unsigned)return_code, (unsigned)lr.AL); tsr = TRUE; return_user(); break; @@ -1034,6 +1037,7 @@ rc = 0x100; } return_code = lr.AL | rc; + printf("ErrorLevel kernel returns is %x\n", (unsigned)return_code); if (DosMemCheck() != SUCCESS) panic("MCB chain corrupted"); #ifdef TSC @@ -1045,6 +1049,7 @@ /* Get Child-program Return Value */ case 0x4d: lr.AX = return_code; + printf("Child ErrorLevel kernel returns is %x(==%x)\n", (unsigned)return_code, (unsigned)lr.AX); /* needs to be cleared (RBIL) */ return_code = 0; break; @@ -1731,10 +1736,17 @@ else if (r.AH == 0x16) /* Window/Multitasking hooks */ { #ifdef WIN31SUPPORT /* See "DOS Internals" or RBIL under DOSMGR for details */ + if ((r.AL != 0x80) && (r.AL != 0x8F)) { DebugPrintf(("Win API call (2Fh):\n")); } switch (r.AL) { /* default: unhandled requests pass through unchanged */ - #if 0 + #if 1 + case 0x0: /* is Windows active */ + case 0x0A: /* identify Windows version */ + { + /* return AX unchanged if Windows not active */ + break; + } /* 0x0, 0x0A */ case 0x03: /* Windows Get Instance Data */ { /* This should only be called if AX=1607h/BX=15h is not supported. */ @@ -1742,6 +1754,7 @@ can also be in INSTANCE.386 [which in theory means Windows could be updated to support FD kernel without responding to these?]. */ + DebugPrintf(("get instance data\n")); break; } /* 0x03 */ #endif @@ -1763,6 +1776,7 @@ r.BX = FP_OFF(&winStartupInfo); winStartupInfo.winver = r.di; /* match what caller says it is */ winInstanced = 1; /* internal flag marking Windows is active */ + DebugPrintf(("Win startup\n")); break; } /* 0x05 */ case 0x06: /* Windows Exit Broadcast */ @@ -1772,10 +1786,12 @@ Note: If Windows fatally exits then may not be called. */ winInstanced = 0; /* internal flag marking Windows is NOT active */ + DebugPrintf(("Win exit\n")); break; } /* 0x06 */ case 0x07: /* DOSMGR Virtual Device API */ { + DebugPrintf(("Vxd:DOSMGR:%x:%x:%x:%x\n",r.AX,r.BX,r.CX,r.DX)); if (r.BX == 0x15) /* VxD id of "DOSMGR" */ { switch (r.CX) @@ -1791,7 +1807,7 @@ } case 0x01: /* enable Win support, ie patch DOS */ { - /* DOS 5+ return with flags unchanged, Windows critical section + /* DOS 5+ return with bitflags unchanged, Windows critical section needs are handled without need to patch. If this function does not return successfully windows will attempt to do the patching itself (very bad idea). @@ -1810,12 +1826,19 @@ 0010h: notify Windows of logical drive map change ("Insert disk X:") */ r.BX = r.DX; /* sure we support everything asked for, ;-) */ - r.DX = 0xA2AB; /* on succes DS:AX set to A2AB:B97Ch */ + r.DX = 0xA2AB; /* on succes DX:AX set to A2AB:B97Ch */ r.AX = 0xB97C; /* FIXME: do we need to do anything special for FD kernel? */ break; } - /* case 0x02 is below so we can reuse it for 0x05 */ + case 0x02: /* disable Win support, ie remove patches */ + { + /* Note: if we do anything special in 'patch DOS', undo it here. + This is only called when Windows exits, can be ignored. + */ + r.CX = 0; /* for compatibility with MS-DOS 5/6 */ + break; + } case 0x03: /* get internal structure sizes */ { if (r.CX & 0x01) /* size of Current Directory Structure in bytes */ @@ -1839,29 +1862,146 @@ */ r.DX = 0xA2AB; /* on succes DS:AX set to A2AB:B97Ch */ r.AX = 0xB97C; - r.BX = 0x0008; /* our whole data seg is instanced, so - anything within it we assume instanced. */ + r.BX = 0; /* a zero here tells Windows to instance everything */ break; } case 0x05: /* get device driver size */ { + /* On entry ES:DI points to possible device driver + if is not one return with AX=BX=CX=DX=0 + else return BX:CX size in bytes allocated to driver + and DX:AX set to A2AB:B97Ch */ + mcb FAR *smcb = MK_PTR(mcb, (r.ES-1), 0); /* para before is possibly submcb segment */ + /* drivers always start a seg:0 (DI==0), so if not then either + not device driver or duplicate (ie device driver file loaded + is of multi-driver variety; multiple device drivers in same file, + whose memory was allocated as a single chunk) + Drivers don't really have a MCB, instead the DOS MCB is broken + up into submcbs, which will have a type of 'D' (or 'E') + So we check that this is primary segment, a device driver, and owner. + */ + if (!r.DI && (smcb->m_type == 'D') && (smcb->m_psp == r.ES)) + { + ULONG size = smcb->m_size * 16ul; + r.BX = hiword(size); + r.CX = loword(size); + r.DX = 0xA2AB; /* on succes DX:AX set to A2AB:B97Ch */ + r.AX = 0xB97C; + break; + } r.DX = 0; /* we aren't one so return unsupported */ r.AX = 0; r.BX = 0; - /* fall through to set CX=0 and exit */ - } - case 0x02: /* disable Win support, ie remove patches */ - { - /* Note: if we do anything special in 'patch DOS', undo it here. - This is only called when Windows exits, can be ignored. - */ - r.CX = 0; /* for compatibility with MS-DOS 5/6 */ + r.CX = 0; break; } } } + DebugPrintf(("Vxd:DOSMGR:%x:%x:%x:%x\n",r.AX,r.BX,r.CX,r.DX)); break; } /* 0x07 */ + case 0x08: /* Windows Init Complete Broadcast */ + { + DebugPrintf(("Init complete\n")); + break; + } /* 0x08 */ + case 0x09: /* Windows Begin Exit Broadcast */ + { + DebugPrintf(("Exit initiated\n")); + break; + } /* 0x09 */ + case 0x0B: /* Win TSR Identify */ + { + DebugPrintf(("TSR identify request.\n")); + break; + } /* 0x0B */ + case 0x80: /* Win Release Time-slice */ + { + /* This function is generally only called in idle loops */ + enable; /* enable interrupts */ + // __emit__(0xf4); /* halt */ + asm hlt; + r.AX = 0; + /* DebugPrintf(("Release Time Slice\n")); */ + break; + } /* 0x80 */ + case 0x81: /* Win3 Begin Critical Section */ + { + DebugPrintf(("Begin CritSect\n")); + break; + } /* 0x81 */ + case 0x82: /* Win3 End Critical Section */ + { + DebugPrintf(("End CritSect\n")); + break; + } /* 0x82 */ + case 0x8F: /* Win4 Close Awareness */ + { + if (r.DH != 0x01) /* query close */ + r.AX = 0x0; + /* else r.AX = 0x168F; don't close -- continue execution */ + break; + } /* 0x8F */ + default: + #ifdef DEBUG + if (r.AL < 0x10) + { + DebugPrintf(("AL<10h\n")); + if (r.AL == 0x0) DebugPrintf(("0\n")); + if (r.AL == 0x1) DebugPrintf(("1\n")); + if (r.AL == 0x2) DebugPrintf(("2\n")); + if (r.AL == 0x3) DebugPrintf(("3\n")); + if (r.AL == 0x4) DebugPrintf(("4\n")); + if (r.AL == 0xa) DebugPrintf(("a\n")); + if (r.AL == 0xc) DebugPrintf(("c\n")); + if (r.AL == 0xd) DebugPrintf(("d\n")); + if (r.AL == 0xe) DebugPrintf(("e\n")); + if (r.AL == 0xf) DebugPrintf(("f\n")); + } + else if (r.AL < 0x20) + DebugPrintf(("10<=AL<20h\n")); + else if (r.AL < 0x30) + DebugPrintf(("20<=AL<30h\n")); + else if (r.AL < 0x40) + DebugPrintf(("30<=AL<40h\n")); + else if (r.AL < 0x50) + DebugPrintf(("40<=AL<50h\n")); + else if (r.AL < 0x60) + DebugPrintf(("50<=AL<60h\n")); + else if (r.AL < 0x70) + DebugPrintf(("60<=AL<70h\n")); + else if (r.AL < 0x80) + DebugPrintf(("70<=AL<80h\n")); + else if (r.AL < 0x90) + { + DebugPrintf(("80<=AL<90h\n")); + if (r.AL == 0x83) DebugPrintf(("83\n")); + if (r.AL == 0x84) DebugPrintf(("84\n")); + if (r.AL == 0x85) DebugPrintf(("85\n")); + if (r.AL == 0x86) DebugPrintf(("86\n")); + if (r.AL == 0x87) DebugPrintf(("87\n")); + if (r.AL == 0x88) DebugPrintf(("88\n")); + if (r.AL == 0x89) DebugPrintf(("89\n")); + if (r.AL == 0x8a) DebugPrintf(("8a\n")); + if (r.AL == 0x8b) DebugPrintf(("8b\n")); + if (r.AL == 0x8c) DebugPrintf(("8c\n")); + if (r.AL == 0x8d) DebugPrintf(("8d\n")); + if (r.AL == 0x8e) DebugPrintf(("8e\n")); + } + else if (r.AL < 0xa0) + DebugPrintf(("90<=AL=e0h\n")); + #endif /* DEBUG */ + break; } #endif return; @@ -1874,7 +2014,7 @@ /* To prevent corruption when dos=umb where Windows 3.0 standard writes a sentinel at 9FFEh, DOS 5 will save the MCB marking end of conventional memory (ie MCB following caller's PSP memory - block [which I assume occupies all of convential memory] into + block [which I assume occupies all of conventional memory] into the DOS data segment. Note: presumably Win3.1 uses the WinPatchTable.OffLastMCBSeg when DOS ver > 5 to do this itself. Index: kernel/kernel.asm =================================================================== RCS file: /cvsroot/freedos/kernel/kernel/kernel.asm,v retrieving revision 1.54.2.4 diff -u -3 -r1.54.2.4 kernel.asm --- kernel/kernel.asm 31 Jan 2005 20:48:32 -0000 1.54.2.4 +++ kernel/kernel.asm 18 Sep 2005 15:02:02 -0000 @@ -256,11 +256,14 @@ global _NetBios _NetBios dw 0 ; NetBios Number - times (26h - 0ch - ($ - DATASTART)) db 0 + times (26h - 12h - ($ - DATASTART)) db 0 ; Globally referenced variables - WARNING: DO NOT CHANGE ORDER ; BECAUSE THEY ARE DOCUMENTED AS UNDOCUMENTED (?) AND HAVE ; MANY MULTIPLEX PROGRAMS AND TSR'S ACCESSING THEM + global _OemHook21 +_OemHook21 dd -1 ;-0012 OEM fn handler (int21/f8h) + dw 0 ;-000e offset from DOS CS of int21 ret global _NetRetry _NetRetry dw 3 ;-000c network retry count global _NetDelay @@ -284,7 +287,8 @@ _syscon dw _con_dev,seg _con_dev ; 000c console device global _maxbksize _maxbksize dw 512 ; 0010 maximum bytes/sector of any block device - dd 0 ; 0012 pointer to buffers info structure + global _inforecptr +_inforecptr dd 0 ; 0012 pointer to buffers info structure global _CDSp _CDSp dd 0 ; 0016 Current Directory Structure global _FCBp @@ -338,7 +342,7 @@ _deblock_buf dd 0 ; 0054 deblock buffer times 3 db 0 ; 0058 unknown dw 0 ; 005B unknown - db 0, 0FFh, 0 ; 005D unknown + db 0, 0FFh, 0 ; 005D int24fail,memstrat,a20count global _VgaSet _VgaSet db 0 ; 0060 unknown dw 0 ; 0061 unknown @@ -385,7 +389,8 @@ dw instance_table,seg instance_table ; array of instance data instance_table: ; should include stacks, Win may auto determine SDA region ; we simply include whole DOS data segment - dw 0, seg _DATASTART ; [?linear?] address of region's base + dw seg _DATASTART, 0 ; [?linear?] address of region's base +; dw 0, 0;seg _DATASTART ; [?linear?] address of region's base dw markEndInstanceData wrt seg _DATASTART ; size in bytes dd 0 ; 0 marks end of table patch_bytes: ; mark end of array of offsets of critical section bytes to patch @@ -414,6 +419,8 @@ _firstsftt: dd -1 ; link to next dw 5 ; count + times 5*59 db 0 ; reserve space for the 5 sft entries + db 0 ; pad byte so next value on even boundary ; Some references seem to indicate that this data should start at 01fbh in ; order to maintain 100% MS-DOS compatibility. @@ -717,6 +724,13 @@ times 64 dw 0 clk_stk_top: +%IFDEF WIN31SUPPORT +; mux2F private stack + global mux2F_stk_top + times 128 dw 0 +mux2F_stk_top: +%ENDIF ; WIN31SUPPORT + ; Dynamic data: ; member of the DOS DATA GROUP ; and marks definitive end of all used data in kernel data segment