1 /* This file contains routines for initializing the 8259 interrupt controller: 2 * put_irq_handler: register an interrupt handler 3 * rm_irq_handler: deregister an interrupt handler 4 * intr_handle: handle a hardware interrupt 5 * intr_init: initialize the interrupt controller(s) 6 */ 7 8 #include "kernel/kernel.h" 9 #include "arch_proto.h" 10 #include "hw_intr.h" 11 #include <machine/cpu.h> 12 13 #define ICW1_AT 0x11 /* edge triggered, cascade, need ICW4 */ 14 #define ICW1_PC 0x13 /* edge triggered, no cascade, need ICW4 */ 15 #define ICW1_PS 0x19 /* level triggered, cascade, need ICW4 */ 16 #define ICW4_AT_SLAVE 0x01 /* not SFNM, not buffered, normal EOI, 8086 */ 17 #define ICW4_AT_MASTER 0x05 /* not SFNM, not buffered, normal EOI, 8086 */ 18 #define ICW4_PC_SLAVE 0x09 /* not SFNM, buffered, normal EOI, 8086 */ 19 #define ICW4_PC_MASTER 0x0D /* not SFNM, buffered, normal EOI, 8086 */ 20 #define ICW4_AT_AEOI_SLAVE 0x03 /* not SFNM, not buffered, auto EOI, 8086 */ 21 #define ICW4_AT_AEOI_MASTER 0x07 /* not SFNM, not buffered, auto EOI, 8086 */ 22 #define ICW4_PC_AEOI_SLAVE 0x0B /* not SFNM, buffered, auto EOI, 8086 */ 23 #define ICW4_PC_AEOI_MASTER 0x0F /* not SFNM, buffered, auto EOI, 8086 */ 24 25 /*===========================================================================* 26 * intr_init * 27 *===========================================================================*/ 28 int intr_init(const int auto_eoi) 29 { 30 /* Initialize the 8259s, finishing with all interrupts disabled. */ 31 outb( INT_CTL, ICW1_AT); 32 outb( INT_CTLMASK, IRQ0_VECTOR); 33 /* ICW2 for master */ 34 outb( INT_CTLMASK, (1 << CASCADE_IRQ)); 35 /* ICW3 tells slaves */ 36 if (auto_eoi) 37 outb( INT_CTLMASK, ICW4_AT_AEOI_MASTER); 38 else 39 outb( INT_CTLMASK, ICW4_AT_MASTER); 40 outb( INT_CTLMASK, ~(1 << CASCADE_IRQ)); /* IRQ 0-7 mask */ 41 outb( INT2_CTL, ICW1_AT); 42 outb( INT2_CTLMASK, IRQ8_VECTOR); 43 /* ICW2 for slave */ 44 outb( INT2_CTLMASK, CASCADE_IRQ); /* ICW3 is slave nr */ 45 if (auto_eoi) 46 outb( INT2_CTLMASK, ICW4_AT_AEOI_SLAVE); 47 else 48 outb( INT2_CTLMASK, ICW4_AT_SLAVE); 49 outb( INT2_CTLMASK, ~0); /* IRQ 8-15 mask */ 50 51 return OK; 52 } 53 54 void irq_8259_unmask(const int irq) 55 { 56 const unsigned ctl_mask = irq < 8 ? INT_CTLMASK : INT2_CTLMASK; 57 outb(ctl_mask, inb(ctl_mask) & ~(1 << (irq & 0x7))); 58 } 59 60 void irq_8259_mask(const int irq) 61 { 62 const unsigned ctl_mask = irq < 8 ? INT_CTLMASK : INT2_CTLMASK; 63 outb(ctl_mask, inb(ctl_mask) | (1 << (irq & 0x7))); 64 } 65 66 /* Disable 8259 - write 0xFF in OCW1 master and slave. */ 67 void i8259_disable(void) 68 { 69 outb(INT2_CTLMASK, 0xFF); 70 outb(INT_CTLMASK, 0xFF); 71 inb(INT_CTLMASK); 72 } 73 74 void irq_8259_eoi(int irq) 75 { 76 if (irq < 8) 77 eoi_8259_master(); 78 else 79 eoi_8259_slave(); 80 } 81