]> git.ipfire.org Git - people/ms/u-boot.git/blob - board/MAI/bios_emulator/scitech/src/pm/dos/pmdos.c
* Code cleanup:
[people/ms/u-boot.git] / board / MAI / bios_emulator / scitech / src / pm / dos / pmdos.c
1 /****************************************************************************
2 *
3 * SciTech OS Portability Manager Library
4 *
5 * ========================================================================
6 *
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
11 *
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.
16 *
17 * The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
18 *
19 * The Initial Developer of the Original Code is SciTech Software, Inc.
20 * All Rights Reserved.
21 *
22 * ========================================================================
23 *
24 * Language: ANSI C
25 * Environment: 16/32 bit DOS
26 *
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.
32 *
33 ****************************************************************************/
34
35 #include "pmapi.h"
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <dos.h>
40
41 /*--------------------------- Global variables ----------------------------*/
42
43 #ifndef REALMODE
44 static int globalDataStart;
45 #endif
46
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;
56
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 */
75
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).
79 */
80
81 typedef struct {
82 uchar IRQ;
83 uchar IRQVect;
84 uchar prevPIC;
85 uchar prevPIC2;
86 PMFARPTR prevHandler;
87 long prevRealhandler;
88 uchar thunk[1];
89 /* IRQ assembler thunk follows ... */
90 } _PM_IRQHandle;
91
92 /*----------------------------- Implementation ----------------------------*/
93
94 /* Globals for locking interrupt handlers in _pmdos.asm */
95
96 #ifndef REALMODE
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);
105 #endif
106
107 /* Protected mode interrupt handlers, also called by PM callbacks below */
108
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);
120
121 /* Protected mode DPMI callback handlers */
122
123 void _ASMAPI _PM_mousePMCB(void);
124
125 /* Routine to install a mouse handler function */
126
127 void _ASMAPI _PM_setMouseHandler(int mask);
128
129 /* Routine to allocate DPMI real mode callback routines */
130
131 ibool _ASMAPI _DPMI_allocateCallback(void (_ASMAPI *pmcode)(),void *rmregs,long *RMCB);
132 void _ASMAPI _DPMI_freeCallback(long RMCB);
133
134 /* DPMI helper functions in PMLITE.C */
135
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);
144
145 /* Functions to read and write CMOS registers */
146
147 uchar PMAPI _PM_readCMOS(int index);
148 void PMAPI _PM_writeCMOS(int index,uchar value);
149
150 /*-------------------------------------------------------------------------*/
151 /* Generic routines common to all environments */
152 /*-------------------------------------------------------------------------*/
153
154 void PMAPI PM_resetMouseDriver(int hardReset)
155 {
156 RMREGS regs;
157 PM_mouseHandler oldHandler = _PM_mouseHandler;
158
159 PM_restoreMouseHandler();
160 regs.x.ax = hardReset ? 0 : 33;
161 PM_int86(0x33, &regs, &regs);
162 if (oldHandler)
163 PM_setMouseHandler(_PM_mouseMask, oldHandler);
164 }
165
166 void PMAPI PM_setRealTimeClockFrequency(int frequency)
167 {
168 static short convert[] = {
169 8192,
170 4096,
171 2048,
172 1024,
173 512,
174 256,
175 128,
176 64,
177 32,
178 16,
179 8,
180 4,
181 2,
182 -1,
183 };
184 int i;
185
186 /* First clear any pending RTC timeout if not cleared */
187 _PM_readCMOS(0x0C);
188 if (frequency == 0) {
189 /* Disable RTC timout */
190 _PM_writeCMOS(0x0A,_PM_oldCMOSRegA);
191 _PM_writeCMOS(0x0B,_PM_oldCMOSRegB & 0x0F);
192 }
193 else {
194 /* Convert frequency value to RTC clock indexes */
195 for (i = 0; convert[i] != -1; i++) {
196 if (convert[i] == frequency)
197 break;
198 }
199
200 /* Set RTC timout value and enable timeout */
201 _PM_writeCMOS(0x0A,0x20 | (i+3));
202 _PM_writeCMOS(0x0B,(_PM_oldCMOSRegB & 0x0F) | 0x40);
203 }
204 }
205
206 #ifndef REALMODE
207
208 static void PMAPI lockPMHandlers(void)
209 {
210 static int locked = 0;
211 int stat;
212 PM_lockHandle lh; /* Unused in DOS */
213
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
216 * under real mode.
217 */
218 if (!locked) {
219 PM_saveDS();
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);
225 if (stat) {
226 printf("Page locking services failed - interrupt handling not safe!\n");
227 exit(1);
228 }
229 locked = 1;
230 }
231 }
232
233 #endif
234
235 /*-------------------------------------------------------------------------*/
236 /* DOS Real Mode support. */
237 /*-------------------------------------------------------------------------*/
238
239 #ifdef REALMODE
240
241 #ifndef MK_FP
242 #define MK_FP(s,o) ( (void far *)( ((ulong)(s) << 16) + \
243 (ulong)(o) ))
244 #endif
245
246 int PMAPI PM_setMouseHandler(int mask, PM_mouseHandler mh)
247 {
248 PM_saveDS();
249 _PM_mouseHandler = mh;
250 _PM_setMouseHandler(_PM_mouseMask = mask);
251 return 1;
252 }
253
254 void PMAPI PM_restoreMouseHandler(void)
255 {
256 union REGS regs;
257
258 if (_PM_mouseHandler) {
259 regs.x.ax = 33;
260 int86(0x33, &regs, &regs);
261 _PM_mouseHandler = NULL;
262 }
263 }
264
265 void PMAPI PM_setTimerHandler(PM_intHandler th)
266 {
267 _PM_getRMvect(0x8, (long*)&_PM_prevTimer);
268 _PM_timerHandler = th;
269 _PM_setRMvect(0x8, (long)_PM_timerISR);
270 }
271
272 void PMAPI PM_restoreTimerHandler(void)
273 {
274 if (_PM_timerHandler) {
275 _PM_setRMvect(0x8, (long)_PM_prevTimer);
276 _PM_timerHandler = NULL;
277 }
278 }
279
280 ibool PMAPI PM_setRealTimeClockHandler(PM_intHandler th,int frequency)
281 {
282 /* Save the old CMOS real time clock values */
283 _PM_oldCMOSRegA = _PM_readCMOS(0x0A);
284 _PM_oldCMOSRegB = _PM_readCMOS(0x0B);
285
286 /* Set the real time clock interrupt handler */
287 _PM_getRMvect(0x70, (long*)&_PM_prevRTC);
288 _PM_rtcHandler = th;
289 _PM_setRMvect(0x70, (long)_PM_rtcISR);
290
291 /* Program the real time clock default frequency */
292 PM_setRealTimeClockFrequency(frequency);
293
294 /* Unmask IRQ8 in the PIC2 */
295 _PM_oldRTCPIC2 = PM_inpb(0xA1);
296 PM_outpb(0xA1,_PM_oldRTCPIC2 & 0xFE);
297 return true;
298 }
299
300 void PMAPI PM_restoreRealTimeClockHandler(void)
301 {
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));
307
308 /* Restore the interrupt vector */
309 _PM_setRMvect(0x70, (long)_PM_prevRTC);
310 _PM_rtcHandler = NULL;
311 }
312 }
313
314 void PMAPI PM_setKeyHandler(PM_intHandler kh)
315 {
316 _PM_getRMvect(0x9, (long*)&_PM_prevKey);
317 _PM_keyHandler = kh;
318 _PM_setRMvect(0x9, (long)_PM_keyISR);
319 }
320
321 void PMAPI PM_restoreKeyHandler(void)
322 {
323 if (_PM_keyHandler) {
324 _PM_setRMvect(0x9, (long)_PM_prevKey);
325 _PM_keyHandler = NULL;
326 }
327 }
328
329 void PMAPI PM_setKey15Handler(PM_key15Handler kh)
330 {
331 _PM_getRMvect(0x15, (long*)&_PM_prevKey15);
332 _PM_key15Handler = kh;
333 _PM_setRMvect(0x15, (long)_PM_key15ISR);
334 }
335
336 void PMAPI PM_restoreKey15Handler(void)
337 {
338 if (_PM_key15Handler) {
339 _PM_setRMvect(0x15, (long)_PM_prevKey15);
340 _PM_key15Handler = NULL;
341 }
342 }
343
344 void PMAPI PM_installAltBreakHandler(PM_breakHandler bh)
345 {
346 static int ctrlCFlag,ctrlBFlag;
347
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);
355 }
356
357 void PMAPI PM_installBreakHandler(void)
358 {
359 PM_installAltBreakHandler(NULL);
360 }
361
362 void PMAPI PM_restoreBreakHandler(void)
363 {
364 if (_PM_prevBreak) {
365 _PM_setRMvect(0x1B, (long)_PM_prevBreak);
366 _PM_setRMvect(0x23, (long)_PM_prevCtrlC);
367 _PM_prevBreak = NULL;
368 _PM_breakHandler = NULL;
369 }
370 }
371
372 void PMAPI PM_installAltCriticalHandler(PM_criticalHandler ch)
373 {
374 static short critBuf[2];
375
376 _PM_critPtr = (uchar*)critBuf;
377 _PM_getRMvect(0x24, (long*)&_PM_prevCritical);
378 _PM_critHandler = ch;
379 _PM_setRMvect(0x24, (long)_PM_criticalISR);
380 }
381
382 void PMAPI PM_installCriticalHandler(void)
383 {
384 PM_installAltCriticalHandler(NULL);
385 }
386
387 void PMAPI PM_restoreCriticalHandler(void)
388 {
389 if (_PM_prevCritical) {
390 _PM_setRMvect(0x24, (long)_PM_prevCritical);
391 _PM_prevCritical = NULL;
392 _PM_critHandler = NULL;
393 }
394 }
395
396 int PMAPI PM_lockDataPages(void *p,uint len,PM_lockHandle *lh)
397 {
398 p = p; len = len; /* Do nothing for real mode */
399 return 1;
400 }
401
402 int PMAPI PM_unlockDataPages(void *p,uint len,PM_lockHandle *lh)
403 {
404 p = p; len = len; /* Do nothing for real mode */
405 return 1;
406 }
407
408 int PMAPI PM_lockCodePages(void (*p)(),uint len,PM_lockHandle *lh)
409 {
410 p = p; len = len; /* Do nothing for real mode */
411 return 1;
412 }
413
414 int PMAPI PM_unlockCodePages(void (*p)(),uint len,PM_lockHandle *lh)
415 {
416 p = p; len = len; /* Do nothing for real mode */
417 return 1;
418 }
419
420 void PMAPI PM_getPMvect(int intno, PMFARPTR *isr)
421 {
422 long t;
423 _PM_getRMvect(intno,&t);
424 *isr = (void*)t;
425 }
426
427 void PMAPI PM_setPMvect(int intno, PM_intHandler isr)
428 {
429 PM_saveDS();
430 _PM_setRMvect(intno,(long)isr);
431 }
432
433 void PMAPI PM_restorePMvect(int intno, PMFARPTR isr)
434 {
435 _PM_setRMvect(intno,(long)isr);
436 }
437
438 #endif
439
440 /*-------------------------------------------------------------------------*/
441 /* Phar Lap TNT DOS Extender support. */
442 /*-------------------------------------------------------------------------*/
443
444 #ifdef TNT
445
446 #include <pldos32.h>
447 #include <pharlap.h>
448 #include <hw386.h>
449
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;
454
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.
458 */
459
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 */
465 0x1E, /* push ds */
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 */
472 0x1F, /* pop ds */
473 0x66,0x61, /* popad */
474 0xCB, /* retf */
475 };
476
477 /* The following functions installs the above realmode callback mechanism
478 * in real mode memory for calling the protected mode routine.
479 */
480
481 uchar * installCallback(void (PMAPI *pmCB)(),uint *rseg, uint *roff)
482 {
483 CONFIG_INF config;
484 REALPTR realBufAdr,callProtp;
485 ULONG bufSize;
486 FARPTR protBufAdr;
487 uchar *p;
488
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);
492
493 /* Fill in the values in the real mode code segment so that it will
494 * call the correct routine.
495 */
496 *((REALPTR*)&realHandler[0]) = callProtp;
497 *((USHORT*)&realHandler[4]) = config.c_cs_sel;
498 *((ULONG*)&realHandler[6]) = (ULONG)pmCB;
499
500 /* Copy the real mode handler to real mode memory */
501 if ((p = PM_allocRealSeg(sizeof(realHandler),rseg,roff)) == NULL)
502 return NULL;
503 memcpy(p,realHandler,sizeof(realHandler));
504
505 /* Skip past global variabls in real mode code segment */
506 *roff += 0x0A;
507 return p;
508 }
509
510 int PMAPI PM_setMouseHandler(int mask, PM_mouseHandler mh)
511 {
512 RMREGS regs;
513 RMSREGS sregs;
514 uint rseg,roff;
515
516 lockPMHandlers(); /* Ensure our handlers are locked */
517
518 if ((mousePtr = installCallback(_PM_mouseISR, &rseg, &roff)) == NULL)
519 return 0;
520 _PM_mouseHandler = mh;
521
522 /* Install the real mode mouse handler */
523 sregs.es = rseg;
524 regs.x.dx = roff;
525 regs.x.cx = _PM_mouseMask = mask;
526 regs.x.ax = 0xC;
527 PM_int86x(0x33, &regs, &regs, &sregs);
528 return 1;
529 }
530
531 void PMAPI PM_restoreMouseHandler(void)
532 {
533 RMREGS regs;
534
535 if (_PM_mouseHandler) {
536 regs.x.ax = 33;
537 PM_int86(0x33, &regs, &regs);
538 PM_freeRealSeg(mousePtr);
539 _PM_mouseHandler = NULL;
540 }
541 }
542
543 void PMAPI PM_getPMvect(int intno, PMFARPTR *isr)
544 {
545 FARPTR ph;
546
547 _dx_pmiv_get(intno, &ph);
548 isr->sel = FP_SEL(ph);
549 isr->off = FP_OFF(ph);
550 }
551
552 void PMAPI PM_setPMvect(int intno, PM_intHandler isr)
553 {
554 CONFIG_INF config;
555 FARPTR ph;
556
557 PM_saveDS();
558 _dx_config_inf(&config, (UCHAR*)&config);
559 FP_SET(ph,(uint)isr,config.c_cs_sel);
560 _dx_pmiv_set(intno,ph);
561 }
562
563 void PMAPI PM_restorePMvect(int intno, PMFARPTR isr)
564 {
565 FARPTR ph;
566
567 FP_SET(ph,isr.off,isr.sel);
568 _dx_pmiv_set(intno,ph);
569 }
570
571 static void getISR(int intno, PMFARPTR *pmisr, long *realisr)
572 {
573 PM_getPMvect(intno,pmisr);
574 _PM_getRMvect(intno, realisr);
575 }
576
577 static void restoreISR(int intno, PMFARPTR pmisr, long realisr)
578 {
579 _PM_setRMvect(intno,realisr);
580 PM_restorePMvect(intno,pmisr);
581 }
582
583 static void setISR(int intno, void (PMAPI *isr)())
584 {
585 CONFIG_INF config;
586 FARPTR ph;
587
588 lockPMHandlers(); /* Ensure our handlers are locked */
589
590 _dx_config_inf(&config, (UCHAR*)&config);
591 FP_SET(ph,(uint)isr,config.c_cs_sel);
592 _dx_apmiv_set(intno,ph);
593 }
594
595 void PMAPI PM_setTimerHandler(PM_intHandler th)
596 {
597 getISR(0x8, &_PM_prevTimer, &_PM_prevRealTimer);
598 _PM_timerHandler = th;
599 setISR(0x8, _PM_timerISR);
600 }
601
602 void PMAPI PM_restoreTimerHandler(void)
603 {
604 if (_PM_timerHandler) {
605 restoreISR(0x8, _PM_prevTimer, _PM_prevRealTimer);
606 _PM_timerHandler = NULL;
607 }
608 }
609
610 ibool PMAPI PM_setRealTimeClockHandler(PM_intHandler th,int frequency)
611 {
612 /* Save the old CMOS real time clock values */
613 _PM_oldCMOSRegA = _PM_readCMOS(0x0A);
614 _PM_oldCMOSRegB = _PM_readCMOS(0x0B);
615
616 /* Set the real time clock interrupt handler */
617 getISR(0x70, &_PM_prevRTC, &_PM_prevRealRTC);
618 _PM_rtcHandler = th;
619 setISR(0x70, _PM_rtcISR);
620
621 /* Program the real time clock default frequency */
622 PM_setRealTimeClockFrequency(frequency);
623
624 /* Unmask IRQ8 in the PIC2 */
625 _PM_oldRTCPIC2 = PM_inpb(0xA1);
626 PM_outpb(0xA1,_PM_oldRTCPIC2 & 0xFE);
627 return true;
628 }
629
630 void PMAPI PM_restoreRealTimeClockHandler(void)
631 {
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));
637
638 /* Restore the interrupt vector */
639 restoreISR(0x70, _PM_prevRTC, _PM_prevRealRTC);
640 _PM_rtcHandler = NULL;
641 }
642 }
643
644 void PMAPI PM_setKeyHandler(PM_intHandler kh)
645 {
646 getISR(0x9, &_PM_prevKey, &_PM_prevRealKey);
647 _PM_keyHandler = kh;
648 setISR(0x9, _PM_keyISR);
649 }
650
651 void PMAPI PM_restoreKeyHandler(void)
652 {
653 if (_PM_keyHandler) {
654 restoreISR(0x9, _PM_prevKey, _PM_prevRealKey);
655 _PM_keyHandler = NULL;
656 }
657 }
658
659 void PMAPI PM_setKey15Handler(PM_key15Handler kh)
660 {
661 getISR(0x15, &_PM_prevKey15, &_PM_prevRealKey15);
662 _PM_key15Handler = kh;
663 setISR(0x15, _PM_key15ISR);
664 }
665
666 void PMAPI PM_restoreKey15Handler(void)
667 {
668 if (_PM_key15Handler) {
669 restoreISR(0x15, _PM_prevKey15, _PM_prevRealKey15);
670 _PM_key15Handler = NULL;
671 }
672 }
673
674 void PMAPI PM_installAltBreakHandler(PM_breakHandler bh)
675 {
676 static int ctrlCFlag,ctrlBFlag;
677
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);
685 }
686
687 void PMAPI PM_installBreakHandler(void)
688 {
689 PM_installAltBreakHandler(NULL);
690 }
691
692 void PMAPI PM_restoreBreakHandler(void)
693 {
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;
699 }
700 }
701
702 void PMAPI PM_installAltCriticalHandler(PM_criticalHandler ch)
703 {
704 static short critBuf[2];
705
706 _PM_critPtr = (uchar*)critBuf;
707 getISR(0x24, &_PM_prevCritical, &prevRealCritical);
708 _PM_critHandler = ch;
709 setISR(0x24, _PM_criticalISR);
710 }
711
712 void PMAPI PM_installCriticalHandler(void)
713 {
714 PM_installAltCriticalHandler(NULL);
715 }
716
717 void PMAPI PM_restoreCriticalHandler(void)
718 {
719 if (_PM_prevCritical.sel) {
720 restoreISR(0x24, _PM_prevCritical, prevRealCritical);
721 _PM_prevCritical.sel = 0;
722 _PM_critHandler = NULL;
723 }
724 }
725
726 int PMAPI PM_lockDataPages(void *p,uint len,PM_lockHandle *lh)
727 {
728 return (_dx_lock_pgsn(p,len) == 0);
729 }
730
731 int PMAPI PM_unlockDataPages(void *p,uint len,PM_lockHandle *lh)
732 {
733 return (_dx_ulock_pgsn(p,len) == 0);
734 }
735
736 int PMAPI PM_lockCodePages(void (*p)(),uint len,PM_lockHandle *lh)
737 {
738 CONFIG_INF config;
739 FARPTR fp;
740
741 _dx_config_inf(&config, (UCHAR*)&config);
742 FP_SET(fp,p,config.c_cs_sel);
743 return (_dx_lock_pgs(fp,len) == 0);
744 }
745
746 int PMAPI PM_unlockCodePages(void (*p)(),uint len,PM_lockHandle *lh)
747 {
748 CONFIG_INF config;
749 FARPTR fp;
750
751 _dx_config_inf(&config, (UCHAR*)&config);
752 FP_SET(fp,p,config.c_cs_sel);
753 return (_dx_ulock_pgs(fp,len) == 0);
754 }
755
756 #endif
757
758 /*-------------------------------------------------------------------------*/
759 /* Symantec C++ DOSX and FlashTek X-32/X-32VM support */
760 /*-------------------------------------------------------------------------*/
761
762 #if defined(DOSX) || defined(X32VM)
763
764 #ifdef X32VM
765 #include <x32.h>
766 #endif
767
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 */
771
772 static uint mouseSel = 0,mouseOff;
773
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.
777 */
778
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 */
783 0x1E, /* push ds */
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 */
790 0x1F, /* pop ds */
791 0xCB, /* retf */
792 };
793
794 /* The following functions installs the above realmode callback mechanism
795 * in real mode memory for calling the protected mode routine.
796 */
797
798 int installCallback(void (PMAPI *pmCB)(),uint *psel, uint *poff,
799 uint *rseg, uint *roff)
800 {
801 PMREGS regs;
802 PMSREGS sregs;
803
804 regs.x.ax = 0x250D;
805 PM_segread(&sregs);
806 PM_int386x(0x21,&regs,&regs,&sregs); /* Get RM callback address */
807
808 /* Fill in the values in the real mode code segment so that it will
809 * call the correct routine.
810 */
811 *((ulong*)&realHandler[0]) = regs.e.eax;
812 *((ushort*)&realHandler[4]) = sregs.cs;
813 *((ulong*)&realHandler[6]) = (ulong)pmCB;
814
815 /* Copy the real mode handler to real mode memory (only allocate the
816 * buffer once since we cant dealloate it with X32).
817 */
818 if (*psel == 0) {
819 if (!PM_allocRealSeg(sizeof(realHandler),psel,poff,rseg,roff))
820 return 0;
821 }
822 PM_memcpyfn(*psel,*poff,realHandler,sizeof(realHandler));
823
824 /* Skip past global variables in real mode code segment */
825 *roff += 0x0A;
826 return 1;
827 }
828
829 int PMAPI PM_setMouseHandler(int mask, PM_mouseHandler mh)
830 {
831 RMREGS regs;
832 RMSREGS sregs;
833 uint rseg,roff;
834
835 lockPMHandlers(); /* Ensure our handlers are locked */
836
837 if (!installCallback(_PM_mouseISR, &mouseSel, &mouseOff, &rseg, &roff))
838 return 0;
839 _PM_mouseHandler = mh;
840
841 /* Install the real mode mouse handler */
842 sregs.es = rseg;
843 regs.x.dx = roff;
844 regs.x.cx = _PM_mouseMask = mask;
845 regs.x.ax = 0xC;
846 PM_int86x(0x33, &regs, &regs, &sregs);
847 return 1;
848 }
849
850 void PMAPI PM_restoreMouseHandler(void)
851 {
852 RMREGS regs;
853
854 if (_PM_mouseHandler) {
855 regs.x.ax = 33;
856 PM_int86(0x33, &regs, &regs);
857 _PM_mouseHandler = NULL;
858 }
859 }
860
861 void PMAPI PM_getPMvect(int intno, PMFARPTR *isr)
862 {
863 PMREGS regs;
864 PMSREGS sregs;
865
866 PM_segread(&sregs);
867 regs.x.ax = 0x2502; /* Get PM interrupt vector */
868 regs.x.cx = intno;
869 PM_int386x(0x21, &regs, &regs, &sregs);
870 isr->sel = sregs.es;
871 isr->off = regs.e.ebx;
872 }
873
874 void PMAPI PM_setPMvect(int intno, PM_intHandler isr)
875 {
876 PMFARPTR pmisr;
877 PMSREGS sregs;
878
879 PM_saveDS();
880 PM_segread(&sregs);
881 pmisr.sel = sregs.cs;
882 pmisr.off = (uint)isr;
883 PM_restorePMvect(intno, pmisr);
884 }
885
886 void PMAPI PM_restorePMvect(int intno, PMFARPTR isr)
887 {
888 PMREGS regs;
889 PMSREGS sregs;
890
891 PM_segread(&sregs);
892 regs.x.ax = 0x2505; /* Set PM interrupt vector */
893 regs.x.cx = intno;
894 sregs.ds = isr.sel;
895 regs.e.edx = isr.off;
896 PM_int386x(0x21, &regs, &regs, &sregs);
897 }
898
899 static void getISR(int intno, PMFARPTR *pmisr, long *realisr)
900 {
901 PM_getPMvect(intno,pmisr);
902 _PM_getRMvect(intno,realisr);
903 }
904
905 static void restoreISR(int intno, PMFARPTR pmisr, long realisr)
906 {
907 PMREGS regs;
908 PMSREGS sregs;
909
910 PM_segread(&sregs);
911 regs.x.ax = 0x2507; /* Set real and PM vectors */
912 regs.x.cx = intno;
913 sregs.ds = pmisr.sel;
914 regs.e.edx = pmisr.off;
915 regs.e.ebx = realisr;
916 PM_int386x(0x21, &regs, &regs, &sregs);
917 }
918
919 static void setISR(int intno, void *isr)
920 {
921 PMREGS regs;
922 PMSREGS sregs;
923
924 lockPMHandlers(); /* Ensure our handlers are locked */
925
926 PM_segread(&sregs);
927 regs.x.ax = 0x2506; /* Hook real and protected vectors */
928 regs.x.cx = intno;
929 sregs.ds = sregs.cs;
930 regs.e.edx = (uint)isr;
931 PM_int386x(0x21, &regs, &regs, &sregs);
932 }
933
934 void PMAPI PM_setTimerHandler(PM_intHandler th)
935 {
936 getISR(0x8, &_PM_prevTimer, &_PM_prevRealTimer);
937 _PM_timerHandler = th;
938 setISR(0x8, _PM_timerISR);
939 }
940
941 void PMAPI PM_restoreTimerHandler(void)
942 {
943 if (_PM_timerHandler) {
944 restoreISR(0x8, _PM_prevTimer, _PM_prevRealTimer);
945 _PM_timerHandler = NULL;
946 }
947 }
948
949 ibool PMAPI PM_setRealTimeClockHandler(PM_intHandler th,int frequency)
950 {
951 /* Save the old CMOS real time clock values */
952 _PM_oldCMOSRegA = _PM_readCMOS(0x0A);
953 _PM_oldCMOSRegB = _PM_readCMOS(0x0B);
954
955 /* Set the real time clock interrupt handler */
956 getISR(0x70, &_PM_prevRTC, &_PM_prevRealRTC);
957 _PM_rtcHandler = th;
958 setISR(0x70, _PM_rtcISR);
959
960 /* Program the real time clock default frequency */
961 PM_setRealTimeClockFrequency(frequency);
962
963 /* Unmask IRQ8 in the PIC2 */
964 _PM_oldRTCPIC2 = PM_inpb(0xA1);
965 PM_outpb(0xA1,_PM_oldRTCPIC2 & 0xFE);
966 return true;
967 }
968
969 void PMAPI PM_restoreRealTimeClockHandler(void)
970 {
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));
976
977 /* Restore the interrupt vector */
978 restoreISR(0x70, _PM_prevRTC, _PM_prevRealRTC);
979 _PM_rtcHandler = NULL;
980 }
981 }
982
983 void PMAPI PM_setKeyHandler(PM_intHandler kh)
984 {
985 getISR(0x9, &_PM_prevKey, &_PM_prevRealKey);
986 _PM_keyHandler = kh;
987 setISR(0x9, _PM_keyISR);
988 }
989
990 void PMAPI PM_restoreKeyHandler(void)
991 {
992 if (_PM_keyHandler) {
993 restoreISR(0x9, _PM_prevKey, _PM_prevRealKey);
994 _PM_keyHandler = NULL;
995 }
996 }
997
998 void PMAPI PM_setKey15Handler(PM_key15Handler kh)
999 {
1000 getISR(0x15, &_PM_prevKey15, &_PM_prevRealKey15);
1001 _PM_key15Handler = kh;
1002 setISR(0x15, _PM_key15ISR);
1003 }
1004
1005 void PMAPI PM_restoreKey15Handler(void)
1006 {
1007 if (_PM_key15Handler) {
1008 restoreISR(0x15, _PM_prevKey15, _PM_prevRealKey15);
1009 _PM_key15Handler = NULL;
1010 }
1011 }
1012
1013 void PMAPI PM_installAltBreakHandler(PM_breakHandler bh)
1014 {
1015 static int ctrlCFlag,ctrlBFlag;
1016
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);
1024 }
1025
1026 void PMAPI PM_installBreakHandler(void)
1027 {
1028 PM_installAltBreakHandler(NULL);
1029 }
1030
1031 void PMAPI PM_restoreBreakHandler(void)
1032 {
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;
1038 }
1039 }
1040
1041 void PMAPI PM_installAltCriticalHandler(PM_criticalHandler ch)
1042 {
1043 static short critBuf[2];
1044
1045 _PM_critPtr = (uchar*)critBuf;
1046 getISR(0x24, &_PM_prevCritical, &prevRealCritical);
1047 _PM_critHandler = ch;
1048 setISR(0x24, _PM_criticalISR);
1049 }
1050
1051 void PMAPI PM_installCriticalHandler(void)
1052 {
1053 PM_installAltCriticalHandler(NULL);
1054 }
1055
1056 void PMAPI PM_restoreCriticalHandler(void)
1057 {
1058 if (_PM_prevCritical.sel) {
1059 restoreISR(0x24, _PM_prevCritical, prevRealCritical);
1060 _PM_prevCritical.sel = 0;
1061 _PM_critHandler = NULL;
1062 }
1063 }
1064
1065 int PMAPI PM_lockDataPages(void *p,uint len,PM_lockHandle *lh)
1066 {
1067 return (_x386_memlock(p,len) == 0);
1068 }
1069
1070 int PMAPI PM_unlockDataPages(void *p,uint len,PM_lockHandle *lh)
1071 {
1072 return (_x386_memunlock(p,len) == 0);
1073 }
1074
1075 int PMAPI PM_lockCodePages(void (*p)(),uint len,PM_lockHandle *lh)
1076 {
1077 return (_x386_memlock(p,len) == 0);
1078 }
1079
1080 int PMAPI PM_unlockCodePages(void (*p)(),uint len,PM_lockHandle *lh)
1081 {
1082 return (_x386_memunlock(p,len) == 0);
1083 }
1084
1085 #endif
1086
1087 /*-------------------------------------------------------------------------*/
1088 /* Borland's DPMI32 DOS Power Pack Extender support. */
1089 /*-------------------------------------------------------------------------*/
1090
1091 #ifdef DPMI32
1092 #define GENERIC_DPMI32 /* Use generic 32 bit DPMI routines */
1093
1094 void PMAPI PM_getPMvect(int intno, PMFARPTR *isr)
1095 {
1096 PMREGS regs;
1097
1098 regs.x.ax = 0x204;
1099 regs.h.bl = intno;
1100 PM_int386(0x31,&regs,&regs);
1101 isr->sel = regs.x.cx;
1102 isr->off = regs.e.edx;
1103 }
1104
1105 void PMAPI PM_setPMvect(int intno, PM_intHandler isr)
1106 {
1107 PMSREGS sregs;
1108 PMREGS regs;
1109
1110 PM_saveDS();
1111 regs.x.ax = 0x205; /* Set protected mode vector */
1112 regs.h.bl = intno;
1113 PM_segread(&sregs);
1114 regs.x.cx = sregs.cs;
1115 regs.e.edx = (uint)isr;
1116 PM_int386(0x31,&regs,&regs);
1117 }
1118
1119 void PMAPI PM_restorePMvect(int intno, PMFARPTR isr)
1120 {
1121 PMREGS regs;
1122
1123 regs.x.ax = 0x205;
1124 regs.h.bl = intno;
1125 regs.x.cx = isr.sel;
1126 regs.e.edx = isr.off;
1127 PM_int386(0x31,&regs,&regs);
1128 }
1129 #endif
1130
1131 /*-------------------------------------------------------------------------*/
1132 /* Watcom C/C++ with Rational DOS/4GW support. */
1133 /*-------------------------------------------------------------------------*/
1134
1135 #ifdef DOS4GW
1136 #define GENERIC_DPMI32 /* Use generic 32 bit DPMI routines */
1137
1138 #define MOUSE_SUPPORTED /* DOS4GW directly supports mouse */
1139
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.
1146 */
1147
1148 void PMAPI PM_getPMvect(int intno, PMFARPTR *isr)
1149 {
1150 PMREGS regs;
1151 PMSREGS sregs;
1152
1153 PM_segread(&sregs);
1154 regs.h.ah = 0x35;
1155 regs.h.al = intno;
1156 PM_int386x(0x21,&regs,&regs,&sregs);
1157 isr->sel = sregs.es;
1158 isr->off = regs.e.ebx;
1159 }
1160
1161 void PMAPI PM_setPMvect(int intno, PM_intHandler isr)
1162 {
1163 PMREGS regs;
1164 PMSREGS sregs;
1165
1166 PM_saveDS();
1167 PM_segread(&sregs);
1168 regs.h.ah = 0x25;
1169 regs.h.al = intno;
1170 sregs.ds = sregs.cs;
1171 regs.e.edx = (uint)isr;
1172 PM_int386x(0x21,&regs,&regs,&sregs);
1173 }
1174
1175 void PMAPI PM_restorePMvect(int intno, PMFARPTR isr)
1176 {
1177 PMREGS regs;
1178 PMSREGS sregs;
1179
1180 PM_segread(&sregs);
1181 regs.h.ah = 0x25;
1182 regs.h.al = intno;
1183 sregs.ds = isr.sel;
1184 regs.e.edx = isr.off;
1185 PM_int386x(0x21,&regs,&regs,&sregs);
1186 }
1187
1188 int PMAPI PM_setMouseHandler(int mask, PM_mouseHandler mh)
1189 {
1190 lockPMHandlers(); /* Ensure our handlers are locked */
1191
1192 _PM_mouseHandler = mh;
1193 _PM_setMouseHandler(_PM_mouseMask = mask);
1194 return 1;
1195 }
1196
1197 void PMAPI PM_restoreMouseHandler(void)
1198 {
1199 PMREGS regs;
1200
1201 if (_PM_mouseHandler) {
1202 regs.x.ax = 33;
1203 PM_int386(0x33, &regs, &regs);
1204 _PM_mouseHandler = NULL;
1205 }
1206 }
1207
1208 #endif
1209
1210 /*-------------------------------------------------------------------------*/
1211 /* DJGPP port of GNU C++ support. */
1212 /*-------------------------------------------------------------------------*/
1213
1214 #ifdef DJGPP
1215 #define GENERIC_DPMI32 /* Use generic 32 bit DPMI routines */
1216
1217 void PMAPI PM_getPMvect(int intno, PMFARPTR *isr)
1218 {
1219 PMREGS regs;
1220
1221 regs.x.ax = 0x204;
1222 regs.h.bl = intno;
1223 PM_int386(0x31,&regs,&regs);
1224 isr->sel = regs.x.cx;
1225 isr->off = regs.e.edx;
1226 }
1227
1228 void PMAPI PM_setPMvect(int intno, PM_intHandler isr)
1229 {
1230 PMSREGS sregs;
1231 PMREGS regs;
1232
1233 PM_saveDS();
1234 regs.x.ax = 0x205; /* Set protected mode vector */
1235 regs.h.bl = intno;
1236 PM_segread(&sregs);
1237 regs.x.cx = sregs.cs;
1238 regs.e.edx = (uint)isr;
1239 PM_int386(0x31,&regs,&regs);
1240 }
1241
1242 void PMAPI PM_restorePMvect(int intno, PMFARPTR isr)
1243 {
1244 PMREGS regs;
1245
1246 regs.x.ax = 0x205;
1247 regs.h.bl = intno;
1248 regs.x.cx = isr.sel;
1249 regs.e.edx = isr.off;
1250 PM_int386(0x31,&regs,&regs);
1251 }
1252
1253 #endif
1254
1255 /*-------------------------------------------------------------------------*/
1256 /* Generic 32 bit DPMI routines */
1257 /*-------------------------------------------------------------------------*/
1258
1259 #if defined(GENERIC_DPMI32)
1260
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 */
1264
1265 #ifndef MOUSE_SUPPORTED
1266
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.
1270 */
1271
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] */
1278 0xCB, /* retf */
1279 };
1280
1281 int PMAPI PM_setMouseHandler(int mask, PM_mouseHandler mh)
1282 {
1283 RMREGS regs;
1284 RMSREGS sregs;
1285 uint rseg,roff;
1286
1287 lockPMHandlers(); /* Ensure our handlers are locked */
1288
1289 /* Copy the real mode handler to real mode memory */
1290 if ((mousePtr = PM_allocRealSeg(sizeof(mouseHandler),&rseg,&roff)) == NULL)
1291 return 0;
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);
1296
1297 /* Install the real mode mouse handler */
1298 _PM_mouseHandler = mh;
1299 sregs.es = rseg;
1300 regs.x.dx = roff+4;
1301 regs.x.cx = _PM_mouseMask = mask;
1302 regs.x.ax = 0xC;
1303 PM_int86x(0x33, &regs, &regs, &sregs);
1304 return 1;
1305 }
1306
1307 void PMAPI PM_restoreMouseHandler(void)
1308 {
1309 RMREGS regs;
1310
1311 if (_PM_mouseHandler) {
1312 regs.x.ax = 33;
1313 PM_int86(0x33, &regs, &regs);
1314 PM_freeRealSeg(mousePtr);
1315 _DPMI_freeCallback(mouseRMCB);
1316 _PM_mouseHandler = NULL;
1317 }
1318 }
1319
1320 #endif
1321
1322 static void getISR(int intno, PMFARPTR *pmisr, long *realisr)
1323 {
1324 PM_getPMvect(intno,pmisr);
1325 _PM_getRMvect(intno,realisr);
1326 }
1327
1328 static void restoreISR(int intno, PMFARPTR pmisr, long realisr)
1329 {
1330 _PM_setRMvect(intno,realisr);
1331 PM_restorePMvect(intno,pmisr);
1332 }
1333
1334 static void setISR(int intno, void (* PMAPI pmisr)())
1335 {
1336 lockPMHandlers(); /* Ensure our handlers are locked */
1337 PM_setPMvect(intno,pmisr);
1338 }
1339
1340 void PMAPI PM_setTimerHandler(PM_intHandler th)
1341 {
1342 getISR(0x8, &_PM_prevTimer, &_PM_prevRealTimer);
1343 _PM_timerHandler = th;
1344 setISR(0x8, _PM_timerISR);
1345 }
1346
1347 void PMAPI PM_restoreTimerHandler(void)
1348 {
1349 if (_PM_timerHandler) {
1350 restoreISR(0x8, _PM_prevTimer, _PM_prevRealTimer);
1351 _PM_timerHandler = NULL;
1352 }
1353 }
1354
1355 ibool PMAPI PM_setRealTimeClockHandler(PM_intHandler th,int frequency)
1356 {
1357 /* Save the old CMOS real time clock values */
1358 _PM_oldCMOSRegA = _PM_readCMOS(0x0A);
1359 _PM_oldCMOSRegB = _PM_readCMOS(0x0B);
1360
1361 /* Set the real time clock interrupt handler */
1362 getISR(0x70, &_PM_prevRTC, &_PM_prevRealRTC);
1363 _PM_rtcHandler = th;
1364 setISR(0x70, _PM_rtcISR);
1365
1366 /* Program the real time clock default frequency */
1367 PM_setRealTimeClockFrequency(frequency);
1368
1369 /* Unmask IRQ8 in the PIC2 */
1370 _PM_oldRTCPIC2 = PM_inpb(0xA1);
1371 PM_outpb(0xA1,_PM_oldRTCPIC2 & 0xFE);
1372 return true;
1373 }
1374
1375 void PMAPI PM_restoreRealTimeClockHandler(void)
1376 {
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));
1382
1383 /* Restore the interrupt vector */
1384 restoreISR(0x70, _PM_prevRTC, _PM_prevRealRTC);
1385 _PM_rtcHandler = NULL;
1386 }
1387 }
1388
1389 PM_IRQHandle PMAPI PM_setIRQHandler(
1390 int IRQ,
1391 PM_irqHandler ih)
1392 {
1393 int thunkSize,PICmask,chainPrevious;
1394 ulong offsetAdjust;
1395 _PM_IRQHandle *handle;
1396
1397 thunkSize = (ulong)_PM_irqISRTemplateEnd - (ulong)_PM_irqISRTemplate;
1398 if ((handle = PM_malloc(sizeof(_PM_IRQHandle) + thunkSize)) == NULL)
1399 return NULL;
1400 handle->IRQ = IRQ;
1401 handle->prevPIC = PM_inpb(0x21);
1402 handle->prevPIC2 = PM_inpb(0xA1);
1403 if (IRQ < 8) {
1404 handle->IRQVect = (IRQ + 8);
1405 PICmask = (1 << IRQ);
1406 chainPrevious = ((handle->prevPIC & PICmask) == 0);
1407 }
1408 else {
1409 handle->IRQVect = (0x60 + IRQ + 8);
1410 PICmask = ((1 << IRQ) | 0x4);
1411 chainPrevious = ((handle->prevPIC2 & (PICmask >> 8)) == 0);
1412 }
1413
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;
1422 }
1423 else {
1424 *((ulong*)&handle->thunk[11+4]) = 0;
1425 *((ulong*)&handle->thunk[11+8]) = 0;
1426 }
1427 *((ulong*)&handle->thunk[11+12]) = IRQ;
1428
1429 /* Set the real time clock interrupt handler */
1430 getISR(handle->IRQVect, &handle->prevHandler, &handle->prevRealhandler);
1431 setISR(handle->IRQVect, (PM_intHandler)handle->thunk);
1432
1433 /* Unmask the IRQ in the PIC */
1434 PM_outpb(0xA1,handle->prevPIC2 & ~(PICmask >> 8));
1435 PM_outpb(0x21,handle->prevPIC & ~PICmask);
1436 return handle;
1437 }
1438
1439 void PMAPI PM_restoreIRQHandler(
1440 PM_IRQHandle irqHandle)
1441 {
1442 int PICmask;
1443 _PM_IRQHandle *handle = irqHandle;
1444
1445 /* Restore PIC mask for the interrupt */
1446 if (handle->IRQ < 8)
1447 PICmask = (1 << handle->IRQ);
1448 else
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));
1452
1453 /* Restore the interrupt vector */
1454 restoreISR(handle->IRQVect, handle->prevHandler, handle->prevRealhandler);
1455
1456 /* Finally free the thunk */
1457 PM_free(handle);
1458 }
1459
1460 void PMAPI PM_setKeyHandler(PM_intHandler kh)
1461 {
1462 getISR(0x9, &_PM_prevKey, &_PM_prevRealKey);
1463 _PM_keyHandler = kh;
1464 setISR(0x9, _PM_keyISR);
1465 }
1466
1467 void PMAPI PM_restoreKeyHandler(void)
1468 {
1469 if (_PM_keyHandler) {
1470 restoreISR(0x9, _PM_prevKey, _PM_prevRealKey);
1471 _PM_keyHandler = NULL;
1472 }
1473 }
1474
1475 void PMAPI PM_setKey15Handler(PM_key15Handler kh)
1476 {
1477 getISR(0x15, &_PM_prevKey15, &_PM_prevRealKey15);
1478 _PM_key15Handler = kh;
1479 setISR(0x15, _PM_key15ISR);
1480 }
1481
1482 void PMAPI PM_restoreKey15Handler(void)
1483 {
1484 if (_PM_key15Handler) {
1485 restoreISR(0x15, _PM_prevKey15, _PM_prevRealKey15);
1486 _PM_key15Handler = NULL;
1487 }
1488 }
1489
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.
1494 */
1495
1496 #ifndef DOS4GW
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 */
1501 0xCF, /* iretf */
1502 };
1503 #endif
1504
1505 void PMAPI PM_installAltBreakHandler(PM_breakHandler bh)
1506 {
1507 #ifndef DOS4GW
1508 uint rseg,roff;
1509 #else
1510 static int ctrlCFlag,ctrlBFlag;
1511
1512 _PM_ctrlCPtr = (uchar*)&ctrlCFlag;
1513 _PM_ctrlBPtr = (uchar*)&ctrlBFlag;
1514 #endif
1515
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);
1521
1522 #ifndef DOS4GW
1523 /* Hook the real mode vectors for these handlers, as these are not
1524 * normally reflected by the DPMI server up to protected mode
1525 */
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));
1532 #endif
1533 }
1534
1535 void PMAPI PM_installBreakHandler(void)
1536 {
1537 PM_installAltBreakHandler(NULL);
1538 }
1539
1540 void PMAPI PM_restoreBreakHandler(void)
1541 {
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;
1547 #ifndef DOS4GW
1548 PM_freeRealSeg(_PM_ctrlBPtr);
1549 #endif
1550 }
1551 }
1552
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.
1557 */
1558
1559 #ifndef DOS4GW
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 */
1566 0xCF, /* iretf */
1567 };
1568 #endif
1569
1570 void PMAPI PM_installAltCriticalHandler(PM_criticalHandler ch)
1571 {
1572 #ifndef DOS4GW
1573 uint rseg,roff;
1574 #else
1575 static short critBuf[2];
1576
1577 _PM_critPtr = (uchar*)critBuf;
1578 #endif
1579
1580 getISR(0x24, &_PM_prevCritical, &prevRealCritical);
1581 _PM_critHandler = ch;
1582 setISR(0x24, _PM_criticalISR);
1583
1584 #ifndef DOS4GW
1585 /* Hook the real mode vector, as this is not normally reflected by the
1586 * DPMI server up to protected mode.
1587 */
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));
1591 #endif
1592 }
1593
1594 void PMAPI PM_installCriticalHandler(void)
1595 {
1596 PM_installAltCriticalHandler(NULL);
1597 }
1598
1599 void PMAPI PM_restoreCriticalHandler(void)
1600 {
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;
1606 }
1607 }
1608
1609 int PMAPI PM_lockDataPages(void *p,uint len,PM_lockHandle *lh)
1610 {
1611 PMSREGS sregs;
1612 PM_segread(&sregs);
1613 return DPMI_lockLinearPages((uint)p + DPMI_getSelectorBase(sregs.ds),len);
1614 }
1615
1616 int PMAPI PM_unlockDataPages(void *p,uint len,PM_lockHandle *lh)
1617 {
1618 PMSREGS sregs;
1619 PM_segread(&sregs);
1620 return DPMI_unlockLinearPages((uint)p + DPMI_getSelectorBase(sregs.ds),len);
1621 }
1622
1623 int PMAPI PM_lockCodePages(void (*p)(),uint len,PM_lockHandle *lh)
1624 {
1625 PMSREGS sregs;
1626 PM_segread(&sregs);
1627 return DPMI_lockLinearPages((uint)p + DPMI_getSelectorBase(sregs.cs),len);
1628 }
1629
1630 int PMAPI PM_unlockCodePages(void (*p)(),uint len,PM_lockHandle *lh)
1631 {
1632 PMSREGS sregs;
1633 PM_segread(&sregs);
1634 return DPMI_unlockLinearPages((uint)p + DPMI_getSelectorBase(sregs.cs),len);
1635 }
1636
1637 #endif