| /**************************************************************************** |
| * |
| * SciTech OS Portability Manager Library |
| * |
| * ======================================================================== |
| * |
| * The contents of this file are subject to the SciTech MGL Public |
| * License Version 1.0 (the "License"); you may not use this file |
| * except in compliance with the License. You may obtain a copy of |
| * the License at http://www.scitechsoft.com/mgl-license.txt |
| * |
| * Software distributed under the License is distributed on an |
| * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or |
| * implied. See the License for the specific language governing |
| * rights and limitations under the License. |
| * |
| * The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc. |
| * |
| * The Initial Developer of the Original Code is SciTech Software, Inc. |
| * All Rights Reserved. |
| * |
| * ======================================================================== |
| * |
| * Language: ANSI C |
| * Environment: 32-bit OS/2 VDD |
| * |
| * Description: Implementation for the OS Portability Manager Library, which |
| * contains functions to implement OS specific services in a |
| * generic, cross platform API. Porting the OS Portability |
| * Manager library is the first step to porting any SciTech |
| * products to a new platform. |
| * |
| ****************************************************************************/ |
| |
| #include "pmapi.h" |
| #include "drvlib/os/os.h" |
| #include "sdd/sddhelp.h" |
| #include "mtrr.h" |
| |
| #define TRACE(a) |
| |
| /*--------------------------- Global variables ----------------------------*/ |
| |
| #define MAX_MEMORY_SHARED 100 |
| #define MAX_MEMORY_MAPPINGS 100 |
| |
| /* TODO: I think the global and linear members will be the same, but not sure yet. */ |
| typedef struct { |
| void *linear; |
| ulong global; |
| ulong length; |
| int npages; |
| } memshared; |
| |
| typedef struct { |
| ulong physical; |
| ulong linear; |
| ulong length; |
| int npages; |
| ibool isCached; |
| } mmapping; |
| |
| static int numMappings = 0; |
| static memshared shared[MAX_MEMORY_MAPPINGS] = {0}; |
| static mmapping maps[MAX_MEMORY_MAPPINGS]; |
| ibool _PM_haveBIOS = TRUE; |
| char _PM_cntPath[PM_MAX_PATH] = ""; /* there just isn't any */ |
| uchar *_PM_rmBufAddr = NULL; |
| ushort _VARAPI PM_savedDS = 0; /* why can't I use the underscore prefix? */ |
| |
| HVDHSEM hevFarCallRet = NULL; |
| HVDHSEM hevIRet = NULL; |
| HHOOK hhookUserReturnHook = NULL; |
| HHOOK hhookUserIRetHook = NULL; |
| |
| static void (PMAPIP fatalErrorCleanup)(void) = NULL; |
| |
| /*----------------------------- Implementation ----------------------------*/ |
| |
| /* Functions to read and write CMOS registers */ |
| |
| ulong PMAPI _PM_getPDB(void); |
| uchar PMAPI _PM_readCMOS(int index); |
| void PMAPI _PM_writeCMOS(int index,uchar value); |
| |
| VOID HOOKENTRY UserReturnHook(PVOID pRefData, PCRF pcrf); |
| VOID HOOKENTRY UserIRetHook(PVOID pRefData, PCRF pcrf); |
| |
| void PMAPI PM_init(void) |
| { |
| MTRR_init(); |
| |
| /* Initialize VDD-specific data */ |
| /* Note: PM_init must be (obviously) called in VDM task context! */ |
| VDHCreateSem(&hevFarCallRet, VDH_EVENTSEM); |
| VDHCreateSem(&hevIRet, VDH_EVENTSEM); |
| hhookUserReturnHook = VDHAllocHook(VDH_RETURN_HOOK, (PFNARM)UserReturnHook, 0); |
| hhookUserIRetHook = VDHAllocHook(VDH_RETURN_HOOK, (PFNARM)UserIRetHook, 0); |
| |
| if ((hevIRet == NULL) || (hevFarCallRet == NULL) || |
| (hhookUserReturnHook == NULL) || (hhookUserIRetHook == NULL)) { |
| /* something failed, we can't go on */ |
| /* TODO: take some action here! */ |
| } |
| } |
| |
| /* Do some cleaning up */ |
| void PMAPI PM_exit(void) |
| { |
| /* Note: Hooks allocated during or after VDM creation are deallocated automatically */ |
| if (hevIRet != NULL) |
| VDHDestroySem(hevIRet); |
| |
| if (hevFarCallRet != NULL) |
| VDHDestroySem(hevFarCallRet); |
| } |
| |
| ibool PMAPI PM_haveBIOSAccess(void) |
| { return _PM_haveBIOS; } |
| |
| long PMAPI PM_getOSType(void) |
| { return /*_OS_OS2VDD*/ _OS_OS2; } /*FIX!! */ |
| |
| int PMAPI PM_getModeType(void) |
| { return PM_386; } |
| |
| void PMAPI PM_backslash(char *s) |
| { |
| uint pos = strlen(s); |
| if (s[pos-1] != '\\') { |
| s[pos] = '\\'; |
| s[pos+1] = '\0'; |
| } |
| } |
| |
| void PMAPI PM_setFatalErrorCleanup( |
| void (PMAPIP cleanup)(void)) |
| { |
| fatalErrorCleanup = cleanup; |
| } |
| |
| void PMAPI PM_fatalError(const char *msg) |
| { |
| if (fatalErrorCleanup) |
| fatalErrorCleanup(); |
| /* Fatal_Error_Handler(msg,0); TODO: implement somehow! */ |
| } |
| |
| /**************************************************************************** |
| PARAMETERS: |
| len - Place to store the length of the buffer |
| rseg - Place to store the real mode segment of the buffer |
| roff - Place to store the real mode offset of the buffer |
| |
| REMARKS: |
| This function returns the address and length of the global VESA transfer |
| buffer. |
| ****************************************************************************/ |
| void * PMAPI PM_getVESABuf( |
| uint *len, |
| uint *rseg, |
| uint *roff) |
| { |
| if (_PM_rmBufAddr) { |
| *len = 0; /*VESA_BUF_SIZE; */ |
| *rseg = (ulong)(_PM_rmBufAddr) >> 4; |
| *roff = (ulong)(_PM_rmBufAddr) & 0xF; |
| return _PM_rmBufAddr; |
| } |
| return NULL; |
| } |
| |
| int PMAPI PM_int386(int intno, PMREGS *in, PMREGS *out) |
| { |
| /* Unused in VDDs */ |
| return 0; |
| } |
| |
| char * PMAPI PM_getCurrentPath(char *path,int maxLen) |
| { |
| strncpy(path, _PM_cntPath, maxLen); |
| path[maxLen - 1] = 0; |
| return path; |
| } |
| |
| char PMAPI PM_getBootDrive(void) |
| { |
| ulong boot = 3; |
| boot = VDHQuerySysValue(0, VDHGSV_BOOTDRV); |
| return (char)('a' + boot - 1); |
| } |
| |
| const char * PMAPI PM_getVBEAFPath(void) |
| { |
| static char path[CCHMAXPATH]; |
| strcpy(path,"x:\\"); |
| path[0] = PM_getBootDrive(); |
| return path; |
| } |
| |
| const char * PMAPI PM_getNucleusPath(void) |
| { |
| static char path[CCHMAXPATH]; |
| strcpy(path,"x:\\os2\\drivers"); |
| path[0] = PM_getBootDrive(); |
| PM_backslash(path); |
| strcat(path,"nucleus"); |
| return path; |
| } |
| |
| const char * PMAPI PM_getNucleusConfigPath(void) |
| { |
| static char path[256]; |
| strcpy(path,PM_getNucleusPath()); |
| PM_backslash(path); |
| strcat(path,"config"); |
| return path; |
| } |
| |
| const char * PMAPI PM_getUniqueID(void) |
| { return PM_getMachineName(); } |
| |
| const char * PMAPI PM_getMachineName(void) |
| { |
| return "Unknown"; |
| } |
| |
| int PMAPI PM_kbhit(void) |
| { return 1; } |
| |
| int PMAPI PM_getch(void) |
| { return 0; } |
| |
| PM_HWND PMAPI PM_openConsole(PM_HWND hwndUser,int device,int xRes,int yRes,int bpp,ibool fullScreen) |
| { |
| /* Unused in VDDs */ |
| return NULL; |
| } |
| |
| int PMAPI PM_getConsoleStateSize(void) |
| { |
| /* Unused in VDDs */ |
| return 1; |
| } |
| |
| void PMAPI PM_saveConsoleState(void *stateBuf,PM_HWND hwndConsole) |
| { |
| /* Unused in VDDs */ |
| } |
| |
| void PMAPI PM_setSuspendAppCallback(int (_ASMAPIP saveState)(int flags)) |
| { |
| /* Unused in VDDs */ |
| } |
| |
| void PMAPI PM_restoreConsoleState(const void *stateBuf,PM_HWND hwndConsole) |
| { |
| /* Unused in VDDs */ |
| } |
| |
| void PMAPI PM_closeConsole(PM_HWND hwndConsole) |
| { |
| /* Unused in VDDs */ |
| } |
| |
| 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_setByte(_biosPtr+0x4A,width); |
| PM_setByte(_biosPtr+0x84,height-1); |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| Allocate a block of shared memory. For OS/2 VDD we allocate shared memory |
| as locked, global memory that is accessible from any memory context |
| (including interrupt time context), which allows us to load our important |
| data structure and code such that we can access it directly from a ring |
| 0 interrupt context. |
| ****************************************************************************/ |
| void * PMAPI PM_mallocShared(long size) |
| { |
| ULONG nPages = (size + 0xFFF) >> 12; |
| int i; |
| |
| /* First find a free slot in our shared memory table */ |
| for (i = 0; i < MAX_MEMORY_SHARED; i++) { |
| if (shared[i].linear == 0) |
| break; |
| } |
| if (i < MAX_MEMORY_SHARED) { |
| shared[i].linear = VDHAllocPages(NULL, nPages, VDHAP_SYSTEM | VDHAP_FIXED); |
| shared[i].npages = nPages; |
| shared[i].global = (ULONG)shared[i].linear; |
| return (void*)shared[i].global; |
| } |
| return NULL; |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| Free a block of shared memory |
| ****************************************************************************/ |
| void PMAPI PM_freeShared(void *p) |
| { |
| int i; |
| |
| /* Find a shared memory block in our table and free it */ |
| for (i = 0; i < MAX_MEMORY_SHARED; i++) { |
| if (shared[i].global == (ulong)p) { |
| VDHFreePages(shared[i].linear); |
| shared[i].linear = 0; |
| break; |
| } |
| } |
| } |
| |
| void * PMAPI PM_mapToProcess(void *base,ulong limit) |
| { return (void*)base; } |
| |
| ibool PMAPI PM_doBIOSPOST( |
| ushort axVal, |
| ulong BIOSPhysAddr, |
| void *mappedBIOS, |
| ulong BIOSLen) |
| { |
| /* TODO: Figure out how to do this */ |
| return false; |
| } |
| |
| void * PMAPI PM_getBIOSPointer(void) |
| { return (void*)0x400; } |
| |
| void * PMAPI PM_getA0000Pointer(void) |
| { return PM_mapPhysicalAddr(0xA0000,0xFFFF,true); } |
| |
| /**************************************************************************** |
| PARAMETERS: |
| base - Physical base address of the memory to maps in |
| limit - Limit of physical memory to region to maps in |
| |
| RETURNS: |
| Linear address of the newly mapped memory. |
| |
| REMARKS: |
| Maps a physical memory range to a linear memory range. |
| ****************************************************************************/ |
| ulong MapPhysicalToLinear( |
| ulong base, |
| ulong limit, |
| int *npages) |
| { |
| ulong linear,length = limit+1; |
| int i,ppage,flags; |
| #if 0 |
| ppage = base >> 12; |
| *npages = (length + (base & 0xFFF) + 4095) >> 12; |
| flags = PR_FIXED | PR_STATIC; |
| if (base == 0xA0000) { |
| /* We require the linear address to be aligned to a 64Kb boundary |
| * for mapping the banked framebuffer (so we can do efficient |
| * carry checking for bank changes in the assembler code). The only |
| * way to ensure this is to force the linear address to be aligned |
| * to a 4Mb boundary. |
| */ |
| flags |= PR_4MEG; |
| } |
| if ((linear = (ulong)PageReserve(PR_SYSTEM,*npages,flags)) == (ulong)-1) |
| return 0; |
| if (!PageCommitPhys(linear >> 12,*npages,ppage,PC_INCR | PC_USER | PC_WRITEABLE)) |
| return 0; |
| #endif |
| return linear + (base & 0xFFF); |
| } |
| |
| /**************************************************************************** |
| PARAMETERS: |
| base - Physical base address of the memory to map in |
| limit - Limit of physical memory to region to map in |
| isCached - True if the memory should be cached, false if not |
| |
| RETURNS: |
| Linear address of the newly mapped memory. |
| |
| REMARKS: |
| This function maps physical memory to linear memory, which can then be used |
| to create a selector or used directly from 32-bit protected mode programs. |
| This is better than DPMI 0x800, since it allows you to maps physical |
| memory below 1Mb, which gets this memory out of the way of the Windows VxD's |
| sticky paws. |
| |
| NOTE: If the memory is not expected to be cached, this function will |
| directly re-program the PCD (Page Cache Disable) bit in the |
| page tables. There does not appear to be a mechanism in the VMM |
| to control this bit via the regular interface. |
| ****************************************************************************/ |
| void * PMAPI PM_mapPhysicalAddr( |
| ulong base, |
| ulong limit, |
| ibool isCached) |
| { |
| ulong linear,length = limit+1; |
| int i,npages; |
| ulong PDB,*pPDB; |
| |
| /* Search table of existing mappings to see if we have already mapped |
| * a region of memory that will serve this purpose. |
| */ |
| for (i = 0; i < numMappings; i++) { |
| if (maps[i].physical == base && maps[i].length == length && maps[i].isCached == isCached) |
| return (void*)maps[i].linear; |
| } |
| if (numMappings == MAX_MEMORY_MAPPINGS) |
| return NULL; |
| |
| /* We did not find any previously mapped memory region, so map it in. |
| * Note that we do not use MapPhysToLinear, since this function appears |
| * to have problems mapping memory in the 1Mb physical address space. |
| * Hence we use PageReserve and PageCommitPhys. |
| */ |
| if ((linear = MapPhysicalToLinear(base,limit,&npages)) == 0) |
| return NULL; |
| maps[numMappings].physical = base; |
| maps[numMappings].length = length; |
| maps[numMappings].linear = linear; |
| maps[numMappings].npages = npages; |
| maps[numMappings].isCached = isCached; |
| numMappings++; |
| |
| #if 0 |
| /* Finally disable caching where necessary */ |
| if (!isCached && (PDB = _PM_getPDB()) != 0) { |
| int startPDB,endPDB,iPDB,startPage,endPage,start,end,iPage; |
| ulong pageTable,*pPageTable; |
| |
| if (PDB >= 0x100000) |
| pPDB = (ulong*)MapPhysicalToLinear(PDB,0xFFF,&npages); |
| else |
| pPDB = (ulong*)PDB; |
| 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; |
| if (pageTable >= 0x100000) |
| pPageTable = (ulong*)MapPhysicalToLinear(pageTable,0xFFF,&npages); |
| else |
| pPageTable = (ulong*)pageTable; |
| start = (iPDB == startPDB) ? startPage : 0; |
| end = (iPDB == endPDB) ? endPage : 0x3FF; |
| for (iPage = start; iPage <= end; iPage++) |
| pPageTable[iPage] |= 0x10; |
| PageFree((ulong)pPageTable,PR_STATIC); |
| } |
| PageFree((ulong)pPDB,PR_STATIC); |
| } |
| } |
| #endif |
| return (void*)linear; |
| } |
| |
| void PMAPI PM_freePhysicalAddr(void *ptr,ulong limit) |
| { |
| /* We never free the mappings */ |
| } |
| |
| void PMAPI PM_sleep(ulong milliseconds) |
| { |
| /* We never sleep in a VDD */ |
| } |
| |
| int PMAPI PM_getCOMPort(int port) |
| { |
| /* TODO: Re-code this to determine real values using the Plug and Play */ |
| /* manager for the OS. */ |
| switch (port) { |
| case 0: return 0x3F8; |
| case 1: return 0x2F8; |
| } |
| return 0; |
| } |
| |
| int PMAPI PM_getLPTPort(int port) |
| { |
| /* TODO: Re-code this to determine real values using the Plug and Play */ |
| /* manager for the OS. */ |
| switch (port) { |
| case 0: return 0x3BC; |
| case 1: return 0x378; |
| case 2: return 0x278; |
| } |
| return 0; |
| } |
| |
| ulong PMAPI PM_getPhysicalAddr(void *p) |
| { |
| /* TODO: This function should find the physical address of a linear */ |
| /* address. */ |
| return 0xFFFFFFFFUL; |
| } |
| |
| void PMAPI _PM_freeMemoryMappings(void) |
| { |
| int i; |
| /* for (i = 0; i < numMappings; i++) */ |
| /* PageFree(maps[i].linear,PR_STATIC); */ |
| } |
| |
| void * PMAPI PM_mapRealPointer(uint r_seg,uint r_off) |
| { return (void*)MK_PHYS(r_seg,r_off); } |
| |
| void * PMAPI PM_allocRealSeg(uint size,uint *r_seg,uint *r_off) |
| { return NULL; } |
| |
| void PMAPI PM_freeRealSeg(void *mem) |
| { } |
| |
| void PMAPI DPMI_int86(int intno, DPMI_regs *regs) |
| { |
| /* Unsed in VDDs */ |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| Load the V86 registers in the client state, and save the original state |
| before loading the registers. |
| ****************************************************************************/ |
| static void LoadV86Registers( |
| PCRF saveRegs, |
| RMREGS *in, |
| RMSREGS *sregs) |
| { |
| PCRF pcrf; /* current client register frame */ |
| |
| /* get pointer to registers */ |
| pcrf = (PCRF)VDHQuerySysValue(CURRENT_VDM, VDHLSV_PCRF); |
| |
| /* Note: We could do VDHPushRegs instead but this should be safer as it */ |
| /* doesn't rely on the VDM session having enough free stack space. */ |
| *saveRegs = *pcrf; /* save all registers */ |
| |
| pcrf->crf_eax = in->e.eax; /* load new values */ |
| pcrf->crf_ebx = in->e.ebx; |
| pcrf->crf_ecx = in->e.ecx; |
| pcrf->crf_edx = in->e.edx; |
| pcrf->crf_esi = in->e.esi; |
| pcrf->crf_edi = in->e.edi; |
| pcrf->crf_es = sregs->es; |
| pcrf->crf_ds = sregs->ds; |
| |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| Read the V86 registers from the client state and restore the original state. |
| ****************************************************************************/ |
| static void ReadV86Registers( |
| PCRF saveRegs, |
| RMREGS *out, |
| RMSREGS *sregs) |
| { |
| PCRF pcrf; /* current client register frame */ |
| |
| /* get pointer to registers */ |
| pcrf = (PCRF)VDHQuerySysValue(CURRENT_VDM, VDHLSV_PCRF); |
| |
| /* read new register values */ |
| out->e.eax = pcrf->crf_eax; |
| out->e.ebx = pcrf->crf_ebx; |
| out->e.ecx = pcrf->crf_ecx; |
| out->e.edx = pcrf->crf_edx; |
| out->e.esi = pcrf->crf_esi; |
| out->e.edi = pcrf->crf_edi; |
| sregs->es = pcrf->crf_es; |
| sregs->ds = pcrf->crf_ds; |
| |
| /* restore original client registers */ |
| *pcrf = *saveRegs; |
| } |
| |
| /**************************************************************************** |
| REMARKS: Used for far calls into V86 code |
| ****************************************************************************/ |
| VOID HOOKENTRY UserReturnHook( |
| PVOID pRefData, |
| PCRF pcrf ) |
| { |
| VDHPostEventSem(hevFarCallRet); |
| } |
| |
| /**************************************************************************** |
| REMARKS: Used for calling BIOS interrupts |
| ****************************************************************************/ |
| VOID HOOKENTRY UserIRetHook( |
| PVOID pRefData, |
| PCRF pcrf ) |
| { |
| VDHPostEventSem(hevIRet); |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| Call a V86 real mode function with the specified register values |
| loaded before the call. The call returns with a far ret. |
| Must be called from within a DOS session context! |
| ****************************************************************************/ |
| void PMAPI PM_callRealMode( |
| uint seg, |
| uint off, |
| RMREGS *regs, |
| RMSREGS *sregs) |
| { |
| CRF saveRegs; |
| FPFN fnAddress; |
| ULONG rc; |
| |
| TRACE("SDDHELP: Entering PM_callRealMode()\n"); |
| LoadV86Registers(SSToDS(&saveRegs),regs,sregs); |
| |
| /* set up return hook for call */ |
| rc = VDHArmReturnHook(hhookUserReturnHook, VDHARH_CSEIP_HOOK); |
| |
| VDHResetEventSem(hevFarCallRet); |
| |
| /* the address is a 16:32 pointer */ |
| OFFSETOF32(fnAddress) = off; |
| SEGMENTOF32(fnAddress) = seg; |
| rc = VDHPushFarCall(fnAddress); |
| VDHYield(0); |
| |
| /* wait until the V86 call returns - our return hook posts the semaphore */ |
| rc = VDHWaitEventSem(hevFarCallRet, SEM_INDEFINITE_WAIT); |
| |
| ReadV86Registers(SSToDS(&saveRegs),regs,sregs); |
| TRACE("SDDHELP: Exiting PM_callRealMode()\n"); |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| Issue a V86 real mode interrupt with the specified register values |
| loaded before the interrupt. |
| Must be called from within a DOS session context! |
| ****************************************************************************/ |
| int PMAPI PM_int86( |
| int intno, |
| RMREGS *in, |
| RMREGS *out) |
| { |
| RMSREGS sregs = {0}; |
| CRF saveRegs; |
| ushort oldDisable; |
| ULONG rc; |
| |
| memset(SSToDS(&sregs), 0, sizeof(sregs)); |
| |
| #if 0 /* do we need this?? */ |
| /* Disable pass-up to our VDD handler so we directly call BIOS */ |
| TRACE("SDDHELP: Entering PM_int86()\n"); |
| if (disableTSRFlag) { |
| oldDisable = *disableTSRFlag; |
| *disableTSRFlag = 0; |
| } |
| #endif |
| |
| LoadV86Registers(SSToDS(&saveRegs), in, SSToDS(&sregs)); |
| |
| VDHResetEventSem(hevIRet); |
| rc = VDHPushInt(intno); |
| |
| /* set up return hook for interrupt */ |
| rc = VDHArmReturnHook(hhookUserIRetHook, VDHARH_NORMAL_IRET); |
| |
| VDHYield(0); |
| |
| /* wait until the V86 IRETs - our return hook posts the semaphore */ |
| rc = VDHWaitEventSem(hevIRet, 5000); /*SEM_INDEFINITE_WAIT); */ |
| |
| ReadV86Registers(SSToDS(&saveRegs), out, SSToDS(&sregs)); |
| |
| #if 0 |
| /* Re-enable pass-up to our VDD handler if previously enabled */ |
| if (disableTSRFlag) |
| *disableTSRFlag = oldDisable; |
| #endif |
| |
| TRACE("SDDHELP: Exiting PM_int86()\n"); |
| return out->x.ax; |
| |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| Issue a V86 real mode interrupt with the specified register values |
| loaded before the interrupt. |
| ****************************************************************************/ |
| int PMAPI PM_int86x( |
| int intno, |
| RMREGS *in, |
| RMREGS *out, |
| RMSREGS *sregs) |
| { |
| CRF saveRegs; |
| ushort oldDisable; |
| ULONG rc; |
| |
| #if 0 |
| /* Disable pass-up to our VxD handler so we directly call BIOS */ |
| TRACE("SDDHELP: Entering PM_int86x()\n"); |
| if (disableTSRFlag) { |
| oldDisable = *disableTSRFlag; |
| *disableTSRFlag = 0; |
| } |
| #endif |
| LoadV86Registers(SSToDS(&saveRegs), in, sregs); |
| |
| VDHResetEventSem(hevIRet); |
| rc = VDHPushInt(intno); |
| |
| /* set up return hook for interrupt */ |
| rc = VDHArmReturnHook(hhookUserIRetHook, VDHARH_NORMAL_IRET); |
| |
| VDHYield(0); |
| |
| /* wait until the V86 IRETs - our return hook posts the semaphore */ |
| rc = VDHWaitEventSem(hevIRet, 5000); /*SEM_INDEFINITE_WAIT); */ |
| |
| ReadV86Registers(SSToDS(&saveRegs), out, sregs); |
| |
| #if 0 |
| /* Re-enable pass-up to our VxD handler if previously enabled */ |
| if (disableTSRFlag) |
| *disableTSRFlag = oldDisable; |
| #endif |
| |
| TRACE("SDDHELP: Exiting PM_int86x()\n"); |
| return out->x.ax; |
| } |
| |
| void PMAPI PM_availableMemory(ulong *physical,ulong *total) |
| { *physical = *total = 0; } |
| |
| /**************************************************************************** |
| REMARKS: |
| Allocates a block of locked physical memory. |
| ****************************************************************************/ |
| void * PMAPI PM_allocLockedMem( |
| uint size, |
| ulong *physAddr, |
| ibool contiguous, |
| ibool below16M) |
| { |
| ULONG flags = VDHAP_SYSTEM; |
| ULONG nPages = (size + 0xFFF) >> 12; |
| |
| flags |= (physAddr != NULL) ? VDHAP_PHYSICAL : VDHAP_FIXED; |
| |
| return VDHAllocPages(physAddr, nPages, VDHAP_SYSTEM | VDHAP_PHYSICAL); |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| Frees a block of locked physical memory. |
| ****************************************************************************/ |
| void PMAPI PM_freeLockedMem( |
| void *p, |
| uint size, |
| ibool contiguous) |
| { |
| if (p) |
| VDHFreePages((PVOID)p); |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| Lock linear memory so it won't be paged. |
| ****************************************************************************/ |
| int PMAPI PM_lockDataPages(void *p,uint len,PM_lockHandle *lh) |
| { |
| ULONG lockHandle; |
| |
| /* TODO: the lock handle is essential for the unlock operation!! */ |
| lockHandle = VDHLockMem(p, len, 0, (PVOID)VDHLM_NO_ADDR, NULL); |
| |
| if (lockHandle != NULL) |
| return 0; |
| else |
| return 1; |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| Unlock linear memory so it won't be paged. |
| ****************************************************************************/ |
| int PMAPI PM_unlockDataPages(void *p,uint len,PM_lockHandle *lh) |
| { |
| /* TODO: implement - use a table of lock handles? */ |
| /* VDHUnlockPages(lockHandle); */ |
| return 0; |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| Lock linear memory so it won't be paged. |
| ****************************************************************************/ |
| int PMAPI PM_lockCodePages(void (*p)(),uint len,PM_lockHandle *lh) |
| { |
| return PM_lockDataPages((void*)p,len,lh); |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| Unlock linear memory so it won't be paged. |
| ****************************************************************************/ |
| int PMAPI PM_unlockCodePages(void (*p)(),uint len,PM_lockHandle *lh) |
| { |
| return PM_unlockDataPages((void*)p,len,lh); |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| OS specific shared libraries not supported inside a VDD |
| ****************************************************************************/ |
| PM_MODULE PMAPI PM_loadLibrary( |
| const char *szDLLName) |
| { |
| (void)szDLLName; |
| return NULL; |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| OS specific shared libraries not supported inside a VDD |
| ****************************************************************************/ |
| void * PMAPI PM_getProcAddress( |
| PM_MODULE hModule, |
| const char *szProcName) |
| { |
| (void)hModule; |
| (void)szProcName; |
| return NULL; |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| OS specific shared libraries not supported inside a VDD |
| ****************************************************************************/ |
| void PMAPI PM_freeLibrary( |
| PM_MODULE hModule) |
| { |
| (void)hModule; |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| Function to find the first file matching a search criteria in a directory. |
| ****************************************************************************/ |
| void *PMAPI PM_findFirstFile( |
| const char *filename, |
| PM_findData *findData) |
| { |
| /* TODO: This function should start a directory enumeration search */ |
| /* given the filename (with wildcards). The data should be */ |
| /* converted and returned in the findData standard form. */ |
| (void)filename; |
| (void)findData; |
| 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) |
| { |
| /* TODO: This function should find the next file in directory enumeration */ |
| /* search given the search criteria defined in the call to */ |
| /* PM_findFirstFile. The data should be converted and returned */ |
| /* in the findData standard form. */ |
| (void)handle; |
| (void)findData; |
| return false; |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| Function to close the find process |
| ****************************************************************************/ |
| void PMAPI PM_findClose( |
| void *handle) |
| { |
| /* TODO: This function should close the find process. This may do */ |
| /* nothing for some OS'es. */ |
| (void)handle; |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| Function to determine if a drive is a valid drive or not. Under Unix this |
| function will return false for anything except a value of 3 (considered |
| the root drive, and equivalent to C: for non-Unix systems). The drive |
| numbering is: |
| |
| 1 - Drive A: |
| 2 - Drive B: |
| 3 - Drive C: |
| etc |
| |
| ****************************************************************************/ |
| ibool PMAPI PM_driveValid( |
| char drive) |
| { |
| /* Not applicable in a VDD */ |
| (void)drive; |
| return false; |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| Function to get the current working directory for the specififed drive. |
| Under Unix this will always return the current working directory regardless |
| of what the value of 'drive' is. |
| ****************************************************************************/ |
| void PMAPI PM_getdcwd( |
| int drive, |
| char *dir, |
| int len) |
| { |
| /* Not applicable in a VDD */ |
| (void)drive; |
| (void)dir; |
| (void)len; |
| } |
| |
| /**************************************************************************** |
| PARAMETERS: |
| base - The starting physical base address of the region |
| size - The size in bytes of the region |
| type - Type to place into the MTRR register |
| |
| RETURNS: |
| Error code describing the result. |
| |
| REMARKS: |
| Function to enable write combining for the specified region of memory. |
| ****************************************************************************/ |
| int PMAPI PM_enableWriteCombine( |
| ulong base, |
| ulong size, |
| uint type) |
| { |
| return MTRR_enableWriteCombine(base,size,type); |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| Function to change the file attributes for a specific file. |
| ****************************************************************************/ |
| void PMAPI PM_setFileAttr( |
| const char *filename, |
| uint attrib) |
| { |
| /* TODO: Implement this ? */ |
| (void)filename; |
| (void)attrib; |
| PM_fatalError("PM_setFileAttr not implemented!"); |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| Function to get the file attributes for a specific file. |
| ****************************************************************************/ |
| uint PMAPI PM_getFileAttr( |
| const char *filename) |
| { |
| /* TODO: Implement this ? */ |
| (void)filename; |
| PM_fatalError("PM_getFileAttr not implemented!"); |
| return 0; |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| Function to create a directory. |
| ****************************************************************************/ |
| ibool PMAPI PM_mkdir( |
| const char *filename) |
| { |
| /* TODO: Implement this ? */ |
| (void)filename; |
| PM_fatalError("PM_mkdir not implemented!"); |
| return false; |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| Function to remove a directory. |
| ****************************************************************************/ |
| ibool PMAPI PM_rmdir( |
| const char *filename) |
| { |
| /* TODO: Implement this ? */ |
| (void)filename; |
| PM_fatalError("PM_rmdir not implemented!"); |
| return false; |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| Function to get the file time and date for a specific file. |
| ****************************************************************************/ |
| ibool PMAPI PM_getFileTime( |
| const char *filename, |
| ibool gmTime, |
| PM_time *time) |
| { |
| /* TODO: Implement this ? */ |
| (void)filename; |
| (void)gmTime; |
| (void)time; |
| PM_fatalError("PM_getFileTime not implemented!"); |
| return false; |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| Function to set the file time and date for a specific file. |
| ****************************************************************************/ |
| ibool PMAPI PM_setFileTime( |
| const char *filename, |
| ibool gmTime, |
| PM_time *time) |
| { |
| /* TODO: Implement this ? */ |
| (void)filename; |
| (void)gmTime; |
| (void)time; |
| PM_fatalError("PM_setFileTime not implemented!"); |
| return false; |
| } |