3 * John W. Linville, linville@tuxdriver.com
5 * See file CREDITS for list of people who contributed to this
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
30 #define PRINTF(fmt,args...) printf (fmt ,##args)
32 #define PRINTF(fmt,args...)
35 static inline unsigned char read_byte(volatile unsigned char* from)
38 asm volatile ("lbz %0,%1\n eieio" : "=r" (x) : "m" (*from));
39 return (unsigned char)x;
42 static inline void write_byte(volatile unsigned char *to, int x)
44 asm volatile ("stb %1,%0\n eieio" : "=m" (*to) : "r" (x));
47 static inline unsigned long read_long_little(volatile unsigned long *from)
50 asm volatile ("lwbrx %0,0,%1\n eieio\n sync" : "=r" (x) : "r" (from), "m"(*from));
51 return (unsigned long)x;
62 #define out8(addr, byte) write_byte(0xFE000000 | addr, byte)
63 #define in8(addr) read_byte(0xFE000000 | addr)
66 * This contains the irq mask for both 8259A irq controllers,
68 static char cached_imr[2] = {0xff, 0xff};
70 #define cached_imr1 (cached_imr[0])
71 #define cached_imr2 (cached_imr[1])
76 PRINTF("Initializing Interrupt controller\n");
77 /* init master interrupt controller */
78 out8(0x20, 0x11); /* 0x19); /###* Start init sequence */
79 out8(0x21, 0x00); /* Vector base */
80 out8(0x21, 0x04); /* edge tiggered, Cascade (slave) on IRQ2 */
81 out8(0x21, 0x11); /* was: 0x01); /###* Select 8086 mode */
83 /* init slave interrupt controller */
84 out8(0xA0, 0x11); /* 0x19); /###* Start init sequence */
85 out8(0xA1, 0x08); /* Vector base */
86 out8(0xA1, 0x02); /* edge triggered, Cascade (slave) on IRQ2 */
87 out8(0xA1, 0x11); /* was: 0x01); /###* Select 8086 mode */
95 /* out8(0x43, 0x30); */
98 /* out8(0x43, 0x70); */
101 /* out8(0x43, 0xb0); */
105 /* Mask all interrupts */
106 out8(IMR_2, cached_imr2);
107 out8(IMR_1, cached_imr1);
121 static volatile char *pci_intack = (void *)0xFEF00000;
127 irq = read_long_little(pci_intack) & 0xff;
130 * This may be a spurious interrupt.
132 * Read the interrupt status register (ISR). If the most
133 * significant bit is not set then there is no valid
136 if(~in8(0x20)&0x80) {
143 int i8259_get_irq(struct pt_regs *regs)
148 * Perform an interrupt acknowledge cycle on controller 1
150 out8(OCW3_1, 0x0C); /* prepare for poll */
151 irq = in8(IPL_1) & 7;
154 * Interrupt is cascaded so perform interrupt
155 * acknowledge on controller 2
157 out8(OCW3_2, 0x0C); /* prepare for poll */
158 irq = (in8(IPL_2) & 7) + 8;
161 * This may be a spurious interrupt
163 * Read the interrupt status register. If the most
164 * significant bit is not set then there is no valid
168 if (~(in8(ISR_2) & 0x80)) {
172 } else if (irq == 7) {
174 * This may be a spurious interrupt
176 * Read the interrupt status register. If the most
177 * significant bit is not set then there is no valid
181 if (~(in8(ISR_1) & 0x80)) {
189 * Careful! The 8259A is a fragile beast, it pretty
190 * much _has_ to be done exactly like this (mask it
191 * first, _then_ send the EOI, and the order of EOI
192 * to the two 8259s is important!
194 void i8259_mask_and_ack(int irq)
197 cached_imr2 |= (1 << (irq - 8));
198 in8(IMR_2); /* DUMMY */
199 out8(IMR_2, cached_imr2);
200 out8(OCW2_2, 0x20); /* Non-specific EOI */
201 out8(OCW2_1, 0x20); /* Non-specific EOI to cascade */
203 cached_imr1 |= (1 << irq);
204 in8(IMR_1); /* DUMMY */
205 out8(IMR_1, cached_imr1);
206 out8(OCW2_1, 0x20); /* Non-specific EOI */
210 void i8259_mask_irq(int irq)
213 cached_imr2 |= (1 << (irq & 7));
214 out8(IMR_2, cached_imr2);
216 cached_imr1 |= (1 << irq);
217 out8(IMR_1, cached_imr1);
221 void i8259_unmask_irq(int irq)
224 cached_imr2 &= ~(1 << (irq & 7));
225 out8(IMR_2, cached_imr2);
227 cached_imr1 &= ~(1 << irq);
228 out8(IMR_1, cached_imr1);