Coding style cleanup
[platform/kernel/u-boot.git] / board / MAI / bios_emulator / scitech / src / pm / smx / pmsmx.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:  32-bit SMX embedded systems development
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 #include "smx/ps2mouse.h"
41
42 /*--------------------------- Global variables ----------------------------*/
43
44 static int  globalDataStart;
45
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;
55
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      */
74
75 /*----------------------------- Implementation ----------------------------*/
76
77 /* Globals for locking interrupt handlers in _pmsmx.asm */
78
79 extern int  _ASMAPI _PM_pmsmxDataStart;
80 extern int  _ASMAPI _PM_pmsmxDataEnd;
81 void _ASMAPI _PM_pmsmxCodeStart(void);
82 void _ASMAPI _PM_pmsmxCodeEnd(void);
83
84 /* Protected mode interrupt handlers, also called by PM callbacks below */
85
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);
95
96 /* Protected mode DPMI callback handlers */
97
98 void _ASMAPI _PM_mousePMCB(void);
99
100 /* Routine to install a mouse handler function */
101
102 void _ASMAPI _PM_setMouseHandler(int mask);
103
104 /* Routine to allocate DPMI real mode callback routines */
105
106 void _ASMAPI _DPMI_allocateCallback(void (_ASMAPI *pmcode)(),void *rmregs,long *RMCB);
107 void _ASMAPI _DPMI_freeCallback(long RMCB);
108
109 /* DPMI helper functions in PMLITE.C */
110
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);
119
120 /* Functions to read and write CMOS registers */
121
122 uchar   PMAPI _PM_readCMOS(int index);
123 void    PMAPI _PM_writeCMOS(int index,uchar value);
124
125 /*-------------------------------------------------------------------------*/
126 /* Generic routines common to all environments                             */
127 /*-------------------------------------------------------------------------*/
128
129 void PMAPI PM_resetMouseDriver(int hardReset)
130 {
131     ps2MouseReset();
132 }
133
134 void PMAPI PM_setRealTimeClockFrequency(int frequency)
135 {
136     static short convert[] = {
137         8192,
138         4096,
139         2048,
140         1024,
141         512,
142         256,
143         128,
144         64,
145         32,
146         16,
147         8,
148         4,
149         2,
150         -1,
151         };
152     int i;
153
154     /* First clear any pending RTC timeout if not cleared */
155     _PM_readCMOS(0x0C);
156     if (frequency == 0) {
157         /* Disable RTC timout */
158         _PM_writeCMOS(0x0A,_PM_oldCMOSRegA);
159         _PM_writeCMOS(0x0B,_PM_oldCMOSRegB & 0x0F);
160         }
161     else {
162         /* Convert frequency value to RTC clock indexes */
163         for (i = 0; convert[i] != -1; i++) {
164             if (convert[i] == frequency)
165                 break;
166             }
167
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);
171         }
172 }
173
174 static void PMAPI lockPMHandlers(void)
175 {
176     static int      locked = 0;
177     int             stat = 0;
178     PM_lockHandle   lh;
179
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
182      * under real mode.
183      */
184     if (!locked) {
185         PM_saveDS();
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);
189         if (stat) {
190             printf("Page locking services failed - interrupt handling not safe!\n");
191             exit(1);
192             }
193         locked = 1;
194         }
195 }
196
197 void PMAPI PM_getPMvect(int intno, PMFARPTR *isr)
198 {
199     PMREGS  regs;
200
201     regs.x.ax = 0x204;
202     regs.h.bl = intno;
203     PM_int386(0x31,&regs,&regs);
204     isr->sel = regs.x.cx;
205     isr->off = regs.e.edx;
206 }
207
208 void PMAPI PM_setPMvect(int intno, PM_intHandler isr)
209 {
210     PMSREGS sregs;
211     PMREGS  regs;
212
213     PM_saveDS();
214     regs.x.ax = 0x205;          /* Set protected mode vector        */
215     regs.h.bl = intno;
216     PM_segread(&sregs);
217     regs.x.cx = sregs.cs;
218     regs.e.edx = (uint)isr;
219     PM_int386(0x31,&regs,&regs);
220 }
221
222 void PMAPI PM_restorePMvect(int intno, PMFARPTR isr)
223 {
224     PMREGS  regs;
225
226     regs.x.ax = 0x205;
227     regs.h.bl = intno;
228     regs.x.cx = isr.sel;
229     regs.e.edx = isr.off;
230     PM_int386(0x31,&regs,&regs);
231 }
232
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      */
236
237 int PMAPI PM_setMouseHandler(int mask, PM_mouseHandler mh)
238 {
239     lockPMHandlers();           /* Ensure our handlers are locked   */
240
241     _PM_mouseHandler = mh;
242     return 0;
243 }
244
245 void PMAPI PM_restoreMouseHandler(void)
246 {
247     if (_PM_mouseHandler)
248         _PM_mouseHandler = NULL;
249 }
250
251 static void getISR(int intno, PMFARPTR *pmisr, long *realisr)
252 {
253     PM_getPMvect(intno,pmisr);
254 }
255
256 static void restoreISR(int intno, PMFARPTR pmisr, long realisr)
257 {
258     PM_restorePMvect(intno,pmisr);
259 }
260
261 static void setISR(int intno, void (* PMAPI pmisr)())
262 {
263     lockPMHandlers();           /* Ensure our handlers are locked   */
264     PM_setPMvect(intno,pmisr);
265 }
266
267 void PMAPI PM_setTimerHandler(PM_intHandler th)
268 {
269     getISR(PM_IRQ0, &_PM_prevTimer, &_PM_prevRealTimer);
270     _PM_timerHandler = th;
271     setISR(PM_IRQ0, _PM_timerISR);
272 }
273
274 void PMAPI PM_restoreTimerHandler(void)
275 {
276     if (_PM_timerHandler) {
277         restoreISR(PM_IRQ0, _PM_prevTimer, _PM_prevRealTimer);
278         _PM_timerHandler = NULL;
279         }
280 }
281
282 ibool PMAPI PM_setRealTimeClockHandler(PM_intHandler th,int frequency)
283 {
284     /* Save the old CMOS real time clock values */
285     _PM_oldCMOSRegA = _PM_readCMOS(0x0A);
286     _PM_oldCMOSRegB = _PM_readCMOS(0x0B);
287
288     /* Set the real time clock interrupt handler */
289     getISR(0x70, &_PM_prevRTC, &_PM_prevRealRTC);
290     _PM_rtcHandler = th;
291     setISR(0x70, _PM_rtcISR);
292
293     /* Program the real time clock default frequency */
294     PM_setRealTimeClockFrequency(frequency);
295
296     /* Unmask IRQ8 in the PIC2 */
297     _PM_oldRTCPIC2 = PM_inpb(0xA1);
298     PM_outpb(0xA1,_PM_oldRTCPIC2 & 0xFE);
299     return true;
300 }
301
302 void PMAPI PM_restoreRealTimeClockHandler(void)
303 {
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));
309
310         /* Restore the interrupt vector */
311         restoreISR(0x70, _PM_prevRTC, _PM_prevRealRTC);
312         _PM_rtcHandler = NULL;
313         }
314 }
315
316 void PMAPI PM_setKeyHandler(PM_intHandler kh)
317 {
318     getISR(PM_IRQ1, &_PM_prevKey, &_PM_prevRealKey);
319     _PM_keyHandler = kh;
320     setISR(PM_IRQ1, _PM_keyISR);
321 }
322
323 void PMAPI PM_restoreKeyHandler(void)
324 {
325     if (_PM_keyHandler) {
326         restoreISR(PM_IRQ1, _PM_prevKey, _PM_prevRealKey);
327         _PM_keyHandler = NULL;
328         }
329 }
330
331 void PMAPI PM_setKey15Handler(PM_key15Handler kh)
332 {
333     getISR(0x15, &_PM_prevKey15, &_PM_prevRealKey15);
334     _PM_key15Handler = kh;
335     setISR(0x15, _PM_key15ISR);
336 }
337
338 void PMAPI PM_restoreKey15Handler(void)
339 {
340     if (_PM_key15Handler) {
341         restoreISR(0x15, _PM_prevKey15, _PM_prevRealKey15);
342         _PM_key15Handler = NULL;
343         }
344 }
345
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.
350  */
351
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        */
356     0xCF,                           /*  iretf                           */
357     };
358
359 void PMAPI PM_installAltBreakHandler(PM_breakHandler bh)
360 {
361     uint    rseg,roff;
362
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);
368
369     /* Hook the real mode vectors for these handlers, as these are not
370      * normally reflected by the DPMI server up to protected mode
371      */
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));
378 }
379
380 void PMAPI PM_installBreakHandler(void)
381 {
382     PM_installAltBreakHandler(NULL);
383 }
384
385 void PMAPI PM_restoreBreakHandler(void)
386 {
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);
393         }
394 }
395
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.
400  */
401
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                    */
408     0xCF,                           /*  iretf                           */
409     };
410
411 void PMAPI PM_installAltCriticalHandler(PM_criticalHandler ch)
412 {
413     uint    rseg,roff;
414
415     getISR(0x24, &_PM_prevCritical, &prevRealCritical);
416     _PM_critHandler = ch;
417     setISR(0x24, _PM_criticalISR);
418
419     /* Hook the real mode vector, as this is not normally reflected by the
420      * DPMI server up to protected mode.
421      */
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));
425 }
426
427 void PMAPI PM_installCriticalHandler(void)
428 {
429     PM_installAltCriticalHandler(NULL);
430 }
431
432 void PMAPI PM_restoreCriticalHandler(void)
433 {
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;
439         }
440 }
441
442 int PMAPI PM_lockDataPages(void *p,uint len,PM_lockHandle *lh)
443 {
444     PMSREGS sregs;
445     PM_segread(&sregs);
446     return DPMI_lockLinearPages((uint)p + DPMI_getSelectorBase(sregs.ds),len);
447 }
448
449 int PMAPI PM_unlockDataPages(void *p,uint len,PM_lockHandle *lh)
450 {
451     PMSREGS sregs;
452     PM_segread(&sregs);
453     return DPMI_unlockLinearPages((uint)p + DPMI_getSelectorBase(sregs.ds),len);
454 }
455
456 int PMAPI PM_lockCodePages(void (*p)(),uint len,PM_lockHandle *lh)
457 {
458     PMSREGS sregs;
459     PM_segread(&sregs);
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);
464 }
465
466 int PMAPI PM_unlockCodePages(void (*p)(),uint len,PM_lockHandle *lh)
467 {
468     PMSREGS sregs;
469     PM_segread(&sregs);
470     return DPMI_unlockLinearPages((uint)p,len);
471 }