976 lines
27 KiB
C
976 lines
27 KiB
C
/****************************************************************************
|
|
*
|
|
* 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;
|
|
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++;
|
|
|
|
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));
|
|
|
|
|
|
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));
|
|
|
|
|
|
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;
|
|
|
|
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);
|
|
|
|
|
|
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;
|
|
}
|