1 /* See COPYRIGHT for copyright information. */
3 #include <inc/assert.h>
5 #include <kern/picirq.h>
9 // Initial IRQ mask has interrupt 2 enabled (for slave 8259A).
10 uint16_t irq_mask_8259A
= 0xFFFF & ~(1<<IRQ_SLAVE
);
13 /* Initialize the 8259A interrupt controllers. */
19 // mask all interrupts
20 outb(IO_PIC1
+1, 0xFF);
21 outb(IO_PIC2
+1, 0xFF);
23 // Set up master (8259A-1)
26 // g: 0 = edge triggering, 1 = level triggering
27 // h: 0 = cascaded PICs, 1 = master only
28 // i: 0 = no ICW4, 1 = ICW4 required
31 // ICW2: Vector offset
32 outb(IO_PIC1
+1, IRQ_OFFSET
);
34 // ICW3: bit mask of IR lines connected to slave PICs (master PIC),
35 // 3-bit No of IR line at which slave connects to master(slave PIC).
36 outb(IO_PIC1
+1, 1<<IRQ_SLAVE
);
39 // n: 1 = special fully nested mode
40 // b: 1 = buffered mode
41 // m: 0 = slave PIC, 1 = master PIC
42 // (ignored when b is 0, as the master/slave role
44 // a: 1 = Automatic EOI mode
45 // p: 0 = MCS-80/85 mode, 1 = intel x86 mode
48 // Set up slave (8259A-2)
49 outb(IO_PIC2
, 0x11); // ICW1
50 outb(IO_PIC2
+1, IRQ_OFFSET
+ 8); // ICW2
51 outb(IO_PIC2
+1, IRQ_SLAVE
); // ICW3
52 // NB Automatic EOI mode doesn't tend to work on the slave.
53 // Linux source code says it's "to be investigated".
54 outb(IO_PIC2
+1, 0x01); // ICW4
57 // ef: 0x = NOP, 10 = clear specific mask, 11 = set specific mask
58 // p: 0 = no polling, 1 = polling mode
59 // rs: 0x = NOP, 10 = read IRR, 11 = read ISR
60 outb(IO_PIC1
, 0x68); /* clear specific mask */
61 outb(IO_PIC1
, 0x0a); /* read IRR by default */
63 outb(IO_PIC2
, 0x68); /* OCW3 */
64 outb(IO_PIC2
, 0x0a); /* OCW3 */
66 if (irq_mask_8259A
!= 0xFFFF)
67 irq_setmask_8259A(irq_mask_8259A
);
71 irq_setmask_8259A(uint16_t mask
)
74 irq_mask_8259A
= mask
;
77 outb(IO_PIC1
+1, (char)mask
);
78 outb(IO_PIC2
+1, (char)(mask
>> 8));
79 cprintf("enabled interrupts:");
80 for (i
= 0; i
< 16; i
++)