source: vendor/emx/current/src/dos/rmint.asm

Last change on this file was 18, checked in by bird, 22 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 26.6 KB
Line 
1;
2; RMINT.ASM -- Initialize interrupts and handle real-mode interrupts
3;
4; Copyright (c) 1991-1995 by Eberhard Mattes
5;
6; This file is part of emx.
7;
8; emx is free software; you can redistribute it and/or modify it
9; under the terms of the GNU General Public License as published by
10; the Free Software Foundation; either version 2, or (at your option)
11; any later version.
12;
13; emx is distributed in the hope that it will be useful,
14; but WITHOUT ANY WARRANTY; without even the implied warranty of
15; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16; GNU General Public License for more details.
17;
18; You should have received a copy of the GNU General Public License
19; along with emx; see the file COPYING. If not, write to
20; the Free Software Foundation, 59 Temple Place - Suite 330,
21; Boston, MA 02111-1307, USA.
22;
23; See emx.asm for a special exception.
24;
25
26 INCLUDE EMX.INC
27 INCLUDE TABLES.INC
28 INCLUDE VCPI.INC
29 INCLUDE PMINT.INC
30 INCLUDE EXCEPT.INC
31 INCLUDE RPRINT.INC
32 INCLUDE SIGNAL.INC
33 INCLUDE PROCESS.INC
34 INCLUDE OPTIONS.INC
35 INCLUDE MISC.INC
36
37 PUBLIC INIT_INT, CLEANUP_INT, INIT_TIMER, CLEANUP_TIMER
38 PUBLIC SET_RM_INT, RESTORE_RM_INT
39
40RM_DEBUGGER = FALSE
41
42;
43; The interrupt redirection machinery has four states:
44;
45; - IC_NOT
46; This is the initial state: interrupt vectors have not been
47; changed yet. Do not restore interrupt vectors on exit!
48;
49; - IC_VCPI_SERVER
50; There is a VCPI server (EMS emulator) which has already reprogrammed
51; the interrupt controller to redirect hardware interrupts. Or a
52; different client of the VCPI server has redirected the hardware
53; interrupts. This is the simple case as we don't have to touch
54; the interrupt controller.
55;
56; - IC_VCPI_CLIENT
57; There is a VCPI server (EMS emulator) which hasn't reprogrammed
58; the interrupt controller. We have to reprogram the interrupt
59; controller in order to distinguish hardware interrupts from
60; processor exceptions. PC design flaw...
61;
62; - IC_MYSELF
63; There is no VCPI server (EMS emulator). We have to reprogram the
64; interrupt controller in order to distinguish hardware interrupts from
65; processor exceptions. PC design flaw...
66;
67
68IC_NOT = 0 ; Interrupt vectors not changed
69IC_VCPI_SERVER = 1 ; VCPI server has changed vectors
70IC_VCPI_CLIENT = 2 ; VCPI server hasn't changed vectors
71IC_MYSELF = 3 ; This program has changed vectors
72
73
74
75SV_DATA SEGMENT
76
77 IF RM_DEBUGGER
78;
79; The original debug interrupt vectors.
80;
81OLD_RM_INT01_OFF DW ?
82OLD_RM_INT01_SEG DW ?
83
84OLD_RM_INT03_OFF DW ?
85OLD_RM_INT03_SEG DW ?
86
87 ENDIF
88
89;
90;
91; The original interrupt vectors IRQ0_BASE .. IRQ0_BASE+7.
92;
93SAVED_IVECS DD 8 DUP (?)
94
95;
96; Check the interrupt vectors in this table in this sequence for
97; 8 successive unused interrupts vectors. The first entry should
98; be the safest, the last the most dangerous. But all vectors
99; are checked, so that nothing evil should happen if a vector
100; is already in use. The danger is that some other program may
101; change an interrupt vector used by this program for redirecting
102; a hardware interrupt. This would cause a system crash.
103;
104UNUSED_INT_TAB DB 50H, 88H, 90H, 98H
105 DB 0A8H, 0B8H, 0C0H, 0C8H, 0D0H, 0D8H
106 DB 80H, 0A0H, 0B0H, 0E0H, 0E8H, 38H, 78H, 58H, 0F0H
107 DB 00H
108
109;
110; These are the offsets for the new interrupt vectors used for IRQ0..IRQ7.
111; The code at that address just issues INT 08H .. INT 0FH.
112;
113NEW_IVECS DW HWINT0, HWINT1, HWINT2, HWINT3
114 DW HWINT4, HWINT5, HWINT6, HWINT7
115
116;
117; These are the first interrupt vector used for redirecting IRQ0..IRQ7
118; and IRQ8..IRQ15, respectively.
119;
120IRQ0_BASE DB ?
121IRQ8_BASE DB ?
122
123;
124; This is the interrupt redirection status.
125;
126INT_CHANGED DB IC_NOT
127;
128; This is the future interrupt redirection status.
129;
130NEW_INT_CHANGED DB IC_NOT
131
132;
133; This message should never be required: The VCPI server (or one of its
134; clients) has changed the interrupt vectors. But that mappings aren't
135; usable.
136;
137$BAD_VCPI DB "Unusable interrupt vector mappings set by VCPI server", CR, LF, 0
138
139 IF RM_DEBUGGER
140;
141; There's no real-mode debugger
142;
143$RM_DEBUG DB "Real-mode breakpoint at ", 0
144
145 ENDIF
146
147SV_DATA ENDS
148
149
150INIT_CODE SEGMENT
151
152 ASSUME CS:INIT_CODE, DS:NOTHING
153
154;
155; The original timer interrupt vector. This is in the code segment because
156; we need OLD_RM_INT1C for jumping to the next interrupt handler in the
157; chain.
158;
159OLD_RM_INT1C LABEL DWORD
160OLD_RM_INT1C_OFF DW ?
161OLD_RM_INT1C_SEG DW ?
162OLD_RM_INT1C_FLAG DB FALSE
163
164
165;
166; Redirect hardware interrupt IRQ X to real-mode interrupt Y
167;
168 ASSUME DS:NOTHING
169HWINTX MACRO X,Y
170 TALIGN 2
171HWINT&X: INT Y ; Issue software interrupt
172 IRET ; Return
173 ENDM
174;
175; Redirect IRQ 0 (-> INT 08H) to IRQ 7 (-> INT 0FH)
176;
177 IRPC X, <01234567>
178 HWINTX X, %&X+8
179 ENDM
180
181
182;
183; Access rights for 32-bit interrupt gates
184;
185INT_GATE_0 = 08EH ; DPL=0 (hardware interrupt)
186INT_GATE_1 = 0AEH ; DPL=1
187INT_GATE_2 = 0CEH ; DPL=2
188INT_GATE_3 = 0EEH ; DPL=3 (software interrupt)
189
190
191;
192; Initialize IDT, redirect hardware interrupts
193;
194; This procedure is also called after spawning a DOS program
195;
196
197 ASSUME DS:SV_DATA
198
199 TALIGN 2
200INIT_INT PROC NEAR
201 MOV IRQ0_BASE, 40H
202 MOV IRQ8_BASE, 48H
203 CMP MACHINE, MACH_FMR70 ; Fujitsu FMR70?
204 JE II_TABLE ; Yes -> use above values
205 MOV IRQ0_BASE, 40H
206 MOV IRQ8_BASE, 48H
207 CMP MACHINE, MACH_PC98 ; NEC PC-98?
208 JE II_TABLE ; Yes -> use above values
209 MOV IRQ8_BASE, 70H ; The standard configuration
210 MOV NEW_INT_CHANGED, IC_MYSELF
211 CMP VCPI_FLAG, FALSE ; Use VCPI?
212 JE SHORT II_CHECK_INT ; No -> redirect interrupts
213 CALL GET_INT_MAP ; Get interrupt vector mappings
214 MOV IRQ0_BASE, BL ; Controller 1 address
215 MOV IRQ8_BASE, CL ; Controller 2 address
216 CMP BL, 17 ; Conflict with exceptions?
217 JBE SHORT II_NEED_REMAP ; Yes -> remapping required
218 CMP CL, 17 ; Conflict with exceptions?
219 JBE SHORT II_NEED_REMAP ; Yes -> remapping required
220;
221; Interrupt vector mapping is usable, VCPI server has done this.
222;
223 MOV NEW_INT_CHANGED, IC_VCPI_SERVER
224 JMP SHORT II_TABLE ; VCPI server has done the work
225
226II_NEED_REMAP: CMP BL, 08H ; Standard configuration?
227 JNE II_ERROR ; No -> almost impossible
228 CMP CL, 70H ; Standard configuration?
229 JNE II_ERROR ; No -> almost impossible
230 MOV NEW_INT_CHANGED, IC_VCPI_CLIENT
231 JMP SHORT II_MYSELF
232
233;
234; There may be programs which redirect IRQ0..IRQ7. As we're not
235; running under a VCPI server, we should find this out by hand.
236; Here's how:
237; - save all the interrupt vectors
238; - setup 256 *different* interrupt handlers
239; - set a variable V in the code segment to some number I unequal 0..255
240; - each handler stores its vector number to V if V equals I
241; (this must be done in an atomic operation) and then jumps to the
242; original handler for that interrupt vector
243; - the main program loops until V != I or a loop counter expires
244; - restore interrupt vectors
245; - if V == 8, we have the original mapping
246; Actually, we aren't doing all this. It isn't worth the trouble.
247; There's an explicit check for DESQview in VCPI.ASM, instead.
248;
249II_CHECK_INT:
250
251;
252; We have to redirect hardware interrupts. Find 8 sucessive unused
253; interrupt vectors for redirecting IRQ0..IRQ7.
254;
255II_MYSELF: LEA SI, UNUSED_INT_TAB ; Table of vectors to check
256 XOR AX, AX ; AH:=0
257 MOV ES, AX ; Access interrupt table
258II_FIND_1: LODS UNUSED_INT_TAB ; Get interupt vector
259 OR AL, AL ; End of table?
260 JZ SHORT II_FIND_FAIL ; Yes -> be brutal
261 MOV BX, AX ; AH=0
262 SHL BX, 2 ; Compute address of vector
263 MOV EDX, ES:[BX] ; Fetch first vector
264 MOV CX, 7 ; Compare to the following 7
265II_FIND_2: ADD BX, 4 ; Next vector
266 CMP EDX, ES:[BX] ; Same as first vector?
267 JNE II_FIND_1 ; No -> try next table entry
268 LOOP II_FIND_2 ; Repeat for 7 vectors
269 MOV IRQ0_BASE, AL ; Use this vector
270 JMP SHORT II_TABLE ; Continue
271
272;
273; No unused interrupt vectors found. We don't have mercy and use some
274; interrupt vectors reserved for BASIC. Starting BASIC while this
275; program is running will cause a system crash.
276;
277II_FIND_FAIL: MOV IRQ0_BASE, 0D0H
278
279;
280; Initialize all IDT entries.
281;
282II_TABLE: LEA DI, IDT+0
283 MOV CX, 256
284 MOV AL, INT_GATE_0
285 MOV DX, OFFSET SV_CODE:INTERRUPT
286II_UNUSED_1: CALL SET_INT_GATE
287 ADD DI, 8
288 LOOP II_UNUSED_1
289;
290; Put exceptions into IDT.
291;
292; Use interrupt gate instead of trap gate to disable interrupts
293;
294 LEA SI, EXC_TAB ; Table of handlers
295II_EXC_1: LODS EXC_TAB ; Get exception number
296 CMP AX, 0FFFFH ; End of table?
297 JE SHORT II_EXC_3
298 MOV BX, AX
299 SHL AX, 3 ; Compute offset into IDT
300 LEA DI, IDT
301 ADD DI, AX ; Compute pointer into IDT
302 LODS EXC_TAB ; Get offset of handler
303 MOV DX, AX
304 MOV AL, INT_GATE_0 ; Interrupt gate, DPL=0
305 CMP BL, 3 ; Breakpoint?
306 JNE SHORT II_EXC_2 ; No -> use DPL=0
307 MOV AL, INT_GATE_3 ; Use DPL=3 (for breakpoints)
308II_EXC_2: CALL SET_INT_GATE ; Insert into IDT
309 JMP SHORT II_EXC_1 ; Repeat for all table entries
310II_EXC_3:
311;
312; Put task gates for exceptions 8 & 10 into IDT.
313;
314 LEA DI, IDT+8*8
315 MOV AX, G_TSS_EX8_SEL
316 CALL SET_TASK_GATE
317 LEA DI, IDT+10*8
318 MOV AX, G_TSS_EX10_SEL
319 CALL SET_TASK_GATE
320;
321; Put hardware interrupts into IDT.
322;
323 LEA SI, PMINT0_TAB
324 MOVZX BX, IRQ0_BASE
325 CALL PUT_HW_INT
326 LEA SI, PMINT8_TAB
327 MOVZX BX, IRQ8_BASE
328 CALL PUT_HW_INT
329;
330; Put software interrupts into IDT.
331;
332 IRP SWINT, <10H, 11H, 14H, 16H, 17H, 21H, 31H, 33H>
333 LEA DI, IDT + SWINT*8
334 MOV DX, OFFSET SV_CODE:PMINT_&SWINT
335 MOV AL, INT_GATE_3
336 CALL SET_INT_GATE
337 ENDM
338;
339; Setup debug interrupt
340;
341 IF RM_DEBUGGER
342 LEA DX, RM_DEBUG
343 MOV AL, 01H
344 CALL SET_RM_INT
345 MOV OLD_RM_INT01_OFF, DX
346 MOV OLD_RM_INT01_SEG, AX
347 LEA DX, RM_DEBUG
348 MOV AL, 03H
349 CALL SET_RM_INT
350 MOV OLD_RM_INT03_OFF, DX
351 MOV OLD_RM_INT03_SEG, AX
352 ENDIF
353;
354; Copy IRQ0_BASE and IRQ8_BASE to IRQ0_ADD and IRQ8_ADD (in the SV_CODE
355; segment), respectively, to make them accessible in the protected-mode
356; interrupt handler without setting any segment register (CS will be set
357; automatically to SV_CODE_SEL).
358;
359 MOV AX, SV_CODE ; Used for setting IRQ0_ADD
360 MOV ES, AX ; and IRQ8_ADD
361 ASSUME ES:SV_CODE
362 MOV AL, IRQ0_BASE
363 MOV IRQ0_ADD, AL ; Set IRQ0_ADD
364 MOV AL, IRQ8_BASE
365 MOV IRQ8_ADD, AL ; Set IRQ8_ADD
366 ASSUME ES:NOTHING ; Access to SV_CODE finished
367;
368; Redirect hardware interrupts if required: reprogram interrupt controller 1
369; and notify VCPI server (if present).
370;
371 CLI
372 CMP NEW_INT_CHANGED, IC_MYSELF
373 JNE SHORT II_REDIR_1
374 CALL REDIR_INT_VEC
375 MOV CL, IRQ0_BASE
376 CALL SET_HW_INT_BASE
377 JMP SHORT II_REDIR_END
378
379II_REDIR_1: CMP NEW_INT_CHANGED, IC_VCPI_CLIENT
380 JNE SHORT II_REDIR_END
381 CALL REDIR_INT_VEC
382 MOV CL, IRQ0_BASE
383 CALL SET_HW_INT_BASE
384 MOVZX BX, IRQ0_BASE
385 MOVZX CX, IRQ8_BASE ; This is always 70H
386 CALL SET_INT_MAP ; Inform VCPI server
387;
388; Now we can copy NEW_INT_CHANGED to INT_CHANGED.
389;
390II_REDIR_END: MOV AL, NEW_INT_CHANGED
391 MOV INT_CHANGED, AL
392 RET
393
394;
395; We cannot cooperate with a buggy VCPI server; give up.
396;
397II_ERROR: LEA DX, $BAD_VCPI
398 CALL RTEXT
399 MOV AL, 0FFH
400 JMP EXIT
401
402INIT_INT ENDP
403
404;
405; Put hardware interrupts into IDT
406;
407; In: BX First interrupt number
408; DS:SI Table of vectors
409;
410 ASSUME DS:SV_DATA
411PUT_HW_INT PROC NEAR
412 SHL BX, 3
413 LEA DI, IDT[BX]
414 MOV CX, 8
415PHI_1: LODS PMINT0_TAB ; ...or PMINT8_TAB
416 MOV DX, AX
417 MOV AL, INT_GATE_0 ; Not accessible from ring 3
418 CALL SET_INT_GATE
419 ADD DI, 8
420 LOOP PHI_1
421 RET
422PUT_HW_INT ENDP
423
424;
425; Put interrupt gate (disables interrupts) into IDT
426;
427; In: DS:DI Pointer to IDT entry
428; DX Offset of interrupt routine (SV_CODE:DX)
429; AL INT_GATE_0 ... INT_GATE_3
430;
431 ASSUME DS:NOTHING
432
433SET_INT_GATE PROC NEAR
434 MOV WORD PTR [DI+0], DX
435 MOV WORD PTR [DI+2], G_SV_CODE_SEL
436 MOV BYTE PTR [DI+4], 0
437 MOV BYTE PTR [DI+5], AL
438 MOV WORD PTR [DI+6], 0
439 RET
440SET_INT_GATE ENDP
441
442
443;
444; Put task gate into IDT
445;
446; In: DS:DI Pointer to IDT entry
447; AX TSS selector
448;
449 ASSUME DS:NOTHING
450SET_TASK_GATE PROC NEAR
451 MOV WORD PTR [DI+0], 0
452 MOV WORD PTR [DI+2], AX
453 MOV BYTE PTR [DI+4], 0
454 MOV BYTE PTR [DI+5], 85H
455 MOV WORD PTR [DI+6], 0
456 RET
457SET_TASK_GATE ENDP
458
459
460;
461; Setup real-mode interrupt vectors for redirecting IRQ0..IRQ7.
462;
463 ASSUME DS:SV_DATA
464REDIR_INT_VEC PROC NEAR
465 XOR AX, AX
466 MOV ES, AX
467 LEA SI, NEW_IVECS
468 LEA DI, SAVED_IVECS
469 MOV CX, 8
470 MOVZX BX, IRQ0_BASE
471 SHL BX, 2
472II_41: MOV AX, ES:[BX+0]
473 MOV [DI+0], AX
474 MOV AX, ES:[BX+2]
475 MOV [DI+2], AX
476 MOV AX, [SI]
477 MOV ES:[BX+0], AX
478 MOV ES:[BX+2], CS
479 ADD BX, 4
480 ADD DI, 4
481 ADD SI, 2
482 LOOP II_41
483 RET
484REDIR_INT_VEC ENDP
485
486;
487; Restore interrupt vectors
488;
489 ASSUME DS:SV_DATA
490RESTORE_INT_VEC PROC NEAR
491 XOR AX, AX
492 MOV ES, AX
493 MOVZX DI, IRQ0_BASE
494 SHL DI, 2
495 LEA SI, SAVED_IVECS
496 MOV CX, 8
497 CLD
498 REP MOVSD
499 RET
500RESTORE_INT_VEC ENDP
501
502;
503; Delay for accessing interrupt controller registers
504;
505IO_DELAY MACRO
506 LOCAL SKIP
507 JMP SHORT SKIP
508SKIP:
509 ENDM
510
511
512;
513; Reprogram interrupt controller #1
514;
515; In: CL Interrupt base
516;
517 ASSUME DS:SV_DATA
518SET_HW_INT_BASE PROC NEAR
519 IN AL, 21H ; Read IMR
520 MOV AH, AL ; Save old IMR
521 CMP MACHINE, MACH_INBOARD ; Inboard 386/PC
522 JE SHORT SET_HIB_INB
523 MOV AL, 11H ; ICW1
524 OUT 20H, AL
525 IO_DELAY
526 MOV AL, CL ; ICW2
527 OUT 21H, AL
528 IO_DELAY
529 MOV AL, 04H ; ICW3
530 OUT 21H, AL
531 IO_DELAY
532 MOV AL, 01H ; ICW4
533 OUT 21H, AL
534 IO_DELAY
535SET_HIB_END: MOV AL, AH
536 OUT 21H, AL ; Write IMR
537 RET
538
539;
540; Use the values of the original PC for the Inboard 386/PC
541;
542SET_HIB_INB: MOV AL, 13H ; ICW1
543 OUT 20H,AL
544 IO_DELAY
545 MOV AL, CL ; ICW2
546 OUT 21H,AL
547 IO_DELAY
548 MOV AL, 09H ; ICW4
549 OUT 21H, AL
550 JMP SHORT SET_HIB_END
551
552SET_HW_INT_BASE ENDP
553
554
555;
556; Install real-mode interrupt handler
557;
558; In: AL Interrupt number
559; DX Offset of interrupt handler (CS=INIT_CODE)
560;
561; Out: AX Segment of original interrupt handler
562; DX Offset of original interrupt handler
563;
564 ASSUME DS:NOTHING
565SET_RM_INT PROC NEAR
566 PUSH DS
567 PUSH ES
568 PUSH BX
569 MOV AH, 35H
570 INT 21H
571 PUSH CS
572 POP DS
573 PUSH BX
574 PUSH ES
575 MOV AH, 25H
576 INT 21H
577 POP AX
578 POP DX
579 POP BX
580 POP ES
581 POP DS
582 RET
583SET_RM_INT ENDP
584
585;
586; Restore real-mode interrupt vector
587;
588; This is done only if the interrupt vector still points into INIT_CODE
589; (avoid restoring the vector if it has been hooked by somebody else)
590;
591; In: AL Interrupt number
592; DX Original offset
593; BX Original segment
594;
595 ASSUME DS:NOTHING
596RESTORE_RM_INT PROC NEAR
597 PUSH ES
598 PUSH BX
599 MOV AH, 35H
600 INT 21H
601 MOV BX, ES
602 CMP BX, INIT_CODE
603 POP BX
604 POP ES
605 JNE SHORT RRI_RET
606 PUSH DS
607 MOV DS, BX
608 MOV AH, 25H
609 INT 21H
610 POP DS
611RRI_RET: RET
612RESTORE_RM_INT ENDP
613
614
615;
616; Restore interrupts
617;
618; This procedure is also called before spawning a DOS program
619;
620 ASSUME DS:SV_DATA
621CLEANUP_INT PROC NEAR
622 CMP INT_CHANGED, IC_NOT ; Interrupt vectors remapped?
623 JE SHORT CI_9 ; No -> skip
624 CLI ; Interrupts must be disabled
625 CMP INT_CHANGED, IC_MYSELF ; Done without VCPI?
626 JNE SHORT CI_1 ; No -> try next case
627 CALL RESTORE_INT_VEC ; Restore interrupt vectors
628 MOV CL, 8 ; Restore interrupt controller
629 CALL SET_HW_INT_BASE
630 JMP SHORT CI_8 ; Done
631
632CI_1: CMP INT_CHANGED, IC_VCPI_CLIENT ; Done with VCPI?
633 JNE SHORT CI_8 ; No -> skip
634 CALL RESTORE_INT_VEC ; Restore interrupt vectors
635 MOV CL, 8 ; Restore interrupt controller
636 CALL SET_HW_INT_BASE
637 MOV BX, 8 ; Tell VCPI server about change
638 MOV CX, 70H
639 CALL SET_INT_MAP
640
641CI_8: MOV INT_CHANGED, IC_NOT ; Back at original state
642 STI ; Interrupts allowed again
643CI_9: IF RM_DEBUGGER
644 MOV DX, OLD_RM_INT01_OFF
645 MOV BX, OLD_RM_INT01_SEG
646 MOV AL, 01H
647 CALL RESTORE_RM_INT
648 MOV DX, OLD_RM_INT03_OFF
649 MOV BX, OLD_RM_INT03_SEG
650 MOV AL, 03H
651 CALL RESTORE_RM_INT
652 ENDIF
653 RET
654
655CLEANUP_INT ENDP
656
657
658;
659; Initialize timer interrupt
660;
661; This procedure is not called after spawning a DOS program
662;
663
664 ASSUME DS:SV_DATA
665 TALIGN 2
666INIT_TIMER PROC NEAR
667 CMP MACHINE, MACH_PC98 ; NEC PC-98?
668 JE SHORT IT_DONE ; Yes -> don't set INT 1CH
669 LEA DX, RM_TIMER
670 MOV AL, 1CH
671 CALL SET_RM_INT
672 MOV OLD_RM_INT1C_FLAG, NOT FALSE
673 MOV OLD_RM_INT1C_OFF, DX
674 MOV OLD_RM_INT1C_SEG, AX
675IT_DONE: RET
676INIT_TIMER ENDP
677
678;
679; Restore timer interrupt
680;
681; This procedure is not called before spawning a DOS program
682;
683 ASSUME DS:SV_DATA
684 TALIGN 2
685CLEANUP_TIMER PROC NEAR
686 CMP OLD_RM_INT1C_FLAG, FALSE
687 JE SHORT CT_DONE
688 MOV OLD_RM_INT1C_FLAG, FALSE
689 MOV DX, OLD_RM_INT1C_OFF
690 MOV BX, OLD_RM_INT1C_SEG
691 MOV AL, 1CH
692 CALL RESTORE_RM_INT
693CT_DONE: RET
694CLEANUP_TIMER ENDP
695
696;
697; The timer interrupt handler. Note that interrupt 1CH is not
698; available on NEC PC-98.
699;
700 ASSUME DS:NOTHING
701 TALIGN 4
702RM_TIMER PROC NEAR
703 PUSH EAX
704 PUSH DS
705 MOV AX, SV_DATA
706 MOV DS, AX
707 ASSUME DS:SV_DATA
708;
709; Update clock for __clock()
710;
711 ADD CLOCK_LO, 1
712 ADC CLOCK_HI, 0
713;
714; Decrement timer for emergency exit
715;
716 CMP EMERGENCY_TIMER, 0
717 JE SHORT RMT_SKIP_EMERGENCY
718 DEC EMERGENCY_TIMER
719 TALIGN 4
720RMT_SKIP_EMERGENCY:
721;
722; Update software timers
723;
724 CMP TIMER_MIN, 0
725 JE SHORT RMT_DONE
726 INC TIMER_TICKS
727 DEC TIMER_MIN
728 JNZ SHORT RMT_DONE
729 CALL RMT_CHECK
730 TALIGN 4
731RMT_DONE: POP DS
732 ASSUME DS:NOTHING
733 POP EAX
734 JMP OLD_RM_INT1C
735RM_TIMER ENDP
736
737;
738; At least one timer expired; examine all timers
739;
740 TALIGN 4
741 ASSUME DS:SV_DATA
742RMT_CHECK PROC NEAR
743 PUSH BX
744 PUSH CX
745 PUSH EDX
746 PUSH DI
747 MOV CX, MAX_TIMERS
748 LEA BX, TIMER_TABLE
749 ASSUME BX:PTR TIMER
750 XOR EDX, EDX
751 MOV TIMER_MIN, EDX
752 XCHG EDX, TIMER_TICKS
753RMT_LOOP: CMP [BX].T_TYPE, TT_RUNNING
754 JB SHORT RMT_NEXT
755 SUB [BX].T_TICKS, EDX
756 JA SHORT RMT_MIN
757 MOV AX, TT_EXPIRED
758 XCHG AX, [BX].T_TYPE
759 CMP AX, TT_TERMIO_TIME
760 JE SHORT RMT_TERMIO
761 CMP AX, TT_SLEEP
762 JE SHORT RMT_SLEEP
763 CMP AX, TT_ALARM
764 JNE SHORT RMT_NEXT
765RMT_ALARM: MOV DI, [BX].T_PROCESS
766 ASSUME DI:PTR PROCESS
767 CMP [DI].P_SIG_HANDLERS[4*SIGALRM], SIG_IGN
768 JE SHORT RMT_NEXT
769 BTS [DI].P_SIG_PENDING, SIGALRM ; Generate SIGALRM
770 ASSUME DI:NOTHING
771 JMP SHORT RMT_NEXT
772
773RMT_TERMIO: MOV DI, [BX].T_PROCESS
774 OR (PROCESS PTR [DI]).P_FLAGS, PF_TERMIO_TIME
775 JMP SHORT RMT_NEXT
776
777RMT_SLEEP: MOV DI, [BX].T_PROCESS
778 OR (PROCESS PTR [DI]).P_FLAGS, PF_SLEEP_FLAG
779 JMP SHORT RMT_NEXT
780
781RMT_MIN: MOV EAX, [BX].T_TICKS
782 CMP TIMER_MIN, 0
783 JE SHORT RMT_SET
784 CMP EAX, TIMER_MIN
785 JAE SHORT RMT_NEXT
786RMT_SET: MOV TIMER_MIN, EAX
787RMT_NEXT: ADD BX, SIZE TIMER
788 LOOP RMT_LOOP
789 ASSUME BX:NOTHING
790 POP DI
791 POP EDX
792 POP CX
793 POP BX
794 RET
795RMT_CHECK ENDP
796
797 IF RM_DEBUGGER
798;
799; Debug interrupt in real mode
800;
801 ASSUME DS:NOTHING
802RM_DEBUG PROC NEAR
803 MOV AX, SV_DATA
804 MOV DS, AX
805 ASSUME DS:SV_DATA
806 LEA DX, $RM_DEBUG
807 CALL RTEXT
808 MOV BP, SP
809 MOV AX, [BP+2]
810 CALL RWORD
811 MOV AL, ":"
812 CALL RCHAR
813 MOV AX, [BP+0]
814 CALL RWORD
815 CALL RCRLF
816 JMP EXIT
817RM_DEBUG ENDP
818
819 ENDIF
820
821INIT_CODE ENDS
822
823 END
Note: See TracBrowser for help on using the repository browser.