Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

253 lines
5.2 KiB

/* xmsblock.c - XMS Extended block related routines
*
* xmsAllocBlock
* xmsFreeBlock
* xmsReallocBlock
* xmsMoveBlock
* xmsQueryExtMem
*
* Modification History:
*
* Sudeepb 15-May-1991 Created
*/
#include "xms.h"
#include <memory.h>
#include <string.h>
#include <xmssvc.h>
#include <softpc.h>
#include <mvdm.h>
/* xmsAllocBlock - Commit Memory for an EMB.
*
*
* Entry - DX - Size in K to allocate
*
* Exit
* SUCCESS
* Client (AX) - Start address of the EMB (in K)
*
* FAILURE
* Client (AX) = 0
*/
VOID xmsAllocBlock (VOID)
{
BOOL Success;
ULONG BaseAddress;
ULONG size;
size = getDX() * 1024;
if(size) {
//
// Ask for a chunk of memory
//
Success = SAAllocate(
ExtMemSA,
size,
&BaseAddress
);
if (!Success) {
DbgPrint("xmsAllocBlock:SAAlloc failed !!!!\n");
setAX(0);
return;
}
}
else
BaseAddress = 0;
ASSERT((USHORT)(BaseAddress / 1024) < 65535);
setAX((USHORT)(BaseAddress / 1024));
return;
}
/* xmsFreeBlock - Free Memory for an EMB.
*
*
* Entry - AX - Start address of the EMB (in K)
* DX - Size in K to free
*
* Exit
* SUCCESS
* Client (AX) = 1
*
* FAILURE
* Client (AX) = 0
*/
VOID xmsFreeBlock (VOID)
{
BOOL Success;
ULONG BaseAddress;
ULONG size;
BaseAddress = (getAX() * 1024);
size = getDX() * 1024;
Success = SAFree(
ExtMemSA,
size,
BaseAddress
);
if (!Success) {
DbgPrint("xmsFreeBlock:SAFree failed !!!!");
setAX(0);
return;
}
setAX(1);
return;
}
/* xmsReallocBlock - Change the size of an EMB.
*
*
* Entry - AX - Start address of the EMB (in K)
* DX - Original Size in K
* BX - New size in K
*
* Exit
* SUCCESS
* Client (CX) = New base of block
*
* FAILURE
* Client (AX) = 0
*/
VOID xmsReallocBlock (VOID)
{
BOOL Success;
ULONG BaseAddress;
ULONG NewAddress;
ULONG size;
ULONG NewSize;
size = getDX() * 1024;
NewSize = getBX() * 1024;
BaseAddress = getAX() * 1024;
if(size != NewSize) {
//
// Realloc the chunk of memory
//
Success = SAReallocate(
ExtMemSA,
size,
BaseAddress,
NewSize,
&NewAddress
);
if (!Success) {
DbgPrint("xmsReallocBlock:SARealloc failed !!!!\n");
setCX(0);
return;
}
}
else
{
NewAddress = BaseAddress;
}
ASSERT((NewAddress / 1024) < 65535);
setCX((USHORT)(NewAddress / 1024));
return;
}
/* xmsMoveBlock - Process Move Block Functions
*
*
* Entry - Client (SS:BP) Pointer to Ext. Memory Move Structure
* SS:BP-4 = DWORD Transfer Count in words (guaranteed even)
* SS:BP-8 = DWORD Src Linear Address
* SS:BP-12 = DWORD Dst Linear Address
*
* Exit
* SUCCESS
* Client (AX) = 1
*
* FAILURE
* Client (AX) = 0
* Client (BL) = error code
*
* NOTE: For Overlapping regions XMS spec says "If the Source and
* Destination blocks overlap, only forward moves (i.e. where
* the destination base is less than the source base) are
* guaranteed to work properly"
*/
VOID xmsMoveBlock (VOID)
{
PBYTE pExtMoveInfo,pSrc,pDst;
ULONG cbTransfer,SoftpcBase, DstSegOff;
pExtMoveInfo = (PBYTE) GetVDMAddr(getSS(),getBP());
(ULONG)pExtMoveInfo = (ULONG)pExtMoveInfo -4;
cbTransfer = (FETCHDWORD(*(PULONG)pExtMoveInfo));
cbTransfer *= 2; // Get in bytes
(ULONG)pExtMoveInfo = (ULONG)pExtMoveInfo -4;
(DWORD)pSrc = FETCHDWORD(*(PULONG)pExtMoveInfo);
(ULONG)pExtMoveInfo = (ULONG)pExtMoveInfo -4;
(DWORD)pDst = FETCHDWORD(*(PULONG)pExtMoveInfo);
// Yes, we could use memmov for handling the overlapping regions
// but XMS spec wants memcpy behaviour.
#ifdef i386
RtlCopyMemory (pDst,pSrc,cbTransfer);
#else
SoftpcBase = (ULONG) GetVDMAddr (0,0);
RtlCopyMemory((PVOID)((ULONG)pDst + SoftpcBase),
(PVOID)((ULONG)pSrc + SoftpcBase),
cbTransfer);
// if we touched the intel memory, tell the emulator to flush its cache
// WARNING!!!! Donot use Sim32FlushVDMPoiner unless you know the exact segment
// address. In this case, we have no idea what the segment value is, all we
// know is its "linear address".
// BUGBUG verify whether we can ignore the case with pDst > 0x110000
sas_overwrite_memory(pDst, cbTransfer);
#endif
setAX(1);
return;
}
/* xmsQueryExtMem - Process query extended memory
*
*
* Entry - None
*
* Exit
* SUCCESS
* Client (AX) = Largest Free Block in K
* Client (DX) = Free Memory in K
*
* FAILURE
* Client (AX) = 0
* Client (DX) = 0
*
*/
VOID xmsQueryFreeExtMem(VOID)
{
ULONG LargestFree = 0;
ULONG TotalFree = 0;
//
// Find out how much memory remains
//
SAQueryFree(
ExtMemSA,
&TotalFree,
&LargestFree
);
ASSERT((TotalFree / 1024) < 65534);
setAX((USHORT)(TotalFree / 1024));
ASSERT((LargestFree / 1024) < 65534);
setDX((USHORT)(LargestFree / 1024));
}