cjveenm@cs.vu.nl (11/16/89)
From: cjveenm@cs.vu.nl () Newsgroups: comp.sys.ibm.pc Subject: chaining interrupts Expires: References: Sender: Reply-To: cjveenm@cs.vu.nl () Followup-To: Distribution: world Organization: VU Informatica, Amsterdam Keywords: I have written several own interrupt handlers for the ibm pc, and I wonder if it's possible to use the old interrupt routines by chaining from the new one. One way to do this is by setting the old vector on the address of an other interrupt number. A disadvantage of this method is that you don't always know which interrupt is free and you can run out of all possible interrupts. So is there an other way, from TP4 for instance: jmp oldvector (with inline code) doesn't succeed. thanks in advance, Cor
pelegrin@geocub.greco-prog.fr (11/16/89)
It is absolutely harmless to link interrupt routines one to another WITH THE SAME INTERRUPT VECTOR provided that, for interrupts such as timer ticks, the total amount of time spent in the routines does not exceed the tick clock rate... A general example of a resident interrupt routine installation program (machine language) is given below : Initialization routine : 1) Save the old interrupt vector (INT 21H, FCN 25H) in a double word variable named, i.e. OLDVEC (defined with "DD OLDVEC"). 2) Set the new interrupt vector (INT 21H, FCN 35H) to the segment:offset of your own interrupt routine NEWVEC, located within this program. 3) Make the program resident, including this routine (which will now be of no use but we have no way to eliminate it), and the next routine : Interrupt routine (starting at address NEWVEC) : 1) Push the registers you will use in your routine. 2) Perform whatever you want to... (8^D). Since it is an interrupt routine, DS and ES may have any value ; for small use of local variables, use the CS: prefix to access them within your code segment, else push DS and/or ES and set them equal to CS (for example...). If you use a large amount of stack, you can also switch to your own local stack. 3) Pop the registers you pushed before, in reverse order. 4) Use the JMP OLDVEC mnemonic (inter-segment jump from a memory operand) to link to the old interrupt vector. If you want to bypass the old interrupt vector, just perform at step 4) a single IRET mnemonic for software interrupts, but if it was a hardware interrupt (issued thru a Programmable Interrupt Timer), NEVER forget to use the EOI mnemonic to warn the PIT of the end of the interrupt (for such cases, I *strongly* recommend to link your interrupt to the previous one, so that you don't have to hold those stinky cases...). Have fun. f.p. ------------------------------------------------------------------------------ ! Zeu<FP> : The craziest programmer in France ! _________ ! !---------------------------------------------! / | \ \ ! ! Francois Pellegrini is : ! / |__ ___/ \ ! ! pelegrin@goofi.greco-prog.fr ! \ | | / ! ! uunet!mcsun!inria!geocub!goofi!pelegrin ! \ | | / ! ! pelegrin@goofi.UUCP ! ! ------------------------------------------------------------------------------
johnl@esegue.segue.boston.ma.us (John R. Levine) (11/17/89)
In article <1484@geocub.greco-prog.fr> pelegrin@goofi.UUCP (Uncle Ben's) writes: > It is absolutely harmless to link interrupt routines one to >another WITH THE SAME INTERRUPT VECTOR provided that, for interrupts >such as timer ticks, the total amount of time spent in the routines >does not exceed the tick clock rate... Well, sometimes. The problem is that many cards were not designed with interrupt sharing in mind and so are not good citizens about the way that they handle their interrupt line. I have used cards (a WD8003 Ethernet, for example) that keep anything else from interrupting on the same level. -- John R. Levine, Segue Software, POB 349, Cambridge MA 02238, +1 617 864 9650 johnl@esegue.segue.boston.ma.us, {ima|lotus|spdcc}!esegue!johnl "Now, we are all jelly doughnuts."
MATHRICH@umcvmb.missouri.edu (Rich Winkel UMC Math Department) (11/17/89)
I've done this many times with assembler, but not pascal. Are you sure of the condition of the stack when you do the jump? If you're doing this inside a TP INTERRUPT procedure, you need to read about what TP does with the stack before your inline code gets control. Basically it pushes ALL the registers except CS, SS, IP, SP and the flags register. You'll need to pop everything and then execute the jump. See page 222 of the TP 5.0 manual. Are you sure you're doing a far jump? Are you using the jump seg & offset properly? If the seg & offset of the target routine is: aabb:ccdd then the jump could be coded as: $EA/$dd/$cc/$bb/$aa (immediate-operand form of far jump) or $FF/$2E/variable assuming 'variable' is a four byte variable in the data segment (it must be a global variable to be in the data seg). The variable should have the contents: $dd $cc $bb $aa. One way to load it would be: var intvec:longint absolute $0:yyyy; saveintvec:longint; ... saveintvec:=intvec; {save the old int vector} Where yyyy is 4 times the interrupt number. To be on the safe side, you should do a CLI before the jump (if you've done an STI in your procedure). Rich
KULOKARI@cc.helsinki.fi (Hannu Kulokari) (12/04/89)
In article <4543@solo5.cs.vu.nl>, cjveenm@cs.vu.nl writes: > I have written several own interrupt handlers for the ibm pc, > and I wonder if it's possible to use the old interrupt routines by > chaining from the new one. One way to do this is by setting the old > vector on the address of an other interrupt number. A disadvantage > of this method is that you don't always know which interrupt is free > and you can run out of all possible interrupts. > So is there an other way, from TP4 for instance: > jmp oldvector (with inline code) > doesn't succeed. > > thanks in advance, Cor You should CALL (not JMP to) the old interrupt routine, with a FAR call. You should also push the flags (PUSHF) before the call. This is what INT does (besides looking up the address of the routine from the interrupt table). Hannu Kulokari CC, U of Helsinki, Finland