diff options
Diffstat (limited to 'private/mvdm/dpmi/dxrom.asm')
-rw-r--r-- | private/mvdm/dpmi/dxrom.asm | 805 |
1 files changed, 805 insertions, 0 deletions
diff --git a/private/mvdm/dpmi/dxrom.asm b/private/mvdm/dpmi/dxrom.asm new file mode 100644 index 000000000..30b8dd89f --- /dev/null +++ b/private/mvdm/dpmi/dxrom.asm @@ -0,0 +1,805 @@ + PAGE ,132 + TITLE DXROM.ASM -- Dos Extender ROM Specific Code + +; Copyright (c) Microsoft Corporation 1990-1991. All Rights Reserved. + +;*********************************************************************** +; +; DXROM.ASM -- Dos Extender ROM Specific Code +; +;----------------------------------------------------------------------- +; +; This module contains code specific to the ROM version of the DOS +; Extender. +; +;----------------------------------------------------------------------- +; +; 11/05/90 jimmat Created. +; +;*********************************************************************** + + .286p + +IFDEF ROM + +; ------------------------------------------------------- +; INCLUDE FILE DEFINITIONS +; ------------------------------------------------------- + + .xlist + .sall +include segdefs.inc +include gendefs.inc +include pmdefs.inc +include dxrom.inc + .list + + +; ------------------------------------------------------- +; GENERAL SYMBOL DEFINITIONS +; ------------------------------------------------------- + +; Define some pubilc symbols to be exported for the ROM Image Builder + + public __selDXCODE, __selDXDGROUP, __selDXPMCODE + +__selDXCODE = SEL_DXCODE +__selDXDGROUP = SEL_DXDATA +__selDXPMCODE = SEL_DXPMCODE + + public __selFirstLDT, __selLDTAlias + +__selFirstLDT = SEL_USER +__selLDTAlias = SEL_LDT_ALIAS + + +; ------------------------------------------------------- +; EXTERNAL SYMBOL DEFINITIONS +; ------------------------------------------------------- + + extrn ParaToLinear:NEAR + extrn AllocateLDTSelector:NEAR + extrn ChildTerminationHandler:NEAR + +externFP NSetSegmentDscr + +; ------------------------------------------------------- +; DATA SEGMENT DEFINITIONS +; ------------------------------------------------------- + +DXDATA segment + + extrn selGDTFree:WORD + extrn segDXData:WORD + extrn ExitCode:BYTE + +SaveROMVector dw ? + +cparChildMem dw ? ; size of child DOS mem block in para's +regOurSSSP dd ? ; SS:SP save location + +DXDATA ends + +; ------------------------------------------------------- +; CODE SEGMENT VARIABLES +; ------------------------------------------------------- + +DXCODE segment + +; For the ROM version, the following items locate (and size) the +; DGROUP and DXPMCODE segments. These items are 'imported' from +; the ROM Image Builder which sets the values when the ROM image +; is created. + + extrn lmaDXDGROUP:DWORD, cparDXDGROUP:ABS, lmaDXPMCODE:DWORD + public lmaRomDXPMCode + +cparDgroup dw cparDXDGROUP +lmaDGroup dd lmaDXDGROUP +lmaRomDXPMCode dd lmaDXPMCODE + +DXCODE ends + + +DXPMCODE segment + + extrn selDgroupPM:WORD + + extrn lmaROMTOC:DWORD + +MyLmaROMTOC dd lmaROMTOC + +DXPMCODE ends + + +; ------------------------------------------------------- + subttl ROM Real Mode ROM Specific Routines + page +; ------------------------------------------------------- +; ROM REAL MODE ROM SPECIFIC ROUTINES +; ------------------------------------------------------- + +DXCODE segment + assume cs:DXCODE + +; ------------------------------------------------------- +; ROMEntry -- Setup the special ROM environment needed +; immediately by DOSX. +; +; Note: This routine runs in real mode only! +; +; Input: ES -> PSP for use by DOSX +; Output: CY clear if successful, set if init failed +; DS -> DOSX RAM DGROUP +; DX:AX = far return address to app that invoked DOSX +; Errors: none +; Uses: All except ES + + assume ds:NOTHING,es:NOTHING,ss:NOTHING + public ROMEntry + +ROMEntry proc near + +; Allocate a data segment in RAM and copy down the ROM version + + mov ah,48h ;allocate RAM for DGROUP + mov bx,cparDgroup + int 21h + jc REAllocFailed ;big trouble if this happens + + push ax ;save RAM DGROUP + + mov dx, word ptr lmaDGroup[0] + mov bx, word ptr lmaDGroup[2] + mov cx, 4 + xor si, si +@@: + shr bx, 1 ;determine if its in conventional + rcr dx, 1 ;memory and if so the canonical + rcr si, 1 ;segment:offset in dx:si + loop @B + + or bx, bx + jnz RECopyFromExtended + +RECopyFromConventional: + push es ;save es + mov es,ax + mov ds,dx + mov cx,cparDgroup ; (CS variable) + shl cx,3 ;DGROUP size in words + xor di,di + cld + rep movsw + pop es ;restore es + + pop ds ;point to RAM dgroup + assume ds:DGROUP, es:NOTHING + + clc ;worked! + +REAllocFailed: + + ret + +RECopyFromExtended: + + sub sp, 30h + mov si, sp + push ss + pop es + mov di, si + push ax + xor ax,ax + mov cx, 18h + rep stosw + dec ax + mov es:[si+10h], ax ; Limits to FFFF + mov es:[si+18h], ax + mov al, 93h + mov es:[si+15h], al ; access to data rw + mov es:[si+1Dh], al + pop ax + mov cx, 4 + sub dx, dx +@@: + shl ax, 1 ;compute new DGROUP lma + rcl dx, 1 + loop @B + mov es:[si+1Ah], ax ;stuff into dest descr + mov es:[si+1Ch], dl + mov ax, word ptr lmaDGroup[0] + mov dx, word ptr lmaDGroup[2] + mov es:[si+12h], ax + mov es:[si+14h], dl ;put ROM lma in source descr + mov cx, cparDGroup + shl cx, 3 ;length of dgroup ***in words *** + mov ah, 87h ;fn 87h = copy extended memory + int 15h + jc REExtCopyFailed + add sp, 30h + pop ds ;get ram address in ds + clc + ret + +REExtCopyFailed: + add sp, 32h ;remove stuff from stack + stc + ret + +ROMEntry endp + + +; ------------------------------------------------------- +; InvokeROMChild -- ROM specific method of invoking the +; child application. +; +; Note: This routine must be called in real mode! +; It returns to the caller after the child returns. Control +; passes directly to ChildTerminationHandler if child does a +; DOS exit call. +; +; Input: none +; Output: CY clear if child executed successfully, set if failed +; AX = error code if failure (8 = insufficient DOS memory) +; Errors: none +; Uses: All except DS + + assume ds:DGROUP,es:NOTHING,ss:NOTHING + public InvokeROMChild + +InvokeROMChild proc near + +; Setup the environment for the ROM child app. First, allocate +; the largest conventional memory block available and build a PSP +; at the start of it. + + mov bx,-1 ; how big is the largest avail block? + dossvc 48h + + cmp bx,64 SHL 6 ; is there at least 64k available? + jae @f + mov ax,8 ; DOS insufficient memory error + jmp short IRCFail +@@: + mov cparChildMem,bx ; save block size + dossvc 48h ; allocate block + +IF DEBUG + jnc @f ; shouldn't fail, but... + int 3 +@@: +ENDIF + +; Got conventional memory, now build a PSP at the start of it. + + mov dx,ax ; new PSP here + mov si,10h ; use this as mem length for now + dossvc 55h ; duplicate PSP call + +; Set up the termination vector in the child's PSP to point to +; the Dos Extender termination code. + + mov es,dx + assume es:PSPSEG + + mov word ptr [lpfnParent],offset ChildTerminationHandler + mov word ptr [lpfnParent+2],cs + +; Switch to protected mode to complete initialization of child environment + + SwitchToProtectedMode + assume ds:DGROUP,es:DGROUP + + sti + +; Allocate/init a selector mapping first 64k of child memory block & PSP + + call AllocateLDTSelector ; get new selector in AX + + ; DX still has PSP segment, + call ParaToLinear ; convert to linear memory address + + push bx ; save lma for later + push dx + push ax ; save mem/PSP selector too + + cCall NSetSegmentDscr,<ax,bx,dx,0,0FFFFh,STD_DATA> + +; Allocate/init a zero length selector pointing to just past the end of +; the child's memory block and plug the selector into the PSP. + + call AllocateLDTSelector ; get another selector + + pop es + assume es:PSPSEG + + mov segMemEnd,ax ; store in child's PSP + + mov dx,cparChildMem ; get size of memory block in bytes + call ParaToLinear ; in BX:DX + + pop ax ; recover lma of block start + pop cx ; in CX:AX + + add dx,ax + adc bx,cx ; BX:DX = lma of block end + + cCall NSetSegmentDscr,<segMemEnd,bx,dx,0,0,STD_DATA> + +; Allocate/init a selector pointin to our DOS environment block--plug this +; into the child's PSP so it can party on the same env block. + + call AllocateLDTSelector + + mov dx,segEnviron ; segment from PSP + call ParaToLinear + + cCall NSetSegmentDscr,<ax,bx,dx,0,7FFFH,STD_DATA> + + mov segEnviron,ax ; selector to PSP + +; The child environment is now build, invoke the child with DS = ES = +; memory/PSP block. Set the stack 64k (less one word) into the block, +; push our far return address on the stack. + + mov word ptr [regOurSSSP],sp ;save DOSX stack location + mov word ptr [regOurSSSP+2],ss + + mov ax,es ; switch to child stack + mov ss,ax + mov sp,0FFFEh + + push cs ; far return address to us + push offset IRCReturn + + call GetROMTOCPointer ; push the kernel entry CS:IP on stack + assume es:ROMTOC + + push word ptr [KRNL_CSIP+2] + push word ptr [KRNL_CSIP] + + mov ds,ax + mov es,ax + assume ds:NOTHING,es:NOTHING + + xor cx, cx ; tell KRNL386 linear == physical + xor dx, dx + + retf ; invoke the kernel + + public IRCReturn ;public for debugging +IRCReturn: + + mov ds,selDgroupPM ; restore our DS + assume ds:DGROUP + + mov ss,word ptr [regOurSSSP+2] ; and our stack + mov sp,word ptr [regOurSSSP] + + mov ExitCode,al ; save the child exit code + + SwitchToRealMode + sti + + clc + ret + +IRCFail: + stc + ret + +InvokeROMChild endp + + +; ------------------------------------------------------- +; ROMInitialization -- This routine performs the initial ROM +; specific DOS Extender initialization. +; +; Note: This routine runs in real mode only! +; +; Input: none +; Output: CY clear if successful, set if init failed +; Errors: none +; Uses: AX + + assume ds:DGROUP,es:NOTHING,ss:NOTHING + public ROMInitialization + +ROMInitialization proc near + +; Point 2nd word of DOSX ROM Int vector to the data segment. + + push es + xor ax,ax + mov es,ax + + mov ax, word ptr es:[ROMIntVector*4][2] ;save current vector + mov SaveROMVector,ax ; contents + + mov word ptr es:[ROMIntVector*4][2],ds ;point vector to data + pop es + + clc + +ROMInitFailed: + + ret + +ROMInitialization endp + + +; ------------------------------------------------------- +; ROMCleanUp -- This routine performs the ROM specific +; DOS Extender termination clean up. +; +; Note: This routine runs in real mode only! +; +; Input: none +; Output: none +; Errors: none +; Uses: none + + assume ds:DGROUP,es:NOTHING,ss:NOTHING + public ROMCleanUp + +ROMCleanUp proc near + +; Remove DOSX Int vector pointer to the data segment. + + push es + xor ax,ax + mov es,ax + + mov ax,SaveROMVector ;restore prior contents + mov word ptr es:[ROMIntVector*4][2],ax + + pop es + + ret + +ROMCleanUp endp + + +; ------------------------------------------------------- + subttl ROM Real Mode Utility Routines + page +; ------------------------------------------------------- +; ROM REAL MODE UTILITY ROUTINES +; ------------------------------------------------------- + +; GetDXDataRM -- This routine returns the paragraph address of +; the DOS Extender data segment. It should only be called +; by real mode code. +; +; Input: none +; Output: AX = DOSX data segment paragraph address +; Errors: none +; Uses: none + + assume ds:NOTHING,es:NOTHING,ss:NOTHING + public GetDXDataRM + +GetDXDataRM proc near + +; Get data segment value from 2nd word of DOSX Int vector + + push ds + + xor ax,ax + mov ds,ax + mov ax,word ptr ds:[ROMIntVector*4][2] + +IF DEBUG + mov ds,ax + cmp ax,ds:[segDXData] ; Make sure ax points to the + jz @f ; right place + int 3 +@@: +ENDIF + pop ds + ret + +GetDXDataRM endp + + +; ------------------------------------------------------- +; SetDXDataRM -- This routine sets DS equal to the DOS Extender +; data segment address. It should only be called by real +; mode code. +; +; Input: none +; Output: DS -> DOSX data segment +; Errors: none +; Uses: none + + assume ds:NOTHING,es:NOTHING,ss:NOTHING + public SetDXDataRM + +SetDXDataRM proc near + +; Get data segment value from 2nd word of DOSX Int vector + + push ax + + xor ax,ax + mov ds,ax + mov ds,word ptr ds:[ROMIntVector*4][2] + +IF DEBUG + mov ax,ds ; Make sure DS points to the + cmp ax,ds:[segDXData] ; right place + jz @f + int 3 +@@: +ENDIF + pop ax + ret + +SetDXDataRM endp + + +DXCODE ends + +;**************************************************************** + +DXPMCODE SEGMENT + assume cs:DXPMCODE + +; ------------------------------------------------------- + subttl ROM Protect Mode Utility Routines + page +; ------------------------------------------------------- +; ROM PROTECT MODE UTILITY ROUTINES +; ------------------------------------------------------- + +; ROMInitLDT -- This routine initializes the LDT descriptors +; defined in the ROM prototype LDT. +; +; Input: none +; Output: none +; Errors: none +; Uses: none + + assume ds:DGROUP,es:NOTHING,ss:NOTHING + public ROMInitLDT + +ROMInitLDT proc near + +; Access the ROM Table of Contents to find out where the proto LDT +; is, and how many descriptors it contains. + + pusha + push ds + push es + + call GetROMTOCPointer ; Note: uses SEL_SCR0 + assume es:ROMTOC + + mov cx,cROMsels ; # descriptors defined in proto LDT + mov bx,word ptr [lmaROMLDT+2] + mov dx,word ptr [lmaROMLDT] ; bx:dx = lma of proto LDT + mov ax,FirstROMSel + mov di, ax + +; Do a quick (and dirty?) allocation of the correct number of LDT selectors. +; DANGER: this code has intimate knowledge of how the LDT free list is kept! +; We could make CX calls to AllocateLDTSelector, but that is slow and would +; do zillions and zillions of segment loads. +; + cmp ax,selGDTFree ; next free descriptor in LDT + jne alloc_in_chain + +IF DEBUG + cmp ax,__selFirstLDT ; first one free better be the one + jz @f ; the ROM Image Builder used. + int 3 +@@: +ENDIF + shl cx,3 ; 'allocate' all these by setting + add ax,cx ; the next free to be beyond them + mov selGDTFree,ax + push SEL_LDT_ALIAS OR STD_RING + pop es + jmp short sels_alloced + +alloc_in_chain: + mov si, ax + sub si, 8 + push SEL_LDT_ALIAS OR STD_RING + pop es + shl cx, 3 + add ax, cx + mov es:[si], ax + +sels_alloced: + +; Copy the prototype descriptors into the actual LDT + + cCall NSetSegmentDscr,<SEL_SCR0,bx,dx,0,-1,STD_DATA> + + push SEL_SCR0 OR STD_TBL_RING + pop ds ; ds -> proto LDT descriptors + assume ds:NOTHING + + xor si,si + + shr cx,1 ; # words of descriptors to copy + + cld + rep movsw ; move'm into the LDT + + pop es + pop ds + assume ds:DGROUP,es:NOTHING + popa + + ret + +ROMInitLDT endp + + +; ------------------------------------------------------- +; GetROMTOCPointer -- return ES:0 pointing to the ROM Table of +; Contents. +; +; Note: modifies the SEL_SCR0 descriptor! +; +; Input: none +; Output: ES:0 -> ROM TOC +; Errors: none +; Uses: none + + assume ds:DGROUP,es:NOTHING,ss:NOTHING + public GetROMTOCPointer + +GetROMTOCPointer proc near + + push bx + push dx + + mov bx,word ptr [MyLmaROMTOC+2] + mov dx,word ptr [MyLmaROMTOC] ;bx:dx = lma of ROMTOC + + cCall NSetSegmentDscr,<SEL_SCR0,bx,dx,0,-1,STD_DATA> + + push SEL_SCR0 OR STD_TBL_RING + pop es + + pop dx + pop bx + + ret + +GetROMTOCPointer endp + + +; ------------------------------------------------------- +; GetDXDataPM -- This routine returns the paragraph address of +; the DOS Extender data segment. It should only be called +; by protected mode code. +; +; Input: none +; Output: AX = DOSX data segment paragraph address +; Errors: none +; Uses: none + + assume ds:NOTHING,es:NOTHING,ss:NOTHING + public GetDXDataPM + +GetDXDataPM proc near + +; Get data segment value from 1st word of DOSX Int vector + + push ds + + mov ax,SEL_RMIVT or STD_RING + mov ds,ax + mov ax,word ptr ds:[ROMIntVector*4][2] + + pop ds + ret + +GetDXDataPM endp + +if 0 ;*************************************************************** +; ------------------------------------------------------- +; SetDXDataPM -- This routine sets DS equal to the DOS Extender +; data segment address. It should only be called by protected +; mode code. +; +; Input: none +; Output: DS -> DOSX data segment +; Errors: none +; Uses: none + + assume ds:NOTHING,es:NOTHING,ss:NOTHING + public SetDXDataPM + +SetDXDataPM proc near + +; Set DS = data segment selector. + + push SEL_DXDATA OR STD_RING + pop ds + ret + +SetDXDataPM endp +endif ;*************************************************************** + + +DXPMCODE ends + +;**************************************************************** + +ifdef ROMSTUB ;-------------------------------------------------------- + + ********************************************* + ********************************************* + ***** ***** + ***** THIS CODE IS NO LONGER USED ***** + ***** ***** + ********************************************* + ********************************************* + +DXSTUB SEGMENT + assume cs:DXSTUB + +; ------------------------------------------------------- + subttl Real Mode RAM Stub Segment + page +; ------------------------------------------------------- +; REAL MODE RAM STUB SEGMENT +; ------------------------------------------------------- + +; This segment contains code and data that is moved to conventional +; RAM during initialization. The code is only executed from RAM +; mode and exists for those few cases where it is most convenient +; to have code segement variables. +; +; Note: Since this code is moved to RAM, be very carefull of the +; instructions it contains. In particular, realize the the code segment +; value is going to be different from the copy in ROM. + +; ------------------------------------------------------- +; CODE SEGMENT VARIABLES +; ------------------------------------------------------- + + public PrevInt2FHandler + +PrevInt2FHandler dd ? + +; ------------------------------------------------------- +; StubInt2FHook -- This code is used by the DOS Extender real mode +; Int 2Fh hook to chain the interrupt to the previous Int 2Fh +; handler. +; +; Note: This code executes in real mode only! +; +; Input: stack = [DS] [IP] [CS] [FL] +; Output: none +; Errors: none +; Uses: none + + + assume ds:NOTHING,es:NOTHING,ss:NOTHING + public StubInt2FHook + +StubInt2FHook proc far + + pop ds + jmp [PrevInt2FHandler] + +StubInt2FHook endp + +; ------------------------------------------------------- + +DXSTUB ends + +endif ;---------------------------------------------------------------- + +;**************************************************************** + +ENDIF ;ROM + + end |