File: /usr/src/linux/arch/mips/kernel/old-irq.c

1     /*
2      * This file is subject to the terms and conditions of the GNU General Public
3      * License.  See the file "COPYING" in the main directory of this archive
4      * for more details.
5      *
6      * Code to handle x86 style IRQs plus some generic interrupt stuff.
7      *
8      * Copyright (C) 1992 Linus Torvalds
9      * Copyright (C) 1994 - 2001 Ralf Baechle
10      *
11      * Old rotten IRQ code.  To be killed as soon as everybody had converted or
12      * in 2.5.0, whatever comes first.
13      */
14     #include <linux/config.h>
15     #include <linux/errno.h>
16     #include <linux/init.h>
17     #include <linux/kernel_stat.h>
18     #include <linux/module.h>
19     #include <linux/signal.h>
20     #include <linux/sched.h>
21     #include <linux/types.h>
22     #include <linux/interrupt.h>
23     #include <linux/ioport.h>
24     #include <linux/timex.h>
25     #include <linux/slab.h>
26     #include <linux/random.h>
27     
28     #include <asm/bitops.h>
29     #include <asm/bootinfo.h>
30     #include <asm/io.h>
31     #include <asm/irq.h>
32     #include <asm/mipsregs.h>
33     #include <asm/system.h>
34     #include <asm/nile4.h>
35     
36     /*
37      * The board specific setup routine sets irq_setup to point to a board
38      * specific setup routine.
39      */
40     void (*irq_setup)(void);
41     
42     /*
43      * Linux has a controller-independent x86 interrupt architecture.
44      * every controller has a 'controller-template', that is used
45      * by the main code to do the right thing. Each driver-visible
46      * interrupt source is transparently wired to the apropriate
47      * controller. Thus drivers need not be aware of the
48      * interrupt-controller.
49      *
50      * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC,
51      * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC.
52      * (IO-APICs assumed to be messaging to Pentium local-APICs)
53      *
54      * the code is designed to be easily extended with new/different
55      * interrupt controllers, without having to do assembly magic.
56      */
57     
58     /*
59      * This contains the irq mask for both 8259A irq controllers, it's an
60      * int so we can deal with the third PIC in some systems like the RM300.
61      * (XXX This is broken for big endian.)
62      */
63     static unsigned int cached_irq_mask = 0xffff;
64     
65     #define __byte(x,y) (((unsigned char *)&(y))[x])
66     #define __word(x,y) (((unsigned short *)&(y))[x])
67     #define __long(x,y) (((unsigned int *)&(y))[x])
68     
69     #define cached_21       (__byte(0,cached_irq_mask))
70     #define cached_A1       (__byte(1,cached_irq_mask))
71     
72     unsigned long spurious_count = 0;
73     
74     /*
75      * (un)mask_irq, disable_irq() and enable_irq() only handle (E)ISA and
76      * PCI devices.  Other onboard hardware needs specific routines.
77      */
78     static inline void mask_irq(unsigned int irq)
79     {
80     	cached_irq_mask |= 1 << irq;
81     	if (irq & 8) {
82     		outb(cached_A1, 0xa1);
83     	} else {
84     		outb(cached_21, 0x21);
85     	}
86     }
87     
88     static inline void unmask_irq(unsigned int irq)
89     {
90     	cached_irq_mask &= ~(1 << irq);
91     	if (irq & 8) {
92     		outb(cached_A1, 0xa1);
93     	} else {
94     		outb(cached_21, 0x21);
95     	}
96     }
97     
98     void i8259_disable_irq(unsigned int irq_nr)
99     {
100     	unsigned long flags;
101     
102     	save_and_cli(flags);
103     	mask_irq(irq_nr);
104     	restore_flags(flags);
105     }
106     
107     void i8259_enable_irq(unsigned int irq_nr)
108     {
109     	unsigned long flags;
110     	save_and_cli(flags);
111     	unmask_irq(irq_nr);
112     	restore_flags(flags);
113     }
114     
115     static struct irqaction *irq_action[NR_IRQS] = {
116     	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
117     	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
118     	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
119     	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
120     	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
121     	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
122     	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
123     	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
124     };
125     
126     int get_irq_list(char *buf)
127     {
128     	int i, len = 0;
129     	struct irqaction * action;
130     
131     	for (i = 0 ; i < 32 ; i++) {
132     		action = irq_action[i];
133     		if (!action) 
134     			continue;
135     		len += sprintf(buf+len, "%2d: %8d %c %s",
136     			i, kstat.irqs[0][i],
137     			(action->flags & SA_INTERRUPT) ? '+' : ' ',
138     			action->name);
139     		for (action=action->next; action; action = action->next) {
140     			len += sprintf(buf+len, ",%s %s",
141     				(action->flags & SA_INTERRUPT) ? " +" : "",
142     				action->name);
143     		}
144     		len += sprintf(buf+len, "\n");
145     	}
146     	return len;
147     }
148     
149     static inline void i8259_mask_and_ack_irq(int irq)
150     {
151     	cached_irq_mask |= 1 << irq;
152     
153     	if (irq & 8) {
154     		inb(0xa1);
155     		outb(cached_A1, 0xa1);
156     		outb(0x62, 0x20);		/* Specific EOI to cascade */
157                     outb(0x20, 0xa0);
158             } else {
159     		inb(0x21);
160     		outb(cached_21, 0x21);
161     		outb(0x20, 0x20);
162             }
163     }
164     
165     asmlinkage void i8259_do_irq(int irq, struct pt_regs *regs)
166     {
167     	struct irqaction *action;
168     	int do_random, cpu;
169     
170     	cpu = smp_processor_id();
171     	irq_enter(cpu, irq);
172     
173     	if (irq >= 16)
174     		goto out;
175     
176     	i8259_mask_and_ack_irq(irq);
177     
178     	kstat.irqs[cpu][irq]++;
179     
180     	action = *(irq + irq_action);
181     	if (!action)
182     		goto out;
183     
184     	if (!(action->flags & SA_INTERRUPT))
185     		__sti();
186     	action = *(irq + irq_action);
187     	do_random = 0;
188            	do {
189     		do_random |= action->flags;
190     		action->handler(irq, action->dev_id, regs);
191     		action = action->next;
192            	} while (action);
193     	if (do_random & SA_SAMPLE_RANDOM)
194     		add_interrupt_randomness(irq);
195     	__cli();
196     	unmask_irq (irq);
197     
198     out:
199     	irq_exit(cpu, irq);
200     }
201     
202     /*
203      * do_IRQ handles IRQ's that have been installed without the
204      * SA_INTERRUPT flag: it uses the full signal-handling return
205      * and runs with other interrupts enabled. All relatively slow
206      * IRQ's should use this format: notably the keyboard/timer
207      * routines.
208      */
209     asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
210     {
211     	struct irqaction *action;
212     	int do_random, cpu;
213     
214     	cpu = smp_processor_id();
215     	irq_enter(cpu, irq);
216     	kstat.irqs[cpu][irq]++;
217     
218     	action = *(irq + irq_action);
219     	if (action) {
220     		if (!(action->flags & SA_INTERRUPT))
221     			__sti();
222     		action = *(irq + irq_action);
223     		do_random = 0;
224             	do {
225     			do_random |= action->flags;
226     			action->handler(irq, action->dev_id, regs);
227     			action = action->next;
228             	} while (action);
229     		if (do_random & SA_SAMPLE_RANDOM)
230     			add_interrupt_randomness(irq);
231     		__cli();
232     	}
233     	irq_exit(cpu, irq);
234     
235     	if (softirq_pending(cpu))
236     		do_softirq();
237     
238     	/* unmasking and bottom half handling is done magically for us. */
239     }
240     
241     int i8259_setup_irq(int irq, struct irqaction * new)
242     {
243     	int shared = 0;
244     	struct irqaction *old, **p;
245     	unsigned long flags;
246     
247     	p = irq_action + irq;
248     	if ((old = *p) != NULL) {
249     		/* Can't share interrupts unless both agree to */
250     		if (!(old->flags & new->flags & SA_SHIRQ))
251     			return -EBUSY;
252     
253     		/* Can't share interrupts unless both are same type */
254     		if ((old->flags ^ new->flags) & SA_INTERRUPT)
255     			return -EBUSY;
256     
257     		/* add new interrupt at end of irq queue */
258     		do {
259     			p = &old->next;
260     			old = *p;
261     		} while (old);
262     		shared = 1;
263     	}
264     
265     	if (new->flags & SA_SAMPLE_RANDOM)
266     		rand_initialize_irq(irq);
267     
268     	save_and_cli(flags);
269     	*p = new;
270     
271     	if (!shared) {
272     		if (is_i8259_irq(irq))
273     		    unmask_irq(irq);
274     #if (defined(CONFIG_DDB5074) || defined(CONFIG_DDB5476))
275     		else
276     		    nile4_enable_irq(irq_to_nile4(irq));
277     #endif
278     	}
279     	restore_flags(flags);
280     	return 0;
281     }
282     
283     /*
284      * Request_interrupt and free_interrupt ``sort of'' handle interrupts of
285      * non i8259 devices.  They will have to be replaced by architecture
286      * specific variants.  For now we still use this as broken as it is because
287      * it used to work ...
288      */
289     int request_irq(unsigned int irq, 
290     		void (*handler)(int, void *, struct pt_regs *),
291     		unsigned long irqflags, const char * devname, void *dev_id)
292     {
293     	int retval;
294     	struct irqaction * action;
295     
296     	if (irq >= 32)
297     		return -EINVAL;
298     	if (!handler)
299     		return -EINVAL;
300     
301     	action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
302     	if (!action)
303     		return -ENOMEM;
304     
305     	action->handler = handler;
306     	action->flags = irqflags;
307     	action->mask = 0;
308     	action->name = devname;
309     	action->next = NULL;
310     	action->dev_id = dev_id;
311     
312     	retval = i8259_setup_irq(irq, action);
313     
314     	if (retval)
315     		kfree(action);
316     	return retval;
317     }
318     		
319     void free_irq(unsigned int irq, void *dev_id)
320     {
321     	struct irqaction * action, **p;
322     	unsigned long flags;
323     
324     	if (irq > 31) {
325     		printk("Trying to free IRQ%d\n",irq);
326     		return;
327     	}
328     	for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
329     		if (action->dev_id != dev_id)
330     			continue;
331     
332     		/* Found it - now free it */
333     		save_and_cli(flags);
334     		*p = action->next;
335     		if (!irq[irq_action])
336     			mask_irq(irq);
337     		restore_flags(flags);
338     		kfree(action);
339     		return;
340     	}
341     	printk("Trying to free free IRQ%d\n",irq);
342     }
343     
344     unsigned long probe_irq_on (void)
345     {
346     	unsigned int i, irqs = 0;
347     	unsigned long delay;
348     
349     	/* first, enable any unassigned (E)ISA irqs */
350     	for (i = 15; i > 0; i--) {
351     		if (!irq_action[i]) {
352     			i8259_enable_irq(i);
353     			irqs |= (1 << i);
354     		}
355     	}
356     
357     	/* wait for spurious interrupts to mask themselves out again */
358     	for (delay = jiffies + HZ/10; time_before(jiffies, delay); )
359     		/* about 100ms delay */;
360     
361     	/* now filter out any obviously spurious interrupts */
362     	return irqs & ~cached_irq_mask;
363     }
364     
365     int probe_irq_off (unsigned long irqs)
366     {
367     	unsigned int i;
368     
369     #ifdef DEBUG
370     	printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
371     #endif
372     	irqs &= cached_irq_mask;
373     	if (!irqs)
374     		return 0;
375     	i = ffz(~irqs);
376     	if (irqs != (irqs & (1 << i)))
377     		i = -i;
378     	return i;
379     }
380     
381     void __init i8259_init(void)
382     {
383     	/* Init master interrupt controller */
384     	outb(0x11, 0x20); /* Start init sequence */
385     	outb(0x00, 0x21); /* Vector base */
386     	outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */
387     	outb(0x01, 0x21); /* Select 8086 mode */
388     	outb(0xff, 0x21); /* Mask all */
389             
390     	/* Init slave interrupt controller */
391     	outb(0x11, 0xa0); /* Start init sequence */
392     	outb(0x08, 0xa1); /* Vector base */
393     	outb(0x02, 0xa1); /* edge triggered, Cascade (slave) on IRQ2 */
394     	outb(0x01, 0xa1); /* Select 8086 mode */
395     	outb(0xff, 0xa1); /* Mask all */
396     
397     	outb(cached_A1, 0xa1);
398     	outb(cached_21, 0x21);
399     }
400     
401     void __init init_IRQ(void)
402     {
403     	/* i8259_init(); */
404     	irq_setup();
405     }
406