summaryrefslogtreecommitdiffstats
path: root/private/mvdm/dos/v86/dev/himem/himem4.asm
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/mvdm/dos/v86/dev/himem/himem4.asm674
1 files changed, 674 insertions, 0 deletions
diff --git a/private/mvdm/dos/v86/dev/himem/himem4.asm b/private/mvdm/dos/v86/dev/himem/himem4.asm
new file mode 100644
index 000000000..085d87847
--- /dev/null
+++ b/private/mvdm/dos/v86/dev/himem/himem4.asm
@@ -0,0 +1,674 @@
+;/* himem4.asm
+; *
+; * Microsoft Confidential
+; * Copyright (C) Microsoft Corporation 1988-1991
+; * All Rights Reserved.
+; *
+; * Modification History
+; *
+; * Sudeepb 14-May-1991 Ported for NT XMS support
+; *
+; * williamh 25-Sept-1992 Added RequestUMB and ReleaseUMB
+; *
+; * daveh 1-Feb-1994 Changed to do mem management on 32 bit side
+; */
+ page 95,160
+ title himem4 - block allocation stuff
+
+ .xlist
+ include himem.inc
+ include xmssvc.inc
+ include vint.inc
+ .list
+
+; The stuff we provide:
+
+ public Version
+ public QueryExtMemory
+ public AllocExtMemory
+ public FreeExtMemory
+ public LockExtMemory
+ public UnlockExtMemory
+ public GetExtMemoryInfo
+ public ReallocExtMemory
+ public end_of_hiseg
+ public textseg
+ public KiddValley
+ public KiddValleyTop
+ public cHandles
+ public RequestUMB
+ public ReleaseUMB
+
+; externals from himem.asm
+
+ extrn PrevInt15:dword
+ extrn Moveit:word
+ extrn fHMAMayExist:byte
+ extrn fHMAExists:byte
+ extrn winbug_fix:word
+ extrn FLclEnblA20:far
+ extrn FLclDsblA20:far
+_text ends
+
+funky segment word public 'funky'
+ assume cs:funky,ds:_text
+
+ extrn end_of_funky_seg:near
+
+ org HISEG_ORG
+
+ public LEnblA20
+ public LDsblA20
+
+end_of_hiseg dw end_of_funky_seg
+textseg dw _text
+KiddValley dw end_of_funky_seg; The address of the handle table
+KiddValleyTop dw 0 ; end of handle table
+cHandles dw DEFHANDLES ; number of handles
+LEnblA20 dd _text:FLclEnblA20
+LDsblA20 dd _text:FLclDsblA20
+;*----------------------------------------------------------------------*
+;* *
+;* Get XMS Version Number - FUNCTION 00h *
+;* *
+;* Returns the XMS version number *
+;* *
+;* ARGS: None *
+;* RETS: AX = XMS Version Number *
+;* BX = Internal Driver Version Number *
+;* DX = 1 if HMA exists, 0 if it doesn't *
+;* REGS: AX, BX and DX are clobbered *
+;* *
+;* INTERNALLY REENTRANT *
+;* *
+;*----------------------------------------------------------------------*
+
+
+Version proc far
+
+ mov ax,XMSVersion
+ mov bx,HimemVersion
+ xor dh,dh
+
+; Is Int 15h hooked?
+
+ cmp word ptr [PrevInt15][2],0 ; Is the segment non-zero?
+ jne VHooked
+ mov dl,[fHMAMayExist] ; No, return the status at
+ ret ; init time.
+
+VHooked:
+ mov dl,[fHMAExists] ; Yes, return the real status
+ ret
+
+Version endp
+
+;*----------------------------------------------------------------------*
+;* *
+;* QueryExtMemory - FUNCTION 08h *
+;* *
+;* Returns the size of the largest free extended memory block in K *
+;* *
+;* ARGS: None *
+;* RETS: AX = Size of largest free block in K. BL = Error code *
+;* DX = Total amount of free extended memory in K *
+;* REGS: AX, BX, DX, DI, SI and Flags clobbered *
+;* *
+;* INTERNALLY REENTRANT *
+;* *
+;*----------------------------------------------------------------------*
+
+QueryExtMemory proc far
+
+ mov bl,0 ; assume no error
+ XMSSVC XMS_QUERYEXTMEM
+ test dx,dx
+ jne QEM20
+
+ mov bl,ERR_OUTOMEMORY
+QEM20:
+ ret
+
+QueryExtMemory endp
+
+
+;*----------------------------------------------------------------------*
+;* *
+;* AllocExtMemory - FUNCTION 09h *
+;* *
+;* Reserve a block of extended memory *
+;* *
+;* ARGS: DX = Amount of K being requested *
+;* RETS: AX = 1 of successful, 0 otherwise. BL = Error Code *
+;* DX = 16-bit handle to the allocated block *
+;* REGS: AX, BX, DX and Flags clobbered *
+;* *
+;* Notice: called internally from ReallocExtMemory *
+;* *
+;* INTERNALLY NON-REENTRANT *
+;* *
+;*----------------------------------------------------------------------*
+
+hFreeBlock dw ?
+hUnusedBlock dw ?
+
+AllocExtMemoryNear proc near
+AllocExtMemoryNear endp
+AllocExtMemory proc far
+
+ call FunkyCLI ; This is a non-reentrant function
+
+; Scan the handle table looking for an unused handle
+
+ xor ax,ax
+ mov [hUnusedBlock],ax
+ mov bx,[KiddValley]
+ mov cx,[cHandles] ; Loop through the handle table
+
+; Have we already found a free block which is large enough?
+
+AEMhLoop:
+
+ cmp [bx].Flags,UNUSEDFLAG ; Is this block unused?
+ jne AEMNexth ; No, get the next handle
+
+ mov [hUnusedBlock],bx ; save this guy away
+ jmp AEMGotHandle
+
+AEMNexth:
+ add bx,SIZE Handle ; go check the next handle
+ loop AEMhLoop
+
+; We are at the end of the handle table and we didn't an unused
+; handle
+
+ jmp AEMOOHandles ; No, Case 4 - We're out of handles
+
+AEMGotHandle:
+
+ mov di,[hUnusedBlock]
+
+ XMSSVC XMS_ALLOCBLOCK ; ax=Base and dx=Size
+ or ax,ax
+ jz AEMOOMemory
+
+ mov [di].Base,ax
+ mov [di].Len,dx
+ mov [di].Flags,USEDFLAG ; New.Flags = USED
+
+ if keep_cs
+ mov ax,callers_cs
+ mov [si].Acs,ax ; keep track of allocator's cs:
+ endif
+
+ mov dx,[hUnusedBlock]
+ mov ax,1
+ xor bl,bl
+ ret
+
+AEMOOMemory:
+ mov bl,ERR_OUTOMEMORY
+ jmp short AEMErrRet
+
+AEMOOHandles:
+ mov bl,ERR_OUTOHANDLES
+AEMErrRet:
+ xor ax,ax ; Return failure
+ mov dx,ax
+ ret
+AllocExtMemory endp
+
+;*----------------------------------------------------------------------*
+;* *
+;* FreeExtMemory - FUNCTION 0Ah *
+;* *
+;* Frees a block of extended memory *
+;* *
+;* ARGS: DX = 16-bit handle to the extended memory block *
+;* RETS: AX = 1 if successful, 0 otherwise. BL = Error code *
+;* REGS: AX, BX, CX, DX, SI, DI and Flags clobbered *
+;* *
+;* called internally from ReallocExtMemory *
+;* *
+;* INTERNALLY NON-REENTRANT *
+;* *
+;*----------------------------------------------------------------------*
+
+FreeExtMemoryNear proc near
+FreeExtMemoryNear endp
+
+FreeExtMemory proc far
+ call FunkyCLI ; This is a non-reentrant function
+
+ call ValidateHandle ; Make sure handle is valid
+ jnc FEMBadh
+ mov si,dx ; Move the handle into SI
+
+ cmp [si].cLock,0 ; make sure it points to unlocked block
+ jne FEMLockedh
+
+ mov [si].Flags,UNUSEDFLAG ; mark it as UNUSED
+ cmp [si].Len,0 ; if zero length block
+ jz FEMExit ; done if it was zero length
+
+ mov ax,[si].Base
+ mov dx,[si].Len
+ XMSSVC XMS_FREEBLOCK ; ax=base dx=size in k
+ or ax,ax
+ je FEMBadh
+
+FEMExit:
+
+ mov ax,1 ; Return success
+ xor bl,bl
+ ret
+
+FEMBadh:
+ mov bl,ERR_INVALIDHANDLE
+ jmp short FEMErrExit
+
+FEMLockedh:
+ mov bl,ERR_EMBLOCKED
+FEMErrExit:
+ xor ax,ax ; Return failure
+ ret
+FreeExtMemory endp
+
+
+;*----------------------------------------------------------------------*
+;* *
+;* LockExtMemory - FUNCTION 0Ch *
+;* *
+;* Locks a block of extended memory *
+;* *
+;* ARGS: DX = 16-bit handle to the extended memory block *
+;* RETS: AX = 1 of successful, 0 otherwise. BL = Error code *
+;* DX:BX = 32-bit linear address of the base of the memory block *
+;* REGS: AX, BX, DX and Flags clobbered *
+;* *
+;* INTERNALLY NON-REENTRANT *
+;* *
+;*----------------------------------------------------------------------*
+
+LockExtMemory proc far
+
+ call FunkyCLI ; This is a non-reentrant function
+
+ call ValidateHandle ; Is the handle valid?
+ jnc LEMBadh
+ mov bx,dx ; Move the handle into BX
+
+; Are we at some preposterously large limit?
+
+ cmp [bx].cLock,0FFh
+ je LEMOverflow
+
+ inc [bx].cLock ; lock the block
+
+ mov dx,[bx].Base ; return the 32-bit address of base
+ mov bx,dx
+ shr dx,6
+ shl bx,10
+
+ mov ax,1 ; return success
+ ret
+
+LEMBadh:
+ mov bl,ERR_INVALIDHANDLE
+ jmp short LEMErrExit
+
+LEMOverflow:
+ mov bl,ERR_LOCKOVERFLOW
+LEMErrExit:
+ xor ax,ax ; Return failure
+ mov dx,ax
+ ret
+
+LockExtMemory endp
+
+
+;*----------------------------------------------------------------------*
+;* *
+;* UnlockExtMemory - FUNCTION 0Dh *
+;* *
+;* Unlocks a block of extended memory *
+;* *
+;* ARGS: DX = 16-bit handle to the extended memory block *
+;* RETS: AX = 1 if successful, 0 otherwise. BL = Error code *
+;* REGS: AX, BX and Flags clobbered *
+;* *
+;* INTERNALLY NON-REENTRANT *
+;* *
+;*----------------------------------------------------------------------*
+
+UnlockExtMemory proc far
+
+ call FunkyCLI ; This is a non-reentrant function
+
+ call ValidateHandle ; Is the handle valid?
+ jnc UEMBadh
+ mov bx,dx ; Move the handle into BX
+
+ cmp [bx].cLock,0 ; is handle locked?
+ je UEMUnlocked ; No, return error
+
+ dec [bx].cLock ; Unlock the block
+
+ mov ax,1 ; Return success
+ xor bl,bl
+ ret
+
+UEMUnlocked:
+ mov bl,ERR_EMBUNLOCKED
+ jmp short UEMErrExit
+
+UEMBadh:
+ mov bl,ERR_INVALIDHANDLE
+UEMErrExit:
+ xor ax,ax
+ ret
+
+UnlockExtMemory endp
+
+
+;*----------------------------------------------------------------------*
+;* *
+;* GetExtMemoryInfo - FUNCTION 0Eh *
+;* *
+;* Gets other information about an extended memory block *
+;* *
+;* ARGS: DX = 16-bit handle to the extended memory block *
+;* RETS: AX = 1 if successful, 0 otherwise. BL = Error code *
+;* BH = EMB's lock count *
+;* BL = Total number of unused handles in the system *
+;* DX = EMB's length *
+;* REGS: AX, BX, CX, DX and Flags clobbered *
+;* *
+;* INTERNALLY NON-REENTRANT *
+;* *
+;*----------------------------------------------------------------------*
+
+GetExtMemoryInfo proc far
+
+ call FunkyCLI ; This is a non-reentrant function
+
+ call ValidateHandle ; is the handle valid?
+ jnc GEMBadh
+ mov si,dx ; Move the handle into SI
+
+ xor al,al ; count number of UNUSED handles
+ mov bx,[KiddValley]
+ mov cx,[cHandles] ; Loop through the handle table
+GEMLoop:
+ cmp [bx].Flags,USEDFLAG ; Is this handle in use?
+ je GEMNexth ; Yes, continue
+ inc al ; No, increment the count
+GEMNexth:
+ add bx,SIZE Handle
+ loop GEMLoop
+
+ mov dx,[si].Len ; Length in DX
+ mov bh,[si].cLock ; Lock count in BH
+ mov bl,al
+ mov ax,1
+ ret
+
+GEMBadh:
+ mov bl,ERR_INVALIDHANDLE
+ xor ax,ax
+ ret
+
+GetExtMemoryInfo endp
+
+
+;*----------------------------------------------------------------------*
+;* *
+;* ReallocExtMemory - FUNCTION 0Fh *
+;* *
+;* Reallocates a block of extended memory *
+;* *
+;* ARGS: DX = 16-bit handle to the extended memory block *
+;* BX = new size for block *
+;* RETS: AX = 1 if successful, 0 otherwise. BL = Error code *
+;* REGS: trashes si,di,bx,cx,dx *
+;* *
+;* INTERNALLY NON-REENTRANT *
+;* *
+;*----------------------------------------------------------------------*
+
+; Define our memory move structure for calling the move function
+
+ReallocExtMemory proc far
+
+ call FunkyCLI ; This is a non-reentrant function
+
+ call ValidateHandle ; is the handle valid?
+ mov si,dx ; Move the handle into SI
+ mov dx,bx ; Move the new length into dx
+ mov bl,ERR_INVALIDHANDLE
+ jnc REMError
+
+ cmp [si].cLock,0 ; We can only work on unlocked EMBs
+ mov bl,ERR_EMBLOCKED
+ jnz REMError
+
+ mov bx,dx
+ cmp [si].Len,bx
+ je REMExit
+
+ mov ax,[si].Base
+ mov dx,[si].Len
+ XMSSVC XMS_REALLOCBLOCK ; ax = old base, dx = old size
+ cmp cx,0 ; cx = new base, bx = new size
+ je REM20
+
+ mov [si].Base,cx
+ mov [si].Len,bx
+REMExit:
+ mov ax,1 ; succesful return
+ xor bl,bl ; non-documented no-error return
+ ret
+
+REM20:
+ mov bl,ERR_OUTOMEMORY
+REMError:
+ xor ax,ax
+ ret
+
+ReallocExtMemory endp
+
+
+;*----------------------------------------------------------------------*
+;* *
+;* FindAdjacent unused blocks *
+;* *
+;* Scan through handle list looking for blocks adjacent *
+;* to a given handle. *
+;* *
+;* ARGS: SI handle of original block *
+;* RETS: DI = handle of adjacent block below or zero if none *
+;* BP = handle of adjacent block above or zero if none *
+;* *
+;* TRASHES: AX,BX,CX,DX *
+;* *
+;* messes with handle table - not reentrant - assumes ints disabled *
+;* *
+;*----------------------------------------------------------------------*
+
+FindAdjacent proc near
+
+ mov ax,[si].Base ; look for blocks ending here
+ mov dx,[si].Len
+ add dx,ax ; and ending here
+
+ xor di,di ; initialize to fail condition
+ mov bp,di
+
+ mov bx,[KiddValley] ; prepare to loop thru handle tab
+ mov cx,[cHandles]
+
+ push si ; preserve original handle
+
+FindAdj1:
+ cmp [bx].Flags,FREEFLAG
+ jnz FindAdj3 ; ignore blocks that aren't UNUSED
+ mov si,[bx].Base
+ cmp dx,si ; found beg block?
+ jnz FindAdj2 ; skip if not
+ mov bp,bx ; remember the handle
+ or di,di ; did we already find a follower?
+ jnz FindAdj9 ; we're done if so
+
+FindAdj2:
+ add si,[bx].Len ; find length
+ cmp si,ax ; does this block end at spec addr?
+ jnz FindAdj3 ; skip if not
+ mov di,bx ; remember the handle
+ or bp,bp ; did we already find a leader?
+ jnz FindAdj9 ; we're done if so
+
+FindAdj3:
+ add bx,SIZE handle
+ loop FindAdj1
+
+FindAdj9:
+ pop si ; restore original handle
+ ret
+;
+
+FindAdjacent endp
+
+
+;*----------------------------------------------------------------------*
+;* *
+;* ValidateHandle - *
+;* *
+;* Validates an extended memory block handle *
+;* *
+;* ARGS: DX = 16-bit handle to the extended memory block *
+;* RETS: Carry is set if the handle is valid *
+;* REGS: Preserved except the carry flag *
+;* *
+;*----------------------------------------------------------------------*
+
+ValidateHandle proc near
+
+ pusha ; Save everything
+ mov bx,dx ; Move the handle into BX
+
+; The handle must be equal to or above "KiddValley".
+
+ cmp bx,[KiddValley]
+ jb VHOne
+
+; The handle must not be above "KiddValleyTop".
+
+ cmp bx,[KiddValleyTop]
+ ja VHOne
+
+; (The handle-"KiddValley") must be a multiple of a handle's size.
+
+ sub dx,[KiddValley]
+ mov ax,dx
+ xor dx,dx
+ mov cx,SIZE Handle
+ div cx
+ or dx,dx ; Any remainder?
+ jnz VHOne ; Yup, it's bad
+
+; Does the handle point to a currently USED block?
+
+ cmp [bx].Flags,USEDFLAG
+ jne VHOne ; This handle is not being used.
+
+; The handle looks good to me...
+
+ popa ; Restore everything
+ stc ; Return success
+ ret
+
+VHOne:
+
+; It's really bad.
+ popa ; Restore everything
+ clc ; Return failure
+ ret
+
+ValidateHandle endp
+
+BlkMovX proc near
+ assume ds:_text
+ jmp MoveIt
+BlkMovX endp
+
+;-----------------------------------------------------------------------;
+;This is the routine for XMS function 16, request UMB.
+;
+; Input:
+; (DX) = requested size in paragraphs
+;
+; Output:
+; (AX) = 1 if request is granted and
+; (BX) = segment address of the requested block
+; (DX) = actual size allocated in paragraphs
+; = 0 if requtest failed and
+; (BL) = 0B0h if a smaller UMB is available
+; (BL) = 0B1h if no UMBs are available
+; (DX) = largest UMB available.
+;Modified: AX, BX, DX
+;
+;NOTE:
+;The funcition was implemented in the 32bits xms because
+;any memory we need for house keeping purpose are kept in extented memory
+;rather than in the UMB itself(DOS arena). Of course, it has the penalty
+;of ring transition each time a request being made. However, the major
+;allocator of UMBs is IO.SYS, the device driver of MS-DOS for devicehigh
+;and loadhigh during bootstrap. This should adjust the penalty a little bits.
+;
+;-----------------------------------------------------------------------;
+RequestUMB proc far
+ XMSSVC XMS_REQUESTUMB
+ ret
+RequestUMB endp
+
+
+;-----------------------------------------------------------------------;
+;This is the routine for XMS function 17, release UMB
+;
+; Input:
+; (DX) = segment of the UMB block to be released
+;
+; Output:
+; (AX) = 1 if the block was released successfully.
+; (AX) = 0 if the block couldn't be released and
+; (BL) = 0B2h if the given segment is invalid
+; Modified: AX, BX
+;
+;Note:
+; See note in RequestUMB
+;-----------------------------------------------------------------------;
+
+ReleaseUMB proc far
+ XMSSVC XMS_RELEASEUMB
+ ret
+ReleaseUMB endp
+
+ PUBLIC FunkyCLI
+FunkyCLI:
+ FCLI
+ ret
+
+ PUBLIC FunkySTI
+FunkySTI:
+ FSTI
+ ret
+
+;*----------------------------------------------------------------------*
+;* *
+;* NOTE: RequestUMB and ReleaseUMB will not be implemented by HIMEM. *
+;* *
+;*----------------------------------------------------------------------*
+
+funky ends
+ end
+