⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pm.c

📁 BIOS emulator and interface to Realmode X86 Emulator Library Can emulate a PCI Graphic Controller V
💻 C
📖 第 1 页 / 共 3 页
字号:
	(void)hModule;	(void)szProcName;	return NULL;}void PMAPI PM_freeLibrary(	PM_MODULE hModule){	(void)hModule;}int PMAPI PM_setIOPL(	int level){	return level;}/*-------------------------------------------------------------------------*//* Generic DPMI routines common to 16/32 bit code						   *//*-------------------------------------------------------------------------*/ulong PMAPI DPMI_mapPhysicalToLinear(ulong physAddr,ulong limit){	PMREGS  r;	ulong	physOfs;	if (physAddr < 0x100000L) {		/* We can't map memory below 1Mb, but the linear address are already		 * mapped 1:1 for this memory anyway so we just return the base address.		 */		return physAddr;		}	/* Round the physical address to a 4Kb boundary and the limit to a	 * 4Kb-1 boundary before passing the values to DPMI as some extenders	 * will fail the calls unless this is the case. If we round the	 * physical address, then we also add an extra offset into the address	 * that we return.	 */	physOfs = physAddr & 4095;	physAddr = physAddr & ~4095;	limit = ((limit+physOfs+1+4095) & ~4095)-1;	r.x.ax = 0x800;                 /* DPMI map physical to linear      */	r.x.bx = physAddr >> 16;	r.x.cx = physAddr & 0xFFFF;	r.x.si = limit >> 16;	r.x.di = limit & 0xFFFF;	PM_int386(0x31, &r, &r);	if (r.x.cflag)		return 0xFFFFFFFFUL;	return ((ulong)r.x.bx << 16) + r.x.cx + physOfs;}int PMAPI DPMI_setSelectorBase(ushort sel,ulong linAddr){	PMREGS  r;	r.x.ax = 7;                     /* DPMI set selector base address   */	r.x.bx = sel;	r.x.cx = linAddr >> 16;	r.x.dx = linAddr & 0xFFFF;	PM_int386(0x31, &r, &r);	if (r.x.cflag)		return 0;	return 1;}ulong PMAPI DPMI_getSelectorBase(ushort sel){	PMREGS  r;	r.x.ax = 6;                     /* DPMI get selector base address   */	r.x.bx = sel;	PM_int386(0x31, &r, &r);	return ((ulong)r.x.cx << 16) + r.x.dx;}int PMAPI DPMI_setSelectorLimit(ushort sel,ulong limit){	PMREGS  r;	r.x.ax = 8;                     /* DPMI set selector limit          */	r.x.bx = sel;	r.x.cx = limit >> 16;	r.x.dx = limit & 0xFFFF;	PM_int386(0x31, &r, &r);	if (r.x.cflag)		return 0;	return 1;}uint PMAPI DPMI_createSelector(ulong base,ulong limit){	uint	sel;	PMREGS	r;	/* Allocate 1 descriptor */	r.x.ax = 0;	r.x.cx = 1;	PM_int386(0x31, &r, &r);	if (r.x.cflag) return 0;	sel = r.x.ax;	/* Set the descriptor access rights (for a 32 bit page granular	 * segment).	 */	if (limit >= 0x10000L) {		r.x.ax = 9;        r.x.bx = sel;        r.x.cx = 0x40F3;		PM_int386(0x31, &r, &r);		}	/* Map physical memory and create selector */	if ((base = DPMI_mapPhysicalToLinear(base,limit)) == 0xFFFFFFFFUL)		return 0;	if (!DPMI_setSelectorBase(sel,base))		return 0;	if (!DPMI_setSelectorLimit(sel,limit))		return 0;	return sel;}void PMAPI DPMI_freeSelector(uint sel){	PMREGS	r;	r.x.ax = 1;	r.x.bx = sel;	PM_int386(0x31, &r, &r);}int PMAPI DPMI_lockLinearPages(ulong linear,ulong len){	PMREGS	r;	r.x.ax = 0x600;						/* DPMI Lock Linear Region 		*/	r.x.bx = (linear >> 16);         	/* Linear address in BX:CX 		*/	r.x.cx = (linear & 0xFFFF);	r.x.si = (len >> 16);         		/* Length in SI:DI 				*/	r.x.di = (len & 0xFFFF);	PM_int386(0x31, &r, &r);	return (!r.x.cflag);}int PMAPI DPMI_unlockLinearPages(ulong linear,ulong len){	PMREGS	r;	r.x.ax = 0x601;						/* DPMI Unlock Linear Region 	*/	r.x.bx = (linear >> 16);         	/* Linear address in BX:CX 		*/	r.x.cx = (linear & 0xFFFF);	r.x.si = (len >> 16);         		/* Length in SI:DI 				*/	r.x.di = (len & 0xFFFF);	PM_int386(0x31, &r, &r);	return (!r.x.cflag);}void * PMAPI DPMI_mapPhysicalAddr(ulong base,ulong limit,ibool isCached){	PMSREGS	sregs;	ulong	linAddr;	ulong	DSBaseAddr;	/* Get the base address for the default DS selector */	PM_segread(&sregs);	DSBaseAddr = DPMI_getSelectorBase(sregs.ds);	if ((base < 0x100000) && (DSBaseAddr == 0)) {		/* DS is zero based, so we can directly access the first 1Mb of		 * system memory (like under DOS4GW).		 */		return (void*)base;		}	/* Map the memory to a linear address using DPMI function 0x800 */	if ((linAddr = DPMI_mapPhysicalToLinear(base,limit)) == 0xFFFFFFFF) {		if (base >= 0x100000)			return NULL;		/* If the linear address mapping fails but we are trying to		 * map an area in the first 1Mb of system memory, then we must		 * be running under a Windows or OS/2 DOS box. Under these		 * environments we can use the segment wrap around as a fallback		 * measure, as this does work properly.		 */		linAddr = base;		}	/* Now expand the default DS selector to 4Gb so we can access it */	if (!DPMI_setSelectorLimit(sregs.ds,0xFFFFFFFFUL))		return NULL;	/* Finally enable caching for the page tables that we just mapped in,	 * since DOS4GW and PMODE/W create the page table entries without	 * caching enabled which hurts the performance of the linear framebuffer	 * as it disables write combining on Pentium Pro and above processors.	 *	 * For those processors cache disabling is better handled through the	 * MTRR registers anyway (we can write combine a region but disable	 * caching) so that MMIO register regions do not screw up.	 */	if (isCached) {#ifdef	DOS4GW		if ((PDB = _PM_getPDB()) != 0 && DSBaseAddr == 0) {			int 	startPDB,endPDB,iPDB,startPage,endPage,start,end,iPage;			ulong 	pageTable,*pPageTable;			if (!pPDB) {				if (PDB >= 0x100000)					pPDB = (ulong*)DPMI_mapPhysicalToLinear(PDB,0xFFF);				else					pPDB = (ulong*)PDB;				}			if (pPDB) {				startPDB = (linAddr >> 22) & 0x3FF;				startPage = (linAddr >> 12) & 0x3FF;				endPDB = ((linAddr+limit) >> 22) & 0x3FF;				endPage = ((linAddr+limit) >> 12) & 0x3FF;				for (iPDB = startPDB; iPDB <= endPDB; iPDB++) {					pageTable = pPDB[iPDB] & ~0xFFF;					if (pageTable >= 0x100000)						pPageTable = (ulong*)DPMI_mapPhysicalToLinear(pageTable,0xFFF);					else						pPageTable = (ulong*)pageTable;					start = (iPDB == startPDB) ? startPage : 0;					end = (iPDB == endPDB) ? endPage : 0x3FF;					for (iPage = start; iPage <= end; iPage++)						pPageTable[iPage] &= ~0x18;					}				}			}#endif		}	/* Now return the base address of the memory into the default DS */	return (void*)(linAddr - DSBaseAddr);}#if	defined(PM386)/* Some DOS extender implementations do not directly support calling a * real mode procedure from protected mode. However we can simulate what * we need temporarily hooking the INT 6Ah vector with a small real mode * stub that will call our real mode code for us. */static uchar int6AHandler[] = {	0x00,0x00,0x00,0x00,		/* 	__PMODE_callReal variable			*/	0xFB,						/*	sti									*/	0x2E,0xFF,0x1E,0x00,0x00,	/*  call	[cs:__PMODE_callReal]		*/	0xCF,						/*	iretf								*/	};static uchar *crPtr = NULL;	/* Pointer to of int 6A handler			*/static uint crRSeg,crROff;	/* Real mode seg:offset of handler		*/void PMAPI PM_callRealMode(uint seg,uint off, RMREGS *in,	RMSREGS *sregs){	uchar	*p;	uint	oldSeg,oldOff;	if (!crPtr) {		/* Allocate and copy the memory block only once */		crPtr = PM_allocRealSeg(sizeof(int6AHandler), &crRSeg, &crROff);		memcpy(crPtr,int6AHandler,sizeof(int6AHandler));		}	PM_setWord(crPtr,off);				/* Plug in address to call	*/	PM_setWord(crPtr+2,seg);	p = PM_mapRealPointer(0,0x6A * 4);	oldOff = PM_getWord(p);				/* Save old handler address	*/	oldSeg = PM_getWord(p+2);	PM_setWord(p,crROff+4);				/* Hook 6A handler			*/	PM_setWord(p+2,crRSeg);	PM_int86x(0x6A, in, in, sregs);		/* Call real mode code		*/	PM_setWord(p,oldOff);				/* Restore old handler		*/	PM_setWord(p+2,oldSeg);}#endif	/* PM386 *//*-------------------------------------------------------------------------*//* DOS Real Mode support.												   *//*-------------------------------------------------------------------------*/#ifdef REALMODE#ifndef	MK_FP#define MK_FP(s,o)  ( (void far *)( ((ulong)(s) << 16) + \					(ulong)(o) ))#endifvoid * PMAPI PM_mapRealPointer(uint r_seg,uint r_off){ return MK_FP(r_seg,r_off); }void * PMAPI PM_getBIOSPointer(void){	return MK_FP(0x40,0);}void * PMAPI PM_getA0000Pointer(void){	return MK_FP(0xA000,0);}void * PMAPI PM_mapPhysicalAddr(ulong base,ulong limit,ibool isCached){	uint sel = base >> 4;	uint off = base & 0xF;	limit = limit;	return MK_FP(sel,off);}void PMAPI PM_freePhysicalAddr(void *ptr,ulong limit){ ptr = ptr; }ulong PMAPI PM_getPhysicalAddr(void *p){ return 0xFFFFFFFFUL; }void * PMAPI PM_mapToProcess(void *base,ulong limit){ return (void*)base; }void * PMAPI PM_allocRealSeg(uint size,uint *r_seg,uint *r_off){	/* Call malloc() to allocate the memory for us */	void *p = malloc(size);	*r_seg = FP_SEG(p);	*r_off = FP_OFF(p);	return p;}void PMAPI PM_freeRealSeg(void *mem){	free(mem);}int PMAPI PM_int86(int intno, RMREGS *in, RMREGS *out){	return PM_int386(intno,in,out);}int PMAPI PM_int86x(int intno, RMREGS *in, RMREGS *out,	RMSREGS *sregs){	return PM_int386x(intno,in,out,sregs);}void PMAPI PM_availableMemory(ulong *physical,ulong *total){	PMREGS regs;	regs.h.ah = 0x48;	regs.x.bx = 0xFFFF;	PM_int86(0x21,&regs,&regs);	*physical = *total = regs.x.bx * 16UL;}ibool PMAPI PM_enableWriteCombine(ulong base,ulong length,uint type){ return false; }#endif/*-------------------------------------------------------------------------*//* Phar Lap TNT DOS Extender support.									   *//*-------------------------------------------------------------------------*/#ifdef TNT#include <pldos32.h>#include <pharlap.h>#include <hw386.h>static uchar *zeroPtr = NULL;void * PMAPI PM_getBIOSPointer(void){	if (!zeroPtr)		zeroPtr = PM_mapPhysicalAddr(0,0xFFFFF,true);	return (void*)(zeroPtr + 0x400);}void * PMAPI PM_getA0000Pointer(void){	static void *bankPtr;	if (!bankPtr)		bankPtr = PM_mapPhysicalAddr(0xA0000,0xFFFF,true);	return bankPtr;}void * PMAPI PM_mapPhysicalAddr(ulong base,ulong limit,ibool isCached){	CONFIG_INF	config;	ULONG		offset;	int			err;	ulong		baseAddr,baseOfs,newLimit;	/* Round the physical address to a 4Kb boundary and the limit to a	 * 4Kb-1 boundary before passing the values to TNT. If we round the	 * physical address, then we also add an extra offset into the address	 * that we return.	 */	baseOfs = base & 4095;	baseAddr = base & ~4095;	newLimit = ((limit+baseOfs+1+4095) & ~4095)-1;	_dx_config_inf(&config, (UCHAR*)&config);	err = _dx_map_phys(config.c_ds_sel,baseAddr,(newLimit + 4095) / 4096,&offset);	if (err == 130) {		/* If the TNT function failed, we are running in a DPMI environment		 * and this function does not work. However we know how to handle		 * DPMI properly, so we use our generic DPMI functions to do		 * what the TNT runtime libraries can't.		 */		return DPMI_mapPhysicalAddr(base,limit,isCached);		}	if (err == 0)		return (void*)(offset + baseOfs);	return NULL;}void PMAPI PM_freePhysicalAddr(void *ptr,ulong limit){	/* TODO: We should be able to free non-DPMI mappings with PharLap */}ulong PMAPI PM_getPhysicalAddr(void *p){ return 0xFFFFFFFFUL; }void * PMAPI PM_mapToProcess(void *base,ulong limit){ return (void*)base; }void * PMAPI PM_mapRealPointer(uint r_seg,uint r_off){	if (!zeroPtr)		zeroPtr = PM_mapPhysicalAddr(0,0xFFFFF);	return (void*)(zeroPtr + MK_PHYS(r_seg,r_off));}void * PMAPI PM_allocRealSeg(uint size,uint *r_seg,uint *r_off){	USHORT	addr,t;	void	*p;	if (_dx_real_alloc((size + 0xF) >> 4,&addr,&t) != 0)		return 0;	*r_seg = addr;					/* Real mode segment address	*/	*r_off = 0;						/* Real mode segment offset		*/	p = PM_mapRealPointer(*r_seg,*r_off);	_PM_addRealModeBlock(p,addr);	return p;}void PMAPI PM_freeRealSeg(void *mem){	_dx_real_free(_PM_findRealModeBlock(mem));}#define INDPMI(reg)     rmregs.reg = regs->reg#define OUTDPMI(reg)    regs->reg = rmregs.regvoid PMAPI DPMI_int86(int intno, DPMI_regs *regs){	SWI_REGS	rmregs;	memset(&rmregs, 0, sizeof(rmregs));	INDPMI(eax); INDPMI(ebx); INDPMI(ecx); INDPMI(edx); INDPMI(esi); INDPMI(edi);	_dx_real_int(intno,&rmregs);	OUTDPMI(eax); OUTDPMI(ebx); OUTDPMI(ecx); OUTDPMI(edx); OUTDPMI(esi); OUTDPMI(edi);	regs->flags = rmregs.flags;}#define IN(reg)     rmregs.reg = in->e.reg#define OUT(reg)    out->e.reg = rmregs.reg

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -