/****************************************************************************
*
* PM/Pro Library
*
* Copyright (C) 1996 SciTech Software.
* All rights reserved.
*
* Filename: $Workfile: pmpro.c $
* Version: $Revision: 1.0 $
*
* Language: ANSI C
* Environment: IBM PC (MSDOS) Real mode and 16/32 bit Protected Mode
*
* Description: Module implementing DOS extender independant protected
* mode programming. This module will need to be included in
* all programs that use SciTech Software's products that
* are to be compiled in protected mode, and will need to be
* compiled with the correct defines for the DOS extender that
* you will be using (or with no defines for real mode
* emulation of these routines).
*
* $Date: 05 Feb 1996 21:41:30 $ $Author: KendallB $
*
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pmpro.h"
#ifndef __WINDOWS__
/*--------------------------- Global variables ----------------------------*/
#ifndef REALMODE
static int globalDataStart;
#endif
PM_criticalHandler _PM_critHandler = NULL;
PM_breakHandler _PM_breakHandler = NULL;
PM_intHandler _PM_timerHandler = NULL;
PM_intHandler _PM_keyHandler = NULL;
PM_key15Handler _PM_key15Handler = NULL;
PM_mouseHandler _PM_mouseHandler = NULL;
int _PM_mouseMask;
uint _PM_ctrlCSel,_PM_ctrlCOff; /* Location of Ctrl-C flag */
uint _PM_ctrlBSel,_PM_ctrlBOff; /* Location of Ctrl-Break flag */
uint _PM_critSel,_PM_critOff; /* Location of Critical error Bf*/
PMFARPTR _PM_prevTimer = PMNULL; /* Previous timer handler */
PMFARPTR _PM_prevKey = PMNULL; /* Previous key handler */
PMFARPTR _PM_prevKey15 = PMNULL; /* Previous key15 handler */
PMFARPTR _PM_prevVBE = PMNULL; /* Previous VBE handler */
PMFARPTR _PM_prevBreak = PMNULL; /* Previous break handler */
PMFARPTR _PM_prevCtrlC = PMNULL; /* Previous CtrlC handler */
PMFARPTR _PM_prevCritical = PMNULL; /* Previous critical handler */
long _PM_prevRealTimer; /* Previous real mode timer */
long _PM_prevRealKey; /* Previous real mode key */
long _PM_prevRealKey15; /* Previous real mode key15 */
#ifndef REALMODE
static int globalDataEnd;
#endif
/*----------------------------- Implementation ----------------------------*/
/* Globals for locking interrupt handlers in _pmpro.asm */
#ifndef REALMODE
extern int _PM_pmproDataStart;
extern int _PM_pmproDataEnd;
void _ASMAPI _PM_pmproCodeStart(void);
void _ASMAPI _PM_pmproCodeEnd(void);
#endif
/* Protected mode interrupt handlers, also called by PM callbacks below */
void _ASMAPI _PM_timerISR(void);
void _ASMAPI _PM_keyISR(void);
void _ASMAPI _PM_key15ISR(void);
void _ASMAPI _PM_breakISR(void);
void _ASMAPI _PM_ctrlCISR(void);
void _ASMAPI _PM_criticalISR(void);
void _ASMAPI _PM_mouseISR(void);
/* Protected mode DPMI callback handlers */
void _ASMAPI _PM_mousePMCB(void);
/* Routine to install a mouse handler function */
void _ASMAPI _PM_setMouseHandler(int mask);
/* Routine to allocate DPMI real mode callback routines */
void _ASMAPI _DPMI_allocateCallback(void (_ASMAPI *pmcode)(),void *rmregs,long *RMCB);
void _ASMAPI _DPMI_freeCallback(long RMCB);
/* DPMI helper functions in PMLITE.C */
ulong DPMI_mapPhysicalToLinear(ulong physAddr,ulong limit);
int DPMI_setSelectorBase(ushort sel,ulong linAddr);
ulong DPMI_getSelectorBase(ushort sel);
int DPMI_setSelectorLimit(ushort sel,ulong limit);
uint DPMI_createSelector(ulong base,ulong limit);
void DPMI_freeSelector(uint sel);
int DPMI_lockLinearPages(ulong linear,ulong len);
int DPMI_unlockLinearPages(ulong linear,ulong len);
void PMAPI _PM_getRMvect(int intno, long *realisr);
void PMAPI _PM_setRMvect(int intno, long realisr);
/*-------------------------------------------------------------------------*/
/* Generic routines common to all extenders */
/*-------------------------------------------------------------------------*/
void PMAPI PM_resetMouseDriver(int hardReset)
{
RMREGS regs;
PM_mouseHandler oldHandler = _PM_mouseHandler;
PM_restoreMouseHandler();
regs.x.ax = hardReset ? 0 : 33;
PM_int86(0x33, ®s, ®s);
if (oldHandler)
PM_setMouseHandler(_PM_mouseMask, oldHandler);
}
#ifndef REALMODE
static void PMAPI lockPMHandlers(void)
{
static int locked = 0;
int stat = 0;
/* Lock all of the code and data used by our protected mode interrupt
* handling routines, so that it will continue to work correctly
* under real mode.
*/
if (!locked) {
PM_saveDS();
stat = !PM_lockDataPages(&globalDataStart,(int)&globalDataEnd-(int)&globalDataStart);
stat |= !PM_lockDataPages(&_PM_pmproDataStart,(int)&_PM_pmproDataEnd - (int)&_PM_pmproDataStart);
stat |= !PM_lockCodePages((__codePtr)_PM_pmproCodeStart,(int)_PM_pmproCodeEnd-(int)_PM_pmproCodeStart);
if (stat) {
printf("Page locking services failed - interrupt handling not safe!\n");
exit(1);
}
locked = 1;
}
}
#endif
/*-------------------------------------------------------------------------*/
/* DOS Real Mode support. */
/*-------------------------------------------------------------------------*/
#ifdef REALMODE
#ifndef MK_FP
#define MK_FP(s,o) ( (void far *)( ((ulong)(s) << 16) + \
(ulong)(o) ))
#endif
int PMAPI PM_setMouseHandler(int mask, PM_mouseHandler mh)
{
PM_saveDS();
_PM_mouseHandler = mh;
_PM_setMouseHandler(_PM_mouseMask = mask);
return 1;
}
void PMAPI PM_restoreMouseHandler(void)
{
union REGS regs;
if (_PM_mouseHandler) {
regs.x.ax = 33;
int86(0x33, ®s, ®s);
_PM_mouseHandler = NULL;
}
}
void PMAPI PM_setTimerHandler(PM_intHandler th)
{
_PM_getRMvect(0x8, (long*)&_PM_prevTimer);
_PM_timerHandler = th;
_PM_setRMvect(0x8, (long)_PM_timerISR);
}
void PMAPI PM_restoreTimerHandler(void)
{
if (_PM_timerHandler) {
_PM_setRMvect(0x8, (long)_PM_prevTimer);
_PM_timerHandler = NULL;
}
}
void PMAPI PM_setKeyHandler(PM_intHandler kh)
{
_PM_getRMvect(0x9, (long*)&_PM_prevKey);
_PM_keyHandler = kh;
_PM_setRMvect(0x9, (long)_PM_keyISR);
}
void PMAPI PM_restoreKeyHandler(void)
{
if (_PM_keyHandler) {
_PM_setRMvect(0x9, (long)_PM_prevKey);
_PM_keyHandler = NULL;
}
}
void PMAPI PM_setKey15Handler(PM_key15Handler kh)
{
_PM_getRMvect(0x15, (long*)&_PM_prevKey15);
_PM_key15Handler = kh;
_PM_setRMvect(0x15, (long)_PM_key15ISR);
}
void PMAPI PM_restoreKey15Handler(void)
{
if (_PM_key15Handler) {
_PM_setRMvect(0x15, (long)_PM_prevKey15);
_PM_key15Handler = NULL;
}
}
void PMAPI PM_installAltBreakHandler(PM_breakHandler bh)
{
static int ctrlCFlag,ctrlBFlag;
void *p;
p = &ctrlCFlag; /* Need this for buggy compilers */
_PM_ctrlCSel = FP_SEG(p);
_PM_ctrlCOff = FP_OFF(p);
p = &ctrlBFlag; /* Need this for buggy compilers */
_PM_ctrlBSel = FP_SEG(p);
_PM_ctrlBOff = FP_OFF(p);
_PM_getRMvect(0x1B, (long*)&_PM_prevBreak);
_PM_getRMvect(0x23, (long*)&_PM_prevCtrlC);
_PM_breakHandler = bh;
_PM_setRMvect(0x1B, (long)_PM_breakISR);
_PM_setRMvect(0x23, (long)_PM_ctrlCISR);
}
void PMAPI PM_installBreakHandler(void)
{
PM_installAltBreakHandler(NULL);
}
void PMAPI PM_restoreBreakHandler(void)
{
if (_PM_prevBreak) {
_PM_setRMvect(0x1B, (long)_PM_prevBreak);
_PM_setRMvect(0x23, (long)_PM_prevCtrlC);
_PM_prevBreak = NULL;
_PM_breakHandler = NULL;
}
}
void PMAPI PM_installAltCriticalHandler(PM_criticalHandler ch)
{
static short critBuf[2];
void *p;
p = critBuf; /* Need this for buggy compilers */
_PM_critSel = FP_SEG(p);
_PM_critOff = FP_OFF(p);
_PM_getRMvect(0x24, (long*)&_PM_prevCritical);
_PM_critHandler = ch;
_PM_setRMvect(0x24, (long)_PM_criticalISR);
}
void PMAPI PM_installCriticalHandler(void)
{
PM_installAltCriticalHandler(NULL);
}
void PMAPI PM_restoreCriticalHandler(void)
{
if (_PM_prevCritical) {
_PM_setRMvect(0x24, (long)_PM_prevCritical);
_PM_prevCritical = NULL;
_PM_critHandler = NULL;
}
}
int PMAPI PM_lockDataPages(void *p,uint len)
{
p = p; len = len; /* Do nothing for real mode */
return 1;
}
int PMAPI PM_unlockDataPages(void *p,uint len)
{
p = p; len = len; /* Do nothing for real mode */
return 1;
}
int PMAPI PM_lockCodePages(void (*p)(),uint len)
{
p = p; len = len; /* Do nothing for real mode */
return 1;
}
int PMAPI PM_unlockCodePages(void (*p)(),uint len)
{
p = p; len = len; /* Do nothing for real mode */
return 1;
}
void PMAPI PM_getPMvect(int intno, PMFARPTR *isr)
{
long t;
_PM_getRMvect(intno,&t);
*isr = (void*)t;
}
void PMAPI PM_setPMvect(int intno, PM_intHandler isr)
{
PM_saveDS();
_PM_setRMvect(intno,(long)isr);
}
void PMAPI PM_restorePMvect(int intno, PMFARPTR isr)
{
_PM_setRMvect(intno,(long)isr);
}
#endif
/*-------------------------------------------------------------------------*/
/* Borland DPMI16 DOS Power Pack support. */
/*-------------------------------------------------------------------------*/
#if defined(__WINDOWS16__) || defined(DPMI16)
static long prevRealBreak; /* Previous real mode break handler */
static long prevRealCtrlC; /* Previous real mode CtrlC handler */
static long prevRealCritical; /* Prev real mode critical handler */
int PMAPI PM_setMouseHandler(int mask, PM_mouseHandler mh)
{
lockPMHandlers(); /* Ensure our handlers are locked */
_PM_mouseHandler = mh;
_PM_setMouseHandler(_PM_mouseMask = mask);
return 1;
}
void PMAPI PM_restoreMouseHandler(void)
{
union REGS regs;
if (_PM_mouseHandler) {
regs.x.ax = 33;
int86(0x33, ®s, ®s);
_PM_mouseHandler = NULL;
}
}
void PMAPI PM_getPMvect(int intno, PMFARPTR *isr)
{
union REGS regs;
regs.x.ax = 0x204;
regs.h.bl = intno;
int86(0x31,®s,®s);
*isr = MK_FP(regs.x.cx, regs.x.dx);
}
void PMAPI PM_setPMvect(int intno, PM_intHandler isr)
{
PM_saveDS();
PM_restorePMvect(intno, (void*)isr);
}
void PMAPI PM_restorePMvect(int intno, PMFARPTR isr)
{
union REGS regs;
regs.x.ax = 0x205;
regs.h.bl = intno;
regs.x.cx = FP_SEG(isr);
regs.x.dx = FP_OFF(isr);
int86(0x31,®s,®s);
}
static void getISR(int intno, PMFARPTR *pmisr, long *realisr)
{
PM_getPMvect(intno,pmisr);
_PM_getRMvect(intno,realisr);
}
static void restoreISR(int intno, PMFARPTR pmisr, long realisr)
{
_PM_setRMvect(intno,realisr);
PM_restorePMvect(intno,pmisr);
}
static void setISR(int intno, void (* PMAPI pmisr)())
{
lockPMHandlers(); /* Ensure our handlers are locked */
PM_setPMvect(intno,pmisr);
}
void PMAPI PM_setTimerHandler(PM_intHandler th)
{
getISR(0x8, &_PM_prevTimer, &_PM_prevRealTimer);
_PM_timerHandler = th;
setISR(0x8, _PM_timerISR);
}
void PMAPI PM_restoreTimerHandler(void)
{
if (_PM_timerHandler) {
restoreISR(0x8, _PM_prevTimer, _PM_prevRealTimer);
_PM_timerHandler = NULL;
}
}
void PMAPI PM_setKeyHandler(PM_intHandler kh)
{
getISR(0x9, &_PM_prevKey, &_PM_prevRealKey);
_PM_keyHandler = kh;
setISR(0x9, _PM_keyISR);
}
void PMAPI PM_restoreKeyHandler(void)
{
if (_PM_keyHandler) {
restoreISR(0x9, _PM_prevKey, _PM_prevRealKey);
_PM_keyHandler = NULL;
}
}
void PMAPI PM_setKey15Handler(PM_key15Handler kh)
{
getISR(0x15, &_PM_prevKey15, &_PM_prevRealKey15);
_PM_key15Handler = kh;
setISR(0x15, _PM_key15ISR);
}
void PMAPI PM_restoreKey15Handler(void)
{
if (_PM_key15Handler) {
restoreISR(0x15, _PM_prevKey15, _PM_prevRealKey15);
_PM_key15Handler = NULL;
}
}
/* Real mode Ctrl-C and Ctrl-Break handler. This handler simply sets a
* flag in the real mode code segment and exits. We save the location
* of this flag in real mode memory so that both the real mode and
* protected mode code will be modifying the same flags.
*/
static uchar ctrlHandler[] = {
0x00,0x00,0x00,0x00, /* ctrlBFlag */
0x66,0x2E,0xC7,0x06,0x00,0x00,
0x01,0x00,0x00,0x00, /* mov [cs:ctrlBFlag],1 */
0xCF, /* iretf */
};
void PMAPI PM_installAltBreakHandler(PM_breakHandler bh)
{
uint rseg,roff;
getISR(0x1B, &_PM_prevBreak, &prevRealBreak);
getISR(0x23, &_PM_prevCtrlC, &prevRealCtrlC);
_PM_breakHandler = bh;
setISR(0x1B, _PM_breakISR);
setISR(0x23, _PM_ctrlCISR);
/* Hook the real mode vectors for these handlers, as these are not
* normally reflected by the DPMI server up to protected mode
*/
PM_allocRealSeg(sizeof(ctrlHandler)*2, &_PM_ctrlBSel, &_PM_ctrlBOff,
&rseg, &roff);
PM_memcpyfn(_PM_ctrlBSel,_PM_ctrlBOff,ctrlHandler,
sizeof(ctrlHandler));
PM_memcpyfn(_PM_ctrlBSel,_PM_ctrlBOff+sizeof(ctrlHandler),
ctrlHandler,sizeof(ctrlHandler));
_PM_ctrlCSel = _PM_ctrlBSel;
_PM_ctrlCOff = _PM_ctrlBOff + sizeof(ctrlHandler);
_PM_setRMvect(0x1B,((long)rseg << 16) | roff+4);
_PM_setRMvect(0x23,((long)rseg << 16) | roff+sizeof(ctrlHandler)+4);
}
void PMAPI PM_installBreakHandler(void)
{
PM_installAltBreakHandler(NULL);
}
void PMAPI PM_restoreBreakHandler(void)
{
if (_PM_prevBreak) {
restoreISR(0x1B, _PM_prevBreak, prevRealBreak);
restoreISR(0x23, _PM_prevCtrlC, prevRealCtrlC);
PM_freeRealSeg(_PM_ctrlBSel, _PM_ctrlBOff);
_PM_prevBreak = NULL;
_PM_breakHandler = NULL;
}
}
/* Real mode Critical Error handler. This handler simply saves the AX and
* DI values in the real mode code segment and exits. We save the location
* of this flag in real mode memory so that both the real mode and
* protected mode code will be modifying the same flags.
*/
static uchar criticalHandler[] = {
0x00,0x00, /* axCode */
0x00,0x00, /* diCode */
0x2E,0xA3,0x00,0x00, /* mov [cs:axCode],ax */
0x2E,0x89,0x3E,0x02,0x00, /* mov [cs:diCode],di */
0xB8,0x03,0x00, /* mov ax,3 */
0xCF, /* iretf */
};
void PMAPI PM_installAltCriticalHandler(PM_criticalHandler ch)
{
uint rseg,roff;
getISR(0x24, &_PM_prevCritical, &prevRealCritical);
_PM_critHandler = ch;
setISR(0x24, _PM_criticalISR);
/* Hook the real mode vector, as this is not normally reflected by the
* DPMI server up to protected mode.
*/
PM_allocRealSeg(sizeof(criticalHandler)*2, &_PM_critSel, &_PM_critOff,
&rseg, &roff);
PM_memcpyfn(_PM_critSel,_PM_critOff,criticalHandler,
sizeof(criticalHandler));
_PM_setRMvect(0x24,((long)rseg << 16) | roff+4);
}
void PMAPI PM_installCriticalHandler(void)
{
PM_installAltCriticalHandler(NULL);
}
void PMAPI PM_restoreCriticalHandler(void)
{
if (_PM_prevCritical) {
restoreISR(0x24, _PM_prevCritical, prevRealCritical);
PM_freeRealSeg(_PM_critSel, _PM_critOff);
_PM_prevCritical = NULL;
_PM_critHandler = NULL;
}
}
int PMAPI PM_lockDataPages(void *p,uint len)
{
PMSREGS sregs;
PM_segread(&sregs);
return DPMI_lockLinearPages(FP_OFF(p) + DPMI_getSelectorBase(sregs.ds),len);
}
int PMAPI PM_unlockDataPages(void *p,uint len)
{
PMSREGS sregs;
PM_segread(&sregs);
return DPMI_unlockLinearPages(FP_OFF(p) + DPMI_getSelectorBase(sregs.ds),len);
}
int PMAPI PM_lockCodePages(void (*p)(),uint len)
{
PMSREGS sregs;
PM_segread(&sregs);
return DPMI_lockLinearPages(FP_OFF(p) + DPMI_getSelectorBase(sregs.cs),len);
}
int PMAPI PM_unlockCodePages(void (*p)(),uint len)
{
PMSREGS sregs;
PM_segread(&sregs);
return DPMI_unlockLinearPages(FP_OFF(p) + DPMI_getSelectorBase(sregs.cs),len);
}
#endif
/*-------------------------------------------------------------------------*/
/* Phar Lap TNT DOS Extender support. */
/*-------------------------------------------------------------------------*/
#ifdef TNT
#include <pldos32.h>
#include <pharlap.h>
#include <hw386.h>
static long prevRealBreak; /* Previous real mode break handler */
static long prevRealCtrlC; /* Previous real mode CtrlC handler */
static long prevRealCritical; /* Prev real mode critical handler */
static uint mouseSel,mouseOff;
/* The following real mode routine is used to call a 32 bit protected
* mode FAR function from real mode. We use this for passing up control
* from the real mode mouse callback to our protected mode code.
*/
static UCHAR realHandler[] = { /* Real mode code generic handler */
0x00,0x00,0x00,0x00, /* __PM_callProtp */
0x00,0x00, /* __PM_protCS */
0x00,0x00,0x00,0x00, /* __PM_protHandler */
0x66,0x60, /* pushad */
0x1E, /* push ds */
0x6A,0x00, /* push 0 */
0x6A,0x00, /* push 0 */
0x2E,0xFF,0x36,0x04,0x00, /* push [cs:__PM_protCS] */
0x66,0x2E,0xFF,0x36,0x06,0x00, /* push [cs:__PM_protHandler] */
0x2E,0xFF,0x1E,0x00,0x00, /* call [cs:__PM_callProtp] */
0x83,0xC4,0x0A, /* add sp,10 */
0x1F, /* pop ds */
0x66,0x61, /* popad */
0xCB, /* retf */
};
/* The following functions installs the above realmode callback mechanism
* in real mode memory for calling the protected mode routine.
*/
int installCallback(void (PMAPI *pmCB)(),uint *psel, uint *poff,
uint *rseg, uint *roff)
{
CONFIG_INF config;
REALPTR realBufAdr,callProtp;
ULONG bufSize;
FARPTR protBufAdr;
/* Get address of real mode routine to call up to protected mode */
_dx_rmlink_get(&callProtp, &realBufAdr, &bufSize, &protBufAdr);
_dx_config_inf(&config, (UCHAR*)&config);
/* Fill in the values in the real mode code segment so that it will
* call the correct routine.
*/
*((REALPTR*)&realHandler[0]) = callProtp;
*((USHORT*)&realHandler[4]) = config.c_cs_sel;
*((ULONG*)&realHandler[6]) = (ULONG)pmCB;
/* Copy the real mode handler to real mode memory */
if (!PM_allocRealSeg(sizeof(realHandler),psel,poff,rseg,roff))
return 0;
PM_memcpyfn(*psel,*poff,realHandler,sizeof(realHandler));
/* Skip past global variabls in real mode code segment */
*roff += 0x0A;
return 1;
}
int PMAPI PM_setMouseHandler(int mask, PM_mouseHandler mh)
{
RMREGS regs;
RMSREGS sregs;
uint rseg,roff;
lockPMHandlers(); /* Ensure our handlers are locked */
if (!installCallback(_PM_mouseISR, &mouseSel, &mouseOff, &rseg, &roff))
return 0;
_PM_mouseHandler = mh;
/* Install the real mode mouse handler */
sregs.es = rseg;
regs.x.dx = roff;
regs.x.cx = _PM_mouseMask = mask;
regs.x.ax = 0xC;
PM_int86x(0x33, ®s, ®s, &sregs);
return 1;
}
void PMAPI PM_restoreMouseHandler(void)
{
RMREGS regs;
if (_PM_mouseHandler) {
regs.x.ax = 33;
PM_int86(0x33, ®s, ®s);
PM_freeRealSeg(mouseSel,mouseOff);
_PM_mouseHandler = NULL;
}
}
void PMAPI PM_getPMvect(int intno, PMFARPTR *isr)
{
FARPTR ph;
_dx_pmiv_get(intno, &ph);
isr->sel = FP_SEL(ph);
isr->off = FP_OFF(ph);
}
void PMAPI PM_setPMvect(int intno, PM_intHandler isr)
{
CONFIG_INF config;
FARPTR ph;
PM_saveDS();
_dx_config_inf(&config, (UCHAR*)&config);
FP_SET(ph,(uint)isr,config.c_cs_sel);
_dx_pmiv_set(intno,ph);
}
void PMAPI PM_restorePMvect(int intno, PMFARPTR isr)
{
FARPTR ph;
FP_SET(ph,isr.off,isr.sel);
_dx_pmiv_set(intno,ph);
}
static void getISR(int intno, PMFARPTR *pmisr, long *realisr)
{
PM_getPMvect(intno,pmisr);
_PM_getRMvect(intno, realisr);
}
static void restoreISR(int intno, PMFARPTR pmisr, long realisr)
{
_PM_setRMvect(intno,realisr);
PM_restorePMvect(intno,pmisr);
}
static void setISR(int intno, void (PMAPI *isr)())
{
CONFIG_INF config;
FARPTR ph;
lockPMHandlers(); /* Ensure our handlers are locked */
_dx_config_inf(&config, (UCHAR*)&config);
FP_SET(ph,(uint)isr,config.c_cs_sel);
_dx_apmiv_set(intno,ph);
}
void PMAPI PM_setTimerHandler(PM_intHandler th)
{
getISR(0x8, &_PM_prevTimer, &_PM_prevRealTimer);
_PM_timerHandler = th;
setISR(0x8, _PM_timerISR);
}
void PMAPI PM_restoreTimerHandler(void)
{
if (_PM_timerHandler) {
restoreISR(0x8, _PM_prevTimer, _PM_prevRealTimer);
_PM_timerHandler = NULL;
}
}
void PMAPI PM_setKeyHandler(PM_intHandler kh)
{
getISR(0x9, &_PM_prevKey, &_PM_prevRealKey);
_PM_keyHandler = kh;
setISR(0x9, _PM_keyISR);
}
void PMAPI PM_restoreKeyHandler(void)
{
if (_PM_keyHandler) {
restoreISR(0x9, _PM_prevKey, _PM_prevRealKey);
_PM_keyHandler = NULL;
}
}
void PMAPI PM_setKey15Handler(PM_key15Handler kh)
{
getISR(0x15, &_PM_prevKey15, &_PM_prevRealKey15);
_PM_key15Handler = kh;
setISR(0x15, _PM_key15ISR);
}
void PMAPI PM_restoreKey15Handler(void)
{
if (_PM_key15Handler) {
restoreISR(0x15, _PM_prevKey15, _PM_prevRealKey15);
_PM_key15Handler = NULL;
}
}
void PMAPI PM_installAltBreakHandler(PM_breakHandler bh)
{
static int ctrlCFlag,ctrlBFlag;
CONFIG_INF config;
_dx_config_inf(&config, (UCHAR*)&config);
_PM_ctrlCSel = config.c_ds_sel;
_PM_ctrlCOff = (uint)&ctrlCFlag;
_PM_ctrlBSel = config.c_ds_sel;
_PM_ctrlBOff = (uint)&ctrlBFlag;
getISR(0x1B, &_PM_prevBreak, &prevRealBreak);
getISR(0x23, &_PM_prevCtrlC, &prevRealCtrlC);
_PM_breakHandler = bh;
setISR(0x1B, _PM_breakISR);
setISR(0x23, _PM_ctrlCISR);
}
void PMAPI PM_installBreakHandler(void)
{
PM_installAltBreakHandler(NULL);
}
void PMAPI PM_restoreBreakHandler(void)
{
if (_PM_prevBreak.sel) {
restoreISR(0x1B, _PM_prevBreak, prevRealBreak);
restoreISR(0x23, _PM_prevCtrlC, prevRealCtrlC);
_PM_prevBreak.sel = 0;
_PM_breakHandler = NULL;
}
}
void PMAPI PM_installAltCriticalHandler(PM_criticalHandler ch)
{
static short critBuf[2];
CONFIG_INF config;
_dx_config_inf(&config, (UCHAR*)&config);
_PM_critSel = config.c_ds_sel;
_PM_critOff = (uint)critBuf;
getISR(0x24, &_PM_prevCritical, &prevRealCritical);
_PM_critHandler = ch;
setISR(0x24, _PM_criticalISR);
}
void PMAPI PM_installCriticalHandler(void)
{
PM_installAltCriticalHandler(NULL);
}
void PMAPI PM_restoreCriticalHandler(void)
{
if (_PM_prevCritical.sel) {
restoreISR(0x24, _PM_prevCritical, prevRealCritical);
_PM_prevCritical.sel = 0;
_PM_critHandler = NULL;
}
}
int PMAPI PM_lockDataPages(void *p,uint len)
{
return (_dx_lock_pgsn(p,len) == 0);
}
int PMAPI PM_unlockDataPages(void *p,uint len)
{
return (_dx_ulock_pgsn(p,len) == 0);
}
int PMAPI PM_lockCodePages(void (*p)(),uint len)
{
CONFIG_INF config;
FARPTR fp;
_dx_config_inf(&config, (UCHAR*)&config);
FP_SET(fp,p,config.c_cs_sel);
return (_dx_lock_pgs(fp,len) == 0);
}
int PMAPI PM_unlockCodePages(void (*p)(),uint len)
{
CONFIG_INF config;
FARPTR fp;
_dx_config_inf(&config, (UCHAR*)&config);
FP_SET(fp,p,config.c_cs_sel);
return (_dx_ulock_pgs(fp,len) == 0);
}
#endif
/*-------------------------------------------------------------------------*/
/* Symantec C++ DOSX and FlashTek X-32/X-32VM support */
/*-------------------------------------------------------------------------*/
#if defined(DOSX) || defined(X32VM)
#ifdef X32VM
#include <x32.h>
#endif
static long prevRealBreak; /* Previous real mode break handler */
static long prevRealCtrlC; /* Previous real mode CtrlC handler */
static long prevRealCritical; /* Prev real mode critical handler */
static uint mouseSel = 0,mouseOff;
/* The following real mode routine is used to call a 32 bit protected
* mode FAR function from real mode. We use this for passing up control
* from the real mode mouse callback to our protected mode code.
*/
static char realHandler[] = { /* Real mode code generic handler */
0x00,0x00,0x00,0x00, /* __PM_callProtp */
0x00,0x00, /* __PM_protCS */
0x00,0x00,0x00,0x00, /* __PM_protHandler */
0x1E, /* push ds */
0x6A,0x00, /* push 0 */
0x6A,0x00, /* push 0 */
0x2E,0xFF,0x36,0x04,0x00, /* push [cs:__PM_protCS] */
0x66,0x2E,0xFF,0x36,0x06,0x00, /* push [cs:__PM_protHandler] */
0x2E,0xFF,0x1E,0x00,0x00, /* call [cs:__PM_callProtp] */
0x83,0xC4,0x0A, /* add sp,10 */
0x1F, /* pop ds */
0xCB, /* retf */
};
/* The following functions installs the above realmode callback mechanism
* in real mode memory for calling the protected mode routine.
*/
int installCallback(void (PMAPI *pmCB)(),uint *psel, uint *poff,
uint *rseg, uint *roff)
{
PMREGS regs;
PMSREGS sregs;
regs.x.ax = 0x250D;
PM_segread(&sregs);
PM_int386x(0x21,®s,®s,&sregs); /* Get RM callback address */
/* Fill in the values in the real mode code segment so that it will
* call the correct routine.
*/
*((ulong*)&realHandler[0]) = regs.e.eax;
*((ushort*)&realHandler[4]) = sregs.cs;
*((ulong*)&realHandler[6]) = (ulong)pmCB;
/* Copy the real mode handler to real mode memory (only allocate the
* buffer once since we cant dealloate it with X32).
*/
if (*psel == 0) {
if (!PM_allocRealSeg(sizeof(realHandler),psel,poff,rseg,roff))
return 0;
}
PM_memcpyfn(*psel,*poff,realHandler,sizeof(realHandler));
/* Skip past global variables in real mode code segment */
*roff += 0x0A;
return 1;
}
int PMAPI PM_setMouseHandler(int mask, PM_mouseHandler mh)
{
RMREGS regs;
RMSREGS sregs;
uint rseg,roff;
lockPMHandlers(); /* Ensure our handlers are locked */
if (!installCallback(_PM_mouseISR, &mouseSel, &mouseOff, &rseg, &roff))
return 0;
_PM_mouseHandler = mh;
/* Install the real mode mouse handler */
sregs.es = rseg;
regs.x.dx = roff;
regs.x.cx = _PM_mouseMask = mask;
regs.x.ax = 0xC;
PM_int86x(0x33, ®s, ®s, &sregs);
return 1;
}
void PMAPI PM_restoreMouseHandler(void)
{
RMREGS regs;
if (_PM_mouseHandler) {
regs.x.ax = 33;
PM_int86(0x33, ®s, ®s);
_PM_mouseHandler = NULL;
}
}
void PMAPI PM_getPMvect(int intno, PMFARPTR *isr)
{
PMREGS regs;
PMSREGS sregs;
PM_segread(&sregs);
regs.x.ax = 0x2502; /* Get PM interrupt vector */
regs.x.cx = intno;
PM_int386x(0x21, ®s, ®s, &sregs);
isr->sel = sregs.es;
isr->off = regs.e.ebx;
}
void PMAPI PM_setPMvect(int intno, PM_intHandler isr)
{
PMFARPTR pmisr;
PMSREGS sregs;
PM_saveDS();
PM_segread(&sregs);
pmisr.sel = sregs.cs;
pmisr.off = (uint)isr;
PM_restorePMvect(intno, pmisr);
}
void PMAPI PM_restorePMvect(int intno, PMFARPTR isr)
{
PMREGS regs;
PMSREGS sregs;
PM_segread(&sregs);
regs.x.ax = 0x2505; /* Set PM interrupt vector */
regs.x.cx = intno;
sregs.ds = isr.sel;
regs.e.edx = isr.off;
PM_int386x(0x21, ®s, ®s, &sregs);
}
static void getISR(int intno, PMFARPTR *pmisr, long *realisr)
{
PM_getPMvect(intno,pmisr);
_PM_getRMvect(intno,realisr);
}
static void restoreISR(int intno, PMFARPTR pmisr, long realisr)
{
PMREGS regs;
PMSREGS sregs;
PM_segread(&sregs);
regs.x.ax = 0x2507; /* Set real and PM vectors */
regs.x.cx = intno;
sregs.ds = pmisr.sel;
regs.e.edx = pmisr.off;
regs.e.ebx = realisr;
PM_int386x(0x21, ®s, ®s, &sregs);
}
static void setISR(int intno, void *isr)
{
PMREGS regs;
PMSREGS sregs;
lockPMHandlers(); /* Ensure our handlers are locked */
PM_segread(&sregs);
regs.x.ax = 0x2506; /* Hook real and protected vectors */
regs.x.cx = intno;
sregs.ds = sregs.cs;
regs.e.edx = (uint)isr;
PM_int386x(0x21, ®s, ®s, &sregs);
}
void PMAPI PM_setTimerHandler(PM_intHandler th)
{
getISR(0x8, &_PM_prevTimer, &_PM_prevRealTimer);
_PM_timerHandler = th;
setISR(0x8, _PM_timerISR);
}
void PMAPI PM_restoreTimerHandler(void)
{
if (_PM_timerHandler) {
restoreISR(0x8, _PM_prevTimer, _PM_prevRealTimer);
_PM_timerHandler = NULL;
}
}
void PMAPI PM_setKeyHandler(PM_intHandler kh)
{
getISR(0x9, &_PM_prevKey, &_PM_prevRealKey);
_PM_keyHandler = kh;
setISR(0x9, _PM_keyISR);
}
void PMAPI PM_restoreKeyHandler(void)
{
if (_PM_keyHandler) {
restoreISR(0x9, _PM_prevKey, _PM_prevRealKey);
_PM_keyHandler = NULL;
}
}
void PMAPI PM_setKey15Handler(PM_key15Handler kh)
{
getISR(0x15, &_PM_prevKey15, &_PM_prevRealKey15);
_PM_key15Handler = kh;
setISR(0x15, _PM_key15ISR);
}
void PMAPI PM_restoreKey15Handler(void)
{
if (_PM_key15Handler) {
restoreISR(0x15, _PM_prevKey15, _PM_prevRealKey15);
_PM_key15Handler = NULL;
}
}
void PMAPI PM_installAltBreakHandler(PM_breakHandler bh)
{
static int ctrlCFlag,ctrlBFlag;
PMSREGS sregs;
PM_segread(&sregs);
_PM_ctrlCSel = sregs.ds;
_PM_ctrlCOff = (uint)&ctrlCFlag;
_PM_ctrlBSel = sregs.ds;
_PM_ctrlBOff = (uint)&ctrlBFlag;
getISR(0x1B, &_PM_prevBreak, &prevRealBreak);
getISR(0x23, &_PM_prevCtrlC, &prevRealCtrlC);
_PM_breakHandler = bh;
setISR(0x1B, _PM_breakISR);
setISR(0x23, _PM_ctrlCISR);
}
void PMAPI PM_installBreakHandler(void)
{
PM_installAltBreakHandler(NULL);
}
void PMAPI PM_restoreBreakHandler(void)
{
if (_PM_prevBreak.sel) {
restoreISR(0x1B, _PM_prevBreak, prevRealBreak);
restoreISR(0x23, _PM_prevCtrlC, prevRealCtrlC);
_PM_prevBreak.sel = 0;
_PM_breakHandler = NULL;
}
}
void PMAPI PM_installAltCriticalHandler(PM_criticalHandler ch)
{
static short critBuf[2];
PMSREGS sregs;
PM_segread(&sregs);
_PM_critSel = sregs.ds;
_PM_critOff = (uint)critBuf;
getISR(0x24, &_PM_prevCritical, &prevRealCritical);
_PM_critHandler = ch;
setISR(0x24, _PM_criticalISR);
}
void PMAPI PM_installCriticalHandler(void)
{
PM_installAltCriticalHandler(NULL);
}
void PMAPI PM_restoreCriticalHandler(void)
{
if (_PM_prevCritical.sel) {
restoreISR(0x24, _PM_prevCritical, prevRealCritical);
_PM_prevCritical.sel = 0;
_PM_critHandler = NULL;
}
}
int PMAPI PM_lockDataPages(void *p,uint len)
{
return (_x386_memlock(p,len) == 0);
}
int PMAPI PM_unlockDataPages(void *p,uint len)
{
return (_x386_memunlock(p,len) == 0);
}
int PMAPI PM_lockCodePages(void (*p)(),uint len)
{
return (_x386_memlock(p,len) == 0);
}
int PMAPI PM_unlockCodePages(void (*p)(),uint len)
{
return (_x386_memunlock(p,len) == 0);
}
#endif
/*-------------------------------------------------------------------------*/
/* Borland's DPMI32 DOS Power Pack Extender support. */
/*-------------------------------------------------------------------------*/
#ifdef DPMI32
#define GENERIC_DPMI32 /* Use generic 32 bit DPMI routines */
void PMAPI PM_getPMvect(int intno, PMFARPTR *isr)
{
PMREGS regs;
regs.x.ax = 0x204;
regs.h.bl = intno;
PM_int386(0x31,®s,®s);
isr->sel = regs.x.cx;
isr->off = regs.e.edx;
}
void PMAPI PM_setPMvect(int intno, PM_intHandler isr)
{
PMSREGS sregs;
PMREGS regs;
PM_saveDS();
regs.x.ax = 0x205; /* Set protected mode vector */
regs.h.bl = intno;
PM_segread(&sregs);
regs.x.cx = sregs.cs;
regs.e.edx = (uint)isr;
PM_int386(0x31,®s,®s);
}
void PMAPI PM_restorePMvect(int intno, PMFARPTR isr)
{
PMREGS regs;
regs.x.ax = 0x205;
regs.h.bl = intno;
regs.x.cx = isr.sel;
regs.e.edx = isr.off;
PM_int386(0x31,®s,®s);
}
/* The following is supposed to work, according to all the Borland
* documentation and the sample code that they give us. However it
* never does work 100% (never in the MGL code) so we install the
* mouse handler ourselves using the real mode callback stuff. This
* unfortunately has the effect of causing TD32's mouse handling stuff
* to be hooked out.
*/
#if 0
#define MOUSE_SUPPORTED /* DPMI32 directly supports mouse */
int PMAPI PM_setMouseHandler(int mask, PM_mouseHandler mh)
{
lockPMHandlers(); /* Ensure our handlers are locked */
_PM_mouseHandler = mh;
_PM_setMouseHandler(_PM_mouseMask = mask);
return 1;
}
void PMAPI PM_restoreMouseHandler(void)
{
PMREGS regs;
if (_PM_mouseHandler) {
regs.x.ax = 33;
PM_int386(0x33, ®s, ®s);
_PM_mouseHandler = NULL;
}
}
#endif
#endif
/*-------------------------------------------------------------------------*/
/* Watcom C/C++ with Rational DOS/4GW support. */
/*-------------------------------------------------------------------------*/
#ifdef DOS4GW
#define GENERIC_DPMI32 /* Use generic 32 bit DPMI routines */
#define MOUSE_SUPPORTED /* DOS4GW directly supports mouse */
/* We use the normal DOS services to save and restore interrupts handlers
* for Watcom C++, because using the direct DPMI functions does not
* appear to work properly. At least if we use the DPMI functions, we
* dont get the auto-passup feature that we need to correctly trap
* real and protected mode interrupts without installing Bi-model
* interrupt handlers.
*/
void PMAPI PM_getPMvect(int intno, PMFARPTR *isr)
{
PMREGS regs;
PMSREGS sregs;
PM_segread(&sregs);
regs.h.ah = 0x35;
regs.h.al = intno;
PM_int386x(0x21,®s,®s,&sregs);
isr->sel = sregs.es;
isr->off = regs.e.ebx;
}
void PMAPI PM_setPMvect(int intno, PM_intHandler isr)
{
PMREGS regs;
PMSREGS sregs;
PM_saveDS();
PM_segread(&sregs);
regs.h.ah = 0x25;
regs.h.al = intno;
sregs.ds = sregs.cs;
regs.e.edx = (uint)isr;
PM_int386x(0x21,®s,®s,&sregs);
}
void PMAPI PM_restorePMvect(int intno, PMFARPTR isr)
{
PMREGS regs;
PMSREGS sregs;
PM_segread(&sregs);
regs.h.ah = 0x25;
regs.h.al = intno;
sregs.ds = isr.sel;
regs.e.edx = isr.off;
PM_int386x(0x21,®s,®s,&sregs);
}
int PMAPI PM_setMouseHandler(int mask, PM_mouseHandler mh)
{
lockPMHandlers(); /* Ensure our handlers are locked */
_PM_mouseHandler = mh;
_PM_setMouseHandler(_PM_mouseMask = mask);
return 1;
}
void PMAPI PM_restoreMouseHandler(void)
{
PMREGS regs;
if (_PM_mouseHandler) {
regs.x.ax = 33;
PM_int386(0x33, ®s, ®s);
_PM_mouseHandler = NULL;
}
}
#endif
/*-------------------------------------------------------------------------*/
/* DJGPP port of GNU C++ support. */
/*-------------------------------------------------------------------------*/
#ifdef DJGPP
#define GENERIC_DPMI32 /* Use generic 32 bit DPMI routines */
#define MOUSE_SUPPORTED /* go32 directly supports mouse */
void PMAPI PM_getPMvect(int intno, PMFARPTR *isr)
{
PMREGS regs;
regs.x.ax = 0x204;
regs.h.bl = intno;
PM_int386(0x31,®s,®s);
isr->sel = regs.x.cx;
isr->off = regs.e.edx;
}
void PMAPI PM_setPMvect(int intno, PM_intHandler isr)
{
PMSREGS sregs;
PMREGS regs;
PM_saveDS();
regs.x.ax = 0x205; /* Set protected mode vector */
regs.h.bl = intno;
PM_segread(&sregs);
regs.x.cx = sregs.cs;
regs.e.edx = (uint)isr;
PM_int386(0x31,®s,®s);
}
void PMAPI PM_restorePMvect(int intno, PMFARPTR isr)
{
PMREGS regs;
regs.x.ax = 0x205;
regs.h.bl = intno;
regs.x.cx = isr.sel;
regs.e.edx = isr.off;
PM_int386(0x31,®s,®s);
}
int PM_setMouseHandler(int mask, PM_mouseHandler mh)
{
PMREGS regs;
PMSREGS sregs;
_PM_mouseHandler = mh;
PM_segread(&sregs);
sregs.es = sregs.cs;
regs.e.edx = (uint)_PM_mouseISR;
regs.x.cx = _PM_mouseMask = mask;
regs.x.ax = 0xC;
PM_int386x(0x33, ®s, ®s, &sregs);
return 1;
}
void PM_restoreMouseHandler(void)
{
PMREGS regs;
if (_PM_mouseHandler) {
regs.x.ax = 33;
PM_int386(0x33, ®s, ®s);
_PM_mouseHandler = NULL;
}
}
#endif
/*-------------------------------------------------------------------------*/
/* Generic 32 bit DPMI routines */
/*-------------------------------------------------------------------------*/
#if defined(GENERIC_DPMI32)
static long prevRealBreak; /* Previous real mode break handler */
static long prevRealCtrlC; /* Previous real mode CtrlC handler */
static long prevRealCritical; /* Prev real mode critical handler */
#ifndef MOUSE_SUPPORTED
/* The following real mode routine is used to call a 32 bit protected
* mode FAR function from real mode. We use this for passing up control
* from the real mode mouse callback to our protected mode code.
*/
static long mouseRMCB; /* Mouse real mode callback address */
static uint mouseSel,mouseOff;
static char mouseRegs[0x32]; /* Real mode regs for mouse callback */
static char mouseHandler[] = {
0x00,0x00,0x00,0x00, /* _realRMCB */
0x2E,0xFF,0x1E,0x00,0x00, /* call [cs:_realRMCB] */
0xCB, /* retf */
};
int PMAPI PM_setMouseHandler(int mask, PM_mouseHandler mh)
{
RMREGS regs;
RMSREGS sregs;
uint rseg,roff;
lockPMHandlers(); /* Ensure our handlers are locked */
/* Copy the real mode handler to real mode memory */
if (!PM_allocRealSeg(sizeof(mouseHandler),&mouseSel,&mouseOff,&rseg,&roff))
return 0;
PM_memcpyfn(mouseSel,mouseOff,mouseHandler,sizeof(mouseHandler));
_DPMI_allocateCallback(_PM_mousePMCB, mouseRegs, &mouseRMCB);
PM_setLong(mouseSel,mouseOff,mouseRMCB);
/* Install the real mode mouse handler */
_PM_mouseHandler = mh;
sregs.es = rseg;
regs.x.dx = roff+4;
regs.x.cx = _PM_mouseMask = mask;
regs.x.ax = 0xC;
PM_int86x(0x33, ®s, ®s, &sregs);
return 1;
}
void PMAPI PM_restoreMouseHandler(void)
{
RMREGS regs;
if (_PM_mouseHandler) {
regs.x.ax = 33;
PM_int86(0x33, ®s, ®s);
PM_freeRealSeg(mouseSel,mouseOff);
_DPMI_freeCallback(mouseRMCB);
_PM_mouseHandler = NULL;
}
}
#endif
static void getISR(int intno, PMFARPTR *pmisr, long *realisr)
{
PM_getPMvect(intno,pmisr);
_PM_getRMvect(intno,realisr);
}
static void restoreISR(int intno, PMFARPTR pmisr, long realisr)
{
_PM_setRMvect(intno,realisr);
PM_restorePMvect(intno,pmisr);
}
static void setISR(int intno, void (* PMAPI pmisr)())
{
lockPMHandlers(); /* Ensure our handlers are locked */
PM_setPMvect(intno,pmisr);
}
void PMAPI PM_setTimerHandler(PM_intHandler th)
{
getISR(0x8, &_PM_prevTimer, &_PM_prevRealTimer);
_PM_timerHandler = th;
setISR(0x8, _PM_timerISR);
}
void PMAPI PM_restoreTimerHandler(void)
{
if (_PM_timerHandler) {
restoreISR(0x8, _PM_prevTimer, _PM_prevRealTimer);
_PM_timerHandler = NULL;
}
}
void PMAPI PM_setKeyHandler(PM_intHandler kh)
{
getISR(0x9, &_PM_prevKey, &_PM_prevRealKey);
_PM_keyHandler = kh;
setISR(0x9, _PM_keyISR);
}
void PMAPI PM_restoreKeyHandler(void)
{
if (_PM_keyHandler) {
restoreISR(0x9, _PM_prevKey, _PM_prevRealKey);
_PM_keyHandler = NULL;
}
}
void PMAPI PM_setKey15Handler(PM_key15Handler kh)
{
getISR(0x15, &_PM_prevKey15, &_PM_prevRealKey15);
_PM_key15Handler = kh;
setISR(0x15, _PM_key15ISR);
}
void PMAPI PM_restoreKey15Handler(void)
{
if (_PM_key15Handler) {
restoreISR(0x15, _PM_prevKey15, _PM_prevRealKey15);
_PM_key15Handler = NULL;
}
}
/* Real mode Ctrl-C and Ctrl-Break handler. This handler simply sets a
* flag in the real mode code segment and exit. We save the location
* of this flag in real mode memory so that both the real mode and
* protected mode code will be modifying the same flags.
*/
#ifndef DOS4GW
static uchar ctrlHandler[] = {
0x00,0x00,0x00,0x00, /* ctrlBFlag */
0x66,0x2E,0xC7,0x06,0x00,0x00,
0x01,0x00,0x00,0x00, /* mov [cs:ctrlBFlag],1 */
0xCF, /* iretf */
};
#endif
void PMAPI PM_installAltBreakHandler(PM_breakHandler bh)
{
#ifndef DOS4GW
uint rseg,roff;
#else
static int ctrlCFlag,ctrlBFlag;
PMSREGS sregs;
PM_segread(&sregs);
_PM_ctrlCSel = sregs.ds;
_PM_ctrlCOff = (uint)&ctrlCFlag;
_PM_ctrlBSel = sregs.ds;
_PM_ctrlBOff = (uint)&ctrlBFlag;
#endif
getISR(0x1B, &_PM_prevBreak, &prevRealBreak);
getISR(0x23, &_PM_prevCtrlC, &prevRealCtrlC);
_PM_breakHandler = bh;
setISR(0x1B, _PM_breakISR);
setISR(0x23, _PM_ctrlCISR);
#ifndef DOS4GW
/* Hook the real mode vectors for these handlers, as these are not
* normally reflected by the DPMI server up to protected mode
*/
PM_allocRealSeg(sizeof(ctrlHandler)*2, &_PM_ctrlBSel, &_PM_ctrlBOff,
&rseg, &roff);
PM_memcpyfn(_PM_ctrlBSel,_PM_ctrlBOff,ctrlHandler,
sizeof(ctrlHandler));
PM_memcpyfn(_PM_ctrlBSel,_PM_ctrlBOff+sizeof(ctrlHandler),
ctrlHandler,sizeof(ctrlHandler));
_PM_ctrlCSel = _PM_ctrlBSel;
_PM_ctrlCOff = _PM_ctrlBOff + sizeof(ctrlHandler);
_PM_setRMvect(0x1B,((long)rseg << 16) | (roff+4));
_PM_setRMvect(0x23,((long)rseg << 16) | (roff+sizeof(ctrlHandler)+4));
#endif
}
void PMAPI PM_installBreakHandler(void)
{
PM_installAltBreakHandler(NULL);
}
void PMAPI PM_restoreBreakHandler(void)
{
if (_PM_prevBreak.sel) {
restoreISR(0x1B, _PM_prevBreak, prevRealBreak);
restoreISR(0x23, _PM_prevCtrlC, prevRealCtrlC);
PM_freeRealSeg(_PM_ctrlBSel, _PM_ctrlBOff);
_PM_prevBreak.sel = 0;
_PM_breakHandler = NULL;
}
}
/* Real mode Critical Error handler. This handler simply saves the AX and
* DI values in the real mode code segment and exits. We save the location
* of this flag in real mode memory so that both the real mode and
* protected mode code will be modifying the same flags.
*/
#ifndef DOS4GW
static uchar criticalHandler[] = {
0x00,0x00, /* axCode */
0x00,0x00, /* diCode */
0x2E,0xA3,0x00,0x00, /* mov [cs:axCode],ax */
0x2E,0x89,0x3E,0x02,0x00, /* mov [cs:diCode],di */
0xB8,0x03,0x00, /* mov ax,3 */
0xCF, /* iretf */
};
#endif
void PMAPI PM_installAltCriticalHandler(PM_criticalHandler ch)
{
#ifndef DOS4GW
uint rseg,roff;
#else
static short critBuf[2];
PMSREGS sregs;
PM_segread(&sregs);
_PM_critSel = sregs.ds;
_PM_critOff = (uint)critBuf;
#endif
getISR(0x24, &_PM_prevCritical, &prevRealCritical);
_PM_critHandler = ch;
setISR(0x24, _PM_criticalISR);
#ifndef DOS4GW
/* Hook the real mode vector, as this is not normally reflected by the
* DPMI server up to protected mode.
*/
PM_allocRealSeg(sizeof(criticalHandler)*2, &_PM_critSel, &_PM_critOff,
&rseg, &roff);
PM_memcpyfn(_PM_critSel,_PM_critOff,criticalHandler,
sizeof(criticalHandler));
_PM_setRMvect(0x24,((long)rseg << 16) | (roff+4));
#endif
}
void PMAPI PM_installCriticalHandler(void)
{
PM_installAltCriticalHandler(NULL);
}
void PMAPI PM_restoreCriticalHandler(void)
{
if (_PM_prevCritical.sel) {
restoreISR(0x24, _PM_prevCritical, prevRealCritical);
PM_freeRealSeg(_PM_critSel, _PM_critOff);
_PM_prevCritical.sel = 0;
_PM_critHandler = NULL;
}
}
int PMAPI PM_lockDataPages(void *p,uint len)
{
PMSREGS sregs;
PM_segread(&sregs);
return DPMI_lockLinearPages((uint)p + DPMI_getSelectorBase(sregs.ds),len);
}
int PMAPI PM_unlockDataPages(void *p,uint len)
{
PMSREGS sregs;
PM_segread(&sregs);
return DPMI_unlockLinearPages((uint)p + DPMI_getSelectorBase(sregs.ds),len);
}
int PMAPI PM_lockCodePages(void (*p)(),uint len)
{
PMSREGS sregs;
PM_segread(&sregs);
return DPMI_lockLinearPages((uint)p + DPMI_getSelectorBase(sregs.cs),len);
}
int PMAPI PM_unlockCodePages(void (*p)(),uint len)
{
PMSREGS sregs;
PM_segread(&sregs);
return DPMI_unlockLinearPages((uint)p + DPMI_getSelectorBase(sregs.cs),len);
}
#endif
#endif /* !__WINDOWS__ */