X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=blobdiff_plain;f=geekos%2Fsrc%2Fgeekos%2Firq.c;fp=geekos%2Fsrc%2Fgeekos%2Firq.c;h=07543ba111a596d8d94a18f7bda62dab8e706210;hp=0000000000000000000000000000000000000000;hb=ddc16b0737cf58f7aa90a69c6652cdf4090aec51;hpb=626595465a2c6987606a6bc697df65130ad8c2d3 diff --git a/geekos/src/geekos/irq.c b/geekos/src/geekos/irq.c new file mode 100644 index 0000000..07543ba --- /dev/null +++ b/geekos/src/geekos/irq.c @@ -0,0 +1,141 @@ +/* + * This is the device-driver interface to the interrupt system. + * Copyright (c) 2001,2003 David H. Hovemeyer + * $Revision: 1.4 $ + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "COPYING". + */ + +#include +#include +#include +#include + +#include + +/* ---------------------------------------------------------------------- + * Private functions and data + * ---------------------------------------------------------------------- */ + +/* + * Current IRQ mask. + * This should be kept up to date with setup.asm + * (which does the initial programming of the PICs). + */ +static ushort_t s_irqMask = 0xfffb; + +/* + * Get the master and slave parts of an IRQ mask. + */ +#define MASTER(mask) ((mask) & 0xff) +#define SLAVE(mask) (((mask)>>8) & 0xff) + + +/* ---------------------------------------------------------------------- + * Public functions + * ---------------------------------------------------------------------- */ + +/* + * Install a handler for given IRQ. + * Note that we don't unmask the IRQ. + */ +void Install_IRQ(int irq, Interrupt_Handler handler) +{ + Install_Interrupt_Handler(irq + FIRST_EXTERNAL_INT, handler); +} + +/* + * Get current IRQ mask. Each bit position represents + * one of the 16 IRQ lines. + */ +ushort_t Get_IRQ_Mask(void) +{ + return s_irqMask; +} + +/* + * Set the IRQ mask. + */ +void Set_IRQ_Mask(ushort_t mask) +{ + uchar_t oldMask, newMask; + + oldMask = MASTER(s_irqMask); + newMask = MASTER(mask); + if (newMask != oldMask) { + Out_Byte(0x21, newMask); + } + + oldMask = SLAVE(s_irqMask); + newMask = SLAVE(mask); + if (newMask != oldMask) { + Out_Byte(0xA1, newMask); + } + + s_irqMask = mask; +} + +/* + * Enable given IRQ. + */ +void Enable_IRQ(int irq) +{ + bool iflag = Begin_Int_Atomic(); + + KASSERT(irq >= 0 && irq < 16); + ushort_t mask = Get_IRQ_Mask(); + mask &= ~(1 << irq); + Set_IRQ_Mask(mask); + + End_Int_Atomic(iflag); +} + +/* + * Disable given IRQ. + */ +void Disable_IRQ(int irq) +{ + bool iflag = Begin_Int_Atomic(); + + KASSERT(irq >= 0 && irq < 16); + ushort_t mask = Get_IRQ_Mask(); + mask |= (1 << irq); + Set_IRQ_Mask(mask); + + End_Int_Atomic(iflag); +} + +/* + * Called by an IRQ handler to begin the interrupt. + * Currently a no-op. + */ +void Begin_IRQ(struct Interrupt_State* state) +{ + // SerialPrint("Begin_IRQ for interrupt 0x%x\n",state->intNum); +} + +/* + * Called by an IRQ handler to end the interrupt. + * Sends an EOI command to the appropriate PIC(s). + */ +void End_IRQ(struct Interrupt_State* state) +{ + int irq = state->intNum - FIRST_EXTERNAL_INT; + End_IRQ_num(irq); +} + + +void End_IRQ_num(int irq) { + uchar_t command = 0x60 | (irq & 0x7); + + if (irq < 8) { + /* Specific EOI to master PIC */ + Out_Byte(0x20, command); + } + else { + /* Specific EOI to slave PIC, then to master (cascade line) */ + Out_Byte(0xA0, command); + Out_Byte(0x20, 0x62); + } +}