
4-13
spend too long in your ISR, it may be called again before you have completed handling the first run. This often
leads to a hang that requires a reboot.
Your ISR should have this structure:
Push any processor registers used in your ISR. Most C and Pascal interrupt routines automatically do this for
you.
Put the body of your routine here.
Clear the interrupt bit on the DM5806 by writing any value to BA + 5.
Issue the EOI command to the 8259 interrupt controller by writing 20H to port 20H.
Pop all registers pushed on entrance. Most C and Pascal interrupt routines automatically do this for you.
The following C and Pascal examples show what the shell of your ISR should be like:
In C:
void interrupt ISR(void)
{
/* Your code goes here. Do not use any DOS functions! */
outportb(BaseAddress + 5, 0);
outportb(0x20, 0x20);
}
/* Clear DM5806 interrupt */
/* Send EOI command to 8259 */
In Pascal:
Procedure ISR; Interrupt;
begin
{ Your code goes here. Do not use any DOS functions! }
Port[BaseAddress + 5] := 0;
Port[$20] := $20;
end;
{ Clear DM5806 interrupt }
{ Send EOI command to 8259 }
- Saving the Startup Interrupt Mask Register (IMR) and Interrupt Vector
The next step after writing the ISR is to save the startup state of the interrupt mask register and the interrupt
vector that you will be using. The IMR is located at I/O port 21H. The interrupt vector you will be using is located
in the interrupt vector table which is simply an array of 256-bit (4-byte) pointers and is located in the first 1024
bytes of memory (Segment = 0, Offset = 0). You can read this value directly, but it is a better practice to use DOS
function 35H (get interrupt vector). Most C and Pascal compilers provide a library routine for reading the value of a
vector. The vectors for the hardware interrupts are vectors 8 through 15, where IRQ0 uses vector 8, IRQ1 uses
vector 9, and so on. Thus, if the DM5806 will be using IRQ3, you should save the value of interrupt vector 11.
Before you install your ISR, temporarily mask out the IRQ you will be using. This prevents the IRQ from
requesting an interrupt while you are installing and initializing your ISR. To mask the IRQ, read in the current IMR
at I/O port 21H and
set
the bit that corresponds to your IRQ (remember, setting a bit disables interrupts on that IRQ
while clearing a bit enables them). The IMR is arranged so that bit 0 is for IRQ0, bit 1 is for IRQ1, and so on. See
the paragraph entitled
Interrupt Mask Register (IMR)
earlier in this chapter for help in determining your IRQ’s bit.
After setting the bit, write the new value to I/O port 21H.
With the startup IMR saved and the interrupts on your IRQ temporarily disabled, you can assign the interrupt
vector to point to your ISR. Again, you can overwrite the appropriate entry in the vector table with a direct memory
write, but this is a bad practice. Instead, use either DOS function 25H (set interrupt vector) or, if your compiler
provides it, the library routine for setting an interrupt vector. Remember that vector 8 is for IRQ0, vector 9 is for
IRQ1, and so on.
If you need to program the source of your interrupts, do that next. For example, if you are using the program-
mable interval timer to generate interrupts, you must program it to run in the proper mode and at the proper rate.
Finally, clear the bit in the IMR for the IRQ you are using. This enables interrupts on the IRQ.