From 2d04cacc5322951f187bb17e017c12920ac8ebe2 Mon Sep 17 00:00:00 2001 From: Mark Zbikowski Date: Thu, 25 Apr 2024 21:24:10 +0100 Subject: MZ is back! --- v4.0/src/MEMM/EMM/EMMSUP.ASM | 652 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 652 insertions(+) create mode 100644 v4.0/src/MEMM/EMM/EMMSUP.ASM (limited to 'v4.0/src/MEMM/EMM/EMMSUP.ASM') diff --git a/v4.0/src/MEMM/EMM/EMMSUP.ASM b/v4.0/src/MEMM/EMM/EMMSUP.ASM new file mode 100644 index 0000000..4034e18 --- /dev/null +++ b/v4.0/src/MEMM/EMM/EMMSUP.ASM @@ -0,0 +1,652 @@ +page 58,132 +;****************************************************************************** + title EMMSUP - EMM support routines +;****************************************************************************** +; +; (C) Copyright MICROSOFT Corp. 1986 +; +; Title: CEMM.EXE - COMPAQ Expanded Memory Manager 386 Driver +; EMMLIB.LIB - Expanded Memory Manager Functions Library +; +; Module: EMMSUP - EMM support routines +; +; Version: 0.04 +; +; Date: May 13, 1986 +; +;****************************************************************************** +; +; Change log: +; +; DATE REVISION DESCRIPTION +; -------- -------- ------------------------------------------------------- +; 5/13/86 Original Initial _TEXT +; 6/14/86 Added _sotofar routine and removed stack define. +; And added protected mode check to Map_Page (SBP). +; 6/14/86 map_page now sets _current_map(SBP). +; 6/14/86 moved save_current_map and restore_map from C code (SBP) +; 6/14/86 brought SegOffTo24 and SetDescInfo in from LAST code +; segment as local routines(SBP). +; 6/21/86 0.02 cld in copyout (SBP). +; 6/21/86 0.02 MapHandlePage added. +; 6/23/86 0.02 make_addr, sotofar removed. source_addr and dest_addr +; added. +; 6/27/86 0.02 Fix for restore_map. +; 6/28/86 0.02 Name change from CEMM386 to CEMM (SBP). +; 7/06/86 0.04 Changed _emm_page,_emm_free, & _pft386 to ptrs (SBP). +; 7/06/86 0.04 Changed assumes from _DATA to DGROUP (SBP). +; 7/06/86 0.04 Changed internal save area structure (SBP). +; 7/06/86 0.04 moved SavePageMap and RestorePageMap to .ASM (SBP). +; 7/07/86 0.04 moved MapHandlePage,SavePageMap, and RestorePageMap to +; emmp.asm (SBP). +; 5/09/88 1.01 moved routines names_match and flush_tlb from win386 +; 9/01/88 rename SegOffTo24/SetDescInfo to +; SegOffTo24Resident/SetDescInfoResdient and made public +;****************************************************************************** +; +; Functional Description: +; Support routines for emm/386 +; C callable +; +; +;****************************************************************************** +.lfcond ; list false conditionals +.386p + +;****************************************************************************** +; P U B L I C S +;****************************************************************************** + public _source_addr + public _dest_addr + public _copyout + public _copyin + public _wcopy + public _wcopyb + public _valid_handle + public SetDescInfoResident + public SegOffTo24Resident +; +;****************************************************************************** +; D E F I N E S +;****************************************************************************** + + include vdmseg.inc + include vdmsel.inc + include desc.inc + include page.inc +; include instr386.inc + include emmdef.inc + +FALSE equ 0 +TRUE equ not FALSE +CR equ 0dh +LF equ 0ah + + page +;****************************************************************************** +; E X T E R N A L R E F E R E N C E S +;****************************************************************************** + +_DATA SEGMENT +; +; pointer to entry stack frame +; stored as offset, SS +extrn _regp:word + +; +; current state of mapping registers and # of mapping registers emulated +; +;extrn _current_map:byte +;extrn _map_size:byte + +; +; total # of EMM pages in system +; +extrn _total_pages:word + +; +; table of offsets into in to the first page table +; for user logical emm page map +; +extrn _page_frame_base:dword + +; +; ptr to table of emm page # for each handle's logical pages. +; +extrn _emm_page:word + +; +; ptr to table of page table entries for the EMM pages +; +extrn _pft386:word ; note: actually a dword array + +; +; handle data structure +; +extrn _handle_table:word +extrn _handle_table_size:word + +; +; save area for handles +; +extrn _save_map:byte + +_DATA ENDS + + + page +;****************************************************************************** +; L O C A L D A T A +;****************************************************************************** +_DATA SEGMENT +; +; kludge to prevent unresolved from C compiler +; +public __acrtused +__acrtused label dword + dd (0) +_DATA ENDS + + page +;****************************************************************************** +; C O D E +;****************************************************************************** +_TEXT SEGMENT +assume cs:_TEXT, ds:DGROUP, ss:DGROUP + +;*********************************************** +; +; _source_addr - return far pointer for source address (= int 67 entry DS:SI). +; +; SYNOPSIS: src = source_addr() +; char far *src; /* ptr to area at DS:SI */ +; +; DESCRIPTION: This function generates a far pointer equivalent to the client's +; DS:SI pointer. If this code was called in protected mode, the +; address is a (selector,offset) pair; otherwise, it is a segment +; offset pair. EMM1_GSEL is used if a selector is needed. +; +; 05/09/88 ISP No update needed for MEMM +;*********************************************** +_source_addr proc near +; + push bp +; + mov bp,[_regp] ; get entry stack frame pointer + test [bp.PFlag],PFLAG_VIRTUAL ;Q: real/virtual mode ? + jnz sa_pm ; N: go get selector/offset + mov ax,word ptr [bp.rSI] ; Y: get offset + mov dx,word ptr [bp.rDS] ; get segment + jmp sa_exit ; return DX:AX = seg:offset +; +; protected mode - set up selector to client's DS +sa_pm: + push bx + push cx + push es ; save ES + ; + ; load ES with GDT alias + ; + push GDTD_GSEL + pop es ; ES -> GDT + ; + ; compute physical address + ; + mov ax,word ptr [bp.rDS] ; ax <-- base addr + mov dx,word ptr [bp.rSI] ; dx <-- offset + call SegOffTo24Resident ; converts to physical addr + + ; + ; set up the appropriate table entry + ; + mov bx,EMM1_GSEL ; bx <-- selector + mov cx,0FFFFh ; cx <-- gets limit (64k) + mov ah,D_DATA0 ; ah <-- gets access rights + ; + ; at this point: + ; ah -- access rights + ; al -- bits 16-23 of linear address + ; dx -- low 16 bits of linear address + ; cx -- limit = 64k + ; bx -- selector + ; es -- selector to GDT Alias + call SetDescInfoResident ; set up descriptor + + ; + ; set up return pointer + ; + xor ax,ax ; ax <-- offset (0) + mov dx,bx ; dx <-- selector + ; + pop es ; restore ES + pop cx + pop bx +; +sa_exit: + pop bp + ret +; +_source_addr endp + +;*********************************************** +; +; _dest_addr - return far pointer for destination address (= int 67 entry ES:DI). +; +; SYNOPSIS: dest = dest_addr() +; char far *dest; /* ptr to area at ES:DI */ +; +; DESCRIPTION: This function generates a far pointer equivalent to the client's +; ES:DI pointer. If this code was called in protected mode, the +; address is a (selector,offset) pair; otherwise, it is a segment +; offset pair. EMM2_GSEL is used if a selector is needed. +; +; 05/09/88 ISP No update needed for MEMM +;*********************************************** +_dest_addr proc near +; + push bp +; + mov bp,[_regp] ; get entry stack frame pointer + test [bp.PFlag],PFLAG_VIRTUAL ;Q: real/virtual mode ? + jnz da_pm ; N: go get selector/offset + mov ax,word ptr [bp.rDI] ; Y: get offset + mov dx,word ptr [bp.rES] ; get segment + jmp da_exit ; return DX:AX = seg:offset +; +; protected mode - set up selector to client's DS +da_pm: + push bx + push cx + push es ; save ES + ; + ; load ES with GDT alias + ; + push GDTD_GSEL + pop es ; ES -> GDT + ; + ; compute physical address + ; + mov ax,word ptr [bp.rES] ; ax <-- base addr + mov dx,word ptr [bp.rDI] ; dx <-- offset + call SegOffTo24Resident ; converts to physical addr + + ; + ; set up the appropriate table entry + ; + mov bx,EMM2_GSEL ; bx <-- selector + mov cx,0FFFFh ; cx <-- gets limit (64k) + mov ah,D_DATA0 ; ah <-- gets access rights + ; + ; at this point: + ; ah -- access rights + ; al -- bits 16-23 of linear address + ; dx -- low 16 bits of linear address + ; cx -- limit = 64k + ; bx -- selector + ; es -- selector to GDT Alias + call SetDescInfoResident ; set up descriptor + + ; + ; set up return pointer + ; + xor ax,ax ; ax <-- offset (0) + mov dx,bx ; dx <-- selector + ; + pop es ; restore ES + pop cx + pop bx +; +da_exit: + pop bp + ret +; +_dest_addr endp + + page +;*********************************************** +; +; _copyout +; +; This routine takes a far pointer, a near pointer +; and a byte count and copies from the near address +; to the far address. +; +; Parameters: +; destptr -- sel:off 286 pointer to target area +; srcptr --- offset of source data in current D Seg +; count ---- byte count for copy +; +; uses: +; cx, ax, es +; +; 05/09/88 ISP No update needed for MEMM +;*********************************************** +destptr = 4 +srcptr = 8 +count = 10 +_copyout proc near + push bp ; entry prolog + mov bp,sp + push di ; reg var + push si ; reg var + + les di,[bp+destptr] ; es:di <-- destination address + mov si,[bp+srcptr] ; ds:si <-- source address + mov cx,[bp+count] ; cx <-- byte count + cld ; strings foward + rep movsb ; do it + + pop si ; restore reg var + pop di ; restore reg var + pop bp + ret +_copyout endp + page + +;*********************************************** +; +; _copyin +; +; This routine takes a near pointer, a far pointer +; and a byte count and copies from the far address +; to the near address. +; +; Parameters: +; destptr -- offset of dest in current D Seg +; srcptr --- sel:off 286 pointer to source data area +; count ---- byte count for copy +; +; uses: +; cx, ax, es +; +; 05/09/88 ISP Written for MEMM. +;*********************************************** +destptr = 4 +srcptr = 6 +count = 10 +_copyin proc near + push bp ; entry prolog + mov bp,sp + push di ; reg var + push si ; reg var + push ds + + push ds + pop es ; es to dgroup + + mov di,[bp+destptr] ; es:di <-- destination address + lds si,[bp+srcptr] ; ds:si <-- source address + mov cx,[bp+count] ; cx <-- byte count + cld ; strings foward + rep movsb ; do it + + pop ds + pop si ; restore reg var + pop di ; restore reg var + pop bp + ret +_copyin endp + page +;*********************************************** +; +; _wcopy +; +; This routine takes a two near pointers +; and a word count and copies from the +; first address to the second address. +; +; Parameters: +; srcptr --- offset of source data in current D Seg +; destptr -- offset of destination address in DS +; count ---- word count for copy +; +; uses: +; si, di, cx, ax +; (si, di are restored) +; +; 05/09/88 ISP No update needed for MEMM +;*********************************************** +srcptr = 4 +destptr = 6 +count = 8 +_wcopy proc near + push bp ; entry prolog + mov bp,sp + push di ; reg var + push si ; reg var + + cld ; clear dir flag (forward move) + mov ax,ds ; + mov es,ax ; mov es,ds + mov di,[bp+destptr] ; es:di <-- destination address + mov si,[bp+srcptr] ; ds:si <-- source address + mov cx,[bp+count] ; cx <-- word count + rep movsw ; do it + + pop si ; restore reg var + pop di ; restore reg var + pop bp + ret +_wcopy endp + page +;*********************************************** +; +; _wcopyb +; +; This routine takes a two near pointers +; and a word count and copies from the +; first address to the second address. +; The copy is done backwards to allow certain overlap of source and destination. +; +; Parameters: +; srcptr --- offset of source data in current D Seg +; destptr -- offset of destination address in DS +; count ---- word count for copy +; +; uses: +; si, di, cx, ax, es +; (si, di are restored) +; +; 05/20/88 ISP Shifted in from win386 and updated for 16 bit ptrs +;*********************************************** +srcptr = 4 +destptr = 6 +count = 8 +_wcopyb proc near + push bp ; entry prolog + mov bp,sp + push di ; reg var + push si ; reg var + + mov ax,ds ; + mov es,ax ; mov es,ds + mov di, word ptr [bp+destptr] ; destination address + mov si, word ptr [bp+srcptr] ; source address + mov cx, word ptr [bp+count] ; word count + dec cx + shl cx, 1 ; offset of 'last' word to move + add si, cx + add di, cx + mov cx, word ptr [bp+count] ; recover word count + + std ; set dir flag (backward move) + rep movsw ; do it + cld ; 'C' tends to expect this. + + pop si ; restore reg var + pop di ; restore reg var + pop bp + ret +_wcopyb endp + page +;*********************************************** +; +; _valid_handle - validate current handle +; +; SYNOPSIS: hp = _valid_handle() +; struct handle_ptr *hp; /* ptr to handle's structure */ +; /* OR NULL_HANDLE if invalid handle */ +; /* also sets AH = INVALID_HANDLE if it fails */ +; +; DESCRIPTION: This routine validates the current handle in regp->rDX and +; returns either an error or a ptr to the handle's index and +; page count structure. +; +; 05/09/88 ISP No update needed for MEMM +;*********************************************** +_valid_handle proc near +; + push bp + mov bp,[_regp] ; get entry args pointer + push bx +; + mov bx,word ptr [bp.rDX] ; BX = entry handle + cmp bx,[_handle_table_size] ;Q: handle in range ? + jae vh_fail ; N: return invalid handle error + shl bx,2 ; Y: BX = handle's table offset + add bx,offset DGROUP:_handle_table ; BX = offset to handle's data + cmp [bx.ht_index],NULL_PAGE ;Q: is this an active handle ? + je vh_fail ; N: return invalid handle error + mov ax,bx ; Y: return ptr to handle's data +; +vh_exit: + pop bx + pop bp + ret +vh_fail: + mov byte ptr [bp.rAX+1],INVALID_HANDLE ; set AH on stack + mov ax,NULL_HANDLE ; return NULL_HANDLE to caller + jmp short vh_exit + +; +_valid_handle endp + +;*********************************************** +; +; flush_tlb: +; +; no params, no return value, uses eax +; +; flush the Translation Look-Aside Buffer +; +; 05/09/88 ISP Shifted in from WIN386 +;*********************************************** +_flush_tlb proc near +public _flush_tlb + mov eax, cr3 + mov cr3, eax + ret +_flush_tlb endp + +;*********************************************** +; +; _Names_Match +; +; Returns a boolean value (0 = false, FFFF = True) if 2 handle names match +; +; uses: +; cx, ax +; +; 05/09/88 ISP Shifted in from WIN386 and modified for 16 bit ptrs +;*********************************************** +name1 = 4 +name2 = 6 + public _Names_Match +_Names_Match proc near + push bp ; entry prolog + mov bp,sp + push di ; reg var + push si ; reg var + + mov ax,ds ; initialise es segment to + mov es,ax ; DGROUP + + xor ax, ax ; Assume it did NOT work + + mov di, word ptr [bp+name1] ; First name + mov si, word ptr [bp+name2] ; Second name + cld + mov cx, 2 ; Compare 2 dwords + rep cmpsd ; do it + jne SHORT Names_Dont_Match + not ax ; They match! + +Names_Dont_Match: + pop si ; restore reg var + pop di ; restore reg var + pop bp + ret +_Names_Match endp + + page +;** SetDescInfoResident - set descriptor information +; +; The limit field of a specified descriptor is set. +; (limit = size - 1). +; The base address of the specified descriptor is set. +; The access field of the specified descriptor is set. +; +; ENTRY BX = selector +; ES:0 = descriptor table to use +; CX = limit +; AL, DX = 24 bit base address +; AH = access rights byte +; EXIT None +; USES Flags, other regs preserved +; +; WARNING This code only works on a 286. It can be called in +; either mode. + +SetDescInfoResident proc near + push bx ; save selector + and bl,SEL_LOW_MASK + +; fill in the limit field + + mov es:[bx],cx + +; fill in base address + + mov es:[bx + 2],dx + mov es:[bx + 4],al + +; fill in access rights byte + + mov es:[bx + 5],ah + pop bx + ret +SetDescInfoResident endp + + page +;** SegOffTo24Resident - convert seg:off to 24 bit physical address +; +; The specified real mode segment:offset is converted to +; a 24 bit physical address. +; +; ENTRY AX = segment +; DX = offset +; EXIT AL, DX = 24 bit physical address +; USES AH, Flags, other regs preserved. +; +; WARNING This code only works on a 286. It can be called in +; either mode. + +SegOffTo24Resident proc near + push cx + +; Convert AX:DX into 24 bit addr in AL, DX + + mov ch,ah + shl ax,4 + shr ch,4 ; CH = high byte + add dx,ax ; DX = low word + mov al,ch ; AL = high byte + adc al,0 ; propagate cy from low word + + pop cx + ret +SegOffTo24Resident endp + +_TEXT ENDS +END + \ No newline at end of file -- cgit v1.2.3