Node:Hardware interrupts, Next:, Previous:RMCB, Up:Low-level

18.9 How to hook hardware interrupts

Q: How do I register my DJGPP function as a hardware interrupt handler?

A: The optimal setup depends on the interrupt frequency and on the amount of processing it requires. Therefore, only some basic considerations and techniques are listed below. What combination of these is best for your application is up to you to decide.

First, some background. Hardware interrupts can occur when the processor is either in real mode (like when your program calls some DOS service) or in protected mode. When your program runs under a DPMI host, hardware interrupts are caught by the DPMI host and passed to protected mode first; only if unhandled, they are then reflected to real mode. Therefore, in DPMI mode you can get away with installing only a protected-mode handler. However, if the interrupts happen at a high frequency (say, more than 10 KHz), and if your program spends lots of time calling real-mode DOS/BIOS functions, then the overhead of the interrupt reflection from real to protected mode might be too painful, and you should consider installing a real-mode interrupt handler in addition to the protected-mode one. Such a real-mode handler will be called before the interrupt gets to the DPMI host, and handle the interrupt entirely in real mode, so it must be written in assembly and located in conventional memory (below the 1MB mark). If you need to hook an interrupt with both PM and RM handlers, you must hook the PM interrupt first, then the RM one (because hooking the PM interrupt modifies the RM one). Also, you should know that some DPMI hosts don't allow you to hook the RM interrupt (CWSDPMI does), and some call both handlers, no matter in what mode the interrupt arrived (CWSDPMI will only call one of them); the only way to be sure is to try.

To install a protected-mode interrupt handler, you do this:

To install a real-mode interrupt handler, you do this:

Note that Windows 9X is reported to call both the RM and PM handlers if both are installed, at least for some interrupts (CWSDPMI only invokes one of them). So, if you want to play safe, you will need some kind of a semaphore variable that the two handlers could use so that only one of them actually handles the interrupt in any given case.

The DPMI spec says that 3 software interrupts are special, in that they also get reflected to a protected-mode handler. These interrupts are: 1Ch (the timer tick interrupt), 23h (Keyboard Break interrupt), and 24h (Critical Error interrupt). This means that, to catch these interrupts, you need to install a protected-mode handler only. Unlike hardware interrupts, it doesn't make sense to install dual RM and PM handlers for these software interrupts. In particular, Windows will call both RM and PM handlers if you install both, so you effectively wind up handling the same interrupt twice.

For examples of installing and using hardware interrupt handlers, see the sources of the Allegro library, the sample code written by Bill Currie, the Sound Blaster interrupt-driven functions, the mkkbd package, and the libhw library, described under sample DJGPP packages. Alaric B. Williams has written a tutorial on interrupt handling.

The DJGPP User's Guide includes a chapter on hardware interrupts, written by Peter Marinov, which includes sample code for hooking hardware interrupts.

The file src/libc/go32/dpmiexcp.c in the DJGPP library sources, djlsrNNN.zip, is one example of the subtleties involved with installing a real-mode interrupt handler. The handlers themselves are in the file src/libc/go32/exceptn.S.