\subsubsection{Interrupt tables and interrupt masks}
On Intels we tolerate up to 32 interrupts and up to 255 traps4.6. We must include also some space for virtual traps and virtual interrupts.
<Off machine dependent interrupt table size. >= (U->) const natural_t OFF_MDEP_NPINT_MAX=32; // 32 actual interrupts on intels. const natural_t OFF_MDEP_NINT_MAX=OFF_MDEP_NPINT_MAX+OFF_MDEP_NVINT_MAX;
DefinesOFF_MDEP_NINT_MAX,OFF_MDEP_NPINT_MAX(links are to index).
<Off machine dependent trap table size. >= (U->) const natural_t OFF_MDEP_NPTRP_MAX=0x100; // 256 trap entries on intels. const natural_t OFF_MDEP_NTRP_MAX=OFF_MDEP_NPTRP_MAX+OFF_MDEP_NVTRP_MAX;
DefinesOFF_MDEP_NPTRP_MAX,OFF_MDEP_NTRP_MAX(links are to index).
The maximum number of virtual trap and virtual interrupts are system limits.
<Off limits. >+= [<-D] const int OFF_MDEP_NVINT_MAX=8; // 8 virtual timers. const int OFF_MDEP_NVTRP_MAX=9; // 9 virtual traps
DefinesOFF_MDEP_NVINT_MAX,OFF_MDEP_NVTRP_MAX(links are to index).
<Off machine dependent event table dependencies. >= (U->) [D->]
#include <klib/limits.h> // for OFF_MDEP_NV{INT,TRP}_MAX
#include <flux/types.h> // for boolean_t natural_t et al.
Another constant is defined to identify the first virtual interrupt.
<Off machine dependent interrupt numbers. >= (U->) [D->] // Irq # for the first virtual interrupt line. const natural_t OFF_MDEP_VINT0_IRQ=OFF_MDEP_NPINT_MAX;
We maintain a machine dependent interrupt table per interrupt
table. It deals with interrupt masks and also with IDT handling.
<Off machine dependent interrupt table. >= (U->)
// An ix86 interrupt table
//
class off_mdepIntTbl {
public:
// Creates an x86 interrupt table.
off_mdepIntTbl(void);
// Masks the interrupt.
void mask(natural_t i);
// Unmasks the interrupt.
void unmask(natural_t i);
// Is it masked?.
inline boolean_t is_masked(natural_t i) const;
private:
<Other private members of off_mdepIntTbl. >
};
Definesoff_mdepIntTbl(links are to index).
An interrupt mask is an integer with one bit set per enabled interrupt. Only real interrupts can be masked; virtual interrupts are non maskable.
<Off machine dependent interrupt mask. >= (U->)
class off_mdepIrqMask {
private:
natural_t i_mask; // Interrupt mask
public:
off_mdepIrqMask(natural_t val=0) : i_mask(val) {;}
void mask(natural_t i) {
if (i < OFF_MDEP_NPINT_MAX)
set_bit(i,(void*)&i_mask);
}
void unmask(natural_t i ) {
if (i < OFF_MDEP_NPINT_MAX)
clear_bit(i,(void*)&i_mask);
}
boolean_t is_masked(natural_t i) const {
if (i < OFF_MDEP_NPINT_MAX)
return test_bit(i,(void*)&i_mask);
else
return FALSE;
}
boolean_t is_empty(void) const { return i_mask==0; }
};
Definesoff_mdepIrqMask(links are to index).
<Off machine dependent event table dependencies. >+= (U->) [<-D->] #include <flux/machine/bitops.h> // for set_,clear_ and test_bit
Such mask is stored in i_mask.
<Other private members of off_mdepIntTbl. >= (<-U)
off_mdepIrqMask i_mask;
It is initialized at instantiation time with every interrupt cleared.
<off_mdepIntTbl::off_mdepIntTbl implementation. >= (U->)
// Creates an x86 interrupt table.
off_mdepIntTbl::off_mdepIntTbl(void) :
i_mask(0)
{
<Machine dependent interrupt hardware initialization. >
}
After that, mask and unmask requests are handled by programming the PIC
and setting the bit in the i_mask.
<off_mdepIntTbl::is_masked implementation. >= (U->)
// Is it masked?.
inline boolean_t off_mdepIntTbl::is_masked(natural_t i) const
{
assert(i<OFF_MDEP_NINT_MAX);
return i_mask.is_masked(i);
}
<Off machine dependent event table dependencies. >+= (U->) [<-D->] #include <assert.h> // for assert
<off_mdepIntTbl::mask implementation. >= (U->)
// Masks the interrupt.
void off_mdepIntTbl::mask(natural_t i)
{
assert(i<OFF_MDEP_NINT_MAX);
if (is_masked(i))
return;
i_mask.mask(i);
pic_disable_irq(i);
}
The real work is done by pic_disable_irq.
<Off machine dependent event table implementation dependencies. >= (U->) [D->] #include <flux/machine/pc/pic.h> // for pic_disable_irq et al.
<off_mdepIntTbl::unmask implementation. >= (U->)
// Unmasks the interrupt.
void off_mdepIntTbl::unmask(natural_t i)
{
assert( i<OFF_MDEP_NINT_MAX);
if (!is_masked(i))
return;
i_mask.unmask(i);
pic_enable_irq(i);
}