]> git.ipfire.org Git - people/ms/u-boot.git/blame - board/MAI/bios_emulator/scitech/src/pm/smx/_pmsmx.asm
USB: This patch fix readl in ohci swap reg access.
[people/ms/u-boot.git] / board / MAI / bios_emulator / scitech / src / pm / smx / _pmsmx.asm
CommitLineData
c7de829c
WD
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: 80386 Assembler, TASM 4.0 or NASM
25;* Environment: 32-bit SMX embedded systems development
26;*
27;* Description: Low level assembly support for the PM library specific to
28;* SMX interrupt handling.
29;*
30;****************************************************************************
31
32 IDEAL
33
34include "scitech.mac" ; Memory model macros
35
36header _pmsmx ; Set up memory model
37
38; Define the size of our local stacks. For real mode code they cant be
39; that big, but for 32 bit protected mode code we can make them nice and
40; large so that complex C functions can be used.
41
42MOUSE_STACK EQU 4096
43TIMER_STACK EQU 4096
44KEY_STACK EQU 1024
45INT10_STACK EQU 1024
46
47ifdef USE_NASM
48
49; Macro to load DS and ES registers with correct value.
50
51%imacro LOAD_DS 0
52 mov ds,[cs:_PM_savedDS]
53 mov es,[cs:_PM_savedDS]
54%endmacro
55
56; Note that interrupts we disable interrupts during the following stack
57; %imacro for correct operation, but we do not enable them again. Normally
58; these %imacros are used within interrupt handlers so interrupts should
59; already be off. We turn them back on explicitly later if the user code
60; needs them to be back on.
61
62; Macro to switch to a new local stack.
63
64%imacro NEWSTK 1
65 cli
66 mov [seg_%1],ss
67 mov [ptr_%1],_sp
68 mov [TempSeg],ds
69 mov ss,[TempSeg]
70 mov _sp,offset %1
71%endmacro
72
73; %imacro to switch back to the old stack.
74
75%imacro RESTSTK 1
76 cli
77 mov ss,[seg_%1]
78 mov _sp,[ptr_%1]
79%endmacro
80
81; %imacro to swap the current stack with the one saved away.
82
83%imacro SWAPSTK 1
84 cli
85 mov ax,ss
86 xchg ax,[seg_%1]
87 mov ss,ax
88 xchg _sp,[ptr_%1]
89%endmacro
90
91else
92
93; Macro to load DS and ES registers with correct value.
94
95MACRO LOAD_DS
96 mov ds,[cs:_PM_savedDS]
97 mov es,[cs:_PM_savedDS]
98ENDM
99
100; Note that interrupts we disable interrupts during the following stack
101; macro for correct operation, but we do not enable them again. Normally
102; these macros are used within interrupt handlers so interrupts should
103; already be off. We turn them back on explicitly later if the user code
104; needs them to be back on.
105
106; Macro to switch to a new local stack.
107
108MACRO NEWSTK stkname
109 cli
110 mov [seg_&stkname&],ss
111 mov [ptr_&stkname&],_sp
112 mov [TempSeg],ds
113 mov ss,[TempSeg]
114 mov _sp,offset stkname
115ENDM
116
117; Macro to switch back to the old stack.
118
119MACRO RESTSTK stkname
120 cli
121 mov ss,[seg_&stkname&]
122 mov _sp,[ptr_&stkname&]
123ENDM
124
125; Macro to swap the current stack with the one saved away.
126
127MACRO SWAPSTK stkname
128 cli
129 mov ax,ss
130 xchg ax,[seg_&stkname&]
131 mov ss,ax
132 xchg _sp,[ptr_&stkname&]
133ENDM
134
135endif
136
137begdataseg _pmsmx
138
139 cextern _PM_savedDS,USHORT
140 cextern _PM_critHandler,CPTR
141 cextern _PM_breakHandler,CPTR
142 cextern _PM_timerHandler,CPTR
143 cextern _PM_rtcHandler,CPTR
144 cextern _PM_keyHandler,CPTR
145 cextern _PM_key15Handler,CPTR
146 cextern _PM_mouseHandler,CPTR
147 cextern _PM_int10Handler,CPTR
148
149 cextern _PM_ctrlCPtr,DPTR
150 cextern _PM_ctrlBPtr,DPTR
151 cextern _PM_critPtr,DPTR
152
153 cextern _PM_prevTimer,FCPTR
154 cextern _PM_prevRTC,FCPTR
155 cextern _PM_prevKey,FCPTR
156 cextern _PM_prevKey15,FCPTR
157 cextern _PM_prevBreak,FCPTR
158 cextern _PM_prevCtrlC,FCPTR
159 cextern _PM_prevCritical,FCPTR
160 cextern _PM_prevRealTimer,ULONG
161 cextern _PM_prevRealRTC,ULONG
162 cextern _PM_prevRealKey,ULONG
163 cextern _PM_prevRealKey15,ULONG
164 cextern _PM_prevRealInt10,ULONG
165
166cpublic _PM_pmsmxDataStart
167
168; Allocate space for all of the local stacks that we need. These stacks
169; are not very large, but should be large enough for most purposes
170; (generally you want to handle these interrupts quickly, simply storing
171; the information for later and then returning). If you need bigger
172; stacks then change the appropriate value in here.
173
174 ALIGN 4
175 dclb MOUSE_STACK ; Space for local stack (small)
176MsStack: ; Stack starts at end!
177ptr_MsStack DUINT 0 ; Place to store old stack offset
178seg_MsStack dw 0 ; Place to store old stack segment
179
180 ALIGN 4
181 dclb INT10_STACK ; Space for local stack (small)
182Int10Stack: ; Stack starts at end!
183ptr_Int10Stack DUINT 0 ; Place to store old stack offset
184seg_Int10Stack dw 0 ; Place to store old stack segment
185
186 ALIGN 4
187 dclb TIMER_STACK ; Space for local stack (small)
188TmStack: ; Stack starts at end!
189ptr_TmStack DUINT 0 ; Place to store old stack offset
190seg_TmStack dw 0 ; Place to store old stack segment
191
192 ALIGN 4
193 dclb TIMER_STACK ; Space for local stack (small)
194RtcStack: ; Stack starts at end!
195ptr_RtcStack DUINT 0 ; Place to store old stack offset
196seg_RtcStack dw 0 ; Place to store old stack segment
197RtcInside dw 0 ; Are we still handling current interrupt
198
199 ALIGN 4
200 dclb KEY_STACK ; Space for local stack (small)
201KyStack: ; Stack starts at end!
202ptr_KyStack DUINT 0 ; Place to store old stack offset
203seg_KyStack dw 0 ; Place to store old stack segment
204KyInside dw 0 ; Are we still handling current interrupt
205
206 ALIGN 4
207 dclb KEY_STACK ; Space for local stack (small)
208Ky15Stack: ; Stack starts at end!
209ptr_Ky15Stack DUINT 0 ; Place to store old stack offset
210seg_Ky15Stack dw 0 ; Place to store old stack segment
211
212TempSeg dw 0 ; Place to store stack segment
213
214cpublic _PM_pmsmxDataEnd
215
216enddataseg _pmsmx
217
218begcodeseg _pmsmx ; Start of code segment
219
220cpublic _PM_pmsmxCodeStart
221
222;----------------------------------------------------------------------------
223; PM_mouseISR - Mouse interrupt subroutine dispatcher
224;----------------------------------------------------------------------------
225; Interrupt subroutine called by the mouse driver upon interrupts, to
226; dispatch control to high level C based subroutines. Interrupts are on
227; when we call the user code.
228;
229; It is _extremely_ important to save the state of the extended registers
230; as these may well be trashed by the routines called from here and not
231; restored correctly by the mouse interface module.
232;
233; NOTE: This routine switches to a local stack before calling any C code,
234; and hence is _not_ re-entrant. For mouse handlers this is not a
235; problem, as the mouse driver arbitrates calls to the user mouse
236; handler for us.
237;
238; Entry: AX - Condition mask giving reason for call
239; BX - Mouse button state
240; CX - Horizontal cursor coordinate
241; DX - Vertical cursor coordinate
242; SI - Horizontal mickey value
243; DI - Vertical mickey value
244;
245;----------------------------------------------------------------------------
246cprocfar _PM_mouseISR
247
248 push ds ; Save value of DS
249 push es
250 pushad ; Save _all_ extended registers
251 cld ; Clear direction flag
252
253 LOAD_DS ; Load DS register
254 NEWSTK MsStack ; Switch to local stack
255
256; Call the installed high level C code routine
257
258 clrhi dx ; Clear out high order values
259 clrhi cx
260 clrhi bx
261 clrhi ax
262 sgnhi si
263 sgnhi di
264
265 push _di
266 push _si
267 push _dx
268 push _cx
269 push _bx
270 push _ax
271 sti ; Enable interrupts
272 call [CPTR _PM_mouseHandler]
273 _add sp,12,24
274
275 RESTSTK MsStack ; Restore previous stack
276
277 popad ; Restore all extended registers
278 pop es
279 pop ds
280 ret ; We are done!!
281
282cprocend
283
284;----------------------------------------------------------------------------
285; PM_timerISR - Timer interrupt subroutine dispatcher
286;----------------------------------------------------------------------------
287; Hardware interrupt handler for the timer interrupt, to dispatch control
288; to high level C based subroutines. We save the state of all registers
289; in this routine, and switch to a local stack. Interrupts are *off*
290; when we call the user code.
291;
292; NOTE: This routine switches to a local stack before calling any C code,
293; and hence is _not_ re-entrant. Make sure your C code executes as
294; quickly as possible, since a timer overrun will simply hang the
295; system.
296;----------------------------------------------------------------------------
297cprocfar _PM_timerISR
298
299 push ds ; Save value of DS
300 push es
301 pushad ; Save _all_ extended registers
302 cld ; Clear direction flag
303
304 LOAD_DS ; Load DS register
305
306 NEWSTK TmStack ; Switch to local stack
307 call [CPTR _PM_timerHandler]
308 RESTSTK TmStack ; Restore previous stack
309
310 popad ; Restore all extended registers
311 pop es
312 pop ds
313 iret ; Return from interrupt
314
315cprocend
316
317;----------------------------------------------------------------------------
318; PM_chainPrevTimer - Chain to previous timer interrupt and return
319;----------------------------------------------------------------------------
320; Chains to the previous timer interrupt routine and returns control
321; back to the high level interrupt handler.
322;----------------------------------------------------------------------------
323cprocstart PM_chainPrevTimer
324
325ifdef TNT
326 push eax
327 push ebx
328 push ecx
329 pushfd ; Push flags on stack to simulate interrupt
330 mov ax,250Eh ; Call real mode procedure function
331 mov ebx,[_PM_prevRealTimer]
332 mov ecx,1 ; Copy real mode flags to real mode stack
333 int 21h ; Call the real mode code
334 popfd
335 pop ecx
336 pop ebx
337 pop eax
338 ret
339else
340 SWAPSTK TmStack ; Swap back to previous stack
341 pushf ; Save state of interrupt flag
342 pushf ; Push flags on stack to simulate interrupt
343ifdef USE_NASM
344 call far dword [_PM_prevTimer]
345else
346 call [_PM_prevTimer]
347endif
348 popf ; Restore state of interrupt flag
349 SWAPSTK TmStack ; Swap back to C stack again
350 ret
351endif
352
353cprocend
354
355; Macro to delay briefly to ensure that enough time has elapsed between
356; successive I/O accesses so that the device being accessed can respond
357; to both accesses even on a very fast PC.
358
359ifdef USE_NASM
360%macro DELAY 0
361 jmp short $+2
362 jmp short $+2
363 jmp short $+2
364%endmacro
365%macro IODELAYN 1
366%rep %1
367 DELAY
368%endrep
369%endmacro
370else
371macro DELAY
372 jmp short $+2
373 jmp short $+2
374 jmp short $+2
375endm
376macro IODELAYN N
377 rept N
378 DELAY
379 endm
380endm
381endif
382
383;----------------------------------------------------------------------------
384; PM_rtcISR - Real time clock interrupt subroutine dispatcher
385;----------------------------------------------------------------------------
386; Hardware interrupt handler for the timer interrupt, to dispatch control
387; to high level C based subroutines. We save the state of all registers
388; in this routine, and switch to a local stack. Interrupts are *off*
389; when we call the user code.
390;
391; NOTE: This routine switches to a local stack before calling any C code,
392; and hence is _not_ re-entrant. Make sure your C code executes as
393; quickly as possible, since a timer overrun will simply hang the
394; system.
395;----------------------------------------------------------------------------
396cprocfar _PM_rtcISR
397
398 push ds ; Save value of DS
399 push es
400 pushad ; Save _all_ extended registers
401 cld ; Clear direction flag
402
403; Clear priority interrupt controller and re-enable interrupts so we
404; dont lock things up for long.
405
406 mov al,20h
407 out 0A0h,al
408 out 020h,al
409
410; Clear real-time clock timeout
411
412 in al,70h ; Read CMOS index register
413 push _ax ; and save for later
414 IODELAYN 3
415 mov al,0Ch
416 out 70h,al
417 IODELAYN 5
418 in al,71h
419
420; Call the C interrupt handler function
421
422 LOAD_DS ; Load DS register
423 cmp [BYTE RtcInside],1 ; Check for mutual exclusion
424 je @@Exit
425 mov [BYTE RtcInside],1
426 sti ; Re-enable interrupts
427 NEWSTK RtcStack ; Switch to local stack
428 call [CPTR _PM_rtcHandler]
429 RESTSTK RtcStack ; Restore previous stack
430 mov [BYTE RtcInside],0
431
432@@Exit: pop _ax
433 out 70h,al ; Restore CMOS index register
434 popad ; Restore all extended registers
435 pop es
436 pop ds
437 iret ; Return from interrupt
438
439cprocend
440
441;----------------------------------------------------------------------------
442; PM_keyISR - keyboard interrupt subroutine dispatcher
443;----------------------------------------------------------------------------
444; Hardware interrupt handler for the keyboard interrupt, to dispatch control
445; to high level C based subroutines. We save the state of all registers
446; in this routine, and switch to a local stack. Interrupts are *off*
447; when we call the user code.
448;
449; NOTE: This routine switches to a local stack before calling any C code,
450; and hence is _not_ re-entrant. However we ensure within this routine
451; mutual exclusion to the keyboard handling routine.
452;----------------------------------------------------------------------------
453cprocfar _PM_keyISR
454
455 push ds ; Save value of DS
456 push es
457 pushad ; Save _all_ extended registers
458 cld ; Clear direction flag
459
460 LOAD_DS ; Load DS register
461
462 cmp [BYTE KyInside],1 ; Check for mutual exclusion
463 je @@Reissued
464
465 mov [BYTE KyInside],1
466 NEWSTK KyStack ; Switch to local stack
467 call [CPTR _PM_keyHandler] ; Call C code
468 RESTSTK KyStack ; Restore previous stack
469 mov [BYTE KyInside],0
470
471@@Exit: popad ; Restore all extended registers
472 pop es
473 pop ds
474 iret ; Return from interrupt
475
476; When the BIOS keyboard handler needs to change the SHIFT status lights
477; on the keyboard, in the process of doing this the keyboard controller
478; re-issues another interrupt, while the current handler is still executing.
479; If we recieve another interrupt while still handling the current one,
480; then simply chain directly to the previous handler.
481;
482; Note that for most DOS extenders, the real mode interrupt handler that we
483; install takes care of this for us.
484
485@@Reissued:
486ifdef TNT
487 push eax
488 push ebx
489 push ecx
490 pushfd ; Push flags on stack to simulate interrupt
491 mov ax,250Eh ; Call real mode procedure function
492 mov ebx,[_PM_prevRealKey]
493 mov ecx,1 ; Copy real mode flags to real mode stack
494 int 21h ; Call the real mode code
495 popfd
496 pop ecx
497 pop ebx
498 pop eax
499else
500 pushf
501ifdef USE_NASM
502 call far dword [_PM_prevKey]
503else
504 call [_PM_prevKey]
505endif
506endif
507 jmp @@Exit
508
509cprocend
510
511;----------------------------------------------------------------------------
512; PM_chainPrevkey - Chain to previous key interrupt and return
513;----------------------------------------------------------------------------
514; Chains to the previous key interrupt routine and returns control
515; back to the high level interrupt handler.
516;----------------------------------------------------------------------------
517cprocstart PM_chainPrevKey
518
519ifdef TNT
520 push eax
521 push ebx
522 push ecx
523 pushfd ; Push flags on stack to simulate interrupt
524 mov ax,250Eh ; Call real mode procedure function
525 mov ebx,[_PM_prevRealKey]
526 mov ecx,1 ; Copy real mode flags to real mode stack
527 int 21h ; Call the real mode code
528 popfd
529 pop ecx
530 pop ebx
531 pop eax
532 ret
533else
534
535; YIKES! For some strange reason, when execution returns from the
536; previous keyboard handler, interrupts are re-enabled!! Since we expect
537; interrupts to remain off during the duration of our handler, this can
538; cause havoc. However our stack macros always turn off interrupts, so they
539; will be off when we exit this routine. Obviously there is a tiny weeny
540; window when interrupts will be enabled, but there is nothing we can
541; do about this.
542
543 SWAPSTK KyStack ; Swap back to previous stack
544 pushf ; Push flags on stack to simulate interrupt
545ifdef USE_NASM
546 call far dword [_PM_prevKey]
547else
548 call [_PM_prevKey]
549endif
550 SWAPSTK KyStack ; Swap back to C stack again
551 ret
552endif
553
554cprocend
555
556;----------------------------------------------------------------------------
557; PM_key15ISR - Int 15h keyboard interrupt subroutine dispatcher
558;----------------------------------------------------------------------------
559; This routine gets called if we have been called to handle the Int 15h
560; keyboard interrupt callout from real mode.
561;
562; Entry: AX - Hardware scan code to process
563; Exit: AX - Hardware scan code to process (0 to ignore)
564;----------------------------------------------------------------------------
565cprocfar _PM_key15ISR
566
567 push ds
568 push es
569 LOAD_DS
570 cmp ah,4Fh
571 jnz @@NotOurs ; Quit if not keyboard callout
572
573 pushad
574 cld ; Clear direction flag
575 xor ah,ah ; AX := scan code
576 NEWSTK Ky15Stack ; Switch to local stack
577 push _ax
578 call [CPTR _PM_key15Handler] ; Call C code
579 _add sp,2,4
580 RESTSTK Ky15Stack ; Restore previous stack
581 test ax,ax
582 jz @@1
583 stc ; Set carry to process as normal
584 jmp @@2
585@@1: clc ; Clear carry to ignore scan code
586@@2: popad
587 jmp @@Exit ; We are done
588
589@@NotOurs:
590ifdef TNT
591 push eax
592 push ebx
593 push ecx
594 pushfd ; Push flags on stack to simulate interrupt
595 mov ax,250Eh ; Call real mode procedure function
596 mov ebx,[_PM_prevRealKey15]
597 mov ecx,1 ; Copy real mode flags to real mode stack
598 int 21h ; Call the real mode code
599 popfd
600 pop ecx
601 pop ebx
602 pop eax
603else
604 pushf
605ifdef USE_NASM
606 call far dword [_PM_prevKey15]
607else
608 call [_PM_prevKey15]
609endif
610endif
611@@Exit: pop es
612 pop ds
613 retf 4
614
615cprocend
616
617;----------------------------------------------------------------------------
618; PM_breakISR - Control Break interrupt subroutine dispatcher
619;----------------------------------------------------------------------------
620; Hardware interrupt handler for the Ctrl-Break interrupt. We simply set
621; the Ctrl-Break flag to a 1 and leave (note that this is accessed through
622; a far pointer, as it may well be located in conventional memory).
623;----------------------------------------------------------------------------
624cprocfar _PM_breakISR
625
626 sti
627 push ds ; Save value of DS
628 push es
629 push _bx
630
631 LOAD_DS ; Load DS register
632 mov ebx,[_PM_ctrlBPtr]
633 mov [UINT _ES _bx],1
634
635; Run alternate break handler code if installed
636
637 cmp [CPTR _PM_breakHandler],0
638 je @@Exit
639
640 pushad
641 mov _ax,1
642 push _ax
643 call [CPTR _PM_breakHandler] ; Call C code
644 pop _ax
645 popad
646
647@@Exit: pop _bx
648 pop es
649 pop ds
650 iret ; Return from interrupt
651
652cprocend
653
654;----------------------------------------------------------------------------
655; int PM_ctrlBreakHit(int clearFlag)
656;----------------------------------------------------------------------------
657; Returns the current state of the Ctrl-Break flag and possibly clears it.
658;----------------------------------------------------------------------------
659cprocstart PM_ctrlBreakHit
660
661 ARG clearFlag:UINT
662
663 enter_c
664 pushf ; Save interrupt status
665 push es
666 mov ebx,[_PM_ctrlBPtr]
667 cli ; No interrupts thanks!
668 mov _ax,[_ES _bx]
669 test [BYTE clearFlag],1
670 jz @@Done
671 mov [UINT _ES _bx],0
672
673@@Done: pop es
674 popf ; Restore interrupt status
675 leave_c
676 ret
677
678cprocend
679
680;----------------------------------------------------------------------------
681; PM_ctrlCISR - Control Break interrupt subroutine dispatcher
682;----------------------------------------------------------------------------
683; Hardware interrupt handler for the Ctrl-C interrupt. We simply set
684; the Ctrl-C flag to a 1 and leave (note that this is accessed through
685; a far pointer, as it may well be located in conventional memory).
686;----------------------------------------------------------------------------
687cprocfar _PM_ctrlCISR
688
689 sti
690 push ds ; Save value of DS
691 push es
692 push _bx
693
694 LOAD_DS ; Load DS register
695 mov ebx,[_PM_ctrlCPtr]
696 mov [UINT _ES _bx],1
697
698; Run alternate break handler code if installed
699
700 cmp [CPTR _PM_breakHandler],0
701 je @@Exit
702
703 pushad
704 mov _ax,0
705 push _ax
706 call [CPTR _PM_breakHandler] ; Call C code
707 pop _ax
708 popad
709
710@@Exit: pop _bx
711 pop es
712 pop ds
713 iret ; Return from interrupt
714 iretd
715
716cprocend
717
718;----------------------------------------------------------------------------
719; int PM_ctrlCHit(int clearFlag)
720;----------------------------------------------------------------------------
721; Returns the current state of the Ctrl-C flag and possibly clears it.
722;----------------------------------------------------------------------------
723cprocstart PM_ctrlCHit
724
725 ARG clearFlag:UINT
726
727 enter_c
728 pushf ; Save interrupt status
729 push es
730 mov ebx,[_PM_ctrlCPtr]
731 cli ; No interrupts thanks!
732 mov _ax,[_ES _bx]
733 test [BYTE clearFlag],1
734 jz @@Done
735 mov [UINT _ES _bx],0
736
737@@Done:
738 pop es
739 popf ; Restore interrupt status
740 leave_c
741 ret
742
743cprocend
744
745;----------------------------------------------------------------------------
746; PM_criticalISR - Control Error handler interrupt subroutine dispatcher
747;----------------------------------------------------------------------------
748; Interrupt handler for the MSDOS Critical Error interrupt, to dispatch
749; control to high level C based subroutines. We save the state of all
750; registers in this routine, and switch to a local stack. We also pass
751; the values of the AX and DI registers to the as pointers, so that the
752; values can be modified before returning to MSDOS.
753;----------------------------------------------------------------------------
754cprocfar _PM_criticalISR
755
756 sti
757 push ds ; Save value of DS
758 push es
759 push _bx ; Save register values changed
760 cld ; Clear direction flag
761
762 LOAD_DS ; Load DS register
763 mov ebx,[_PM_critPtr]
764 mov [_ES _bx],ax
765 mov [_ES _bx+2],di
766
767; Run alternate critical handler code if installed
768
769 cmp [CPTR _PM_critHandler],0
770 je @@NoAltHandler
771
772 pushad
773 push _di
774 push _ax
775 call [CPTR _PM_critHandler] ; Call C code
776 _add sp,4,8
777 popad
778
779 pop _bx
780 pop es
781 pop ds
782 iret ; Return from interrupt
783
784@@NoAltHandler:
785 mov ax,3 ; Tell MSDOS to fail the operation
786 pop _bx
787 pop es
788 pop ds
789 iret ; Return from interrupt
790
791cprocend
792
793;----------------------------------------------------------------------------
794; int PM_criticalError(int *axVal,int *diVal,int clearFlag)
795;----------------------------------------------------------------------------
796; Returns the current state of the critical error flags, and the values that
797; MSDOS passed in the AX and DI registers to our handler.
798;----------------------------------------------------------------------------
799cprocstart PM_criticalError
800
801 ARG axVal:DPTR, diVal:DPTR, clearFlag:UINT
802
803 enter_c
804 pushf ; Save interrupt status
805 push es
806 mov ebx,[_PM_critPtr]
807 cli ; No interrupts thanks!
808 xor _ax,_ax
809 xor _di,_di
810 mov ax,[_ES _bx]
811 mov di,[_ES _bx+2]
812 test [BYTE clearFlag],1
813 jz @@NoClear
814 mov [ULONG _ES _bx],0
815@@NoClear:
816 _les _bx,[axVal]
817 mov [_ES _bx],_ax
818 _les _bx,[diVal]
819 mov [_ES _bx],_di
820 pop es
821 popf ; Restore interrupt status
822 leave_c
823 ret
824
825cprocend
826
827;----------------------------------------------------------------------------
828; void PM_setMouseHandler(int mask, PM_mouseHandler mh)
829;----------------------------------------------------------------------------
830cprocstart _PM_setMouseHandler
831
832 ARG mouseMask:UINT
833
834 enter_c
835 push es
836
837 mov ax,0Ch ; AX := Function 12 - install interrupt sub
838 mov _cx,[mouseMask] ; CX := mouse mask
839 mov _dx,offset _PM_mouseISR
840 push cs
841 pop es ; ES:_DX -> mouse handler
842 int 33h ; Call mouse driver
843
844 pop es
845 leave_c
846 ret
847
848cprocend
849
850;----------------------------------------------------------------------------
851; void PM_mousePMCB(void)
852;----------------------------------------------------------------------------
853; Mouse realmode callback routine. Upon entry to this routine, we recieve
854; the following from the DPMI server:
855;
856; Entry: DS:_SI -> Real mode stack at time of call
857; ES:_DI -> Real mode register data structure
858; SS:_SP -> Locked protected mode stack to use
859;----------------------------------------------------------------------------
860cprocfar _PM_mousePMCB
861
862 pushad
863 mov eax,[es:_di+1Ch] ; Load register values from real mode
864 mov ebx,[es:_di+10h]
865 mov ecx,[es:_di+18h]
866 mov edx,[es:_di+14h]
867 mov esi,[es:_di+04h]
868 mov edi,[es:_di]
869 call _PM_mouseISR ; Call the mouse handler
870 popad
871
872 mov ax,[ds:_si]
873 mov [es:_di+2Ah],ax ; Plug in return IP address
874 mov ax,[ds:_si+2]
875 mov [es:_di+2Ch],ax ; Plug in return CS value
876 add [WORD es:_di+2Eh],4 ; Remove return address from stack
877 iret ; Go back to real mode!
878
879cprocend
880
881;----------------------------------------------------------------------------
882; void PM_int10PMCB(void)
883;----------------------------------------------------------------------------
884; int10 realmode callback routine. Upon entry to this routine, we recieve
885; the following from the DPMI server:
886;
887; Entry: DS:ESI -> Real mode stack at time of call
888; ES:EDI -> Real mode register data structure
889; SS:ESP -> Locked protected mode stack to use
890;----------------------------------------------------------------------------
891cprocfar _PM_int10PMCB
892
893 pushad
894 push ds
895 push es
896 push fs
897
898 pushfd
899 pop eax
900 mov [es:edi+20h],ax ; Save return flag status
901 mov ax,[ds:esi]
902 mov [es:edi+2Ah],ax ; Plug in return IP address
903 mov ax,[ds:esi+2]
904 mov [es:edi+2Ch],ax ; Plug in return CS value
905 add [WORD es:edi+2Eh],4 ; Remove return address from stack
906
907; Call the install int10 handler in protected mode. This function gets called
908; with DS set to the current data selector, and ES:EDI pointing the the
909; real mode DPMI register structure at the time of the interrupt. The
910; handle must be written in assembler to be able to extract the real mode
911; register values from the structure
912
913 push es
914 pop fs ; FS:EDI -> real mode registers
915 LOAD_DS
916 NEWSTK Int10Stack ; Switch to local stack
917
918 call [_PM_int10Handler]
919
920 RESTSTK Int10Stack ; Restore previous stack
921 pop fs
922 pop es
923 pop ds
924 popad
925 iret ; Go back to real mode!
926
927cprocend
928
929cpublic _PM_pmsmxCodeEnd
930
931endcodeseg _pmsmx
932
933 END ; End of module