diff options
Diffstat (limited to '')
-rw-r--r-- | private/mvdm/dos/v86/dev/himem/himem4.asm | 674 |
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 + |