diff --git a/src/ints/ems.cpp b/src/ints/ems.cpp index 52b8a6a3..063af139 100644 --- a/src/ints/ems.cpp +++ b/src/ints/ems.cpp @@ -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;index0x7fff) 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()=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())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_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(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=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=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_indexXMS_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[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) || !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) 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 (nextxms_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 (nextsizeDelta) { - // 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(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