* same with xv6
[mascara-docs.git] / i386 / MIT / course / src / git.lab / kern / picirq.c
blob6548d97fbbf12c2e2ccc4fcfa18569586008a65b
1 /* See COPYRIGHT for copyright information. */
3 #include <inc/assert.h>
4 #include <inc/trap.h>
6 #include <kern/picirq.h>
9 // Current IRQ mask.
10 // Initial IRQ mask has interrupt 2 enabled (for slave 8259A).
11 uint16_t irq_mask_8259A = 0xFFFF & ~(1<<IRQ_SLAVE);
12 static bool didinit;
14 /* Initialize the 8259A interrupt controllers. */
15 void
16 pic_init(void)
18 didinit = 1;
20 // mask all interrupts
21 outb(IO_PIC1+1, 0xFF);
22 outb(IO_PIC2+1, 0xFF);
24 // Set up master (8259A-1)
26 // ICW1: 0001g0hi
27 // g: 0 = edge triggering, 1 = level triggering
28 // h: 0 = cascaded PICs, 1 = master only
29 // i: 0 = no ICW4, 1 = ICW4 required
30 outb(IO_PIC1, 0x11);
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);
39 // ICW4: 000nbmap
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
44 // can be hardwired).
45 // a: 1 = Automatic EOI mode
46 // p: 0 = MCS-80/85 mode, 1 = intel x86 mode
47 outb(IO_PIC1+1, 0x3);
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
57 // OCW3: 0ef01prs
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);
71 void
72 irq_setmask_8259A(uint16_t mask)
74 int i;
75 irq_mask_8259A = mask;
76 if (!didinit)
77 return;
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++)
82 if (~mask & (1<<i))
83 cprintf(" %d", i);
84 cprintf("\n");
87 void
88 irq_eoi(void)
90 // OCW2: rse00xxx
91 // r: rotate
92 // s: specific
93 // e: end-of-interrupt
94 // xxx: specific interrupt line
95 outb(IO_PIC1, 0x20);
96 outb(IO_PIC2, 0x20);