1 /* 2 * linux/arch/alpha/kernel/irq_i8259.c 3 * 4 * This is the 'legacy' 8259A Programmable Interrupt Controller, 5 * present in the majority of PC/AT boxes. 6 * 7 * Started hacking from linux-2.3.30pre6/arch/i386/kernel/i8259.c. 8 */ 9 10 #include <linux/config.h> 11 #include <linux/init.h> 12 #include <linux/cache.h> 13 #include <linux/sched.h> 14 #include <linux/irq.h> 15 #include <linux/interrupt.h> 16 17 #include <asm/io.h> 18 19 #include "proto.h" 20 #include "irq_impl.h" 21 22 23 /* Note mask bit is true for DISABLED irqs. */ 24 static unsigned int cached_irq_mask = 0xffff; 25 static DEFINE_SPINLOCK(i8259_irq_lock); 26 27 static inline void 28 i8259_update_irq_hw(unsigned int irq, unsigned long mask) 29 { 30 int port = 0x21; 31 if (irq & 8) mask >>= 8; 32 if (irq & 8) port = 0xA1; 33 outb(mask, port); 34 } 35 36 inline void 37 i8259a_enable_irq(unsigned int irq) 38 { 39 spin_lock(&i8259_irq_lock); 40 i8259_update_irq_hw(irq, cached_irq_mask &= ~(1 << irq)); 41 spin_unlock(&i8259_irq_lock); 42 } 43 44 static inline void 45 __i8259a_disable_irq(unsigned int irq) 46 { 47 i8259_update_irq_hw(irq, cached_irq_mask |= 1 << irq); 48 } 49 50 void 51 i8259a_disable_irq(unsigned int irq) 52 { 53 spin_lock(&i8259_irq_lock); 54 __i8259a_disable_irq(irq); 55 spin_unlock(&i8259_irq_lock); 56 } 57 58 void 59 i8259a_mask_and_ack_irq(unsigned int irq) 60 { 61 spin_lock(&i8259_irq_lock); 62 __i8259a_disable_irq(irq); 63 64 /* Ack the interrupt making it the lowest priority. */ 65 if (irq >= 8) { 66 outb(0xE0 | (irq - 8), 0xa0); /* ack the slave */ 67 irq = 2; 68 } 69 outb(0xE0 | irq, 0x20); /* ack the master */ 70 spin_unlock(&i8259_irq_lock); 71 } 72 73 unsigned int 74 i8259a_startup_irq(unsigned int irq) 75 { 76 i8259a_enable_irq(irq); 77 return 0; /* never anything pending */ 78 } 79 80 void 81 i8259a_end_irq(unsigned int irq) 82 { 83 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) 84 i8259a_enable_irq(irq); 85 } 86 87 struct hw_interrupt_type i8259a_irq_type = { 88 .typename = "XT-PIC", 89 .startup = i8259a_startup_irq, 90 .shutdown = i8259a_disable_irq, 91 .enable = i8259a_enable_irq, 92 .disable = i8259a_disable_irq, 93 .ack = i8259a_mask_and_ack_irq, 94 .end = i8259a_end_irq, 95 }; 96 97 void __init 98 init_i8259a_irqs(void) 99 { 100 static struct irqaction cascade = { 101 .handler = no_action, 102 .name = "cascade", 103 }; 104 105 long i; 106 107 outb(0xff, 0x21); /* mask all of 8259A-1 */ 108 outb(0xff, 0xA1); /* mask all of 8259A-2 */ 109 110 for (i = 0; i < 16; i++) { 111 irq_desc[i].status = IRQ_DISABLED; 112 irq_desc[i].handler = &i8259a_irq_type; 113 } 114 115 setup_irq(2, &cascade); 116 } 117 118 119 #if defined(CONFIG_ALPHA_GENERIC) 120 # define IACK_SC alpha_mv.iack_sc 121 #elif defined(CONFIG_ALPHA_APECS) 122 # define IACK_SC APECS_IACK_SC 123 #elif defined(CONFIG_ALPHA_LCA) 124 # define IACK_SC LCA_IACK_SC 125 #elif defined(CONFIG_ALPHA_CIA) 126 # define IACK_SC CIA_IACK_SC 127 #elif defined(CONFIG_ALPHA_PYXIS) 128 # define IACK_SC PYXIS_IACK_SC 129 #elif defined(CONFIG_ALPHA_TITAN) 130 # define IACK_SC TITAN_IACK_SC 131 #elif defined(CONFIG_ALPHA_TSUNAMI) 132 # define IACK_SC TSUNAMI_IACK_SC 133 #elif defined(CONFIG_ALPHA_IRONGATE) 134 # define IACK_SC IRONGATE_IACK_SC 135 #endif 136 /* Note that CONFIG_ALPHA_POLARIS is intentionally left out here, since 137 sys_rx164 wants to use isa_no_iack_sc_device_interrupt for some reason. */ 138 139 #if defined(IACK_SC) 140 void 141 isa_device_interrupt(unsigned long vector, struct pt_regs *regs) 142 { 143 /* 144 * Generate a PCI interrupt acknowledge cycle. The PIC will 145 * respond with the interrupt vector of the highest priority 146 * interrupt that is pending. The PALcode sets up the 147 * interrupts vectors such that irq level L generates vector L. 148 */ 149 int j = *(vuip) IACK_SC; 150 j &= 0xff; 151 handle_irq(j, regs); 152 } 153 #endif 154 155 #if defined(CONFIG_ALPHA_GENERIC) || !defined(IACK_SC) 156 void 157 isa_no_iack_sc_device_interrupt(unsigned long vector, struct pt_regs *regs) 158 { 159 unsigned long pic; 160 161 /* 162 * It seems to me that the probability of two or more *device* 163 * interrupts occurring at almost exactly the same time is 164 * pretty low. So why pay the price of checking for 165 * additional interrupts here if the common case can be 166 * handled so much easier? 167 */ 168 /* 169 * The first read of gives you *all* interrupting lines. 170 * Therefore, read the mask register and and out those lines 171 * not enabled. Note that some documentation has 21 and a1 172 * write only. This is not true. 173 */ 174 pic = inb(0x20) | (inb(0xA0) << 8); /* read isr */ 175 pic &= 0xFFFB; /* mask out cascade & hibits */ 176 177 while (pic) { 178 int j = ffz(~pic); 179 pic &= pic - 1; 180 handle_irq(j, regs); 181 } 182 } 183 #endif 184