📄 pm.c
字号:
if (sb->old50Lines) { regs.x.ax = 0x1112; regs.x.bx = 0; PM_int86(0x10,®s,®s); } (void)hwndConsole;}void PMAPI PM_closeConsole(PM_HWND hwndConsole){ /* Not used for DOS */ (void)hwndConsole;}void PMAPI PM_setOSCursorLocation(int x,int y){ uchar *_biosPtr = PM_getBIOSPointer(); PM_setByte(_biosPtr+0x50,x); PM_setByte(_biosPtr+0x51,y);}void PMAPI PM_setOSScreenWidth(int width,int height){ uchar *_biosPtr = PM_getBIOSPointer(); PM_setWord(_biosPtr+0x4A,width); PM_setWord(_biosPtr+0x4C,width*2); PM_setByte(_biosPtr+0x84,height-1); if (height > 25) { PM_setWord(_biosPtr+0x60,0x0607); PM_setByte(_biosPtr+0x85,0x08); } else { PM_setWord(_biosPtr+0x60,0x0D0E); PM_setByte(_biosPtr+0x85,0x016); }}void * PMAPI PM_mallocShared(long size){ return PM_malloc(size);}void PMAPI PM_freeShared(void *ptr){ PM_free(ptr);}#define GetRMVect(intno,isr) *(isr) = ((ulong*)rmZeroPtr)[intno]#define SetRMVect(intno,isr) ((ulong*)rmZeroPtr)[intno] = (isr)ibool PMAPI PM_doBIOSPOST( ushort axVal, ulong BIOSPhysAddr, void *mappedBIOS, ulong BIOSLen){ static int firstTime = true; static uchar *rmZeroPtr; long Current10,Current6D,Current42; RMREGS regs; RMSREGS sregs; /* Create a zero memory mapping for us to use */ if (firstTime) { rmZeroPtr = PM_mapPhysicalAddr(0,0x7FFF,true); firstTime = false; } /* Remap the secondary BIOS to 0xC0000 physical */ if (BIOSPhysAddr != 0xC0000L || BIOSLen > 32768) { /* DOS cannot virtually remap the BIOS, so we can only work if all * the secondary controllers are identical, and we then use the * BIOS on the first controller for all the remaining controllers. * * For OS'es that do virtual memory, and remapping of 0xC0000 * physical (perhaps a copy on write mapping) should be all that * is needed. */ return false; } /* Save current handlers of int 10h and 6Dh */ GetRMVect(0x10,&Current10); GetRMVect(0x6D,&Current6D); /* POST the secondary BIOS */ GetRMVect(0x42,&Current42); SetRMVect(0x10,Current42); /* Restore int 10h to STD-BIOS */ regs.x.ax = axVal; PM_callRealMode(0xC000,0x0003,®s,&sregs); /* Restore current handlers */ SetRMVect(0x10,Current10); SetRMVect(0x6D,Current6D); /* Second the primary BIOS mappin 1:1 for 0xC0000 physical */ if (BIOSPhysAddr != 0xC0000L) { /* DOS does not support this */ (void)mappedBIOS; } return true;}void PMAPI PM_sleep(ulong milliseconds){ ulong microseconds = milliseconds * 1000L; LZTimerObject tm; LZTimerOnExt(&tm); while (LZTimerLapExt(&tm) < microseconds) ; LZTimerOffExt(&tm);}int PMAPI PM_getCOMPort(int port){ switch (port) { case 0: return 0x3F8; case 1: return 0x2F8; } return 0;}int PMAPI PM_getLPTPort(int port){ switch (port) { case 0: return 0x3BC; case 1: return 0x378; case 2: return 0x278; } return 0;}PM_MODULE PMAPI PM_loadLibrary( const char *szDLLName){ (void)szDLLName; return NULL;}void * PMAPI PM_getProcAddress( PM_MODULE hModule, const char *szProcName){ (void)hModule; (void)szProcName; return NULL;}void PMAPI PM_freeLibrary( PM_MODULE hModule){ (void)hModule;}int PMAPI PM_setIOPL( int level){ return level;}/****************************************************************************REMARKS:Internal function to convert the find data to the generic interface.****************************************************************************/static void convertFindData( PM_findData *findData, struct find_t *blk){ ulong dwSize = findData->dwSize; memset(findData,0,findData->dwSize); findData->dwSize = dwSize; if (blk->attrib & _A_RDONLY) findData->attrib |= PM_FILE_READONLY; if (blk->attrib & _A_SUBDIR) findData->attrib |= PM_FILE_DIRECTORY; if (blk->attrib & _A_ARCH) findData->attrib |= PM_FILE_ARCHIVE; if (blk->attrib & _A_HIDDEN) findData->attrib |= PM_FILE_HIDDEN; if (blk->attrib & _A_SYSTEM) findData->attrib |= PM_FILE_SYSTEM; findData->sizeLo = blk->size; strncpy(findData->name,blk->name,PM_MAX_PATH); findData->name[PM_MAX_PATH-1] = 0;}#define FIND_MASK (_A_RDONLY | _A_ARCH | _A_SUBDIR | _A_HIDDEN | _A_SYSTEM)/****************************************************************************REMARKS:Function to find the first file matching a search criteria in a directory.****************************************************************************/void * PMAPI PM_findFirstFile( const char *filename, PM_findData *findData){ struct find_t *blk; if ((blk = PM_malloc(sizeof(*blk))) == NULL) return PM_FILE_INVALID; if (_dos_findfirst((char*)filename,FIND_MASK,blk) == 0) { convertFindData(findData,blk); return blk; } return PM_FILE_INVALID;}/****************************************************************************REMARKS:Function to find the next file matching a search criteria in a directory.****************************************************************************/ibool PMAPI PM_findNextFile( void *handle, PM_findData *findData){ struct find_t *blk = handle; if (_dos_findnext(blk) == 0) { convertFindData(findData,blk); return true; } return false;}/****************************************************************************REMARKS:Function to close the find process****************************************************************************/void PMAPI PM_findClose( void *handle){ PM_free(handle);}/****************************************************************************REMARKS:Function to determine if a drive is a valid drive or not. Under Unix thisfunction will return false for anything except a value of 3 (consideredthe root drive, and equivalent to C: for non-Unix systems). The drivenumbering is: 1 - Drive A: 2 - Drive B: 3 - Drive C: etc****************************************************************************/ibool PMAPI PM_driveValid( char drive){ RMREGS regs; regs.h.dl = (uchar)(drive - 'A' + 1); regs.h.ah = 0x36; /* Get disk information service */ PM_int86(0x21,®s,®s); return regs.x.ax != 0xFFFF; /* AX = 0xFFFF if disk is invalid */}/****************************************************************************REMARKS:Function to get the current working directory for the specififed drive.Under Unix this will always return the current working directory regardlessof what the value of 'drive' is.****************************************************************************/void PMAPI PM_getdcwd( int drive, char *dir, int len){ uint oldDrive,maxDrives; _dos_getdrive(&oldDrive); _dos_setdrive(drive,&maxDrives); getcwd(dir,len); _dos_setdrive(oldDrive,&maxDrives);}/****************************************************************************REMARKS:Function to change the file attributes for a specific file.****************************************************************************/void PMAPI PM_setFileAttr( const char *filename, uint attrib){#if defined(TNT) && defined(_MSC_VER) DWORD attr = 0; if (attrib & PM_FILE_READONLY) attr |= FILE_ATTRIBUTE_READONLY; if (attrib & PM_FILE_ARCHIVE) attr |= FILE_ATTRIBUTE_ARCHIVE; if (attrib & PM_FILE_HIDDEN) attr |= FILE_ATTRIBUTE_HIDDEN; if (attrib & PM_FILE_SYSTEM) attr |= FILE_ATTRIBUTE_SYSTEM; SetFileAttributes((LPSTR)filename, attr);#else uint attr = 0; if (attrib & PM_FILE_READONLY) attr |= _A_RDONLY; if (attrib & PM_FILE_ARCHIVE) attr |= _A_ARCH; if (attrib & PM_FILE_HIDDEN) attr |= _A_HIDDEN; if (attrib & PM_FILE_SYSTEM) attr |= _A_SYSTEM; _dos_setfileattr(filename,attr);#endif}/****************************************************************************REMARKS:Function to create a directory.****************************************************************************/ibool PMAPI PM_mkdir( const char *filename){#ifdef __GNUC__ return mkdir(filename,S_IRUSR) == 0;#else return mkdir(filename) == 0;#endif}/****************************************************************************REMARKS:Function to remove a directory.****************************************************************************/ibool PMAPI PM_rmdir( const char *filename){ return rmdir(filename) == 0;}/*-------------------------------------------------------------------------*//* Generic DPMI routines common to 16/32 bit code *//*-------------------------------------------------------------------------*/#ifndef REALMODEulong PMAPI DPMI_mapPhysicalToLinear(ulong physAddr,ulong limit){ PMREGS r; int i; ulong baseAddr,baseOfs,roundedLimit; /* 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. */ if (physAddr < 0x100000L) return physAddr; /* Search table of existing mappings to see if we have already mapped * a region of memory that will serve this purpose. We do this because * DPMI 0.9 does not allow us to free physical memory mappings, and if * the mappings get re-used in the program we want to avoid allocating * more mappings than necessary. */ for (i = 0; i < numMaps; i++) { if (maps[i].physical == physAddr && maps[i].limit == limit) return maps[i].linear; } /* Find a free slot in our physical memory mapping table */ for (i = 0; i < numMaps; i++) { if (maps[i].limit == 0) break; } if (i == numMaps) { i = numMaps++; if (i == MAX_MEMORY_MAPPINGS) return NULL; } /* 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. */ baseOfs = physAddr & 4095; baseAddr = physAddr & ~4095; roundedLimit = ((limit+baseOfs+1+4095) & ~4095)-1; r.x.ax = 0x800; r.x.bx = baseAddr >> 16; r.x.cx = baseAddr & 0xFFFF; r.x.si = roundedLimit >> 16; r.x.di = roundedLimit & 0xFFFF; PM_int386(0x31, &r, &r); if (r.x.cflag) return 0xFFFFFFFFUL; maps[i].physical = physAddr; maps[i].limit = limit; maps[i].linear = ((ulong)r.x.bx << 16) + r.x.cx + baseOfs; return maps[i].linear;}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);}/****************************************************************************REMARKS:Adjust the page table caching bits directly. Requires ring 0 access andonly works with DOS4GW and compatible extenders (CauseWay also works sinceit has direct support for the ring 0 instructions we need from ring 3). Willnot work in a DOS box, but we call into the ring 0 helper VxD so we shouldnever get here in a DOS box anyway (assuming the VxD is present). If wedo get here and we are in windows, this code will be skipped.****************************************************************************/static void PM_adjustPageTables( ulong linear, ulong limit, ibool isCached){#ifdef DOS4GW int startPDB,endPDB,iPDB,startPage,endPage,start,end,iPage; ulong andMask,orMask,pageTable,*pPageTable; andMask = ~0x18; orMask = (isCached) ? 0x00 : 0x18; if (_PM_pagingEnabled() == 1 && (PDB = _PM_getPDB()) != 0) { if (_PM_haveCauseWay) { /* CauseWay is a little different in the page table handling. * The code that we use for DOS4G/W does not appear to work * with CauseWay correctly as it does not appear to allow us * to map the page tables directly. Instead we can directly * access the page table entries in extended memory where * CauseWay always locates them (starting at 1024*4096*1023) */ startPage = (linear >> 12); endPage = ((linear+limit) >> 12); pPageTable = (ulong*)CW_PAGE_TABLE_START; for (iPage = startPage; iPage <= endPage; iPage++) pPageTable[iPage] = (pPageTable[iPage] & andMask) | orMask; } else { pPDB = (ulong*)DPMI_mapPhysicalToLinear(PDB,0xFFF); if (pPDB) { startPDB = (linear >> 22) & 0x3FF; startPage = (linear >> 12) & 0x3FF; endPDB = ((linear+limit) >> 22) & 0x3FF; endPage = ((linear+limit) >> 12) & 0x3FF; for (iPDB = startPDB; iPDB <= endPDB; iPDB++) { pageTable = pPDB[iPDB] & ~0xFFF; pPageTable = (ulong*)DPMI_mapPhysicalToLinear(pageTable,0xFFF); start = (iPDB == startPDB) ? startPage : 0; end = (iPDB == endPDB) ? endPage : 0x3FF; for (iPage = start; iPage <= end; iPage++) pPageTable[iPage] = (pPageTable[iPage] & andMask) | orMask; } } } PM_flushTLB(); }#endif}void * PMAPI DPMI_mapPhysicalAddr(ulong base,ulong limit,ibool isCached)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -