1 // io/irq/i8259.cc -- Intel 8259-compatible IRQ support
3 // This software is copyright (c) 2006 Scott Wood <scott@buserror.net>.
5 // Permission is hereby granted, free of charge, to any person obtaining a copy of
6 // this software and associated documentation files (the "Software"), to deal with
7 // the Software without restriction, including without limitation the rights to
8 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9 // of the Software, and to permit persons to whom the Software is furnished to do
10 // so, subject to the following condition:
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
24 #include <kern/kernel.h>
26 #include <kern/i8259.h>
31 // This assumes a second i8259 cascaded on IRQ2 of the first i8259,
32 // with I/O port bases of 0x20 and 0xa0, as every i8259 I've
33 // encountered has been configured that way, even on non-x86
34 // platforms. This can be made more general later if need be.
36 // FIXME: For non-x86 platforms, the I/O window base must be added in.
38 inline void I8259::output_mask(int off)
40 ll_out_8(off ? 0xa1 : 0x21, cached_masks[0]);
43 inline void I8259::mask(u32 irq)
50 cached_masks[off] |= (1 << bit);
54 void I8259::unmask(u32 irq)
61 cached_masks[off] &= ~(1 << bit);
65 void I8259::mask_and_ack(u32 irq)
73 ll_out_8(0x20, 0x60 | bit);
75 ll_out_8(0xa0, 0x60 | bit);
80 int I8259::get_pending_irq()
82 #if defined(_LL_ARCH_x86) || defined(_LL_ARCH_x64)
87 u8 ret = ll_in_8(0x20);
100 // Shouldn't happen, as even if the device de-asserts the
101 // cascaded interrupt, it should wait for EOI.
106 return (ret & 7) | 8;
112 // Initialize each 8259 for edge triggered, cascade, 8086 mode.
113 // Interrupt vectors are set to 0x20-0x2f (this only matters on
116 ll_out_8(0x20, 0x11);
117 ll_out_8(0x21, 0x20);
118 ll_out_8(0x21, 0x04);
119 ll_out_8(0x21, 0x01);
121 ll_out_8(0xa0, 0x11);
122 ll_out_8(0xa1, 0x28);
123 ll_out_8(0xa1, 0x02);
124 ll_out_8(0xa1, 0x01);
126 // Mask all IRQs initially.
128 cached_masks[0] = cached_masks[1] = 0xff;
129 ll_out_8(0x21, 0xff);
130 ll_out_8(0xa1, 0xff);
132 bzero(irqslots, sizeof(irqslots));
134 for (int i = 0; i < 16; i++)
135 irqslots[i].controller = this;