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 conditions:
12 // * Redistributions of source code must retain the above copyright notice,
13 // this list of conditions and the following disclaimers.
15 // * Redistributions in binary form must reproduce the above copyright notice,
16 // this list of conditions and the following disclaimers in the
17 // documentation and/or other materials provided with the distribution.
19 // * The names of the Software's authors and/or contributors
20 // may not be used to endorse or promote products derived from
21 // this Software without specific prior written permission.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
25 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
32 #include <kern/kernel.h>
34 #include <kern/i8259.h>
39 // This assumes a second i8259 cascaded on IRQ2 of the first i8259,
40 // with I/O port bases of 0x20 and 0xa0, as every i8259 I've
41 // encountered has been configured that way, even on non-x86
42 // platforms. This can be made more general later if need be.
44 // FIXME: For non-x86 platforms, the I/O window base must be added in.
46 inline void I8259::output_mask(int off)
48 ll_out_8(off ? 0xa1 : 0x21, cached_masks[0]);
51 inline void I8259::mask(u32 irq)
58 cached_masks[off] |= (1 << bit);
62 void I8259::unmask(u32 irq)
69 cached_masks[off] &= ~(1 << bit);
73 void I8259::mask_and_ack(u32 irq)
81 ll_out_8(0x20, 0x60 | bit);
83 ll_out_8(0xa0, 0x60 | bit);
88 int I8259::get_pending_irq()
90 #if defined(_LL_ARCH_x86) || defined(_LL_ARCH_x64)
95 u8 ret = ll_in_8(0x20);
105 ll_out_8(0xa0, 0x0b);
108 // Shouldn't happen, as even if the device de-asserts the
109 // cascaded interrupt, it should wait for EOI.
114 return (ret & 7) | 8;
120 // Initialize each 8259 for edge triggered, cascade, 8086 mode.
121 // Interrupt vectors are set to 0x20-0x2f (this only matters on
124 ll_out_8(0x20, 0x11);
125 ll_out_8(0x21, 0x20);
126 ll_out_8(0x21, 0x04);
127 ll_out_8(0x21, 0x01);
129 ll_out_8(0xa0, 0x11);
130 ll_out_8(0xa1, 0x28);
131 ll_out_8(0xa1, 0x02);
132 ll_out_8(0xa1, 0x01);
134 // Mask all IRQs initially.
136 cached_masks[0] = cached_masks[1] = 0xff;
137 ll_out_8(0x21, 0xff);
138 ll_out_8(0xa1, 0xff);
140 bzero(irqslots, sizeof(irqslots));
142 for (int i = 0; i < 16; i++)
143 irqslots[i].controller = this;