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