xref: /xv6-public/picirq.c (revision 5bf3fbee)
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 }
85 
86 //PAGEBREAK!
87 // Blank page.
88