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: 32-bit SMX embedded systems development
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 ****************************************************************************/
40 #include "smx/ps2mouse.h"
42 /*--------------------------- Global variables ----------------------------*/
44 static int globalDataStart
;
46 PM_criticalHandler _VARAPI _PM_critHandler
= NULL
;
47 PM_breakHandler _VARAPI _PM_breakHandler
= NULL
;
48 PM_intHandler _VARAPI _PM_timerHandler
= NULL
;
49 PM_intHandler _VARAPI _PM_rtcHandler
= NULL
;
50 PM_intHandler _VARAPI _PM_keyHandler
= NULL
;
51 PM_key15Handler _VARAPI _PM_key15Handler
= NULL
;
52 PM_mouseHandler _VARAPI _PM_mouseHandler
= NULL
;
53 PM_intHandler _VARAPI _PM_int10Handler
= NULL
;
54 int _VARAPI _PM_mouseMask
;
56 uchar
* _VARAPI _PM_ctrlCPtr
; /* Location of Ctrl-C flag */
57 uchar
* _VARAPI _PM_ctrlBPtr
; /* Location of Ctrl-Break flag */
58 uchar
* _VARAPI _PM_critPtr
; /* Location of Critical error Bf*/
59 PMFARPTR _VARAPI _PM_prevTimer
= PMNULL
; /* Previous timer handler */
60 PMFARPTR _VARAPI _PM_prevRTC
= PMNULL
; /* Previous RTC handler */
61 PMFARPTR _VARAPI _PM_prevKey
= PMNULL
; /* Previous key handler */
62 PMFARPTR _VARAPI _PM_prevKey15
= PMNULL
; /* Previous key15 handler */
63 PMFARPTR _VARAPI _PM_prevBreak
= PMNULL
; /* Previous break handler */
64 PMFARPTR _VARAPI _PM_prevCtrlC
= PMNULL
; /* Previous CtrlC handler */
65 PMFARPTR _VARAPI _PM_prevCritical
= PMNULL
; /* Previous critical handler */
66 long _VARAPI _PM_prevRealTimer
; /* Previous real mode timer */
67 long _VARAPI _PM_prevRealRTC
; /* Previous real mode RTC */
68 long _VARAPI _PM_prevRealKey
; /* Previous real mode key */
69 long _VARAPI _PM_prevRealKey15
; /* Previous real mode key15 */
70 long _VARAPI _PM_prevRealInt10
; /* Previous real mode int 10h */
71 static uchar _PM_oldCMOSRegA
; /* CMOS register A contents */
72 static uchar _PM_oldCMOSRegB
; /* CMOS register B contents */
73 static uchar _PM_oldRTCPIC2
; /* Mask value for RTC IRQ8 */
75 /*----------------------------- Implementation ----------------------------*/
77 /* Globals for locking interrupt handlers in _pmsmx.asm */
79 extern int _ASMAPI _PM_pmsmxDataStart
;
80 extern int _ASMAPI _PM_pmsmxDataEnd
;
81 void _ASMAPI
_PM_pmsmxCodeStart(void);
82 void _ASMAPI
_PM_pmsmxCodeEnd(void);
84 /* Protected mode interrupt handlers, also called by PM callbacks below */
86 void _ASMAPI
_PM_timerISR(void);
87 void _ASMAPI
_PM_rtcISR(void);
88 void _ASMAPI
_PM_keyISR(void);
89 void _ASMAPI
_PM_key15ISR(void);
90 void _ASMAPI
_PM_breakISR(void);
91 void _ASMAPI
_PM_ctrlCISR(void);
92 void _ASMAPI
_PM_criticalISR(void);
93 void _ASMAPI
_PM_mouseISR(void);
94 void _ASMAPI
_PM_int10PMCB(void);
96 /* Protected mode DPMI callback handlers */
98 void _ASMAPI
_PM_mousePMCB(void);
100 /* Routine to install a mouse handler function */
102 void _ASMAPI
_PM_setMouseHandler(int mask
);
104 /* Routine to allocate DPMI real mode callback routines */
106 void _ASMAPI
_DPMI_allocateCallback(void (_ASMAPI
*pmcode
)(),void *rmregs
,long *RMCB
);
107 void _ASMAPI
_DPMI_freeCallback(long RMCB
);
109 /* DPMI helper functions in PMLITE.C */
111 ulong PMAPI
DPMI_mapPhysicalToLinear(ulong physAddr
,ulong limit
);
112 int PMAPI
DPMI_setSelectorBase(ushort sel
,ulong linAddr
);
113 ulong PMAPI
DPMI_getSelectorBase(ushort sel
);
114 int PMAPI
DPMI_setSelectorLimit(ushort sel
,ulong limit
);
115 uint PMAPI
DPMI_createSelector(ulong base
,ulong limit
);
116 void PMAPI
DPMI_freeSelector(uint sel
);
117 int PMAPI
DPMI_lockLinearPages(ulong linear
,ulong len
);
118 int PMAPI
DPMI_unlockLinearPages(ulong linear
,ulong len
);
120 /* Functions to read and write CMOS registers */
122 uchar PMAPI
_PM_readCMOS(int index
);
123 void PMAPI
_PM_writeCMOS(int index
,uchar value
);
125 /*-------------------------------------------------------------------------*/
126 /* Generic routines common to all environments */
127 /*-------------------------------------------------------------------------*/
129 void PMAPI
PM_resetMouseDriver(int hardReset
)
134 void PMAPI
PM_setRealTimeClockFrequency(int frequency
)
136 static short convert
[] = {
154 /* First clear any pending RTC timeout if not cleared */
156 if (frequency
== 0) {
157 /* Disable RTC timout */
158 _PM_writeCMOS(0x0A,_PM_oldCMOSRegA
);
159 _PM_writeCMOS(0x0B,_PM_oldCMOSRegB
& 0x0F);
162 /* Convert frequency value to RTC clock indexes */
163 for (i
= 0; convert
[i
] != -1; i
++) {
164 if (convert
[i
] == frequency
)
168 /* Set RTC timout value and enable timeout */
169 _PM_writeCMOS(0x0A,(_PM_oldCMOSRegA
& 0xF0) | (i
+3));
170 _PM_writeCMOS(0x0B,(_PM_oldCMOSRegB
& 0x0F) | 0x40);
174 static void PMAPI
lockPMHandlers(void)
176 static int locked
= 0;
180 /* Lock all of the code and data used by our protected mode interrupt
181 * handling routines, so that it will continue to work correctly
186 stat
= !PM_lockDataPages(&globalDataStart
-2048,4096,&lh
);
187 stat
|= !PM_lockDataPages(&_PM_pmsmxDataStart
,(int)&_PM_pmsmxDataEnd
- (int)&_PM_pmsmxDataStart
,&lh
);
188 stat
|= !PM_lockCodePages((__codePtr
)_PM_pmsmxCodeStart
,(int)_PM_pmsmxCodeEnd
-(int)_PM_pmsmxCodeStart
,&lh
);
190 printf("Page locking services failed - interrupt handling not safe!\n");
197 void PMAPI
PM_getPMvect(int intno
, PMFARPTR
*isr
)
203 PM_int386(0x31,®s
,®s
);
204 isr
->sel
= regs
.x
.cx
;
205 isr
->off
= regs
.e
.edx
;
208 void PMAPI
PM_setPMvect(int intno
, PM_intHandler isr
)
214 regs
.x
.ax
= 0x205; /* Set protected mode vector */
217 regs
.x
.cx
= sregs
.cs
;
218 regs
.e
.edx
= (uint
)isr
;
219 PM_int386(0x31,®s
,®s
);
222 void PMAPI
PM_restorePMvect(int intno
, PMFARPTR isr
)
229 regs
.e
.edx
= isr
.off
;
230 PM_int386(0x31,®s
,®s
);
233 static long prevRealBreak
; /* Previous real mode break handler */
234 static long prevRealCtrlC
; /* Previous real mode CtrlC handler */
235 static long prevRealCritical
; /* Prev real mode critical handler */
237 int PMAPI
PM_setMouseHandler(int mask
, PM_mouseHandler mh
)
239 lockPMHandlers(); /* Ensure our handlers are locked */
241 _PM_mouseHandler
= mh
;
245 void PMAPI
PM_restoreMouseHandler(void)
247 if (_PM_mouseHandler
)
248 _PM_mouseHandler
= NULL
;
251 static void getISR(int intno
, PMFARPTR
*pmisr
, long *realisr
)
253 PM_getPMvect(intno
,pmisr
);
256 static void restoreISR(int intno
, PMFARPTR pmisr
, long realisr
)
258 PM_restorePMvect(intno
,pmisr
);
261 static void setISR(int intno
, void (* PMAPI pmisr
)())
263 lockPMHandlers(); /* Ensure our handlers are locked */
264 PM_setPMvect(intno
,pmisr
);
267 void PMAPI
PM_setTimerHandler(PM_intHandler th
)
269 getISR(PM_IRQ0
, &_PM_prevTimer
, &_PM_prevRealTimer
);
270 _PM_timerHandler
= th
;
271 setISR(PM_IRQ0
, _PM_timerISR
);
274 void PMAPI
PM_restoreTimerHandler(void)
276 if (_PM_timerHandler
) {
277 restoreISR(PM_IRQ0
, _PM_prevTimer
, _PM_prevRealTimer
);
278 _PM_timerHandler
= NULL
;
282 ibool PMAPI
PM_setRealTimeClockHandler(PM_intHandler th
,int frequency
)
284 /* Save the old CMOS real time clock values */
285 _PM_oldCMOSRegA
= _PM_readCMOS(0x0A);
286 _PM_oldCMOSRegB
= _PM_readCMOS(0x0B);
288 /* Set the real time clock interrupt handler */
289 getISR(0x70, &_PM_prevRTC
, &_PM_prevRealRTC
);
291 setISR(0x70, _PM_rtcISR
);
293 /* Program the real time clock default frequency */
294 PM_setRealTimeClockFrequency(frequency
);
296 /* Unmask IRQ8 in the PIC2 */
297 _PM_oldRTCPIC2
= PM_inpb(0xA1);
298 PM_outpb(0xA1,_PM_oldRTCPIC2
& 0xFE);
302 void PMAPI
PM_restoreRealTimeClockHandler(void)
304 if (_PM_rtcHandler
) {
305 /* Restore CMOS registers and mask RTC clock */
306 _PM_writeCMOS(0x0A,_PM_oldCMOSRegA
);
307 _PM_writeCMOS(0x0B,_PM_oldCMOSRegB
);
308 PM_outpb(0xA1,(PM_inpb(0xA1) & 0xFE) | (_PM_oldRTCPIC2
& ~0xFE));
310 /* Restore the interrupt vector */
311 restoreISR(0x70, _PM_prevRTC
, _PM_prevRealRTC
);
312 _PM_rtcHandler
= NULL
;
316 void PMAPI
PM_setKeyHandler(PM_intHandler kh
)
318 getISR(PM_IRQ1
, &_PM_prevKey
, &_PM_prevRealKey
);
320 setISR(PM_IRQ1
, _PM_keyISR
);
323 void PMAPI
PM_restoreKeyHandler(void)
325 if (_PM_keyHandler
) {
326 restoreISR(PM_IRQ1
, _PM_prevKey
, _PM_prevRealKey
);
327 _PM_keyHandler
= NULL
;
331 void PMAPI
PM_setKey15Handler(PM_key15Handler kh
)
333 getISR(0x15, &_PM_prevKey15
, &_PM_prevRealKey15
);
334 _PM_key15Handler
= kh
;
335 setISR(0x15, _PM_key15ISR
);
338 void PMAPI
PM_restoreKey15Handler(void)
340 if (_PM_key15Handler
) {
341 restoreISR(0x15, _PM_prevKey15
, _PM_prevRealKey15
);
342 _PM_key15Handler
= NULL
;
346 /* Real mode Ctrl-C and Ctrl-Break handler. This handler simply sets a
347 * flag in the real mode code segment and exit. We save the location
348 * of this flag in real mode memory so that both the real mode and
349 * protected mode code will be modifying the same flags.
352 static uchar ctrlHandler
[] = {
353 0x00,0x00,0x00,0x00, /* ctrlBFlag */
354 0x66,0x2E,0xC7,0x06,0x00,0x00,
355 0x01,0x00,0x00,0x00, /* mov [cs:ctrlBFlag],1 */
359 void PMAPI
PM_installAltBreakHandler(PM_breakHandler bh
)
363 getISR(0x1B, &_PM_prevBreak
, &prevRealBreak
);
364 getISR(0x23, &_PM_prevCtrlC
, &prevRealCtrlC
);
365 _PM_breakHandler
= bh
;
366 setISR(0x1B, _PM_breakISR
);
367 setISR(0x23, _PM_ctrlCISR
);
369 /* Hook the real mode vectors for these handlers, as these are not
370 * normally reflected by the DPMI server up to protected mode
372 _PM_ctrlBPtr
= PM_allocRealSeg(sizeof(ctrlHandler
)*2, &rseg
, &roff
);
373 memcpy(_PM_ctrlBPtr
,ctrlHandler
,sizeof(ctrlHandler
));
374 memcpy(_PM_ctrlBPtr
+sizeof(ctrlHandler
),ctrlHandler
,sizeof(ctrlHandler
));
375 _PM_ctrlCPtr
= _PM_ctrlBPtr
+ sizeof(ctrlHandler
);
376 _PM_setRMvect(0x1B,((long)rseg
<< 16) | (roff
+4));
377 _PM_setRMvect(0x23,((long)rseg
<< 16) | (roff
+sizeof(ctrlHandler
)+4));
380 void PMAPI
PM_installBreakHandler(void)
382 PM_installAltBreakHandler(NULL
);
385 void PMAPI
PM_restoreBreakHandler(void)
387 if (_PM_prevBreak
.sel
) {
388 restoreISR(0x1B, _PM_prevBreak
, prevRealBreak
);
389 restoreISR(0x23, _PM_prevCtrlC
, prevRealCtrlC
);
390 _PM_prevBreak
.sel
= 0;
391 _PM_breakHandler
= NULL
;
392 PM_freeRealSeg(_PM_ctrlBPtr
);
396 /* Real mode Critical Error handler. This handler simply saves the AX and
397 * DI values in the real mode code segment and exits. We save the location
398 * of this flag in real mode memory so that both the real mode and
399 * protected mode code will be modifying the same flags.
402 static uchar criticalHandler
[] = {
403 0x00,0x00, /* axCode */
404 0x00,0x00, /* diCode */
405 0x2E,0xA3,0x00,0x00, /* mov [cs:axCode],ax */
406 0x2E,0x89,0x3E,0x02,0x00, /* mov [cs:diCode],di */
407 0xB8,0x03,0x00, /* mov ax,3 */
411 void PMAPI
PM_installAltCriticalHandler(PM_criticalHandler ch
)
415 getISR(0x24, &_PM_prevCritical
, &prevRealCritical
);
416 _PM_critHandler
= ch
;
417 setISR(0x24, _PM_criticalISR
);
419 /* Hook the real mode vector, as this is not normally reflected by the
420 * DPMI server up to protected mode.
422 _PM_critPtr
= PM_allocRealSeg(sizeof(criticalHandler
)*2, &rseg
, &roff
);
423 memcpy(_PM_critPtr
,criticalHandler
,sizeof(criticalHandler
));
424 _PM_setRMvect(0x24,((long)rseg
<< 16) | (roff
+4));
427 void PMAPI
PM_installCriticalHandler(void)
429 PM_installAltCriticalHandler(NULL
);
432 void PMAPI
PM_restoreCriticalHandler(void)
434 if (_PM_prevCritical
.sel
) {
435 restoreISR(0x24, _PM_prevCritical
, prevRealCritical
);
436 PM_freeRealSeg(_PM_critPtr
);
437 _PM_prevCritical
.sel
= 0;
438 _PM_critHandler
= NULL
;
442 int PMAPI
PM_lockDataPages(void *p
,uint len
,PM_lockHandle
*lh
)
446 return DPMI_lockLinearPages((uint
)p
+ DPMI_getSelectorBase(sregs
.ds
),len
);
449 int PMAPI
PM_unlockDataPages(void *p
,uint len
,PM_lockHandle
*lh
)
453 return DPMI_unlockLinearPages((uint
)p
+ DPMI_getSelectorBase(sregs
.ds
),len
);
456 int PMAPI
PM_lockCodePages(void (*p
)(),uint len
,PM_lockHandle
*lh
)
460 /*AM: causes minor glitch with */
461 /*AM: older versions pmEasy which don't allow DPMI 06 on */
462 /*AM: Code selector 0x0C -- assume base is 0 which it should be. */
463 return DPMI_lockLinearPages((uint
)p
,len
);
466 int PMAPI
PM_unlockCodePages(void (*p
)(),uint len
,PM_lockHandle
*lh
)
470 return DPMI_unlockLinearPages((uint
)p
,len
);