Paging tables/functions changed somewhat
Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1356
This commit is contained in:
		
							parent
							
								
									708eee4f86
								
							
						
					
					
						commit
						e712e7dc9c
					
				
					 2 changed files with 282 additions and 640 deletions
				
			
		|  | @ -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_page<LINK_START) phys_page=mapfirstmb[lin_page]; | ||||
| 			else phys_page=lin_page; | ||||
| 		} | ||||
| 		PAGING_LinkPage(lin_page,phys_page); | ||||
| 	} | ||||
| private: | ||||
| 	PageDirectory * dir; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| PageDirectory::PageDirectory()	{ | ||||
| 	entry_init.data.dir=this; | ||||
| 	entry_init.type=ENTRY_INIT; | ||||
| 	link_init.read=0; | ||||
| 	link_init.write=0; | ||||
| 	link_init.entry=&entry_init; | ||||
| 	table_change = new PageTableChange(this); | ||||
| 	dir_change = new PageDirChange(this); | ||||
| } | ||||
| PageDirectory::~PageDirectory() { | ||||
| 	delete table_change; | ||||
| 	delete dir_change; | ||||
| } | ||||
| void PageDirectory::ClearDirectory(void) { | ||||
| 	Bitu i; | ||||
| 	for (i=0;i<1024*1024;i++) links[i]=&link_init; | ||||
| 	for (i=0;i<1024;i++) { | ||||
| 		tables[i]=0; | ||||
| 	} | ||||
| } | ||||
| void PageDirectory::SetBase(PhysPt page) { | ||||
| 	base_page=page; | ||||
| 	ClearDirectory(); | ||||
| 	/* Setup handler for PageDirectory changes */ | ||||
| 	link_dir=MEM_LinkPage(base_page,0); | ||||
| 	if (!link_dir) E_Exit("PAGING:Directory setup on illegal address"); | ||||
| 	link_dir->data.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;i<LINK_START;i++) { | ||||
| 		paging.tlb.read[i]=0; | ||||
| 		paging.tlb.write[i]=0; | ||||
| 		paging.tlb.handler[i]=&init_page_handler; | ||||
| 	} | ||||
| 	MEM_UnlinkPages(); | ||||
| } | ||||
| 
 | ||||
