From e712e7dc9ce14809f49cf10325a4d6fbf354549e Mon Sep 17 00:00:00 2001 From: Sjoerd van der Berg Date: Wed, 22 Oct 2003 14:30:57 +0000 Subject: [PATCH] Paging tables/functions changed somewhat Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1356 --- src/cpu/paging.cpp | 330 ++++++++++------------ src/hardware/memory.cpp | 592 +++++++++------------------------------- 2 files changed, 282 insertions(+), 640 deletions(-) diff --git a/src/cpu/paging.cpp b/src/cpu/paging.cpp index 8f6c68b9..6d777b72 100644 --- a/src/cpu/paging.cpp +++ b/src/cpu/paging.cpp @@ -23,169 +23,165 @@ #include "dosbox.h" #include "mem.h" #include "paging.h" -#include "../hardware/vga.h" - +#include "regs.h" #define LINK_TOTAL (64*1024) -static PageLink link_list[LINK_TOTAL]; -struct PagingBlock paging; +PagingBlock paging; +static Bit32u mapfirstmb[LINK_START]; -class PageDirChange : public PageChange { -public: - PageDirChange(PageDirectory * mydir) { dir=mydir;} - void Changed(PageLink * link,Bitu start,Bitu end) { - start>>=2;end>>=2; - for (;start<=end;start++) { - dir->InvalidateTable(start); - } - } -private: - PageDirectory * dir; +Bitu PageHandler::readb(PhysPt addr) { + E_Exit("No byte handler for read from %d",addr); + return 0; +} +Bitu PageHandler::readw(PhysPt addr) { + return + (readb(addr+0) << 0) | + (readb(addr+1) << 8); +} +Bitu PageHandler::readd(PhysPt addr) { + return + (readb(addr+0) << 0) | + (readb(addr+1) << 8) | + (readb(addr+2) << 16) | + (readb(addr+3) << 24); +} + +void PageHandler::writeb(PhysPt addr,Bitu val) { + E_Exit("No byte handler for write to %d",addr); }; -class PageTableChange : public PageChange { +void PageHandler::writew(PhysPt addr,Bitu val) { + writeb(addr+0,(Bit8u) (val >> 0)); + writeb(addr+1,(Bit8u) (val >> 8)); +} +void PageHandler::writed(PhysPt addr,Bitu val) { + writeb(addr+0,(Bit8u) (val >> 0)); + writeb(addr+1,(Bit8u) (val >> 8)); + writeb(addr+2,(Bit8u) (val >> 16)); + writeb(addr+3,(Bit8u) (val >> 24)); +}; + +HostPt PageHandler::GetHostPt(Bitu phys_page) { + return 0; +} + + +class InitPageHandler : public PageHandler { public: - PageTableChange(PageDirectory * mydir) { dir=mydir;} - void Changed(PageLink * link,Bitu start,Bitu end) { - start>>=2;end>>=2; - for (;start<=end;start++) { - dir->InvalidateLink(link->data.table,start); - } + InitPageHandler() {flags=0;} + void AddPageLink(Bitu lin_page, Bitu phys_page) { + assert(0); + } + Bitu readb(PhysPt addr) { + InitPage(addr); + return mem_readb(addr); + } + Bitu readw(PhysPt addr) { + InitPage(addr); + return mem_readw(addr); + } + Bitu readd(PhysPt addr) { + InitPage(addr); + return mem_readd(addr); + } + void writeb(PhysPt addr,Bitu val) { + InitPage(addr); + mem_writeb(addr,val); + } + void writew(PhysPt addr,Bitu val) { + InitPage(addr); + mem_writew(addr,val); + } + void writed(PhysPt addr,Bitu val) { + InitPage(addr); + mem_writed(addr,val); + } + void InitPage(Bitu addr) { + Bitu lin_page=addr >> 12; + Bitu phys_page; + if (paging.enabled) { + E_Exit("No paging support"); + } else { + if (lin_pagedata.dir=this; - link_dir->change=dir_change; - MEM_CheckLinks(link_dir->entry); -} -void PageDirectory::LinkPage(Bitu lin_page,Bitu phys_page) { - if (links[lin_page] != &link_init) MEM_UnlinkPage(links[lin_page]); - PageLink * link=MEM_LinkPage(phys_page,lin_page*4096); - if (link) links[lin_page]=link; - else links[lin_page]=&link_init; -} - -bool PageDirectory::InitPage(Bitu lin_address) { - Bitu lin_page=lin_address >> 12; - Bitu table=lin_page >> 10; - Bitu index=lin_page & 0x3ff; - /* Check if there already is table linked */ - if (!tables[table]) { - X86PageEntry table_entry; - table_entry.load=phys_page_readd(base_page,0); - if (!table_entry.block.p) { - LOG(LOG_PAGING,LOG_ERROR)("NP TABLE"); - return false; - } - PageLink * link=MEM_LinkPage(table_entry.block.base,table_entry.block.base); - if (!link) return false; - link->data.table=table; - link->change=table_change; - MEM_CheckLinks(link->entry); - tables[table]=link; - } - X86PageEntry entry; - entry.load=phys_page_readd(tables[table]->lin_base,index); - if (!entry.block.p) { - LOG(LOG_PAGING,LOG_ERROR)("NP PAGE"); - return false; - } - PageLink * link=MEM_LinkPage(entry.block.base,lin_page*4096); - if (!link) return false; - links[lin_page]=link; - return true; -} - - -bool PageDirectory::InitPageLinear(Bitu lin_address) { - Bitu phys_page=lin_address >> 12; - PageLink * link=MEM_LinkPage(phys_page,phys_page*4096); - if (link) { - /* Set the page entry in our table */ - links[phys_page]=link; - return true; - } - return false; -} - - -void PageDirectory::InvalidateTable(Bitu table) { - if (tables[table]) { - MEM_UnlinkPage(tables[table]); - tables[table]=0; - for (Bitu i=(table*1024);i<(table+1)*1024;i++) { - if (links[i]!=&link_init) { - MEM_UnlinkPage(links[i]); - links[i]=&link_init; - } - } - } -} - -void PageDirectory::InvalidateLink(Bitu table,Bitu index) { - Bitu i=(table*1024)+index; - if (links[i]!=&link_init) { - MEM_UnlinkPage(links[i]); - links[i]=&link_init; - } -} +static InitPageHandler init_page_handler; Bitu PAGING_GetDirBase(void) { return paging.cr3; } +void PAGING_ClearTLB(void) { + LOG(LOG_PAGING,LOG_NORMAL)("Clearing TLB"); + Bitu i; + for (i=0;i0;pages--) { + Bitu page=*entries++; + paging.tlb.read[page]=0; + paging.tlb.write[page]=0; + paging.tlb.handler[page]=&init_page_handler; + } +} + +void PAGING_LinkPage(Bitu lin_page,Bitu phys_page) { + + PageHandler * handler=MEM_GetPageHandler(phys_page); + Bitu lin_base=lin_page << 12; + + HostPt host_mem=handler->GetHostPt(phys_page); + paging.tlb.phys_page[lin_page]=phys_page; + if (handler->flags & PFLAG_READABLE) paging.tlb.read[lin_page]=host_mem-lin_base; + else paging.tlb.read[lin_page]=0; + if (handler->flags & PFLAG_WRITEABLE) paging.tlb.write[lin_page]=host_mem-lin_base; + else paging.tlb.write[lin_page]=0; + + handler->AddPageLink(lin_page,phys_page); + paging.tlb.handler[lin_page]=handler; +} + +void PAGING_MapPage(Bitu lin_page,Bitu phys_page) { + if (lin_page> 12; - LOG(LOG_PAGING,LOG_NORMAL)("CR3:%X Base %X",cr3,base_page); + + paging.base.page=cr3 >> 12; + paging.base.addr=cr3 & ~4095; + LOG(LOG_PAGING,LOG_NORMAL)("CR3:%X Base %X",cr3,paging.base.page); if (paging.enabled) { - /* Check if we already have this one cached */ - PageDirectory * dir=paging.cache; - while (dir) { - if (dir->base_page==base_page) { - paging.dir=dir; - return; - } - dir=dir->next; - } - /* Couldn't find cached directory, make a new one */ - dir=new PageDirectory(); - dir->next=paging.cache; - paging.cache=dir; - dir->SetBase(base_page); - paging.dir=dir; + PAGING_ClearTLB(); } } @@ -195,7 +191,6 @@ void PAGING_Enable(bool enabled) { paging.enabled=enabled; if (!enabled) { LOG(LOG_PAGING,LOG_NORMAL)("Disabled"); - paging.dir=MEM_DefaultDirectory(); } else { LOG(LOG_PAGING,LOG_NORMAL)("Enabled"); #if !(C_DEBUG) @@ -203,51 +198,20 @@ void PAGING_Enable(bool enabled) { #endif PAGING_SetDirBase(paging.cr3); } + PAGING_ClearTLB(); } bool PAGING_Enabled(void) { return paging.enabled; } - -void PAGING_FreePageLink(PageLink * link) { - MEM_UnlinkPage(link); - PAGING_AddFreePageLink(link); -} - -void PAGING_LinkPage(PageDirectory * dir,Bitu lin_page,Bitu phys_page) { - PageLink * link=MEM_LinkPage(phys_page,lin_page*4096); - /* Only replace if we can */ - if (link) { - PAGING_FreePageLink(dir->links[lin_page]); - dir->links[lin_page]=link; +void PAGING_Init(Section * sec) { + /* Setup default Page Directory, force it to update */ + paging.enabled=false; + PAGING_InitTLB(); + Bitu i; + for (i=0;iread=0; - link->write=0; - link->change=0; - link->next=paging.free_link; - link->entry=0; - paging.free_link=link; -} - -PageLink * PAGING_GetFreePageLink(void) { - PageLink * ret; - if (paging.free_link) ret=paging.free_link; - else E_Exit("PAGING:Ran out of PageEntries"); - paging.free_link=ret->next; - ret->next=0; - return ret; -} - -void PAGING_Init(Section * sec) { - Bitu i; - /* Setup the free pages tables for fast page allocation */ - paging.cache=0; - paging.free_link=0; - for (i=0;itype) { - case ENTRY_VGA: - return (*vga.config.readhandler)(pentry->data.vga_base+(address & 4095)); - case ENTRY_NA: - if (pentry->data.dir->InitPageLinear(address)) return mem_readb(address); - break; - case ENTRY_INIT: - if (pentry->data.dir->InitPage(address)) return mem_readb(address); - break; +class IllegalPageHandler : public PageHandler { +public: + void AddPageLink(Bitu lin_page, Bitu phys_page) { - default: - LOG(LOG_PAGING,LOG_ERROR)("Entry read from %X with illegal type %d",address,pentry->type); + } + IllegalPageHandler() { + flags=0; + } +}; + +class RAMPageHandler : public PageHandler { +public: + void AddPageLink(Bitu lin_page, Bitu phys_page) { + /* Always clear links in first MB on TLB change */ + if (lin_page=memory.lfb.start_page) && (phys_pagetype) { - case ENTRY_VGA: - { - VGA_ReadHandler * handler=vga.config.readhandler; - address=pentry->data.vga_base + (address & 4095); - return (*handler)(address) | - ((*handler)(address+1) << 8); - } - case ENTRY_NA: - if (pentry->data.dir->InitPageLinear(address)) return mem_readw(address); - break; - case ENTRY_INIT: - if (pentry->data.dir->InitPage(address)) return mem_readw(address); - break; - default: - LOG(LOG_PAGING,LOG_ERROR)("Entry read from %X with illegal type %d",address,pentry->type); - } - return 0; -} - -Bit32u ENTRY_readd(PageEntry * pentry,PhysPt address) { - switch(pentry->type) { - case ENTRY_VGA: - { - VGA_ReadHandler * handler=vga.config.readhandler; - address=pentry->data.vga_base + (address & 4095); - return (*handler)(address) | - ((*handler)(address+1) << 8) | - ((*handler)(address+2) << 16) | - ((*handler)(address+3) << 24); - } - case ENTRY_NA: - if (pentry->data.dir->InitPageLinear(address)) return mem_readd(address); - break; - case ENTRY_INIT: - if (pentry->data.dir->InitPage(address)) return mem_readd(address); - break; - default: - LOG(LOG_PAGING,LOG_ERROR)("Entry read from %X with illegal type %d",address,pentry->type); - } - return 0; -} - -void ENTRY_writeb(PageEntry * pentry,PhysPt address,Bit8u val) { - switch(pentry->type) { - case ENTRY_VGA: - (*vga.config.writehandler)(pentry->data.vga_base+(address&4095),val); - break; - case ENTRY_NA: - if (pentry->data.dir->InitPageLinear(address)) mem_writeb(address,val); - break; - case ENTRY_INIT: - if (pentry->data.dir->InitPage(address)) mem_writeb(address,val); - break; - case ENTRY_ROM: - LOG(LOG_PAGING,LOG_WARN)("Write %X to ROM at %X",val,address); - break; - case ENTRY_CHANGES: - writeb(pentry->data.mem+(address&4095),val); - { - Bitu start=address&4095;Bitu end=start; - for (PageLink * link=pentry->links;link;link=link->next) - if (link->change) link->change->Changed(link,start,end); - } - break; - default: - LOG(LOG_PAGING,LOG_ERROR)("Entry write %X to %X with illegal type %d",val,address,pentry->type); +void MEM_SetPageHandler(Bitu phys_page,Bitu pages,PageHandler * handler) { + for (;pages>0;pages--) { + memory.phandlers[phys_page]=handler; + phys_page++; } } -void ENTRY_writew(PageEntry * pentry,PhysPt address,Bit16u val) { - switch(pentry->type) { - case ENTRY_VGA: - { - VGA_WriteHandler * handler=vga.config.writehandler; - address=pentry->data.vga_base+(address&4095); - (*handler)(address,(Bit8u)val); - (*handler)(address+1,(Bit8u)(val>>8)); - } - break; - case ENTRY_NA: - if (pentry->data.dir->InitPageLinear(address)) mem_writew(address,val); - break; - case ENTRY_INIT: - if (pentry->data.dir->InitPage(address)) mem_writew(address,val); - break; - case ENTRY_ROM: - LOG(LOG_PAGING,LOG_WARN)("Write %X to ROM at %X",val,address); - break; - case ENTRY_CHANGES: - writew(pentry->data.mem+(address&4095),val); - { - Bitu start=address&4095;Bitu end=start+1; - for (PageLink * link=pentry->links;link;link=link->next) - if (link->change) link->change->Changed(link,start,end); - } - break; - default: - LOG(LOG_PAGING,LOG_ERROR)("Entry write %X to %X with illegal type %d",val,address,pentry->type); - } +void MEM_UnlinkPages(void) { + PAGING_ClearTLBEntries(memory.links.used,memory.links.pages); } - -void ENTRY_writed(PageEntry * pentry,PhysPt address,Bit32u val) { - switch(pentry->type) { - case ENTRY_VGA: - { - VGA_WriteHandler * handler=vga.config.writehandler; - address=pentry->data.vga_base+(address&4095); - (*handler)(address,(Bit8u)val); - (*handler)(address+1,(Bit8u)(val>>8)); - (*handler)(address+2,(Bit8u)(val>>16)); - (*handler)(address+3,(Bit8u)(val>>24)); - } - break; - case ENTRY_NA: - if (pentry->data.dir->InitPageLinear(address)) mem_writed(address,val); - break; - case ENTRY_INIT: - if (pentry->data.dir->InitPage(address)) mem_writed(address,val); - break; - case ENTRY_ROM: - LOG(LOG_PAGING,LOG_WARN)("Write %X to ROM at %X",val,address); - break; - case ENTRY_CHANGES: - writed(pentry->data.mem+(address&4095),val); - { - Bitu start=address&4095;Bitu end=start+3; - for (PageLink * link=pentry->links;link;link=link->next) - if (link->change) link->change->Changed(link,start,end); - } - break; - default: - LOG(LOG_PAGING,LOG_ERROR)("Entry write %X to %X with illegal type %d",val,address,pentry->type); - } -} - - Bitu mem_strlen(PhysPt pt) { Bitu x=0; while (x<1024) { @@ -270,193 +198,11 @@ Bitu MEM_TotalPages(void) { return memory.pages; } -void MEM_UnlinkPage(PageLink * plink) { - PageLink * checker=plink->entry->links; - PageLink * * last=&plink->entry->links; - while (checker) { - if (checker == plink) { - *last=plink->next; - PAGING_AddFreePageLink(plink); - return; - } - last=&checker->next; - checker=checker->next; - } - E_Exit("Unlinking unlinked link"); - -} - -PageLink * MEM_LinkPage(Bitu phys_page,PhysPt lin_base) { - PageEntry * entry; - /* Check if it's in a valid memory range */ - if (phys_page=memory.lfb.start_page && phys_pagelin_base=lin_base; - link->change=0; - /* Check what kind of handler we need to give the page */ - switch (entry->type) { - case ENTRY_RAM: - link->read=entry->data.mem - lin_base; - link->write=link->read; - break; - case ENTRY_ROM: - link->read=entry->data.mem - lin_base; - link->write=0; - break; - case ENTRY_VGA: - link->read=0; - link->write=0; - break; - case ENTRY_LFB: - link->read=entry->data.mem - lin_base; - link->write=link->read; - break; - case ENTRY_ALLOC: - entry->type=ENTRY_RAM; - entry->data.mem=MEM_GetBlockPage(); - link->read=entry->data.mem - lin_base; - link->write=link->read; - break; - case ENTRY_CHANGES: - link->read=entry->data.mem - lin_base; - link->write=0; - break; - default: - E_Exit("LinkPage:Illegal type %d",entry->type); - } - /* Place the entry in the link */ - link->entry=entry; - link->next=entry->links; - entry->links=link; - return link; -} - - -void MEM_CheckLinks(PageEntry * theentry) { - if (theentry->type!=ENTRY_RAM && theentry->type!=ENTRY_CHANGES) { - LOG(LOG_PAGING,LOG_NORMAL)("Checking links on type %d",theentry->type); - return; - } - bool haschange=false;PageLink * link; - for (link=theentry->links;link;link=link->next) { - if (link->change) { - haschange=true;break; - } - } - if (haschange) { - theentry->type=ENTRY_CHANGES; - for (link=theentry->links;link;link=link->next) { - link->read=theentry->data.mem - link->lin_base; - link->write=0; - } - } else { - theentry->type=ENTRY_RAM; - for (link=theentry->links;link;link=link->next) { - link->read=theentry->data.mem - link->lin_base; - link->write=link->read; - } - } -} - -void MEM_AllocLinkMemory(PageEntry * theentry) { - //TODO Maybe check if this is a LINK_ALLOC type - HostPt themem=MEM_GetBlockPage(); - theentry->data.mem=themem; - theentry->type=ENTRY_RAM; - theentry->links=0; -} - -void MEM_SetLFB(Bitu page,Bitu pages,HostPt pt) { - if (pages>LFB_PAGES) E_Exit("MEM:LFB to large"); - LOG(LOG_PAGING,LOG_NORMAL)("LFB Base at address %X,page %X",page*4096,page); - memory.lfb.pages=pages; - memory.lfb.start_page=page; - memory.lfb.end_page=page+pages; - memory.lfb.address=pt; - for (Bitu i=0;idata.mem=themem; - theentry->type=ENTRY_LFB; - PageLink * link=theentry->links; - while (link) { - link->read=themem - link->lin_base; - link->write=link->read; - link=link->next; - } - } - memory.vga.range=range; - } - /* Setup the new range, check if it's gonna handler based */ - Bitu start,end; - switch (range) { - case VGA_RANGE_A000:start=0;end=16;break; - case VGA_RANGE_B000:start=16;end=24;break; - case VGA_RANGE_B800:start=24;end=32;break; - } - if (base) { - /* If it has an address it's a mapping */ - for (i=start;itype=ENTRY_LFB; - theentry->data.mem=themem; - PageLink * link=theentry->links; - while (link) { - link->read=themem - link->lin_base; - link->write=link->read; - link=link->next; - } - } - } else { - /* No address, so it'll be a handler */ - for (i=start;itype=ENTRY_VGA; - PhysPt thebase=(i-start)*4096; - PageLink * link=theentry->links; - theentry->data.vga_base=thebase; - while (link) { - link->read=0; - link->write=0; - link=link->next; - } - } - } -} - Bitu MEM_FreeLargest(void) { Bitu size=0;Bitu largest=0; Bitu index=XMS_START; while (indexlargest) largest=size; @@ -472,7 +218,7 @@ Bitu MEM_FreeTotal(void) { Bitu free=0; Bitu index=XMS_START; while (index0) { pages++; - handle=memory.entries[handle].next_handle; + handle=memory.mhandles[handle]; } return pages; } @@ -499,12 +245,12 @@ INLINE Bitu BestMatch(Bitu size) { /* Check if we are searching for first free page */ if (!first) { /* Check if this is a free page */ - if (!memory.entries[index].next_handle) { + if (!memory.mhandles[index]) { first=index; } } else { /* Check if this still is used page */ - if (memory.entries[index].next_handle) { + if (memory.mhandles[index]) { Bitu pages=index-first; if (pages==size) { return first; @@ -535,7 +281,7 @@ MemHandle MEM_AllocatePages(Bitu pages,bool sequence) { MemHandle * next=&ret; while (pages) { *next=index; - next=&memory.entries[index].next_handle; + next=&memory.mhandles[index]; index++;pages--; } *next=-1; @@ -545,9 +291,9 @@ MemHandle MEM_AllocatePages(Bitu pages,bool sequence) { while (pages) { Bitu index=BestMatch(1); if (!index) E_Exit("MEM:corruption during allocate"); - while (pages && (!memory.entries[index].next_handle)) { + while (pages && (!memory.mhandles[index])) { *next=index; - next=&memory.entries[index].next_handle; + next=&memory.mhandles[index]; index++;pages--; } *next=-1; //Invalidate it in case we need another match @@ -558,8 +304,8 @@ MemHandle MEM_AllocatePages(Bitu pages,bool sequence) { void MEM_ReleasePages(MemHandle handle) { while (handle>0) { - MemHandle next=memory.entries[handle].next_handle; - memory.entries[handle].next_handle=0; + MemHandle next=memory.mhandles[handle]; + memory.mhandles[handle]=0; handle=next; } } @@ -580,22 +326,22 @@ bool MEM_ReAllocatePages(MemHandle & handle,Bitu pages,bool sequence) { while (index>0) { old_pages++; last=index; - index=memory.entries[index].next_handle; + index=memory.mhandles[index]; } if (old_pages == pages) return true; if (old_pages > pages) { /* Decrease size */ pages--;index=handle;old_pages--; while (pages) { - index=memory.entries[index].next_handle; + index=memory.mhandles[index]; pages--;old_pages--; } - MemHandle next=memory.entries[index].next_handle; - memory.entries[index].next_handle=-1; + MemHandle next=memory.mhandles[index]; + memory.mhandles[index]=-1; index=next; while (old_pages) { - next=memory.entries[index].next_handle; - memory.entries[index].next_handle=0; + next=memory.mhandles[index]; + memory.mhandles[index]=0; index=next; old_pages--; } @@ -606,17 +352,17 @@ bool MEM_ReAllocatePages(MemHandle & handle,Bitu pages,bool sequence) { if (sequence) { index=last+1; Bitu free=0; - while ((index=need) { /* Enough space allocate more pages */ index=last; while (need) { - memory.entries[index].next_handle=index+1; + memory.mhandles[index]=index+1; need--;index++; } - memory.entries[index].next_handle=-1; + memory.mhandles[index]=-1; return true; } else { /* Not Enough space allocate new block and copy */ @@ -630,63 +376,38 @@ bool MEM_ReAllocatePages(MemHandle & handle,Bitu pages,bool sequence) { } else { MemHandle rem=MEM_AllocatePages(need,false); if (!rem) return false; - memory.entries[last].next_handle=rem; + memory.mhandles[last]=rem; return true; } } return 0; } - -void MEM_UnmapPages(Bitu phys_page,Bitu pages) { - for (;pages;pages--) { - memory.dir.LinkPage(phys_page,phys_page); - phys_page++; - } -} - -void MEM_MapPagesHandle(Bitu lin_page,MemHandle mem,Bitu mem_page,Bitu pages) { - for (;mem_page;mem_page--) { - if (mem<=0) E_Exit("MEM:MapPages:Fault in memory tables"); - mem=memory.entries[mem].next_handle; - } - for (;pages;pages--) { - if (mem<=0) E_Exit("MEM:MapPages:Fault in memory tables"); - memory.dir.LinkPage(lin_page++,mem); - mem=memory.entries[mem].next_handle; - } -} - -void MEM_MapPagesDirect(Bitu lin_page,Bitu phys_page,Bitu pages) { - for (;pages;pages--) { - memory.dir.LinkPage(lin_page++,phys_page++); - } -} - MemHandle MEM_NextHandle(MemHandle handle) { - return memory.entries[handle].next_handle; + return memory.mhandles[handle]; } +MemHandle MEM_NextHandleAt(MemHandle handle,Bitu where) { + while (where) { + where--; + handle=memory.mhandles[handle]; + } + return handle; +} + + /* A20 line handling, Basically maps the 4 pages at the 1mb to 0mb in the default page directory */ bool MEM_A20_Enabled(void) { - return a20_enabled; + return memory.a20.enabled; } void MEM_A20_Enable(bool enabled) { - a20_enabled=enabled; - Bitu i; - if (!enabled) { - for (i=0x0;i<0x10;i++) { - memory.dir.LinkPage(0x100+i,i); - } - } else { - for (i=0x0;i<0x10;i++) { - memory.dir.LinkPage(0x100+i,0x100+i); - } - } + Bitu phys_base=enabled ? (1024/4) : 0; + for (Bitu i=0;i<16;i++) PAGING_MapPage((1024/4)+i,phys_base+i); + memory.a20.enabled=enabled; } @@ -742,20 +463,11 @@ void mem_writed(PhysPt address,Bit32u val) { } void phys_writeb(PhysPt addr,Bit8u val) { - Bitu page=addr>>12; - if (page>=memory.pages) E_Exit("physwrite:outside of physical range"); - PageEntry * theentry=&memory.entries[page]; - switch (theentry->type) { - case ENTRY_ALLOC: - MEM_AllocLinkMemory(theentry); - break; - case ENTRY_RAM: - case ENTRY_ROM: - break; - default: - E_Exit("physwrite:illegal type %d",theentry->type); + HostPt block=memory.hostpts[addr >> 12]; + if (!block) { + block=memory.hostpts[addr >> 12]=MEM_GetBlockPage(); } - writeb(theentry->data.mem+(addr & 4095),val); + host_writeb(block+(addr & 4095),val); } void phys_writew(PhysPt addr,Bit16u val) { @@ -771,17 +483,6 @@ void phys_writed(PhysPt addr,Bit32u val) { } Bit32u phys_page_readd(Bitu page,Bitu index) { - if (page>=memory.pages) E_Exit("physwrite:outside of physical range"); - PageEntry * theentry=&memory.entries[page]; - switch (theentry->type) { - case ENTRY_CHANGES: - case ENTRY_RAM: - case ENTRY_ROM: - return readd(memory.entries[page].data.mem+index*4); - break; - default: - E_Exit("pageread:illegal type %d",theentry->type); - } return 0; } @@ -789,19 +490,15 @@ Bit32u phys_page_readd(Bitu page,Bitu index) { static void write_p92(Bit32u port,Bit8u val) { // Bit 0 = system reset (switch back to real mode) if (val&1) E_Exit("XMS: CPU reset via port 0x92 not supported."); - controlport_data = val & ~2; + memory.a20.controlport = val & ~2; MEM_A20_Enable((val & 2)>0); } static Bit8u read_p92(Bit32u port) { - return controlport_data | (a20_enabled ? 0x02 : 0); + return memory.a20.controlport | (memory.a20.enabled ? 0x02 : 0); } -PageDirectory * MEM_DefaultDirectory(void) { - return &memory.dir; -} - HostPt MEM_GetBlockPage(void) { HostPt ret; if (memory.block.pages) { @@ -847,36 +544,17 @@ void MEM_Init(Section * sec) { memsize=MAX_MEMORY; } memory.pages=(memsize*1024*1024)/4096; - if (memory.pages>0x110) memory.free_pages=memory.pages-0x110; - else memory.free_pages=0; - - memory.entries= new PageEntry[memory.pages]; + /* Allocate the data for the different page information blocks */ + memory.hostpts=new HostPt[memory.pages]; + memory.phandlers=new PageHandler * [memory.pages]; + memory.mhandles=new MemHandle [memory.pages]; for (i=0;i