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. */ 24static unsigned int cached_irq_mask = 0xffff; 25static spinlock_t i8259_irq_lock = SPIN_LOCK_UNLOCKED; 26 27static inline void 28i8259_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 36inline void 37i8259a_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 44static inline void 45__i8259a_disable_irq(unsigned int irq) 46{ 47 i8259_update_irq_hw(irq, cached_irq_mask |= 1 << irq); 48} 49 50void 51i8259a_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 58void 59i8259a_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 73unsigned int 74i8259a_startup_irq(unsigned int irq) 75{ 76 i8259a_enable_irq(irq); 77 return 0; /* never anything pending */ 78} 79 80void 81i8259a_end_irq(unsigned int irq) 82{ 83 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) 84 i8259a_enable_irq(irq); 85} 86 87struct 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 97void __init 98init_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_POLARIS) 134# define IACK_SC POLARIS_IACK_SC 135#elif defined(CONFIG_ALPHA_IRONGATE) 136# define IACK_SC IRONGATE_IACK_SC 137#endif 138 139#if defined(IACK_SC) 140void 141isa_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) 156void 157isa_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