You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
559 lines
12 KiB
559 lines
12 KiB
;/* himem5.asm
|
|
; *
|
|
; * Microsoft Confidential
|
|
; * Copyright (C) Microsoft Corporation 1988-1991
|
|
; * All Rights Reserved.
|
|
; *
|
|
; * Modification History
|
|
; *
|
|
; * Sudeepb 14-May-1991 Ported for NT XMS support
|
|
; */
|
|
page 95,160
|
|
title himem5.asm - Extended Memory Moves
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; M001 : inserted a jmp $+2 between an out & in while reading the ISR
|
|
; M003 : fixed bug to do with not returning int 15h errors on a blockmove
|
|
; call.
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
.xlist
|
|
include himem.inc
|
|
include xmssvc.inc
|
|
include vint.inc
|
|
.list
|
|
|
|
|
|
extrn TopOfTextSeg:word
|
|
extrn hiseg:word
|
|
extrn pReqHdr:dword
|
|
extrn dd_int_loc:word
|
|
extrn interrupt:word
|
|
|
|
|
|
extrn fInHMA:byte
|
|
extrn EndText:byte
|
|
ifdef NEC_98
|
|
extrn InHMAMsg:byte
|
|
endif ;NEC_98
|
|
_text ends
|
|
|
|
funky segment word public 'funky'
|
|
assume cs:funky
|
|
|
|
extrn KiddValley:word
|
|
extrn KiddValleyTop:word
|
|
extrn end_of_hiseg:word
|
|
extrn textseg:word
|
|
extrn LEnblA20:dword
|
|
extrn LDsblA20:dword
|
|
extrn FunkyCLI:near
|
|
extrn FunkySTI:near
|
|
|
|
|
|
;******************************************************************************
|
|
;
|
|
; MoveBlock
|
|
; XMM Move Extended Memory Block
|
|
;
|
|
; Entry:
|
|
; ES:SI Points to structure containing:
|
|
; bCount dd ? ; Length of block to move
|
|
; SourceHandle dw ? ; Handle for souce
|
|
; SourceOffset dd ? ; Offset into source
|
|
; DestHandle dw ? ; Handle for destination
|
|
; DestOffset dd ? ; Offset into destination
|
|
;
|
|
; Return:
|
|
; AX = 1 Success
|
|
; AX = 0 Failure
|
|
; Error code in BL
|
|
;
|
|
; Registers Destroyed:
|
|
; Flags
|
|
;
|
|
;------------------------------------------------------------------------------
|
|
|
|
public MoveBlock
|
|
|
|
MoveBlock proc far
|
|
assume ds:_text
|
|
|
|
call FunkySTI ; Be nice
|
|
push bp ; Set up stack frame so we
|
|
mov bp, sp ; can have local variables
|
|
sub sp, 18 ; Space for local variables
|
|
|
|
; Following Ordering is used in xms.dll and should be retained
|
|
; as is or changed in both places.
|
|
|
|
Count = -4 ; Local DWORD for byte count
|
|
SrcLinear = -8
|
|
DstLinear = -12
|
|
MEReturn = -14 ; Local WORD for return code
|
|
SrcHandle = -16
|
|
DstHandle = -18
|
|
push bx
|
|
push dx
|
|
|
|
xor ax, ax
|
|
mov [bp.MEReturn], ax ; Assume success
|
|
mov [bp.SrcHandle], ax
|
|
mov [bp.DstHandle], ax
|
|
mov ax, word ptr es:[si].bCount ; Pick up length specified
|
|
mov word ptr [bp.Count], ax
|
|
mov cx, word ptr es:[si].bCount+2
|
|
mov word ptr [bp.Count+2], cx
|
|
or cx, ax
|
|
jcxz MEM2_Exit ; Exit immediately if zero
|
|
|
|
lea bx, [si].SourceHandle ; Normalize Source
|
|
call GetLinear ; Linear address in DX:AX
|
|
jc MEM2_SrcError ; Have Dest Error Code
|
|
|
|
mov word ptr [bp.SrcLinear], ax ; Save Linear address
|
|
mov word ptr [bp.SrcLinear+2], dx
|
|
mov [bp.SrcHandle], bx ; Save Handle for Unlock
|
|
|
|
lea bx, [si].DestHandle ; Normalize Destination
|
|
call GetLinear
|
|
jc MEM2_Error
|
|
|
|
mov word ptr [bp.DstLinear], ax ; Save Linear address
|
|
mov word ptr [bp.DstLinear+2], dx
|
|
mov [bp.DstHandle], bx ; Save Handle for Unlock
|
|
|
|
shr word ptr [bp.Count+2], 1 ; Make word count
|
|
rcr word ptr [bp.Count], 1
|
|
jc MEM2_InvCount ; Odd count not allowed
|
|
|
|
call LEnblA20
|
|
cmp ax, 1
|
|
jne MEM2_Error
|
|
|
|
XMSSVC XMS_MOVEBLOCK ; Call Worker
|
|
; Parameters on the stack
|
|
|
|
call LDSblA20
|
|
cmp ax, 1
|
|
jne MEM2_Error
|
|
|
|
MEM2_Exit:
|
|
mov bx, [bp.SrcHandle] ; Unlock Handles if necessary
|
|
or bx, bx
|
|
jz NoSrcHandle
|
|
dec [bx].cLock ; Unlock Source
|
|
NoSrcHandle:
|
|
mov bx, [bp.DstHandle]
|
|
or bx, bx
|
|
jz NoDstHandle
|
|
dec [bx].cLock ; Unlock Destination
|
|
NoDstHandle:
|
|
pop dx
|
|
pop bx
|
|
mov ax, 1
|
|
cmp word ptr [bp.MEReturn], 0
|
|
jz MEM2_Success
|
|
dec ax
|
|
mov bl, byte ptr [bp.MEReturn]
|
|
MEM2_Success:
|
|
mov sp, bp ; Unwind stack
|
|
pop bp
|
|
ret
|
|
|
|
MEM2_SrcError:
|
|
cmp bl, ERR_LENINVALID ; Invalid count
|
|
je MEM2_Error ; yes, no fiddle
|
|
sub bl, 2 ; Convert to Source error code
|
|
jmp short MEM2_Error
|
|
MEM2_InvCount:
|
|
mov bl, ERR_LENINVALID
|
|
MEM2_Error:
|
|
mov byte ptr [bp.MEReturn], bl ; Pass error code through
|
|
jmp short MEM2_Exit
|
|
MoveBlock endp
|
|
|
|
;*******************************************************************************
|
|
;
|
|
; GetLinear
|
|
; Convert Handle and Offset (or 0 and SEG:OFFSET) into Linear address
|
|
; Locks Handle if necessary
|
|
;
|
|
; Entry:
|
|
; ES:BX Points to structure containing:
|
|
; Handle dw
|
|
; Offset dd
|
|
; [BP.Count] Count of bytes to move
|
|
;
|
|
; Return:
|
|
; BX Handle of block (0 if conventional)
|
|
; AX:DX Linear address
|
|
; CARRY => Error
|
|
; Error code in BL
|
|
;
|
|
; Registers Destroyed:
|
|
; Flags, CX, DI
|
|
;
|
|
;-------------------------------------------------------------------------------
|
|
|
|
GetLinear proc near
|
|
push si
|
|
call FunkyCLI ; NO INTERRUPTS
|
|
mov si, word ptr es:[bx+2] ; Offset from start of handle
|
|
mov di, word ptr es:[bx+4] ; in DI:SI
|
|
mov bx, word ptr es:[bx] ; Handle in bx
|
|
or bx, bx
|
|
jz GL2_Conventional
|
|
|
|
test [bx].Flags, USEDFLAG ; Valid Handle?
|
|
jz GL2_InvHandle
|
|
|
|
mov ax, [bx].Len ; Length of Block
|
|
mov cx, 1024
|
|
mul cx ; mul is faster
|
|
sub ax, si
|
|
sbb dx, di ; DX:AX = max possible count
|
|
jc GL2_InvOffset ; Base past end of block
|
|
sub ax, word ptr [bp.Count]
|
|
sbb dx, word ptr [bp.Count+2]
|
|
jc GL2_InvCount ; Count too big
|
|
|
|
inc [bx].cLock ; Lock the Handle
|
|
mov ax, [bx].Base
|
|
mul cx
|
|
add ax, si ; Linear address
|
|
adc dx, di ; in DX:AX
|
|
|
|
GL2_OKExit:
|
|
clc
|
|
GL2_Exit:
|
|
call FunkySTI
|
|
pop si
|
|
ret
|
|
|
|
GL2_Conventional:
|
|
mov ax, di ; Convert SEG:OFFSET into
|
|
mov dx, 16 ; 24 bit address
|
|
mul dx
|
|
add ax, si
|
|
adc dx, 0 ; DX:AX has base address
|
|
mov di, dx
|
|
mov si, ax
|
|
add si, word ptr [bp.Count] ; Get End of Block + 1 in DI:SI
|
|
adc di, word ptr [bp.Count+2]
|
|
|
|
cmp di, 010h ; Make sure it doesn't wrap
|
|
ja GL2_InvCount ; past the end of the HMA
|
|
jb GL2_OKExit
|
|
cmp si, 0FFF0h
|
|
jbe GL2_OKExit ; Must be < 10FFF0h
|
|
GL2_InvCount:
|
|
mov bl, ERR_LENINVALID
|
|
jmp short GL2_Error
|
|
|
|
GL2_InvHandle:
|
|
mov bl, ERR_DHINVALID ; Dest handle invalid
|
|
jmp short GL2_Error
|
|
|
|
GL2_InvOffset:
|
|
mov bl, ERR_DOINVALID ; Dest Offset invalid
|
|
GL2_Error:
|
|
stc
|
|
jmp short GL2_Exit
|
|
|
|
GetLinear endp
|
|
|
|
|
|
;*----------------------------------------------------------------------*
|
|
;* *
|
|
;* pack_and_truncate - packs everything down into the *
|
|
;* lowest available memory and sets up variable for driver *
|
|
;* truncation, then terminates. *
|
|
;* *
|
|
;*----------------------------------------------------------------------*
|
|
|
|
ifdef NEC_98
|
|
HMALen dw ? ; Length of funky (without init code)
|
|
endif ;NEC_98
|
|
public pack_and_truncate
|
|
pack_and_truncate proc far
|
|
|
|
assume ds:_text,es:nothing
|
|
push ds
|
|
mov dx, offset _text:EndText ; end of text seg
|
|
add dx, 15
|
|
and dx, not 15 ; size of text seg including init code
|
|
|
|
mov ax, TopOfTextSeg ; end of resident text seg
|
|
or ax, ax
|
|
jnz @f
|
|
xor di, di
|
|
pop es
|
|
jmp short InitFailed
|
|
|
|
@@:
|
|
add ax, 15
|
|
and ax, not 15 ; size of resident text seg
|
|
|
|
sub dx, ax ; size of memory whole between
|
|
shr dx, 4 ; resident text seg and funky seg
|
|
; The funky seg should be moved down
|
|
; 'dx' number of paragraphs
|
|
mov ax, hiseg ; Get the current seg at which funky
|
|
; is running from
|
|
|
|
cmp ax, dx ; If funky is already running from a
|
|
; segment value less than 'dx'
|
|
; number of paras funky can be
|
|
; moved to zero segment only
|
|
jbe @f
|
|
mov ax, dx ; ax has min of seg of funky
|
|
; & memory whole size in para
|
|
@@:
|
|
or ax, ax ; if funky is to be moved by zero
|
|
; paras our job is over
|
|
jnz @f
|
|
mov es, hiseg
|
|
assume es:funky
|
|
mov di, es:KiddValleyTop
|
|
jmp NoMoveEntry
|
|
@@:
|
|
mov dx, hiseg ; current segment value of funky
|
|
push ds
|
|
pop es
|
|
assume es:_text
|
|
mov ds, dx ; which is our source for move
|
|
assume ds:nothing
|
|
sub dx, ax ; less the 'paras' to be shrinked
|
|
mov hiseg, dx ; is the new seg value of funky
|
|
mov es, dx ; which is our dest. for the move
|
|
assume es:nothing
|
|
mov si, HISEG_ORG
|
|
mov di, si
|
|
mov cx, end_of_hiseg
|
|
sub cx, si ; size of funky without ORG
|
|
cld
|
|
rep movsb ; move it!!!
|
|
|
|
;;
|
|
MoveHandleTable:
|
|
inc di ; round to word value
|
|
and di,0fffeh
|
|
|
|
mov si,di
|
|
assume es:funky
|
|
xchg si,es:KiddValley ; replace KiddValley with new location
|
|
mov cx,es:KiddValleyTop
|
|
sub cx,si
|
|
|
|
rep movsb ; move the handle table down
|
|
mov es:KiddValleyTop,di ; update end of table
|
|
assume es:nothing
|
|
|
|
NoMoveEntry:
|
|
pop ds ; restore _text segment
|
|
assume ds:_text
|
|
add di,15 ; round new segment to paragraph
|
|
and di,not 15
|
|
|
|
ifndef NEC_98
|
|
InitFailed:
|
|
ifdef debug_tsr
|
|
mov ax,ds ; # paragraphs to keep =
|
|
mov dx,es ; (ES - DS) +
|
|
sub dx,ax ; (DI >> 4) +
|
|
mov ax,di ; 10h
|
|
shr ax,4
|
|
add dx,ax
|
|
add dx,10h ; PSP size
|
|
mov ax,3100h
|
|
int 21h
|
|
else
|
|
lds si,[pReqHdr] ; discard the initialization code
|
|
mov word ptr ds:[si].Address[0],di
|
|
mov word ptr ds:[si].Address[2],es
|
|
mov ds:[si].Status,100h ; Store return code - DONE
|
|
|
|
pop ax ; throw away return from InitDriver
|
|
|
|
push cs
|
|
call an_iret ; call an iret in our segment
|
|
|
|
or di, di
|
|
jz we_are_quitting
|
|
|
|
mov ds, textseg
|
|
assume ds:_text
|
|
mov ax, hiseg
|
|
mov dd_int_loc,offset Interrupt ; replace Interrupt with
|
|
; tiny permanent stub
|
|
|
|
mov ax, KiddValleyTop
|
|
sub ax, KiddValley
|
|
add ax, end_of_hiseg
|
|
sub ax, HISEG_ORG ; size of resident funky including
|
|
mov cs:HMALen, ax
|
|
|
|
mov ax, ((multMULT shl 8)+multMULTGETHMAPTR)
|
|
xor bx, bx ; in case there is no HMA handler
|
|
int 2fh
|
|
cmp cs:HMALen, bx
|
|
ja we_are_quitting
|
|
|
|
cmp di, HISEG_ORG
|
|
ja we_are_quitting
|
|
|
|
mov bx, cs:HMALen
|
|
mov ax, ((multMULT shl 8)+multMULTALLOCHMA)
|
|
int 2fh
|
|
cmp di, 0ffffh
|
|
je we_are_quitting
|
|
|
|
call MoveHi
|
|
|
|
we_are_quitting:
|
|
pop bp
|
|
pop si
|
|
pop di
|
|
pop es
|
|
pop ds
|
|
pop dx
|
|
pop cx
|
|
pop bx
|
|
pop ax
|
|
ret ; far return from driver init
|
|
endif
|
|
else ;NEC_98
|
|
ifdef debug_tsr
|
|
mov dx,di
|
|
shr dx,4 ; get # paragraphs to retain
|
|
mov ax,3100h
|
|
int 21h
|
|
else
|
|
InitFailed:
|
|
lds si,[pReqHdr] ; discard the initialization code
|
|
mov word ptr ds:[si].Address[0],di
|
|
mov word ptr ds:[si].Address[2],es
|
|
mov ds:[si].Status,100h ; Store return code - DONE
|
|
|
|
pop ax ; throw away return from InitDriver
|
|
|
|
push cs
|
|
call an_iret ; call an iret in our segment
|
|
|
|
or di, di
|
|
jz we_are_quitting
|
|
|
|
mov ds, textseg
|
|
assume ds:_text
|
|
mov ax, hiseg
|
|
mov dd_int_loc,offset Interrupt ; replace Interrupt with
|
|
; tiny permanent stub
|
|
|
|
mov ax, KiddValleyTop
|
|
sub ax, KiddValley
|
|
add ax, end_of_hiseg
|
|
sub ax, HISEG_ORG ; size of resident funky including
|
|
mov HMALen, ax
|
|
|
|
mov ax, ((multMULT shl 8)+multMULTGETHMAPTR)
|
|
int 2fh
|
|
cmp HMALen, bx
|
|
ja we_are_quitting
|
|
|
|
cmp di, HISEG_ORG
|
|
ja we_are_quitting
|
|
|
|
mov bx, HMALen
|
|
mov ax, ((multMULT shl 8)+multMULTALLOCHMA)
|
|
int 2fh
|
|
cmp di, 0ffffh
|
|
je we_are_quitting
|
|
|
|
call MoveHi
|
|
|
|
we_are_quitting:
|
|
pop bp
|
|
pop si
|
|
pop di
|
|
pop es
|
|
pop ds
|
|
pop dx
|
|
pop cx
|
|
pop bx
|
|
pop ax
|
|
ret ; far return from driver init
|
|
endif
|
|
endif ;NEC_98
|
|
|
|
pack_and_truncate endp
|
|
|
|
ifndef NEC_98
|
|
HMALen dw ? ; Length of funky (without init code)
|
|
endif ;NEC_98
|
|
|
|
|
|
;
|
|
;---------------------------------------------------------------------------
|
|
;
|
|
; procedure : MoveHi
|
|
;
|
|
;---------------------------------------------------------------------------
|
|
;
|
|
MoveHi proc near
|
|
push di ; remember offset in HMA
|
|
mov si, HISEG_ORG
|
|
ifndef NEC_98
|
|
mov cx, cs:HMALen
|
|
else ;NEC_98
|
|
mov cx, HMALen
|
|
endif ;NEC_98
|
|
mov ax, textseg
|
|
mov ds, ax
|
|
assume ds:_text
|
|
mov ds, hiseg
|
|
assume ds:nothing
|
|
rep movsb ; move it to HMA
|
|
pop di ; get back offset in HMA
|
|
mov ax, HISEG_ORG
|
|
sub ax, di
|
|
shr ax, 1
|
|
shr ax, 1
|
|
shr ax, 1
|
|
shr ax, 1
|
|
mov bx, es
|
|
sub bx, ax
|
|
|
|
|
|
mov ax, textseg
|
|
mov ds, ax ; get addressability to text seg
|
|
assume ds:_text
|
|
mov fInHMA, 1 ; Flag that we are running from HMA
|
|
|
|
mov hiseg, bx
|
|
mov es, bx
|
|
|
|
mov di, TopOfTextSeg ; end of resident text code
|
|
mov ax, textseg
|
|
lds si, pReqHdr
|
|
assume ds:nothing
|
|
|
|
mov word ptr ds:[si].Address[0],di
|
|
mov word ptr ds:[si].Address[2],ax
|
|
|
|
ret
|
|
MoveHi endp
|
|
|
|
;
|
|
an_iret proc near
|
|
FIRET
|
|
an_iret endp
|
|
|
|
public end_of_funky_seg
|
|
end_of_funky_seg:
|
|
funky ends
|
|
end
|
|
|