mirror of https://github.com/FDOS/kernel.git
initial windows 3 enhanced support based on unstable kernel branch
This commit is contained in:
parent
292f3079be
commit
9186e6c5ed
|
@ -41,6 +41,7 @@ segment HMA_TEXT
|
|||
extern _user_r
|
||||
extern _ErrorMode
|
||||
extern _InDOS
|
||||
extern _winInstanced
|
||||
extern _cu_psp
|
||||
extern _MachineId
|
||||
extern critical_sp
|
||||
|
@ -276,7 +277,9 @@ int21_reentry:
|
|||
jne int21_1
|
||||
|
||||
int21_user:
|
||||
call dos_crit_sect
|
||||
%IFNDEF WIN31SUPPORT
|
||||
call end_dos_crit_sect
|
||||
%ENDIF ; NOT WIN31SUPPORT
|
||||
|
||||
push ss
|
||||
push bp
|
||||
|
@ -362,15 +365,27 @@ int21_onerrorstack:
|
|||
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
|
||||
call begin_dos_crit_sect
|
||||
%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:
|
||||
call dos_crit_sect
|
||||
%IFNDEF WIN31SUPPORT
|
||||
call end_dos_crit_sect
|
||||
%ENDIF ; NOT WIN31SUPPORT
|
||||
mov cx,_disk_api_tos
|
||||
|
||||
int21_normalentry:
|
||||
|
@ -390,6 +405,15 @@ int21_normalentry:
|
|||
call _int21_service
|
||||
|
||||
int21_exit: dec byte [_InDOS]
|
||||
%IFDEF WIN31SUPPORT
|
||||
call end_dos_crit_sect ; release all critical sections
|
||||
%if 0
|
||||
push ax
|
||||
mov ax, 8101h ; Leave Critical Section
|
||||
int 2ah
|
||||
pop ax
|
||||
%endif
|
||||
%ENDIF ; WIN31SUPPORT
|
||||
|
||||
;
|
||||
; Recover registers from system call. Registers and flags
|
||||
|
@ -415,11 +439,28 @@ int21_ret:
|
|||
; ... and return.
|
||||
;
|
||||
iret
|
||||
%IFDEF WIN31SUPPORT
|
||||
;
|
||||
; begin DOS Critical Section 1
|
||||
;
|
||||
;
|
||||
begin_dos_crit_sect:
|
||||
; we only enable critical sections if Windows is active
|
||||
; we currently use winInstanced, but may need to use separate patchable location
|
||||
cmp word [_winInstanced], 0
|
||||
jz skip_crit_sect
|
||||
push ax
|
||||
mov ax, 8001h ; Enter Critical Section
|
||||
int 2ah
|
||||
pop ax
|
||||
skip_crit_sect:
|
||||
ret
|
||||
%ENDIF ; WIN31SUPPORT
|
||||
;
|
||||
; end Dos Critical Section 0 thur 7
|
||||
;
|
||||
;
|
||||
dos_crit_sect:
|
||||
end_dos_crit_sect:
|
||||
mov [_Int21AX],ax ; needed!
|
||||
push ax ; This must be here!!!
|
||||
mov ah,82h ; re-enrty sake before disk stack
|
||||
|
|
|
@ -122,10 +122,14 @@ WinIdle: ; only HLT if at haltlevel 2+
|
|||
|
||||
Int2f3: cmp ax,1680h ; Win "release time slice"
|
||||
je WinIdle
|
||||
cmp ah,16h
|
||||
je FarTabRetn ; other Win Hook return fast
|
||||
cmp ah,12h
|
||||
je IntDosCal ; Dos Internal calls
|
||||
cmp ah,13h
|
||||
je IntDosCal ; Install Int13h Hook
|
||||
cmp ah,16h
|
||||
je IntDosCal ; Win (Multitasking) Hook
|
||||
cmp ah,46h
|
||||
je IntDosCal ; Win Hook to avoid MCB corruption
|
||||
|
||||
cmp ax,4a01h
|
||||
je IntDosCal ; Dos Internal calls
|
||||
|
@ -135,6 +139,9 @@ Int2f3: cmp ax,1680h ; Win "release time slice"
|
|||
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
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
#include "portab.h"
|
||||
#include "globals.h"
|
||||
#include "nls.h"
|
||||
#include "win.h"
|
||||
#include "debug.h"
|
||||
|
||||
#ifdef VERSION_STRINGS
|
||||
BYTE *RcsId =
|
||||
|
@ -1901,7 +1903,12 @@ struct int2f12regs {
|
|||
UWORD callerARG1; /* used if called from INT2F/12 */
|
||||
};
|
||||
|
||||
/* On input pr->AX==0x12xx, 0x4A01 or 0x4A02
|
||||
extern intvec BIOSInt13, UserInt13, BIOSInt19;
|
||||
|
||||
|
||||
/* WARNING: modifications in `r' are used outside of int2F_12_handler()
|
||||
* On input r.AX==0x12xx, 0x4A01 or 0x4A02
|
||||
* also handle Windows' DOS notification hooks, r.AH==0x16 and r.AH==0x13
|
||||
*/
|
||||
VOID ASMCFUNC int2F_12_handler(struct int2f12regs FAR *pr)
|
||||
{
|
||||
|
@ -1931,6 +1938,252 @@ VOID ASMCFUNC int2F_12_handler(struct int2f12regs FAR *pr)
|
|||
r.BX = size;
|
||||
return;
|
||||
}
|
||||
else if (r.AH == 0x13) /* set disk interrupt (13h) handler */
|
||||
{
|
||||
/* set new values for int13h calls, and must return old values */
|
||||
register intvec tmp = UserInt13;
|
||||
UserInt13 = MK_FP(r.ds, r.DX); /* int13h handler to use */
|
||||
r.ds = FP_SEG(tmp); r.DX = FP_OFF(tmp);
|
||||
tmp = BIOSInt13;
|
||||
BIOSInt13 = MK_FP(r.es, r.BX); /* int13h handler to restore on reboot */
|
||||
r.es = FP_SEG(tmp); r.BX = FP_OFF(tmp);
|
||||
return;
|
||||
}
|
||||
else if (r.AH == 0x16) /* Window/Multitasking hooks */
|
||||
{
|
||||
#ifdef WIN31SUPPORT /* See "DOS Internals" or RBIL under DOSMGR for details */
|
||||
switch (r.AL)
|
||||
{
|
||||
/* default: unhandled requests pass through unchanged */
|
||||
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. */
|
||||
/* The data returned here corresponds directly with text entries that
|
||||
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 */
|
||||
case 0x05: /* Windows Startup Broadcast */
|
||||
{
|
||||
/* After receiving this call we activate compatibility changes
|
||||
as DOS 5 does, though can wait until 0x07 subfunc 0x01
|
||||
*/
|
||||
/* on entry:
|
||||
DX flags, bit 0 is set(=1) for standard mode
|
||||
DI Windows version#, major# in high byte
|
||||
CX 0, set on exit to nonzero to fail load request
|
||||
DS:SI is 0000:0000, for enhanced mode, at most 1 program can
|
||||
set to memory manager calling point to disable V86
|
||||
ES:BX is 0000:0000, set to startup structure
|
||||
*/
|
||||
r.CX = 0x0; /* it is ok to load Windows, give it a shot anyway :-) */
|
||||
r.es = FP_SEG(&winStartupInfo);
|
||||
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 */
|
||||
{
|
||||
/* can do nothing or can remove any changes made
|
||||
specifically for Windows, must preserve DS.
|
||||
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)
|
||||
{
|
||||
/* default: unhandled requests pass through unchanged */
|
||||
case 0x00: /* query if supported */
|
||||
{
|
||||
r.CX = winInstanced; /* should always be nonzero if Win is active */
|
||||
r.DX = FP_SEG(&nul_dev); /* data segment / segment of DOS drivers */
|
||||
r.es = FP_SEG(&winPatchTable); /* es:bx points to table of offsets */
|
||||
r.BX = FP_OFF(&winPatchTable);
|
||||
break;
|
||||
}
|
||||
case 0x01: /* enable Win support, ie patch DOS */
|
||||
{
|
||||
/* 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).
|
||||
On entry BX is bitflags describing support requested,
|
||||
and on return DX is set to which we can support.
|
||||
Note: any we report as unhandled Windows will attempt
|
||||
to patch kernel to handle, probably not a good idea.
|
||||
0001h: enable critical section signals (int 2Ah functions
|
||||
80h/81h) to allow re-entering DOS while InDOS.
|
||||
0002h: allow nonzero local machine ID, ie different VMs
|
||||
report different values.
|
||||
FIXME: does this mean we need to set this or does Windows?
|
||||
0004h: split up binary reads to increase int 2Ah function 84h scheduling
|
||||
/ turn Int 21h function 3Fh on STDIN into polling loop
|
||||
0008h: notify Windows of halting due to internal stack errors
|
||||
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 DX:AX set to A2AB:B97Ch */
|
||||
r.AX = 0xB97C;
|
||||
/* FIXME: do we need to do anything special for FD kernel? */
|
||||
break;
|
||||
}
|
||||
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 */
|
||||
{
|
||||
r.DX = 0xA2AB; /* on succes DS:AX set to A2AB:B97Ch */
|
||||
r.AX = 0xB97C;
|
||||
r.CX = sizeof(struct cds);
|
||||
}
|
||||
else
|
||||
r.CX = 0; /* unknown or unsupported structure requested */
|
||||
break;
|
||||
}
|
||||
case 0x04: /* Get Instancing Exemptions */
|
||||
{
|
||||
/* On exit BX is bit flags denoting data that is instanced
|
||||
so Windows need not instance it. DOS 5&6 fail with DX=CX=0.
|
||||
0001h: Current Directory Structure
|
||||
0002h: System File Table and device status of STDOUT
|
||||
0004h: device driver chain
|
||||
0008h: Swappable Data Area
|
||||
*/
|
||||
r.DX = 0xA2AB; /* on succes DX:AX set to A2AB:B97Ch */
|
||||
r.AX = 0xB97C;
|
||||
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;
|
||||
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 */
|
||||
DosIdle_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:
|
||||
DebugPrintf(("Win call (int 2Fh/16h): %04x %04x %04x %04x\n", r.AX, r.BX, r.CX, r.DX));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
else if (r.AH == 0x46) /* MS Windows WinOLDAP switching */
|
||||
{
|
||||
#ifdef WIN31SUPPORT /* See "DOS Internals" under DOSMGR or RBIL for details */
|
||||
if (r.AL == 0x01) /* save MCB */
|
||||
{
|
||||
/* 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 conventional memory] into
|
||||
the DOS data segment.
|
||||
Note: presumably Win3.1 uses the WinPatchTable.OffLastMCBSeg
|
||||
when DOS ver > 5 to do this itself.
|
||||
*/
|
||||
/* FIXME: Implement this! */
|
||||
}
|
||||
else if (r.AL == 0x02) /* restore MCB */
|
||||
{
|
||||
/* Copy the MCB we previously saved back. */
|
||||
/* FIXME: Implement this! */
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
/* else (r.AH == 0x12) */
|
||||
|
||||
switch (r.AL)
|
||||
{
|
||||
|
|
|
@ -320,14 +320,22 @@ segment _LOWTEXT
|
|||
global _intvec_table
|
||||
_intvec_table: db 10h
|
||||
dd 0
|
||||
; used by int13 handler and get/set via int 2f/13h
|
||||
global _BIOSInt13 ; BIOS provided disk handler
|
||||
global _UserInt13 ; actual disk handler used by kernel
|
||||
db 13h
|
||||
dd 0
|
||||
_BIOSInt13: dd 0
|
||||
db 15h
|
||||
dd 0
|
||||
; used for cleanup on reboot
|
||||
global _BIOSInt19
|
||||
db 19h
|
||||
dd 0
|
||||
_BIOSInt19: dd 0
|
||||
db 1Bh
|
||||
dd 0
|
||||
; default to using BIOS provided disk handler
|
||||
db 13h
|
||||
_UserInt13: dd 0
|
||||
|
||||
; floppy parameter table
|
||||
global _int1e_table
|
||||
|
@ -480,7 +488,7 @@ _winStartupInfo:
|
|||
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 ; [SEG:OFF] address of region's base
|
||||
dw seg _DATASTART, 0 ; [SEG:OFF] address of region's base
|
||||
dw markEndInstanceData wrt seg _DATASTART ; size in bytes
|
||||
dd 0 ; 0 marks end of table
|
||||
dw 0 ; and 0 length for end of instance_table entry
|
||||
|
@ -508,7 +516,9 @@ _winPatchTable: ; returns offsets to various internal variables
|
|||
_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.
|
||||
times (01fbh - ($ - DATASTART)) db 0
|
||||
|
|
|
@ -112,6 +112,7 @@ VOID ASMCFUNC FreeDOSmain(void)
|
|||
/* install DOS API and other interrupt service routines, basic kernel functionality works */
|
||||
setup_int_vectors();
|
||||
|
||||
/* check if booting from floppy/CD */
|
||||
CheckContinueBootFromHarddisk();
|
||||
|
||||
/* display copyright info and kernel emulation status */
|
||||
|
@ -247,24 +248,27 @@ STATIC void setup_int_vectors(void)
|
|||
{ 0x1, FP_OFF(empty_handler) }, /* single step */
|
||||
{ 0x3, FP_OFF(empty_handler) }, /* debug breakpoint */
|
||||
{ 0x6, FP_OFF(int6_handler) }, /* invalid opcode */
|
||||
{ 0x19, FP_OFF(int19_handler) },
|
||||
{ 0x19, FP_OFF(int19_handler) }, /* BIOS bootstrap loader, vdisk */
|
||||
{ 0x20, FP_OFF(int20_handler) },
|
||||
{ 0x21, FP_OFF(int21_handler) },
|
||||
{ 0x21, FP_OFF(int21_handler) }, /* primary DOS API */
|
||||
{ 0x22, FP_OFF(int22_handler) },
|
||||
{ 0x24, FP_OFF(int24_handler) },
|
||||
{ 0x25, FP_OFF(low_int25_handler) },
|
||||
{ 0x25, FP_OFF(low_int25_handler) }, /* DOS abs read/write calls */
|
||||
{ 0x26, FP_OFF(low_int26_handler) },
|
||||
{ 0x27, FP_OFF(int27_handler) },
|
||||
{ 0x28, FP_OFF(int28_handler) },
|
||||
{ 0x2a, FP_OFF(int2a_handler) },
|
||||
{ 0x2f, FP_OFF(int2f_handler) }
|
||||
{ 0x2f, FP_OFF(int2f_handler) } /* multiplex int */
|
||||
};
|
||||
struct vec *pvec;
|
||||
struct lowvec FAR *plvec;
|
||||
int i;
|
||||
|
||||
for (plvec = intvec_table; plvec < intvec_table + 5; plvec++)
|
||||
/* save current int vectors so can restore on reboot and call original directly */
|
||||
for (plvec = intvec_table; plvec < intvec_table + 6; plvec++)
|
||||
plvec->isv = getvec(plvec->intno);
|
||||
|
||||
/* install default handlers */
|
||||
for (i = 0x23; i <= 0x3f; i++)
|
||||
setvec(i, empty_handler);
|
||||
HaltCpuWhileIdle = 0;
|
||||
|
@ -273,7 +277,7 @@ STATIC void setup_int_vectors(void)
|
|||
pokeb(0, 0x30 * 4, 0xea);
|
||||
pokel(0, 0x30 * 4 + 1, (ULONG)cpm_entry);
|
||||
|
||||
/* these two are in the device driver area LOWTEXT (0x70) */
|
||||
/* handlers for int 0x1b and 0x29 are in the device driver area LOWTEXT (0x70) */
|
||||
setvec(0x1b, got_cbreak);
|
||||
setvec(0x29, int29_handler); /* required for printf! */
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue