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);