| void PAGING_InitTLB(void) { | ||||
| 	for (Bitu i=0;i<TLB_SIZE;i++) { | ||||
| 		paging.tlb.read[i]=0; | ||||
| 		paging.tlb.write[i]=0; | ||||
| 		paging.tlb.handler[i]=&init_page_handler; | ||||
| 
 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void PAGING_ClearTLBEntries(Bitu pages,Bit32u * entries) { | ||||
| 	for (;pages>0;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<LINK_START) { | ||||
| 		mapfirstmb[lin_page]=phys_page; | ||||
| 		paging.tlb.read[lin_page]=0; | ||||
| 		paging.tlb.write[lin_page]=0; | ||||
| 		paging.tlb.handler[lin_page]=&init_page_handler; | ||||
| 	} else { | ||||
| 		PAGING_LinkPage(lin_page,phys_page); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void PAGING_SetDirBase(Bitu cr3) { | ||||
| 	paging.cr3=cr3; | ||||
| 	Bitu base_page=cr3 >> 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;i<LINK_START;i++) { | ||||
| 		mapfirstmb[i]=i; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void PAGING_AddFreePageLink(PageLink * link) { | ||||
| 	link->read=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;i<LINK_TOTAL;i++) PAGING_AddFreePageLink(&link_list[i]); | ||||
| 	/* Setup default Page Directory, force it to update */ | ||||
| 	paging.enabled=true;PAGING_Enable(false); | ||||
| } | ||||
|  | @ -30,20 +30,26 @@ | |||
| 
 | ||||
| #define PAGES_IN_BLOCK	((1024*1024)/MEM_PAGE_SIZE) | ||||
| #define MAX_MEMORY	64 | ||||
| #define MAX_PAGE_ENTRIES (MAX_MEMORY*1024*1024/4096) | ||||
| #define LFB_PAGES	512 | ||||
| 
 | ||||
| static Bit8u controlport_data; | ||||
| static bool	a20_enabled; | ||||
| #define MAX_LINKS	((MAX_MEMORY*1024/4)+4096)		//Hopefully enough
 | ||||
| 
 | ||||
| struct AllocBlock { | ||||
| 	Bit8u				data[PAGES_IN_BLOCK*4096]; | ||||
| 	AllocBlock			* next; | ||||
| }; | ||||
| 
 | ||||
| struct LinkBlock { | ||||
| 	Bit8u used; | ||||
| 	Bit32u pages[MAX_LINKS]; | ||||
| }; | ||||
| 
 | ||||
| static struct MemoryBlock { | ||||
| 	Bitu		pages; | ||||
| 	Bitu		free_pages; | ||||
| 	PageEntry *	entries; | ||||
| 	Bitu pages; | ||||
| 	PageHandler * * phandlers; | ||||
| 	HostPt * hostpts; | ||||
| 	MemHandle * mhandles; | ||||
| 	LinkBlock links; | ||||
| 	struct { | ||||
| 		Bitu			pages; | ||||
| 		HostPt			cur_page; | ||||
|  | @ -54,172 +60,94 @@ static struct MemoryBlock { | |||
| 		Bitu		end_page; | ||||
| 		Bitu		pages; | ||||
| 		HostPt		address; | ||||
| 		PageEntry	entries[LFB_PAGES]; | ||||
| 	} lfb; | ||||
| 	struct { | ||||
| 		HostPt		ram_bases[128/4]; | ||||
| 		HostPt		map_base; | ||||
| 		VGA_RANGES	range; | ||||
| 	} vga; | ||||
| 	PageDirectory	dir; | ||||
| 		bool enabled; | ||||
| 		Bit8u controlport; | ||||
| 	} a20; | ||||
| } memory; | ||||
| 
 | ||||
| Bit8u ENTRY_readb(PageEntry * pentry,PhysPt address) { | ||||
| 	switch(pentry->type) { | ||||
| 	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<LINK_START) return; | ||||
| 		if (memory.links.used<MAX_LINKS) { | ||||
| 			memory.links.pages[memory.links.used++]=lin_page; | ||||
| 		} else E_Exit("MEM:Ran out of page links"); | ||||
| 	} | ||||
| 	RAMPageHandler() { | ||||
| 		flags=PFLAG_READABLE|PFLAG_WRITEABLE; | ||||
| 	} | ||||
| 	HostPt GetHostPt(Bitu phys_page) { | ||||
| 		if (!memory.hostpts[phys_page]) { | ||||
| 			memory.hostpts[phys_page]=MEM_GetBlockPage(); | ||||
| 		} | ||||
| 		return memory.hostpts[phys_page]; | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| class ROMPageHandler : public RAMPageHandler { | ||||
| public: | ||||
| 	ROMPageHandler() { | ||||
| 		flags=PFLAG_READABLE|PFLAG_HASROM; | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| class LFBPageHandler : public RAMPageHandler { | ||||
| public: | ||||
| 	LFBPageHandler() { | ||||
| 		flags=PFLAG_READABLE|PFLAG_WRITEABLE|PFLAG_NOCODE; | ||||
| 	} | ||||
| 	HostPt GetHostPt(Bitu phys_page) { | ||||
| 		return memory.lfb.address+(phys_page-memory.lfb.start_page)*4096; | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| static IllegalPageHandler illegal_page_handler; | ||||
| static RAMPageHandler ram_page_handler; | ||||
| static ROMPageHandler rom_page_handler; | ||||
| static LFBPageHandler lfb_page_handler; | ||||
| 
 | ||||
| void MEM_SetLFB(Bitu page,Bitu pages,HostPt pt) { | ||||
| 	memory.lfb.address=pt; | ||||
| 	memory.lfb.start_page=page; | ||||
| 	memory.lfb.end_page=page+pages; | ||||
| 	memory.lfb.pages=pages; | ||||
| 	PAGING_ClearTLB(); | ||||
| } | ||||
| 
 | ||||
| PageHandler * MEM_GetPageHandler(Bitu phys_page) { | ||||
| 	if (phys_page<memory.pages) { | ||||
| 		return memory.phandlers[phys_page]; | ||||
| 	} else if ((phys_page>=memory.lfb.start_page) && (phys_page<memory.lfb.end_page)) { | ||||
| 		return &lfb_page_handler; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| Bit16u ENTRY_readw(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); | ||||
| 		} | ||||
| 	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.pages) { | ||||
| 		entry=&memory.entries[phys_page]; | ||||
| 	/* Check if it's in the lfb range */ | ||||
| 	} else if (phys_page>=memory.lfb.start_page && phys_page<memory.lfb.end_page) { | ||||
| 		entry=&memory.lfb.entries[phys_page-memory.lfb.start_page]; | ||||
| 	} else { | ||||
| 		/* Invalid memory */ | ||||
| 		LOG(LOG_PAGING,LOG_NORMAL)("Trying to link invalid page %X",phys_page); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	PageLink * link=PAGING_GetFreePageLink(); | ||||
| 	link->lin_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;i<pages;i++) { | ||||
| 		memory.lfb.entries[i].data.mem=pt+(i*4096); | ||||
| 		memory.lfb.entries[i].type=ENTRY_LFB; | ||||
| 	} | ||||
| 	//TODO Maybe free the linked pages, but doubht that will be necessary
 | ||||
| } | ||||
| 
 | ||||
| void MEM_SetupVGA(VGA_RANGES range,HostPt base) { | ||||
| 	Bitu i; | ||||
| 	memory.vga.map_base=base; | ||||
| 	/* If it's another range, first clear the old one */ | ||||
| 	if (memory.vga.range!=range) { | ||||
| 		Bitu start,end; | ||||
| 		switch (memory.vga.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; | ||||
| 		} | ||||
| 		for (i=start;i<end;i++) { | ||||
| 			PageEntry * theentry=&memory.entries[i+0xa0]; | ||||
| 			HostPt themem=memory.vga.ram_bases[i]; | ||||
| 			theentry->data.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;i<end;i++) { | ||||
| 			PageEntry * theentry=&memory.entries[i+0xa0]; | ||||
| 			HostPt themem=base+(i-start)*4096; | ||||
| 			theentry->type=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;i<end;i++) { | ||||
| 			PageEntry * theentry=&memory.entries[i+0xa0]; | ||||
| 			theentry->type=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 (index<memory.pages) { | ||||
| 		if (!memory.entries[index].next_handle) { | ||||
| 		if (!memory.mhandles[index]) { | ||||
| 			size++; | ||||
| 		} else { | ||||
| 			if (size>largest) largest=size; | ||||
|  | @ -472,7 +218,7 @@ Bitu MEM_FreeTotal(void) { | |||
| 	Bitu free=0; | ||||
| 	Bitu index=XMS_START;	 | ||||
| 	while (index<memory.pages) { | ||||
| 		if (!memory.entries[index].next_handle) free++; | ||||
| 		if (!memory.mhandles[index]) free++; | ||||
| 		index++; | ||||
| 	} | ||||
| 	return free; | ||||
|  | @ -483,7 +229,7 @@ Bitu MEM_AllocatedPages(MemHandle handle) | |||
| 	Bitu pages = 0; | ||||
| 	while (handle>0) { | ||||
| 		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<memory.pages) && !memory.entries[index].next_handle) { | ||||
| 			while ((index<(MemHandle)memory.pages) && !memory.mhandles[index]) { | ||||
| 				index++;free++; | ||||
| 			} | ||||
| 			if (free>=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<memory.pages;i++) { | ||||
| 		memory.entries[i].type=ENTRY_ALLOC; | ||||
| 		memory.entries[i].data.mem=0; | ||||
| 		memory.entries[i].links=0; | ||||
| 		memory.entries[i].next_handle=0;			//Set to 0 for memory allocation
 | ||||
| 	} | ||||
| 	/* Setup 128kb of memory for the VGA segments */ | ||||
| 	for (i=0;i<128/4;i++) { | ||||
| 		memory.vga.ram_bases[i]=MEM_GetBlockPage(); | ||||
| 		memory.entries[0xa0+i].type=ENTRY_LFB; | ||||
| 		memory.entries[0xa0+i].data.mem=memory.vga.ram_bases[i]; | ||||
| 	} | ||||
| 	memory.vga.range=VGA_RANGE_B800; | ||||
| 	/* Setup the default page mapping */ | ||||
| 	memory.dir.entry_init.type=ENTRY_NA;		//Setup to use NA by default
 | ||||
| 	memory.dir.ClearDirectory(); | ||||
| 	/* All pages now pointing to NA handler that will check on first access */ | ||||
| 	/* Setup the ROM Areas */ | ||||
| 	for (i=0xc0;i<0xd0;i++) { | ||||
| 		MEM_AllocLinkMemory(&memory.entries[i]); | ||||
| 		memory.entries[i].type=ENTRY_ROM; | ||||
| 	} | ||||
| 	for (i=0xf0;i<0x100;i++) { | ||||
| 		MEM_AllocLinkMemory(&memory.entries[i]); | ||||
| 		memory.entries[i].type=ENTRY_ROM; | ||||
| 		memory.hostpts[i]=0;				//0 handler is allocate memory
 | ||||
| 		memory.phandlers[i]=&ram_page_handler; | ||||
| 		memory.mhandles[i]=0;				//Set to 0 for memory allocation
 | ||||
| 	} | ||||
| 	/* Reset some links */ | ||||
| 	memory.links.used=0; | ||||
| 	// A20 Line - PS/2 system control port A
 | ||||
| 	IO_RegisterWriteHandler(0x92,write_p92,"Control Port"); | ||||
| 	IO_RegisterReadHandler(0x92,read_p92,"Control Port"); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue