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 ! ! ------------------------------------------------------------------------------
mikej@vax1.acs.udel.EDU (Michael Jacobs) (11/16/89)
> 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. I was playing with interrupts last night and just worked it out. I have succeeded in replacing interrupt $1C (the clock updater), and then, inside my routine, calling the clock updated (so it gets done), then returning safely. in turbo 5.5 (it would work in tp >= 4.0 I would think): {$m 1024,0,0} { this program installs the interrupt replacement, and since we want the code to stay in memory so it can be used, we'll have to use the KEEP command, so we don't want a big stack and heap clogging memory } uses dos; { getintvec and setintvec are in unit dos } var ticksave : pointer; { this holds onto the old interrupt vector } procedure tick; interrupt; { this is what would get called instead } begin inline ( $50/$bb/ticksave/$ff/$1f ) { call tick routine } { what this does is PUSH AX MOV BX, OFFSET ticksave CALL [BX] (intersegment call) I push AX, because at the end of the old clock updating stuff, there will be an IRET which pops the offset (IP), the segment (CS), and the flags. since the flags are irrelevent in this case, i just pushed the garbage in AX } { your code here... } end; var X : pointer; begin getintvec ( $1C, ticksave ); { get the old vector and remember it } x := @tick; { the address of tick is the new vector } setintvec ( $1c, x ); { set it } keep ( 0 ) { end the program but keep all this } end. { BS in memory } fun, huh? -- Mike J | The Grey Sysop... | Phone...RING!...yep yep yep yep yep! |
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."
pelegrin@geocub.greco-prog.fr (11/17/89)
In article <1989Nov16.173228.7309@esegue.segue.boston.ma.us> johnl@esegue.segue.boston.ma.us (John R. Levine) writes: >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. From a software point of view, if you handle chaining properly in your interrupt routine, you will be able to run it without any problems provided that you load it AFTER all interrupt routines using the same vector since, as you pointed, older-designed interrupt routines may issue a single IRET on exiting instead of properly linking to the next interrupt on the list... From a hardware point of view, I don't know... 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 ! ! ------------------------------------------------------------------------------
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