picirq.c (2355B)
1 // Intel 8259A programmable interrupt controllers. 2 3 #include "types.h" 4 #include "x86.h" 5 #include "traps.h" 6 7 // I/O Addresses of the two programmable interrupt controllers 8 #define IO_PIC1 0x20 // Master (IRQs 0-7) 9 #define IO_PIC2 0xA0 // Slave (IRQs 8-15) 10 11 #define IRQ_SLAVE 2 // IRQ at which slave connects to master 12 13 // Current IRQ mask. 14 // Initial IRQ mask has interrupt 2 enabled (for slave 8259A). 15 static ushort irqmask = 0xFFFF & ~(1<<IRQ_SLAVE); 16 17 static void 18 picsetmask(ushort mask) 19 { 20 irqmask = mask; 21 outb(IO_PIC1+1, mask); 22 outb(IO_PIC2+1, mask >> 8); 23 } 24 25 void 26 picenable(int irq) 27 { 28 picsetmask(irqmask & ~(1<<irq)); 29 } 30 31 // Initialize the 8259A interrupt controllers. 32 void 33 picinit(void) 34 { 35 // mask all interrupts 36 outb(IO_PIC1+1, 0xFF); 37 outb(IO_PIC2+1, 0xFF); 38 39 // Set up master (8259A-1) 40 41 // ICW1: 0001g0hi 42 // g: 0 = edge triggering, 1 = level triggering 43 // h: 0 = cascaded PICs, 1 = master only 44 // i: 0 = no ICW4, 1 = ICW4 required 45 outb(IO_PIC1, 0x11); 46 47 // ICW2: Vector offset 48 outb(IO_PIC1+1, T_IRQ0); 49 50 // ICW3: (master PIC) bit mask of IR lines connected to slaves 51 // (slave PIC) 3-bit # of slave's connection to master 52 outb(IO_PIC1+1, 1<<IRQ_SLAVE); 53 54 // ICW4: 000nbmap 55 // n: 1 = special fully nested mode 56 // b: 1 = buffered mode 57 // m: 0 = slave PIC, 1 = master PIC 58 // (ignored when b is 0, as the master/slave role 59 // can be hardwired). 60 // a: 1 = Automatic EOI mode 61 // p: 0 = MCS-80/85 mode, 1 = intel x86 mode 62 outb(IO_PIC1+1, 0x3); 63 64 // Set up slave (8259A-2) 65 outb(IO_PIC2, 0x11); // ICW1 66 outb(IO_PIC2+1, T_IRQ0 + 8); // ICW2 67 outb(IO_PIC2+1, IRQ_SLAVE); // ICW3 68 // NB Automatic EOI mode doesn't tend to work on the slave. 69 // Linux source code says it's "to be investigated". 70 outb(IO_PIC2+1, 0x3); // ICW4 71 72 // OCW3: 0ef01prs 73 // ef: 0x = NOP, 10 = clear specific mask, 11 = set specific mask 74 // p: 0 = no polling, 1 = polling mode 75 // rs: 0x = NOP, 10 = read IRR, 11 = read ISR 76 outb(IO_PIC1, 0x68); // clear specific mask 77 outb(IO_PIC1, 0x0a); // read IRR by default 78 79 outb(IO_PIC2, 0x68); // OCW3 80 outb(IO_PIC2, 0x0a); // OCW3 81 82 if(irqmask != 0xFFFF) 83 picsetmask(irqmask); 84 }