1
0
Fork 0

Changes for new allocation system

Changes for new page mapping system


Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1113
This commit is contained in:
Sjoerd van der Berg 2003-07-14 08:20:33 +00:00
parent 695d8e91d4
commit 84b3d2d4c2
3 changed files with 126 additions and 387 deletions

View file

@ -22,6 +22,7 @@
#include "dosbox.h"
#include "callback.h"
#include "mem.h"
#include "paging.h"
#include "bios.h"
#include "keyboard.h"
#include "regs.h"
@ -29,9 +30,8 @@
#include "dos_inc.h"
#include "setup.h"
#define EMM_USEHANDLER 1
#define EMM_PAGEFRAME 0xE000
#define EMM_PAGEFRAME4K ((EMM_PAGEFRAME*16)/4096)
#define EMM_MAX_HANDLES 50 /* 255 Max */
#define EMM_PAGE_SIZE (16*1024)
#define EMM_MAX_PAGES (32 * 1024 / 16 )
@ -82,26 +82,17 @@ struct EMM_Mapping {
Bit16u page;
};
struct EMM_Page {
HostPt memory;
Bit16u handle;
Bit16u next;
};
struct EMM_Handle {
Bit16u first_page;
Bit16u pages;
MemHandle mem;
char name[8];
bool saved_page_map;
EMM_Mapping page_map[EMM_MAX_PHYS];
};
static EMM_Handle emm_handles[EMM_MAX_HANDLES];
static EMM_Page emm_pages[EMM_MAX_PAGES];
static EMM_Mapping emm_mappings[EMM_MAX_PHYS];
static HostPt emm_pagebase[EMM_MAX_PHYS];
static Bitu emm_page_count;
Bitu call_int67;
static Bitu call_int67;
struct MoveRegion {
Bit32u bytes;
@ -115,26 +106,10 @@ struct MoveRegion {
Bit16u dest_page_seg;
};
#if EMM_USEHANDLER
Bit8u EMM_ReadHandler(PhysPt start) {
start-=EMM_PAGEFRAME * 16;
Bitu page=start>>14;
return readb(emm_pagebase[page]+(start&0x3fff));
}
void EMM_WriteHandler(PhysPt start,Bit8u val) {
start-=EMM_PAGEFRAME * 16;
Bitu page=start>>14;
writeb(emm_pagebase[page]+(start&0x3fff),val);
}
#endif
static Bit16u EMM_GetFreePages(void) {
Bit16u count=0;
for (Bitu index=0;index<emm_page_count;index++) {
if (emm_pages[index].handle==NULL_HANDLE) count++;
}
return count;
Bitu count=MEM_FreeTotal()/4;
if (count>0x7fff) count=0x7fff;
return (Bit16u)count;
}
static bool INLINE ValidHandle(Bit16u handle) {
@ -147,118 +122,47 @@ static Bit8u EMM_AllocateMemory(Bit16u pages,Bit16u & handle) {
/* Check for 0 page allocation */
if (!pages) return EMM_ZERO_PAGES;
/* Check for enough free pages */
if (EMM_GetFreePages()<pages){ handle=NULL_HANDLE; return EMM_OUT_OF_LOG;}
if ((MEM_FreeTotal()/4)<pages) { handle=NULL_HANDLE; return EMM_OUT_OF_LOG;}
handle=1;
/* Check for a free handle */
while (emm_handles[handle].pages!=NULL_HANDLE) {
if (++handle>=EMM_MAX_HANDLES) {handle=NULL_HANDLE;return EMM_OUT_OF_HANDLES;}
}
/* Allocate the pages */
Bit16u page=0;Bit16u last=NULL_PAGE;
MemHandle mem=MEM_AllocatePages(pages*4,false);
if (!mem) E_Exit("EMS:Memory allocation failure");
emm_handles[handle].pages=pages;
while (pages) {
if (emm_pages[page].handle==NULL_HANDLE) {
emm_pages[page].handle=handle;
emm_pages[page].memory=(HostPt)malloc(EMM_PAGE_SIZE);
if (!emm_pages[page].memory) E_Exit("EMM:Cannont allocate memory");
if (last!=NULL_PAGE) emm_pages[last].next=page;
else emm_handles[handle].first_page=page;
last=page;
pages--;
} else {
if (++page>=emm_page_count) E_Exit("EMM:Ran out of pages");
}
}
emm_handles[handle].mem=mem;
return EMM_NO_ERROR;
}
static Bit8u EMM_ReallocatePages(Bit16u handle,Bit16u & pages) {
/* Check for valid handle */
if (handle>=EMM_MAX_HANDLES || emm_handles[handle].pages==NULL_HANDLE) return EMM_INVALID_HANDLE;
if (!ValidHandle(handle)) return EMM_INVALID_HANDLE;
/* Check for enough pages */
if ((emm_handles[handle].pages+EMM_GetFreePages())<pages) return EMM_OUT_OF_LOG;
Bit16u page=emm_handles[handle].first_page;
Bit16u last=page;
Bit16u page_count=emm_handles[handle].pages;
while (pages>0 && page_count>0) {
if (emm_pages[page].handle!=handle) E_Exit("EMM:Error illegal handle reference");
last=page;
page=emm_pages[page].next;
pages--;
page_count--;
}
/* Free the rest of the handles */
if (page_count && !pages) {
emm_handles[handle].pages-=page_count;
while (page_count>0) {
free(emm_pages[page].memory);
emm_pages[page].memory=0;
emm_pages[page].handle=NULL_HANDLE;
Bit16u next_page=emm_pages[page].next;
emm_pages[page].next=NULL_PAGE;
page=next_page;page_count--;
}
pages=emm_handles[handle].pages;
if (!pages) emm_handles[handle].first_page=NULL_PAGE;
return EMM_NO_ERROR;
}
if (!page_count && pages) {
/* Allocate extra pages */
emm_handles[handle].pages+=pages;
page=0;
while (pages) {
if (emm_pages[page].handle==NULL_HANDLE) {
emm_pages[page].handle=handle;
emm_pages[page].memory=(HostPt)malloc(EMM_PAGE_SIZE);
if (!emm_pages[page].memory) E_Exit("EMM:Cannont allocate memory");
if (last!=NULL_PAGE) emm_pages[last].next=page;
else emm_handles[handle].first_page=page;
last=page;
pages--;
} else {
if (++page>=emm_page_count) E_Exit("EMM:Ran out of pages");
}
}
pages=emm_handles[handle].pages;
return EMM_NO_ERROR;
}
/* Size exactly the same as the original size */
pages=emm_handles[handle].pages;
if (!MEM_ReAllocatePages(emm_handles[handle].mem,pages*4,false)) return EMM_OUT_OF_LOG;
/* Update size */
emm_handles[handle].pages=pages;
return EMM_NO_ERROR;
}
static Bit8u EMM_MapPage(Bitu phys_page,Bit16u handle,Bit16u log_page) {
// LOG_MSG("EMS MapPage handle %d phys %d log %d",handle,phys_page,log_page);
/* Check for too high physical page */
if (phys_page>=EMM_MAX_PHYS) return EMM_ILL_PHYS;
/* Check for valid handle */
if (handle>=EMM_MAX_HANDLES || emm_handles[handle].pages==NULL_HANDLE) return EMM_INVALID_HANDLE;
if (!ValidHandle(handle)) return EMM_INVALID_HANDLE;
/* Check to do unmapping or mappning */
if (log_page<emm_handles[handle].pages) {
/* Mapping it is */
emm_mappings[phys_page].handle=handle;
emm_mappings[phys_page].page=log_page;
Bit16u index=emm_handles[handle].first_page;
while (log_page) {
index=emm_pages[index].next;
if (index==NULL_PAGE) E_Exit("EMM:Detected NULL Page in chain");
log_page--;
}
/* Do the actual mapping */
#if EMM_USEHANDLER
emm_pagebase[phys_page]=(HostPt) emm_pages[index].memory;
#else
MEM_SetupMapping(PAGE_COUNT(PhysMake(EMM_PAGEFRAME,phys_page*EMM_PAGE_SIZE)),PAGE_COUNT(PAGE_SIZE),emm_pages[index].memory);
#endif
MEM_MapPages(EMM_PAGEFRAME4K+phys_page*4,emm_handles[handle].mem,log_page*4,4);
return EMM_NO_ERROR;
} else if (log_page==NULL_PAGE) {
/* Unmapping it is */
emm_mappings[phys_page].handle=NULL_HANDLE;
emm_mappings[phys_page].page=NULL_PAGE;
#if EMM_USEHANDLER
emm_pagebase[phys_page]=memory+EMM_PAGEFRAME*16+phys_page*16*1024;
#else
MEM_ClearMapping(PAGE_COUNT(PhysMake(EMM_PAGEFRAME,phys_page*EMM_PAGE_SIZE)),PAGE_COUNT(PAGE_SIZE));
#endif
MEM_UnmapPages(EMM_PAGEFRAME4K+phys_page*4,4);
return EMM_NO_ERROR;
} else {
/* Illegal logical page it is */
@ -268,19 +172,10 @@ static Bit8u EMM_MapPage(Bitu phys_page,Bit16u handle,Bit16u log_page) {
static Bit8u EMM_ReleaseMemory(Bit16u handle) {
/* Check for valid handle */
if (handle>=EMM_MAX_HANDLES || emm_handles[handle].pages==NULL_HANDLE) return EMM_INVALID_HANDLE;
Bit16u page=emm_handles[handle].first_page;
Bit16u pages=emm_handles[handle].pages;
while (pages) {
free(emm_pages[page].memory);
emm_pages[page].memory=0;
emm_pages[page].handle=NULL_HANDLE;
Bit16u next_page=emm_pages[page].next;
emm_pages[page].next=NULL_PAGE;
page=next_page;pages--;
}
if (!ValidHandle(handle)) return EMM_INVALID_HANDLE;
MEM_ReleasePages(emm_handles[handle].mem);
/* Reset handle */
emm_handles[handle].first_page=NULL_PAGE;
emm_handles[handle].mem=0;
emm_handles[handle].pages=NULL_HANDLE;
emm_handles[handle].saved_page_map=false;
memset(&emm_handles[handle].name,0,8);
@ -446,8 +341,8 @@ static void LoadMoveRegion(PhysPt data,MoveRegion & region) {
static Bit8u MemoryRegion(void) {
MoveRegion region;
Bit8u buf_src[EMM_PAGE_SIZE];
Bit8u buf_dest[EMM_PAGE_SIZE];
Bit8u buf_src[MEM_PAGE_SIZE];
Bit8u buf_dest[MEM_PAGE_SIZE];
if (reg_al>1) {
LOG(LOG_MISC,LOG_ERROR)("EMS:Call %2X Subfunction %2X not supported",reg_ah,reg_al);
return EMM_FUNC_NOSUP;
@ -455,46 +350,43 @@ static Bit8u MemoryRegion(void) {
LoadMoveRegion(SegPhys(ds)+reg_si,region);
/* Parse the region for information */
PhysPt src_mem,dest_mem;
Bit16u src_page,dest_page;Bitu src_off,dest_off;Bitu src_remain,dest_remain;
MemHandle src_handle,dest_handle;
Bitu src_off,dest_off;Bitu src_remain,dest_remain;
if (!region.src_type) {
src_mem=region.src_page_seg*16+region.src_offset;
} else {
if (!ValidHandle(region.src_handle)) return EMM_INVALID_HANDLE;
if (emm_handles[region.src_handle].pages*EMM_PAGE_SIZE < (region.src_page_seg*EMM_PAGE_SIZE)+region.src_offset+region.bytes) return EMM_LOG_OUT_RANGE;
src_page=emm_handles[region.src_handle].first_page;
while (region.src_page_seg>0) {
src_page=emm_pages[src_page].next;
region.src_page_seg--;
}
src_off=region.src_offset;
src_remain=EMM_PAGE_SIZE-src_off;
src_handle=emm_handles[region.src_handle].mem;
Bitu pages=region.src_page_seg*4+(region.src_offset/MEM_PAGE_SIZE);
for (;pages>0;pages--) src_handle=MEM_NextHandle(src_handle);
src_off=region.src_offset&(MEM_PAGE_SIZE-1);
src_remain=MEM_PAGE_SIZE-src_off;
}
if (!region.dest_type) {
dest_mem=region.dest_page_seg*16+region.dest_offset;
} else {
if (!ValidHandle(region.dest_handle)) return EMM_INVALID_HANDLE;
if (emm_handles[region.dest_handle].pages*EMM_PAGE_SIZE < (region.dest_page_seg*EMM_PAGE_SIZE)+region.dest_offset+region.bytes) return EMM_LOG_OUT_RANGE;
dest_page=emm_handles[region.dest_handle].first_page;
while (region.dest_page_seg>0) {
dest_page=emm_pages[dest_page].next;
region.dest_page_seg--;
}
dest_off=region.dest_offset;
dest_remain=EMM_PAGE_SIZE-dest_off;
dest_handle=emm_handles[region.dest_handle].mem;
Bitu pages=region.dest_page_seg*4+(region.dest_offset/MEM_PAGE_SIZE);
for (;pages>0;pages--) dest_handle=MEM_NextHandle(dest_handle);
dest_off=region.dest_offset&(MEM_PAGE_SIZE-1);
dest_remain=MEM_PAGE_SIZE-dest_off;
}
Bitu toread;
while (region.bytes>0) {
if (region.bytes>EMM_PAGE_SIZE) toread=EMM_PAGE_SIZE;
if (region.bytes>MEM_PAGE_SIZE) toread=MEM_PAGE_SIZE;
else toread=region.bytes;
/* Read from the source */
if (!region.src_type) {
MEM_BlockRead(src_mem,buf_src,toread);
} else {
if (toread<src_remain) {
memcpy(buf_src,emm_pages[src_page].memory+src_off,toread);
MEM_BlockRead((src_handle*MEM_PAGE_SIZE)+src_off,buf_src,toread);
} else {
memcpy(buf_src,emm_pages[src_page].memory+src_off,src_remain);
memcpy(buf_src+src_remain,emm_pages[emm_pages[src_page].next].memory,toread-src_remain);
MEM_BlockRead((src_handle*MEM_PAGE_SIZE)+src_off,buf_src,src_remain);
MEM_BlockRead((MEM_NextHandle(src_handle)*MEM_PAGE_SIZE),&buf_src[src_remain],toread-src_remain);
}
}
/* Check for a move */
@ -504,21 +396,21 @@ static Bit8u MemoryRegion(void) {
MEM_BlockRead(dest_mem,buf_dest,toread);
} else {
if (toread<dest_remain) {
memcpy(buf_dest,emm_pages[dest_page].memory+dest_off,toread);
MEM_BlockRead((dest_handle*MEM_PAGE_SIZE)+dest_off,buf_dest,toread);
} else {
memcpy(buf_dest,emm_pages[dest_page].memory+dest_off,dest_remain);
memcpy(buf_dest+dest_remain,emm_pages[emm_pages[dest_page].next].memory,toread-dest_remain);
MEM_BlockRead((dest_handle*MEM_PAGE_SIZE)+dest_off,buf_dest,dest_remain);
MEM_BlockRead((MEM_NextHandle(dest_handle)*MEM_PAGE_SIZE),&buf_dest[dest_remain],toread-dest_remain);
}
}
/* Write to the source */
if (!region.src_type) {
MEM_BlockWrite(src_mem,buf_dest,toread);
} else {
if (toread<(EMM_PAGE_SIZE-src_off)) {
memcpy(emm_pages[src_page].memory+src_off,buf_dest,toread);
if (toread<src_remain) {
MEM_BlockWrite((src_handle*MEM_PAGE_SIZE)+src_off,buf_dest,toread);
} else {
memcpy(emm_pages[src_page].memory+src_off,buf_dest,EMM_PAGE_SIZE-src_off);
memcpy(emm_pages[emm_pages[src_page].next].memory,buf_dest+EMM_PAGE_SIZE-src_off,toread-(EMM_PAGE_SIZE-src_off));
MEM_BlockWrite((src_handle*MEM_PAGE_SIZE)+src_off,buf_dest,src_remain);
MEM_BlockWrite((MEM_NextHandle(src_handle)*MEM_PAGE_SIZE),&buf_dest[src_remain],toread-src_remain);
}
}
}
@ -527,17 +419,17 @@ static Bit8u MemoryRegion(void) {
MEM_BlockWrite(dest_mem,buf_src,toread);
} else {
if (toread<dest_remain) {
memcpy(emm_pages[dest_page].memory+dest_off,buf_src,toread);
MEM_BlockWrite((dest_handle*MEM_PAGE_SIZE)+dest_off,buf_dest,toread);
} else {
memcpy(emm_pages[dest_page].memory+dest_off,buf_src,dest_remain);
memcpy(emm_pages[emm_pages[dest_page].next].memory,buf_src+dest_remain,toread-dest_remain);
MEM_BlockWrite((dest_handle*MEM_PAGE_SIZE)+dest_off,buf_src,dest_remain);
MEM_BlockWrite((MEM_NextHandle(dest_handle)*MEM_PAGE_SIZE),&buf_src[dest_remain],toread-dest_remain);
}
}
/* Advance the pointers */
if (!region.src_type) src_mem+=toread;
else src_page=emm_pages[src_page].next;
else src_handle=MEM_NextHandle(src_handle);
if (!region.dest_type) dest_mem+=toread;
else dest_page=emm_pages[dest_page].next;
else dest_handle=MEM_NextHandle(dest_handle);
region.bytes-=toread;
}
return EMM_NO_ERROR;
@ -554,7 +446,7 @@ static Bitu INT67_Handler(void) {
reg_ah=EMM_NO_ERROR;
break;
case 0x42: /* Get number of pages */
reg_dx=emm_page_count;
reg_dx=MEM_TotalPages()/4; //Not entirely correct but okay
reg_bx=EMM_GetFreePages();
reg_ah=EMM_NO_ERROR;
break;
@ -681,17 +573,9 @@ static Bitu INT67_Handler(void) {
}
void EMS_Init(Section* sec) {
Section_prop * section=static_cast<Section_prop *>(sec);
Bitu size=section->Get_int("emssize");
if (!size) return;
if ((size*(1024/16))>EMM_MAX_PAGES) {
LOG_MSG("EMS Max size is %d",EMM_MAX_PAGES/(1024/16));
emm_page_count=EMM_MAX_PAGES;
} else {
emm_page_count=size*(1024/16);
}
if (!section->Get_bool("ems")) return;
call_int67=CALLBACK_Allocate();
CALLBACK_Setup(call_int67,&INT67_Handler,CB_IRET);
/* Register the ems device */
@ -709,13 +593,8 @@ void EMS_Init(Section* sec) {
RealSetVec(0x67,RealMake(seg,0));
/* Clear handle and page tables */
Bitu i;
for (i=0;i<emm_page_count;i++) {
emm_pages[i].memory=0;
emm_pages[i].handle=NULL_HANDLE;
emm_pages[i].next=NULL_PAGE;
}
for (i=0;i<EMM_MAX_HANDLES;i++) {
emm_handles[i].first_page=NULL_PAGE;
emm_handles[i].mem=0;
emm_handles[i].pages=NULL_HANDLE;
memset(&emm_handles[i].name,0,8);
}
@ -723,13 +602,5 @@ void EMS_Init(Section* sec) {
emm_mappings[i].page=NULL_PAGE;
emm_mappings[i].handle=NULL_HANDLE;
}
#if EMM_USEHANDLER
/* Setup page handler */
MEM_SetupPageHandlers(PAGE_COUNT(EMM_PAGEFRAME*16),PAGE_COUNT(64*1024),EMM_ReadHandler,EMM_WriteHandler);
emm_pagebase[0]=memory+EMM_PAGEFRAME*16;
emm_pagebase[1]=memory+EMM_PAGEFRAME*16+16*1024;
emm_pagebase[2]=memory+EMM_PAGEFRAME*16+32*1024;
emm_pagebase[3]=memory+EMM_PAGEFRAME*16+48*1024;
#endif
}

View file

@ -60,12 +60,10 @@
#define XMS_BLOCK_LOCKED 0xab
struct XMS_Block {
Bit16u prev,next;
Bit16u size; /* Size in kb's */
PhysPt phys;
Bitu size;
MemHandle mem;
Bit8u locked;
bool allocated;
bool active;
bool free;
};
#pragma pack (push,1)
@ -103,18 +101,14 @@ static RealPt xms_callback;
static XMS_Block xms_handles[XMS_HANDLES];
static INLINE bool InvalidHandle(Bitu handle) {
return (!handle || (handle>=XMS_HANDLES) || xms_handles[handle].free);
}
Bitu XMS_QueryFreeMemory(Bit16u& largestFree, Bit16u& totalFree) {
/* Scan the tree for free memory and find largest free block */
Bit16u index=1;
largestFree=totalFree=0;
while (xms_handles[index].active) {
if (!xms_handles[index].allocated) {
if (xms_handles[index].size>largestFree) largestFree=xms_handles[index].size;
totalFree+=xms_handles[index].size;
}
if (xms_handles[index].next<XMS_HANDLES) index=xms_handles[index].next;
else break;
}
totalFree=(Bit16u)(MEM_FreeTotal()*4);
largestFree=(Bit16u)(MEM_FreeLargest()*4);
if (!totalFree) return XMS_OUT_OF_SPACE;
return 0;
};
@ -122,134 +116,89 @@ Bitu XMS_QueryFreeMemory(Bit16u& largestFree, Bit16u& totalFree) {
Bitu XMS_AllocateMemory(Bitu size, Bit16u& handle)
// size = kb
{
/* Find free handle */
Bit16u index=1;
/* First make reg_dx a multiple of PAGE_KB */
if (size & (PAGE_KB-1)) size=(size&(~(PAGE_KB-1)))+PAGE_KB;
while (xms_handles[index].active) {
/* Find a free block, check if there's enough size */
if (!xms_handles[index].allocated && xms_handles[index].size>=size) {
/* Check if block is bigger than request */
if (xms_handles[index].size>size) {
/* Split Block, find new handle and split up memory */
Bit16u new_index=1;
while (new_index<XMS_HANDLES) {
if (!xms_handles[new_index].active) goto foundnew;
new_index++;
}
handle = 0;
return XMS_OUT_OF_HANDLES;
foundnew:
xms_handles[new_index].next=xms_handles[index].next;
xms_handles[new_index].prev=index;
xms_handles[index].next=new_index;
xms_handles[index].locked=0;
xms_handles[new_index].active=true;
xms_handles[new_index].allocated=0;
xms_handles[new_index].locked=0;
xms_handles[new_index].size=xms_handles[index].size-size;
xms_handles[new_index].phys=xms_handles[index].phys+size*1024;
xms_handles[index].size=size;
}
/* Use the data from handle index to allocate the actual memory */
handle = index;
xms_handles[index].allocated = 1;
//CheckAllocationArea(xms_handles[index].phys,xms_handles[index].size*1024);
return 0;
}
/* Not a free block or too small advance to next one if possible */
if (xms_handles[index].next < XMS_HANDLES ) index=xms_handles[index].next;
else break;
while (!xms_handles[index].free) {
if (++index>XMS_HANDLES) return XMS_OUT_OF_HANDLES;
}
/* Found no good blocks give some errors */
return XMS_OUT_OF_SPACE;
Bitu pages=(size/4) + (size & 3) ? 1 : 0;
MemHandle mem=MEM_AllocatePages(pages,true);
if (!mem) return XMS_OUT_OF_SPACE;
xms_handles[index].free=false;
xms_handles[index].mem=mem;
xms_handles[index].locked=0;
xms_handles[index].size=size;
handle=index;
return 0;
};
Bitu XMS_FreeMemory(Bitu handle)
{
/* Check for a valid handle */
if (!handle || (handle>=XMS_HANDLES) || !xms_handles[handle].active || !xms_handles[handle].allocated ) {
return XMS_INVALID_HANDLE;
}
/* Free the memory in the block and merge the blocks previous and next block */
Bit16u prev=xms_handles[handle].prev;
Bit16u next=xms_handles[handle].next;
xms_handles[handle].allocated=0;
if ((next<XMS_HANDLES) && !xms_handles[next].allocated) {
xms_handles[next].active=false;
xms_handles[handle].size+=xms_handles[next].size;
xms_handles[handle].next=xms_handles[next].next;
next=xms_handles[handle].next;
if (next<XMS_HANDLES) xms_handles[next].prev=handle;
}
if ((prev<XMS_HANDLES) && !xms_handles[prev].allocated) {
xms_handles[handle].active=false;
xms_handles[prev].size+=xms_handles[handle].size;
next=xms_handles[handle].next;
xms_handles[prev].next=next;
if (next<XMS_HANDLES) xms_handles[next].prev=prev;
}
if (InvalidHandle(handle)) return XMS_INVALID_HANDLE;
MEM_ReleasePages(xms_handles[handle].mem);
xms_handles[handle].mem=-1;
xms_handles[handle].size=0;
xms_handles[handle].free=true;
return 0;
};
Bitu XMS_MoveMemory(PhysPt bpt)
{
XMS_MemMove block;
/* Fill the block with mem_read's and shit */
block.length=mem_readd(bpt+offsetof(XMS_MemMove,length));
block.src_handle=mem_readw(bpt+offsetof(XMS_MemMove,src_handle));
block.src.offset=mem_readd(bpt+offsetof(XMS_MemMove,src.offset));
block.dest_handle=mem_readw(bpt+offsetof(XMS_MemMove,dest_handle));
block.dest.offset=mem_readd(bpt+offsetof(XMS_MemMove,dest.offset));
PhysPt src,dest;
if (block.src_handle) {
if ((block.src_handle>=XMS_HANDLES) || !xms_handles[block.src_handle].active ||!xms_handles[block.src_handle].allocated) {
/* Read the block with mem_read's */
Bitu length=mem_readd(bpt+offsetof(XMS_MemMove,length));
Bitu src_handle=mem_readw(bpt+offsetof(XMS_MemMove,src_handle));
union {
RealPt realpt;
Bit32u offset;
} src,dest;
src.offset=mem_readd(bpt+offsetof(XMS_MemMove,src.offset));
Bitu dest_handle=mem_readw(bpt+offsetof(XMS_MemMove,dest_handle));
dest.offset=mem_readd(bpt+offsetof(XMS_MemMove,dest.offset));
PhysPt srcpt,destpt;
if (src_handle) {
if (InvalidHandle(src_handle)) {
return 0xa3; /* Src Handle invalid */
}
if (block.src.offset>=(xms_handles[block.src_handle].size*1024U)) {
if (src.offset>=(xms_handles[src_handle].size*1024U)) {
return 0xa4; /* Src Offset invalid */
}
if (block.length>xms_handles[block.src_handle].size*1024U-block.src.offset) {
if (length>xms_handles[src_handle].size*1024U-src.offset) {
return 0xa7; /* Length invalid */
}
src=xms_handles[block.src_handle].phys+block.src.offset;
srcpt=(xms_handles[src_handle].mem*4096)+src.offset;
} else {
src=Real2Phys(block.src.realpt);
srcpt=Real2Phys(src.realpt);
}
if (block.dest_handle) {
if ((block.dest_handle>=XMS_HANDLES) || !xms_handles[block.dest_handle].active ||!xms_handles[block.dest_handle].allocated) {
if (dest_handle) {
if (InvalidHandle(dest_handle)) {
return 0xa3; /* Dest Handle invalid */
}
if (block.dest.offset>=(xms_handles[block.dest_handle].size*1024U)) {
if (dest.offset>=(xms_handles[dest_handle].size*1024U)) {
return 0xa4; /* Dest Offset invalid */
}
if (block.length>xms_handles[block.dest_handle].size*1024U-block.dest.offset) {
if (length>xms_handles[dest_handle].size*1024U-dest.offset) {
return 0xa7; /* Length invalid */
}
dest=xms_handles[block.dest_handle].phys+block.dest.offset;
destpt=(xms_handles[dest_handle].mem*4096)+dest.offset;
} else {
dest=Real2Phys(block.dest.realpt);
destpt=Real2Phys(dest.realpt);
}
MEM_BlockCopy(dest,src,block.length);
// LOG_MSG("XMS move src %X dest %X length %X",srcpt,destpt,length);
mem_memcpy(destpt,srcpt,length);
return 0;
}
Bitu XMS_LockMemory(Bitu handle, Bit32u& address)
{
/* Check for a valid handle */
if (!handle || (handle>=XMS_HANDLES) || !xms_handles[handle].active || !xms_handles[handle].allocated ) {
return XMS_INVALID_HANDLE;
}
if (InvalidHandle(handle)) return XMS_INVALID_HANDLE;
if (xms_handles[handle].locked<255) xms_handles[handle].locked++;
address = xms_handles[handle].phys;
address = xms_handles[handle].mem*4096;
return 0;
};
Bitu XMS_UnlockMemory(Bitu handle)
{
/* Check for a valid handle */
if (!handle || (handle>=XMS_HANDLES) || !xms_handles[handle].active || !xms_handles[handle].allocated ) {
return XMS_INVALID_HANDLE;
}
if (InvalidHandle(handle)) return XMS_INVALID_HANDLE;
if (xms_handles[handle].locked) {
xms_handles[handle].locked--;
return 0;
@ -259,94 +208,27 @@ Bitu XMS_UnlockMemory(Bitu handle)
Bitu XMS_GetHandleInformation(Bitu handle, Bit8u& lockCount, Bit8u& numFree, Bit16u& size)
{
/* Check for a valid handle */
if (!handle || (handle>=XMS_HANDLES) || !xms_handles[handle].active || !xms_handles[handle].allocated ) {
return XMS_INVALID_HANDLE;
}
if (InvalidHandle(handle)) return XMS_INVALID_HANDLE;
lockCount = xms_handles[handle].locked;
/* Find available blocks */
numFree=0;{ for (Bitu i=1;i<XMS_HANDLES;i++) if (!xms_handles[i].allocated) numFree++;}
numFree=0;
for (Bitu i=1;i<XMS_HANDLES;i++) {
if (xms_handles[i].free) numFree++;
}
size=xms_handles[handle].size;
return 0;
};
Bitu XMS_ResizeMemory(Bitu handle, Bitu newSize)
{
/* Check for a valid handle */
if (!handle || (handle>=XMS_HANDLES) || !xms_handles[handle].active || !xms_handles[handle].allocated ) {
return XMS_INVALID_HANDLE;
}
if (InvalidHandle(handle)) return XMS_INVALID_HANDLE;
// Block has to be unlocked
if (xms_handles[handle].locked>0) return XMS_BLOCK_LOCKED;
if (newSize<xms_handles[handle].size) {
// shrink block...
Bit16u sizeDelta = xms_handles[handle].size - newSize;
Bit16u next = xms_handles[handle].next;
if ((next<XMS_HANDLES) && (xms_handles[next].active && !xms_handles[next].allocated)) {
// add size / set phys
xms_handles[next].size += sizeDelta;
xms_handles[next].phys -= sizeDelta*1024;
} else {
// next block is in use, create a new lonely unused one :)
Bit16u newindex=1;
while (newindex<XMS_HANDLES) {
if (!xms_handles[newindex].active) break;
newindex++;
}
if (newindex>=XMS_HANDLES) return XMS_OUT_OF_HANDLES;
xms_handles[newindex].active = true;
xms_handles[newindex].allocated = false;
xms_handles[newindex].locked = 0;
xms_handles[newindex].prev = handle;
xms_handles[newindex].next = next;
xms_handles[newindex].phys = xms_handles[handle].phys+newSize*1024;
xms_handles[newindex].size = sizeDelta;
xms_handles[handle] .next = newindex;
if (next<XMS_HANDLES) xms_handles[next].prev = newindex;
}
// Resize and allocate new mem
xms_handles[handle].size = newSize;
xms_handles[handle].allocated = 1;
//CheckAllocationArea(xms_handles[handle].phys,xms_handles[handle].size*1024);
} else if (newSize>xms_handles[handle].size) {
// Lets see if successor has enough free space to do that
Bit16u oldSize = xms_handles[handle].size;
Bit16u next = xms_handles[handle].next;
Bit16u sizeDelta = newSize - xms_handles[handle].size;
if (next<XMS_HANDLES && !xms_handles[next].allocated) {
if (xms_handles[next].size>sizeDelta) {
// remove size from it
xms_handles[next].size-=sizeDelta;
xms_handles[next].phys+=sizeDelta*1024;
} else if (xms_handles[next].size==sizeDelta) {
// exact match, skip it
xms_handles[handle].next = xms_handles[next].next;
xms_handles[next].active = false;
} else {
// Not enough mem available
LOG(LOG_MISC,LOG_ERROR)("XMS: Resize failure: out of mem 1");
return XMS_OUT_OF_SPACE;
};
// Resize and allocate new mem
xms_handles[handle].size = newSize;
xms_handles[handle].allocated = 1;
//CheckAllocationArea(xms_handles[handle].phys,xms_handles[handle].size*1024);
} else {
// No more free mem ?
LOG(LOG_MISC,LOG_ERROR)("XMS: Resize failure: out of mem 2");
return XMS_OUT_OF_SPACE;
};
};
return 0;
};
// Return size of xms mem in mb
static Bitu xms_size = 0;
Bitu XMS_GetSize(void) { return xms_size; };
Bitu pages=newSize/4 + (newSize & 3) ? 1 : 0;
if (MEM_ReAllocatePages(xms_handles[handle].mem,pages,true)) {
return 0;
} else return XMS_OUT_OF_SPACE;
}
static bool multiplex_xms(void) {
switch (reg_ax) {
@ -448,33 +330,22 @@ Bitu XMS_Handler(void) {
}
void XMS_Init(Section* sec) {
Section_prop * section=static_cast<Section_prop *>(sec);
Bitu size=section->Get_int("xmssize");
if (!size) return;
Bitu memavail=(MEM_TotalSize()-1088)/1024;
if (!section->Get_bool("ems")) return;
Bitu i;
if (size>memavail) size=memavail;
xms_size = size;
DOS_AddMultiplexHandler(multiplex_xms);
call_xms=CALLBACK_Allocate();
CALLBACK_Setup(call_xms,&XMS_Handler,CB_RETF);
xms_callback=CALLBACK_RealPointer(call_xms);
/* Setup the handler table */
Bitu i;
for (i=0;i<XMS_HANDLES;i++) {
xms_handles[i].active=false;
xms_handles[i].allocated=0;
xms_handles[i].next=0xffff;
xms_handles[i].prev=0xffff;
xms_handles[i].free=true;
xms_handles[i].mem=-1;
xms_handles[i].size=0;
xms_handles[i].locked=0;
}
/* Disable the 0 handle */
xms_handles[0].active =true;
xms_handles[0].allocated=true;
/* Setup the 1st handle */
xms_handles[1].active=true;
xms_handles[1].phys=1088*1024; /* right behind the hma area */
xms_handles[1].size=size*1024-64;
xms_handles[0].free = false;
}

View file

@ -19,9 +19,6 @@
#ifndef __XMS_H__
#define __XMS_H__
// Return size of xms mem in mb
Bitu XMS_GetSize (void);
Bitu XMS_QueryFreeMemory (Bit16u& largestFree, Bit16u& totalFree);
Bitu XMS_AllocateMemory (Bitu size, Bit16u& handle);
Bitu XMS_FreeMemory (Bitu handle);