tasos@bu-cs.BU.EDU (Anastasios Kotsikonas) (09/20/89)
I am trying to write a TSR in Turbo Pascal, and I capture the $1C timer interrupt. Once inside the interrupt routine, I switch stacks and look for the hot key. The problem is that I cannot chain the interrupt before exiting. If I try: { code to switch stacks } GetIntVec ($1C, old_intr); SetIntVec ($1C, prev_intr); { the vector before my TSR came to life } Intr ($1C, Regs); SetIntVec ($1C, old_intr); { code to restore original stack configuration } the system freezes. This technique works for the $28 interrupt, but it is impossible to do it this way for the timer interrupt. If anyone knows anything about it I would appreciate any comments. Tasos tasos@cs.bu.edu
jeff@com2serv.C2S.MN.ORG (Jeffery S. Wilson) (09/21/89)
> I am trying to write a TSR in Turbo Pascal, and I capture the $1C timer > interrupt. Once inside the interrupt routine, I switch stacks and look > for the hot key. The problem is that I cannot chain the interrupt before > exiting. If I try: > { code to switch stacks } > GetIntVec ($1C, old_intr); > SetIntVec ($1C, prev_intr); { the vector before my TSR came to life } > Intr ($1C, Regs); > SetIntVec ($1C, old_intr); > { code to restore original stack configuration } > the system freezes. ... > Tasos > > tasos@cs.bu.edu When you are servicing the int $1C interrupt, you are essentially servicing a hardware interrupt. The int $08 handler services the IRQ 0 hardware interrupt then does an int $1C. You should not make int $21 calls from within a hardware interrupt handler, because DOS is not re-entrant. The Turbo Pascal GetIntVec and SetIntVec procedures use int $21 functions $35 and $25 respectively, so this what is hosing up your program. I would suggest that you get and set the interrupt vector using the MemL array: var old_intr, prev_intr : longint ... inline($FA); { disable hardware interrupt processing } old_intr := MemL[0:$1C * 4]; { get your interrupt vector } MemL[0:$1C * 4] := prev_intr; { restore the old interrupt vector } inline($FB); { re-enable hardware interrupt processing } Intr($1C,regs); inline($FA); { disable hardware interrupt processing } MemL[0:$1C * 4] := old_intr; { resore your interrupt vector } inline($FB); { re-enable hardware interrupt processing } .... The inline instructions are used to prevent hardware interrupts from being serviced during the time you are fooling around with the interrupt vector, just to be safe. > This technique works for the $28 interrupt, but it is impossible to do it > this way for the timer interrupt. Int $28 is generated by DOS keyboard input loop if and only if it is safe to use int $21 functions. Even then, you must not use int $21 functions $00 through $0C. The only problem with using int $28 is that some applications bypass DOS for their keyboard input, therefore the DOS keyboard input loop is never called. You will not be able to hot key while these sort of programs are running. If you absolutely must perform DOS int $21 functions while in a hardware interrupt handler, you should check the DOS critical section flag and the DOS critical error flag before doing the function call. This is done by doing an int $21 function $34. A pointer to the critical section flag will be returned in ES:BX. In DOS 2.xx the critical error flag is the byte after the critical section flag. In DOS 3.xx the critical error flag is the byte before the critical section flag, execpt Compaq DOS 3.0, where the critical error flag is $1AA bytes before the critical section flag. Both the critical section flag and the critical error flag should be 0 before you call an int $21 function within a hardware interrupt handler. Jeffery S. Wilson | {amdahl|hpda}!bungia!com50!jeff Com Squared Systems, Inc. | jeff@c2s.mn.org 2520 Pilot Knob Road | (612) 452-9522 voice Mendota Heights MN 55120 | (612) 452-3607 fax