1 /****************************************************************************
3 * SciTech OS Portability Manager Library
5 * ========================================================================
7 * The contents of this file are subject to the SciTech MGL Public
8 * License Version 1.0 (the "License"); you may not use this file
9 * except in compliance with the License. You may obtain a copy of
10 * the License at http://www.scitechsoft.com/mgl-license.txt
12 * Software distributed under the License is distributed on an
13 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * rights and limitations under the License.
17 * The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
19 * The Initial Developer of the Original Code is SciTech Software, Inc.
20 * All Rights Reserved.
22 * ========================================================================
25 * Environment: 16/32 bit DOS
27 * Description: Implementation for the OS Portability Manager Library, which
28 * contains functions to implement OS specific services in a
29 * generic, cross platform API. Porting the OS Portability
30 * Manager library is the first step to porting any SciTech
31 * products to a new platform.
33 ****************************************************************************/
41 /*--------------------------- Global variables ----------------------------*/
44 static int globalDataStart
;
47 PM_criticalHandler _VARAPI _PM_critHandler
= NULL
;
48 PM_breakHandler _VARAPI _PM_breakHandler
= NULL
;
49 PM_intHandler _VARAPI _PM_timerHandler
= NULL
;
50 PM_intHandler _VARAPI _PM_rtcHandler
= NULL
;
51 PM_intHandler _VARAPI _PM_keyHandler
= NULL
;
52 PM_key15Handler _VARAPI _PM_key15Handler
= NULL
;
53 PM_mouseHandler _VARAPI _PM_mouseHandler
= NULL
;
54 PM_intHandler _VARAPI _PM_int10Handler
= NULL
;
55 int _VARAPI _PM_mouseMask
;
57 uchar
* _VARAPI _PM_ctrlCPtr
; /* Location of Ctrl-C flag */
58 uchar
* _VARAPI _PM_ctrlBPtr
; /* Location of Ctrl-Break flag */
59 uchar
* _VARAPI _PM_critPtr
; /* Location of Critical error Bf*/
60 PMFARPTR _VARAPI _PM_prevTimer
= PMNULL
; /* Previous timer handler */
61 PMFARPTR _VARAPI _PM_prevRTC
= PMNULL
; /* Previous RTC handler */
62 PMFARPTR _VARAPI _PM_prevKey
= PMNULL
; /* Previous key handler */
63 PMFARPTR _VARAPI _PM_prevKey15
= PMNULL
; /* Previous key15 handler */
64 PMFARPTR _VARAPI _PM_prevBreak
= PMNULL
; /* Previous break handler */
65 PMFARPTR _VARAPI _PM_prevCtrlC
= PMNULL
; /* Previous CtrlC handler */
66 PMFARPTR _VARAPI _PM_prevCritical
= PMNULL
; /* Previous critical handler */
67 long _VARAPI _PM_prevRealTimer
; /* Previous real mode timer */
68 long _VARAPI _PM_prevRealRTC
; /* Previous real mode RTC */
69 long _VARAPI _PM_prevRealKey
; /* Previous real mode key */
70 long _VARAPI _PM_prevRealKey15
; /* Previous real mode key15 */
71 long _VARAPI _PM_prevRealInt10
; /* Previous real mode int 10h */
72 static uchar _PM_oldCMOSRegA
; /* CMOS register A contents */
73 static uchar _PM_oldCMOSRegB
; /* CMOS register B contents */
74 static uchar _PM_oldRTCPIC2
; /* Mask value for RTC IRQ8 */
76 /* Structure to maintain information about hardware interrupt handlers,
77 * include a copy of the hardware IRQ assembler thunk (one for each
78 * hooked interrupt handler).
89 /* IRQ assembler thunk follows ... */
92 /*----------------------------- Implementation ----------------------------*/
94 /* Globals for locking interrupt handlers in _pmdos.asm */
97 extern int _VARAPI _PM_pmdosDataStart
;
98 extern int _VARAPI _PM_pmdosDataEnd
;
99 extern int _VARAPI _PM_DMADataStart
;
100 extern int _VARAPI _PM_DMADataEnd
;
101 void _ASMAPI
_PM_pmdosCodeStart(void);
102 void _ASMAPI
_PM_pmdosCodeEnd(void);
103 void _ASMAPI
_PM_DMACodeStart(void);
104 void _ASMAPI
_PM_DMACodeEnd(void);
107 /* Protected mode interrupt handlers, also called by PM callbacks below */
109 void _ASMAPI
_PM_timerISR(void);
110 void _ASMAPI
_PM_rtcISR(void);
111 void _ASMAPI
_PM_irqISRTemplate(void);
112 void _ASMAPI
_PM_irqISRTemplateEnd(void);
113 void _ASMAPI
_PM_keyISR(void);
114 void _ASMAPI
_PM_key15ISR(void);
115 void _ASMAPI
_PM_breakISR(void);
116 void _ASMAPI
_PM_ctrlCISR(void);
117 void _ASMAPI
_PM_criticalISR(void);
118 void _ASMAPI
_PM_mouseISR(void);
119 void _ASMAPI
_PM_int10PMCB(void);
121 /* Protected mode DPMI callback handlers */
123 void _ASMAPI
_PM_mousePMCB(void);
125 /* Routine to install a mouse handler function */
127 void _ASMAPI
_PM_setMouseHandler(int mask
);
129 /* Routine to allocate DPMI real mode callback routines */
131 ibool _ASMAPI
_DPMI_allocateCallback(void (_ASMAPI
*pmcode
)(),void *rmregs
,long *RMCB
);
132 void _ASMAPI
_DPMI_freeCallback(long RMCB
);
134 /* DPMI helper functions in PMLITE.C */
136 ulong PMAPI
DPMI_mapPhysicalToLinear(ulong physAddr
,ulong limit
);
137 int PMAPI
DPMI_setSelectorBase(ushort sel
,ulong linAddr
);
138 ulong PMAPI
DPMI_getSelectorBase(ushort sel
);
139 int PMAPI
DPMI_setSelectorLimit(ushort sel
,ulong limit
);
140 uint PMAPI
DPMI_createSelector(ulong base
,ulong limit
);
141 void PMAPI
DPMI_freeSelector(uint sel
);
142 int PMAPI
DPMI_lockLinearPages(ulong linear
,ulong len
);
143 int PMAPI
DPMI_unlockLinearPages(ulong linear
,ulong len
);
145 /* Functions to read and write CMOS registers */
147 uchar PMAPI
_PM_readCMOS(int index
);
148 void PMAPI
_PM_writeCMOS(int index
,uchar value
);
150 /*-------------------------------------------------------------------------*/
151 /* Generic routines common to all environments */
152 /*-------------------------------------------------------------------------*/
154 void PMAPI
PM_resetMouseDriver(int hardReset
)
157 PM_mouseHandler oldHandler
= _PM_mouseHandler
;
159 PM_restoreMouseHandler();
160 regs
.x
.ax
= hardReset
? 0 : 33;
161 PM_int86(0x33, ®s
, ®s
);
163 PM_setMouseHandler(_PM_mouseMask
, oldHandler
);
166 void PMAPI
PM_setRealTimeClockFrequency(int frequency
)
168 static short convert
[] = {
186 /* First clear any pending RTC timeout if not cleared */
188 if (frequency
== 0) {
189 /* Disable RTC timout */
190 _PM_writeCMOS(0x0A,_PM_oldCMOSRegA
);
191 _PM_writeCMOS(0x0B,_PM_oldCMOSRegB
& 0x0F);
194 /* Convert frequency value to RTC clock indexes */
195 for (i
= 0; convert
[i
] != -1; i
++) {
196 if (convert
[i
] == frequency
)
200 /* Set RTC timout value and enable timeout */
201 _PM_writeCMOS(0x0A,0x20 | (i
+3));
202 _PM_writeCMOS(0x0B,(_PM_oldCMOSRegB
& 0x0F) | 0x40);
208 static void PMAPI
lockPMHandlers(void)
210 static int locked
= 0;
212 PM_lockHandle lh
; /* Unused in DOS */
214 /* Lock all of the code and data used by our protected mode interrupt
215 * handling routines, so that it will continue to work correctly
220 stat
= !PM_lockDataPages(&globalDataStart
-2048,4096,&lh
);
221 stat
|= !PM_lockDataPages(&_PM_pmdosDataStart
,(int)&_PM_pmdosDataEnd
- (int)&_PM_pmdosDataStart
,&lh
);
222 stat
|= !PM_lockCodePages((__codePtr
)_PM_pmdosCodeStart
,(int)_PM_pmdosCodeEnd
-(int)_PM_pmdosCodeStart
,&lh
);
223 stat
|= !PM_lockDataPages(&_PM_DMADataStart
,(int)&_PM_DMADataEnd
- (int)&_PM_DMADataStart
,&lh
);
224 stat
|= !PM_lockCodePages((__codePtr
)_PM_DMACodeStart
,(int)_PM_DMACodeEnd
-(int)_PM_DMACodeStart
,&lh
);
226 printf("Page locking services failed - interrupt handling not safe!\n");
235 /*-------------------------------------------------------------------------*/
236 /* DOS Real Mode support. */
237 /*-------------------------------------------------------------------------*/
242 #define MK_FP(s,o) ( (void far *)( ((ulong)(s) << 16) + \
246 int PMAPI
PM_setMouseHandler(int mask
, PM_mouseHandler mh
)
249 _PM_mouseHandler
= mh
;
250 _PM_setMouseHandler(_PM_mouseMask
= mask
);
254 void PMAPI
PM_restoreMouseHandler(void)
258 if (_PM_mouseHandler
) {
260 int86(0x33, ®s
, ®s
);
261 _PM_mouseHandler
= NULL
;
265 void PMAPI
PM_setTimerHandler(PM_intHandler th
)
267 _PM_getRMvect(0x8, (long*)&_PM_prevTimer
);
268 _PM_timerHandler
= th
;
269 _PM_setRMvect(0x8, (long)_PM_timerISR
);
272 void PMAPI
PM_restoreTimerHandler(void)
274 if (_PM_timerHandler
) {
275 _PM_setRMvect(0x8, (long)_PM_prevTimer
);
276 _PM_timerHandler
= NULL
;
280 ibool PMAPI
PM_setRealTimeClockHandler(PM_intHandler th
,int frequency
)
282 /* Save the old CMOS real time clock values */
283 _PM_oldCMOSRegA
= _PM_readCMOS(0x0A);
284 _PM_oldCMOSRegB
= _PM_readCMOS(0x0B);
286 /* Set the real time clock interrupt handler */
287 _PM_getRMvect(0x70, (long*)&_PM_prevRTC
);
289 _PM_setRMvect(0x70, (long)_PM_rtcISR
);
291 /* Program the real time clock default frequency */
292 PM_setRealTimeClockFrequency(frequency
);
294 /* Unmask IRQ8 in the PIC2 */
295 _PM_oldRTCPIC2
= PM_inpb(0xA1);
296 PM_outpb(0xA1,_PM_oldRTCPIC2
& 0xFE);
300 void PMAPI
PM_restoreRealTimeClockHandler(void)
302 if (_PM_rtcHandler
) {
303 /* Restore CMOS registers and mask RTC clock */
304 _PM_writeCMOS(0x0A,_PM_oldCMOSRegA
);
305 _PM_writeCMOS(0x0B,_PM_oldCMOSRegB
);
306 PM_outpb(0xA1,(PM_inpb(0xA1) & 0xFE) | (_PM_oldRTCPIC2
& ~0xFE));
308 /* Restore the interrupt vector */
309 _PM_setRMvect(0x70, (long)_PM_prevRTC
);
310 _PM_rtcHandler
= NULL
;
314 void PMAPI
PM_setKeyHandler(PM_intHandler kh
)
316 _PM_getRMvect(0x9, (long*)&_PM_prevKey
);
318 _PM_setRMvect(0x9, (long)_PM_keyISR
);
321 void PMAPI
PM_restoreKeyHandler(void)
323 if (_PM_keyHandler
) {
324 _PM_setRMvect(0x9, (long)_PM_prevKey
);
325 _PM_keyHandler
= NULL
;
329 void PMAPI
PM_setKey15Handler(PM_key15Handler kh
)
331 _PM_getRMvect(0x15, (long*)&_PM_prevKey15
);
332 _PM_key15Handler
= kh
;
333 _PM_setRMvect(0x15, (long)_PM_key15ISR
);
336 void PMAPI
PM_restoreKey15Handler(void)
338 if (_PM_key15Handler
) {
339 _PM_setRMvect(0x15, (long)_PM_prevKey15
);
340 _PM_key15Handler
= NULL
;
344 void PMAPI
PM_installAltBreakHandler(PM_breakHandler bh
)
346 static int ctrlCFlag
,ctrlBFlag
;
348 _PM_ctrlCPtr
= (uchar
*)&ctrlCFlag
;
349 _PM_ctrlBPtr
= (uchar
*)&ctrlBFlag
;
350 _PM_getRMvect(0x1B, (long*)&_PM_prevBreak
);
351 _PM_getRMvect(0x23, (long*)&_PM_prevCtrlC
);
352 _PM_breakHandler
= bh
;
353 _PM_setRMvect(0x1B, (long)_PM_breakISR
);
354 _PM_setRMvect(0x23, (long)_PM_ctrlCISR
);
357 void PMAPI
PM_installBreakHandler(void)
359 PM_installAltBreakHandler(NULL
);
362 void PMAPI
PM_restoreBreakHandler(void)
365 _PM_setRMvect(0x1B, (long)_PM_prevBreak
);
366 _PM_setRMvect(0x23, (long)_PM_prevCtrlC
);
367 _PM_prevBreak
= NULL
;
368 _PM_breakHandler
= NULL
;
372 void PMAPI
PM_installAltCriticalHandler(PM_criticalHandler ch
)
374 static short critBuf
[2];
376 _PM_critPtr
= (uchar
*)critBuf
;
377 _PM_getRMvect(0x24, (long*)&_PM_prevCritical
);
378 _PM_critHandler
= ch
;
379 _PM_setRMvect(0x24, (long)_PM_criticalISR
);
382 void PMAPI
PM_installCriticalHandler(void)
384 PM_installAltCriticalHandler(NULL
);
387 void PMAPI
PM_restoreCriticalHandler(void)
389 if (_PM_prevCritical
) {
390 _PM_setRMvect(0x24, (long)_PM_prevCritical
);
391 _PM_prevCritical
= NULL
;
392 _PM_critHandler
= NULL
;
396 int PMAPI
PM_lockDataPages(void *p
,uint len
,PM_lockHandle
*lh
)
398 p
= p
; len
= len
; /* Do nothing for real mode */
402 int PMAPI
PM_unlockDataPages(void *p
,uint len
,PM_lockHandle
*lh
)
404 p
= p
; len
= len
; /* Do nothing for real mode */
408 int PMAPI
PM_lockCodePages(void (*p
)(),uint len
,PM_lockHandle
*lh
)
410 p
= p
; len
= len
; /* Do nothing for real mode */
414 int PMAPI
PM_unlockCodePages(void (*p
)(),uint len
,PM_lockHandle
*lh
)
416 p
= p
; len
= len
; /* Do nothing for real mode */
420 void PMAPI
PM_getPMvect(int intno
, PMFARPTR
*isr
)
423 _PM_getRMvect(intno
,&t
);
427 void PMAPI
PM_setPMvect(int intno
, PM_intHandler isr
)
430 _PM_setRMvect(intno
,(long)isr
);
433 void PMAPI
PM_restorePMvect(int intno
, PMFARPTR isr
)
435 _PM_setRMvect(intno
,(long)isr
);
440 /*-------------------------------------------------------------------------*/
441 /* Phar Lap TNT DOS Extender support. */
442 /*-------------------------------------------------------------------------*/
450 static long prevRealBreak
; /* Previous real mode break handler */
451 static long prevRealCtrlC
; /* Previous real mode CtrlC handler */
452 static long prevRealCritical
; /* Prev real mode critical handler */
453 static uchar
*mousePtr
;
455 /* The following real mode routine is used to call a 32 bit protected
456 * mode FAR function from real mode. We use this for passing up control
457 * from the real mode mouse callback to our protected mode code.
460 static UCHAR realHandler
[] = { /* Real mode code generic handler */
461 0x00,0x00,0x00,0x00, /* __PM_callProtp */
462 0x00,0x00, /* __PM_protCS */
463 0x00,0x00,0x00,0x00, /* __PM_protHandler */
464 0x66,0x60, /* pushad */
466 0x6A,0x00, /* push 0 */
467 0x6A,0x00, /* push 0 */
468 0x2E,0xFF,0x36,0x04,0x00, /* push [cs:__PM_protCS] */
469 0x66,0x2E,0xFF,0x36,0x06,0x00, /* push [cs:__PM_protHandler] */
470 0x2E,0xFF,0x1E,0x00,0x00, /* call [cs:__PM_callProtp] */
471 0x83,0xC4,0x0A, /* add sp,10 */
473 0x66,0x61, /* popad */
477 /* The following functions installs the above realmode callback mechanism
478 * in real mode memory for calling the protected mode routine.
481 uchar
* installCallback(void (PMAPI
*pmCB
)(),uint
*rseg
, uint
*roff
)
484 REALPTR realBufAdr
,callProtp
;
489 /* Get address of real mode routine to call up to protected mode */
490 _dx_rmlink_get(&callProtp
, &realBufAdr
, &bufSize
, &protBufAdr
);
491 _dx_config_inf(&config
, (UCHAR
*)&config
);
493 /* Fill in the values in the real mode code segment so that it will
494 * call the correct routine.
496 *((REALPTR
*)&realHandler
[0]) = callProtp
;
497 *((USHORT
*)&realHandler
[4]) = config
.c_cs_sel
;
498 *((ULONG
*)&realHandler
[6]) = (ULONG
)pmCB
;
500 /* Copy the real mode handler to real mode memory */
501 if ((p
= PM_allocRealSeg(sizeof(realHandler
),rseg
,roff
)) == NULL
)
503 memcpy(p
,realHandler
,sizeof(realHandler
));
505 /* Skip past global variabls in real mode code segment */
510 int PMAPI
PM_setMouseHandler(int mask
, PM_mouseHandler mh
)
516 lockPMHandlers(); /* Ensure our handlers are locked */
518 if ((mousePtr
= installCallback(_PM_mouseISR
, &rseg
, &roff
)) == NULL
)
520 _PM_mouseHandler
= mh
;
522 /* Install the real mode mouse handler */
525 regs
.x
.cx
= _PM_mouseMask
= mask
;
527 PM_int86x(0x33, ®s
, ®s
, &sregs
);
531 void PMAPI
PM_restoreMouseHandler(void)
535 if (_PM_mouseHandler
) {
537 PM_int86(0x33, ®s
, ®s
);
538 PM_freeRealSeg(mousePtr
);
539 _PM_mouseHandler
= NULL
;
543 void PMAPI
PM_getPMvect(int intno
, PMFARPTR
*isr
)
547 _dx_pmiv_get(intno
, &ph
);
548 isr
->sel
= FP_SEL(ph
);
549 isr
->off
= FP_OFF(ph
);
552 void PMAPI
PM_setPMvect(int intno
, PM_intHandler isr
)
558 _dx_config_inf(&config
, (UCHAR
*)&config
);
559 FP_SET(ph
,(uint
)isr
,config
.c_cs_sel
);
560 _dx_pmiv_set(intno
,ph
);
563 void PMAPI
PM_restorePMvect(int intno
, PMFARPTR isr
)
567 FP_SET(ph
,isr
.off
,isr
.sel
);
568 _dx_pmiv_set(intno
,ph
);
571 static void getISR(int intno
, PMFARPTR
*pmisr
, long *realisr
)
573 PM_getPMvect(intno
,pmisr
);
574 _PM_getRMvect(intno
, realisr
);
577 static void restoreISR(int intno
, PMFARPTR pmisr
, long realisr
)
579 _PM_setRMvect(intno
,realisr
);
580 PM_restorePMvect(intno
,pmisr
);
583 static void setISR(int intno
, void (PMAPI
*isr
)())
588 lockPMHandlers(); /* Ensure our handlers are locked */
590 _dx_config_inf(&config
, (UCHAR
*)&config
);
591 FP_SET(ph
,(uint
)isr
,config
.c_cs_sel
);
592 _dx_apmiv_set(intno
,ph
);
595 void PMAPI
PM_setTimerHandler(PM_intHandler th
)
597 getISR(0x8, &_PM_prevTimer
, &_PM_prevRealTimer
);
598 _PM_timerHandler
= th
;
599 setISR(0x8, _PM_timerISR
);
602 void PMAPI
PM_restoreTimerHandler(void)
604 if (_PM_timerHandler
) {
605 restoreISR(0x8, _PM_prevTimer
, _PM_prevRealTimer
);
606 _PM_timerHandler
= NULL
;
610 ibool PMAPI
PM_setRealTimeClockHandler(PM_intHandler th
,int frequency
)
612 /* Save the old CMOS real time clock values */
613 _PM_oldCMOSRegA
= _PM_readCMOS(0x0A);
614 _PM_oldCMOSRegB
= _PM_readCMOS(0x0B);
616 /* Set the real time clock interrupt handler */
617 getISR(0x70, &_PM_prevRTC
, &_PM_prevRealRTC
);
619 setISR(0x70, _PM_rtcISR
);
621 /* Program the real time clock default frequency */
622 PM_setRealTimeClockFrequency(frequency
);
624 /* Unmask IRQ8 in the PIC2 */
625 _PM_oldRTCPIC2
= PM_inpb(0xA1);
626 PM_outpb(0xA1,_PM_oldRTCPIC2
& 0xFE);
630 void PMAPI
PM_restoreRealTimeClockHandler(void)
632 if (_PM_rtcHandler
) {
633 /* Restore CMOS registers and mask RTC clock */
634 _PM_writeCMOS(0x0A,_PM_oldCMOSRegA
);
635 _PM_writeCMOS(0x0B,_PM_oldCMOSRegB
);
636 PM_outpb(0xA1,(PM_inpb(0xA1) & 0xFE) | (_PM_oldRTCPIC2
& ~0xFE));
638 /* Restore the interrupt vector */
639 restoreISR(0x70, _PM_prevRTC
, _PM_prevRealRTC
);
640 _PM_rtcHandler
= NULL
;
644 void PMAPI
PM_setKeyHandler(PM_intHandler kh
)
646 getISR(0x9, &_PM_prevKey
, &_PM_prevRealKey
);
648 setISR(0x9, _PM_keyISR
);
651 void PMAPI
PM_restoreKeyHandler(void)
653 if (_PM_keyHandler
) {
654 restoreISR(0x9, _PM_prevKey
, _PM_prevRealKey
);
655 _PM_keyHandler
= NULL
;
659 void PMAPI
PM_setKey15Handler(PM_key15Handler kh
)
661 getISR(0x15, &_PM_prevKey15
, &_PM_prevRealKey15
);
662 _PM_key15Handler
= kh
;
663 setISR(0x15, _PM_key15ISR
);
666 void PMAPI
PM_restoreKey15Handler(void)
668 if (_PM_key15Handler
) {
669 restoreISR(0x15, _PM_prevKey15
, _PM_prevRealKey15
);
670 _PM_key15Handler
= NULL
;
674 void PMAPI
PM_installAltBreakHandler(PM_breakHandler bh
)
676 static int ctrlCFlag
,ctrlBFlag
;
678 _PM_ctrlCPtr
= (uchar
*)&ctrlCFlag
;
679 _PM_ctrlBPtr
= (uchar
*)&ctrlBFlag
;
680 getISR(0x1B, &_PM_prevBreak
, &prevRealBreak
);
681 getISR(0x23, &_PM_prevCtrlC
, &prevRealCtrlC
);
682 _PM_breakHandler
= bh
;
683 setISR(0x1B, _PM_breakISR
);
684 setISR(0x23, _PM_ctrlCISR
);
687 void PMAPI
PM_installBreakHandler(void)
689 PM_installAltBreakHandler(NULL
);
692 void PMAPI
PM_restoreBreakHandler(void)
694 if (_PM_prevBreak
.sel
) {
695 restoreISR(0x1B, _PM_prevBreak
, prevRealBreak
);
696 restoreISR(0x23, _PM_prevCtrlC
, prevRealCtrlC
);
697 _PM_prevBreak
.sel
= 0;
698 _PM_breakHandler
= NULL
;
702 void PMAPI
PM_installAltCriticalHandler(PM_criticalHandler ch
)
704 static short critBuf
[2];
706 _PM_critPtr
= (uchar
*)critBuf
;
707 getISR(0x24, &_PM_prevCritical
, &prevRealCritical
);
708 _PM_critHandler
= ch
;
709 setISR(0x24, _PM_criticalISR
);
712 void PMAPI
PM_installCriticalHandler(void)
714 PM_installAltCriticalHandler(NULL
);
717 void PMAPI
PM_restoreCriticalHandler(void)
719 if (_PM_prevCritical
.sel
) {
720 restoreISR(0x24, _PM_prevCritical
, prevRealCritical
);
721 _PM_prevCritical
.sel
= 0;
722 _PM_critHandler
= NULL
;
726 int PMAPI
PM_lockDataPages(void *p
,uint len
,PM_lockHandle
*lh
)
728 return (_dx_lock_pgsn(p
,len
) == 0);
731 int PMAPI
PM_unlockDataPages(void *p
,uint len
,PM_lockHandle
*lh
)
733 return (_dx_ulock_pgsn(p
,len
) == 0);
736 int PMAPI
PM_lockCodePages(void (*p
)(),uint len
,PM_lockHandle
*lh
)
741 _dx_config_inf(&config
, (UCHAR
*)&config
);
742 FP_SET(fp
,p
,config
.c_cs_sel
);
743 return (_dx_lock_pgs(fp
,len
) == 0);
746 int PMAPI
PM_unlockCodePages(void (*p
)(),uint len
,PM_lockHandle
*lh
)
751 _dx_config_inf(&config
, (UCHAR
*)&config
);
752 FP_SET(fp
,p
,config
.c_cs_sel
);
753 return (_dx_ulock_pgs(fp
,len
) == 0);
758 /*-------------------------------------------------------------------------*/
759 /* Symantec C++ DOSX and FlashTek X-32/X-32VM support */
760 /*-------------------------------------------------------------------------*/
762 #if defined(DOSX) || defined(X32VM)
768 static long prevRealBreak
; /* Previous real mode break handler */
769 static long prevRealCtrlC
; /* Previous real mode CtrlC handler */
770 static long prevRealCritical
; /* Prev real mode critical handler */
772 static uint mouseSel
= 0,mouseOff
;
774 /* The following real mode routine is used to call a 32 bit protected
775 * mode FAR function from real mode. We use this for passing up control
776 * from the real mode mouse callback to our protected mode code.
779 static char realHandler
[] = { /* Real mode code generic handler */
780 0x00,0x00,0x00,0x00, /* __PM_callProtp */
781 0x00,0x00, /* __PM_protCS */
782 0x00,0x00,0x00,0x00, /* __PM_protHandler */
784 0x6A,0x00, /* push 0 */
785 0x6A,0x00, /* push 0 */
786 0x2E,0xFF,0x36,0x04,0x00, /* push [cs:__PM_protCS] */
787 0x66,0x2E,0xFF,0x36,0x06,0x00, /* push [cs:__PM_protHandler] */
788 0x2E,0xFF,0x1E,0x00,0x00, /* call [cs:__PM_callProtp] */
789 0x83,0xC4,0x0A, /* add sp,10 */
794 /* The following functions installs the above realmode callback mechanism
795 * in real mode memory for calling the protected mode routine.
798 int installCallback(void (PMAPI
*pmCB
)(),uint
*psel
, uint
*poff
,
799 uint
*rseg
, uint
*roff
)
806 PM_int386x(0x21,®s
,®s
,&sregs
); /* Get RM callback address */
808 /* Fill in the values in the real mode code segment so that it will
809 * call the correct routine.
811 *((ulong
*)&realHandler
[0]) = regs
.e
.eax
;
812 *((ushort
*)&realHandler
[4]) = sregs
.cs
;
813 *((ulong
*)&realHandler
[6]) = (ulong
)pmCB
;
815 /* Copy the real mode handler to real mode memory (only allocate the
816 * buffer once since we cant dealloate it with X32).
819 if (!PM_allocRealSeg(sizeof(realHandler
),psel
,poff
,rseg
,roff
))
822 PM_memcpyfn(*psel
,*poff
,realHandler
,sizeof(realHandler
));
824 /* Skip past global variables in real mode code segment */
829 int PMAPI
PM_setMouseHandler(int mask
, PM_mouseHandler mh
)
835 lockPMHandlers(); /* Ensure our handlers are locked */
837 if (!installCallback(_PM_mouseISR
, &mouseSel
, &mouseOff
, &rseg
, &roff
))
839 _PM_mouseHandler
= mh
;
841 /* Install the real mode mouse handler */
844 regs
.x
.cx
= _PM_mouseMask
= mask
;
846 PM_int86x(0x33, ®s
, ®s
, &sregs
);
850 void PMAPI
PM_restoreMouseHandler(void)
854 if (_PM_mouseHandler
) {
856 PM_int86(0x33, ®s
, ®s
);
857 _PM_mouseHandler
= NULL
;
861 void PMAPI
PM_getPMvect(int intno
, PMFARPTR
*isr
)
867 regs
.x
.ax
= 0x2502; /* Get PM interrupt vector */
869 PM_int386x(0x21, ®s
, ®s
, &sregs
);
871 isr
->off
= regs
.e
.ebx
;
874 void PMAPI
PM_setPMvect(int intno
, PM_intHandler isr
)
881 pmisr
.sel
= sregs
.cs
;
882 pmisr
.off
= (uint
)isr
;
883 PM_restorePMvect(intno
, pmisr
);
886 void PMAPI
PM_restorePMvect(int intno
, PMFARPTR isr
)
892 regs
.x
.ax
= 0x2505; /* Set PM interrupt vector */
895 regs
.e
.edx
= isr
.off
;
896 PM_int386x(0x21, ®s
, ®s
, &sregs
);
899 static void getISR(int intno
, PMFARPTR
*pmisr
, long *realisr
)
901 PM_getPMvect(intno
,pmisr
);
902 _PM_getRMvect(intno
,realisr
);
905 static void restoreISR(int intno
, PMFARPTR pmisr
, long realisr
)
911 regs
.x
.ax
= 0x2507; /* Set real and PM vectors */
913 sregs
.ds
= pmisr
.sel
;
914 regs
.e
.edx
= pmisr
.off
;
915 regs
.e
.ebx
= realisr
;
916 PM_int386x(0x21, ®s
, ®s
, &sregs
);
919 static void setISR(int intno
, void *isr
)
924 lockPMHandlers(); /* Ensure our handlers are locked */
927 regs
.x
.ax
= 0x2506; /* Hook real and protected vectors */
930 regs
.e
.edx
= (uint
)isr
;
931 PM_int386x(0x21, ®s
, ®s
, &sregs
);
934 void PMAPI
PM_setTimerHandler(PM_intHandler th
)
936 getISR(0x8, &_PM_prevTimer
, &_PM_prevRealTimer
);
937 _PM_timerHandler
= th
;
938 setISR(0x8, _PM_timerISR
);
941 void PMAPI
PM_restoreTimerHandler(void)
943 if (_PM_timerHandler
) {
944 restoreISR(0x8, _PM_prevTimer
, _PM_prevRealTimer
);
945 _PM_timerHandler
= NULL
;
949 ibool PMAPI
PM_setRealTimeClockHandler(PM_intHandler th
,int frequency
)
951 /* Save the old CMOS real time clock values */
952 _PM_oldCMOSRegA
= _PM_readCMOS(0x0A);
953 _PM_oldCMOSRegB
= _PM_readCMOS(0x0B);
955 /* Set the real time clock interrupt handler */
956 getISR(0x70, &_PM_prevRTC
, &_PM_prevRealRTC
);
958 setISR(0x70, _PM_rtcISR
);
960 /* Program the real time clock default frequency */
961 PM_setRealTimeClockFrequency(frequency
);
963 /* Unmask IRQ8 in the PIC2 */
964 _PM_oldRTCPIC2
= PM_inpb(0xA1);
965 PM_outpb(0xA1,_PM_oldRTCPIC2
& 0xFE);
969 void PMAPI
PM_restoreRealTimeClockHandler(void)
971 if (_PM_rtcHandler
) {
972 /* Restore CMOS registers and mask RTC clock */
973 _PM_writeCMOS(0x0A,_PM_oldCMOSRegA
);
974 _PM_writeCMOS(0x0B,_PM_oldCMOSRegB
);
975 PM_outpb(0xA1,(PM_inpb(0xA1) & 0xFE) | (_PM_oldRTCPIC2
& ~0xFE));
977 /* Restore the interrupt vector */
978 restoreISR(0x70, _PM_prevRTC
, _PM_prevRealRTC
);
979 _PM_rtcHandler
= NULL
;
983 void PMAPI
PM_setKeyHandler(PM_intHandler kh
)
985 getISR(0x9, &_PM_prevKey
, &_PM_prevRealKey
);
987 setISR(0x9, _PM_keyISR
);
990 void PMAPI
PM_restoreKeyHandler(void)
992 if (_PM_keyHandler
) {
993 restoreISR(0x9, _PM_prevKey
, _PM_prevRealKey
);
994 _PM_keyHandler
= NULL
;
998 void PMAPI
PM_setKey15Handler(PM_key15Handler kh
)
1000 getISR(0x15, &_PM_prevKey15
, &_PM_prevRealKey15
);
1001 _PM_key15Handler
= kh
;
1002 setISR(0x15, _PM_key15ISR
);
1005 void PMAPI
PM_restoreKey15Handler(void)
1007 if (_PM_key15Handler
) {
1008 restoreISR(0x15, _PM_prevKey15
, _PM_prevRealKey15
);
1009 _PM_key15Handler
= NULL
;
1013 void PMAPI
PM_installAltBreakHandler(PM_breakHandler bh
)
1015 static int ctrlCFlag
,ctrlBFlag
;
1017 _PM_ctrlCPtr
= (uchar
*)&ctrlCFlag
;
1018 _PM_ctrlBPtr
= (uchar
*)&ctrlBFlag
;
1019 getISR(0x1B, &_PM_prevBreak
, &prevRealBreak
);
1020 getISR(0x23, &_PM_prevCtrlC
, &prevRealCtrlC
);
1021 _PM_breakHandler
= bh
;
1022 setISR(0x1B, _PM_breakISR
);
1023 setISR(0x23, _PM_ctrlCISR
);
1026 void PMAPI
PM_installBreakHandler(void)
1028 PM_installAltBreakHandler(NULL
);
1031 void PMAPI
PM_restoreBreakHandler(void)
1033 if (_PM_prevBreak
.sel
) {
1034 restoreISR(0x1B, _PM_prevBreak
, prevRealBreak
);
1035 restoreISR(0x23, _PM_prevCtrlC
, prevRealCtrlC
);
1036 _PM_prevBreak
.sel
= 0;
1037 _PM_breakHandler
= NULL
;
1041 void PMAPI
PM_installAltCriticalHandler(PM_criticalHandler ch
)
1043 static short critBuf
[2];
1045 _PM_critPtr
= (uchar
*)critBuf
;
1046 getISR(0x24, &_PM_prevCritical
, &prevRealCritical
);
1047 _PM_critHandler
= ch
;
1048 setISR(0x24, _PM_criticalISR
);
1051 void PMAPI
PM_installCriticalHandler(void)
1053 PM_installAltCriticalHandler(NULL
);
1056 void PMAPI
PM_restoreCriticalHandler(void)
1058 if (_PM_prevCritical
.sel
) {
1059 restoreISR(0x24, _PM_prevCritical
, prevRealCritical
);
1060 _PM_prevCritical
.sel
= 0;
1061 _PM_critHandler
= NULL
;
1065 int PMAPI
PM_lockDataPages(void *p
,uint len
,PM_lockHandle
*lh
)
1067 return (_x386_memlock(p
,len
) == 0);
1070 int PMAPI
PM_unlockDataPages(void *p
,uint len
,PM_lockHandle
*lh
)
1072 return (_x386_memunlock(p
,len
) == 0);
1075 int PMAPI
PM_lockCodePages(void (*p
)(),uint len
,PM_lockHandle
*lh
)
1077 return (_x386_memlock(p
,len
) == 0);
1080 int PMAPI
PM_unlockCodePages(void (*p
)(),uint len
,PM_lockHandle
*lh
)
1082 return (_x386_memunlock(p
,len
) == 0);
1087 /*-------------------------------------------------------------------------*/
1088 /* Borland's DPMI32 DOS Power Pack Extender support. */
1089 /*-------------------------------------------------------------------------*/
1092 #define GENERIC_DPMI32 /* Use generic 32 bit DPMI routines */
1094 void PMAPI
PM_getPMvect(int intno
, PMFARPTR
*isr
)
1100 PM_int386(0x31,®s
,®s
);
1101 isr
->sel
= regs
.x
.cx
;
1102 isr
->off
= regs
.e
.edx
;
1105 void PMAPI
PM_setPMvect(int intno
, PM_intHandler isr
)
1111 regs
.x
.ax
= 0x205; /* Set protected mode vector */
1114 regs
.x
.cx
= sregs
.cs
;
1115 regs
.e
.edx
= (uint
)isr
;
1116 PM_int386(0x31,®s
,®s
);
1119 void PMAPI
PM_restorePMvect(int intno
, PMFARPTR isr
)
1125 regs
.x
.cx
= isr
.sel
;
1126 regs
.e
.edx
= isr
.off
;
1127 PM_int386(0x31,®s
,®s
);
1131 /*-------------------------------------------------------------------------*/
1132 /* Watcom C/C++ with Rational DOS/4GW support. */
1133 /*-------------------------------------------------------------------------*/
1136 #define GENERIC_DPMI32 /* Use generic 32 bit DPMI routines */
1138 #define MOUSE_SUPPORTED /* DOS4GW directly supports mouse */
1140 /* We use the normal DOS services to save and restore interrupts handlers
1141 * for Watcom C++, because using the direct DPMI functions does not
1142 * appear to work properly. At least if we use the DPMI functions, we
1143 * dont get the auto-passup feature that we need to correctly trap
1144 * real and protected mode interrupts without installing Bi-model
1145 * interrupt handlers.
1148 void PMAPI
PM_getPMvect(int intno
, PMFARPTR
*isr
)
1156 PM_int386x(0x21,®s
,®s
,&sregs
);
1157 isr
->sel
= sregs
.es
;
1158 isr
->off
= regs
.e
.ebx
;
1161 void PMAPI
PM_setPMvect(int intno
, PM_intHandler isr
)
1170 sregs
.ds
= sregs
.cs
;
1171 regs
.e
.edx
= (uint
)isr
;
1172 PM_int386x(0x21,®s
,®s
,&sregs
);
1175 void PMAPI
PM_restorePMvect(int intno
, PMFARPTR isr
)
1184 regs
.e
.edx
= isr
.off
;
1185 PM_int386x(0x21,®s
,®s
,&sregs
);
1188 int PMAPI
PM_setMouseHandler(int mask
, PM_mouseHandler mh
)
1190 lockPMHandlers(); /* Ensure our handlers are locked */
1192 _PM_mouseHandler
= mh
;
1193 _PM_setMouseHandler(_PM_mouseMask
= mask
);
1197 void PMAPI
PM_restoreMouseHandler(void)
1201 if (_PM_mouseHandler
) {
1203 PM_int386(0x33, ®s
, ®s
);
1204 _PM_mouseHandler
= NULL
;
1210 /*-------------------------------------------------------------------------*/
1211 /* DJGPP port of GNU C++ support. */
1212 /*-------------------------------------------------------------------------*/
1215 #define GENERIC_DPMI32 /* Use generic 32 bit DPMI routines */
1217 void PMAPI
PM_getPMvect(int intno
, PMFARPTR
*isr
)
1223 PM_int386(0x31,®s
,®s
);
1224 isr
->sel
= regs
.x
.cx
;
1225 isr
->off
= regs
.e
.edx
;
1228 void PMAPI
PM_setPMvect(int intno
, PM_intHandler isr
)
1234 regs
.x
.ax
= 0x205; /* Set protected mode vector */
1237 regs
.x
.cx
= sregs
.cs
;
1238 regs
.e
.edx
= (uint
)isr
;
1239 PM_int386(0x31,®s
,®s
);
1242 void PMAPI
PM_restorePMvect(int intno
, PMFARPTR isr
)
1248 regs
.x
.cx
= isr
.sel
;
1249 regs
.e
.edx
= isr
.off
;
1250 PM_int386(0x31,®s
,®s
);
1255 /*-------------------------------------------------------------------------*/
1256 /* Generic 32 bit DPMI routines */
1257 /*-------------------------------------------------------------------------*/
1259 #if defined(GENERIC_DPMI32)
1261 static long prevRealBreak
; /* Previous real mode break handler */
1262 static long prevRealCtrlC
; /* Previous real mode CtrlC handler */
1263 static long prevRealCritical
; /* Prev real mode critical handler */
1265 #ifndef MOUSE_SUPPORTED
1267 /* The following real mode routine is used to call a 32 bit protected
1268 * mode FAR function from real mode. We use this for passing up control
1269 * from the real mode mouse callback to our protected mode code.
1272 static long mouseRMCB
; /* Mouse real mode callback address */
1273 static uchar
*mousePtr
;
1274 static char mouseRegs
[0x32]; /* Real mode regs for mouse callback */
1275 static uchar mouseHandler
[] = {
1276 0x00,0x00,0x00,0x00, /* _realRMCB */
1277 0x2E,0xFF,0x1E,0x00,0x00, /* call [cs:_realRMCB] */
1281 int PMAPI
PM_setMouseHandler(int mask
, PM_mouseHandler mh
)
1287 lockPMHandlers(); /* Ensure our handlers are locked */
1289 /* Copy the real mode handler to real mode memory */
1290 if ((mousePtr
= PM_allocRealSeg(sizeof(mouseHandler
),&rseg
,&roff
)) == NULL
)
1292 memcpy(mousePtr
,mouseHandler
,sizeof(mouseHandler
));
1293 if (!_DPMI_allocateCallback(_PM_mousePMCB
, mouseRegs
, &mouseRMCB
))
1294 PM_fatalError("Unable to allocate real mode callback!\n");
1295 PM_setLong(mousePtr
,mouseRMCB
);
1297 /* Install the real mode mouse handler */
1298 _PM_mouseHandler
= mh
;
1301 regs
.x
.cx
= _PM_mouseMask
= mask
;
1303 PM_int86x(0x33, ®s
, ®s
, &sregs
);
1307 void PMAPI
PM_restoreMouseHandler(void)
1311 if (_PM_mouseHandler
) {
1313 PM_int86(0x33, ®s
, ®s
);
1314 PM_freeRealSeg(mousePtr
);
1315 _DPMI_freeCallback(mouseRMCB
);
1316 _PM_mouseHandler
= NULL
;
1322 static void getISR(int intno
, PMFARPTR
*pmisr
, long *realisr
)
1324 PM_getPMvect(intno
,pmisr
);
1325 _PM_getRMvect(intno
,realisr
);
1328 static void restoreISR(int intno
, PMFARPTR pmisr
, long realisr
)
1330 _PM_setRMvect(intno
,realisr
);
1331 PM_restorePMvect(intno
,pmisr
);
1334 static void setISR(int intno
, void (* PMAPI pmisr
)())
1336 lockPMHandlers(); /* Ensure our handlers are locked */
1337 PM_setPMvect(intno
,pmisr
);
1340 void PMAPI
PM_setTimerHandler(PM_intHandler th
)
1342 getISR(0x8, &_PM_prevTimer
, &_PM_prevRealTimer
);
1343 _PM_timerHandler
= th
;
1344 setISR(0x8, _PM_timerISR
);
1347 void PMAPI
PM_restoreTimerHandler(void)
1349 if (_PM_timerHandler
) {
1350 restoreISR(0x8, _PM_prevTimer
, _PM_prevRealTimer
);
1351 _PM_timerHandler
= NULL
;
1355 ibool PMAPI
PM_setRealTimeClockHandler(PM_intHandler th
,int frequency
)
1357 /* Save the old CMOS real time clock values */
1358 _PM_oldCMOSRegA
= _PM_readCMOS(0x0A);
1359 _PM_oldCMOSRegB
= _PM_readCMOS(0x0B);
1361 /* Set the real time clock interrupt handler */
1362 getISR(0x70, &_PM_prevRTC
, &_PM_prevRealRTC
);
1363 _PM_rtcHandler
= th
;
1364 setISR(0x70, _PM_rtcISR
);
1366 /* Program the real time clock default frequency */
1367 PM_setRealTimeClockFrequency(frequency
);
1369 /* Unmask IRQ8 in the PIC2 */
1370 _PM_oldRTCPIC2
= PM_inpb(0xA1);
1371 PM_outpb(0xA1,_PM_oldRTCPIC2
& 0xFE);
1375 void PMAPI
PM_restoreRealTimeClockHandler(void)
1377 if (_PM_rtcHandler
) {
1378 /* Restore CMOS registers and mask RTC clock */
1379 _PM_writeCMOS(0x0A,_PM_oldCMOSRegA
);
1380 _PM_writeCMOS(0x0B,_PM_oldCMOSRegB
);
1381 PM_outpb(0xA1,(PM_inpb(0xA1) & 0xFE) | (_PM_oldRTCPIC2
& ~0xFE));
1383 /* Restore the interrupt vector */
1384 restoreISR(0x70, _PM_prevRTC
, _PM_prevRealRTC
);
1385 _PM_rtcHandler
= NULL
;
1389 PM_IRQHandle PMAPI
PM_setIRQHandler(
1393 int thunkSize
,PICmask
,chainPrevious
;
1395 _PM_IRQHandle
*handle
;
1397 thunkSize
= (ulong
)_PM_irqISRTemplateEnd
- (ulong
)_PM_irqISRTemplate
;
1398 if ((handle
= PM_malloc(sizeof(_PM_IRQHandle
) + thunkSize
)) == NULL
)
1401 handle
->prevPIC
= PM_inpb(0x21);
1402 handle
->prevPIC2
= PM_inpb(0xA1);
1404 handle
->IRQVect
= (IRQ
+ 8);
1405 PICmask
= (1 << IRQ
);
1406 chainPrevious
= ((handle
->prevPIC
& PICmask
) == 0);
1409 handle
->IRQVect
= (0x60 + IRQ
+ 8);
1410 PICmask
= ((1 << IRQ
) | 0x4);
1411 chainPrevious
= ((handle
->prevPIC2
& (PICmask
>> 8)) == 0);
1414 /* Copy and setup the assembler thunk */
1415 offsetAdjust
= (ulong
)handle
->thunk
- (ulong
)_PM_irqISRTemplate
;
1416 memcpy(handle
->thunk
,_PM_irqISRTemplate
,thunkSize
);
1417 *((ulong
*)&handle
->thunk
[2]) = offsetAdjust
;
1418 *((ulong
*)&handle
->thunk
[11+0]) = (ulong
)ih
;
1419 if (chainPrevious
) {
1420 *((ulong
*)&handle
->thunk
[11+4]) = handle
->prevHandler
.off
;
1421 *((ulong
*)&handle
->thunk
[11+8]) = handle
->prevHandler
.sel
;
1424 *((ulong
*)&handle
->thunk
[11+4]) = 0;
1425 *((ulong
*)&handle
->thunk
[11+8]) = 0;
1427 *((ulong
*)&handle
->thunk
[11+12]) = IRQ
;
1429 /* Set the real time clock interrupt handler */
1430 getISR(handle
->IRQVect
, &handle
->prevHandler
, &handle
->prevRealhandler
);
1431 setISR(handle
->IRQVect
, (PM_intHandler
)handle
->thunk
);
1433 /* Unmask the IRQ in the PIC */
1434 PM_outpb(0xA1,handle
->prevPIC2
& ~(PICmask
>> 8));
1435 PM_outpb(0x21,handle
->prevPIC
& ~PICmask
);
1439 void PMAPI
PM_restoreIRQHandler(
1440 PM_IRQHandle irqHandle
)
1443 _PM_IRQHandle
*handle
= irqHandle
;
1445 /* Restore PIC mask for the interrupt */
1446 if (handle
->IRQ
< 8)
1447 PICmask
= (1 << handle
->IRQ
);
1449 PICmask
= ((1 << handle
->IRQ
) | 0x4);
1450 PM_outpb(0xA1,(PM_inpb(0xA1) & ~(PICmask
>> 8)) | (handle
->prevPIC2
& (PICmask
>> 8)));
1451 PM_outpb(0x21,(PM_inpb(0x21) & ~PICmask
) | (handle
->prevPIC
& PICmask
));
1453 /* Restore the interrupt vector */
1454 restoreISR(handle
->IRQVect
, handle
->prevHandler
, handle
->prevRealhandler
);
1456 /* Finally free the thunk */
1460 void PMAPI
PM_setKeyHandler(PM_intHandler kh
)
1462 getISR(0x9, &_PM_prevKey
, &_PM_prevRealKey
);
1463 _PM_keyHandler
= kh
;
1464 setISR(0x9, _PM_keyISR
);
1467 void PMAPI
PM_restoreKeyHandler(void)
1469 if (_PM_keyHandler
) {
1470 restoreISR(0x9, _PM_prevKey
, _PM_prevRealKey
);
1471 _PM_keyHandler
= NULL
;
1475 void PMAPI
PM_setKey15Handler(PM_key15Handler kh
)
1477 getISR(0x15, &_PM_prevKey15
, &_PM_prevRealKey15
);
1478 _PM_key15Handler
= kh
;
1479 setISR(0x15, _PM_key15ISR
);
1482 void PMAPI
PM_restoreKey15Handler(void)
1484 if (_PM_key15Handler
) {
1485 restoreISR(0x15, _PM_prevKey15
, _PM_prevRealKey15
);
1486 _PM_key15Handler
= NULL
;
1490 /* Real mode Ctrl-C and Ctrl-Break handler. This handler simply sets a
1491 * flag in the real mode code segment and exit. We save the location
1492 * of this flag in real mode memory so that both the real mode and
1493 * protected mode code will be modifying the same flags.
1497 static uchar ctrlHandler
[] = {
1498 0x00,0x00,0x00,0x00, /* ctrlBFlag */
1499 0x66,0x2E,0xC7,0x06,0x00,0x00,
1500 0x01,0x00,0x00,0x00, /* mov [cs:ctrlBFlag],1 */
1505 void PMAPI
PM_installAltBreakHandler(PM_breakHandler bh
)
1510 static int ctrlCFlag
,ctrlBFlag
;
1512 _PM_ctrlCPtr
= (uchar
*)&ctrlCFlag
;
1513 _PM_ctrlBPtr
= (uchar
*)&ctrlBFlag
;
1516 getISR(0x1B, &_PM_prevBreak
, &prevRealBreak
);
1517 getISR(0x23, &_PM_prevCtrlC
, &prevRealCtrlC
);
1518 _PM_breakHandler
= bh
;
1519 setISR(0x1B, _PM_breakISR
);
1520 setISR(0x23, _PM_ctrlCISR
);
1523 /* Hook the real mode vectors for these handlers, as these are not
1524 * normally reflected by the DPMI server up to protected mode
1526 _PM_ctrlBPtr
= PM_allocRealSeg(sizeof(ctrlHandler
)*2, &rseg
, &roff
);
1527 memcpy(_PM_ctrlBPtr
,ctrlHandler
,sizeof(ctrlHandler
));
1528 memcpy(_PM_ctrlBPtr
+sizeof(ctrlHandler
),ctrlHandler
,sizeof(ctrlHandler
));
1529 _PM_ctrlCPtr
= _PM_ctrlBPtr
+ sizeof(ctrlHandler
);
1530 _PM_setRMvect(0x1B,((long)rseg
<< 16) | (roff
+4));
1531 _PM_setRMvect(0x23,((long)rseg
<< 16) | (roff
+sizeof(ctrlHandler
)+4));
1535 void PMAPI
PM_installBreakHandler(void)
1537 PM_installAltBreakHandler(NULL
);
1540 void PMAPI
PM_restoreBreakHandler(void)
1542 if (_PM_prevBreak
.sel
) {
1543 restoreISR(0x1B, _PM_prevBreak
, prevRealBreak
);
1544 restoreISR(0x23, _PM_prevCtrlC
, prevRealCtrlC
);
1545 _PM_prevBreak
.sel
= 0;
1546 _PM_breakHandler
= NULL
;
1548 PM_freeRealSeg(_PM_ctrlBPtr
);
1553 /* Real mode Critical Error handler. This handler simply saves the AX and
1554 * DI values in the real mode code segment and exits. We save the location
1555 * of this flag in real mode memory so that both the real mode and
1556 * protected mode code will be modifying the same flags.
1560 static uchar criticalHandler
[] = {
1561 0x00,0x00, /* axCode */
1562 0x00,0x00, /* diCode */
1563 0x2E,0xA3,0x00,0x00, /* mov [cs:axCode],ax */
1564 0x2E,0x89,0x3E,0x02,0x00, /* mov [cs:diCode],di */
1565 0xB8,0x03,0x00, /* mov ax,3 */
1570 void PMAPI
PM_installAltCriticalHandler(PM_criticalHandler ch
)
1575 static short critBuf
[2];
1577 _PM_critPtr
= (uchar
*)critBuf
;
1580 getISR(0x24, &_PM_prevCritical
, &prevRealCritical
);
1581 _PM_critHandler
= ch
;
1582 setISR(0x24, _PM_criticalISR
);
1585 /* Hook the real mode vector, as this is not normally reflected by the
1586 * DPMI server up to protected mode.
1588 _PM_critPtr
= PM_allocRealSeg(sizeof(criticalHandler
)*2, &rseg
, &roff
);
1589 memcpy(_PM_critPtr
,criticalHandler
,sizeof(criticalHandler
));
1590 _PM_setRMvect(0x24,((long)rseg
<< 16) | (roff
+4));
1594 void PMAPI
PM_installCriticalHandler(void)
1596 PM_installAltCriticalHandler(NULL
);
1599 void PMAPI
PM_restoreCriticalHandler(void)
1601 if (_PM_prevCritical
.sel
) {
1602 restoreISR(0x24, _PM_prevCritical
, prevRealCritical
);
1603 PM_freeRealSeg(_PM_critPtr
);
1604 _PM_prevCritical
.sel
= 0;
1605 _PM_critHandler
= NULL
;
1609 int PMAPI
PM_lockDataPages(void *p
,uint len
,PM_lockHandle
*lh
)
1613 return DPMI_lockLinearPages((uint
)p
+ DPMI_getSelectorBase(sregs
.ds
),len
);
1616 int PMAPI
PM_unlockDataPages(void *p
,uint len
,PM_lockHandle
*lh
)
1620 return DPMI_unlockLinearPages((uint
)p
+ DPMI_getSelectorBase(sregs
.ds
),len
);
1623 int PMAPI
PM_lockCodePages(void (*p
)(),uint len
,PM_lockHandle
*lh
)
1627 return DPMI_lockLinearPages((uint
)p
+ DPMI_getSelectorBase(sregs
.cs
),len
);
1630 int PMAPI
PM_unlockCodePages(void (*p
)(),uint len
,PM_lockHandle
*lh
)
1634 return DPMI_unlockLinearPages((uint
)p
+ DPMI_getSelectorBase(sregs
.cs
),len
);